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

[Xen-changelog] [xen-unstable] x86: mce: Provide extended physical CPU info.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1234245060 0
# Node ID 4ac8bc60c000500f7fa1aeccea708d2191f5f31a
# Parent  09ea7eea81229fc64276b5682778a131f2fd1e1b
x86: mce: Provide extended physical CPU info.

Provide extended physial CPU info for the sake of dom0 MCE handling.
This information includes <cpu,core,thread> info for all logical CPUs,
cpuid information from all of them, and initial MSR values for a few
MSRs that are important to MCE handling.

Signed-off-by: Frank van der Linden <Frank.Vanderlinden@xxxxxxx>
---
 xen/arch/x86/cpu/mcheck/amd_k8.c       |   14 +--
 xen/arch/x86/cpu/mcheck/amd_nonfatal.c |   13 +--
 xen/arch/x86/cpu/mcheck/mce.c          |  130 +++++++++++++++++++++++++++++++++
 xen/arch/x86/cpu/mcheck/mce.h          |    3 
 xen/arch/x86/cpu/mcheck/mce_intel.c    |    8 --
 xen/include/public/arch-x86/xen-mca.h  |   48 +++++++++++-
 6 files changed, 194 insertions(+), 22 deletions(-)

diff -r 09ea7eea8122 -r 4ac8bc60c000 xen/arch/x86/cpu/mcheck/amd_k8.c
--- a/xen/arch/x86/cpu/mcheck/amd_k8.c  Tue Feb 10 05:47:00 2009 +0000
+++ b/xen/arch/x86/cpu/mcheck/amd_k8.c  Tue Feb 10 05:51:00 2009 +0000
@@ -99,6 +99,8 @@ void k8_machine_check(struct cpu_user_re
 
        mc_data = x86_mcinfo_getptr();
        cpu_nr = smp_processor_id();
+       BUG_ON(cpu_nr != vcpu->processor);
+
        curdom = vcpu->domain;
 
        memset(&mc_global, 0, sizeof(mc_global));
@@ -106,14 +108,12 @@ void k8_machine_check(struct cpu_user_re
        mc_global.common.size = sizeof(mc_global);
 
        mc_global.mc_domid = curdom->domain_id; /* impacted domain */
-       mc_global.mc_coreid = vcpu->processor; /* impacted physical cpu */
-       BUG_ON(cpu_nr != vcpu->processor);
-       mc_global.mc_core_threadid = 0;
+
+       x86_mc_get_cpu_info(cpu_nr, &mc_global.mc_socketid,
+           &mc_global.mc_coreid, &mc_global.mc_core_threadid,
+           &mc_global.mc_apicid, NULL, NULL, NULL);
+
        mc_global.mc_vcpuid = vcpu->vcpu_id; /* impacted vcpu */
-#if 0 /* TODO: on which socket is this physical core?
-         It's not clear to me how to figure this out. */
-       mc_global.mc_socketid = ???;
-#endif
        mc_global.mc_flags |= MC_FLAG_UNCORRECTABLE;
        rdmsrl(MSR_IA32_MCG_STATUS, mc_global.mc_gstatus);
 
diff -r 09ea7eea8122 -r 4ac8bc60c000 xen/arch/x86/cpu/mcheck/amd_nonfatal.c
--- a/xen/arch/x86/cpu/mcheck/amd_nonfatal.c    Tue Feb 10 05:47:00 2009 +0000
+++ b/xen/arch/x86/cpu/mcheck/amd_nonfatal.c    Tue Feb 10 05:51:00 2009 +0000
@@ -95,6 +95,7 @@ void mce_amd_checkregs(void *info)
        mc_data = NULL;
 
        cpu_nr = smp_processor_id();
+       BUG_ON(cpu_nr != vcpu->processor);
        event_enabled = guest_enabled_event(dom0->vcpu[0], VIRQ_MCA);
        error_found = 0;
 
@@ -103,14 +104,12 @@ void mce_amd_checkregs(void *info)
        mc_global.common.size = sizeof(mc_global);
 
        mc_global.mc_domid = vcpu->domain->domain_id; /* impacted domain */
-       mc_global.mc_coreid = vcpu->processor; /* impacted physical cpu */
-       BUG_ON(cpu_nr != vcpu->processor);
-       mc_global.mc_core_threadid = 0;
        mc_global.mc_vcpuid = vcpu->vcpu_id; /* impacted vcpu */
-#if 0 /* TODO: on which socket is this physical core?
-         It's not clear to me how to figure this out. */
-       mc_global.mc_socketid = ???;
-#endif
+
+       x86_mc_get_cpu_info(cpu_nr, &mc_global.mc_socketid,
+           &mc_global.mc_coreid, &mc_global.mc_core_threadid,
+           &mc_global.mc_apicid, NULL, NULL, NULL);
+
        mc_global.mc_flags |= MC_FLAG_CORRECTABLE;
        rdmsrl(MSR_IA32_MCG_STATUS, mc_global.mc_gstatus);
 
diff -r 09ea7eea8122 -r 4ac8bc60c000 xen/arch/x86/cpu/mcheck/mce.c
--- a/xen/arch/x86/cpu/mcheck/mce.c     Tue Feb 10 05:47:00 2009 +0000
+++ b/xen/arch/x86/cpu/mcheck/mce.c     Tue Feb 10 05:51:00 2009 +0000
@@ -443,6 +443,96 @@ next:
 
 
 
+static void do_mc_get_cpu_info(void *v)
+{
+       int cpu = smp_processor_id();
+       int cindex, cpn;
+       struct cpuinfo_x86 *c;
+       xen_mc_logical_cpu_t *log_cpus, *xcp;
+       uint32_t junk, ebx;
+
+       log_cpus = v;
+       c = &cpu_data[cpu];
+       cindex = 0;
+       cpn = cpu - 1;
+
+       /*
+        * Deal with sparse masks, condensed into a contig array.
+        */
+       while (cpn >= 0) {
+               if (cpu_isset(cpn, cpu_online_map))
+                       cindex++;
+               cpn--;
+       }
+
+       xcp = &log_cpus[cindex];
+       c = &cpu_data[cpu];
+       xcp->mc_cpunr = cpu;
+       x86_mc_get_cpu_info(cpu, &xcp->mc_chipid,
+           &xcp->mc_coreid, &xcp->mc_threadid,
+           &xcp->mc_apicid, &xcp->mc_ncores,
+           &xcp->mc_ncores_active, &xcp->mc_nthreads);
+       xcp->mc_cpuid_level = c->cpuid_level;
+       xcp->mc_family = c->x86;
+       xcp->mc_vendor = c->x86_vendor;
+       xcp->mc_model = c->x86_model;
+       xcp->mc_step = c->x86_mask;
+       xcp->mc_cache_size = c->x86_cache_size;
+       xcp->mc_cache_alignment = c->x86_cache_alignment;
+       memcpy(xcp->mc_vendorid, c->x86_vendor_id, sizeof xcp->mc_vendorid);
+       memcpy(xcp->mc_brandid, c->x86_model_id, sizeof xcp->mc_brandid);
+       memcpy(xcp->mc_cpu_caps, c->x86_capability, sizeof xcp->mc_cpu_caps);
+
+       /*
+        * This part needs to run on the CPU itself.
+        */
+       xcp->mc_nmsrvals = __MC_NMSRS;
+       xcp->mc_msrvalues[0].reg = MSR_IA32_MCG_CAP;
+       rdmsrl(MSR_IA32_MCG_CAP, xcp->mc_msrvalues[0].value);
+
+       if (c->cpuid_level >= 1) {
+               cpuid(1, &junk, &ebx, &junk, &junk);
+               xcp->mc_clusterid = (ebx >> 24) & 0xff;
+       } else
+               xcp->mc_clusterid = hard_smp_processor_id();
+}
+
+
+void x86_mc_get_cpu_info(unsigned cpu, uint32_t *chipid, uint16_t *coreid,
+                        uint16_t *threadid, uint32_t *apicid,
+                        unsigned *ncores, unsigned *ncores_active,
+                        unsigned *nthreads)
+{
+       struct cpuinfo_x86 *c;
+
+       *apicid = cpu_physical_id(cpu);
+       c = &cpu_data[cpu];
+       if (c->apicid == BAD_APICID) {
+               *chipid = cpu;
+               *coreid = 0;
+               *threadid = 0;
+               if (ncores != NULL)
+                       *ncores = 1;
+               if (ncores_active != NULL)
+                       *ncores_active = 1;
+               if (nthreads != NULL)
+                       *nthreads = 1;
+       } else {
+               *chipid = phys_proc_id[cpu];
+               if (c->x86_max_cores > 1)
+                       *coreid = cpu_core_id[cpu];
+               else
+                       *coreid = 0;
+               *threadid = c->apicid & ((1 << (c->x86_num_siblings - 1)) - 1);
+               if (ncores != NULL)
+                       *ncores = c->x86_max_cores;
+               if (ncores_active != NULL)
+                       *ncores_active = c->booted_cores;
+               if (nthreads != NULL)
+                       *nthreads = c->x86_num_siblings;
+       }
+}
+
 /* Machine Check Architecture Hypercall */
 long do_mca(XEN_GUEST_HANDLE(xen_mc_t) u_xen_mc)
 {
@@ -452,6 +542,7 @@ long do_mca(XEN_GUEST_HANDLE(xen_mc_t) u
        struct domain *domU;
        struct xen_mc_fetch *mc_fetch;
        struct xen_mc_notifydomain *mc_notifydomain;
+       struct xen_mc_physcpuinfo *mc_physcpuinfo;
        struct mc_info *mi;
        uint32_t flags;
        uint32_t fetch_idx;
@@ -460,6 +551,8 @@ long do_mca(XEN_GUEST_HANDLE(xen_mc_t) u
         * a DomU to fetch mc data while Dom0 notifies another DomU. */
        static DEFINE_SPINLOCK(mc_lock);
        static DEFINE_SPINLOCK(mc_notify_lock);
+       int nlcpu;
+       xen_mc_logical_cpu_t *log_cpus = NULL;
 
        if ( copy_from_guest(op, u_xen_mc, 1) )
                return -EFAULT;
@@ -580,6 +673,43 @@ long do_mca(XEN_GUEST_HANDLE(xen_mc_t) u
 
                spin_unlock(&mc_notify_lock);
                break;
+
+       case XEN_MC_physcpuinfo:
+              if ( !IS_PRIV(v->domain) )
+                      return -EPERM;
+ 
+              mc_physcpuinfo = &op->u.mc_physcpuinfo;
+              nlcpu = num_online_cpus();
+ 
+              if (!guest_handle_is_null(mc_physcpuinfo->info)) {
+                      if (mc_physcpuinfo->ncpus <= 0)
+                              return -EINVAL;
+                      nlcpu = min(nlcpu, (int)mc_physcpuinfo->ncpus);
+                      log_cpus = xmalloc_array(xen_mc_logical_cpu_t, nlcpu);
+                      if (log_cpus == NULL)
+                              return -ENOMEM;
+ 
+                      if (on_each_cpu(do_mc_get_cpu_info, log_cpus,
+                          1, 1) != 0) {
+                              xfree(log_cpus);
+                              return -EIO;
+                      }
+              }
+ 
+              mc_physcpuinfo->ncpus = nlcpu;
+ 
+              if (copy_to_guest(u_xen_mc, op, 1)) {
+                      if (log_cpus != NULL)
+                              xfree(log_cpus);
+                      return -EFAULT;
+              }
+ 
+              if (!guest_handle_is_null(mc_physcpuinfo->info)) {
+                      if (copy_to_guest(mc_physcpuinfo->info,
+                          log_cpus, nlcpu))
+                              ret = -EFAULT;
+                      xfree(log_cpus);
+              }
        }
 
        return ret;
diff -r 09ea7eea8122 -r 4ac8bc60c000 xen/arch/x86/cpu/mcheck/mce.h
--- a/xen/arch/x86/cpu/mcheck/mce.h     Tue Feb 10 05:47:00 2009 +0000
+++ b/xen/arch/x86/cpu/mcheck/mce.h     Tue Feb 10 05:51:00 2009 +0000
@@ -34,4 +34,5 @@ int x86_mcinfo_add(struct mc_info *mi, v
 int x86_mcinfo_add(struct mc_info *mi, void *mcinfo);
 void x86_mcinfo_dump(struct mc_info *mi);
 void mc_panic(char *s);
-
+void x86_mc_get_cpu_info(unsigned, uint32_t *, uint16_t *, uint16_t *,
+                        uint32_t *, uint32_t *, uint32_t *, uint32_t *);
diff -r 09ea7eea8122 -r 4ac8bc60c000 xen/arch/x86/cpu/mcheck/mce_intel.c
--- a/xen/arch/x86/cpu/mcheck/mce_intel.c       Tue Feb 10 05:47:00 2009 +0000
+++ b/xen/arch/x86/cpu/mcheck/mce_intel.c       Tue Feb 10 05:51:00 2009 +0000
@@ -182,11 +182,9 @@ static struct mc_info *machine_check_pol
         mcg.mc_flags = MC_FLAG_POLLED;
     else if (calltype == MC_FLAG_CMCI)
         mcg.mc_flags = MC_FLAG_CMCI;
-    mcg.mc_socketid = phys_proc_id[cpu];
-    mcg.mc_coreid = cpu_core_id[cpu];
-    mcg.mc_apicid = cpu_physical_id(cpu);
-    mcg.mc_core_threadid =
-        mcg.mc_apicid & ( 1 << (cpu_data[cpu].x86_num_siblings - 1)); 
+    x86_mc_get_cpu_info(
+        cpu, &mcg.mc_socketid, &mcg.mc_coreid,
+        &mcg.mc_core_threadid, &mcg.mc_apicid, NULL, NULL, NULL);
     rdmsrl(MSR_IA32_MCG_STATUS, mcg.mc_gstatus);
 
     for ( i = 0; i < nr_mce_banks; i++ ) {
diff -r 09ea7eea8122 -r 4ac8bc60c000 xen/include/public/arch-x86/xen-mca.h
--- a/xen/include/public/arch-x86/xen-mca.h     Tue Feb 10 05:47:00 2009 +0000
+++ b/xen/include/public/arch-x86/xen-mca.h     Tue Feb 10 05:51:00 2009 +0000
@@ -56,7 +56,7 @@
 /* Hypercall */
 #define __HYPERVISOR_mca __HYPERVISOR_arch_0
 
-#define XEN_MCA_INTERFACE_VERSION 0x03000001
+#define XEN_MCA_INTERFACE_VERSION 0x03000002
 
 /* IN: Dom0 calls hypercall from MC event handler. */
 #define XEN_MC_CORRECTABLE  0x0
@@ -118,7 +118,7 @@ struct mcinfo_global {
     uint16_t mc_domid;
     uint32_t mc_socketid; /* physical socket of the physical core */
     uint16_t mc_coreid; /* physical impacted core */
-    uint8_t  mc_apicid;
+    uint32_t mc_apicid;
     uint16_t mc_core_threadid; /* core thread of physical core */
     uint16_t mc_vcpuid; /* virtual cpu scheduled for mc_domid */
     uint64_t mc_gstatus; /* global status */
@@ -175,6 +175,41 @@ struct mc_info {
 };
 typedef struct mc_info mc_info_t;
 
+#define __MC_MSR_ARRAYSIZE 8
+#define __MC_NMSRS 1
+#define MC_NCAPS       7       /* 7 CPU feature flag words */
+#define MC_CAPS_STD_EDX        0       /* cpuid level 0x00000001 (%edx) */
+#define MC_CAPS_AMD_EDX        1       /* cpuid level 0x80000001 (%edx) */
+#define MC_CAPS_TM     2       /* cpuid level 0x80860001 (TransMeta) */
+#define MC_CAPS_LINUX  3       /* Linux-defined */
+#define MC_CAPS_STD_ECX        4       /* cpuid level 0x00000001 (%ecx) */
+#define MC_CAPS_VIA    5       /* cpuid level 0xc0000001 */
+#define MC_CAPS_AMD_ECX        6       /* cpuid level 0x80000001 (%ecx) */
+
+typedef struct mcinfo_logical_cpu {
+    uint32_t mc_cpunr;          
+    uint32_t mc_chipid; 
+    uint16_t mc_coreid;
+    uint16_t mc_threadid;
+    uint32_t mc_apicid;
+    uint32_t mc_clusterid;
+    uint32_t mc_ncores;
+    uint32_t mc_ncores_active;
+    uint32_t mc_nthreads;
+    int32_t mc_cpuid_level;
+    uint32_t mc_family;
+    uint32_t mc_vendor;
+    uint32_t mc_model;
+    uint32_t mc_step;
+    char mc_vendorid[16];
+    char mc_brandid[64];
+    uint32_t mc_cpu_caps[MC_NCAPS];
+    uint32_t mc_cache_size;
+    uint32_t mc_cache_alignment;
+    int32_t mc_nmsrvals;
+    struct mcinfo_msr mc_msrvalues[__MC_MSR_ARRAYSIZE];
+} xen_mc_logical_cpu_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mc_logical_cpu_t);
 
 
 /* 
@@ -272,6 +307,14 @@ typedef struct xen_mc_notifydomain xen_m
 typedef struct xen_mc_notifydomain xen_mc_notifydomain_t;
 DEFINE_XEN_GUEST_HANDLE(xen_mc_notifydomain_t);
 
+#define XEN_MC_physcpuinfo 3
+struct xen_mc_physcpuinfo {
+       /* IN/OUT */
+       uint32_t ncpus;
+       uint32_t pad0;
+       /* OUT */
+       XEN_GUEST_HANDLE(xen_mc_logical_cpu_t) info;
+};
 
 struct xen_mc {
     uint32_t cmd;
@@ -279,6 +322,7 @@ struct xen_mc {
     union {
         struct xen_mc_fetch        mc_fetch;
         struct xen_mc_notifydomain mc_notifydomain;
+        struct xen_mc_physcpuinfo  mc_physcpuinfo;
         uint8_t pad[MCINFO_HYPERCALLSIZE];
     } u;
 };

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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