tech@,

Another vmm/vmd update: fix `vmctl receive` on Intel hosts by adding
another fault enum value to disambiguate fault reasons.

It's expected that the guest will trigger nested page faults after being
received by vmd. When you connect to the vm using `vmctl console` and
interact with the guest, it generates both a page fault and interrupt.

This combo is special because while the page fault will be handled by
vmm via uvm_fault(9), it will still exit to userland/vmd to handle the
interrupt.

vmd always checks the vm-exit reason after the return from vmm before
looping around and servicing interrupts before re-entering vmm. vmd has
a single userland handler for nested page faults for when we have a
protection fault. In this case, it reboots the vm. :-(

Since the enum we used for the fault type flag has only one value, vmm
isn't able to properly convey the type of nested fault. In this case, I
chose to add a "VEE_FAULT_HANDLED" value to indicate the fault has
already been handled by vmm and no userland assist is needed. (And
HANDLED is the same num of characters of PROTECT.)

This prevents the ambiguity and vm happily skips rebooting the vm.

It's possible this reboot could occur at any point in a vm's lifetime,
though I think the probability is low, so this is worth fixing
regardless.

ok?

-dv


Index: sys/arch/amd64/amd64/vmm.c
===================================================================
RCS file: /opt/cvs/src/sys/arch/amd64/amd64/vmm.c,v
retrieving revision 1.308
diff -u -p -r1.308 vmm.c
--- sys/arch/amd64/amd64/vmm.c  4 May 2022 02:24:26 -0000       1.308
+++ sys/arch/amd64/amd64/vmm.c  9 May 2022 13:45:02 -0000
@@ -5732,14 +5732,16 @@ vmx_fault_page(struct vcpu *vcpu, paddr_
        int fault_type, ret;

        fault_type = vmx_get_guest_faulttype();
-       if (fault_type == -1) {
+       switch (fault_type) {
+       case -1:
                printf("%s: invalid fault type\n", __func__);
                return (EINVAL);
-       }
-
-       if (fault_type == VM_FAULT_PROTECT) {
+       case VM_FAULT_PROTECT:
                vcpu->vc_exit.vee.vee_fault_type = VEE_FAULT_PROTECT;
                return (EAGAIN);
+       default:
+               vcpu->vc_exit.vee.vee_fault_type = VEE_FAULT_HANDLED;
+               break;
        }

        /* We may sleep during uvm_fault(9), so reload VMCS. */
Index: sys/arch/amd64/include/vmmvar.h
===================================================================
RCS file: /opt/cvs/src/sys/arch/amd64/include/vmmvar.h,v
retrieving revision 1.75
diff -u -p -r1.75 vmmvar.h
--- sys/arch/amd64/include/vmmvar.h     3 May 2022 21:39:19 -0000       1.75
+++ sys/arch/amd64/include/vmmvar.h     9 May 2022 13:38:18 -0000
@@ -324,7 +324,8 @@ enum {
 };

 enum {
-       VEE_FAULT_PROTECT
+       VEE_FAULT_HANDLED,
+       VEE_FAULT_PROTECT,
 };

 enum {

Reply via email to