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 {