diff options
-rw-r--r-- | lib/libvmmapi/vmmapi.c | 1 | ||||
-rw-r--r-- | sys/amd64/amd64/pmap.c | 2 | ||||
-rw-r--r-- | sys/amd64/include/vmm.h | 1 | ||||
-rw-r--r-- | sys/amd64/vmm/intel/vmx.c | 23 | ||||
-rw-r--r-- | sys/amd64/vmm/intel/vmx.h | 1 | ||||
-rw-r--r-- | sys/amd64/vmm/intel/vmx_controls.h | 1 | ||||
-rw-r--r-- | sys/amd64/vmm/x86.c | 18 | ||||
-rw-r--r-- | usr.sbin/bhyve/bhyverun.c | 80 | ||||
-rw-r--r-- | usr.sbin/bhyve/bhyverun.h | 1 | ||||
-rw-r--r-- | usr.sbin/bhyve/spinup_ap.c | 17 | ||||
-rw-r--r-- | usr.sbin/bhyvectl/bhyvectl.c | 1 |
11 files changed, 93 insertions, 53 deletions
diff --git a/lib/libvmmapi/vmmapi.c b/lib/libvmmapi/vmmapi.c index 810b39e..bb69358 100644 --- a/lib/libvmmapi/vmmapi.c +++ b/lib/libvmmapi/vmmapi.c @@ -415,6 +415,7 @@ static struct { { "mtrap_exit", VM_CAP_MTRAP_EXIT }, { "pause_exit", VM_CAP_PAUSE_EXIT }, { "unrestricted_guest", VM_CAP_UNRESTRICTED_GUEST }, + { "enable_invpcid", VM_CAP_ENABLE_INVPCID }, { 0 } }; diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index c0af020..d60cbd1 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -371,6 +371,8 @@ int pmap_pcid_enabled = 1; SYSCTL_INT(_vm_pmap, OID_AUTO, pcid_enabled, CTLFLAG_RDTUN, &pmap_pcid_enabled, 0, "Is TLB Context ID enabled ?"); int invpcid_works = 0; +SYSCTL_INT(_vm_pmap, OID_AUTO, invpcid_works, CTLFLAG_RD, &invpcid_works, 0, + "Is the invpcid instruction available ?"); static int pmap_pcid_save_cnt_proc(SYSCTL_HANDLER_ARGS) diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h index 64dbc58..e8bc409 100644 --- a/sys/amd64/include/vmm.h +++ b/sys/amd64/include/vmm.h @@ -223,6 +223,7 @@ enum vm_cap_type { VM_CAP_MTRAP_EXIT, VM_CAP_PAUSE_EXIT, VM_CAP_UNRESTRICTED_GUEST, + VM_CAP_ENABLE_INVPCID, VM_CAP_MAX }; diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c index 5b65de6..1241b14 100644 --- a/sys/amd64/vmm/intel/vmx.c +++ b/sys/amd64/vmm/intel/vmx.c @@ -164,6 +164,7 @@ static int cap_halt_exit; static int cap_pause_exit; static int cap_unrestricted_guest; static int cap_monitor_trap; +static int cap_invpcid; static struct unrhdr *vpid_unr; static u_int vpid_alloc_failed; @@ -660,6 +661,11 @@ vmx_init(void) PROCBASED2_UNRESTRICTED_GUEST, 0, &tmp) == 0); + cap_invpcid = (vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS2, + MSR_VMX_PROCBASED_CTLS2, PROCBASED2_ENABLE_INVPCID, 0, + &tmp) == 0); + + /* Initialize EPT */ error = ept_init(); if (error) { @@ -828,6 +834,7 @@ vmx_vminit(struct vm *vm, pmap_t pmap) vmx->cap[i].set = 0; vmx->cap[i].proc_ctls = procbased_ctls; + vmx->cap[i].proc_ctls2 = procbased_ctls2; vmx->state[i].lastcpu = -1; vmx->state[i].vpid = vpid[i]; @@ -1932,6 +1939,10 @@ vmx_getcap(void *arg, int vcpu, int type, int *retval) if (cap_unrestricted_guest) ret = 0; break; + case VM_CAP_ENABLE_INVPCID: + if (cap_invpcid) + ret = 0; + break; default: break; } @@ -1988,11 +1999,21 @@ vmx_setcap(void *arg, int vcpu, int type, int val) case VM_CAP_UNRESTRICTED_GUEST: if (cap_unrestricted_guest) { retval = 0; - baseval = procbased_ctls2; + pptr = &vmx->cap[vcpu].proc_ctls2; + baseval = *pptr; flag = PROCBASED2_UNRESTRICTED_GUEST; reg = VMCS_SEC_PROC_BASED_CTLS; } break; + case VM_CAP_ENABLE_INVPCID: + if (cap_invpcid) { + retval = 0; + pptr = &vmx->cap[vcpu].proc_ctls2; + baseval = *pptr; + flag = PROCBASED2_ENABLE_INVPCID; + reg = VMCS_SEC_PROC_BASED_CTLS; + } + break; default: break; } diff --git a/sys/amd64/vmm/intel/vmx.h b/sys/amd64/vmm/intel/vmx.h index 8e57764..450bb66 100644 --- a/sys/amd64/vmm/intel/vmx.h +++ b/sys/amd64/vmm/intel/vmx.h @@ -84,6 +84,7 @@ struct vmxctx { struct vmxcap { int set; uint32_t proc_ctls; + uint32_t proc_ctls2; }; struct vmxstate { diff --git a/sys/amd64/vmm/intel/vmx_controls.h b/sys/amd64/vmm/intel/vmx_controls.h index 31f29f8..b37e6d1 100644 --- a/sys/amd64/vmm/intel/vmx_controls.h +++ b/sys/amd64/vmm/intel/vmx_controls.h @@ -68,6 +68,7 @@ #define PROCBASED2_WBINVD_EXITING (1 << 6) #define PROCBASED2_UNRESTRICTED_GUEST (1 << 7) #define PROCBASED2_PAUSE_LOOP_EXITING (1 << 10) +#define PROCBASED2_ENABLE_INVPCID (1 << 12) /* VM Exit Controls */ #define VM_EXIT_SAVE_DEBUG_CONTROLS (1 << 2) diff --git a/sys/amd64/vmm/x86.c b/sys/amd64/vmm/x86.c index c23f1fc..c1fc006e 100644 --- a/sys/amd64/vmm/x86.c +++ b/sys/amd64/vmm/x86.c @@ -53,7 +53,7 @@ int x86_emulate_cpuid(struct vm *vm, int vcpu_id, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { - int error; + int error, enable_invpcid; unsigned int func, regs[4]; enum x2apic_state x2apic_state; @@ -202,8 +202,22 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id, regs[0] |= 0x04008000; break; - case CPUID_0000_0006: case CPUID_0000_0007: + regs[0] = 0; + regs[1] = 0; + regs[2] = 0; + regs[3] = 0; + + /* leaf 0 */ + if (*ecx == 0) { + error = vm_get_capability(vm, vcpu_id, + VM_CAP_ENABLE_INVPCID, &enable_invpcid); + if (error == 0 && enable_invpcid) + regs[1] |= CPUID_STDEXT_INVPCID; + } + break; + + case CPUID_0000_0006: case CPUID_0000_000A: case CPUID_0000_000D: /* diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c index 5359442..f679ad5 100644 --- a/usr.sbin/bhyve/bhyverun.c +++ b/usr.sbin/bhyve/bhyverun.c @@ -484,10 +484,54 @@ num_vcpus_allowed(struct vmctx *ctx) return (1); } +void +fbsdrun_set_capabilities(struct vmctx *ctx, int cpu) +{ + int err, tmp; + + if (fbsdrun_vmexit_on_hlt()) { + err = vm_get_capability(ctx, cpu, VM_CAP_HALT_EXIT, &tmp); + if (err < 0) { + fprintf(stderr, "VM exit on HLT not supported\n"); + exit(1); + } + vm_set_capability(ctx, cpu, VM_CAP_HALT_EXIT, 1); + if (cpu == BSP) + handler[VM_EXITCODE_HLT] = vmexit_hlt; + } + + if (fbsdrun_vmexit_on_pause()) { + /* + * pause exit support required for this mode + */ + err = vm_get_capability(ctx, cpu, VM_CAP_PAUSE_EXIT, &tmp); + if (err < 0) { + fprintf(stderr, + "SMP mux requested, no pause support\n"); + exit(1); + } + vm_set_capability(ctx, cpu, VM_CAP_PAUSE_EXIT, 1); + if (cpu == BSP) + handler[VM_EXITCODE_PAUSE] = vmexit_pause; + } + + if (fbsdrun_disable_x2apic()) + err = vm_set_x2apic_state(ctx, cpu, X2APIC_DISABLED); + else + err = vm_set_x2apic_state(ctx, cpu, X2APIC_ENABLED); + + if (err) { + fprintf(stderr, "Unable to set x2apic state (%d)\n", err); + exit(1); + } + + vm_set_capability(ctx, cpu, VM_CAP_ENABLE_INVPCID, 1); +} + int main(int argc, char *argv[]) { - int c, error, gdb_port, tmp, err, ioapic, bvmcons; + int c, error, gdb_port, err, ioapic, bvmcons; int max_vcpus; struct vmctx *ctx; uint64_t rip; @@ -574,39 +618,7 @@ main(int argc, char *argv[]) exit(1); } - if (fbsdrun_vmexit_on_hlt()) { - err = vm_get_capability(ctx, BSP, VM_CAP_HALT_EXIT, &tmp); - if (err < 0) { - fprintf(stderr, "VM exit on HLT not supported\n"); - exit(1); - } - vm_set_capability(ctx, BSP, VM_CAP_HALT_EXIT, 1); - handler[VM_EXITCODE_HLT] = vmexit_hlt; - } - - if (fbsdrun_vmexit_on_pause()) { - /* - * pause exit support required for this mode - */ - err = vm_get_capability(ctx, BSP, VM_CAP_PAUSE_EXIT, &tmp); - if (err < 0) { - fprintf(stderr, - "SMP mux requested, no pause support\n"); - exit(1); - } - vm_set_capability(ctx, BSP, VM_CAP_PAUSE_EXIT, 1); - handler[VM_EXITCODE_PAUSE] = vmexit_pause; - } - - if (fbsdrun_disable_x2apic()) - err = vm_set_x2apic_state(ctx, BSP, X2APIC_DISABLED); - else - err = vm_set_x2apic_state(ctx, BSP, X2APIC_ENABLED); - - if (err) { - fprintf(stderr, "Unable to set x2apic state (%d)\n", err); - exit(1); - } + fbsdrun_set_capabilities(ctx, BSP); err = vm_setup_memory(ctx, memsize, VM_MMAP_ALL); if (err) { diff --git a/usr.sbin/bhyve/bhyverun.h b/usr.sbin/bhyve/bhyverun.h index 28ffb3c..d074d65 100644 --- a/usr.sbin/bhyve/bhyverun.h +++ b/usr.sbin/bhyve/bhyverun.h @@ -41,6 +41,7 @@ extern char *vmname; void *paddr_guest2host(struct vmctx *ctx, uintptr_t addr, size_t len); +void fbsdrun_set_capabilities(struct vmctx *ctx, int cpu); void fbsdrun_addcpu(struct vmctx *ctx, int cpu, uint64_t rip); int fbsdrun_muxed(void); int fbsdrun_vmexit_on_hlt(void); diff --git a/usr.sbin/bhyve/spinup_ap.c b/usr.sbin/bhyve/spinup_ap.c index 2632aed..729108a 100644 --- a/usr.sbin/bhyve/spinup_ap.c +++ b/usr.sbin/bhyve/spinup_ap.c @@ -85,22 +85,7 @@ spinup_ap(struct vmctx *ctx, int vcpu, int newcpu, uint64_t rip) error = vcpu_reset(ctx, newcpu); assert(error == 0); - /* Set up capabilities */ - if (fbsdrun_vmexit_on_hlt()) { - error = vm_set_capability(ctx, newcpu, VM_CAP_HALT_EXIT, 1); - assert(error == 0); - } - - if (fbsdrun_vmexit_on_pause()) { - error = vm_set_capability(ctx, newcpu, VM_CAP_PAUSE_EXIT, 1); - assert(error == 0); - } - - if (fbsdrun_disable_x2apic()) - error = vm_set_x2apic_state(ctx, newcpu, X2APIC_DISABLED); - else - error = vm_set_x2apic_state(ctx, newcpu, X2APIC_ENABLED); - assert(error == 0); + fbsdrun_set_capabilities(ctx, newcpu); /* * Enable the 'unrestricted guest' mode for 'newcpu'. diff --git a/usr.sbin/bhyvectl/bhyvectl.c b/usr.sbin/bhyvectl/bhyvectl.c index d6b32b8..0e92204 100644 --- a/usr.sbin/bhyvectl/bhyvectl.c +++ b/usr.sbin/bhyvectl/bhyvectl.c @@ -1495,6 +1495,7 @@ main(int argc, char *argv[]) vm_capability_type2name(captype), val ? "set" : "not set", vcpu); } else if (errno == ENOENT) { + error = 0; printf("Capability \"%s\" is not available\n", vm_capability_type2name(captype)); } else { |