detect mwait capabilities and extensions
Andriy Gapon
avg at FreeBSD.org
Sun Feb 3 17:45:03 UTC 2013
Guys,
could you please the following change?
It is amd64-centric now, but obviously I plan equivalent changes for i386.
I am mostly concerned about proper header files for various definitions and
proper names for them. Especially I am not sure where to put STATE_RUNNING,
STATE_MWAIT, STATE_SLEEPING...
Thank you.
diff --git a/sys/amd64/amd64/identcpu.c b/sys/amd64/amd64/identcpu.c
index 2517498..d831f95 100644
--- a/sys/amd64/amd64/identcpu.c
+++ b/sys/amd64/amd64/identcpu.c
@@ -513,6 +513,13 @@ identify_cpu(void)
}
}
+ if (cpu_high >= 5 && (cpu_feature2 & CPUID2_MON) != 0) {
+ do_cpuid(5, regs);
+ cpu_mon_mwait_flags = regs[2];
+ cpu_mon_min_size = regs[0] & CPUID5_MON_MIN_SIZE;
+ cpu_mon_max_size = regs[1] & CPUID5_MON_MAX_SIZE;
+ }
+
if (cpu_high >= 7) {
cpuid_count(7, 0, regs);
cpu_stdext_feature = regs[1];
diff --git a/sys/amd64/amd64/initcpu.c b/sys/amd64/amd64/initcpu.c
index 4abed4c..f7574b1 100644
--- a/sys/amd64/amd64/initcpu.c
+++ b/sys/amd64/amd64/initcpu.c
@@ -75,6 +75,9 @@ u_int cpu_mxcsr_mask; /* Valid bits in mxcsr */
u_int cpu_clflush_line_size = 32;
u_int cpu_stdext_feature;
u_int cpu_max_ext_state_size;
+u_int cpu_mon_mwait_flags; /* MONITOR/MWAIT flags (CPUID.05H.ECX) */
+u_int cpu_mon_min_size; /* MONITOR minimum range size, bytes */
+u_int cpu_mon_max_size; /* MONITOR minimum range size, bytes */
SYSCTL_UINT(_hw, OID_AUTO, via_feature_rng, CTLFLAG_RD,
&via_feature_rng, 0, "VIA RNG feature available in CPU");
diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h
index 5d7cb74..ddc5b9f 100644
--- a/sys/amd64/include/md_var.h
+++ b/sys/amd64/include/md_var.h
@@ -58,6 +58,9 @@ extern u_int cpu_procinfo;
extern u_int cpu_procinfo2;
extern char cpu_vendor[];
extern u_int cpu_vendor_id;
+extern u_int cpu_mon_mwait_flags;
+extern u_int cpu_mon_min_size;
+extern u_int cpu_mon_max_size;
extern char ctx_switch_xsave[];
extern char kstack[];
extern char sigcode[];
diff --git a/sys/x86/include/specialreg.h b/sys/x86/include/specialreg.h
index dbf9ba0..af64c1b 100644
--- a/sys/x86/include/specialreg.h
+++ b/sys/x86/include/specialreg.h
@@ -240,6 +240,29 @@
#define CPUID_LOCAL_APIC_ID 0xff000000
/*
+ * CPUID instruction 5 info
+ */
+#define CPUID5_MON_MIN_SIZE 0x0000ffff /* eax */
+#define CPUID5_MON_MAX_SIZE 0x0000ffff /* ebx */
+#define CPUID5_MON_MWAIT_EXT 0x00000001 /* ecx */
+#define CPUID5_MWAIT_INTRBREAK 0x00000002 /* ecx */
+
+/*
+ * MWAIT cpu power states. Lower 4 bits are sub-states.
+ */
+#define MWAIT_C0 0xf0
+#define MWAIT_C1 0x00
+#define MWAIT_C2 0x10
+#define MWAIT_C3 0x20
+#define MWAIT_C4 0x30
+
+/*
+ * MWAIT extensions.
+ */
+/* Interrupt breaks MWAIT even when masked. */
+#define MWAIT_INTRBREAK 0x00000001
+
+/*
* CPUID instruction 6 ecx info
*/
#define CPUID_PERF_STAT 0x00000001
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -665,10 +665,6 @@ TUNABLE_INT("machdep.idle_mwait", &idle_mwait);
SYSCTL_INT(_machdep, OID_AUTO, idle_mwait, CTLFLAG_RW, &idle_mwait,
0, "Use MONITOR/MWAIT for short idle");
-#define STATE_RUNNING 0x0
-#define STATE_MWAIT 0x1
-#define STATE_SLEEPING 0x2
-
static void
cpu_idle_acpi(int busy)
{
diff --git a/sys/amd64/include/cpu.h b/sys/amd64/include/cpu.h
index 1c2871f..dc29a37 100644
--- a/sys/amd64/include/cpu.h
+++ b/sys/amd64/include/cpu.h
@@ -43,8 +43,14 @@
#include <machine/frame.h>
#include <machine/segments.h>
+/*
+ * CPU states for the purpose of communication using MONITOR+MWAIT. */
+#define STATE_RUNNING 0x0
+#define STATE_MWAIT 0x1
+#define STATE_SLEEPING 0x2
+
#define cpu_exec(p) /* nothing */
#define cpu_swapin(p) /* nothing */
#define cpu_getstack(td) ((td)->td_frame->tf_rsp)
#define cpu_setstack(td, ap) ((td)->td_frame->tf_rsp = (ap))
#define cpu_spinwait() ia32_pause()
--
Andriy Gapon
More information about the freebsd-current
mailing list