From 02ee787fcd78d11b22dcab625f1f53fd122b6cd9 Mon Sep 17 00:00:00 2001 From: mlarkin Date: Thu, 12 Jul 2018 10:15:44 +0000 Subject: [PATCH] vmm(8)/vmm(4): send a copy of the guest register state to vmd on exit, avoiding multiple readregs ioctls back to vmm in case register content is needed subsequently. ok phessler --- sys/arch/amd64/amd64/vmm.c | 15 +++++++++++---- sys/arch/amd64/include/vmmvar.h | 31 ++++++++++++++++++------------- usr.sbin/vmd/i8253.c | 6 +++--- usr.sbin/vmd/i8259.c | 10 +++++----- usr.sbin/vmd/mc146818.c | 4 ++-- usr.sbin/vmd/ns8250.c | 20 ++++++++++---------- usr.sbin/vmd/ns8250.h | 18 +++++++++--------- usr.sbin/vmd/pci.c | 8 ++++---- usr.sbin/vmd/vm.c | 12 ++++++------ usr.sbin/vmd/vmm.h | 4 ++-- 10 files changed, 70 insertions(+), 58 deletions(-) diff --git a/sys/arch/amd64/amd64/vmm.c b/sys/arch/amd64/amd64/vmm.c index 1b67245908e..b9052f92a81 100644 --- a/sys/arch/amd64/amd64/vmm.c +++ b/sys/arch/amd64/amd64/vmm.c @@ -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 * @@ -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(); diff --git a/sys/arch/amd64/include/vmmvar.h b/sys/arch/amd64/include/vmmvar.h index 033bb6e21e8..0bbe2aef46d 100644 --- a/sys/arch/amd64/include/vmmvar.h +++ b/sys/arch/amd64/include/vmmvar.h @@ -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 * @@ -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; diff --git a/usr.sbin/vmd/i8253.c b/usr.sbin/vmd/i8253.c index 14c10f31bd7..cf2dfd2d744 100644 --- a/usr.sbin/vmd/i8253.c +++ b/usr.sbin/vmd/i8253.c @@ -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 * @@ -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); diff --git a/usr.sbin/vmd/i8259.c b/usr.sbin/vmd/i8259.c index 1922e9bf827..deb731422c9 100644 --- a/usr.sbin/vmd/i8259.c +++ b/usr.sbin/vmd/i8259.c @@ -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 * @@ -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) { diff --git a/usr.sbin/vmd/mc146818.c b/usr.sbin/vmd/mc146818.c index 4392af5be39..014232c7aab 100644 --- a/usr.sbin/vmd/mc146818.c +++ b/usr.sbin/vmd/mc146818.c @@ -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 * @@ -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; diff --git a/usr.sbin/vmd/ns8250.c b/usr.sbin/vmd/ns8250.c index 2348422d12e..74e86a92954 100644 --- a/usr.sbin/vmd/ns8250.c +++ b/usr.sbin/vmd/ns8250.c @@ -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 * @@ -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); diff --git a/usr.sbin/vmd/ns8250.h b/usr.sbin/vmd/ns8250.h index 6c861107e67..0edeeb95a39 100644 --- a/usr.sbin/vmd/ns8250.h +++ b/usr.sbin/vmd/ns8250.h @@ -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 * @@ -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); diff --git a/usr.sbin/vmd/pci.c b/usr.sbin/vmd/pci.c index 6395c981a2e..ef7053e9594 100644 --- a/usr.sbin/vmd/pci.c +++ b/usr.sbin/vmd/pci.c @@ -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 @@ -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; diff --git a/usr.sbin/vmd/vm.c b/usr.sbin/vmd/vm.c index 2f57d769ae9..67252e5cf89 100644 --- a/usr.sbin/vmd/vm.c +++ b/usr.sbin/vmd/vm.c @@ -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 @@ -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: diff --git a/usr.sbin/vmd/vmm.h b/usr.sbin/vmd/vmm.h index 084554fc87c..214d41d01ea 100644 --- a/usr.sbin/vmd/vmm.h +++ b/usr.sbin/vmd/vmm.h @@ -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 *); -- 2.20.1