[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86: Fix cpu online/offline bug: mce memory leak.
# HG changeset patch # User Liu, Jinsong <jinsong.liu@xxxxxxxxx> # Date 1299061866 0 # Node ID f71212f712fd8dad7997785fd61edca28c0d9536 # Parent 666006a3a4ad3e4015fa0610aae6ebda3d271523 x86: Fix cpu online/offline bug: mce memory leak. Current Xen mce logic didn't free mcabanks. This would be a memory leak when cpu offline. When repeatly do cpu online/offline, this memory leak would make xenpool shrink, and at a time point, will call alloc_heap_pages --> flush_area_mask, which ASSERT(local_irq_is_enabled()). However, cpu online is irq disable, so it finally result in Xen crash. This patch fix the memory leak bug, and tested OK over 50,000 round cpu online/offline. Signed-off-by: Liu, Jinsong <jinsong.liu@xxxxxxxxx> Signed-off-by: Keir Fraser <keir@xxxxxxx> --- diff -r 666006a3a4ad -r f71212f712fd xen/arch/x86/cpu/mcheck/mce_intel.c --- a/xen/arch/x86/cpu/mcheck/mce_intel.c Wed Mar 02 10:23:23 2011 +0000 +++ b/xen/arch/x86/cpu/mcheck/mce_intel.c Wed Mar 02 10:31:06 2011 +0000 @@ -1227,9 +1227,24 @@ mce_uhandler_num = sizeof(intel_mce_uhandlers)/sizeof(struct mca_error_handler); } -static int intel_init_mca_banks(void) +static void cpu_mcabank_free(unsigned int cpu) { - struct mca_banks *mb1, *mb2, * mb3; + struct mca_banks *mb1, *mb2, *mb3, *mb4; + + mb1 = per_cpu(mce_clear_banks, cpu); + mb2 = per_cpu(no_cmci_banks, cpu); + mb3 = per_cpu(mce_banks_owned, cpu); + mb4 = per_cpu(poll_bankmask, cpu); + + mcabanks_free(mb1); + mcabanks_free(mb2); + mcabanks_free(mb3); + mcabanks_free(mb4); +} + +static int cpu_mcabank_alloc(unsigned int cpu) +{ + struct mca_banks *mb1, *mb2, *mb3; mb1 = mcabanks_alloc(); mb2 = mcabanks_alloc(); @@ -1237,9 +1252,9 @@ if (!mb1 || !mb2 || !mb3) goto out; - __get_cpu_var(mce_clear_banks) = mb1; - __get_cpu_var(no_cmci_banks) = mb2; - __get_cpu_var(mce_banks_owned) = mb3; + per_cpu(mce_clear_banks, cpu) = mb1; + per_cpu(no_cmci_banks, cpu) = mb2; + per_cpu(mce_banks_owned, cpu) = mb3; return 0; out: @@ -1249,11 +1264,46 @@ return -ENOMEM; } +static int cpu_callback( + struct notifier_block *nfb, unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + int rc = 0; + + switch ( action ) + { + case CPU_UP_PREPARE: + rc = cpu_mcabank_alloc(cpu); + break; + case CPU_DYING: + cpu_mcheck_disable(); + break; + case CPU_UP_CANCELED: + case CPU_DEAD: + cpu_mcheck_distribute_cmci(); + cpu_mcabank_free(cpu); + break; + default: + break; + } + + return !rc ? NOTIFY_DONE : notifier_from_errno(rc); +} + +static struct notifier_block cpu_nfb = { + .notifier_call = cpu_callback +}; + /* p4/p6 family have similar MCA initialization process */ enum mcheck_type intel_mcheck_init(struct cpuinfo_x86 *c) { - if (intel_init_mca_banks()) - return mcheck_none; + if ( smp_processor_id() == 0 ) + { + /* Early MCE initialisation for BSP. */ + if ( cpu_mcabank_alloc(0) ) + BUG(); + register_cpu_notifier(&cpu_nfb); + } intel_init_mca(c); @@ -1298,31 +1348,3 @@ return ret; } -static int cpu_callback( - struct notifier_block *nfb, unsigned long action, void *hcpu) -{ - switch ( action ) - { - case CPU_DYING: - cpu_mcheck_disable(); - break; - case CPU_DEAD: - cpu_mcheck_distribute_cmci(); - break; - default: - break; - } - - return NOTIFY_DONE; -} - -static struct notifier_block cpu_nfb = { - .notifier_call = cpu_callback -}; - -static int __init intel_mce_initcall(void) -{ - register_cpu_notifier(&cpu_nfb); - return 0; -} -presmp_initcall(intel_mce_initcall); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |