| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  | #!/usr/bin/python | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # 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. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-08 09:29:43 -03:00
										 |  |  | from __future__ import print_function | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  | 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 | 
					
						
							| 
									
										
										
										
											2012-05-16 14:31:37 +03:00
										 |  |  | MSR_IA32_VMX_VMFUNC = 0x491 | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | class msr(object): | 
					
						
							|  |  |  |     def __init__(self): | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2017-02-21 09:29:34 +01:00
										 |  |  |             self.f = open('/dev/cpu/0/msr', 'rb', 0) | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  |         except: | 
					
						
							| 
									
										
										
										
											2017-02-21 09:29:34 +01:00
										 |  |  |             self.f = open('/dev/msr0', 'rb', 0) | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  |     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): | 
					
						
							| 
									
										
										
										
											2017-02-21 09:29:34 +01:00
										 |  |  |         print(self.name) | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  |         mbz, mb1 = self.read2(self.cap_msr) | 
					
						
							|  |  |  |         tmbz, tmb1 = 0, 0 | 
					
						
							|  |  |  |         if self.true_cap_msr: | 
					
						
							|  |  |  |             tmbz, tmb1 = self.read2(self.true_cap_msr) | 
					
						
							|  |  |  |         for bit in sorted(self.bits.keys()): | 
					
						
							|  |  |  |             zero = not (mbz & (1 << bit)) | 
					
						
							|  |  |  |             one = mb1 & (1 << bit) | 
					
						
							|  |  |  |             true_zero = not (tmbz & (1 << bit)) | 
					
						
							|  |  |  |             true_one = tmb1 & (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' | 
					
						
							| 
									
										
										
										
											2017-02-21 09:29:34 +01:00
										 |  |  |             print('  %-40s %s' % (self.bits[bit], s)) | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | class Misc(object): | 
					
						
							|  |  |  |     def __init__(self, name, bits, msr): | 
					
						
							|  |  |  |         self.name = name | 
					
						
							|  |  |  |         self.bits = bits | 
					
						
							|  |  |  |         self.msr = msr | 
					
						
							|  |  |  |     def show(self): | 
					
						
							| 
									
										
										
										
											2017-02-21 09:29:34 +01:00
										 |  |  |         print(self.name) | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  |         value = msr().read(self.msr, 0) | 
					
						
							| 
									
										
										
										
											2017-02-21 09:29:34 +01:00
										 |  |  |         print('  Hex: 0x%x' % (value)) | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  |         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) | 
					
						
							| 
									
										
										
										
											2017-02-21 09:29:34 +01:00
										 |  |  |             print('  %-40s %s' % (self.bits[bits], fmt(v))) | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | controls = [ | 
					
						
							| 
									
										
										
										
											2013-02-13 12:44:06 +01:00
										 |  |  |     Misc( | 
					
						
							|  |  |  |         name = 'Basic VMX Information', | 
					
						
							|  |  |  |         bits = { | 
					
						
							| 
									
										
										
										
											2014-09-17 20:54:11 +02:00
										 |  |  |             (0, 30): 'Revision', | 
					
						
							| 
									
										
										
										
											2013-02-13 12:44:06 +01:00
										 |  |  |             (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, | 
					
						
							|  |  |  |         ), | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  |     Control( | 
					
						
							|  |  |  |         name = 'pin-based controls', | 
					
						
							|  |  |  |         bits = { | 
					
						
							|  |  |  |             0: 'External interrupt exiting', | 
					
						
							|  |  |  |             3: 'NMI exiting', | 
					
						
							|  |  |  |             5: 'Virtual NMIs', | 
					
						
							|  |  |  |             6: 'Activate VMX-preemption timer', | 
					
						
							| 
									
										
										
										
											2013-02-13 12:44:06 +01:00
										 |  |  |             7: 'Process posted interrupts', | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  |             }, | 
					
						
							|  |  |  |         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', | 
					
						
							|  |  |  |             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', | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:54 +01:00
										 |  |  |             3: 'Enable RDTSCP', | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  |             4: 'Virtualize x2APIC mode', | 
					
						
							|  |  |  |             5: 'Enable VPID', | 
					
						
							|  |  |  |             6: 'WBINVD exiting', | 
					
						
							|  |  |  |             7: 'Unrestricted guest', | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:54 +01:00
										 |  |  |             8: 'APIC register emulation', | 
					
						
							| 
									
										
										
										
											2013-01-10 23:02:48 -02:00
										 |  |  |             9: 'Virtual interrupt delivery', | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  |             10: 'PAUSE-loop exiting', | 
					
						
							| 
									
										
										
										
											2012-05-16 14:31:37 +03:00
										 |  |  |             11: 'RDRAND exiting', | 
					
						
							|  |  |  |             12: 'Enable INVPCID', | 
					
						
							|  |  |  |             13: 'Enable VM functions', | 
					
						
							| 
									
										
										
										
											2013-03-17 11:45:50 +01:00
										 |  |  |             14: 'VMCS shadowing', | 
					
						
							| 
									
										
										
										
											2017-02-21 09:35:45 +01:00
										 |  |  |             15: 'Enable ENCLS exiting', | 
					
						
							| 
									
										
										
										
											2014-09-17 20:54:11 +02:00
										 |  |  |             16: 'RDSEED exiting', | 
					
						
							| 
									
										
										
										
											2017-02-21 09:35:45 +01:00
										 |  |  |             17: 'Enable PML', | 
					
						
							| 
									
										
										
										
											2014-09-17 20:54:11 +02:00
										 |  |  |             18: 'EPT-violation #VE', | 
					
						
							| 
									
										
										
										
											2017-02-21 09:35:45 +01:00
										 |  |  |             19: 'Conceal non-root operation from PT', | 
					
						
							| 
									
										
										
										
											2014-09-17 20:54:11 +02:00
										 |  |  |             20: 'Enable XSAVES/XRSTORS', | 
					
						
							| 
									
										
										
										
											2017-02-21 09:35:45 +01:00
										 |  |  |             22: 'Mode-based execute control (XS/XU)', | 
					
						
							| 
									
										
										
										
											2016-08-25 23:10:25 -04:00
										 |  |  |             25: 'TSC scaling', | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  |             }, | 
					
						
							|  |  |  |         cap_msr = MSR_IA32_VMX_PROCBASED_CTLS2, | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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', | 
					
						
							| 
									
										
										
										
											2017-02-21 09:35:45 +01:00
										 |  |  |             23: 'Clear IA32_BNDCFGS', | 
					
						
							|  |  |  |             24: 'Conceal VM exits from PT', | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  |             }, | 
					
						
							|  |  |  |         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', | 
					
						
							| 
									
										
										
										
											2014-09-17 20:54:11 +02:00
										 |  |  |             9: 'IA-32e mode guest', | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  |             10: 'Entry to SMM', | 
					
						
							|  |  |  |             11: 'Deactivate dual-monitor treatment', | 
					
						
							|  |  |  |             13: 'Load IA32_PERF_GLOBAL_CTRL', | 
					
						
							|  |  |  |             14: 'Load IA32_PAT', | 
					
						
							|  |  |  |             15: 'Load IA32_EFER', | 
					
						
							| 
									
										
										
										
											2017-02-21 09:35:45 +01:00
										 |  |  |             16: 'Load IA32_BNDCFGS', | 
					
						
							|  |  |  |             17: 'Conceal VM entries from PT', | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  |             }, | 
					
						
							|  |  |  |         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', | 
					
						
							| 
									
										
										
										
											2013-03-17 11:45:50 +01:00
										 |  |  |             15: 'IA32_SMBASE support', | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  |             (16,24): 'Number of CR3-target values', | 
					
						
							| 
									
										
										
										
											2014-09-17 20:54:11 +02:00
										 |  |  |             (25,27): 'MSR-load/store count recommendation', | 
					
						
							| 
									
										
										
										
											2012-05-16 14:31:37 +03:00
										 |  |  |             28: 'IA32_SMM_MONITOR_CTL[2] can be set to 1', | 
					
						
							| 
									
										
										
										
											2013-03-17 11:45:50 +01:00
										 |  |  |             29: 'VMWRITE to VM-exit information fields', | 
					
						
							| 
									
										
										
										
											2017-02-21 09:35:45 +01:00
										 |  |  |             30: 'Inject event with insn length=0', | 
					
						
							| 
									
										
										
										
											2013-03-17 11:45:50 +01:00
										 |  |  |             (32,63): 'MSEG revision identifier', | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  |             }, | 
					
						
							|  |  |  |         msr = MSR_IA32_VMX_MISC_CTLS, | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Misc( | 
					
						
							|  |  |  |         name = 'VPID and EPT capabilities', | 
					
						
							|  |  |  |         bits = { | 
					
						
							|  |  |  |             0: 'Execute-only EPT translations', | 
					
						
							|  |  |  |             6: 'Page-walk length 4', | 
					
						
							|  |  |  |             8: 'Paging-structure memory type UC', | 
					
						
							|  |  |  |             14: 'Paging-structure memory type WB', | 
					
						
							|  |  |  |             16: '2MB EPT pages', | 
					
						
							|  |  |  |             17: '1GB EPT pages', | 
					
						
							|  |  |  |             20: 'INVEPT supported', | 
					
						
							| 
									
										
										
										
											2012-05-16 14:31:37 +03:00
										 |  |  |             21: 'EPT accessed and dirty flags', | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  |             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, | 
					
						
							|  |  |  |         ), | 
					
						
							| 
									
										
										
										
											2012-05-16 14:31:37 +03:00
										 |  |  |     Misc( | 
					
						
							|  |  |  |         name = 'VM Functions', | 
					
						
							|  |  |  |         bits = { | 
					
						
							|  |  |  |             0: 'EPTP Switching', | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         msr = MSR_IA32_VMX_VMFUNC, | 
					
						
							|  |  |  |         ), | 
					
						
							| 
									
										
										
										
											2011-10-07 09:37:57 +02:00
										 |  |  |     ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | for c in controls: | 
					
						
							|  |  |  |     c.show() |