[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] mce: Add a x86_mcinfo_reserve() function, to reserve space from mc_info.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1271663733 -3600 # Node ID 6860c523d2daf1d110b130a9596469a0957b4032 # Parent 6233eb0f29ba6b89b4dd14fe3d385e85924cd9f1 mce: Add a x86_mcinfo_reserve() function, to reserve space from mc_info. With this method, we don't need to collect bank and globalinformation to a local variable and do x86_mcinfo_add() to copy that information to mc_info. This avoid copy and also we can be aware earlier if there is enough space in the mc_info. Also extract function that get global/bank information to seperated function mca_init_bank/mca_init_global. It's meaningless to get the current information in mce context, keep it here but should be removed in future. Also a flag added to mc_info, to indicate some information is lost due to OOM. Signed-off-by: Jiang, Yunhong <yunhong.jiang@xxxxxxxxx> --- xen/arch/x86/cpu/mcheck/mce.c | 209 ++++++++++++++++++++-------------- xen/arch/x86/cpu/mcheck/mce.h | 3 xen/include/public/arch-x86/xen-mca.h | 3 3 files changed, 128 insertions(+), 87 deletions(-) diff -r 6233eb0f29ba -r 6860c523d2da xen/arch/x86/cpu/mcheck/mce.c --- a/xen/arch/x86/cpu/mcheck/mce.c Mon Apr 19 08:54:53 2010 +0100 +++ b/xen/arch/x86/cpu/mcheck/mce.c Mon Apr 19 08:55:33 2010 +0100 @@ -125,6 +125,88 @@ void mce_need_clearbank_register(mce_nee mc_need_clearbank_scan = cbfunc; } +static struct mcinfo_bank *mca_init_bank(enum mca_source who, + struct mc_info *mi, int bank) +{ + struct mcinfo_bank *mib; + uint64_t addr=0, misc = 0; + + if (!mi) + return NULL; + + mib = x86_mcinfo_reserve(mi, sizeof(struct mcinfo_bank)); + if (!mib) + { + mi->flags |= MCINFO_FLAGS_UNCOMPLETE; + return NULL; + } + + memset(mib, 0, sizeof (struct mcinfo_bank)); + mca_rdmsrl(MSR_IA32_MC0_STATUS + bank * 4, mib->mc_status); + + mib->common.type = MC_TYPE_BANK; + mib->common.size = sizeof (struct mcinfo_bank); + mib->mc_bank = bank; + + addr = misc = 0; + if (mib->mc_status & MCi_STATUS_MISCV) + mca_rdmsrl(MSR_IA32_MC0_MISC + 4 * bank, mib->mc_misc); + + if (mib->mc_status & MCi_STATUS_ADDRV) + { + mca_rdmsrl(MSR_IA32_MC0_ADDR + 4 * bank, mib->mc_addr); + + if (mfn_valid(paddr_to_pfn(mib->mc_addr))) { + struct domain *d; + + d = maddr_get_owner(mib->mc_addr); + if (d != NULL && (who == MCA_POLLER || + who == MCA_CMCI_HANDLER)) + mib->mc_domid = d->domain_id; + } + } + + if (who == MCA_CMCI_HANDLER) { + mca_rdmsrl(MSR_IA32_MC0_CTL2 + bank, mib->mc_ctrl2); + rdtscll(mib->mc_tsc); + } + + return mib; +} + +static int mca_init_global(uint32_t flags, struct mcinfo_global *mig) +{ + uint64_t status; + int cpu_nr; + struct vcpu *v = current; + struct domain *d; + + /* Set global information */ + memset(mig, 0, sizeof (struct mcinfo_global)); + mig->common.type = MC_TYPE_GLOBAL; + mig->common.size = sizeof (struct mcinfo_global); + mca_rdmsrl(MSR_IA32_MCG_STATUS, status); + mig->mc_gstatus = status; + mig->mc_domid = mig->mc_vcpuid = -1; + mig->mc_flags = flags; + cpu_nr = smp_processor_id(); + /* Retrieve detector information */ + x86_mc_get_cpu_info(cpu_nr, &mig->mc_socketid, + &mig->mc_coreid, &mig->mc_core_threadid, + &mig->mc_apicid, NULL, NULL, NULL); + + /* This is really meaningless */ + if (v != NULL && ((d = v->domain) != NULL)) { + mig->mc_domid = d->domain_id; + mig->mc_vcpuid = v->vcpu_id; + } else { + mig->mc_domid = -1; + mig->mc_vcpuid = -1; + } + + return 0; +} + /* Utility function to perform MCA bank telemetry readout and to push that * telemetry towards an interested dom0 for logging and diagnosis. * The caller - #MC handler or MCA poll function - must arrange that we @@ -139,64 +221,38 @@ mctelem_cookie_t mcheck_mca_logout(enum mctelem_cookie_t mcheck_mca_logout(enum mca_source who, cpu_banks_t bankmask, struct mca_summary *sp, cpu_banks_t* clear_bank) { - struct vcpu *v = current; - struct domain *d; - uint64_t gstatus, status, addr, misc; - struct mcinfo_global mcg; /* on stack */ - struct mcinfo_common *mic; - struct mcinfo_global *mig; /* on stack */ + uint64_t gstatus, status; + struct mcinfo_global *mig = NULL; /* on stack */ mctelem_cookie_t mctc = NULL; - uint32_t uc = 0, pcc = 0, recover, need_clear = 1 ; + uint32_t uc = 0, pcc = 0, recover, need_clear = 1, mc_flags = 0; struct mc_info *mci = NULL; mctelem_class_t which = MC_URGENT; /* XXXgcc */ - unsigned int cpu_nr; int errcnt = 0; int i; enum mca_extinfo cbret = MCA_EXTINFO_IGNORED; - cpu_nr = smp_processor_id(); - BUG_ON(cpu_nr != v->processor); - mca_rdmsrl(MSR_IA32_MCG_STATUS, gstatus); - - memset(&mcg, 0, sizeof (mcg)); - mcg.common.type = MC_TYPE_GLOBAL; - mcg.common.size = sizeof (mcg); - if (v != NULL && ((d = v->domain) != NULL)) { - mcg.mc_domid = d->domain_id; - mcg.mc_vcpuid = v->vcpu_id; - } else { - mcg.mc_domid = -1; - mcg.mc_vcpuid = -1; - } - mcg.mc_gstatus = gstatus; /* MCG_STATUS */ - switch (who) { case MCA_MCE_HANDLER: case MCA_MCE_SCAN: - mcg.mc_flags = MC_FLAG_MCE; + mc_flags = MC_FLAG_MCE; which = MC_URGENT; break; case MCA_POLLER: case MCA_RESET: - mcg.mc_flags = MC_FLAG_POLLED; + mc_flags = MC_FLAG_POLLED; which = MC_NONURGENT; break; case MCA_CMCI_HANDLER: - mcg.mc_flags = MC_FLAG_CMCI; + mc_flags = MC_FLAG_CMCI; which = MC_NONURGENT; break; default: BUG(); } - - /* Retrieve detector information */ - x86_mc_get_cpu_info(cpu_nr, &mcg.mc_socketid, - &mcg.mc_coreid, &mcg.mc_core_threadid, - &mcg.mc_apicid, NULL, NULL, NULL); /* If no mc_recovery_scan callback handler registered, * this error is not recoverable @@ -204,7 +260,7 @@ mctelem_cookie_t mcheck_mca_logout(enum recover = (mc_recoverable_scan)? 1: 0; for (i = 0; i < 32 && i < nr_mce_banks; i++) { - struct mcinfo_bank mcb; /* on stack */ + struct mcinfo_bank *mib; /* on stack */ /* Skip bank if corresponding bit in bankmask is clear */ if (!test_bit(i, bankmask)) @@ -227,17 +283,16 @@ mctelem_cookie_t mcheck_mca_logout(enum * a poller; this can fail (for example dom0 may not * yet have consumed past telemetry). */ if (errcnt == 0) { - if ((mctc = mctelem_reserve(which)) != NULL) { + if ( (mctc = mctelem_reserve(which)) != NULL ) { mci = mctelem_dataptr(mctc); mcinfo_clear(mci); + mig = (struct mcinfo_global*)x86_mcinfo_reserve + (mci, sizeof(struct mcinfo_global)); + /* mc_info should at least hold up the global information */ + ASSERT(mig); + mca_init_global(mc_flags, mig); } } - - memset(&mcb, 0, sizeof (mcb)); - mcb.common.type = MC_TYPE_BANK; - mcb.common.size = sizeof (mcb); - mcb.mc_bank = i; - mcb.mc_status = status; /* form a mask of which banks have logged uncorrected errors */ if ((status & MCi_STATUS_UC) != 0) @@ -252,37 +307,7 @@ mctelem_cookie_t mcheck_mca_logout(enum */ recover = mc_recoverable_scan(status); - addr = misc = 0; - - if (status & MCi_STATUS_ADDRV) { - mca_rdmsrl(MSR_IA32_MC0_ADDR + 4 * i, addr); - if (mfn_valid(paddr_to_pfn(addr))) { - d = maddr_get_owner(addr); - if (d != NULL && (who == MCA_POLLER || - who == MCA_CMCI_HANDLER)) - mcb.mc_domid = d->domain_id; - } - } - - if (status & MCi_STATUS_MISCV) - mca_rdmsrl(MSR_IA32_MC0_MISC + 4 * i, misc); - - mcb.mc_addr = addr; - mcb.mc_misc = misc; - - if (who == MCA_CMCI_HANDLER) { - mca_rdmsrl(MSR_IA32_MC0_CTL2 + i, mcb.mc_ctrl2); - rdtscll(mcb.mc_tsc); - } - - /* Increment the error count; if this is the first bank - * with a valid error then add the global info to the mcinfo. */ - if (errcnt++ == 0 && mci != NULL) - x86_mcinfo_add(mci, &mcg); - - /* Add the bank data */ - if (mci != NULL) - x86_mcinfo_add(mci, &mcb); + mib = mca_init_bank(who, mci, i); if (mc_callback_bank_extended && cbret != MCA_EXTINFO_GLOBAL) { cbret = mc_callback_bank_extended(mci, i, status); @@ -298,12 +323,8 @@ mctelem_cookie_t mcheck_mca_logout(enum wmb(); } - if (mci != NULL && errcnt > 0) { - x86_mcinfo_lookup(mic, mci, MC_TYPE_GLOBAL); - mig = container_of(mic, struct mcinfo_global, common); - if (mic == NULL) - ; - else if (pcc) + if (mig && errcnt > 0) { + if (pcc) mig->mc_flags |= MC_FLAG_UNCORRECTABLE; else if (uc) mig->mc_flags |= MC_FLAG_RECOVERABLE; @@ -758,13 +779,12 @@ static void mcinfo_clear(struct mc_info x86_mcinfo_nentries(mi) = 0; } -int x86_mcinfo_add(struct mc_info *mi, void *mcinfo) +void *x86_mcinfo_reserve(struct mc_info *mi, int size) { int i; unsigned long end1, end2; - struct mcinfo_common *mic, *mic_base, *mic_index; - - mic = (struct mcinfo_common *)mcinfo; + struct mcinfo_common *mic_base, *mic_index; + mic_index = mic_base = x86_mcinfo_first(mi); /* go to first free entry */ @@ -774,16 +794,35 @@ int x86_mcinfo_add(struct mc_info *mi, v /* check if there is enough size */ end1 = (unsigned long)((uint8_t *)mic_base + sizeof(struct mc_info)); - end2 = (unsigned long)((uint8_t *)mic_index + mic->size); + end2 = (unsigned long)((uint8_t *)mic_index + size); if (end1 < end2) - return x86_mcerr("mcinfo_add: no more sparc", -ENOSPC); + { + mce_printk(MCE_CRITICAL, + "mcinfo_add: No space left in mc_info\n"); + return NULL; + } /* there's enough space. add entry. */ - memcpy(mic_index, mic, mic->size); x86_mcinfo_nentries(mi)++; - return 0; + return mic_index; +} + +void *x86_mcinfo_add(struct mc_info *mi, void *mcinfo) +{ + struct mcinfo_common *mic, *buf; + + mic = (struct mcinfo_common *)mcinfo; + buf = x86_mcinfo_reserve(mi, mic->size); + + if ( !buf ) + mce_printk(MCE_CRITICAL, + "mcinfo_add: No space left in mc_info\n"); + else + memcpy(buf, mic, mic->size); + + return buf; } /* Dump machine check information in a format, diff -r 6233eb0f29ba -r 6860c523d2da xen/arch/x86/cpu/mcheck/mce.h --- a/xen/arch/x86/cpu/mcheck/mce.h Mon Apr 19 08:54:53 2010 +0100 +++ b/xen/arch/x86/cpu/mcheck/mce.h Mon Apr 19 08:55:33 2010 +0100 @@ -161,7 +161,8 @@ typedef enum mca_extinfo (*x86_mce_callb (struct mc_info *, uint16_t, uint64_t); extern void x86_mce_callback_register(x86_mce_callback_t); -int x86_mcinfo_add(struct mc_info *mi, void *mcinfo); +void *x86_mcinfo_add(struct mc_info *mi, void *mcinfo); +void *x86_mcinfo_reserve(struct mc_info *mi, int size); void x86_mcinfo_dump(struct mc_info *mi); int fill_vmsr_data(struct mcinfo_bank *mc_bank, struct domain *d, diff -r 6233eb0f29ba -r 6860c523d2da xen/include/public/arch-x86/xen-mca.h --- a/xen/include/public/arch-x86/xen-mca.h Mon Apr 19 08:54:53 2010 +0100 +++ b/xen/include/public/arch-x86/xen-mca.h Mon Apr 19 08:55:33 2010 +0100 @@ -233,10 +233,11 @@ struct mcinfo_recovery #define MCINFO_HYPERCALLSIZE 1024 #define MCINFO_MAXSIZE 768 +#define MCINFO_FLAGS_UNCOMPLETE 0x1 struct mc_info { /* Number of mcinfo_* entries in mi_data */ uint32_t mi_nentries; - uint32_t _pad0; + uint32_t flags; uint64_t mi_data[(MCINFO_MAXSIZE - 1) / 8]; }; typedef struct mc_info mc_info_t; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |