summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2013-10-22 00:58:51 +0000
committerneel <neel@FreeBSD.org>2013-10-22 00:58:51 +0000
commitb31f0060b59a4d7ad2b7ddb3261a49fbdce0dad1 (patch)
tree9dfed47515f37a1e3685838506fddfadda2af8dd /sys/amd64
parent44f5357aec14c32040c49f1703b1d4c2cac5d080 (diff)
downloadFreeBSD-src-b31f0060b59a4d7ad2b7ddb3261a49fbdce0dad1.zip
FreeBSD-src-b31f0060b59a4d7ad2b7ddb3261a49fbdce0dad1.tar.gz
MFC r256645.
Add a new capability, VM_CAP_ENABLE_INVPCID, that can be enabled to expose 'invpcid' instruction to the guest. Currently bhyve will try to enable this capability unconditionally if it is available. Consolidate code in bhyve to set the capabilities so it is no longer duplicated in BSP and AP bringup. Add a sysctl 'vm.pmap.invpcid_works' to display whether the 'invpcid' instruction is available. Approved by: re (hrs)
Diffstat (limited to 'sys/amd64')
-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
6 files changed, 43 insertions, 3 deletions
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:
/*
OpenPOWER on IntegriCloud