summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Mooney <pmooney@pfmooney.com>2020-07-08 17:49:55 +0000
committerPatrick Mooney <pmooney@oxide.computer>2020-07-15 04:47:00 +0000
commita517c69d55a640319d65033c3b1275bb8a9c56ab (patch)
treef4cabf46c617b82e0fd572a5a7d3773a9460cf7f
parenteb8e4816e886312ff129c1a9213ad86d0fe5ffb6 (diff)
downloadillumos-joyent-a517c69d55a640319d65033c3b1275bb8a9c56ab.tar.gz
12939 avoid packing and bitfields in bhyve VMCB
Reviewed by: Mike Zeller <mike.zeller@joyent.com> Reviewed by: Toomas Soome <tsoome@me.com> Reviewed by: Andy Fiddaman <andy@omniosce.org> Approved by: Dan McDonald <danmcd@joyent.com>
-rw-r--r--usr/src/uts/i86pc/io/vmm/amd/svm.c28
-rw-r--r--usr/src/uts/i86pc/io/vmm/amd/vmcb.h191
2 files changed, 135 insertions, 84 deletions
diff --git a/usr/src/uts/i86pc/io/vmm/amd/svm.c b/usr/src/uts/i86pc/io/vmm/amd/svm.c
index e2521fee3b..9d3c3a2477 100644
--- a/usr/src/uts/i86pc/io/vmm/amd/svm.c
+++ b/usr/src/uts/i86pc/io/vmm/amd/svm.c
@@ -27,6 +27,15 @@
*/
/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
* Copyright 2018 Joyent, Inc.
* Copyright 2020 Oxide Computer Company
*/
@@ -471,7 +480,7 @@ vmcb_init(struct svm_softc *sc, int vcpu, uint64_t iopm_base_pa,
ctrl->msrpm_base_pa = msrpm_base_pa;
/* Enable nested paging */
- ctrl->np_enable = 1;
+ ctrl->np_ctrl = NP_ENABLE;
ctrl->n_cr3 = np_pml4;
/*
@@ -537,10 +546,10 @@ vmcb_init(struct svm_softc *sc, int vcpu, uint64_t iopm_base_pa,
*
* This must be set for %rflag and %cr8 isolation of guest and host.
*/
- ctrl->v_intr_masking = 1;
+ ctrl->v_intr_ctrl |= V_INTR_MASKING;
/* Enable Last Branch Record aka LBR for debugging */
- ctrl->lbr_virt_en = 1;
+ ctrl->misc_ctrl |= LBR_VIRT_ENABLE;
state->dbgctl = BIT(0);
/* EFER_SVM must always be set when the guest is executing */
@@ -1036,16 +1045,17 @@ enable_intr_window_exiting(struct svm_softc *sc, int vcpu)
ctrl = svm_get_vmcb_ctrl(sc, vcpu);
- if (ctrl->v_irq && ctrl->v_intr_vector == 0) {
- KASSERT(ctrl->v_ign_tpr, ("%s: invalid v_ign_tpr", __func__));
+ if ((ctrl->v_irq & V_IRQ) != 0 && ctrl->v_intr_vector == 0) {
+ KASSERT(ctrl->v_intr_prio & V_IGN_TPR,
+ ("%s: invalid v_ign_tpr", __func__));
KASSERT(vintr_intercept_enabled(sc, vcpu),
("%s: vintr intercept should be enabled", __func__));
return;
}
VCPU_CTR0(sc->vm, vcpu, "Enable intr window exiting");
- ctrl->v_irq = 1;
- ctrl->v_ign_tpr = 1;
+ ctrl->v_irq |= V_IRQ;
+ ctrl->v_intr_prio |= V_IGN_TPR;
ctrl->v_intr_vector = 0;
svm_set_dirty(sc, vcpu, VMCB_CACHE_TPR);
svm_enable_intercept(sc, vcpu, VMCB_CTRL1_INTCPT, VMCB_INTCPT_VINTR);
@@ -1058,14 +1068,14 @@ disable_intr_window_exiting(struct svm_softc *sc, int vcpu)
ctrl = svm_get_vmcb_ctrl(sc, vcpu);
- if (!ctrl->v_irq && ctrl->v_intr_vector == 0) {
+ if ((ctrl->v_irq & V_IRQ) == 0 && ctrl->v_intr_vector == 0) {
KASSERT(!vintr_intercept_enabled(sc, vcpu),
("%s: vintr intercept should be disabled", __func__));
return;
}
VCPU_CTR0(sc->vm, vcpu, "Disable intr window exiting");
- ctrl->v_irq = 0;
+ ctrl->v_irq &= ~V_IRQ;
ctrl->v_intr_vector = 0;
svm_set_dirty(sc, vcpu, VMCB_CACHE_TPR);
svm_disable_intercept(sc, vcpu, VMCB_CTRL1_INTCPT, VMCB_INTCPT_VINTR);
diff --git a/usr/src/uts/i86pc/io/vmm/amd/vmcb.h b/usr/src/uts/i86pc/io/vmm/amd/vmcb.h
index ec7caa91f9..88f65df66a 100644
--- a/usr/src/uts/i86pc/io/vmm/amd/vmcb.h
+++ b/usr/src/uts/i86pc/io/vmm/amd/vmcb.h
@@ -28,6 +28,19 @@
* $FreeBSD$
*/
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * Copyright 2020 Oxide Computer Company
+ */
+
#ifndef _VMCB_H_
#define _VMCB_H_
@@ -215,13 +228,41 @@ struct vmcb_segment {
uint16_t attrib;
uint32_t limit;
uint64_t base;
-} __attribute__ ((__packed__));
+};
CTASSERT(sizeof(struct vmcb_segment) == 16);
/* Code segment descriptor attribute in 12 bit format as saved by VMCB. */
#define VMCB_CS_ATTRIB_L BIT(9) /* Long mode. */
#define VMCB_CS_ATTRIB_D BIT(10) /* OPerand size bit. */
+/* Fields for Virtual Interrupt Control (v_irq) */
+#define V_IRQ BIT(0) /* Offset 0x60 bit 8 (0x61 bit 0) */
+#define V_VGIF_VALUE BIT(1) /* Offset 0x60 bit 9 (0x61 bit 1) */
+
+/* Fields for Virtual Interrupt Control (v_intr_prio) */
+#define V_INTR_PRIO 0xf /* Offset 0x60 bits 16-19 (0x62 bits 0-3) */
+#define V_IGN_TPR BIT(4) /* Offset 0x60 bit 20 (0x62 bit 4) */
+
+/* Fields for Virtual Interrupt Control (v_intr_ctrl) */
+#define V_INTR_MASKING BIT(0) /* Offset 0x60 bit 24 (0x63 bit 0) */
+#define V_VGIF_ENABLE BIT(1) /* Offset 0x60 bit 25 (0x63 bit 1) */
+#define V_AVIC_ENABLE BIT(7) /* Offset 0x60 bit 31 (0x63 bit 7) */
+
+/* Fields in Interrupt Shadow, offset 0x68 */
+#define VIRTUAL_INTR_SHADOW BIT(0)
+#define GUEST_INTERRUPT_MASK BIT(1)
+
+/* Fields in Nested Paging, offset 0x90 */
+#define NP_ENABLE BIT(0) /* Enable nested paging */
+#define SEV_ENABLE BIT(1) /* Enable SEV */
+#define SEV_ES_ENABLE BIT(2) /* Enable SEV-ES */
+#define GUEST_MODE_EXEC_TRAP BIT(3) /* Guest mode execute trap */
+#define VIRT_TRANSPAR_ENCRYPT BIT(5) /* Virtual transparent encryption */
+
+/* Fields in Misc virt controls, offset 0xB8 */
+#define LBR_VIRT_ENABLE BIT(0) /* Enable LBR virtualization accel */
+#define VIRT_VMSAVE_VMLOAD BIT(1) /* Virtualized VMSAVE/VMLOAD */
+
/*
* The VMCB is divided into two areas - the first one contains various
* control bits including the intercept vector and the second one contains
@@ -230,99 +271,99 @@ CTASSERT(sizeof(struct vmcb_segment) == 16);
/* VMCB control area - padded up to 1024 bytes */
struct vmcb_ctrl {
- uint32_t intercept[5]; /* all intercepts */
- uint8_t pad1[0x28]; /* Offsets 0x14-0x3B are reserved. */
- uint16_t pause_filthresh; /* Offset 0x3C, PAUSE filter threshold */
- uint16_t pause_filcnt; /* Offset 0x3E, PAUSE filter count */
+ uint32_t intercept[5]; /* 0x00-0x13: all intercepts */
+ uint32_t _pad1[10]; /* 0x14-0x3B: Reserved. */
+ uint32_t pause_ctrl; /* 0x3C, PAUSE filter thresh/count */
uint64_t iopm_base_pa; /* 0x40: IOPM_BASE_PA */
uint64_t msrpm_base_pa; /* 0x48: MSRPM_BASE_PA */
uint64_t tsc_offset; /* 0x50: TSC_OFFSET */
uint32_t asid; /* 0x58: Guest ASID */
- uint8_t tlb_ctrl; /* 0x5C: TLB_CONTROL */
- uint8_t pad2[3]; /* 0x5D-0x5F: Reserved. */
- uint8_t v_tpr; /* 0x60: V_TPR, guest CR8 */
- uint8_t v_irq:1; /* Is virtual interrupt pending? */
- uint8_t :7; /* Padding */
- uint8_t v_intr_prio:4; /* 0x62: Priority for virtual interrupt. */
- uint8_t v_ign_tpr:1;
- uint8_t :3;
- uint8_t v_intr_masking:1; /* Guest and host sharing of RFLAGS. */
- uint8_t :7;
- uint8_t v_intr_vector; /* 0x64: Vector for virtual interrupt. */
- uint8_t pad3[3]; /* 0x65-0x67 Reserved. */
- uint64_t intr_shadow:1; /* 0x68: Interrupt shadow, section15.2.1 APM2 */
- uint64_t :63;
+ uint8_t tlb_ctrl; /* 0x5C: TLB_CONTROL */
+ uint8_t _pad2[3]; /* 0x5D-0x5F: Reserved. */
+ uint8_t v_tpr; /* 0x60: Virtual TPR */
+ uint8_t v_irq; /* 0x61: V_IRQ, V_GIF_VALUE + Reserved */
+ uint8_t v_intr_prio; /* 0x62: V_INTR_PRIO, V_IGN_TPR */
+ uint8_t v_intr_ctrl; /* 0x63: V_INTR_MASKING, vGIF and AVIC enable */
+ uint8_t v_intr_vector; /* 0x64: Virtual interrupt vector */
+ uint8_t _pad3[3]; /* 0x65-0x67: Reserved */
+ uint64_t intr_shadow; /* 0x68: Interrupt shadow (and more) */
uint64_t exitcode; /* 0x70, Exitcode */
uint64_t exitinfo1; /* 0x78, EXITINFO1 */
uint64_t exitinfo2; /* 0x80, EXITINFO2 */
uint64_t exitintinfo; /* 0x88, Interrupt exit value. */
- uint64_t np_enable:1; /* 0x90, Nested paging enable. */
- uint64_t :63;
- uint8_t pad4[0x10]; /* 0x98-0xA7 reserved. */
+ uint64_t np_ctrl; /* 0x90, Nested paging control. */
+ uint64_t _pad4[2]; /* 0x98-0xA7 reserved. */
uint64_t eventinj; /* 0xA8, Event injection. */
- uint64_t n_cr3; /* B0, Nested page table. */
- uint64_t lbr_virt_en:1; /* Enable LBR virtualization. */
- uint64_t :63;
+ uint64_t n_cr3; /* 0xB0, Nested page table. */
+ uint64_t misc_ctrl; /* 0xB8, Misc virt controls */
uint32_t vmcb_clean; /* 0xC0: VMCB clean bits for caching */
- uint32_t :32; /* 0xC4: Reserved */
+ uint32_t _pad5; /* 0xC4: Reserved */
uint64_t nrip; /* 0xC8: Guest next nRIP. */
- uint8_t inst_len; /* 0xD0: #NPF decode assist */
- uint8_t inst_bytes[15];
- uint8_t padd6[0x320];
-} __attribute__ ((__packed__));
+ uint8_t inst_len; /* 0xD0: #NPF decode assist */
+ uint8_t inst_bytes[15]; /* 0xD1-0xDF: guest instr bytes */
+ uint64_t avic_page_pa; /* 0xEO: AVIC backing page */
+ uint64_t _pad6; /* 0xE8-0xEF: Reserved */
+ uint64_t avic_log_tbl; /* 0xFO: AVIC logical table */
+ uint64_t avic_phys_tbl; /* 0xF8: AVIC physical page */
+ uint64_t _pad7; /* 0x100-0x107: Reserved */
+ uint64_t vmsa_pa; /* 0x108: VMSA pointer */
+ uint64_t _pad8[94]; /* 0x110-0x3FF: Reserved */
+};
CTASSERT(sizeof(struct vmcb_ctrl) == 1024);
+CTASSERT(offsetof(struct vmcb_ctrl, vmsa_pa) == 0x108);
struct vmcb_state {
- struct vmcb_segment es;
- struct vmcb_segment cs;
- struct vmcb_segment ss;
- struct vmcb_segment ds;
- struct vmcb_segment fs;
- struct vmcb_segment gs;
- struct vmcb_segment gdt;
- struct vmcb_segment ldt;
- struct vmcb_segment idt;
- struct vmcb_segment tr;
- uint8_t pad1[0x2b]; /* Reserved: 0xA0-0xCA */
- uint8_t cpl;
- uint8_t pad2[4];
- uint64_t efer;
- uint8_t pad3[0x70]; /* Reserved: 0xd8-0x147 */
- uint64_t cr4;
- uint64_t cr3; /* Guest CR3 */
- uint64_t cr0;
- uint64_t dr7;
- uint64_t dr6;
- uint64_t rflags;
- uint64_t rip;
- uint8_t pad4[0x58]; /* Reserved: 0x180-0x1D7 */
- uint64_t rsp;
- uint8_t pad5[0x18]; /* Reserved 0x1E0-0x1F7 */
- uint64_t rax;
- uint64_t star;
- uint64_t lstar;
- uint64_t cstar;
- uint64_t sfmask;
- uint64_t kernelgsbase;
- uint64_t sysenter_cs;
- uint64_t sysenter_esp;
- uint64_t sysenter_eip;
- uint64_t cr2;
- uint8_t pad6[0x20];
- uint64_t g_pat;
- uint64_t dbgctl;
- uint64_t br_from;
- uint64_t br_to;
- uint64_t int_from;
- uint64_t int_to;
- uint8_t pad7[0x968]; /* Reserved up to end of VMCB */
-} __attribute__ ((__packed__));
+ struct vmcb_segment es; /* 0x00: 32bit base */
+ struct vmcb_segment cs; /* 0x10: 32bit base */
+ struct vmcb_segment ss; /* 0x20: 32bit base */
+ struct vmcb_segment ds; /* 0x30: 32bit base */
+ struct vmcb_segment fs; /* 0x40 */
+ struct vmcb_segment gs; /* 0x50 */
+ struct vmcb_segment gdt; /* 0x60: base + 16bit limit */
+ struct vmcb_segment ldt; /* 0x70 */
+ struct vmcb_segment idt; /* 0x80: base + 16bit limit */
+ struct vmcb_segment tr; /* 0x90 */
+ uint8_t _pad1[43]; /* 0xA0-0xCA: Reserved */
+ uint8_t cpl; /* 0xCB: CPL (real mode: 0, virt: 3) */
+ uint32_t _pad2; /* 0xCC-0xCF: Reserved */
+ uint64_t efer; /* 0xD0 */
+ uint64_t _pad3[14]; /* 0xD8-0x147: Reserved */
+ uint64_t cr4; /* 0x148 */
+ uint64_t cr3; /* 0x150 */
+ uint64_t cr0; /* 0x158 */
+ uint64_t dr7; /* 0x160 */
+ uint64_t dr6; /* 0x168 */
+ uint64_t rflags; /* 0x170 */
+ uint64_t rip; /* 0x178 */
+ uint64_t _pad4[11]; /* 0x180-0x1D7: Reserved */
+ uint64_t rsp; /* 0x1D8 */
+ uint64_t _pad5[3]; /* 0x1E0-0x1F7: Reserved */
+ uint64_t rax; /* 0x1F8 */
+ uint64_t star; /* 0x200 */
+ uint64_t lstar; /* 0x208 */
+ uint64_t cstar; /* 0x210 */
+ uint64_t sfmask; /* 0x218 */
+ uint64_t kernelgsbase; /* 0x220 */
+ uint64_t sysenter_cs; /* 0x228 */
+ uint64_t sysenter_esp; /* 0x230 */
+ uint64_t sysenter_eip; /* 0x238 */
+ uint64_t cr2; /* 0x240 */
+ uint64_t _pad6[4]; /* 0x248-0x267: Reserved */
+ uint64_t g_pat; /* 0x268 */
+ uint64_t dbgctl; /* 0x270 */
+ uint64_t br_from; /* 0x278 */
+ uint64_t br_to; /* 0x280 */
+ uint64_t int_from; /* 0x288 */
+ uint64_t int_to; /* 0x290 */
+ uint64_t _pad7[301]; /* Reserved up to end of VMCB */
+};
CTASSERT(sizeof(struct vmcb_state) == 0xC00);
+CTASSERT(offsetof(struct vmcb_state, int_to) == 0x290);
struct vmcb {
struct vmcb_ctrl ctrl;
struct vmcb_state state;
-} __attribute__ ((__packed__));
+};
CTASSERT(sizeof(struct vmcb) == PAGE_SIZE);
CTASSERT(offsetof(struct vmcb, state) == 0x400);