- Output a summary of optional VT-x features in dmesg similar to CPU
features. If bootverbose is enabled, a detailed list is provided; otherwise, a single-line summary is displayed. - Add read-only sysctls for optional VT-x capabilities used by bhyve under a new hw.vmm.vmx.cap node. Move a few exiting sysctls that indicate the presence of optional capabilities under this node. CR: https://phabric.freebsd.org/D498 Reviewed by: grehan, neel MFC after: 1 week
This commit is contained in:
parent
39c8c62ec4
commit
06fc6db948
@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/specialreg.h>
|
||||
#include <machine/md_var.h>
|
||||
|
||||
#include <amd64/vmm/intel/vmx_controls.h>
|
||||
#include <x86/isa/icu.h>
|
||||
|
||||
/* XXX - should be in header file: */
|
||||
@ -73,6 +74,7 @@ static u_int find_cpu_vendor_id(void);
|
||||
static void print_AMD_info(void);
|
||||
static void print_AMD_assoc(int i);
|
||||
static void print_via_padlock_info(void);
|
||||
static void print_vmx_info(void);
|
||||
|
||||
int cpu_class;
|
||||
char machine[] = "amd64";
|
||||
@ -428,6 +430,9 @@ printcpuinfo(void)
|
||||
if (via_feature_rng != 0 || via_feature_xcrypt != 0)
|
||||
print_via_padlock_info();
|
||||
|
||||
if (cpu_feature2 & CPUID2_VMX)
|
||||
print_vmx_info();
|
||||
|
||||
if ((cpu_feature & CPUID_HTT) &&
|
||||
cpu_vendor_id == CPU_VENDOR_AMD)
|
||||
cpu_feature &= ~CPUID_HTT;
|
||||
@ -722,3 +727,197 @@ print_via_padlock_info(void)
|
||||
"\015RSA" /* PMM */
|
||||
);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
vmx_settable(uint64_t basic, int msr, int true_msr)
|
||||
{
|
||||
uint64_t val;
|
||||
|
||||
if (basic & (1UL << 55))
|
||||
val = rdmsr(true_msr);
|
||||
else
|
||||
val = rdmsr(msr);
|
||||
|
||||
/* Just report the controls that can be set to 1. */
|
||||
return (val >> 32);
|
||||
}
|
||||
|
||||
static void
|
||||
print_vmx_info(void)
|
||||
{
|
||||
uint64_t basic, msr;
|
||||
uint32_t entry, exit, mask, pin, proc, proc2;
|
||||
int comma;
|
||||
|
||||
printf("\n VT-x: ");
|
||||
msr = rdmsr(MSR_IA32_FEATURE_CONTROL);
|
||||
if (!(msr & IA32_FEATURE_CONTROL_VMX_EN))
|
||||
printf("(disabled in BIOS) ");
|
||||
basic = rdmsr(MSR_VMX_BASIC);
|
||||
pin = vmx_settable(basic, MSR_VMX_PINBASED_CTLS,
|
||||
MSR_VMX_TRUE_PINBASED_CTLS);
|
||||
proc = vmx_settable(basic, MSR_VMX_PROCBASED_CTLS,
|
||||
MSR_VMX_TRUE_PROCBASED_CTLS);
|
||||
if (proc & PROCBASED_SECONDARY_CONTROLS)
|
||||
proc2 = vmx_settable(basic, MSR_VMX_PROCBASED_CTLS2,
|
||||
MSR_VMX_PROCBASED_CTLS2);
|
||||
else
|
||||
proc2 = 0;
|
||||
exit = vmx_settable(basic, MSR_VMX_EXIT_CTLS, MSR_VMX_TRUE_EXIT_CTLS);
|
||||
entry = vmx_settable(basic, MSR_VMX_ENTRY_CTLS, MSR_VMX_TRUE_ENTRY_CTLS);
|
||||
|
||||
if (!bootverbose) {
|
||||
comma = 0;
|
||||
if (exit & VM_EXIT_SAVE_PAT && exit & VM_EXIT_LOAD_PAT &&
|
||||
entry & VM_ENTRY_LOAD_PAT) {
|
||||
printf("%sPAT", comma ? "," : "");
|
||||
comma = 1;
|
||||
}
|
||||
if (proc & PROCBASED_HLT_EXITING) {
|
||||
printf("%sHLT", comma ? "," : "");
|
||||
comma = 1;
|
||||
}
|
||||
if (proc & PROCBASED_MTF) {
|
||||
printf("%sMTF", comma ? "," : "");
|
||||
comma = 1;
|
||||
}
|
||||
if (proc & PROCBASED_PAUSE_EXITING) {
|
||||
printf("%sPAUSE", comma ? "," : "");
|
||||
comma = 1;
|
||||
}
|
||||
if (proc2 & PROCBASED2_ENABLE_EPT) {
|
||||
printf("%sEPT", comma ? "," : "");
|
||||
comma = 1;
|
||||
}
|
||||
if (proc2 & PROCBASED2_UNRESTRICTED_GUEST) {
|
||||
printf("%sUG", comma ? "," : "");
|
||||
comma = 1;
|
||||
}
|
||||
if (proc2 & PROCBASED2_ENABLE_VPID) {
|
||||
printf("%sVPID", comma ? "," : "");
|
||||
comma = 1;
|
||||
}
|
||||
if (proc & PROCBASED_USE_TPR_SHADOW &&
|
||||
proc2 & PROCBASED2_VIRTUALIZE_APIC_ACCESSES &&
|
||||
proc2 & PROCBASED2_VIRTUALIZE_X2APIC_MODE &&
|
||||
proc2 & PROCBASED2_APIC_REGISTER_VIRTUALIZATION &&
|
||||
proc2 & PROCBASED2_VIRTUAL_INTERRUPT_DELIVERY) {
|
||||
printf("%sVID", comma ? "," : "");
|
||||
comma = 1;
|
||||
if (pin & PINBASED_POSTED_INTERRUPT)
|
||||
printf(",PostIntr");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mask = basic >> 32;
|
||||
printf("Basic Features=0x%b", mask,
|
||||
"\020"
|
||||
"\02132PA" /* 32-bit physical addresses */
|
||||
"\022SMM" /* SMM dual-monitor */
|
||||
"\027INS/OUTS" /* VM-exit info for INS and OUTS */
|
||||
"\030TRUE" /* TRUE_CTLS MSRs */
|
||||
);
|
||||
printf("\n Pin-Based Controls=0x%b", pin,
|
||||
"\020"
|
||||
"\001ExtINT" /* External-interrupt exiting */
|
||||
"\004NMI" /* NMI exiting */
|
||||
"\006VNMI" /* Virtual NMIs */
|
||||
"\007PreTmr" /* Activate VMX-preemption timer */
|
||||
"\010PostIntr" /* Process posted interrupts */
|
||||
);
|
||||
printf("\n Primary Processor Controls=0x%b", proc,
|
||||
"\020"
|
||||
"\003INTWIN" /* Interrupt-window exiting */
|
||||
"\004TSCOff" /* Use TSC offsetting */
|
||||
"\010HLT" /* HLT exiting */
|
||||
"\012INVLPG" /* INVLPG exiting */
|
||||
"\013MWAIT" /* MWAIT exiting */
|
||||
"\014RDPMC" /* RDPMC exiting */
|
||||
"\015RDTSC" /* RDTSC exiting */
|
||||
"\020CR3-LD" /* CR3-load exiting */
|
||||
"\021CR3-ST" /* CR3-store exiting */
|
||||
"\024CR8-LD" /* CR8-load exiting */
|
||||
"\025CR8-ST" /* CR8-store exiting */
|
||||
"\026TPR" /* Use TPR shadow */
|
||||
"\027NMIWIN" /* NMI-window exiting */
|
||||
"\030MOV-DR" /* MOV-DR exiting */
|
||||
"\031IO" /* Unconditional I/O exiting */
|
||||
"\032IOmap" /* Use I/O bitmaps */
|
||||
"\034MTF" /* Monitor trap flag */
|
||||
"\035MSRmap" /* Use MSR bitmaps */
|
||||
"\036MONITOR" /* MONITOR exiting */
|
||||
"\037PAUSE" /* PAUSE exiting */
|
||||
);
|
||||
if (proc & PROCBASED_SECONDARY_CONTROLS)
|
||||
printf("\n Secondary Processor Controls=0x%b", proc2,
|
||||
"\020"
|
||||
"\001APIC" /* Virtualize APIC accesses */
|
||||
"\002EPT" /* Enable EPT */
|
||||
"\003DT" /* Descriptor-table exiting */
|
||||
"\004RDTSCP" /* Enable RDTSCP */
|
||||
"\005x2APIC" /* Virtualize x2APIC mode */
|
||||
"\006VPID" /* Enable VPID */
|
||||
"\007WBINVD" /* WBINVD exiting */
|
||||
"\010UG" /* Unrestricted guest */
|
||||
"\011APIC-reg" /* APIC-register virtualization */
|
||||
"\012VID" /* Virtual-interrupt delivery */
|
||||
"\013PAUSE-loop" /* PAUSE-loop exiting */
|
||||
"\014RDRAND" /* RDRAND exiting */
|
||||
"\015INVPCID" /* Enable INVPCID */
|
||||
"\016VMFUNC" /* Enable VM functions */
|
||||
"\017VMCS" /* VMCS shadowing */
|
||||
"\020EPT#VE" /* EPT-violation #VE */
|
||||
"\021XSAVES" /* Enable XSAVES/XRSTORS */
|
||||
);
|
||||
printf("\n Exit Controls=0x%b", mask,
|
||||
"\020"
|
||||
"\003DR" /* Save debug controls */
|
||||
/* Ignore Host address-space size */
|
||||
"\015PERF" /* Load MSR_PERF_GLOBAL_CTRL */
|
||||
"\020AckInt" /* Acknowledge interrupt on exit */
|
||||
"\023PAT-SV" /* Save MSR_PAT */
|
||||
"\024PAT-LD" /* Load MSR_PAT */
|
||||
"\025EFER-SV" /* Save MSR_EFER */
|
||||
"\026EFER-LD" /* Load MSR_EFER */
|
||||
"\027PTMR-SV" /* Save VMX-preemption timer value */
|
||||
);
|
||||
printf("\n Entry Controls=0x%b", mask,
|
||||
"\020"
|
||||
"\003DR" /* Save debug controls */
|
||||
/* Ignore IA-32e mode guest */
|
||||
/* Ignore Entry to SMM */
|
||||
/* Ignore Deactivate dual-monitor treatment */
|
||||
"\016PERF" /* Load MSR_PERF_GLOBAL_CTRL */
|
||||
"\017PAT" /* Load MSR_PAT */
|
||||
"\020EFER" /* Load MSR_EFER */
|
||||
);
|
||||
if (proc & PROCBASED_SECONDARY_CONTROLS &&
|
||||
(proc2 & (PROCBASED2_ENABLE_EPT | PROCBASED2_ENABLE_VPID)) != 0) {
|
||||
msr = rdmsr(MSR_VMX_EPT_VPID_CAP);
|
||||
mask = msr;
|
||||
printf("\n EPT Features=0x%b", mask,
|
||||
"\020"
|
||||
"\001XO" /* Execute-only translations */
|
||||
"\007PW4" /* Page-walk length of 4 */
|
||||
"\011UC" /* EPT paging-structure mem can be UC */
|
||||
"\017WB" /* EPT paging-structure mem can be WB */
|
||||
"\0212M" /* EPT PDE can map a 2-Mbyte page */
|
||||
"\0221G" /* EPT PDPTE can map a 1-Gbyte page */
|
||||
"\025INVEPT" /* INVEPT is supported */
|
||||
"\026AD" /* Accessed and dirty flags for EPT */
|
||||
"\032single" /* INVEPT single-context type */
|
||||
"\033all" /* INVEPT all-context type */
|
||||
);
|
||||
mask = msr >> 32;
|
||||
printf("\n VPID Features=0x%b", mask,
|
||||
"\020"
|
||||
"\001INVVPID" /* INVVPID is supported */
|
||||
"\011individual" /* INVVPID individual-address type */
|
||||
"\012single" /* INVVPID single-context type */
|
||||
"\013all" /* INVVPID all-context type */
|
||||
/* INVVPID single-context-retaining-globals type */
|
||||
"\014single-globals"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -149,8 +149,6 @@ SYSCTL_ULONG(_hw_vmm_vmx, OID_AUTO, cr4_ones_mask, CTLFLAG_RD,
|
||||
SYSCTL_ULONG(_hw_vmm_vmx, OID_AUTO, cr4_zeros_mask, CTLFLAG_RD,
|
||||
&cr4_zeros_mask, 0, NULL);
|
||||
|
||||
static int vmx_no_patmsr;
|
||||
|
||||
static int vmx_initialized;
|
||||
SYSCTL_INT(_hw_vmm_vmx, OID_AUTO, initialized, CTLFLAG_RD,
|
||||
&vmx_initialized, 0, "Intel VMX initialized");
|
||||
@ -158,18 +156,38 @@ SYSCTL_INT(_hw_vmm_vmx, OID_AUTO, initialized, CTLFLAG_RD,
|
||||
/*
|
||||
* Optional capabilities
|
||||
*/
|
||||
static SYSCTL_NODE(_hw_vmm_vmx, OID_AUTO, cap, CTLFLAG_RW, NULL, NULL);
|
||||
|
||||
static int vmx_patmsr;
|
||||
SYSCTL_INT(_hw_vmm_vmx_cap, OID_AUTO, patmsr, CTLFLAG_RD, &vmx_patmsr, 0,
|
||||
"PAT MSR saved and restored in VCMS");
|
||||
|
||||
static int cap_halt_exit;
|
||||
SYSCTL_INT(_hw_vmm_vmx_cap, OID_AUTO, halt_exit, CTLFLAG_RD, &cap_halt_exit, 0,
|
||||
"HLT triggers a VM-exit");
|
||||
|
||||
static int cap_pause_exit;
|
||||
SYSCTL_INT(_hw_vmm_vmx_cap, OID_AUTO, pause_exit, CTLFLAG_RD, &cap_pause_exit,
|
||||
0, "PAUSE triggers a VM-exit");
|
||||
|
||||
static int cap_unrestricted_guest;
|
||||
SYSCTL_INT(_hw_vmm_vmx_cap, OID_AUTO, unrestricted_guest, CTLFLAG_RD,
|
||||
&cap_unrestricted_guest, 0, "Unrestricted guests");
|
||||
|
||||
static int cap_monitor_trap;
|
||||
SYSCTL_INT(_hw_vmm_vmx_cap, OID_AUTO, monitor_trap, CTLFLAG_RD,
|
||||
&cap_monitor_trap, 0, "Monitor trap flag");
|
||||
|
||||
static int cap_invpcid;
|
||||
SYSCTL_INT(_hw_vmm_vmx_cap, OID_AUTO, invpcid, CTLFLAG_RD, &cap_invpcid,
|
||||
0, "Guests are allowed to use INVPCID");
|
||||
|
||||
static int virtual_interrupt_delivery;
|
||||
SYSCTL_INT(_hw_vmm_vmx, OID_AUTO, virtual_interrupt_delivery, CTLFLAG_RD,
|
||||
SYSCTL_INT(_hw_vmm_vmx_cap, OID_AUTO, virtual_interrupt_delivery, CTLFLAG_RD,
|
||||
&virtual_interrupt_delivery, 0, "APICv virtual interrupt delivery support");
|
||||
|
||||
static int posted_interrupts;
|
||||
SYSCTL_INT(_hw_vmm_vmx, OID_AUTO, posted_interrupts, CTLFLAG_RD,
|
||||
SYSCTL_INT(_hw_vmm_vmx_cap, OID_AUTO, posted_interrupts, CTLFLAG_RD,
|
||||
&posted_interrupts, 0, "APICv posted interrupt support");
|
||||
|
||||
static int pirvec;
|
||||
@ -618,6 +636,7 @@ vmx_init(int ipinum)
|
||||
}
|
||||
|
||||
/* Check support for VM-exit controls */
|
||||
vmx_patmsr = 1;
|
||||
error = vmx_set_ctlreg(MSR_VMX_EXIT_CTLS, MSR_VMX_TRUE_EXIT_CTLS,
|
||||
VM_EXIT_CTLS_ONE_SETTING,
|
||||
VM_EXIT_CTLS_ZERO_SETTING,
|
||||
@ -637,12 +656,12 @@ vmx_init(int ipinum)
|
||||
if (bootverbose)
|
||||
printf("vmm: PAT MSR access not supported\n");
|
||||
guest_msr_valid(MSR_PAT);
|
||||
vmx_no_patmsr = 1;
|
||||
vmx_patmsr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check support for VM-entry controls */
|
||||
if (!vmx_no_patmsr) {
|
||||
if (vmx_patmsr) {
|
||||
error = vmx_set_ctlreg(MSR_VMX_ENTRY_CTLS,
|
||||
MSR_VMX_TRUE_ENTRY_CTLS,
|
||||
VM_ENTRY_CTLS_ONE_SETTING,
|
||||
@ -918,7 +937,7 @@ vmx_vminit(struct vm *vm, pmap_t pmap)
|
||||
* MSR_PAT save/restore support, leave access disabled so accesses
|
||||
* will be trapped.
|
||||
*/
|
||||
if (!vmx_no_patmsr && guest_msr_rw(vmx, MSR_PAT))
|
||||
if (vmx_patmsr && guest_msr_rw(vmx, MSR_PAT))
|
||||
panic("vmx_vminit: error setting guest pat msr access");
|
||||
|
||||
vpid_alloc(vpid, VM_MAXCPU);
|
||||
|
@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/specialreg.h>
|
||||
|
||||
#include "vmx_msr.h"
|
||||
|
||||
|
@ -29,29 +29,6 @@
|
||||
#ifndef _VMX_MSR_H_
|
||||
#define _VMX_MSR_H_
|
||||
|
||||
#define MSR_VMX_BASIC 0x480
|
||||
#define MSR_VMX_EPT_VPID_CAP 0x48C
|
||||
|
||||
#define MSR_VMX_PROCBASED_CTLS 0x482
|
||||
#define MSR_VMX_TRUE_PROCBASED_CTLS 0x48E
|
||||
|
||||
#define MSR_VMX_PINBASED_CTLS 0x481
|
||||
#define MSR_VMX_TRUE_PINBASED_CTLS 0x48D
|
||||
|
||||
#define MSR_VMX_PROCBASED_CTLS2 0x48B
|
||||
|
||||
#define MSR_VMX_EXIT_CTLS 0x483
|
||||
#define MSR_VMX_TRUE_EXIT_CTLS 0x48f
|
||||
|
||||
#define MSR_VMX_ENTRY_CTLS 0x484
|
||||
#define MSR_VMX_TRUE_ENTRY_CTLS 0x490
|
||||
|
||||
#define MSR_VMX_CR0_FIXED0 0x486
|
||||
#define MSR_VMX_CR0_FIXED1 0x487
|
||||
|
||||
#define MSR_VMX_CR4_FIXED0 0x488
|
||||
#define MSR_VMX_CR4_FIXED1 0x489
|
||||
|
||||
uint32_t vmx_revision(void);
|
||||
|
||||
int vmx_set_ctlreg(int ctl_reg, int true_ctl_reg, uint32_t ones_mask,
|
||||
|
@ -435,6 +435,25 @@
|
||||
#define MSR_MC4_ADDR 0x412
|
||||
#define MSR_MC4_MISC 0x413
|
||||
|
||||
/*
|
||||
* VMX MSRs
|
||||
*/
|
||||
#define MSR_VMX_BASIC 0x480
|
||||
#define MSR_VMX_PINBASED_CTLS 0x481
|
||||
#define MSR_VMX_PROCBASED_CTLS 0x482
|
||||
#define MSR_VMX_EXIT_CTLS 0x483
|
||||
#define MSR_VMX_ENTRY_CTLS 0x484
|
||||
#define MSR_VMX_CR0_FIXED0 0x486
|
||||
#define MSR_VMX_CR0_FIXED1 0x487
|
||||
#define MSR_VMX_CR4_FIXED0 0x488
|
||||
#define MSR_VMX_CR4_FIXED1 0x489
|
||||
#define MSR_VMX_PROCBASED_CTLS2 0x48b
|
||||
#define MSR_VMX_EPT_VPID_CAP 0x48c
|
||||
#define MSR_VMX_TRUE_PINBASED_CTLS 0x48d
|
||||
#define MSR_VMX_TRUE_PROCBASED_CTLS 0x48e
|
||||
#define MSR_VMX_TRUE_EXIT_CTLS 0x48f
|
||||
#define MSR_VMX_TRUE_ENTRY_CTLS 0x490
|
||||
|
||||
/*
|
||||
* X2APIC MSRs
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user