> Shan Haitao
>
> 2011/3/1 Keir Fraser <
keir.xen@xxxxxxxxx>
>> Some 
  comments inline below. Overall a good patch to have, but needs 
  some
>> minor adjustments!
>>
>>  -- 
  Keir
>>
>> On 01/03/2011 09:09, "Liu, Jinsong" <
jinsong.liu@xxxxxxxxx> 
  wrote:
>>
>>> 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 110,000 round cpu
>>> 
  online/offline.
>>>
>>> Signed-off-by: Liu, Jinsong 
  <
jinsong.liu@xxxxxxxxx>
>>>
>>> 
  diff -r 1a364b17d66a xen/arch/x86/cpu/mcheck/mce_intel.c
>>> --- 
  a/xen/arch/x86/cpu/mcheck/mce_intel.c Fri Feb 25 01:26:01 2011 
  +0800
>>> +++ b/xen/arch/x86/cpu/mcheck/mce_intel.c Mon Feb 28 
  19:19:20 2011 +0800
>>> @@ -1227,9 +1227,24 @@ static void 
  intel_init_mce(void)
>>>      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 void cpu_mcabank_alloc(unsigned int cpu)
>>> 
  +{
>>> +    struct mca_banks *mb1, *mb2, 
  *mb3;
>>>
>>>      mb1 = 
  mcabanks_alloc();
>>>      mb2 = 
  mcabanks_alloc();
>>> @@ -1237,22 +1252,23 @@ static int 
  intel_init_mca_banks(void)
>>>      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;
>>>
>>> -    return 
  0;
>>>  out:
>>>     
   mcabanks_free(mb1);
>>>     
   mcabanks_free(mb2);
>>>     
   mcabanks_free(mb3);
>>> -    return 
  -ENOMEM;
>>>  }
>>>
>>>  /* 
  p4/p6 family have similar MCA initialization process */
>>> 
   enum mcheck_type intel_mcheck_init(struct cpuinfo_x86 
  *c)
>>>  {
>>> -    if 
  (intel_init_mca_banks())
>>> +    if ( 
  !this_cpu(mce_clear_banks) ||
>>> +         
  !this_cpu(no_cmci_banks)   ||
>>> +       
    !this_cpu(mce_banks_owned) )
>>>       
      return mcheck_none;
>>>
>>>   
     intel_init_mca(c);
>>> @@ -1301,13 +1317,19 @@ static 
  int cpu_callback(
>>>  static int 
  cpu_callback(
>>>      struct notifier_block *nfb, 
  unsigned long action, void *hcpu)
>>>  {
>>> + 
     unsigned int cpu = (unsigned long)hcpu;
>>> 
  +
>>>      switch ( action )
>>>   
     {
>>> +    case 
  CPU_UP_PREPARE:
>>> +       
   cpu_mcabank_alloc(cpu);
>>> +       
   break;
>>>      case 
  CPU_DYING:
>>>         
   cpu_mcheck_disable();
>>>         
   break;
>>>      case 
  CPU_DEAD:
>>>         
   cpu_mcheck_distribute_cmci();
>>> +       
   cpu_mcabank_free(cpu);
>>>         
   break;
>>
>> You also need to cpu_mcabank_free(cpu) on 
  CPU_UP_CANCELED. Else there's a
>> memory leak on failed CPU 
  bringup.
>>
>>>     
   default:
>>>         
   break;
>>> @@ -1322,6 +1344,8 @@ static struct 
  notifier_block cpu_nfb = {
>>>
>>>  static int 
  __init intel_mce_initcall(void)
>>>  {
>>> + 
     void *hcpu = (void *)(long)smp_processor_id();
>>> + 
     cpu_callback(&cpu_nfb, CPU_UP_PREPARE, hcpu);
>>> 
       register_cpu_notifier(&cpu_nfb);
>>> 
       return 0;
>>>  }
>>> diff -r 
  1a364b17d66a xen/arch/x86/setup.c
>>> --- a/xen/arch/x86/setup.c 
  Fri Feb 25 01:26:01 2011 +0800
>>> +++ b/xen/arch/x86/setup.c Mon 
  Feb 28 19:19:20 2011 +0800
>>> @@ -1203,6 +1203,8 @@ void __init 
  __start_xen(unsigned long mb
>>>
>>>     
   arch_init_memory();
>>>
>>> +   
   do_presmp_initcalls();
>>> +
>>>     
   identify_cpu(&boot_cpu_data);
>>>      if 
  ( cpu_has_fxsr )
>>>         
   set_in_cr4(X86_CR4_OSFXSR);
>>> @@ -1235,8 +1237,6 @@ void 
  __init __start_xen(unsigned long mb
>>>     
   initialize_keytable();
>>>
>>>     
   console_init_postirq();
>>> -
>>> -   
   do_presmp_initcalls();
>>
>> This looks risky, 
  especially so close to 4.1 release. Instead of moving
>> 
  do_presmp_initcalls(), please special-case cpu_mcabank_alloc() for CPU0 
  in
>> intel_mcheck_init(), and remove your direct call to
>> 
  cpu_callback(...CPU_UP_PREPARE...) in 
  intel_mce_initcall().
>>
>>>     
   for_each_present_cpu ( i )
>>>     
   {
>>
>>
>
>