summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/libvmmapi/vmmapi.c1
-rw-r--r--sys/amd64/amd64/pmap.c2
-rw-r--r--sys/amd64/include/vmm.h1
-rw-r--r--sys/amd64/vmm/intel/vmx.c23
-rw-r--r--sys/amd64/vmm/intel/vmx.h1
-rw-r--r--sys/amd64/vmm/intel/vmx_controls.h1
-rw-r--r--sys/amd64/vmm/x86.c18
-rw-r--r--usr.sbin/bhyve/bhyverun.c80
-rw-r--r--usr.sbin/bhyve/bhyverun.h1
-rw-r--r--usr.sbin/bhyve/spinup_ap.c17
-rw-r--r--usr.sbin/bhyvectl/bhyvectl.c1
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 {
OpenPOWER on IntegriCloud