[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86 svm: Clean up and fix start_svm() to avoid memory leaks and
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1245314869 -3600 # Node ID 44fe7ad6fee8229654875485ca57bb6f616045ab # Parent 61ec78692b13bd83392f169de793b677b3b24db0 x86 svm: Clean up and fix start_svm() to avoid memory leaks and resetting ASID generations. Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> --- xen/arch/x86/cpu/amd.c | 2 - xen/arch/x86/hvm/svm/asid.c | 12 +++++++- xen/arch/x86/hvm/svm/svm.c | 61 ++++++++++++++++++++++++++++---------------- xen/arch/x86/hvm/vmx/vmx.c | 6 +--- 4 files changed, 54 insertions(+), 27 deletions(-) diff -r 61ec78692b13 -r 44fe7ad6fee8 xen/arch/x86/cpu/amd.c --- a/xen/arch/x86/cpu/amd.c Wed Jun 17 07:39:27 2009 +0100 +++ b/xen/arch/x86/cpu/amd.c Thu Jun 18 09:47:49 2009 +0100 @@ -12,7 +12,7 @@ #include "cpu.h" #include "amd.h" -int start_svm(struct cpuinfo_x86 *c); +void start_svm(struct cpuinfo_x86 *c); /* * Pre-canned values for overriding the CPUID features diff -r 61ec78692b13 -r 44fe7ad6fee8 xen/arch/x86/hvm/svm/asid.c --- a/xen/arch/x86/hvm/svm/asid.c Wed Jun 17 07:39:27 2009 +0100 +++ b/xen/arch/x86/hvm/svm/asid.c Thu Jun 18 09:47:49 2009 +0100 @@ -61,6 +61,7 @@ struct svm_asid_data { u32 next_asid; u32 max_asid; u32 erratum170:1; + u32 initialised:1; }; static DEFINE_PER_CPU(struct svm_asid_data, svm_asid_data); @@ -70,7 +71,7 @@ static DEFINE_PER_CPU(struct svm_asid_da */ static struct svm_asid_data *svm_asid_core_data(void) { - return &get_cpu_var(svm_asid_data); + return &this_cpu(svm_asid_data); } /* @@ -80,6 +81,15 @@ void svm_asid_init(struct cpuinfo_x86 *c { int nasids; struct svm_asid_data *data = svm_asid_core_data(); + + /* + * If already initialised, we just bump the generation to force a TLB + * flush. Resetting the generation could be dangerous, if VCPUs still + * exist that reference earlier generations on this CPU. + */ + if ( data->initialised ) + return svm_asid_inc_generation(); + data->initialised = 1; /* Find #ASID. */ nasids = cpuid_ebx(0x8000000A); diff -r 61ec78692b13 -r 44fe7ad6fee8 xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Wed Jun 17 07:39:27 2009 +0100 +++ b/xen/arch/x86/hvm/svm/svm.c Thu Jun 18 09:47:49 2009 +0100 @@ -839,45 +839,66 @@ static struct hvm_function_table svm_fun .invlpg_intercept = svm_invlpg_intercept }; -int start_svm(struct cpuinfo_x86 *c) -{ - u32 eax, ecx, edx; - u32 phys_hsa_lo, phys_hsa_hi; +static int svm_cpu_up(struct cpuinfo_x86 *c) +{ + u32 eax, edx, phys_hsa_lo, phys_hsa_hi; u64 phys_hsa; int cpu = smp_processor_id(); - /* Xen does not fill x86_capability words except 0. */ - ecx = cpuid_ecx(0x80000001); - boot_cpu_data.x86_capability[5] = ecx; - - if ( !(test_bit(X86_FEATURE_SVME, &boot_cpu_data.x86_capability)) ) - return 0; - /* Check whether SVM feature is disabled in BIOS */ rdmsr(MSR_K8_VM_CR, eax, edx); if ( eax & K8_VMCR_SVME_DISABLE ) { - printk("AMD SVM Extension is disabled in BIOS.\n"); + printk("CPU%d: AMD SVM Extension is disabled in BIOS.\n", cpu); return 0; } - if ( ((hsa[cpu] = alloc_host_save_area()) == NULL) || - ((root_vmcb[cpu] = alloc_vmcb()) == NULL) ) + if ( ((hsa[cpu] == NULL) && + ((hsa[cpu] = alloc_host_save_area()) == NULL)) || + ((root_vmcb[cpu] == NULL) && + ((root_vmcb[cpu] = alloc_vmcb()) == NULL)) ) return 0; write_efer(read_efer() | EFER_SVME); /* Initialize the HSA for this core. */ - phys_hsa = (u64) virt_to_maddr(hsa[cpu]); - phys_hsa_lo = (u32) phys_hsa; - phys_hsa_hi = (u32) (phys_hsa >> 32); + phys_hsa = (u64)virt_to_maddr(hsa[cpu]); + phys_hsa_lo = (u32)phys_hsa; + phys_hsa_hi = (u32)(phys_hsa >> 32); wrmsr(MSR_K8_VM_HSAVE_PA, phys_hsa_lo, phys_hsa_hi); /* Initialize core's ASID handling. */ svm_asid_init(c); - if ( cpu != 0 ) - return 1; + return 1; +} + +void start_svm(struct cpuinfo_x86 *c) +{ + static bool_t bootstrapped; + + if ( !test_and_set_bool(bootstrapped) ) + { + if ( hvm_enabled && !svm_cpu_up(c) ) + { + printk("SVM: FATAL: failed to initialise CPU%d!\n", + smp_processor_id()); + BUG(); + } + return; + } + + /* Xen does not fill x86_capability words except 0. */ + boot_cpu_data.x86_capability[5] = cpuid_ecx(0x80000001); + + if ( !test_bit(X86_FEATURE_SVME, &boot_cpu_data.x86_capability) ) + return; + + if ( !svm_cpu_up(c) ) + { + printk("SVM: failed to initialise.\n"); + return; + } setup_vmcb_dump(); @@ -887,8 +908,6 @@ int start_svm(struct cpuinfo_x86 *c) svm_function_table.hap_supported = cpu_has_svm_npt; hvm_enable(&svm_function_table); - - return 1; } static void svm_do_nested_pgfault(paddr_t gpa, struct cpu_user_regs *regs) diff -r 61ec78692b13 -r 44fe7ad6fee8 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 17 07:39:27 2009 +0100 +++ b/xen/arch/x86/hvm/vmx/vmx.c Thu Jun 18 09:47:49 2009 +0100 @@ -1403,11 +1403,11 @@ static unsigned long *vpid_bitmap; void start_vmx(void) { - static int bootstrapped; + static bool_t bootstrapped; vmx_save_host_msrs(); - if ( bootstrapped ) + if ( !test_and_set_bool(bootstrapped) ) { if ( hvm_enabled && !vmx_cpu_up() ) { @@ -1417,8 +1417,6 @@ void start_vmx(void) } return; } - - bootstrapped = 1; /* Xen does not fill x86_capability words except 0. */ boot_cpu_data.x86_capability[4] = cpuid_ecx(1); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |