summaryrefslogtreecommitdiff
path: root/sys/arch/i386
diff options
context:
space:
mode:
authorMike Larkin <mlarkin@cvs.openbsd.org>2016-04-14 07:00:25 +0000
committerMike Larkin <mlarkin@cvs.openbsd.org>2016-04-14 07:00:25 +0000
commit9a51b0e7eb49be04049010d6b98ffa106e258530 (patch)
tree795824a5fb4a7cd8d4b2ade868eca1f685d30a25 /sys/arch/i386
parent8383767e7eac6536f2e262d04c97c6b5be037cde (diff)
Use cpuid function 0xa to determine presence of general purpose
architectural performance counters, instead of cpu family/model values. Fixes a panic seen on some hypervisors when pctr(1) is used when the hypervisor masks out the counters. Reported by Hiltjo Posthuma, thanks. ok mikeb@, guenther@
Diffstat (limited to 'sys/arch/i386')
-rw-r--r--sys/arch/i386/i386/pctr.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/sys/arch/i386/i386/pctr.c b/sys/arch/i386/i386/pctr.c
index 0d0dbee7ce0..ef693864de2 100644
--- a/sys/arch/i386/i386/pctr.c
+++ b/sys/arch/i386/i386/pctr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pctr.c,v 1.27 2014/03/29 18:09:29 guenther Exp $ */
+/* $OpenBSD: pctr.c,v 1.28 2016/04/14 07:00:24 mlarkin Exp $ */
/*
* Pentium performance counter driver for OpenBSD.
@@ -24,20 +24,22 @@
#define PCTR_AMD_NUM PCTR_NUM
#define PCTR_INTEL_NUM 2 /* Intel supports only 2 counters */
+#define PCTR_INTEL_VERSION_MASK 0xff
#define usetsc (cpu_feature & CPUID_TSC)
#define usep5ctr (pctr_isintel && (((cpu_id >> 8) & 15) == 5) && \
(((cpu_id >> 4) & 15) > 0))
-#define usepctr ((pctr_isamd || pctr_isintel) && \
- ((cpu_id >> 8) & 15) >= 6)
+#define usepctr ((pctr_isamd && ((cpu_id >> 8) & 15) >= 6) || \
+ (pctr_isintel && \
+ (pctr_intel_cap & PCTR_INTEL_VERSION_MASK) >= 1))
int pctr_isamd;
int pctr_isintel;
+uint32_t pctr_intel_cap;
static int p5ctrsel(int fflag, u_int cmd, u_int fn);
static int pctrsel(int fflag, u_int cmd, u_int fn);
static void pctrrd(struct pctrst *);
-static void pctrrd(struct pctrst *);
static void
p5ctrrd(struct pctrst *st)
@@ -73,13 +75,16 @@ pctrrd(struct pctrst *st)
void
pctrattach(int num)
{
+ uint32_t dummy;
if (num > 1)
return;
pctr_isamd = (strcmp(cpu_vendor, "AuthenticAMD") == 0);
- if (!pctr_isamd)
+ if (!pctr_isamd) {
pctr_isintel = (strcmp(cpu_vendor, "GenuineIntel") == 0);
+ CPUID(0xa, pctr_intel_cap, dummy, dummy, dummy);
+ }
if (usepctr) {
/* Enable RDTSC and RDPMC instructions from user-level. */