vmm(4): fix flawed physical cpu tracking logic in svm_run_vcpu
authordv <dv@openbsd.org>
Tue, 11 May 2021 22:04:10 +0000 (22:04 +0000)
committerdv <dv@openbsd.org>
Tue, 11 May 2021 22:04:10 +0000 (22:04 +0000)
Replace the overly complicated logic used to track which CPU we are on
in svm_run_vcpu. This fixes an issue where ltr causes a #GP on exit in
certain conditions due to referencing the wrong GDT.

This was primarily witnessed with NixOS guests that performed a heavy
amount of disk io.

Reported by Josh Rickmar. Tested by Josh & abieber@. OK mlarkin@.

sys/arch/amd64/amd64/vmm.c

index ebf2bce..b1c49b0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vmm.c,v 1.280 2021/04/06 00:19:58 dv Exp $    */
+/*     $OpenBSD: vmm.c,v 1.281 2021/05/11 22:04:10 dv Exp $    */
 /*
  * Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org>
  *
@@ -6970,15 +6970,14 @@ vmm_handle_cpuid(struct vcpu *vcpu)
 int
 vcpu_run_svm(struct vcpu *vcpu, struct vm_run_params *vrp)
 {
-       int ret = 0, resume;
+       int ret = 0;
        struct region_descriptor gdt;
-       struct cpu_info *ci;
+       struct cpu_info *ci = NULL;
        uint64_t exit_reason;
        struct schedstate_percpu *spc;
        uint16_t irq;
        struct vmcb *vmcb = (struct vmcb *)vcpu->vc_control_va;
 
-       resume = 0;
        irq = vrp->vrp_irq;
 
        /*
@@ -7000,7 +6999,7 @@ vcpu_run_svm(struct vcpu *vcpu, struct vm_run_params *vrp)
 
        while (ret == 0) {
                vmm_update_pvclock(vcpu);
-               if (!resume) {
+               if (ci != curcpu()) {
                        /*
                         * We are launching for the first time, or we are
                         * resuming from a different pcpu, so we need to
@@ -7106,8 +7105,6 @@ vcpu_run_svm(struct vcpu *vcpu, struct vm_run_params *vrp)
 
                /* If we exited successfully ... */
                if (ret == 0) {
-                       resume = 1;
-
                        vcpu->vc_gueststate.vg_rflags = vmcb->v_rflags;
 
                        /*
@@ -7149,7 +7146,6 @@ vcpu_run_svm(struct vcpu *vcpu, struct vm_run_params *vrp)
                        /* Check if we should yield - don't hog the cpu */
                        spc = &ci->ci_schedstate;
                        if (spc->spc_schedflags & SPCF_SHOULDYIELD) {
-                               resume = 0;
                                yield();
                        }
                }