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;

Reply via email to