ia64/xen-unstable

changeset 19784:44fe7ad6fee8

x86 svm: Clean up and fix start_svm() to avoid memory leaks and
resetting ASID generations.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 18 09:47:49 2009 +0100 (2009-06-18)
parents 61ec78692b13
children 82366af53828
files xen/arch/x86/cpu/amd.c xen/arch/x86/hvm/svm/asid.c xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/vmx/vmx.c
line diff
     1.1 --- a/xen/arch/x86/cpu/amd.c	Wed Jun 17 07:39:27 2009 +0100
     1.2 +++ b/xen/arch/x86/cpu/amd.c	Thu Jun 18 09:47:49 2009 +0100
     1.3 @@ -12,7 +12,7 @@
     1.4  #include "cpu.h"
     1.5  #include "amd.h"
     1.6  
     1.7 -int start_svm(struct cpuinfo_x86 *c);
     1.8 +void start_svm(struct cpuinfo_x86 *c);
     1.9  
    1.10  /*
    1.11   * Pre-canned values for overriding the CPUID features 
     2.1 --- a/xen/arch/x86/hvm/svm/asid.c	Wed Jun 17 07:39:27 2009 +0100
     2.2 +++ b/xen/arch/x86/hvm/svm/asid.c	Thu Jun 18 09:47:49 2009 +0100
     2.3 @@ -61,6 +61,7 @@ struct svm_asid_data {
     2.4     u32 next_asid;
     2.5     u32 max_asid;
     2.6     u32 erratum170:1;
     2.7 +   u32 initialised:1;
     2.8  };
     2.9  
    2.10  static DEFINE_PER_CPU(struct svm_asid_data, svm_asid_data);
    2.11 @@ -70,7 +71,7 @@ static DEFINE_PER_CPU(struct svm_asid_da
    2.12   */
    2.13  static struct svm_asid_data *svm_asid_core_data(void)
    2.14  {
    2.15 -    return &get_cpu_var(svm_asid_data);
    2.16 +    return &this_cpu(svm_asid_data);
    2.17  }
    2.18  
    2.19  /*
    2.20 @@ -81,6 +82,15 @@ void svm_asid_init(struct cpuinfo_x86 *c
    2.21      int nasids;
    2.22      struct svm_asid_data *data = svm_asid_core_data();
    2.23  
    2.24 +    /*
    2.25 +     * If already initialised, we just bump the generation to force a TLB
    2.26 +     * flush. Resetting the generation could be dangerous, if VCPUs still
    2.27 +     * exist that reference earlier generations on this CPU.
    2.28 +     */
    2.29 +    if ( data->initialised )
    2.30 +        return svm_asid_inc_generation();
    2.31 +    data->initialised = 1;
    2.32 +
    2.33      /* Find #ASID. */
    2.34      nasids = cpuid_ebx(0x8000000A);
    2.35      data->max_asid = nasids - 1;
     3.1 --- a/xen/arch/x86/hvm/svm/svm.c	Wed Jun 17 07:39:27 2009 +0100
     3.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Thu Jun 18 09:47:49 2009 +0100
     3.3 @@ -839,45 +839,66 @@ static struct hvm_function_table svm_fun
     3.4      .invlpg_intercept     = svm_invlpg_intercept
     3.5  };
     3.6  
     3.7 -int start_svm(struct cpuinfo_x86 *c)
     3.8 +static int svm_cpu_up(struct cpuinfo_x86 *c)
     3.9  {
    3.10 -    u32 eax, ecx, edx;
    3.11 -    u32 phys_hsa_lo, phys_hsa_hi;   
    3.12 +    u32 eax, edx, phys_hsa_lo, phys_hsa_hi;   
    3.13      u64 phys_hsa;
    3.14      int cpu = smp_processor_id();
    3.15   
    3.16 -    /* Xen does not fill x86_capability words except 0. */
    3.17 -    ecx = cpuid_ecx(0x80000001);
    3.18 -    boot_cpu_data.x86_capability[5] = ecx;
    3.19 -    
    3.20 -    if ( !(test_bit(X86_FEATURE_SVME, &boot_cpu_data.x86_capability)) )
    3.21 -        return 0;
    3.22 -
    3.23      /* Check whether SVM feature is disabled in BIOS */
    3.24      rdmsr(MSR_K8_VM_CR, eax, edx);
    3.25      if ( eax & K8_VMCR_SVME_DISABLE )
    3.26      {
    3.27 -        printk("AMD SVM Extension is disabled in BIOS.\n");
    3.28 +        printk("CPU%d: AMD SVM Extension is disabled in BIOS.\n", cpu);
    3.29          return 0;
    3.30      }
    3.31  
    3.32 -    if ( ((hsa[cpu] = alloc_host_save_area()) == NULL) ||
    3.33 -         ((root_vmcb[cpu] = alloc_vmcb()) == NULL) )
    3.34 +    if ( ((hsa[cpu] == NULL) &&
    3.35 +          ((hsa[cpu] = alloc_host_save_area()) == NULL)) ||
    3.36 +         ((root_vmcb[cpu] == NULL) &&
    3.37 +          ((root_vmcb[cpu] = alloc_vmcb()) == NULL)) )
    3.38          return 0;
    3.39  
    3.40      write_efer(read_efer() | EFER_SVME);
    3.41  
    3.42      /* Initialize the HSA for this core. */
    3.43 -    phys_hsa = (u64) virt_to_maddr(hsa[cpu]);
    3.44 -    phys_hsa_lo = (u32) phys_hsa;
    3.45 -    phys_hsa_hi = (u32) (phys_hsa >> 32);    
    3.46 +    phys_hsa = (u64)virt_to_maddr(hsa[cpu]);
    3.47 +    phys_hsa_lo = (u32)phys_hsa;
    3.48 +    phys_hsa_hi = (u32)(phys_hsa >> 32);    
    3.49      wrmsr(MSR_K8_VM_HSAVE_PA, phys_hsa_lo, phys_hsa_hi);
    3.50  
    3.51      /* Initialize core's ASID handling. */
    3.52      svm_asid_init(c);
    3.53  
    3.54 -    if ( cpu != 0 )
    3.55 -        return 1;
    3.56 +    return 1;
    3.57 +}
    3.58 +
    3.59 +void start_svm(struct cpuinfo_x86 *c)
    3.60 +{
    3.61 +    static bool_t bootstrapped;
    3.62 +
    3.63 +    if ( !test_and_set_bool(bootstrapped) )
    3.64 +    {
    3.65 +        if ( hvm_enabled && !svm_cpu_up(c) )
    3.66 +        {
    3.67 +            printk("SVM: FATAL: failed to initialise CPU%d!\n",
    3.68 +                   smp_processor_id());
    3.69 +            BUG();
    3.70 +        }
    3.71 +        return;
    3.72 +    }
    3.73 +
    3.74 +    /* Xen does not fill x86_capability words except 0. */
    3.75 +    boot_cpu_data.x86_capability[5] = cpuid_ecx(0x80000001);
    3.76 +
    3.77 +    if ( !test_bit(X86_FEATURE_SVME, &boot_cpu_data.x86_capability) )
    3.78 +        return;
    3.79 +
    3.80 +    if ( !svm_cpu_up(c) )
    3.81 +    {
    3.82 +        printk("SVM: failed to initialise.\n");
    3.83 +        return;
    3.84 +    }
    3.85  
    3.86      setup_vmcb_dump();
    3.87  
    3.88 @@ -887,8 +908,6 @@ int start_svm(struct cpuinfo_x86 *c)
    3.89      svm_function_table.hap_supported = cpu_has_svm_npt;
    3.90  
    3.91      hvm_enable(&svm_function_table);
    3.92 -
    3.93 -    return 1;
    3.94  }
    3.95  
    3.96  static void svm_do_nested_pgfault(paddr_t gpa, struct cpu_user_regs *regs)
     4.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Wed Jun 17 07:39:27 2009 +0100
     4.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Thu Jun 18 09:47:49 2009 +0100
     4.3 @@ -1403,11 +1403,11 @@ static unsigned long *vpid_bitmap;
     4.4  
     4.5  void start_vmx(void)
     4.6  {
     4.7 -    static int bootstrapped;
     4.8 +    static bool_t bootstrapped;
     4.9  
    4.10      vmx_save_host_msrs();
    4.11  
    4.12 -    if ( bootstrapped )
    4.13 +    if ( !test_and_set_bool(bootstrapped) )
    4.14      {
    4.15          if ( hvm_enabled && !vmx_cpu_up() )
    4.16          {
    4.17 @@ -1418,8 +1418,6 @@ void start_vmx(void)
    4.18          return;
    4.19      }
    4.20  
    4.21 -    bootstrapped = 1;
    4.22 -
    4.23      /* Xen does not fill x86_capability words except 0. */
    4.24      boot_cpu_data.x86_capability[4] = cpuid_ecx(1);
    4.25