[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |