mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-05-31 11:25:30 +00:00
config_tools: board_inspector: refactors MSR utilities
In v3.0 the msrfield class has its initializer changed in a way that is incompatible with the parameter names or the getter/setter. When introduced from the BITS project, that class allows specifying an MSR field of arbitrary length by being given the index of the most and least significant bits. This patch restores the original behavior of that msrfield class and moves the use-case specific methods, namely is_vmx_cap_supported and is_ctrl_setting_allowed, to a helper class. Parsing of the VMX capability reporting MSRs in msr.py are updated accordingly, and brief documentation of the MSR fields are added as well. Tracked-On: #7948 Signed-off-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
parent
4369896549
commit
a6614e7e2f
@ -7,7 +7,7 @@ from cpuparser.platformbase import MSR, msrfield
|
||||
|
||||
class MSR_IA32_MISC_ENABLE(MSR):
|
||||
addr = 0x1a0
|
||||
fast_string = msrfield(1, 0, doc=None)
|
||||
fast_string = msrfield(0, 0, doc="Fast-strings enable")
|
||||
|
||||
capability_bits = [
|
||||
"fast_string",
|
||||
@ -15,39 +15,76 @@ class MSR_IA32_MISC_ENABLE(MSR):
|
||||
|
||||
class MSR_IA32_FEATURE_CONTROL(MSR):
|
||||
addr = 0x03a
|
||||
msr_ia32_feature_control_lock = msrfield(1, 0, doc=None)
|
||||
msr_ia32_feature_control_vmx_no_smx = msrfield(1, 2, doc=None)
|
||||
lock = msrfield(0, 0, doc="Lock bit")
|
||||
vmx_outside_smx = msrfield(2, 2, doc="Enable VMX outside SMX operation")
|
||||
|
||||
@property
|
||||
def disable_vmx(self):
|
||||
return self.msr_ia32_feature_control_lock and not self.msr_ia32_feature_control_vmx_no_smx
|
||||
return self.lock and not self.vmx_outside_smx
|
||||
|
||||
capability_bits = [
|
||||
"disable_vmx",
|
||||
]
|
||||
|
||||
class MSR_IA32_VMX_PROCBASED_CTLS2(MSR):
|
||||
class VMXCapabilityReportingMSR(MSR):
|
||||
def get_field_idx(self, field):
|
||||
if isinstance(field, int):
|
||||
return field
|
||||
if isinstance(field, str):
|
||||
return getattr(type(self), field).lsb
|
||||
assert False, f"Invalid field type: {field}, {type(field)}"
|
||||
|
||||
def allows_0_setting(self, field):
|
||||
field_idx = self.get_field_idx(field)
|
||||
if field_idx >= 32:
|
||||
return False
|
||||
|
||||
bit_mask = (1 << field_idx)
|
||||
return (self.value & bit_mask) == 0
|
||||
|
||||
def allows_1_setting(self, field):
|
||||
field_idx = self.get_field_idx(field)
|
||||
if field_idx >= 32:
|
||||
return False
|
||||
|
||||
bit_mask = (1 << field_idx)
|
||||
high = self.value >> 32
|
||||
return (high & bit_mask) == bit_mask
|
||||
|
||||
def allows_flexible_setting(self, field):
|
||||
field_idx = self.get_field_idx(field)
|
||||
return self.allows_0_setting(field_idx) and self.allows_1_setting(field_idx)
|
||||
|
||||
class MSR_IA32_VMX_PROCBASED_CTLS2(VMXCapabilityReportingMSR):
|
||||
addr = 0x0000048B
|
||||
|
||||
vapic_access = msrfield(0, 0, doc="Virtualize APIC accesses")
|
||||
ept = msrfield(1, 1, doc="Enable EPT")
|
||||
rdtscp = msrfield(3, 3, doc="Enable RDTSCP")
|
||||
vx2apic = msrfield(4, 4, doc="Virtualize x2APIC mode")
|
||||
vpid = msrfield(5, 5, doc="Enable VPID")
|
||||
unrestricted_guest = msrfield(7, 7, doc="Unrestricted guest")
|
||||
apic_reg_virt = msrfield(8, 8, doc="APIC-register virtualization")
|
||||
|
||||
@property
|
||||
def vmx_procbased_ctls2_vapic(self):
|
||||
return msrfield.is_vmx_cap_supported(self, 1 << 0)
|
||||
return self.allows_flexible_setting("vapic_access")
|
||||
|
||||
@property
|
||||
def vmx_procbased_ctls2_ept(self):
|
||||
return msrfield.is_vmx_cap_supported(self, 1 << 1)
|
||||
return self.allows_flexible_setting("ept")
|
||||
|
||||
@property
|
||||
def vmx_procbased_ctls2_vpid(self):
|
||||
return msrfield.is_vmx_cap_supported(self, 1 << 5)
|
||||
return self.allows_flexible_setting("vpid")
|
||||
|
||||
@property
|
||||
def vmx_procbased_ctls2_rdtscp(self):
|
||||
return msrfield.is_vmx_cap_supported(self, 1 << 3)
|
||||
return self.allows_flexible_setting("rdtscp")
|
||||
|
||||
@property
|
||||
def vmx_procbased_ctls2_unrestrict(self):
|
||||
return msrfield.is_vmx_cap_supported(self, 1 << 7)
|
||||
return self.allows_flexible_setting("unrestricted_guest")
|
||||
|
||||
capability_bits = [
|
||||
"vmx_procbased_ctls2_vapic",
|
||||
@ -57,82 +94,69 @@ class MSR_IA32_VMX_PROCBASED_CTLS2(MSR):
|
||||
"vmx_procbased_ctls2_unrestrict",
|
||||
]
|
||||
|
||||
class MSR_IA32_VMX_PINBASED_CTLS(MSR):
|
||||
class MSR_IA32_VMX_PINBASED_CTLS(VMXCapabilityReportingMSR):
|
||||
addr = 0x00000481
|
||||
|
||||
irq_exiting = msrfield(0, 0, doc="External-interrupt existing")
|
||||
|
||||
@property
|
||||
def vmx_pinbased_ctls_irq_exit(self):
|
||||
return msrfield.is_vmx_cap_supported(self, 1 << 0)
|
||||
return self.allows_flexible_setting("irq_exiting")
|
||||
|
||||
capability_bits = [
|
||||
"vmx_pinbased_ctls_irq_exit",
|
||||
]
|
||||
|
||||
class MSR_IA32_VMX_PROCBASED_CTLS(MSR):
|
||||
class MSR_IA32_VMX_PROCBASED_CTLS(VMXCapabilityReportingMSR):
|
||||
addr = 0x00000482
|
||||
|
||||
tsc_offsetting = msrfield(3, 3, doc="Use TSC offsetting")
|
||||
hlt_exiting = msrfield(7, 7, doc="HLT exiting")
|
||||
tpr_shadow = msrfield(21, 21, doc="Use TPR shadow")
|
||||
io_bitmaps = msrfield(25, 25, doc="Use I/O bitmaps")
|
||||
msr_bitmaps = msrfield(28, 28, doc="Use MSR bitmaps")
|
||||
secondary_ctrls = msrfield(31, 31, doc="Activate secondary controls")
|
||||
|
||||
@property
|
||||
def vmx_procbased_ctls_tsc_off(self):
|
||||
return msrfield.is_vmx_cap_supported(self, 1 << 3)
|
||||
return self.allows_flexible_setting("tsc_offsetting")
|
||||
|
||||
@property
|
||||
def vmx_procbased_ctls_tpr_shadow(self):
|
||||
return msrfield.is_vmx_cap_supported(self, 1 << 21)
|
||||
return self.allows_flexible_setting("tpr_shadow")
|
||||
|
||||
@property
|
||||
def vmx_procbased_ctls_io_bitmap(self):
|
||||
return msrfield.is_vmx_cap_supported(self, 1 << 25)
|
||||
return self.allows_flexible_setting("io_bitmaps")
|
||||
|
||||
@property
|
||||
def vmx_procbased_ctls_msr_bitmap(self):
|
||||
return msrfield.is_vmx_cap_supported(self, 1 << 28)
|
||||
return self.allows_flexible_setting("msr_bitmaps")
|
||||
|
||||
@property
|
||||
def vmx_procbased_ctls_hlt(self):
|
||||
return msrfield.is_vmx_cap_supported(self, 1 << 7)
|
||||
return self.allows_flexible_setting("hlt_exiting")
|
||||
|
||||
@property
|
||||
def vmx_procbased_ctls_secondary(self):
|
||||
return msrfield.is_vmx_cap_supported(self, 1 << 31)
|
||||
return self.allows_flexible_setting("secondary_ctrls")
|
||||
|
||||
@property
|
||||
def ept(self):
|
||||
is_ept_supported = False
|
||||
if ((self.value >> 32) & (1 << 31)) != 0:
|
||||
msr_val = MSR_IA32_VMX_PROCBASED_CTLS2.rdmsr(self.cpu_id)
|
||||
if msrfield.is_ctrl_setting_allowed(msr_val.value, 1 << 1):
|
||||
is_ept_supported = True
|
||||
return is_ept_supported
|
||||
if self.allows_1_setting("secondary_ctrls"):
|
||||
ctls2 = MSR_IA32_VMX_PROCBASED_CTLS2.rdmsr(self.cpu_id)
|
||||
return ctls2.allows_1_setting("ept")
|
||||
return False
|
||||
|
||||
@property
|
||||
def apicv(self):
|
||||
features = 0
|
||||
vapic_feature_tpr_shadow = 1 << 3
|
||||
vapic_feature_virt_access = 1 << 0
|
||||
vapic_feature_vx2apic_mode = 1 << 5
|
||||
vapic_feature_virt_reg = 1 << 1
|
||||
vapic_feature_intr_delivery = 1 << 2
|
||||
vapic_feature_post_intr = 1 << 4
|
||||
if not self.allows_1_setting("tpr_shadow"):
|
||||
return False
|
||||
|
||||
if msrfield.is_ctrl_setting_allowed(self.value, 1 << 21):
|
||||
features |= vapic_feature_tpr_shadow
|
||||
|
||||
msr_val = MSR_IA32_VMX_PROCBASED_CTLS2.rdmsr(self.cpu_id)
|
||||
if msrfield.is_ctrl_setting_allowed(msr_val.value, 1 << 0):
|
||||
features |= vapic_feature_virt_access
|
||||
if msrfield.is_ctrl_setting_allowed(msr_val.value, 1 << 4):
|
||||
features |= vapic_feature_vx2apic_mode
|
||||
if msrfield.is_ctrl_setting_allowed(msr_val.value, 1 << 8):
|
||||
features |= vapic_feature_virt_reg
|
||||
if msrfield.is_ctrl_setting_allowed(msr_val.value, 1 << 9):
|
||||
features |= vapic_feature_intr_delivery
|
||||
|
||||
msr_val = MSR_IA32_VMX_PINBASED_CTLS.rdmsr(self.cpu_id)
|
||||
if msrfield.is_ctrl_setting_allowed(msr_val.value, 1 << 7):
|
||||
features |= vapic_feature_post_intr
|
||||
|
||||
apicv_basic_feature = (vapic_feature_tpr_shadow | vapic_feature_virt_access | vapic_feature_vx2apic_mode)
|
||||
return (features & apicv_basic_feature) == apicv_basic_feature
|
||||
ctls2 = MSR_IA32_VMX_PROCBASED_CTLS2.rdmsr(self.cpu_id)
|
||||
return \
|
||||
ctls2.allows_1_setting("vapic_access") and \
|
||||
ctls2.allows_1_setting("vx2apic")
|
||||
|
||||
capability_bits = [
|
||||
"ept",
|
||||
@ -148,10 +172,16 @@ class MSR_IA32_VMX_PROCBASED_CTLS(MSR):
|
||||
class MSR_IA32_VMX_EPT_VPID_CAP(MSR):
|
||||
addr = 0x0000048C
|
||||
|
||||
invept = msrfield(1, 20)
|
||||
ept_2mb_page = msrfield(1, 16)
|
||||
vmx_ept_1gb_page = msrfield(1, 17)
|
||||
invvpid = msrfield(1, 32) and msrfield(1, 41) and msrfield(1, 42)
|
||||
invept = msrfield(20, 20, doc="INVEPT instruction supported")
|
||||
ept_2mb_page = msrfield(16, 16, doc="EPT 2-Mbyte page supported")
|
||||
vmx_ept_1gb_page = msrfield(17, 17, doc="EPT 1-Gbyte page supported")
|
||||
invvpid_inst = msrfield(32, 32, doc="INVVPID instruction supported")
|
||||
invvpid_single_context = msrfield(41, 41, doc="single-context INVVPID type supported")
|
||||
invvpid_all_context = msrfield(42, 42, doc="all-context INVVPID type supported")
|
||||
|
||||
@property
|
||||
def invvpid(self):
|
||||
return self.invvpid_inst and self.invvpid_single_context and self.invvpid_all_context
|
||||
|
||||
capability_bits = [
|
||||
"invept",
|
||||
@ -162,38 +192,43 @@ class MSR_IA32_VMX_EPT_VPID_CAP(MSR):
|
||||
|
||||
class MSR_IA32_VMX_MISC(MSR):
|
||||
addr = 0x00000485
|
||||
unrestricted_guest = msrfield(1, 5)
|
||||
stores_lma_on_exit = msrfield(5, 5, doc="VM exits stores the value of IA32_EFER.LMA into the 'IA-32e mode guest' VM-entry control")
|
||||
|
||||
capability_bits = [
|
||||
"unrestricted_guest",
|
||||
"stores_lma_on_exit",
|
||||
]
|
||||
|
||||
class MSR_IA32_VMX_BASIC(MSR):
|
||||
addr = 0x00000480
|
||||
set_32bit_addr_width = msrfield(1, 48)
|
||||
set_32bit_addr_width = msrfield(48, 48, doc="Addresses of VMXON, VMCS and referenced structures limited to 32-bit")
|
||||
|
||||
capability_bits = [
|
||||
"set_32bit_addr_width",
|
||||
]
|
||||
|
||||
class MSR_IA32_VMX_EXIT_CTLS(MSR):
|
||||
class MSR_IA32_VMX_EXIT_CTLS(VMXCapabilityReportingMSR):
|
||||
addr = 0x00000483
|
||||
|
||||
host_addr_size = msrfield(9, 9, doc="Host address-space size")
|
||||
ack_irq_on_exit = msrfield(15, 15, doc="Acknowledge interrupt on exit")
|
||||
save_pat = msrfield(18, 18, doc="Save IA32_PAT")
|
||||
load_pat = msrfield(19, 19, doc="Load IA32_PAT")
|
||||
|
||||
@property
|
||||
def vmx_exit_ctls_ack_irq(self):
|
||||
return msrfield.is_vmx_cap_supported(self, 1 << 15)
|
||||
return self.allows_flexible_setting("ack_irq_on_exit")
|
||||
|
||||
@property
|
||||
def vmx_exit_ctls_save_pat(self):
|
||||
return msrfield.is_vmx_cap_supported(self, 1 << 18)
|
||||
return self.allows_flexible_setting("save_pat")
|
||||
|
||||
@property
|
||||
def vmx_exit_ctls_load_pat(self):
|
||||
return msrfield.is_vmx_cap_supported(self, 1 << 19)
|
||||
return self.allows_flexible_setting("load_pat")
|
||||
|
||||
@property
|
||||
def vmx_exit_ctls_host_addr64(self):
|
||||
return msrfield.is_vmx_cap_supported(self, 1 << 9)
|
||||
return self.allows_flexible_setting("host_addr_size")
|
||||
|
||||
capability_bits = [
|
||||
"vmx_exit_ctls_ack_irq",
|
||||
@ -202,16 +237,19 @@ class MSR_IA32_VMX_EXIT_CTLS(MSR):
|
||||
"vmx_exit_ctls_host_addr64",
|
||||
]
|
||||
|
||||
class MSR_IA32_VMX_ENTRY_CTLS(MSR):
|
||||
class MSR_IA32_VMX_ENTRY_CTLS(VMXCapabilityReportingMSR):
|
||||
addr = 0x00000484
|
||||
|
||||
ia32e_mode_guest = msrfield(9, 9, doc="IA-32e mode guest")
|
||||
load_pat = msrfield(14, 14, doc="Load IA32_PAT")
|
||||
|
||||
@property
|
||||
def vmx_entry_ctls_load_pat(self):
|
||||
return msrfield.is_vmx_cap_supported(self, 1 << 14)
|
||||
return self.allows_flexible_setting("load_pat")
|
||||
|
||||
@property
|
||||
def vmx_entry_ctls_ia32e_mode(self):
|
||||
return msrfield.is_vmx_cap_supported(self, 1 << 9)
|
||||
return self.allows_flexible_setting("ia32e_mode_guest")
|
||||
|
||||
capability_bits = [
|
||||
"vmx_entry_ctls_load_pat",
|
||||
|
@ -202,10 +202,12 @@ class msrfield(property):
|
||||
def __init__(self, msb, lsb, doc=None):
|
||||
self.msb = msb
|
||||
self.lsb = lsb
|
||||
bit_mask = self.msb << self.lsb
|
||||
|
||||
max_value = (1 << (msb - lsb + 1)) - 1
|
||||
field_mask = max_value << lsb
|
||||
|
||||
def getter(self):
|
||||
return (self.value & bit_mask) != 0
|
||||
return (self.value & field_mask) >> lsb
|
||||
|
||||
def setter(self, value):
|
||||
if value > max_value:
|
||||
@ -219,14 +221,3 @@ class msrfield(property):
|
||||
self.value = (self.value & ~field_mask) | (value << lsb)
|
||||
|
||||
super(msrfield, self).__init__(getter, setter, doc=doc)
|
||||
|
||||
def is_vmx_cap_supported(self, bits):
|
||||
vmx_msr = self.value
|
||||
vmx_msr_bin = int.to_bytes(vmx_msr, 8, 'big')
|
||||
vmx_msr_low = int.from_bytes(vmx_msr_bin[4:], 'big')
|
||||
vmx_msr_high = int.from_bytes(vmx_msr_bin[:4], 'big')
|
||||
return ((vmx_msr_high & bits) == bits) and ((vmx_msr_low & bits) == 0)
|
||||
|
||||
@staticmethod
|
||||
def is_ctrl_setting_allowed(msr_val, ctrl):
|
||||
return ((msr_val >> 32) & ctrl) == ctrl
|
||||
|
@ -147,9 +147,9 @@ ACRN requires this feature to function properly. Please enable it in BIOS.</xs:d
|
||||
</xs:annotation>
|
||||
</xs:assert>
|
||||
|
||||
<xs:assert test="every $model in processors/model satisfies exists($model/capability[@id='unrestricted_guest'])">
|
||||
<xs:assert test="every $model in processors/model satisfies exists($model/capability[@id='stores_lma_on_exit'])">
|
||||
<xs:annotation acrn:severity="error">
|
||||
<xs:documentation>Unrestricted guest is not supported on this processor. ACRN requires this feature to function properly.</xs:documentation>
|
||||
<xs:documentation>The value of IA32_EFER.LMA is not saved upon VM exit on this processor. ACRN requires this feature to function properly.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:assert>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user