summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/amd64/amd64/vmm.c71
-rw-r--r--sys/arch/amd64/include/vmmvar.h66
-rw-r--r--usr.sbin/vmd/vm.c48
-rw-r--r--usr.sbin/vmd/vmd.c129
-rw-r--r--usr.sbin/vmd/vmd.h13
5 files changed, 247 insertions, 80 deletions
diff --git a/sys/arch/amd64/amd64/vmm.c b/sys/arch/amd64/amd64/vmm.c
index 5262b37b949..fb8303c5e1c 100644
--- a/sys/arch/amd64/amd64/vmm.c
+++ b/sys/arch/amd64/amd64/vmm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmm.c,v 1.167 2017/08/20 05:14:16 mlarkin Exp $ */
+/* $OpenBSD: vmm.c,v 1.168 2017/08/20 21:15:32 pd Exp $ */
/*
* Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org>
*
@@ -5379,41 +5379,8 @@ vmm_handle_cpuid(struct vcpu *vcpu)
/* mask off host's APIC ID, reset to vcpu id */
*rbx = cpu_ebxfeature & 0x0000FFFF;
*rbx |= (vcpu->vc_id & 0xFF) << 24;
- /*
- * clone host capabilities minus:
- * debug store (CPUIDECX_DTES64, CPUIDECX_DSCPL, CPUID_DS)
- * monitor/mwait (CPUIDECX_MWAIT)
- * vmx (CPUIDECX_VMX)
- * smx (CPUIDECX_SMX)
- * speedstep (CPUIDECX_EST)
- * thermal (CPUIDECX_TM2, CPUID_ACPI, CPUID_TM)
- * context id (CPUIDECX_CNXTID)
- * silicon debug (CPUIDECX_SDBG)
- * xTPR (CPUIDECX_XTPR)
- * perf/debug (CPUIDECX_PDCM)
- * pcid (CPUIDECX_PCID)
- * direct cache access (CPUIDECX_DCA)
- * x2APIC (CPUIDECX_X2APIC)
- * apic deadline (CPUIDECX_DEADLINE)
- * apic (CPUID_APIC)
- * psn (CPUID_PSN)
- * self snoop (CPUID_SS)
- * hyperthreading (CPUID_HTT)
- * pending break enabled (CPUID_PBE)
- * MTRR (CPUID_MTRR)
- * plus:
- * hypervisor (CPUIDECX_HV)
- */
- *rcx = (cpu_ecxfeature | CPUIDECX_HV) &
- ~(CPUIDECX_EST | CPUIDECX_TM2 | CPUIDECX_MWAIT |
- CPUIDECX_PDCM | CPUIDECX_VMX | CPUIDECX_DTES64 |
- CPUIDECX_DSCPL | CPUIDECX_SMX | CPUIDECX_CNXTID |
- CPUIDECX_SDBG | CPUIDECX_XTPR | CPUIDECX_PCID |
- CPUIDECX_DCA | CPUIDECX_X2APIC | CPUIDECX_DEADLINE);
- *rdx = curcpu()->ci_feature_flags &
- ~(CPUID_ACPI | CPUID_TM | CPUID_HTT |
- CPUID_DS | CPUID_APIC | CPUID_PSN |
- CPUID_SS | CPUID_PBE | CPUID_MTRR);
+ *rcx = (cpu_ecxfeature | CPUIDECX_HV) & VMM_CPUIDECX_MASK;
+ *rdx = curcpu()->ci_feature_flags & VMM_CPUIDEDX_MASK;
break;
case 0x02: /* Cache and TLB information */
*rax = eax;
@@ -5461,37 +5428,9 @@ vmm_handle_cpuid(struct vcpu *vcpu)
break;
case 0x07: /* SEFF */
if (*rcx == 0) {
- /*
- * SEFF flags - copy from host minus:
- * SGX (SEFF0EBX_SGX)
- * HLE (SEFF0EBX_HLE)
- * INVPCID (SEFF0EBX_INVPCID)
- * RTM (SEFF0EBX_RTM)
- * PQM (SEFF0EBX_PQM)
- * AVX512F (SEFF0EBX_AVX512F)
- * AVX512DQ (SEFF0EBX_AVX512DQ)
- * AVX512IFMA (SEFF0EBX_AVX512IFMA)
- * AVX512PF (SEFF0EBX_AVX512PF)
- * AVX512ER (SEFF0EBX_AVX512ER)
- * AVX512CD (SEFF0EBX_AVX512CD)
- * AVX512BW (SEFF0EBX_AVX512BW)
- * AVX512VL (SEFF0EBX_AVX512VL)
- * MPX (SEFF0EBX_MPX)
- * PCOMMIT (SEFF0EBX_PCOMMIT)
- * PT (SEFF0EBX_PT)
- * AVX512VBMI (SEFF0ECX_AVX512VBMI)
- */
*rax = 0; /* Highest subleaf supported */
- *rbx = curcpu()->ci_feature_sefflags_ebx &
- ~(SEFF0EBX_SGX | SEFF0EBX_HLE | SEFF0EBX_INVPCID |
- SEFF0EBX_RTM | SEFF0EBX_PQM | SEFF0EBX_MPX |
- SEFF0EBX_PCOMMIT | SEFF0EBX_PT |
- SEFF0EBX_AVX512F | SEFF0EBX_AVX512DQ |
- SEFF0EBX_AVX512IFMA | SEFF0EBX_AVX512PF |
- SEFF0EBX_AVX512ER | SEFF0EBX_AVX512CD |
- SEFF0EBX_AVX512BW | SEFF0EBX_AVX512VL);
- *rcx = curcpu()->ci_feature_sefflags_ecx &
- ~(SEFF0ECX_AVX512VBMI);
+ *rbx = curcpu()->ci_feature_sefflags_ebx & VMM_SEFF0EBX_MASK;
+ *rcx = curcpu()->ci_feature_sefflags_ecx & VMM_SEFF0ECX_MASK;
*rdx = 0;
} else {
/* Unsupported subleaf */
diff --git a/sys/arch/amd64/include/vmmvar.h b/sys/arch/amd64/include/vmmvar.h
index 4dddc8bf354..4847fa3defa 100644
--- a/sys/arch/amd64/include/vmmvar.h
+++ b/sys/arch/amd64/include/vmmvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmmvar.h,v 1.46 2017/08/14 18:29:41 mlarkin Exp $ */
+/* $OpenBSD: vmmvar.h,v 1.47 2017/08/20 21:15:32 pd Exp $ */
/*
* Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org>
*
@@ -505,6 +505,70 @@ struct vm_rwregs_params {
#define VMM_IOC_READREGS _IOWR('V', 7, struct vm_rwregs_params) /* Get registers */
#define VMM_IOC_WRITEREGS _IOW('V', 8, struct vm_rwregs_params) /* Set registers */
+
+/* CPUID masks */
+/*
+ * clone host capabilities minus:
+ * debug store (CPUIDECX_DTES64, CPUIDECX_DSCPL, CPUID_DS)
+ * monitor/mwait (CPUIDECX_MWAIT)
+ * vmx (CPUIDECX_VMX)
+ * smx (CPUIDECX_SMX)
+ * speedstep (CPUIDECX_EST)
+ * thermal (CPUIDECX_TM2, CPUID_ACPI, CPUID_TM)
+ * context id (CPUIDECX_CNXTID)
+ * silicon debug (CPUIDECX_SDBG)
+ * xTPR (CPUIDECX_XTPR)
+ * perf/debug (CPUIDECX_PDCM)
+ * pcid (CPUIDECX_PCID)
+ * direct cache access (CPUIDECX_DCA)
+ * x2APIC (CPUIDECX_X2APIC)
+ * apic deadline (CPUIDECX_DEADLINE)
+ * apic (CPUID_APIC)
+ * psn (CPUID_PSN)
+ * self snoop (CPUID_SS)
+ * hyperthreading (CPUID_HTT)
+ * pending break enabled (CPUID_PBE)
+ * MTRR (CPUID_MTRR)
+ */
+#define VMM_CPUIDECX_MASK ~(CPUIDECX_EST | CPUIDECX_TM2 | CPUIDECX_MWAIT | \
+ CPUIDECX_PDCM | CPUIDECX_VMX | CPUIDECX_DTES64 | \
+ CPUIDECX_DSCPL | CPUIDECX_SMX | CPUIDECX_CNXTID | \
+ CPUIDECX_SDBG | CPUIDECX_XTPR | CPUIDECX_PCID | \
+ CPUIDECX_DCA | CPUIDECX_X2APIC | CPUIDECX_DEADLINE)
+#define VMM_CPUIDEDX_MASK ~(CPUID_ACPI | CPUID_TM | \
+ CPUID_HTT | CPUID_DS | CPUID_APIC | \
+ CPUID_PSN | CPUID_SS | CPUID_PBE | \
+ CPUID_MTRR)
+
+/*
+ * SEFF flags - copy from host minus:
+ * SGX (SEFF0EBX_SGX)
+ * HLE (SEFF0EBX_HLE)
+ * INVPCID (SEFF0EBX_INVPCID)
+ * RTM (SEFF0EBX_RTM)
+ * PQM (SEFF0EBX_PQM)
+ * AVX512F (SEFF0EBX_AVX512F)
+ * AVX512DQ (SEFF0EBX_AVX512DQ)
+ * AVX512IFMA (SEFF0EBX_AVX512IFMA)
+ * AVX512PF (SEFF0EBX_AVX512PF)
+ * AVX512ER (SEFF0EBX_AVX512ER)
+ * AVX512CD (SEFF0EBX_AVX512CD)
+ * AVX512BW (SEFF0EBX_AVX512BW)
+ * AVX512VL (SEFF0EBX_AVX512VL)
+ * MPX (SEFF0EBX_MPX)
+ * PCOMMIT (SEFF0EBX_PCOMMIT)
+ * PT (SEFF0EBX_PT)
+ * AVX512VBMI (SEFF0ECX_AVX512VBMI)
+ */
+#define VMM_SEFF0EBX_MASK ~(SEFF0EBX_SGX | SEFF0EBX_HLE | SEFF0EBX_INVPCID | \
+ SEFF0EBX_RTM | SEFF0EBX_PQM | SEFF0EBX_MPX | \
+ SEFF0EBX_PCOMMIT | SEFF0EBX_PT | \
+ SEFF0EBX_AVX512F | SEFF0EBX_AVX512DQ | \
+ SEFF0EBX_AVX512IFMA | SEFF0EBX_AVX512PF | \
+ SEFF0EBX_AVX512ER | SEFF0EBX_AVX512CD | \
+ SEFF0EBX_AVX512BW | SEFF0EBX_AVX512VL)
+#define VMM_SEFF0ECX_MASK ~(SEFF0ECX_AVX512VBMI)
+
#ifdef _KERNEL
#define VMX_FAIL_LAUNCH_UNKNOWN 1
diff --git a/usr.sbin/vmd/vm.c b/usr.sbin/vmd/vm.c
index 20adc2a46f8..0199f77860a 100644
--- a/usr.sbin/vmd/vm.c
+++ b/usr.sbin/vmd/vm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm.c,v 1.23 2017/08/14 18:27:58 mlarkin Exp $ */
+/* $OpenBSD: vm.c,v 1.24 2017/08/20 21:15:32 pd Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -80,6 +80,7 @@ uint8_t vcpu_exit_pci(struct vm_run_params *);
int vcpu_pic_intr(uint32_t, uint32_t, uint8_t);
int loadfile_bios(FILE *, struct vcpu_reg_state *);
int send_vm(int, struct vm_create_params *);
+int dump_send_header(int);
int dump_vmr(int , struct vm_mem_range *);
int dump_mem(int, struct vm_create_params *);
void restore_vmr(int, struct vm_mem_range *);
@@ -490,16 +491,12 @@ send_vm(int fd, struct vm_create_params *vcp)
struct vm_rwregs_params vrp;
struct vmop_create_params *vmc;
struct vm_terminate_params vtp;
- struct vm_dump_header vmh;
unsigned int flags = 0;
unsigned int i;
int ret = 0;
- memset(&vmh, 0, sizeof(vmh));
- memcpy(vmh.vmh_signature, VM_DUMP_SIGNATURE, sizeof(vmh.vmh_signature));
- vmh.vmh_version = VM_DUMP_VERSION;
- if (atomicio(vwrite, fd, &vmh, sizeof(vmh)) != sizeof(vmh)) {
- log_warn("%s: failed to send vm dump header", __func__);
+ if (dump_send_header(fd)) {
+ log_info("%s: failed to send vm dump header", __func__);
goto err;
}
@@ -564,6 +561,43 @@ err:
}
int
+dump_send_header(int fd) {
+ struct vm_dump_header vmh;
+ int i;
+
+ vmh.vmh_cpuids[0].code = 0x00;
+ vmh.vmh_cpuids[0].leaf = 0x00;
+
+ vmh.vmh_cpuids[1].code = 0x01;
+ vmh.vmh_cpuids[1].leaf = 0x00;
+
+ vmh.vmh_cpuids[2].code = 0x07;
+ vmh.vmh_cpuids[2].leaf = 0x00;
+
+ vmh.vmh_cpuids[3].code = 0x0d;
+ vmh.vmh_cpuids[3].leaf = 0x00;
+
+ vmh.vmh_cpuids[4].code = 0x80000001;
+ vmh.vmh_cpuids[4].leaf = 0x00;
+
+ vmh.vmh_version = VM_DUMP_VERSION;
+
+ for (i=0; i < VM_DUMP_HEADER_CPUID_COUNT; i++) {
+ CPUID_LEAF(vmh.vmh_cpuids[i].code,
+ vmh.vmh_cpuids[i].leaf,
+ vmh.vmh_cpuids[i].a,
+ vmh.vmh_cpuids[i].b,
+ vmh.vmh_cpuids[i].c,
+ vmh.vmh_cpuids[i].d);
+ }
+
+ if (atomicio(vwrite, fd, &vmh, sizeof(vmh)) != sizeof(vmh))
+ return (-1);
+
+ return (0);
+}
+
+int
dump_mem(int fd, struct vm_create_params *vcp)
{
unsigned int i;
diff --git a/usr.sbin/vmd/vmd.c b/usr.sbin/vmd/vmd.c
index 4fefc3f0420..c7b9247d326 100644
--- a/usr.sbin/vmd/vmd.c
+++ b/usr.sbin/vmd/vmd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmd.c,v 1.67 2017/08/15 15:10:35 pd Exp $ */
+/* $OpenBSD: vmd.c,v 1.68 2017/08/20 21:15:32 pd Exp $ */
/*
* Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
@@ -39,6 +39,9 @@
#include <pwd.h>
#include <grp.h>
+#include <machine/specialreg.h>
+#include <machine/vmmvar.h>
+
#include "proc.h"
#include "atomicio.h"
#include "vmd.h"
@@ -52,6 +55,7 @@ void vmd_shutdown(void);
int vmd_control_run(void);
int vmd_dispatch_control(int, struct privsep_proc *, struct imsg *);
int vmd_dispatch_vmm(int, struct privsep_proc *, struct imsg *);
+int check_vmh(struct vm_dump_header *);
struct vmd *env;
@@ -226,9 +230,7 @@ vmd_dispatch_control(int fd, struct privsep_proc *p, struct imsg *imsg)
cmd = IMSG_VMDOP_START_VM_RESPONSE;
break;
}
- if (vmh.vmh_version != VM_DUMP_VERSION) {
- log_warnx("%s: incompatible dump version",
- __func__);
+ if(check_vmh(&vmh)) {
res = ENOENT;
close(imsg->fd);
cmd = IMSG_VMDOP_START_VM_RESPONSE;
@@ -466,6 +468,125 @@ vmd_dispatch_vmm(int fd, struct privsep_proc *p, struct imsg *imsg)
return (0);
}
+int
+check_vmh(struct vm_dump_header *vmh) {
+ int i;
+ unsigned int code, leaf;
+ unsigned int a, b, c, d;
+
+
+ if (vmh->vmh_version != VM_DUMP_VERSION) {
+ log_warnx("%s: incompatible dump version", __func__);
+ return (-1);
+ }
+
+ for (i = 0; i < VM_DUMP_HEADER_CPUID_COUNT; i++) {
+ code = vmh->vmh_cpuids[i].code;
+ leaf = vmh->vmh_cpuids[i].leaf;
+ if (leaf != 0x00) {
+ log_debug("%s: invalid leaf 0x%x for code 0x%x",
+ __func__, leaf, code);
+ return (-1);
+ }
+
+ switch(code) {
+ case 0x00:
+ CPUID_LEAF(code, leaf, a, b, c, d);
+ if (vmh->vmh_cpuids[i].a > a) {
+ log_debug("%s: incompatible cpuid level", __func__);
+ return (-1);
+ }
+ if (!(vmh->vmh_cpuids[i].b == b &&
+ vmh->vmh_cpuids[i].c == c &&
+ vmh->vmh_cpuids[i].d == d)) {
+ log_debug("%s: incompatible cpu brand", __func__);
+ return (-1);
+ }
+ break;
+
+ case 0x01:
+ CPUID_LEAF(code, leaf, a, b, c, d);
+ if ((vmh->vmh_cpuids[i].c & c & VMM_CPUIDECX_MASK) !=
+ (vmh->vmh_cpuids[i].c & VMM_CPUIDECX_MASK)) {
+ log_debug("%s: incompatible cpu features "
+ "code: 0x%x leaf: 0x%x reg: c", __func__,
+ code, leaf);
+ return (-1);
+ }
+ if ((vmh->vmh_cpuids[i].d & d & VMM_CPUIDEDX_MASK) !=
+ (vmh->vmh_cpuids[i].d & VMM_CPUIDEDX_MASK)) {
+ log_debug("%s: incompatible cpu features "
+ "code: 0x%x leaf: 0x%x reg: d", __func__,
+ code, leaf);
+ return (-1);
+ }
+ break;
+
+ case 0x07:
+ CPUID_LEAF(code, leaf, a, b, c, d);
+ if ((vmh->vmh_cpuids[i].b & b & VMM_SEFF0EBX_MASK) !=
+ (vmh->vmh_cpuids[i].b & VMM_SEFF0EBX_MASK)) {
+ log_debug("%s: incompatible cpu features "
+ "code: 0x%x leaf: 0x%x reg: c", __func__,
+ code, leaf);
+ return (-1);
+ }
+ if ((vmh->vmh_cpuids[i].c & c & VMM_SEFF0ECX_MASK) !=
+ (vmh->vmh_cpuids[i].c & VMM_SEFF0ECX_MASK)) {
+ log_debug("%s: incompatible cpu features "
+ "code: 0x%x leaf: 0x%x reg: d", __func__,
+ code, leaf);
+ return (-1);
+ }
+ break;
+
+ case 0x0d:
+ CPUID_LEAF(code, leaf, a, b, c, d);
+ if (vmh->vmh_cpuids[i].b > b) {
+ log_debug("%s: incompatible cpu: insufficient "
+ "max save area for enabled XCR0 features",
+ __func__);
+ return (-1);
+ }
+ if (vmh->vmh_cpuids[i].c > c) {
+ log_debug("%s: incompatible cpu: insufficient "
+ "max save area for supported XCR0 features",
+ __func__);
+ return (-1);
+ }
+ break;
+
+ case 0x80000001:
+ CPUID_LEAF(code, leaf, a, b, c, d);
+ if ((vmh->vmh_cpuids[i].a & a) != vmh->vmh_cpuids[i].a) {
+ log_debug("%s: incompatible cpu features "
+ "code: 0x%x leaf: 0x%x reg: a", __func__,
+ code, leaf);
+ return (-1);
+ }
+ if ((vmh->vmh_cpuids[i].c & c) != vmh->vmh_cpuids[i].c) {
+ log_debug("%s: incompatible cpu features "
+ "code: 0x%x leaf: 0x%x reg: c", __func__,
+ code, leaf);
+ return (-1);
+ }
+ if ((vmh->vmh_cpuids[i].d & d) != vmh->vmh_cpuids[i].d) {
+ log_debug("%s: incompatible cpu features "
+ "code: 0x%x leaf: 0x%x reg: d", __func__,
+ code, leaf);
+ return (-1);
+ }
+ break;
+
+ default:
+ log_debug("%s: unknown code 0x%x", __func__, code);
+ return (-1);
+ }
+ }
+
+ return (0);
+}
+
void
vmd_sighdlr(int sig, short event, void *arg)
{
diff --git a/usr.sbin/vmd/vmd.h b/usr.sbin/vmd/vmd.h
index d22b797dc35..57bdb71cd5f 100644
--- a/usr.sbin/vmd/vmd.h
+++ b/usr.sbin/vmd/vmd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmd.h,v 1.59 2017/08/18 07:01:29 mlarkin Exp $ */
+/* $OpenBSD: vmd.h,v 1.60 2017/08/20 21:15:32 pd Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -149,12 +149,21 @@ struct vmop_create_params {
int64_t vmc_gid;
};
+struct vm_dump_header_cpuid {
+ unsigned long code, leaf;
+ unsigned int a, b, c, d;
+};
+
+#define VM_DUMP_HEADER_CPUID_COUNT 5
+
struct vm_dump_header {
uint8_t vmh_signature[12];
#define VM_DUMP_SIGNATURE VMM_HV_SIGNATURE
uint8_t vmh_pad[3];
uint8_t vmh_version;
-#define VM_DUMP_VERSION 1
+#define VM_DUMP_VERSION 2
+ struct vm_dump_header_cpuid
+ vmh_cpuids[VM_DUMP_HEADER_CPUID_COUNT];
} __packed;
struct vmboot_params {