summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormlarkin <mlarkin@openbsd.org>2018-04-27 12:15:10 +0000
committermlarkin <mlarkin@openbsd.org>2018-04-27 12:15:10 +0000
commitd326e819e1ac794eb806336d0461ec86ade07f89 (patch)
tree0810b1fa2d2c519fb878e1837f0d5cfaa9ae8a49
parenttest with pledgepath(NULL,NULL) instead of pledge activating things (diff)
downloadwireguard-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.c106
-rw-r--r--usr.sbin/vmd/i8259.h6
-rw-r--r--usr.sbin/vmd/pci.c4
-rw-r--r--usr.sbin/vmd/vm.c4
-rw-r--r--usr.sbin/vmd/vmd.h4
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;