]> git.baikalelectronics.ru Git - kernel.git/commitdiff
KVM: nSVM: Pull CS.Base from actual VMCB12 for soft int/ex re-injection
authorMaciej S. Szmigiero <maciej.szmigiero@oracle.com>
Mon, 18 Jul 2022 15:47:13 +0000 (17:47 +0200)
committerPaolo Bonzini <pbonzini@redhat.com>
Thu, 28 Jul 2022 17:22:14 +0000 (13:22 -0400)
enter_svm_guest_mode() first calls nested_vmcb02_prepare_control() to copy
control fields from VMCB12 to the current VMCB, then
nested_vmcb02_prepare_save() to perform a similar copy of the save area.

This means that nested_vmcb02_prepare_control() still runs with the
previous save area values in the current VMCB so it shouldn't take the L2
guest CS.Base from this area.

Explicitly pull CS.Base from the actual VMCB12 instead in
enter_svm_guest_mode().

Granted, having a non-zero CS.Base is a very rare thing (and even
impossible in 64-bit mode), having it change between nested VMRUNs is
probably even rarer, but if it happens it would create a really subtle bug
so it's better to fix it upfront.

Fixes: 6dc162c00eef ("KVM: SVM: Re-inject INT3/INTO instead of retrying the instruction")
Signed-off-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com>
Message-Id: <4caa0f67589ae3c22c311ee0e6139496902f2edc.1658159083.git.maciej.szmigiero@oracle.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/svm/nested.c

index adf4120b05d908c2ebceb25da9aeb408a2d030af..23252ab82194140f5ca1f7932820de17571c6681 100644 (file)
@@ -639,7 +639,8 @@ static bool is_evtinj_nmi(u32 evtinj)
 }
 
 static void nested_vmcb02_prepare_control(struct vcpu_svm *svm,
-                                         unsigned long vmcb12_rip)
+                                         unsigned long vmcb12_rip,
+                                         unsigned long vmcb12_csbase)
 {
        u32 int_ctl_vmcb01_bits = V_INTR_MASKING_MASK;
        u32 int_ctl_vmcb12_bits = V_TPR_MASK | V_IRQ_INJECTION_BITS_MASK;
@@ -711,7 +712,7 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm,
        svm->nmi_l1_to_l2 = is_evtinj_nmi(vmcb02->control.event_inj);
        if (is_evtinj_soft(vmcb02->control.event_inj)) {
                svm->soft_int_injected = true;
-               svm->soft_int_csbase = svm->vmcb->save.cs.base;
+               svm->soft_int_csbase = vmcb12_csbase;
                svm->soft_int_old_rip = vmcb12_rip;
                if (svm->nrips_enabled)
                        svm->soft_int_next_rip = svm->nested.ctl.next_rip;
@@ -800,7 +801,7 @@ int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vmcb12_gpa,
        nested_svm_copy_common_state(svm->vmcb01.ptr, svm->nested.vmcb02.ptr);
 
        svm_switch_vmcb(svm, &svm->nested.vmcb02);
-       nested_vmcb02_prepare_control(svm, vmcb12->save.rip);
+       nested_vmcb02_prepare_control(svm, vmcb12->save.rip, vmcb12->save.cs.base);
        nested_vmcb02_prepare_save(svm, vmcb12);
 
        ret = nested_svm_load_cr3(&svm->vcpu, svm->nested.save.cr3,
@@ -1663,7 +1664,7 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu,
        nested_copy_vmcb_control_to_cache(svm, ctl);
 
        svm_switch_vmcb(svm, &svm->nested.vmcb02);
-       nested_vmcb02_prepare_control(svm, svm->vmcb->save.rip);
+       nested_vmcb02_prepare_control(svm, svm->vmcb->save.rip, svm->vmcb->save.cs.base);
 
        /*
         * While the nested guest CR3 is already checked and set by