# 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
|