Mercurial > illumos > illumos-gate
changeset 3732:c8e62d396494
6470504 Remove Niagara2 IDLE loop workaround
6481563 Add support for Niagara2 2.x SPARC performance counters
6481949 handle dynamic hpriv peformance counting using N2 2.0 PCR
6528668 move stick compare workaround to Niagara2 and generic CPU module
author | ae112802 |
---|---|
date | Wed, 28 Feb 2007 16:33:41 -0800 |
parents | 79e3159504fa |
children | f1b41f5144cc |
files | usr/src/cmd/cpc/common/cputrack.c usr/src/cmd/cpc/cputrack/Makefile.com usr/src/cmd/cpc/cputrack/i386/Makefile usr/src/lib/libcpc/common/libcpc.c usr/src/uts/common/os/kcpc.c usr/src/uts/common/sys/cpc_impl.h usr/src/uts/common/sys/kcpc.h usr/src/uts/sun4v/Makefile.workarounds usr/src/uts/sun4v/cpu/niagara2.c usr/src/uts/sun4v/cpu/niagara2_asm.s usr/src/uts/sun4v/generic/Makefile usr/src/uts/sun4v/niagara2/Makefile usr/src/uts/sun4v/os/mach_startup.c usr/src/uts/sun4v/pcbe/niagara2_pcbe.c usr/src/uts/sun4v/sys/niagara2regs.h |
diffstat | 15 files changed, 388 insertions(+), 134 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/cpc/common/cputrack.c Wed Feb 28 16:31:04 2007 -0800 +++ b/usr/src/cmd/cpc/common/cputrack.c Wed Feb 28 16:33:41 2007 -0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -80,7 +80,9 @@ } static int cputrack(int argc, char *argv[], int optind); +#if defined(__i386) static void p4_ht_error(void); +#endif #if !defined(TEXT_DOMAIN) #define TEXT_DOMAIN "SYS_TEST" @@ -343,9 +345,11 @@ errstr = strerror(errno); if (errno == EAGAIN) (void) cpc_unbind(cpc, set); +#if defined(__i386) if (errno == EACCES) p4_ht_error(); else +#endif (void) fprintf(stderr, gettext( "%6d: init_lwp: can't bind perf counters " "to lwp%d - %s\n"), (int)pid, (int)lwpid, @@ -690,6 +694,8 @@ return (err != 0 ? 1 : 0); } +#if defined(__i386) + #define OFFLINE_CMD "/usr/sbin/psradm -f " #define BUFSIZE 5 /* enough for "n " where n is a cpuid */ @@ -811,3 +817,5 @@ exit(1); } + +#endif /* defined(__i386) */
--- a/usr/src/cmd/cpc/cputrack/Makefile.com Wed Feb 28 16:31:04 2007 -0800 +++ b/usr/src/cmd/cpc/cputrack/Makefile.com Wed Feb 28 16:33:41 2007 -0800 @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -31,7 +30,7 @@ PROG = cputrack OBJS = $(PROG).o caps.o time.o setgrp.o strtoset.o SRCS = $(OBJS:%.o=../../common/%.c) -LDLIBS += -lcpc -lpctx -lkstat +LDLIBS += -lcpc -lpctx CFLAGS += $(CCVERBOSE) $(CTF_FLAGS) CFLAGS64 += $(CCVERBOSE) $(CTF_FLAGS)
--- a/usr/src/cmd/cpc/cputrack/i386/Makefile Wed Feb 28 16:31:04 2007 -0800 +++ b/usr/src/cmd/cpc/cputrack/i386/Makefile Wed Feb 28 16:33:41 2007 -0800 @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,11 +19,13 @@ # CDDL HEADER END # # -# Copyright (c) 1999 by Sun Microsystems, Inc. -# All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" include ../Makefile.com +LDLIBS += -lkstat + install: all $(ROOTPROG32)
--- a/usr/src/lib/libcpc/common/libcpc.c Wed Feb 28 16:31:04 2007 -0800 +++ b/usr/src/lib/libcpc/common/libcpc.c Wed Feb 28 16:33:41 2007 -0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -953,7 +953,8 @@ "Invalid flags in a request\n", /* CPC_REQ_INVALID_FLAGS */ "Requests conflict with each other\n", /* CPC_CONFLICTING_REQS */ "Attribute requires the cpc_cpu privilege\n", /* CPC_ATTR_REQUIRES_PRIVILEGE */ -"Couldn't bind LWP to requested processor\n" /* CPC_PBIND_FAILED */ +"Couldn't bind LWP to requested processor\n", /* CPC_PBIND_FAILED */ +"Hypervisor event access denied\n" /* CPC_HV_NO_ACCESS */ }; /*VARARGS3*/
--- a/usr/src/uts/common/os/kcpc.c Wed Feb 28 16:31:04 2007 -0800 +++ b/usr/src/uts/common/os/kcpc.c Wed Feb 28 16:33:41 2007 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -302,9 +302,13 @@ &(rp->kr_config), (void *)ctx)) != 0) { kcpc_free_configs(set); *subcode = ret; - if (ret == CPC_ATTR_REQUIRES_PRIVILEGE) + switch (ret) { + case CPC_ATTR_REQUIRES_PRIVILEGE: + case CPC_HV_NO_ACCESS: return (EACCES); - return (EINVAL); + default: + return (EINVAL); + } } ctx->kc_pics[n].kp_req = rp; @@ -364,6 +368,13 @@ } kpreempt_enable(); + + /* + * The config may have been invalidated by + * the pcbe_sample op. + */ + if (ctx->kc_flags & KCPC_CTX_INVALID) + return (EAGAIN); } if (copyout(set->ks_data, buf, @@ -746,8 +757,7 @@ } } if (kcpc_configure_reqs(cctx, cks, &code) != 0) - panic("kcpc_ctx_clone: configure of context %p with " - "set %p failed with subcode %d", cctx, cks, code); + kcpc_invalidate_config(cctx); } @@ -890,7 +900,7 @@ if (pcbe_ops == NULL || (bitmap = pcbe_ops->pcbe_overflow_bitmap()) == 0) return (DDI_INTR_UNCLAIMED); -#ifdef N2_ERRATUM_134 +#ifdef N2_1x_CPC_WORKAROUNDS /* * Check if any of the supported counters overflowed. If * not, it's a spurious overflow trap (Niagara2 1.x silicon @@ -1116,7 +1126,11 @@ kcpc_ctx_clone(ctx, cctx); rw_exit(&kcpc_cpuctx_lock); - cctx->kc_flags = ctx->kc_flags; + /* + * Copy the parent context's kc_flags field, but don't overwrite + * the child's in case it was modified during kcpc_ctx_clone. + */ + cctx->kc_flags |= ctx->kc_flags; cctx->kc_thread = ct; cctx->kc_cpuid = -1; ct->t_cpc_set = cctx->kc_set; @@ -1298,6 +1312,20 @@ } /* + * Interface for PCBEs to signal that an existing configuration has suddenly + * become invalid. + */ +void +kcpc_invalidate_config(void *token) +{ + kcpc_ctx_t *ctx = token; + + ASSERT(ctx != NULL); + + atomic_or_uint(&ctx->kc_flags, KCPC_CTX_INVALID); +} + +/* * Called from lwp_exit() and thread_exit() */ void
--- a/usr/src/uts/common/sys/cpc_impl.h Wed Feb 28 16:31:04 2007 -0800 +++ b/usr/src/uts/common/sys/cpc_impl.h Wed Feb 28 16:33:41 2007 -0800 @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -58,8 +57,10 @@ #define CPC_OVF_NOTIFY_EMT 0x1 #define CPC_COUNT_USER 0x2 #define CPC_COUNT_SYSTEM 0x4 +#define CPC_COUNT_HV 0x8 -#define KCPC_REQ_ALL_FLAGS 0x7 +#define KCPC_REQ_ALL_FLAGS (CPC_OVF_NOTIFY_EMT | CPC_COUNT_USER | \ + CPC_COUNT_SYSTEM | CPC_COUNT_HV) #define KCPC_REQ_VALID_FLAGS(flags) \ (((flags) | KCPC_REQ_ALL_FLAGS) == KCPC_REQ_ALL_FLAGS) @@ -216,6 +217,7 @@ #define CPC_CONFLICTING_REQS 8 /* Reqs in the set conflict */ #define CPC_ATTR_REQUIRES_PRIVILEGE 9 /* Insufficient privs for atr */ #define CPC_PBIND_FAILED 10 /* Couldn't bind to processor */ +#define CPC_HV_NO_ACCESS 11 /* No perm for HV events */ #ifdef __cplusplus }
--- a/usr/src/uts/common/sys/kcpc.h Wed Feb 28 16:31:04 2007 -0800 +++ b/usr/src/uts/common/sys/kcpc.h Wed Feb 28 16:33:41 2007 -0800 @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -129,6 +128,7 @@ extern void *kcpc_next_config(void *token, void *current, uint64_t **data); +extern void kcpc_invalidate_config(void *token); /* * Called by a PCBE to determine if nonprivileged access to counters should be
--- a/usr/src/uts/sun4v/Makefile.workarounds Wed Feb 28 16:31:04 2007 -0800 +++ b/usr/src/uts/sun4v/Makefile.workarounds Wed Feb 28 16:33:41 2007 -0800 @@ -21,7 +21,7 @@ # # uts/sun4v/Makefile.workarounds # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -35,8 +35,5 @@ WORKAROUND_DEFS += -DQCN_POLLING # XXXQ WORKAROUND_DEFS += -DDO_CORELEVEL_LOADBAL -# The following is required to support Niagara2 1.0 -WORKAROUND_DEFS += -DN2_ERRATUM_49 # %stick_compare{6:0} ignored -WORKAROUND_DEFS += -DN2_IDLE_WORKAROUND -WORKAROUND_DEFS += -DN2_ERRATUM_112 # multiple traps for 1 event -WORKAROUND_DEFS += -DN2_ERRATUM_134 # PMU doesn't set OV bit +# The following is required to support Niagara2 1.x +WORKAROUND_DEFS += -DN2_1x_CPC_WORKAROUNDS # Errata 94, 112, 132, & 134
--- a/usr/src/uts/sun4v/cpu/niagara2.c Wed Feb 28 16:31:04 2007 -0800 +++ b/usr/src/uts/sun4v/cpu/niagara2.c Wed Feb 28 16:33:41 2007 -0800 @@ -72,6 +72,19 @@ NIAGARA2_HSVC_MINOR, cpu_module_name }; +#ifdef N2_1x_CPC_WORKAROUNDS +static uint64_t cpu_ver; /* Niagara2 CPU version reg */ +uint64_t ni2_1x_perf_workarounds = 0; + +/* Niagara2 CPU version register */ +#define VER_MASK_MAJOR_SHIFT 28 +#define VER_MASK_MAJOR_MASK 0xf + +extern uint64_t va_to_pa(void *); +extern uint64_t ni2_getver(); /* HV code to get %hver */ +extern uint64_t niagara2_getver(uint64_t ni2_getver_ra, uint64_t *cpu_version); +#endif + void cpu_setup(void) { @@ -79,6 +92,15 @@ extern int cpc_has_overflow_intr; int status; +#ifdef N2_1x_CPC_WORKAROUNDS + /* + * Get CPU version for Niagara2 part. + */ + if (niagara2_getver(va_to_pa((void *)ni2_getver), &cpu_ver) == H_EOK && + ((cpu_ver >> VER_MASK_MAJOR_SHIFT) & VER_MASK_MAJOR_MASK) <= 1) + ni2_1x_perf_workarounds = 1; +#endif + /* * Negotiate the API version for Niagara2 specific hypervisor * services.
--- a/usr/src/uts/sun4v/cpu/niagara2_asm.s Wed Feb 28 16:31:04 2007 -0800 +++ b/usr/src/uts/sun4v/cpu/niagara2_asm.s Wed Feb 28 16:33:41 2007 -0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -142,3 +142,56 @@ SET_SIZE(cpu_inv_tsb) #endif /* lint */ + +#ifdef N2_1x_CPC_WORKAROUNDS +/* + * This workaround will be removed prior to the FCS release. + */ + +#if defined(lint) + +/*ARGSUSED*/ +uint64_t +niagara2_getver(uint64_t ni_getver_ra, uint64_t *cpu_version) +{ return (0); } + +#else /* lint */ + +/* +* The following hypervisor calls are used to get the CPU version register +*/ +#define HV_DIAG_RA2PA 0x200 +#define HV_DIAG_HEXEC 0x201 + + /* + * niagara2_getver(uint64_t ni_getver_ra, uint64_t *cpu_version) + */ + ENTRY(niagara2_getver) + mov %o1, %o4 ! save cpu_version pointer + mov HV_DIAG_RA2PA, %o5 ! get PA of ni_getver routine + ta FAST_TRAP + brnz,pn %o0, 2f ! return error in not successful + nop + + mov %o1, %o0 ! move ni_getver PA to %o0 + mov HV_DIAG_HEXEC, %o5 + ta FAST_TRAP + brnz,pn %o0, 2f + nop + stx %o1, [%o4] ! copy version +2: + retl + nop + SET_SIZE(niagara2_getver) + /* + * Hypervisor code sequence to get chip version via HV_DIAG_HEXEC. + * Returns E_HOK in %o0 and %hver register value in %o1. + */ + .global ni2_getver + .align 16 +ni2_getver: + mov H_EOK, %o0 + rdhpr %hver, %o1 + done +#endif /* lint */ +#endif
--- a/usr/src/uts/sun4v/generic/Makefile Wed Feb 28 16:31:04 2007 -0800 +++ b/usr/src/uts/sun4v/generic/Makefile Wed Feb 28 16:33:41 2007 -0800 @@ -20,7 +20,7 @@ # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -72,6 +72,9 @@ # CFLAGS += $(CCVERBOSE) +# The following is required to support Niagara2 1.0 +WORKAROUND_DEFS += -DN2_ERRATUM_49 # %stick_compare{6:0} ignored + # # cpu-module-specific flags #
--- a/usr/src/uts/sun4v/niagara2/Makefile Wed Feb 28 16:31:04 2007 -0800 +++ b/usr/src/uts/sun4v/niagara2/Makefile Wed Feb 28 16:33:41 2007 -0800 @@ -20,7 +20,7 @@ # # # uts/sun4v/niagara2/Makefile -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -68,6 +68,9 @@ # CFLAGS += $(CCVERBOSE) -DNIAGARA2_IMPL +# The following is required to support Niagara2 1.0 +WORKAROUND_DEFS += -DN2_ERRATUM_49 # %stick_compare{6:0} ignored + # # cpu-module-specific flags #
--- a/usr/src/uts/sun4v/os/mach_startup.c Wed Feb 28 16:31:04 2007 -0800 +++ b/usr/src/uts/sun4v/os/mach_startup.c Wed Feb 28 16:33:41 2007 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -77,14 +77,6 @@ } -#ifdef N2_IDLE_WORKAROUND -/* - * Tuneable to control enabling of IDLE loop workaround on Niagara2 1.x parts. - * This workaround will be removed before the RR. - */ -int n2_idle_workaround; -#endif - /* * Halt the present CPU until awoken via an interrupt */ @@ -138,19 +130,6 @@ return; } -#ifdef N2_IDLE_WORKAROUND - /* - * The following workaround for Niagara2, when enabled, forces the - * IDLE CPU to wait in a tight loop until something becomes runnable - * locally, minimizing the overall CPU usage on an IDLE CPU. - */ - if (n2_idle_workaround) { - while (cpup->cpu_disp->disp_nrunnable == 0) { - (void) hv_cpu_yield(); - } - } -#endif - /* * We're on our way to being halted. Wait until something becomes * runnable locally or we are awaken (i.e. removed from the halt set).
--- a/usr/src/uts/sun4v/pcbe/niagara2_pcbe.c Wed Feb 28 16:31:04 2007 -0800 +++ b/usr/src/uts/sun4v/pcbe/niagara2_pcbe.c Wed Feb 28 16:33:41 2007 -0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -40,6 +40,8 @@ #include <sys/sdt.h> #include <sys/niagara2regs.h> #include <sys/hsvc.h> +#include <sys/hypervisor_api.h> +#include <sys/disp.h> static int ni2_pcbe_init(void); static uint_t ni2_pcbe_ncounters(void); @@ -64,6 +66,10 @@ extern uint64_t ultra_gettick(void); extern char cpu_module_name[]; +#ifdef N2_1x_CPC_WORKAROUNDS +extern uint64_t ni2_1x_perf_workarounds; +#endif + pcbe_ops_t ni2_pcbe_ops = { PCBE_VER_1, CPC_CAP_OVERFLOW_INTERRUPT | CPC_CAP_OVERFLOW_PRECISE, @@ -94,12 +100,21 @@ const uint32_t emask_valid; /* Mask of unreserved MASK bits */ } ni2_event_t; -#define ULTRA_PCR_PRIVPIC (UINT64_C(1) << CPC_NIAGARA2_PCR_PRIVPIC_SHIFT) +#define ULTRA_PCR_PRIVPIC (UINT64_C(1) << CPC_NIAGARA2_PCR_PRIV_SHIFT) #define EV_END {NULL, 0, 0} -static const uint64_t allstopped = ULTRA_PCR_PRIVPIC; +static const uint64_t allstopped = (ULTRA_PCR_PRIVPIC | + CPC_NIAGARA2_PCR_HOLDOV0 | CPC_NIAGARA2_PCR_HOLDOV1); -static ni2_event_t ni2_events[] = { +/* + * We update this array in the program and allstop routine. The array + * is checked in the sample routine to allow us to only perform the + * PCR.ht bit check when counting is in progress. + */ +static boolean_t ni2_cpc_counting[NCPU]; + +#ifdef N2_1x_CPC_WORKAROUNDS +static ni2_event_t ni2_1x_events[] = { { "Idle_strands", 0x000, 0x00 }, { "Br_completed", 0x201, 0x7f }, { "Br_taken", 0x202, 0x7f }, @@ -139,7 +154,52 @@ { "CRC_MPA_cksum", 0x720, 0x3f }, EV_END }; +#endif +static ni2_event_t ni2_2x_events[] = { + { "Idle_strands", 0x000, 0x00 }, + { "Br_completed", 0x201, 0xff }, + { "Br_taken", 0x202, 0xff }, + { "Instr_FGU_arithmetic", 0x204, 0xff }, + { "Instr_ld", 0x208, 0xff }, + { "Instr_st", 0x210, 0xff }, + { "Instr_sw", 0x220, 0xff }, + { "Instr_other", 0x240, 0xff }, + { "Atomics", 0x280, 0xff }, + { "Instr_cnt", 0x2fd, 0xff }, + { "IC_miss", 0x301, 0x33 }, + { "DC_miss", 0x302, 0x33 }, + { "L2_imiss", 0x310, 0x33 }, + { "L2_dmiss_ld", 0x320, 0x33 }, + { "ITLB_HWTW_ref_L2", 0x404, 0x3c }, + { "DTLB_HWTW_ref_L2", 0x408, 0x3c }, + { "ITLB_HWTW_miss_L2", 0x410, 0x3c }, + { "DTLB_HWTW_miss_L2", 0x420, 0x3c }, + { "Stream_ld_to_PCX", 0x501, 0x3f }, + { "Stream_st_to_PCX", 0x502, 0x3f }, + { "CPU_ld_to_PCX", 0x504, 0x3f }, + { "CPU_ifetch_to_PCX", 0x508, 0x3f }, + { "CPU_st_to_PCX", 0x510, 0x3f }, + { "MMU_ld_to_PCX", 0x520, 0x3f }, + { "DES_3DES_op", 0x601, 0x3f }, + { "AES_op", 0x602, 0x3f }, + { "RC4_op", 0x604, 0x3f }, + { "MD5_SHA-1_SHA-256_op", 0x608, 0x3f }, + { "MA_op", 0x610, 0x3f }, + { "CRC_TCPIP_cksum", 0x620, 0x3f }, + { "DES_3DES_busy_cycle", 0x701, 0x3f }, + { "AES_busy_cycle", 0x702, 0x3f }, + { "RC4_busy_cycle", 0x704, 0x3f }, + { "MD5_SHA-1_SHA-256_busy_cycle", 0x708, 0x3f }, + { "MA_busy_cycle", 0x710, 0x3f }, + { "CRC_MPA_cksum", 0x720, 0x3f }, + { "ITLB_miss", 0xb04, 0x0c }, + { "DTLB_miss", 0xb08, 0x0c }, + { "TLB_miss", 0xb0c, 0x0c }, + EV_END +}; + +static ni2_event_t *ni2_events = ni2_2x_events; static const char *ni2_impl_name = "UltraSPARC T2"; static char *evlist; static size_t evlist_sz; @@ -177,6 +237,10 @@ niagara2_hsvc_major, niagara2_hsvc_minor, status); niagara2_hsvc_available = B_FALSE; } +#ifdef N2_1x_CPC_WORKAROUNDS + if (ni2_1x_perf_workarounds) + ni2_events = ni2_1x_events; +#endif /* * Construct event list. * @@ -260,15 +324,11 @@ return (0x3); } -#ifdef N2_ERRATUM_112 +#ifdef N2_1x_CPC_WORKAROUNDS uint64_t ni2_ov_tstamp[NCPU]; /* last overflow time stamp */ uint64_t ni2_ov_spurious_range = 1000000; /* 1 msec at 1GHz */ #endif -/* - * These processors cannot tell which counter overflowed. The PCBE interface - * requires such processors to act as if _all_ counters had overflowed. - */ static uint64_t ni2_pcbe_overflow_bitmap(void) { @@ -276,10 +336,6 @@ uint64_t pic; uint32_t pic0, pic1; boolean_t update_pic = B_FALSE; -#ifdef N2_ERRATUM_112 - uint64_t tstamp; - processorid_t cpun; -#endif ASSERT(getpil() >= DISP_LEVEL); pcr = ultra_getpcr(); @@ -288,51 +344,73 @@ CPC_NIAGARA2_PCR_OV0_SHIFT; overflow |= (pcr & CPC_NIAGARA2_PCR_OV1_MASK) >> CPC_NIAGARA2_PCR_OV1_SHIFT; -#ifdef N2_ERRATUM_112 - /* - * Niagara2 1.x silicon can generate a duplicate overflow trap per - * event. If we take an overflow trap with no counters overflowing, - * return a non-zero bitmask with no OV bit set for supported - * counter so that the framework can ignore this trap. - */ - cpun = CPU->cpu_id; - tstamp = ultra_gettick(); - if (overflow) - ni2_ov_tstamp[cpun] = tstamp; - else if (tstamp < (ni2_ov_tstamp[cpun] + ni2_ov_spurious_range)) - overflow |= 1ULL << 63; -#endif + pic = ultra_getpic(); pic0 = (uint32_t)(pic & PIC0_MASK); pic1 = (uint32_t)((pic >> PIC1_SHIFT) & PIC0_MASK); -#ifdef N2_ERRATUM_134 - /* - * In Niagara2 1.x silicon, PMU doesn't set OV bit for precise events. - * So, if we take a trap with the counter within the overflow range - * and the OV bit is not set, we assume OV bit should have been set. - */ +#ifdef N2_1x_CPC_WORKAROUNDS + if (ni2_1x_perf_workarounds) { + uint64_t tstamp; + processorid_t cpun; + + /* + * Niagara2 1.x silicon can generate a duplicate overflow + * trap per event. If we take an overflow trap with no + * counters overflowing, return a non-zero bitmask with no + * OV bit set for supported counter so that the framework + * can ignore this trap. + */ + cpun = CPU->cpu_id; + tstamp = ultra_gettick(); + if (overflow) + ni2_ov_tstamp[cpun] = tstamp; + else if (tstamp < (ni2_ov_tstamp[cpun] + ni2_ov_spurious_range)) + overflow |= 1ULL << 63; - if (PIC_IN_OV_RANGE(pic0)) - overflow |= 0x1; - if (PIC_IN_OV_RANGE(pic1)) - overflow |= 0x2; + /* + * In Niagara2 1.x silicon, PMU doesn't set OV bit for + * precise events. So, if we take a trap with the counter + * within the overflow range and the OV bit is not set, we + * assume OV bit should have been set. + */ + if (PIC_IN_OV_RANGE(pic0)) + overflow |= 0x1; + if (PIC_IN_OV_RANGE(pic1)) + overflow |= 0x2; + } #endif - /* - * Reset the pic, if it is within the overflow range. - */ - if ((overflow & 0x1) && (PIC_IN_OV_RANGE(pic0))) { - pic0 = 0; - update_pic = B_TRUE; + + pcr |= (CPC_NIAGARA2_PCR_HOLDOV0 | CPC_NIAGARA2_PCR_HOLDOV1); + + if (overflow & 0x1) { + pcr &= ~(CPC_NIAGARA2_PCR_OV0_MASK | + CPC_NIAGARA2_PCR_HOLDOV0); + if (PIC_IN_OV_RANGE(pic0)) { + pic0 = 0; + update_pic = B_TRUE; + } } - if ((overflow & 0x2) && (PIC_IN_OV_RANGE(pic1))) { - pic1 = 0; - update_pic = B_TRUE; + + if (overflow & 0x2) { + pcr &= ~(CPC_NIAGARA2_PCR_OV1_MASK | + CPC_NIAGARA2_PCR_HOLDOV1); + if (PIC_IN_OV_RANGE(pic1)) { + pic1 = 0; + update_pic = B_TRUE; + } } if (update_pic) ultra_setpic(((uint64_t)pic1 << PIC1_SHIFT) | pic0); + /* + * The HV interface does not need to be used here because we are + * only resetting the OV bits and do not need to set the HT bit. + */ + DTRACE_PROBE1(niagara2__setpcr, uint64_t, pcr); + ultra_setpcr(pcr); + return (overflow); } @@ -368,7 +446,7 @@ for (i = 0; i < nattrs; i++) { if (strcmp(attrs[i].ka_name, "hpriv") == 0) { if (attrs[i].ka_val != 0) - flags |= CPC_COUNT_HPRIV; + flags |= CPC_COUNT_HV; } else if (strcmp(attrs[i].ka_name, "emask") == 0) { if ((attrs[i].ka_val | evp->emask_valid) != evp->emask_valid) @@ -386,6 +464,36 @@ (other_config->pcbe_flags != flags)) return (CPC_CONFLICTING_REQS); + /* + * If the hpriv attribute is present, make sure we have + * access to hyperprivileged events before continuing with + * this configuration. If we can set the ht bit in the PCR + * successfully, we must have access to hyperprivileged + * events. + * + * If this is a static per-CPU configuration, the CPC + * driver ensures there can not be more than one for this + * CPU. If this is a per-LWP configuration, the driver + * ensures no static per-CPU counting is ongoing and that + * the target LWP is not already being monitored. + */ + if (flags & CPC_COUNT_HV) { + kpreempt_disable(); + + DTRACE_PROBE1(niagara2__setpcr, uint64_t, + allstopped | CPC_NIAGARA2_PCR_HT); + if (hv_niagara_setperf(HV_NIAGARA_SPARC_CTL, + allstopped | CPC_NIAGARA2_PCR_HT) != H_EOK) { + kpreempt_enable(); + return (CPC_HV_NO_ACCESS); + } + + DTRACE_PROBE1(niagara2__setpcr, uint64_t, allstopped); + (void) hv_niagara_setperf(HV_NIAGARA_SPARC_CTL, allstopped); + + kpreempt_enable(); + } + cfg = kmem_alloc(sizeof (*cfg), KM_SLEEP); cfg->pcbe_picno = picnum; @@ -409,7 +517,7 @@ uint64_t toe; /* enable trap-on-event for pic0 and pic1 */ - toe = (CPC_COUNT_TOE0 | CPC_COUNT_TOE1); + toe = (CPC_NIAGARA2_PCR_TOE0 | CPC_NIAGARA2_PCR_TOE1); if ((pic0 = (ni2_pcbe_config_t *)kcpc_next_config(token, NULL, NULL)) == NULL) @@ -418,7 +526,7 @@ if ((pic1 = kcpc_next_config(token, pic0, NULL)) == NULL) { pic1 = &nullcfg; nullcfg.pcbe_flags = pic0->pcbe_flags; - toe = CPC_COUNT_TOE0; /* enable trap-on-event for pic0 */ + toe = CPC_NIAGARA2_PCR_TOE0; /* enable trap-on-event for pic0 */ } if (pic0->pcbe_picno != 0) { @@ -430,7 +538,7 @@ tmp = pic0; pic0 = pic1; pic1 = tmp; - toe = CPC_COUNT_TOE1; /* enable trap-on-event for pic1 */ + toe = CPC_NIAGARA2_PCR_TOE1; /* enable trap-on-event for pic1 */ } if (pic0->pcbe_picno != 0 || pic1->pcbe_picno != 1) @@ -444,7 +552,8 @@ */ ASSERT(pic0->pcbe_flags == pic1->pcbe_flags); - ultra_setpcr(allstopped); + ni2_pcbe_allstop(); + ultra_setpic(((uint64_t)pic1->pcbe_pic << PIC1_SHIFT) | (uint64_t)pic0->pcbe_pic); @@ -453,25 +562,34 @@ CPC_NIAGARA2_PCR_PIC1_SHIFT; if (pic0->pcbe_flags & CPC_COUNT_USER) - pcr |= (1ull << CPC_NIAGARA2_PCR_USR_SHIFT); + pcr |= (1ull << CPC_NIAGARA2_PCR_UT_SHIFT); if (pic0->pcbe_flags & CPC_COUNT_SYSTEM) - pcr |= (1ull << CPC_NIAGARA2_PCR_SYS_SHIFT); - if (pic0->pcbe_flags & CPC_COUNT_HPRIV) - pcr |= (1ull << CPC_NIAGARA2_PCR_HPRIV_SHIFT); + pcr |= (1ull << CPC_NIAGARA2_PCR_ST_SHIFT); + if (pic0->pcbe_flags & CPC_COUNT_HV) + pcr |= (1ull << CPC_NIAGARA2_PCR_HT_SHIFT); pcr |= toe; DTRACE_PROBE1(niagara2__setpcr, uint64_t, pcr); - /* - * PCR is set by HV using API call hv_niagara_setperf(). - * Silently ignore hvpriv events if access is denied. - */ - if (pic0->pcbe_flags & CPC_COUNT_HPRIV) { - if (hv_niagara_setperf(HV_NIAGARA_SPARC_CTL, pcr) != 0) - ultra_setpcr(pcr); + if (pic0->pcbe_flags & CPC_COUNT_HV) { + /* + * The ht bit in the PCR is only writable in + * hyperprivileged mode. So if we are counting + * hpriv events, we must use the HV interface + * hv_niagara_setperf to set the PCR. If this + * fails, assume we no longer have access to + * hpriv events. + */ + if (hv_niagara_setperf(HV_NIAGARA_SPARC_CTL, pcr) != H_EOK) { + kcpc_invalidate_config(token); + return; + } } else + /* Set the PCR with no hpriv event counting enabled. */ ultra_setpcr(pcr); + ni2_cpc_counting[CPU->cpu_id] = B_TRUE; + /* * On UltraSPARC, only read-to-read counts are accurate. We cannot * expect the value we wrote into the PIC, above, to be there after @@ -488,7 +606,17 @@ static void ni2_pcbe_allstop(void) { - ultra_setpcr(allstopped); + /* + * We use the HV interface here because if we were counting + * hyperprivileged events, we must reset the PCR.ht bit to stop + * the counting. In the event that this HV call fails, we fall + * back on ultra_setpcr which does not have write access to the + * ht bit. + */ + if (hv_niagara_setperf(HV_NIAGARA_SPARC_CTL, allstopped) != H_EOK) + ultra_setpcr(allstopped); + + ni2_cpc_counting[CPU->cpu_id] = B_FALSE; } static void @@ -500,6 +628,7 @@ uint64_t *pic1_data; uint64_t *dtmp; uint64_t tmp; + uint64_t pcr; ni2_pcbe_config_t *pic0; ni2_pcbe_config_t *pic1; ni2_pcbe_config_t nullcfg = { 1, 0, 0, 0 }; @@ -529,6 +658,29 @@ if (pic0->pcbe_picno != 0 || pic1->pcbe_picno != 1) panic("%s: bad config on token %p\n", ni2_impl_name, token); + + if (pic0->pcbe_flags & CPC_COUNT_HV) { + /* + * If the hpriv attribute is present, but the HT bit + * is not set in the PCR, access to hyperprivileged + * events must have been revoked. Only perform this + * check if counting is not stopped. + */ +#ifdef N2_1x_CPC_WORKAROUNDS + if (!ni2_1x_perf_workarounds) { +#endif + pcr = ultra_getpcr(); + DTRACE_PROBE1(niagara2__getpcr, uint64_t, pcr); + if (ni2_cpc_counting[CPU->cpu_id] && + !(pcr & CPC_NIAGARA2_PCR_HT)) { + kcpc_invalidate_config(token); + return; + } +#ifdef N2_1x_CPC_WORKAROUNDS + } +#endif + } + diff = (curpic & PIC0_MASK) - (uint64_t)pic0->pcbe_pic; if (diff < 0) diff += (1ll << 32);
--- a/usr/src/uts/sun4v/sys/niagara2regs.h Wed Feb 28 16:31:04 2007 -0800 +++ b/usr/src/uts/sun4v/sys/niagara2regs.h Wed Feb 28 16:33:41 2007 -0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -53,26 +53,32 @@ /* * Niagara2 SPARC Performance Control Register */ -#define CPC_NIAGARA2_PCR_PRIVPIC_SHIFT 0 -#define CPC_NIAGARA2_PCR_SYS_SHIFT 1 -#define CPC_NIAGARA2_PCR_USR_SHIFT 2 -#define CPC_NIAGARA2_PCR_HPRIV_SHIFT 3 +#define CPC_NIAGARA2_PCR_PRIV_SHIFT 0 +#define CPC_NIAGARA2_PCR_ST_SHIFT 1 +#define CPC_NIAGARA2_PCR_UT_SHIFT 2 + +#define CPC_NIAGARA2_PCR_HT_SHIFT 3 +#define CPC_NIAGARA2_PCR_HT (1ull << CPC_NIAGARA2_PCR_HT_SHIFT) + #define CPC_NIAGARA2_PCR_TOE0_SHIFT 4 #define CPC_NIAGARA2_PCR_TOE1_SHIFT 5 - -#define CPC_COUNT_HPRIV (1ull << CPC_NIAGARA2_PCR_HPRIV_SHIFT) -#define CPC_COUNT_TOE0 (1ull << CPC_NIAGARA2_PCR_TOE0_SHIFT) -#define CPC_COUNT_TOE1 (1ull << CPC_NIAGARA2_PCR_TOE1_SHIFT) +#define CPC_NIAGARA2_PCR_TOE0 (1ull << CPC_NIAGARA2_PCR_TOE0_SHIFT) +#define CPC_NIAGARA2_PCR_TOE1 (1ull << CPC_NIAGARA2_PCR_TOE1_SHIFT) #define CPC_NIAGARA2_PCR_PIC0_SHIFT 6 #define CPC_NIAGARA2_PCR_PIC1_SHIFT 19 #define CPC_NIAGARA2_PCR_PIC0_MASK UINT64_C(0xfff) #define CPC_NIAGARA2_PCR_PIC1_MASK UINT64_C(0xfff) +#define CPC_NIAGARA2_PCR_OV0_SHIFT 18 +#define CPC_NIAGARA2_PCR_OV1_SHIFT 30 #define CPC_NIAGARA2_PCR_OV0_MASK UINT64_C(0x40000) #define CPC_NIAGARA2_PCR_OV1_MASK UINT64_C(0x80000000) -#define CPC_NIAGARA2_PCR_OV0_SHIFT 18 -#define CPC_NIAGARA2_PCR_OV1_SHIFT 30 + +#define CPC_NIAGARA2_PCR_HOLDOV0_SHIFT 62 +#define CPC_NIAGARA2_PCR_HOLDOV1_SHIFT 63 +#define CPC_NIAGARA2_PCR_HOLDOV0 (1ull << CPC_NIAGARA2_PCR_HOLDOV0_SHIFT) +#define CPC_NIAGARA2_PCR_HOLDOV1 (1ull << CPC_NIAGARA2_PCR_HOLDOV1_SHIFT) /* * Hypervisor FAST_TRAP API function numbers to get/set DRAM