[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v2 1/9] x86/acpi: add a common interface for x86 cpu matching



Add a common interface for matching the current cpu against an
array of x86_cpu_ids. Also change mwait-idle.c to use it.

Signed-off-by: Wei Wang <wei.w.wang@xxxxxxxxx>
---
 xen/arch/x86/cpu/common.c       | 39 +++++++++++++++++++++++++++++++++++++++
 xen/arch/x86/cpu/mwait-idle.c   | 30 +++++++++++++-----------------
 xen/include/asm-x86/processor.h | 10 ++++++++++
 3 files changed, 62 insertions(+), 17 deletions(-)

diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c
index 53dbd84..e565754 100644
--- a/xen/arch/x86/cpu/common.c
+++ b/xen/arch/x86/cpu/common.c
@@ -45,6 +45,45 @@ unsigned int paddr_bits __read_mostly = 36;
  */
 u64 host_pat = 0x050100070406;
 
+/*
+ * x86_match_cpu - match the current CPU against an array of
+ * x86_cpu_ids
+ * @match: Pointer to array of x86_cpu_ids. Last entry terminated with
+ *         {}.
+ * Return the entry if the current CPU matches the entries in the
+ * passed x86_cpu_id match table. Otherwise NULL.  The match table
+ * contains vendor (X86_VENDOR_*), family, model and feature bits or
+ * respective wildcard entries.
+ *
+ * A typical table entry would be to match a specific CPU
+ * { X86_VENDOR_INTEL, 6, 0x12 }
+ * or to match a specific CPU feature
+ * { X86_FEATURE_MATCH(X86_FEATURE_FOOBAR) }
+ *
+ * This always matches against the boot cpu, assuming models and
+features are
+ * consistent over all CPUs.
+ */
+const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match)
+{
+    const struct x86_cpu_id *m;
+    struct cpuinfo_x86 *c = &boot_cpu_data;
+
+    for (m = match; m->vendor | m->family | m->model | m->feature; m++) {
+        if (c->x86_vendor != m->vendor)
+            continue;
+        if (c->x86 != m->family)
+            continue;
+        if (c->x86_model != m->model)
+            continue;
+        if (!cpu_has(c, m->feature))
+            continue;
+        return m;
+    }
+    return NULL;
+}
+EXPORT_SYMBOL(x86_match_cpu);
+
 static unsigned int __cpuinitdata cleared_caps[NCAPINTS];
 
 void __init setup_clear_cpu_cap(unsigned int cap)
diff --git a/xen/arch/x86/cpu/mwait-idle.c b/xen/arch/x86/cpu/mwait-idle.c
index 6dd5822..770a3dc 100644
--- a/xen/arch/x86/cpu/mwait-idle.c
+++ b/xen/arch/x86/cpu/mwait-idle.c
@@ -59,6 +59,8 @@
 #include <asm/hpet.h>
 #include <asm/mwait.h>
 #include <asm/msr.h>
+#include <asm/processor.h>
+#include <asm/cpufeature.h>
 #include <acpi/cpufreq/cpufreq.h>
 
 #define MWAIT_IDLE_VERSION "0.4"
@@ -656,12 +658,11 @@ static const struct idle_cpu idle_cpu_avn = {
        .disable_promotion_to_c1e = 1,
 };
 
-#define ICPU(model, cpu) { 6, model, &idle_cpu_##cpu }
+#define ICPU(model, cpu) \
+    { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, \
+        (unsigned long)&idle_cpu_##cpu}
 
-static struct intel_idle_id {
-       unsigned int family, model;
-       const struct idle_cpu *data;
-} intel_idle_ids[] __initdata = {
+static const struct x86_cpu_id intel_idle_ids[] = {
        ICPU(0x1a, nehalem),
        ICPU(0x1e, nehalem),
        ICPU(0x1f, nehalem),
@@ -722,23 +723,18 @@ static void __init mwait_idle_state_table_update(void)
 static int __init mwait_idle_probe(void)
 {
        unsigned int eax, ebx, ecx;
-       const struct intel_idle_id *id;
+       const struct x86_cpu_id *id;
 
-       if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
-           !boot_cpu_has(X86_FEATURE_MWAIT) ||
-           boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF)
-               return -ENODEV;
-
-       for (id = intel_idle_ids; id->family; ++id)
-               if (id->family == boot_cpu_data.x86 &&
-                   id->model == boot_cpu_data.x86_model)
-                       break;
-       if (!id->family) {
+        id = x86_match_cpu(intel_idle_ids);
+        if (!id) {
                pr_debug(PREFIX "does not run on family %d model %d\n",
                         boot_cpu_data.x86, boot_cpu_data.x86_model);
                return -ENODEV;
        }
 
+        if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF)
+            return -ENODEV;
+
        cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &mwait_substates);
 
        if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
@@ -753,7 +749,7 @@ static int __init mwait_idle_probe(void)
 
        pr_debug(PREFIX "MWAIT substates: %#x\n", mwait_substates);
 
-       icpu = id->data;
+        icpu = (const struct idle_cpu *)id->driver_data;
        cpuidle_state_table = icpu->state_table;
 
        if (boot_cpu_has(X86_FEATURE_ARAT))
diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
index a9b4e06..a729fdc 100644
--- a/xen/include/asm-x86/processor.h
+++ b/xen/include/asm-x86/processor.h
@@ -163,6 +163,14 @@ struct vcpu;
     pc;                                             \
 })
 
+struct x86_cpu_id {
+    __u16 vendor;
+    __u16 family;
+    __u16 model;
+    __u16 feature;   /* bit index */
+    __u64 driver_data;
+};
+
 struct cpuinfo_x86 {
     __u8 x86;            /* CPU family */
     __u8 x86_vendor;     /* CPU vendor */
@@ -204,6 +212,8 @@ extern u32 cpuid_ext_features;
 /* Maximum width of physical addresses supported by the hardware */
 extern unsigned int paddr_bits;
 
+extern const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match);
+
 extern void identify_cpu(struct cpuinfo_x86 *);
 extern void setup_clear_cpu_cap(unsigned int);
 extern void print_cpu_info(unsigned int cpu);
-- 
1.9.1


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.