Skip to content

Commit e7aa294

Browse files
committed
Turn on/off SVM dynamically at run time.
This is needed for coexistence with VirtualBox.
1 parent bb5ffbd commit e7aa294

1 file changed

Lines changed: 22 additions & 21 deletions

File tree

arch/x86/kvm/svm.c

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -542,35 +542,24 @@ static int has_svm(void)
542542
return static_cpu_has(X86_FEATURE_SVM);
543543
}
544544

545-
static inline void cpu_svm_disable(void)
546-
{
547-
uint64_t efer;
548-
549-
wrmsrl(MSR_VM_HSAVE_PA, 0);
550-
rdmsrl(MSR_EFER, efer);
551-
wrmsrl(MSR_EFER, efer & ~EFER_SVME);
552-
}
553-
554545
static void svm_hardware_disable(void)
555546
{
556-
cpu_svm_disable();
557-
558547
//amd_pmu_disable_virt();
559548
}
560549

550+
/*
551+
* This does not turn on SVM as Linus does now, as on Windows coexistence with
552+
* other VMMs is important and requires turning on/off SVM dynamically at run
553+
* time.
554+
*/
561555
static int svm_hardware_enable(void)
562556
{
563557

564558
struct svm_cpu_data *sd;
565-
uint64_t efer;
566559
struct desc_ptr gdt_descr;
567560
struct desc_struct *gdt;
568561
int me = raw_smp_processor_id();
569562

570-
rdmsrl(MSR_EFER, efer);
571-
if (efer & EFER_SVME)
572-
return -EBUSY;
573-
574563
if (!has_svm()) {
575564
pr_err("%s: err EOPNOTSUPP on %d\n", __func__, me);
576565
return -EINVAL;
@@ -589,11 +578,6 @@ static int svm_hardware_enable(void)
589578
gdt = (struct desc_struct *)gdt_descr.address;
590579
sd->tss_desc = (struct kvm_ldttss_desc *)(gdt + GDT_ENTRY_TSS);
591580

592-
wrmsrl(MSR_EFER, efer | EFER_SVME);
593-
594-
wrmsrl(MSR_VM_HSAVE_PA, page_to_pfn(sd->save_area) << PAGE_SHIFT);
595-
596-
597581
/*
598582
* Get OSVW bits.
599583
*
@@ -4220,6 +4204,10 @@ static void svm_cancel_injection(struct kvm_vcpu *vcpu)
42204204
static void svm_vcpu_run(struct kvm_vcpu *vcpu)
42214205
{
42224206
struct vcpu_svm *svm = to_svm(vcpu);
4207+
int me = raw_smp_processor_id();
4208+
struct svm_cpu_data *sd;
4209+
uint64_t efer, hsave_pa = 0;
4210+
uint64_t svm_enabled;
42234211

42244212
svm->vmcb->save.rax = vcpu->arch.regs[VCPU_REGS_RAX];
42254213
svm->vmcb->save.rsp = vcpu->arch.regs[VCPU_REGS_RSP];
@@ -4238,6 +4226,15 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
42384226

42394227
svm->vmcb->save.cr2 = vcpu->arch.cr2;
42404228

4229+
sd = per_cpu(svm_data, me);
4230+
rdmsrl(MSR_EFER, efer);
4231+
svm_enabled = !!(efer & EFER_SVME);
4232+
if (!svm_enabled)
4233+
wrmsrl(MSR_EFER, efer | EFER_SVME);
4234+
else
4235+
rdmsrl(MSR_VM_HSAVE_PA, hsave_pa);
4236+
wrmsrl(MSR_VM_HSAVE_PA, page_to_pfn(sd->save_area) << PAGE_SHIFT);
4237+
42414238
clgi();
42424239

42434240
local_irq_enable();
@@ -4265,6 +4262,10 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
42654262

42664263
stgi();
42674264

4265+
wrmsrl(MSR_VM_HSAVE_PA, hsave_pa);
4266+
if (!svm_enabled)
4267+
wrmsrl(MSR_EFER, efer);
4268+
42684269
/* Any pending NMI will happen here */
42694270

42704271
if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))

0 commit comments

Comments
 (0)