4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
26 * x86-specific routines used by the CPU Performance counter driver.
29 #include <sys/types.h>
31 #include <sys/atomic.h>
32 #include <sys/regset.h>
33 #include <sys/privregs.h>
34 #include <sys/x86_archext.h>
35 #include <sys/cpuvar.h>
36 #include <sys/machcpuvar.h>
37 #include <sys/archsystm.h>
38 #include <sys/cpc_pcbe.h>
39 #include <sys/cpc_impl.h>
40 #include <sys/x_call.h>
41 #include <sys/cmn_err.h>
46 static const uint64_t allstopped
= 0;
47 static kcpc_ctx_t
*(*overflow_intr_handler
)(caddr_t
);
49 /* Do threads share performance monitoring hardware? */
50 static int strands_perfmon_shared
= 0;
52 int kcpc_hw_overflow_intr_installed
; /* set by APIC code */
53 extern kcpc_ctx_t
*kcpc_overflow_intr(caddr_t arg
, uint64_t bitmap
);
55 extern int kcpc_counts_include_idle
; /* Project Private /etc/system variable */
57 void (*kcpc_hw_enable_cpc_intr
)(void); /* set by APIC code */
60 kcpc_hw_add_ovf_intr(kcpc_ctx_t
*(*handler
)(caddr_t
))
62 if (x86_type
!= X86_TYPE_P6
)
64 overflow_intr_handler
= handler
;
65 return (ipltospl(APIC_PCINT_IPL
));
69 kcpc_hw_rem_ovf_intr(void)
71 overflow_intr_handler
= NULL
;
75 * Hook used on P4 systems to catch online/offline events.
79 kcpc_cpu_setup(cpu_setup_t what
, int cpuid
, void *arg
)
88 * If any CPU-bound contexts exist, we don't need to invalidate
89 * anything, as no per-LWP contexts can coexist.
91 if (kcpc_cpuctx
|| dtrace_cpc_in_use
)
95 * If this chip now has more than 1 active cpu, we must invalidate all
96 * contexts in the system.
98 chip_pg
= (pg_cmt_t
*)pghw_find_pg(cpu
[cpuid
], PGHW_CHIP
);
99 if (chip_pg
!= NULL
) {
100 active_cpus_cnt
= GROUP_SIZE(&chip_pg
->cmt_cpus_actv
);
101 if (active_cpus_cnt
> 1)
102 kcpc_invalidate_all();
108 static kmutex_t cpu_setup_lock
; /* protects setup_registered */
109 static int setup_registered
;
113 kcpc_hw_init(cpu_t
*cp
)
115 kthread_t
*t
= cp
->cpu_idle_thread
;
117 struct cpuid_regs cpuid
;
119 strands_perfmon_shared
= 0;
120 if (is_x86_feature(x86_featureset
, X86FSET_HTT
)) {
121 if (cpuid_getvendor(cpu
[0]) == X86_VENDOR_Intel
) {
123 * Intel processors that support Architectural
124 * Performance Monitoring Version 3 have per strand
125 * performance monitoring hardware.
126 * Hence we can allow use of performance counters on
127 * multiple strands on the same core simultaneously.
130 (void) __cpuid_insn(&cpuid
);
131 if (cpuid
.cp_eax
< 0xa) {
132 strands_perfmon_shared
= 1;
135 (void) __cpuid_insn(&cpuid
);
137 versionid
= cpuid
.cp_eax
& 0xFF;
139 strands_perfmon_shared
= 1;
143 strands_perfmon_shared
= 1;
147 if (strands_perfmon_shared
) {
148 mutex_enter(&cpu_setup_lock
);
149 if (setup_registered
== 0) {
150 mutex_enter(&cpu_lock
);
151 register_cpu_setup_func(kcpc_cpu_setup
, NULL
);
152 mutex_exit(&cpu_lock
);
153 setup_registered
= 1;
155 mutex_exit(&cpu_setup_lock
);
158 mutex_init(&cp
->cpu_cpc_ctxlock
, "cpu_cpc_ctxlock", MUTEX_DEFAULT
, 0);
160 if (kcpc_counts_include_idle
)
163 installctx(t
, cp
, kcpc_idle_save
, kcpc_idle_restore
,
164 NULL
, NULL
, NULL
, NULL
);
168 kcpc_hw_fini(cpu_t
*cp
)
170 ASSERT(cp
->cpu_idle_thread
== NULL
);
172 mutex_destroy(&cp
->cpu_cpc_ctxlock
);
175 #define BITS(v, u, l) \
176 (((v) >> (l)) & ((1 << (1 + (u) - (l))) - 1))
178 #define PCBE_NAMELEN 30 /* Enough Room for pcbe.manuf.model.family.stepping */
181 * Examine the processor and load an appropriate PCBE.
184 kcpc_hw_load_pcbe(void)
186 return (kcpc_pcbe_tryload(cpuid_getvendorstr(CPU
), cpuid_getfamily(CPU
),
187 cpuid_getmodel(CPU
), cpuid_getstep(CPU
)));
191 * Called by the generic framework to check if it's OK to bind a set to a CPU.
194 kcpc_hw_cpu_hook(processorid_t cpuid
, ulong_t
*kcpc_cpumap
)
200 if (!strands_perfmon_shared
)
204 * Only one logical CPU on each Pentium 4 HT CPU may be bound to at
207 * This loop is protected by holding cpu_lock, in order to properly
208 * access the cpu_t of the desired cpu.
210 mutex_enter(&cpu_lock
);
211 if ((cpu
= cpu_get(cpuid
)) == NULL
) {
212 mutex_exit(&cpu_lock
);
216 chip_pg
= (pg_t
*)pghw_find_pg(cpu
, PGHW_CHIP
);
218 PG_CPU_ITR_INIT(chip_pg
, itr
);
219 while ((p
= pg_cpu_next(&itr
)) != NULL
) {
222 if (BT_TEST(kcpc_cpumap
, p
->cpu_id
)) {
223 mutex_exit(&cpu_lock
);
228 mutex_exit(&cpu_lock
);
233 * Called by the generic framework to check if it's OK to bind a set to an LWP.
236 kcpc_hw_lwp_hook(void)
242 if (!strands_perfmon_shared
)
246 * Only one CPU per chip may be online.
248 mutex_enter(&cpu_lock
);
250 chips
= pghw_set_lookup(PGHW_CHIP
);
252 mutex_exit(&cpu_lock
);
257 while ((chip
= group_iterate(chips
, &i
)) != NULL
) {
258 if (GROUP_SIZE(&chip
->cmt_cpus_actv
) > 1) {
259 mutex_exit(&cpu_lock
);
264 mutex_exit(&cpu_lock
);