diff options
author | 2018-04-27 12:15:10 +0000 | |
---|---|---|
committer | 2018-04-27 12:15:10 +0000 | |
commit | d326e819e1ac794eb806336d0461ec86ade07f89 (patch) | |
tree | 0810b1fa2d2c519fb878e1837f0d5cfaa9ae8a49 | |
parent | test with pledgepath(NULL,NULL) instead of pledge activating things (diff) | |
download | wireguard-openbsd-d326e819e1ac794eb806336d0461ec86ade07f89.tar.xz wireguard-openbsd-d326e819e1ac794eb806336d0461ec86ade07f89.zip |
vmd(8): implement vmd side of ELCR registers
ok guenther
-rw-r--r-- | usr.sbin/vmd/i8259.c | 106 | ||||
-rw-r--r-- | usr.sbin/vmd/i8259.h | 6 | ||||
-rw-r--r-- | usr.sbin/vmd/pci.c | 4 | ||||
-rw-r--r-- | usr.sbin/vmd/vm.c | 4 | ||||
-rw-r--r-- | usr.sbin/vmd/vmd.h | 4 |
5 files changed, 111 insertions, 13 deletions
diff --git a/usr.sbin/vmd/i8259.c b/usr.sbin/vmd/i8259.c index 594420560b2..0859bf69d76 100644 --- a/usr.sbin/vmd/i8259.c +++ b/usr.sbin/vmd/i8259.c @@ -1,4 +1,4 @@ -/* $OpenBSD: i8259.c,v 1.16 2017/11/29 22:08:40 mlarkin Exp $ */ +/* $OpenBSD: i8259.c,v 1.17 2018/04/27 12:15:10 mlarkin Exp $ */ /* * Copyright (c) 2016 Mike Larkin <mlarkin@openbsd.org> * @@ -48,6 +48,9 @@ struct i8259 { uint8_t asserted; }; +/* Edge Level Control Registers */ +uint8_t elcr[2]; + #define PIC_IRR 0 #define PIC_ISR 1 @@ -89,6 +92,9 @@ i8259_init(void) pics[MASTER].cur_icw = 1; pics[SLAVE].cur_icw = 1; + elcr[MASTER] = 0; + elcr[SLAVE] = 0; + if (pthread_mutex_init(&pic_mtx, NULL) != 0) fatalx("unable to create pic mutex"); } @@ -246,15 +252,21 @@ void i8259_deassert_irq(uint8_t irq) { mutex_lock(&pic_mtx); - if (irq <= 7) - CLR(pics[MASTER].irr, 1 << irq); - else { + if (irq <= 7) { + if (elcr[MASTER] & (1 << irq)) + CLR(pics[MASTER].irr, 1 << irq); + } else { irq -= 8; - CLR(pics[SLAVE].irr, 1 << irq); + if (elcr[SLAVE] & (1 << irq)) { + CLR(pics[SLAVE].irr, 1 << irq); - /* Deassert cascade IRQ on master if no IRQs on slave */ - if (pics[SLAVE].irr == 0) - CLR(pics[MASTER].irr, 1 << 2); + /* + * Deassert cascade IRQ on master if no IRQs on + * slave + */ + if (pics[SLAVE].irr == 0) + CLR(pics[MASTER].irr, 1 << 2); + } } mutex_unlock(&pic_mtx); } @@ -669,6 +681,72 @@ vcpu_exit_i8259(struct vm_run_params *vrp) return (0xFF); } +/* + * pic_set_elcr + * + * Sets edge or level triggered mode for the given IRQ. Used internally + * by the vmd PCI setup code. Guest VMs writing to ELCRx will do so via + * vcpu_exit_elcr. + * + * Parameters: + * irq: IRQ (0-15) to set + * val: 0 if edge triggered mode, 1 if level triggered mode + */ +void +pic_set_elcr(uint8_t irq, uint8_t val) +{ + if (irq > 15 || val > 1) + return; + + log_debug("%s: setting %s triggered mode for irq %d", __func__, + val ? "level" : "edge", irq); + + if (irq > 7) { + if (val) + elcr[SLAVE] |= (1 << (irq - 8)); + else + elcr[SLAVE] &= ~(1 << (irq - 8)); + } else { + if (val) + elcr[MASTER] |= (1 << irq); + else + elcr[MASTER] &= ~(1 << irq); + } +} + +/* + * vcpu_exit_elcr + * + * Handler for the ELCRx registers + * + * Parameters: + * vrp: VCPU run parameters (contains exit information) for this ELCR I/O + * + * Return value: + * Always 0xFF (PIC read/writes don't generate interrupts directly) + */ +uint8_t +vcpu_exit_elcr(struct vm_run_params *vrp) +{ + union vm_exit *vei = vrp->vrp_exit; + uint8_t elcr_reg = vei->vei.vei_port - ELCR0; + + if (elcr_reg > 1) { + log_debug("%s: invalid ELCR index %d", __func__, elcr_reg); + return (0xFF); + } + + if (vei->vei.vei_dir == VEI_DIR_OUT) { + log_debug("%s: ELCR[%d] set to 0x%x", __func__, elcr_reg, + (uint8_t)vei->vei.vei_data); + elcr[elcr_reg] = (uint8_t)vei->vei.vei_data; + } else { + set_return_data(vei, elcr[elcr_reg]); + } + + return (0xFF); +} + int i8259_dump(int fd) { @@ -677,6 +755,12 @@ i8259_dump(int fd) log_warnx("%s: error writing PIC to fd", __func__); return (-1); } + + log_debug("%s: sending ELCR", __func__); + if (atomicio(vwrite, fd, &elcr, sizeof(elcr)) != sizeof(elcr)) { + log_warnx("%s: error writing ELCR to fd", __func__); + return (-1); + } return (0); } @@ -689,6 +773,12 @@ i8259_restore(int fd) return (-1); } + log_debug("%s: restoring ELCR", __func__); + if (atomicio(read, fd, &elcr, sizeof(elcr)) != sizeof(elcr)) { + log_warnx("%s: error reading ELCR from fd", __func__); + return (-1); + } + if (pthread_mutex_init(&pic_mtx, NULL) != 0) fatalx("unable to create pic mutex"); diff --git a/usr.sbin/vmd/i8259.h b/usr.sbin/vmd/i8259.h index f8a3e10b510..ce8a22d5c57 100644 --- a/usr.sbin/vmd/i8259.h +++ b/usr.sbin/vmd/i8259.h @@ -1,4 +1,4 @@ -/* $OpenBSD: i8259.h,v 1.3 2017/05/08 09:08:40 reyk Exp $ */ +/* $OpenBSD: i8259.h,v 1.4 2018/04/27 12:15:10 mlarkin Exp $ */ /* * Copyright (c) 2016 Mike Larkin <mlarkin@openbsd.org> * @@ -68,3 +68,7 @@ uint16_t i8259_ack(void); uint8_t i8259_is_pending(void); int i8259_restore(int); int i8259_dump(int); + +/* ELCR functions */ +void pic_set_elcr(uint8_t, uint8_t); +uint8_t vcpu_exit_elcr(struct vm_run_params *); diff --git a/usr.sbin/vmd/pci.c b/usr.sbin/vmd/pci.c index 8abd5c3c304..12f0afcbc81 100644 --- a/usr.sbin/vmd/pci.c +++ b/usr.sbin/vmd/pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pci.c,v 1.23 2018/02/15 05:35:36 mlarkin Exp $ */ +/* $OpenBSD: pci.c,v 1.24 2018/04/27 12:15:10 mlarkin Exp $ */ /* * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org> @@ -28,6 +28,7 @@ #include "vmd.h" #include "pci.h" #include "vmm.h" +#include "i8259.h" #include "atomicio.h" struct pci pci; @@ -193,6 +194,7 @@ pci_add_device(uint8_t *id, uint16_t vid, uint16_t pid, uint8_t class, pci.pci_next_pic_irq++; dprintf("assigned irq %d to pci dev %d", pci.pci_devices[*id].pd_irq, *id); + pic_set_elcr(pci.pci_devices[*id].pd_irq, 1); } pci.pci_dev_ct ++; diff --git a/usr.sbin/vmd/vm.c b/usr.sbin/vmd/vm.c index 18327eb3cdb..a240623752f 100644 --- a/usr.sbin/vmd/vm.c +++ b/usr.sbin/vmd/vm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm.c,v 1.32 2018/04/26 17:10:10 mlarkin Exp $ */ +/* $OpenBSD: vm.c,v 1.33 2018/04/27 12:15:10 mlarkin Exp $ */ /* * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org> @@ -935,6 +935,8 @@ init_emulated_hw(struct vmop_create_params *vmc, int child_cdrom, ioports_map[IO_ICU1 + 1] = vcpu_exit_i8259; ioports_map[IO_ICU2] = vcpu_exit_i8259; ioports_map[IO_ICU2 + 1] = vcpu_exit_i8259; + ioports_map[ELCR0] = vcpu_exit_i8259; + ioports_map[ELCR1] = vcpu_exit_i8259; /* Init ns8250 UART */ ns8250_init(con_fd, vcp->vcp_id); diff --git a/usr.sbin/vmd/vmd.h b/usr.sbin/vmd/vmd.h index 1b9a18322fb..d0260c35929 100644 --- a/usr.sbin/vmd/vmd.h +++ b/usr.sbin/vmd/vmd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmd.h,v 1.67 2018/01/03 05:39:56 ccardenas Exp $ */ +/* $OpenBSD: vmd.h,v 1.68 2018/04/27 12:15:10 mlarkin Exp $ */ /* * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org> @@ -171,7 +171,7 @@ struct vm_dump_header { #define VM_DUMP_SIGNATURE VMM_HV_SIGNATURE uint8_t vmh_pad[3]; uint8_t vmh_version; -#define VM_DUMP_VERSION 2 +#define VM_DUMP_VERSION 3 struct vm_dump_header_cpuid vmh_cpuids[VM_DUMP_HEADER_CPUID_COUNT]; } __packed; |