This diff adds the ability to inject exceptions into the guest. It is needed for a variety of things coming soon (XO kernel .text, #UD on unsupported instructions, routing RDRAND/RDSEED to arc4random, etc).
ok? Index: amd64/vmm.c =================================================================== RCS file: /cvs/src/sys/arch/amd64/amd64/vmm.c,v retrieving revision 1.151 diff -u -p -a -u -r1.151 vmm.c --- amd64/vmm.c 30 May 2017 19:31:28 -0000 1.151 +++ amd64/vmm.c 30 May 2017 19:57:16 -0000 @@ -3681,6 +3681,29 @@ vcpu_run_vmx(struct vcpu *vcpu, struct v } } + /* Inject event if present */ + if (vcpu->vc_event != 0) { + eii = (vcpu->vc_event & 0xFF); + eii |= (1ULL << 31); /* Valid */ + eii |= (1ULL << 11); /* Send error code */ + eii |= (3ULL << 8); /* Hardware Exception */ + if (vmwrite(VMCS_ENTRY_INTERRUPTION_INFO, eii)) { + printf("%s: can't vector event to guest\n", + __func__); + ret = EINVAL; + break; + } + + if (vmwrite(VMCS_ENTRY_EXCEPTION_ERROR_CODE, 0)) { + printf("%s: can't write error code to guest\n", + __func__); + ret = EINVAL; + break; + } + + vcpu->vc_event = 0; + } + if (vcpu->vc_vmx_vpid_enabled) { /* Invalidate old TLB mappings */ vid.vid_vpid = vcpu->vc_parent->vm_id; @@ -5490,6 +5513,14 @@ vcpu_run_svm(struct vcpu *vcpu, struct v vmcb->v_vmcb_clean_bits &= ~(1 << 3); vmcb->v_irq = 0; vmcb->v_intr_vector = 0; + } + + /* Inject event if present */ + if (vcpu->vc_event != 0) { + vmcb->v_eventinj = (vcpu->vc_event) | (1 << 31); + vmcb->v_eventinj |= (1ULL << 1); /* Send error code */ + vmcb->v_eventinj |= (3ULL << 8); /* Hardware Exception */ + vcpu->vc_event = 0; } /* Start / resume the VCPU */ Index: include/vmmvar.h =================================================================== RCS file: /cvs/src/sys/arch/amd64/include/vmmvar.h,v retrieving revision 1.40 diff -u -p -a -u -r1.40 vmmvar.h --- include/vmmvar.h 30 May 2017 17:49:47 -0000 1.40 +++ include/vmmvar.h 30 May 2017 19:57:16 -0000 @@ -721,6 +721,8 @@ struct vcpu { struct vcpu_gueststate vc_gueststate; + uint8_t vc_event; + /* VMX only */ uint64_t vc_vmx_basic; uint64_t vc_vmx_entry_ctls;