]>
Commit | Line | Data |
---|---|---|
5f6caa4f JK |
1 | #!/usr/bin/python |
2 | # | |
3 | # tool for querying VMX capabilities | |
4 | # | |
5 | # Copyright 2009-2010 Red Hat, Inc. | |
6 | # | |
7 | # Authors: | |
8 | # Avi Kivity <avi@redhat.com> | |
9 | # | |
10 | # This work is licensed under the terms of the GNU GPL, version 2. See | |
11 | # the COPYING file in the top-level directory. | |
12 | ||
13 | MSR_IA32_VMX_BASIC = 0x480 | |
14 | MSR_IA32_VMX_PINBASED_CTLS = 0x481 | |
15 | MSR_IA32_VMX_PROCBASED_CTLS = 0x482 | |
16 | MSR_IA32_VMX_EXIT_CTLS = 0x483 | |
17 | MSR_IA32_VMX_ENTRY_CTLS = 0x484 | |
18 | MSR_IA32_VMX_MISC_CTLS = 0x485 | |
19 | MSR_IA32_VMX_PROCBASED_CTLS2 = 0x48B | |
20 | MSR_IA32_VMX_EPT_VPID_CAP = 0x48C | |
21 | MSR_IA32_VMX_TRUE_PINBASED_CTLS = 0x48D | |
22 | MSR_IA32_VMX_TRUE_PROCBASED_CTLS = 0x48E | |
23 | MSR_IA32_VMX_TRUE_EXIT_CTLS = 0x48F | |
24 | MSR_IA32_VMX_TRUE_ENTRY_CTLS = 0x490 | |
287d55c6 | 25 | MSR_IA32_VMX_VMFUNC = 0x491 |
5f6caa4f JK |
26 | |
27 | class msr(object): | |
28 | def __init__(self): | |
29 | try: | |
c3e31eaa | 30 | self.f = open('/dev/cpu/0/msr', 'rb', 0) |
5f6caa4f | 31 | except: |
c3e31eaa | 32 | self.f = open('/dev/msr0', 'rb', 0) |
5f6caa4f JK |
33 | def read(self, index, default = None): |
34 | import struct | |
35 | self.f.seek(index) | |
36 | try: | |
37 | return struct.unpack('Q', self.f.read(8))[0] | |
38 | except: | |
39 | return default | |
40 | ||
41 | class Control(object): | |
42 | def __init__(self, name, bits, cap_msr, true_cap_msr = None): | |
43 | self.name = name | |
44 | self.bits = bits | |
45 | self.cap_msr = cap_msr | |
46 | self.true_cap_msr = true_cap_msr | |
47 | def read2(self, nr): | |
48 | m = msr() | |
49 | val = m.read(nr, 0) | |
50 | return (val & 0xffffffff, val >> 32) | |
51 | def show(self): | |
c3e31eaa | 52 | print(self.name) |
5f6caa4f JK |
53 | mbz, mb1 = self.read2(self.cap_msr) |
54 | tmbz, tmb1 = 0, 0 | |
55 | if self.true_cap_msr: | |
56 | tmbz, tmb1 = self.read2(self.true_cap_msr) | |
57 | for bit in sorted(self.bits.keys()): | |
58 | zero = not (mbz & (1 << bit)) | |
59 | one = mb1 & (1 << bit) | |
60 | true_zero = not (tmbz & (1 << bit)) | |
61 | true_one = tmb1 & (1 << bit) | |
62 | s= '?' | |
63 | if (self.true_cap_msr and true_zero and true_one | |
64 | and one and not zero): | |
65 | s = 'default' | |
66 | elif zero and not one: | |
67 | s = 'no' | |
68 | elif one and not zero: | |
69 | s = 'forced' | |
70 | elif one and zero: | |
71 | s = 'yes' | |
c3e31eaa | 72 | print(' %-40s %s' % (self.bits[bit], s)) |
5f6caa4f JK |
73 | |
74 | class Misc(object): | |
75 | def __init__(self, name, bits, msr): | |
76 | self.name = name | |
77 | self.bits = bits | |
78 | self.msr = msr | |
79 | def show(self): | |
c3e31eaa | 80 | print(self.name) |
5f6caa4f | 81 | value = msr().read(self.msr, 0) |
c3e31eaa | 82 | print(' Hex: 0x%x' % (value)) |
5f6caa4f JK |
83 | def first_bit(key): |
84 | if type(key) is tuple: | |
85 | return key[0] | |
86 | else: | |
87 | return key | |
88 | for bits in sorted(self.bits.keys(), key = first_bit): | |
89 | if type(bits) is tuple: | |
90 | lo, hi = bits | |
91 | fmt = int | |
92 | else: | |
93 | lo = hi = bits | |
94 | def fmt(x): | |
95 | return { True: 'yes', False: 'no' }[x] | |
96 | v = (value >> lo) & ((1 << (hi - lo + 1)) - 1) | |
c3e31eaa | 97 | print(' %-40s %s' % (self.bits[bits], fmt(v))) |
5f6caa4f JK |
98 | |
99 | controls = [ | |
ea4ee283 JK |
100 | Misc( |
101 | name = 'Basic VMX Information', | |
102 | bits = { | |
c5d1e2cc | 103 | (0, 30): 'Revision', |
ea4ee283 JK |
104 | (32,44): 'VMCS size', |
105 | 48: 'VMCS restricted to 32 bit addresses', | |
106 | 49: 'Dual-monitor support', | |
107 | (50, 53): 'VMCS memory type', | |
108 | 54: 'INS/OUTS instruction information', | |
109 | 55: 'IA32_VMX_TRUE_*_CTLS support', | |
110 | }, | |
111 | msr = MSR_IA32_VMX_BASIC, | |
112 | ), | |
5f6caa4f JK |
113 | Control( |
114 | name = 'pin-based controls', | |
115 | bits = { | |
116 | 0: 'External interrupt exiting', | |
117 | 3: 'NMI exiting', | |
118 | 5: 'Virtual NMIs', | |
119 | 6: 'Activate VMX-preemption timer', | |
ea4ee283 | 120 | 7: 'Process posted interrupts', |
5f6caa4f JK |
121 | }, |
122 | cap_msr = MSR_IA32_VMX_PINBASED_CTLS, | |
123 | true_cap_msr = MSR_IA32_VMX_TRUE_PINBASED_CTLS, | |
124 | ), | |
125 | ||
126 | Control( | |
127 | name = 'primary processor-based controls', | |
128 | bits = { | |
129 | 2: 'Interrupt window exiting', | |
130 | 3: 'Use TSC offsetting', | |
131 | 7: 'HLT exiting', | |
132 | 9: 'INVLPG exiting', | |
133 | 10: 'MWAIT exiting', | |
134 | 11: 'RDPMC exiting', | |
135 | 12: 'RDTSC exiting', | |
136 | 15: 'CR3-load exiting', | |
137 | 16: 'CR3-store exiting', | |
138 | 19: 'CR8-load exiting', | |
139 | 20: 'CR8-store exiting', | |
140 | 21: 'Use TPR shadow', | |
141 | 22: 'NMI-window exiting', | |
142 | 23: 'MOV-DR exiting', | |
143 | 24: 'Unconditional I/O exiting', | |
144 | 25: 'Use I/O bitmaps', | |
145 | 27: 'Monitor trap flag', | |
146 | 28: 'Use MSR bitmaps', | |
147 | 29: 'MONITOR exiting', | |
148 | 30: 'PAUSE exiting', | |
149 | 31: 'Activate secondary control', | |
150 | }, | |
151 | cap_msr = MSR_IA32_VMX_PROCBASED_CTLS, | |
152 | true_cap_msr = MSR_IA32_VMX_TRUE_PROCBASED_CTLS, | |
153 | ), | |
154 | ||
155 | Control( | |
156 | name = 'secondary processor-based controls', | |
157 | bits = { | |
158 | 0: 'Virtualize APIC accesses', | |
159 | 1: 'Enable EPT', | |
160 | 2: 'Descriptor-table exiting', | |
614413f7 | 161 | 3: 'Enable RDTSCP', |
5f6caa4f JK |
162 | 4: 'Virtualize x2APIC mode', |
163 | 5: 'Enable VPID', | |
164 | 6: 'WBINVD exiting', | |
165 | 7: 'Unrestricted guest', | |
614413f7 | 166 | 8: 'APIC register emulation', |
f9e90c79 | 167 | 9: 'Virtual interrupt delivery', |
5f6caa4f | 168 | 10: 'PAUSE-loop exiting', |
287d55c6 AK |
169 | 11: 'RDRAND exiting', |
170 | 12: 'Enable INVPCID', | |
171 | 13: 'Enable VM functions', | |
007e986f | 172 | 14: 'VMCS shadowing', |
025533f6 | 173 | 15: 'Enable ENCLS exiting', |
c5d1e2cc | 174 | 16: 'RDSEED exiting', |
025533f6 | 175 | 17: 'Enable PML', |
c5d1e2cc | 176 | 18: 'EPT-violation #VE', |
025533f6 | 177 | 19: 'Conceal non-root operation from PT', |
c5d1e2cc | 178 | 20: 'Enable XSAVES/XRSTORS', |
025533f6 | 179 | 22: 'Mode-based execute control (XS/XU)', |
349cb2fb | 180 | 25: 'TSC scaling', |
5f6caa4f JK |
181 | }, |
182 | cap_msr = MSR_IA32_VMX_PROCBASED_CTLS2, | |
183 | ), | |
184 | ||
185 | Control( | |
186 | name = 'VM-Exit controls', | |
187 | bits = { | |
188 | 2: 'Save debug controls', | |
189 | 9: 'Host address-space size', | |
190 | 12: 'Load IA32_PERF_GLOBAL_CTRL', | |
191 | 15: 'Acknowledge interrupt on exit', | |
192 | 18: 'Save IA32_PAT', | |
193 | 19: 'Load IA32_PAT', | |
194 | 20: 'Save IA32_EFER', | |
195 | 21: 'Load IA32_EFER', | |
196 | 22: 'Save VMX-preemption timer value', | |
025533f6 PB |
197 | 23: 'Clear IA32_BNDCFGS', |
198 | 24: 'Conceal VM exits from PT', | |
5f6caa4f JK |
199 | }, |
200 | cap_msr = MSR_IA32_VMX_EXIT_CTLS, | |
201 | true_cap_msr = MSR_IA32_VMX_TRUE_EXIT_CTLS, | |
202 | ), | |
203 | ||
204 | Control( | |
205 | name = 'VM-Entry controls', | |
206 | bits = { | |
207 | 2: 'Load debug controls', | |
c5d1e2cc | 208 | 9: 'IA-32e mode guest', |
5f6caa4f JK |
209 | 10: 'Entry to SMM', |
210 | 11: 'Deactivate dual-monitor treatment', | |
211 | 13: 'Load IA32_PERF_GLOBAL_CTRL', | |
212 | 14: 'Load IA32_PAT', | |
213 | 15: 'Load IA32_EFER', | |
025533f6 PB |
214 | 16: 'Load IA32_BNDCFGS', |
215 | 17: 'Conceal VM entries from PT', | |
5f6caa4f JK |
216 | }, |
217 | cap_msr = MSR_IA32_VMX_ENTRY_CTLS, | |
218 | true_cap_msr = MSR_IA32_VMX_TRUE_ENTRY_CTLS, | |
219 | ), | |
220 | ||
221 | Misc( | |
222 | name = 'Miscellaneous data', | |
223 | bits = { | |
224 | (0,4): 'VMX-preemption timer scale (log2)', | |
225 | 5: 'Store EFER.LMA into IA-32e mode guest control', | |
226 | 6: 'HLT activity state', | |
227 | 7: 'Shutdown activity state', | |
228 | 8: 'Wait-for-SIPI activity state', | |
007e986f | 229 | 15: 'IA32_SMBASE support', |
5f6caa4f | 230 | (16,24): 'Number of CR3-target values', |
c5d1e2cc | 231 | (25,27): 'MSR-load/store count recommendation', |
287d55c6 | 232 | 28: 'IA32_SMM_MONITOR_CTL[2] can be set to 1', |
007e986f | 233 | 29: 'VMWRITE to VM-exit information fields', |
025533f6 | 234 | 30: 'Inject event with insn length=0', |
007e986f | 235 | (32,63): 'MSEG revision identifier', |
5f6caa4f JK |
236 | }, |
237 | msr = MSR_IA32_VMX_MISC_CTLS, | |
238 | ), | |
239 | ||
240 | Misc( | |
241 | name = 'VPID and EPT capabilities', | |
242 | bits = { | |
243 | 0: 'Execute-only EPT translations', | |
244 | 6: 'Page-walk length 4', | |
245 | 8: 'Paging-structure memory type UC', | |
246 | 14: 'Paging-structure memory type WB', | |
247 | 16: '2MB EPT pages', | |
248 | 17: '1GB EPT pages', | |
249 | 20: 'INVEPT supported', | |
287d55c6 | 250 | 21: 'EPT accessed and dirty flags', |
5f6caa4f JK |
251 | 25: 'Single-context INVEPT', |
252 | 26: 'All-context INVEPT', | |
253 | 32: 'INVVPID supported', | |
254 | 40: 'Individual-address INVVPID', | |
255 | 41: 'Single-context INVVPID', | |
256 | 42: 'All-context INVVPID', | |
257 | 43: 'Single-context-retaining-globals INVVPID', | |
258 | }, | |
259 | msr = MSR_IA32_VMX_EPT_VPID_CAP, | |
260 | ), | |
287d55c6 AK |
261 | Misc( |
262 | name = 'VM Functions', | |
263 | bits = { | |
264 | 0: 'EPTP Switching', | |
265 | }, | |
266 | msr = MSR_IA32_VMX_VMFUNC, | |
267 | ), | |
5f6caa4f JK |
268 | ] |
269 | ||
270 | for c in controls: | |
271 | c.show() |