#!/usr/bin/env python3
#
# tool for querying VMX capabilities
#
# Copyright 2009-2010 Red Hat, Inc.
#
# Authors:
# Avi Kivity <avi@redhat.com>
#
# This work is licensed under the terms of the GNU GPL, version 2. See
# the COPYING file in the top-level directory.
MSR_IA32_VMX_BASIC = 0x480
MSR_IA32_VMX_PINBASED_CTLS = 0x481
MSR_IA32_VMX_PROCBASED_CTLS = 0x482
MSR_IA32_VMX_EXIT_CTLS = 0x483
MSR_IA32_VMX_ENTRY_CTLS = 0x484
MSR_IA32_VMX_MISC_CTLS = 0x485
MSR_IA32_VMX_PROCBASED_CTLS2 = 0x48B
MSR_IA32_VMX_EPT_VPID_CAP = 0x48C
MSR_IA32_VMX_TRUE_PINBASED_CTLS = 0x48D
MSR_IA32_VMX_TRUE_PROCBASED_CTLS = 0x48E
MSR_IA32_VMX_TRUE_EXIT_CTLS = 0x48F
MSR_IA32_VMX_TRUE_ENTRY_CTLS = 0x490
MSR_IA32_VMX_VMFUNC = 0x491
MSR_IA32_VMX_PROCBASED_CTLS3 = 0x492
class msr(object):
def __init__(self):
try:
self.f = open('/dev/cpu/0/msr', 'rb', 0)
except:
self.f = open('/dev/msr0', 'rb', 0)
def read(self, index, default = None):
import struct
self.f.seek(index)
try:
return struct.unpack('Q', self.f.read(8))[0]
except:
return default
class Control(object):
def __init__(self, name, bits, cap_msr, true_cap_msr = None):
self.name = name
self.bits = bits
self.cap_msr = cap_msr
self.true_cap_msr = true_cap_msr
def read2(self, nr):
m = msr()
val = m.read(nr, 0)
return (val & 0xffffffff, val >> 32)
def show(self):
print(self.name)
mb1, cb1 = self.read2(self.cap_msr)
tmb1, tcb1 = 0, 0
if self.true_cap_msr:
tmb1, tcb1 = self.read2(self.true_cap_msr)
for bit in sorted(self.bits.keys()):
zero = not (mb1 & (1 << bit))
one = cb1 & (1 << bit)
true_zero = not (tmb1 & (1 << bit))
true_one = tcb1 & (1 << bit)
s= '?'
if (self.true_cap_msr and true_zero and true_one
and one and not zero):
s = 'default'
elif zero and not one:
s = 'no'
elif one and not zero:
s = 'forced'
elif one and zero:
s = 'yes'
print(' %-40s %s' % (self.bits[bit], s))
# All 64 bits in the tertiary controls MSR are allowed-1
class Allowed1Control(Control):
def read2(self, nr):
m = msr()
val = m.read(nr, 0)
return (0, val)
class Misc(object):
def __init__(self, name, bits, msr):
self.name = name
self.bits = bits
self.msr = msr
def show(self):
print(self.name)
value = msr().read(self.msr, 0)
print(' Hex: 0x%x' % (value))
def first_bit(key):
if type(key) is tuple:
return key[0]
else:
return key
for bits in sorted(self.bits.keys(), key = first_bit):
if type(bits) is tuple:
lo, hi = bits
fmt = int
else:
lo = hi = bits
def fmt(x):
return { True: 'yes', False: 'no' }[x]
v = (value >> lo) & ((1 << (hi - lo + 1)) - 1)
print(' %-40s %s' % (self.bits[bits], fmt(v)))
controls = [
Misc(
name = 'Basic VMX Information',
bits = {
(0, 30): 'Revision',
(32,44): 'VMCS size',
48: 'VMCS restricted to 32 bit addresses',
49: 'Dual-monitor support',
(50, 53): 'VMCS memory type',
54: 'INS/OUTS instruction information',
55: 'IA32_VMX_TRUE_*_CTLS support',
},
msr = MSR_IA32_VMX_BASIC,
),
Control(
name = 'pin-based controls',
bits = {
0: 'External interrupt exiting',
3: 'NMI exiting',
5: 'Virtual NMIs',
6: 'Activate VMX-preemption timer',
7: 'Process posted interrupts',
},
cap_msr = MSR_IA32_VMX_PINBASED_CTLS,
true_cap_msr = MSR_IA32_VMX_TRUE_PINBASED_CTLS,
),
Control(
name = 'primary processor-based controls',
bits = {
2: 'Interrupt window exiting',
3: 'Use TSC offsetting',
7: 'HLT exiting',
9: 'INVLPG exiting',
10: 'MWAIT exiting',
11: 'RDPMC exiting',
12: 'RDTSC exiting',
15: 'CR3-load exiting',
16: 'CR3-store exiting',
17: 'Activate tertiary controls',
19: 'CR8-load exiting',
20: 'CR8-store exiting',
21: 'Use TPR shadow',
22: 'NMI-window exiting',
23: 'MOV-DR exiting',
24: 'Unconditional I/O exiting',
25: 'Use I/O bitmaps',
27: 'Monitor trap flag',
28: 'Use MSR bitmaps',
29: 'MONITOR exiting',
30: 'PAUSE exiting',
31: 'Activate secondary control',
},
cap_msr = MSR_IA32_VMX_PROCBASED_CTLS,
true_cap_msr = MSR_IA32_VMX_TRUE_PROCBASED_CTLS,
),
Control(
name = 'secondary processor-based controls',
bits = {
0: 'Virtualize APIC accesses',
1: 'Enable EPT',
2: 'Descriptor-table exiting',
3: 'Enable RDTSCP',
4: 'Virtualize x2APIC mode',
5: 'Enable VPID',
6: 'WBINVD exiting',
7: 'Unrestricted guest',
8: 'APIC register emulation',
9: 'Virtual interrupt delivery',
10: 'PAUSE-loop exiting',
11: 'RDRAND exiting',
12: 'Enable INVPCID',
13: 'Enable VM functions',
14: 'VMCS shadowing',
15: 'Enable ENCLS exiting',
16: 'RDSEED exiting',
17: 'Enable PML',
18: 'EPT-violation #VE',
19: 'Conceal non-root operation from PT',
20: 'Enable XSAVES/XRSTORS',
22: 'Mode-based execute control (XS/XU)',
23: 'Sub-page write permissions',
24: 'GPA translation for PT',
25: 'TSC scaling',
26: 'User wait and pause',
28: 'ENCLV exiting',
},
cap_msr = MSR_IA32_VMX_PROCBASED_CTLS2,
),
Allowed1Control(
name = 'tertiary processor-based controls',
bits = {
4: 'Enable IPI virtualization'
},
cap_msr = MSR_IA32_VMX_PROCBASED_CTLS3,
),
Control(
name = 'VM-Exit controls',
bits = {
2: 'Save debug controls',
9: 'Host address-space size',
12: 'Load IA32_PERF_GLOBAL_CTRL',
15: 'Acknowledge interrupt on exit',
18: 'Save IA32_PAT',
19: 'Load IA32_PAT',
20: 'Save IA32_EFER',
21: 'Load IA32_EFER',
22: 'Save VMX-preemption timer value',
23: 'Clear IA32_BNDCFGS',
24: 'Conceal VM exits from PT',
25: 'Clear IA32_RTIT_CTL',
},
cap_msr = MSR_IA32_VMX_EXIT_CTLS,
true_cap_msr = MSR_IA32_VMX_TRUE_EXIT_CTLS,
),
Control(
name = 'VM-Entry controls',
bits = {
2: 'Load debug controls',
9: 'IA-32e mode guest',
10: 'Entry to SMM',
11: 'Deactivate dual-monitor treatment',
13: 'Load IA32_PERF_GLOBAL_CTRL',
14: 'Load IA32_PAT',
15: 'Load IA32_EFER',
16: 'Load IA32_BNDCFGS',
17: 'Conceal VM entries from PT',
18: 'Load IA32_RTIT_CTL',
},
cap_msr = MSR_IA32_VMX_ENTRY_CTLS,
true_cap_msr = MSR_IA32_VMX_TRUE_ENTRY_CTLS,
),
Misc(
name = 'Miscellaneous data',
bits = {
(0,4): 'VMX-preemption timer scale (log2)',
5: 'Store EFER.LMA into IA-32e mode guest control',
6: 'HLT activity state',
7: 'Shutdown activity state',
8: 'Wait-for-SIPI activity state',
14: 'PT in VMX operation',
15: 'IA32_SMBASE support',
(16,24): 'Number of CR3-target values',
(25,27): 'MSR-load/store count recommendation',
28: 'IA32_SMM_MONITOR_CTL[2] can be set to 1',
29: 'VMWRITE to VM-exit information fields',
30: 'Inject event with insn length=0',
(32,63): 'MSEG revision identifier',
},
msr = MSR_IA32_VMX_MISC_CTLS,
),
Misc(
name = 'VPID and EPT capabilities',
bits = {
0: 'Execute-only EPT translations',
6: 'Page-walk length 4',
7: 'Page-walk length 5',
8: 'Paging-structure memory type UC',
14: 'Paging-structure memory type WB',
16: '2MB EPT pages',
17: '1GB EPT pages',
20: 'INVEPT supported',
21: 'EPT accessed and dirty flags',
22: 'Advanced VM-exit information for EPT violations',
25: 'Single-context INVEPT',
26: 'All-context INVEPT',
32: 'INVVPID supported',
40: 'Individual-address INVVPID',
41: 'Single-context INVVPID',
42: 'All-context INVVPID',
43: 'Single-context-retaining-globals INVVPID',
},
msr = MSR_IA32_VMX_EPT_VPID_CAP,
),
Misc(
name = 'VM Functions',
bits = {
0: 'EPTP Switching',
},
msr = MSR_IA32_VMX_VMFUNC,
),
]
if __name__ == '__main__':
for c in controls:
c.show()