summaryrefslogtreecommitdiff
path: root/sys/arch/amd64/include
diff options
context:
space:
mode:
authorMarcus Glocker <mglocker@cvs.openbsd.org>2012-11-10 09:45:06 +0000
committerMarcus Glocker <mglocker@cvs.openbsd.org>2012-11-10 09:45:06 +0000
commitfcc13a47ab56f0c004e8ac405ed5af0b7e59e8d0 (patch)
tree26636041125bd70a51b56350dc025de6d75f146e /sys/arch/amd64/include
parent25659e88c95da597f238aea9c5e1cf8748e2e69d (diff)
Recent x86 CPUs come with a constant time stamp counter. If this is
the case we verify if the CPU supports a specific version of the architectural performance monitoring feature and read out the current frequency from the fixed-function performance counter of the unhalted core. My initial motivation to implement this was the Soekris net6501-70 which comes with an Intel Atom E6xx 1.60GHz CPU. It has a constant time stamp counter plus speed step support and boots on the lowest frequency of 600MHz. This caused hw.cpuspeed and hw.setperf to reflect the wrong values. The diff is a cooperation work with jsg@. The fixed-function performance counter read code comes from a former diff of him. OK jsg@
Diffstat (limited to 'sys/arch/amd64/include')
-rw-r--r--sys/arch/amd64/include/cpu.h8
-rw-r--r--sys/arch/amd64/include/specialreg.h38
2 files changed, 44 insertions, 2 deletions
diff --git a/sys/arch/amd64/include/cpu.h b/sys/arch/amd64/include/cpu.h
index 9ce437af9de..60a095eed9e 100644
--- a/sys/arch/amd64/include/cpu.h
+++ b/sys/arch/amd64/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.74 2012/10/09 04:40:36 jsg Exp $ */
+/* $OpenBSD: cpu.h,v 1.75 2012/11/10 09:45:05 mglocker Exp $ */
/* $NetBSD: cpu.h,v 1.1 2003/04/26 18:39:39 fvdl Exp $ */
/*-
@@ -138,6 +138,8 @@ struct cpu_info {
#define CPUF_IDENTIFY 0x0010 /* CPU may now identify */
#define CPUF_IDENTIFIED 0x0020 /* CPU has been identified */
+#define CPUF_CONST_TSC 0x0040 /* CPU has constant TSC */
+
#define CPUF_PRESENT 0x1000 /* CPU is present */
#define CPUF_RUNNING 0x2000 /* CPU is running */
#define CPUF_PAUSE 0x4000 /* CPU is paused in DDB */
@@ -258,6 +260,10 @@ extern int biosextmem;
extern int cpu;
extern int cpu_feature;
extern int cpu_ecxfeature;
+extern int cpu_perf_eax;
+extern int cpu_perf_ebx;
+extern int cpu_perf_edx;
+extern int cpu_apmi_edx;
extern int ecpu_ecxfeature;
extern int cpu_id;
extern char cpu_vendor[];
diff --git a/sys/arch/amd64/include/specialreg.h b/sys/arch/amd64/include/specialreg.h
index 142fbbcbd57..f094f14c7ff 100644
--- a/sys/arch/amd64/include/specialreg.h
+++ b/sys/arch/amd64/include/specialreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: specialreg.h,v 1.23 2012/10/09 09:16:09 jsg Exp $ */
+/* $OpenBSD: specialreg.h,v 1.24 2012/11/10 09:45:05 mglocker Exp $ */
/* $NetBSD: specialreg.h,v 1.1 2003/04/26 18:39:48 fvdl Exp $ */
/* $NetBSD: x86/specialreg.h,v 1.2 2003/04/25 21:54:30 fvdl Exp $ */
@@ -177,6 +177,27 @@
#define SEFF0EBX_ADX 0x00080000 /* ADCX/ADOX instructions */
#define SEFF0EBX_SMAP 0x00100000 /* Supervisor mode access prevent */
+ /*
+ * "Architectural Performance Monitoring" bits (CPUID function 0x0a):
+ * EAX bits, EBX bits, EDX bits.
+ */
+
+#define CPUIDEAX_VERID 0x000000ff /* Version ID */
+#define CPUIDEAX_NUM_GC(cpuid) (((cpuid) >> 8) & 0x000000ff)
+#define CPUIDEAX_BIT_GC(cpuid) (((cpuid) >> 16) & 0x000000ff)
+#define CPUIDEAX_LEN_EBX(cpuid) (((cpuid) >> 24) & 0x000000ff)
+
+#define CPUIDEBX_EVT_CORE (1 << 0) /* Core cycle */
+#define CPUIDEBX_EVT_INST (1 << 1) /* Instruction retired */
+#define CPUIDEBX_EVT_REFR (1 << 2) /* Reference cycles */
+#define CPUIDEBX_EVT_CACHE_REF (1 << 3) /* Last-level cache ref. */
+#define CPUIDEBX_EVT_CACHE_MIS (1 << 4) /* Last-level cache miss. */
+#define CPUIDEBX_EVT_BRANCH_INST (1 << 5) /* Branch instruction ret. */
+#define CPUIDEBX_EVT_BRANCH_MISP (1 << 6) /* Branch mispredict ret. */
+
+#define CPUIDEDX_NUM_FC(cpuid) (((cpuid) >> 0) & 0x0000001f)
+#define CPUIDEDX_BIT_FC(cpuid) (((cpuid) >> 5) & 0x000000ff)
+
/*
* CPUID "extended features" bits (CPUID function 0x80000001):
* EDX bits, then ECX bits
@@ -214,6 +235,13 @@
#define CPUIDECX_TBM 0x00200000 /* Trailing bit manipulation instruction */
#define CPUIDECX_TOPEXT 0x00400000 /* Topology extensions support */
+/*
+ * "Advanced Power Management Information" bits (CPUID function 0x80000007):
+ * EDX bits.
+ */
+
+#define CPUIDEDX_ITSC (1 << 8) /* Invariant TSC */
+
#define CPUID2FAMILY(cpuid) (((cpuid) >> 8) & 15)
#define CPUID2MODEL(cpuid) (((cpuid) >> 4) & 15)
#define CPUID2STEPPING(cpuid) ((cpuid) & 15)
@@ -310,6 +338,14 @@
#define MSR_MTRRfix4K_F8000 0x26f
#define MSR_CR_PAT 0x277
#define MSR_MTRRdefType 0x2ff
+#define MSR_PERF_FIXED_CTR1 0x30a /* CPU_CLK_Unhalted.Core */
+#define MSR_PERF_FIXED_CTR2 0x30b /* CPU_CLK.Unhalted.Ref */
+#define MSR_PERF_FIXED_CTR_CTRL 0x38d
+#define MSR_PERF_FIXED_CTR1_EN (1 << 4)
+#define MSR_PERF_FIXED_CTR2_EN (1 << 8)
+#define MSR_PERF_GLOBAL_CTRL 0x38f
+#define MSR_PERF_GLOBAL_CTR1_EN (1ULL << 33)
+#define MSR_PERF_GLOBAL_CTR2_EN (1ULL << 34)
#define MSR_MC0_CTL 0x400
#define MSR_MC0_STATUS 0x401
#define MSR_MC0_ADDR 0x402