vmm(8)/vmm(4): send a copy of the guest register state to vmd on exit,
authormlarkin <mlarkin@openbsd.org>
Thu, 12 Jul 2018 10:15:44 +0000 (10:15 +0000)
committermlarkin <mlarkin@openbsd.org>
Thu, 12 Jul 2018 10:15:44 +0000 (10:15 +0000)
avoiding multiple readregs ioctls back to vmm in case register content
is needed subsequently.

ok phessler

sys/arch/amd64/amd64/vmm.c
sys/arch/amd64/include/vmmvar.h
usr.sbin/vmd/i8253.c
usr.sbin/vmd/i8259.c
usr.sbin/vmd/mc146818.c
usr.sbin/vmd/ns8250.c
usr.sbin/vmd/ns8250.h
usr.sbin/vmd/pci.c
usr.sbin/vmd/vm.c
usr.sbin/vmd/vmm.h

index 1b67245..b9052f9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vmm.c,v 1.214 2018/07/11 18:04:18 nayden Exp $        */
+/*     $OpenBSD: vmm.c,v 1.215 2018/07/12 10:15:44 mlarkin Exp $       */
 /*
  * Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org>
  *
@@ -3740,7 +3740,7 @@ vm_run(struct vm_run_params *vrp)
         */
        if (vrp->vrp_continue) {
                if (copyin(vrp->vrp_exit, &vcpu->vc_exit,
-                   sizeof(union vm_exit)) == EFAULT) {
+                   sizeof(struct vm_exit)) == EFAULT) {
                        return (EFAULT);
                }
        }
@@ -3773,7 +3773,7 @@ vm_run(struct vm_run_params *vrp)
                vcpu->vc_state = VCPU_STATE_STOPPED;
 
                if (copyout(&vcpu->vc_exit, vrp->vrp_exit,
-                   sizeof(union vm_exit)) == EFAULT) {
+                   sizeof(struct vm_exit)) == EFAULT) {
                        ret = EFAULT;
                } else
                        ret = 0;
@@ -4272,6 +4272,9 @@ vcpu_run_vmx(struct vcpu *vcpu, struct vm_run_params *vrp)
                }
        }
 
+       /* Copy the VCPU register state to the exit structure */
+       if (vcpu_readregs_vmx(vcpu, VM_RWREGS_ALL, &vcpu->vc_exit.vrs))
+               ret = EINVAL;
        /*
         * We are heading back to userspace (vmd), either because we need help
         * handling an exit, a guest interrupt is pending, or we failed in some
@@ -4285,6 +4288,7 @@ vcpu_run_vmx(struct vcpu *vcpu, struct vm_run_params *vrp)
        } else
                ret = EINVAL;
 
+
 #ifdef VMM_DEBUG
        KERNEL_ASSERT_LOCKED();
 #endif /* VMM_DEBUG */
@@ -6398,8 +6402,11 @@ vcpu_run_svm(struct vcpu *vcpu, struct vm_run_params *vrp)
        /*
         * We are heading back to userspace (vmd), either because we need help
         * handling an exit, a guest interrupt is pending, or we failed in some
-        * way to enter the guest.
+        * way to enter the guest. Copy the guest registers to the exit struct
+        * and return to vmd.
         */
+       if (vcpu_readregs_svm(vcpu, VM_RWREGS_ALL, &vcpu->vc_exit.vrs))
+               ret = EINVAL;
 
 #ifdef VMM_DEBUG
        KERNEL_ASSERT_LOCKED();
index 033bb6e..0bbe2ae 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vmmvar.h,v 1.55 2018/07/11 13:19:42 mlarkin Exp $     */
+/*     $OpenBSD: vmmvar.h,v 1.56 2018/07/12 10:15:44 mlarkin Exp $     */
 /*
  * Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org>
  *
@@ -351,16 +351,6 @@ struct vm_exit_inout {
        uint32_t                vei_data;       /* data */
 };
 
-/*
- * union vm_exit
- *
- * Contains VM exit information communicated to vmd(8). This information is
- * gathered by vmm(4) from the CPU on each exit that requires help from vmd.
- */
-union vm_exit {
-       struct vm_exit_inout    vei;            /* IN/OUT exit */
-};
-
 /*
  * struct vcpu_segment_info
  *
@@ -440,6 +430,21 @@ struct vm_mem_range {
        size_t  vmr_size;
 };
 
+/*
+ * struct vm_exit
+ *
+ * Contains VM exit information communicated to vmd(8). This information is
+ * gathered by vmm(4) from the CPU on each exit that requires help from vmd.
+ */
+struct vm_exit {
+       union {
+               struct vm_exit_inout    vei;            /* IN/OUT exit */
+       };
+
+       struct vcpu_reg_state           vrs;
+};
+
+
 struct vm_create_params {
        /* Input parameters to VMM_IOC_CREATE */
        size_t                  vcp_nmemranges;
@@ -465,7 +470,7 @@ struct vm_run_params {
        uint16_t        vrp_irq;                /* IRQ to inject */
 
        /* Input/output parameter to VMM_IOC_RUN */
-       union vm_exit   *vrp_exit;              /* updated exit data */
+       struct vm_exit  *vrp_exit;              /* updated exit data */
 
        /* Output parameter from VMM_IOC_RUN */
        uint16_t        vrp_exit_reason;        /* exit reason */
@@ -845,7 +850,7 @@ struct vcpu {
        uint8_t vc_virt_mode;
 
        struct cpu_info *vc_last_pcpu;
-       union vm_exit vc_exit;
+       struct vm_exit vc_exit;
 
        uint16_t vc_intr;
        uint8_t vc_irqready;
index 14c10f3..cf2dfd2 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: i8253.c,v 1.27 2018/07/09 16:11:37 mlarkin Exp $ */
+/* $OpenBSD: i8253.c,v 1.28 2018/07/12 10:15:44 mlarkin Exp $ */
 /*
  * Copyright (c) 2016 Mike Larkin <mlarkin@openbsd.org>
  *
@@ -137,7 +137,7 @@ i8253_do_readback(uint32_t data)
 uint8_t
 vcpu_exit_i8253_misc(struct vm_run_params *vrp)
 {
-       union vm_exit *vei = vrp->vrp_exit;
+       struct vm_exit *vei = vrp->vrp_exit;
        uint16_t cur;
        uint64_t ns, ticks;
        struct timespec now, delta;
@@ -197,7 +197,7 @@ vcpu_exit_i8253(struct vm_run_params *vrp)
        uint8_t sel, rw, data;
        uint64_t ns, ticks;
        struct timespec now, delta;
-       union vm_exit *vei = vrp->vrp_exit;
+       struct vm_exit *vei = vrp->vrp_exit;
 
        get_input_data(vei, &out_data);
 
index 1922e9b..deb7314 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: i8259.c,v 1.18 2018/06/19 17:12:34 reyk Exp $ */
+/* $OpenBSD: i8259.c,v 1.19 2018/07/12 10:15:44 mlarkin Exp $ */
 /*
  * Copyright (c) 2016 Mike Larkin <mlarkin@openbsd.org>
  *
@@ -586,7 +586,7 @@ i8259_read_cmdreg(uint8_t n)
  *  vei: vm exit info for this I/O
  */
 static void
-i8259_io_write(union vm_exit *vei)
+i8259_io_write(struct vm_exit *vei)
 {
        uint16_t port = vei->vei.vei_port;
        uint32_t data;
@@ -627,7 +627,7 @@ i8259_io_write(union vm_exit *vei)
  *  data that was read, based on the port information in 'vei'
  */
 static uint8_t
-i8259_io_read(union vm_exit *vei)
+i8259_io_read(struct vm_exit *vei)
 {
        uint16_t port = vei->vei.vei_port;
        uint8_t n = 0;
@@ -670,7 +670,7 @@ i8259_io_read(union vm_exit *vei)
 uint8_t
 vcpu_exit_i8259(struct vm_run_params *vrp)
 {
-       union vm_exit *vei = vrp->vrp_exit;
+       struct vm_exit *vei = vrp->vrp_exit;
 
        if (vei->vei.vei_dir == VEI_DIR_OUT) {
                i8259_io_write(vei);
@@ -728,7 +728,7 @@ pic_set_elcr(uint8_t irq, uint8_t val)
 uint8_t
 vcpu_exit_elcr(struct vm_run_params *vrp)
 {
-       union vm_exit *vei = vrp->vrp_exit;
+       struct vm_exit *vei = vrp->vrp_exit;
        uint8_t elcr_reg = vei->vei.vei_port - ELCR0;
 
        if (elcr_reg > 1) {
index 4392af5..014232c 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: mc146818.c,v 1.17 2018/07/09 16:11:37 mlarkin Exp $ */
+/* $OpenBSD: mc146818.c,v 1.18 2018/07/12 10:15:44 mlarkin Exp $ */
 /*
  * Copyright (c) 2016 Mike Larkin <mlarkin@openbsd.org>
  *
@@ -259,7 +259,7 @@ rtc_update_regb(uint32_t data)
 uint8_t
 vcpu_exit_mc146818(struct vm_run_params *vrp)
 {
-       union vm_exit *vei = vrp->vrp_exit;
+       struct vm_exit *vei = vrp->vrp_exit;
        uint16_t port = vei->vei.vei_port;
        uint8_t dir = vei->vei.vei_dir;
        uint32_t data = 0;
index 2348422..74e86a9 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ns8250.c,v 1.16 2018/07/09 16:11:37 mlarkin Exp $ */
+/* $OpenBSD: ns8250.c,v 1.17 2018/07/12 10:15:44 mlarkin Exp $ */
 /*
  * Copyright (c) 2016 Mike Larkin <mlarkin@openbsd.org>
  *
@@ -216,7 +216,7 @@ com_rcv(struct ns8250_dev *com, uint32_t vm_id, uint32_t vcpu_id)
  *  interrupt to inject, or 0xFF if nothing to inject
  */
 uint8_t
-vcpu_process_com_data(union vm_exit *vei, uint32_t vm_id, uint32_t vcpu_id)
+vcpu_process_com_data(struct vm_exit *vei, uint32_t vm_id, uint32_t vcpu_id)
 {
        /*
         * vei_dir == VEI_DIR_OUT : out instruction
@@ -299,7 +299,7 @@ vcpu_process_com_data(union vm_exit *vei, uint32_t vm_id, uint32_t vcpu_id)
  *      instruction being performed
  */
 void
-vcpu_process_com_lcr(union vm_exit *vei)
+vcpu_process_com_lcr(struct vm_exit *vei)
 {
        uint8_t data = (uint8_t)vei->vei.vei_data;
        uint16_t divisor;
@@ -352,7 +352,7 @@ vcpu_process_com_lcr(union vm_exit *vei)
  *      instruction being performed
  */
 void
-vcpu_process_com_iir(union vm_exit *vei)
+vcpu_process_com_iir(struct vm_exit *vei)
 {
        /*
         * vei_dir == VEI_DIR_OUT : out instruction
@@ -391,7 +391,7 @@ vcpu_process_com_iir(union vm_exit *vei)
  *      instruction being performed
  */
 void
-vcpu_process_com_mcr(union vm_exit *vei)
+vcpu_process_com_mcr(struct vm_exit *vei)
 {
        /*
         * vei_dir == VEI_DIR_OUT : out instruction
@@ -420,7 +420,7 @@ vcpu_process_com_mcr(union vm_exit *vei)
  *      instruction being performed
  */
 void
-vcpu_process_com_lsr(union vm_exit *vei)
+vcpu_process_com_lsr(struct vm_exit *vei)
 {
        /*
         * vei_dir == VEI_DIR_OUT : out instruction
@@ -452,7 +452,7 @@ vcpu_process_com_lsr(union vm_exit *vei)
  *      instruction being performed
  */
 void
-vcpu_process_com_msr(union vm_exit *vei)
+vcpu_process_com_msr(struct vm_exit *vei)
 {
        /*
         * vei_dir == VEI_DIR_OUT : out instruction
@@ -484,7 +484,7 @@ vcpu_process_com_msr(union vm_exit *vei)
  *      instruction being performed
  */
 void
-vcpu_process_com_scr(union vm_exit *vei)
+vcpu_process_com_scr(struct vm_exit *vei)
 {
        /*
         * vei_dir == VEI_DIR_OUT : out instruction
@@ -514,7 +514,7 @@ vcpu_process_com_scr(union vm_exit *vei)
  *      instruction being performed
  */
 void
-vcpu_process_com_ier(union vm_exit *vei)
+vcpu_process_com_ier(struct vm_exit *vei)
 {
        /*
         * vei_dir == VEI_DIR_OUT : out instruction
@@ -560,7 +560,7 @@ uint8_t
 vcpu_exit_com(struct vm_run_params *vrp)
 {
        uint8_t intr = 0xFF;
-       union vm_exit *vei = vrp->vrp_exit;
+       struct vm_exit *vei = vrp->vrp_exit;
 
        mutex_lock(&com1_dev.mutex);
 
index 6c86110..0edeeb9 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ns8250.h,v 1.5 2017/06/07 14:53:28 mlarkin Exp $ */
+/* $OpenBSD: ns8250.h,v 1.6 2018/07/12 10:15:44 mlarkin Exp $ */
 /*
  * Copyright (c) 2016 Mike Larkin <mlarkin@openbsd.org>
  *
@@ -60,13 +60,13 @@ struct ns8250_dev {
 
 void ns8250_init(int, uint32_t);
 uint8_t vcpu_exit_com(struct vm_run_params *);
-uint8_t vcpu_process_com_data(union vm_exit *, uint32_t, uint32_t);
-void vcpu_process_com_lcr(union vm_exit *);
-void vcpu_process_com_lsr(union vm_exit *);
-void vcpu_process_com_ier(union vm_exit *);
-void vcpu_process_com_mcr(union vm_exit *);
-void vcpu_process_com_iir(union vm_exit *);
-void vcpu_process_com_msr(union vm_exit *);
-void vcpu_process_com_scr(union vm_exit *);
+uint8_t vcpu_process_com_data(struct vm_exit *, uint32_t, uint32_t);
+void vcpu_process_com_lcr(struct vm_exit *);
+void vcpu_process_com_lsr(struct vm_exit *);
+void vcpu_process_com_ier(struct vm_exit *);
+void vcpu_process_com_mcr(struct vm_exit *);
+void vcpu_process_com_iir(struct vm_exit *);
+void vcpu_process_com_msr(struct vm_exit *);
+void vcpu_process_com_scr(struct vm_exit *);
 int ns8250_dump(int);
 int ns8250_restore(int, int, uint32_t);
index 6395c98..ef7053e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pci.c,v 1.26 2018/07/10 20:43:15 reyk Exp $   */
+/*     $OpenBSD: pci.c,v 1.27 2018/07/12 10:15:44 mlarkin Exp $        */
 
 /*
  * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -228,7 +228,7 @@ pci_init(void)
 void
 pci_handle_address_reg(struct vm_run_params *vrp)
 {
-       union vm_exit *vei = vrp->vrp_exit;
+       struct vm_exit *vei = vrp->vrp_exit;
 
        /*
         * vei_dir == VEI_DIR_OUT : out instruction
@@ -253,7 +253,7 @@ pci_handle_io(struct vm_run_params *vrp)
        int i, j, k, l;
        uint16_t reg, b_hi, b_lo;
        pci_iobar_fn_t fn;
-       union vm_exit *vei = vrp->vrp_exit;
+       struct vm_exit *vei = vrp->vrp_exit;
        uint8_t intr, dir;
 
        k = -1;
@@ -303,7 +303,7 @@ pci_handle_io(struct vm_run_params *vrp)
 void
 pci_handle_data_reg(struct vm_run_params *vrp)
 {
-       union vm_exit *vei = vrp->vrp_exit;
+       struct vm_exit *vei = vrp->vrp_exit;
        uint8_t b, d, f, o, baridx, ofs, sz;
        int ret;
        pci_cs_fn_t csfunc;
index 2f57d76..67252e5 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vm.c,v 1.36 2018/07/10 08:40:20 mlarkin Exp $ */
+/*     $OpenBSD: vm.c,v 1.37 2018/07/12 10:15:44 mlarkin Exp $ */
 
 /*
  * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -1108,7 +1108,7 @@ run_vm(int child_cdrom, int *child_disks, int *child_taps,
                        /* caller will exit, so skip freeing */
                        return (ENOMEM);
                }
-               vrp[i]->vrp_exit = malloc(sizeof(union vm_exit));
+               vrp[i]->vrp_exit = malloc(sizeof(struct vm_exit));
                if (vrp[i]->vrp_exit == NULL) {
                        log_warn("%s: memory allocation error - "
                            "exiting.", __progname);
@@ -1394,7 +1394,7 @@ vcpu_pic_intr(uint32_t vm_id, uint32_t vcpu_id, uint8_t intr)
 uint8_t
 vcpu_exit_pci(struct vm_run_params *vrp)
 {
-       union vm_exit *vei = vrp->vrp_exit;
+       struct vm_exit *vei = vrp->vrp_exit;
        uint8_t intr;
 
        intr = 0xFF;
@@ -1433,7 +1433,7 @@ vcpu_exit_pci(struct vm_run_params *vrp)
 void
 vcpu_exit_inout(struct vm_run_params *vrp)
 {
-       union vm_exit *vei = vrp->vrp_exit;
+       struct vm_exit *vei = vrp->vrp_exit;
        uint8_t intr = 0xFF;
 
        if (ioports_map[vei->vei.vei_port] != NULL)
@@ -1873,7 +1873,7 @@ mutex_unlock(pthread_mutex_t *m)
  *  data: return data
  */
 void
-set_return_data(union vm_exit *vei, uint32_t data)
+set_return_data(struct vm_exit *vei, uint32_t data)
 {
        switch (vei->vei.vei_size) {
        case 1:
@@ -1903,7 +1903,7 @@ set_return_data(union vm_exit *vei, uint32_t data)
  *  data: location to store the result
  */
 void
-get_input_data(union vm_exit *vei, uint32_t *data)
+get_input_data(struct vm_exit *vei, uint32_t *data)
 {
        switch (vei->vei.vei_size) {
        case 1:
index 084554f..214d41d 100644 (file)
@@ -20,5 +20,5 @@ typedef uint8_t (*io_fn_t)(struct vm_run_params *);
 
 void vcpu_assert_pic_irq(uint32_t, uint32_t, int);
 void vcpu_deassert_pic_irq(uint32_t, uint32_t, int);
-void set_return_data(union vm_exit *, uint32_t);
-void get_input_data(union vm_exit *, uint32_t *);
+void set_return_data(struct vm_exit *, uint32_t);
+void get_input_data(struct vm_exit *, uint32_t *);