diff --git a/misc/config_tools/board_inspector/cpuparser/cpuids.py b/misc/config_tools/board_inspector/cpuparser/cpuids.py index b8a074f2e..b2af4d101 100644 --- a/misc/config_tools/board_inspector/cpuparser/cpuids.py +++ b/misc/config_tools/board_inspector/cpuparser/cpuids.py @@ -19,11 +19,19 @@ class LEAF_0(CPUID): leaf = 0x0 max_leaf = cpuidfield(EAX, 31, 0, doc="Highest value the CPUID recognizes for returning basic processor information") + @property + def cpuid_level(self): + return hex(self.regs.eax) + @property def vendor(self): """Vendor identification string""" return struct.pack('III', self.regs.ebx, self.regs.edx, self.regs.ecx) + attribute_bits = [ + "cpuid_level", + ] + class LEAF_1(CPUID): """Basic CPUID Information diff --git a/misc/config_tools/board_inspector/cpuparser/msr.py b/misc/config_tools/board_inspector/cpuparser/msr.py new file mode 100644 index 000000000..f6f8f9729 --- /dev/null +++ b/misc/config_tools/board_inspector/cpuparser/msr.py @@ -0,0 +1,206 @@ +# Copyright (C) 2022 Intel Corporation. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +from cpuparser.platformbase import MSR, msrfield + +class MSR_IA32_MISC_ENABLE(MSR): + addr = 0x1a0 + fast_string = msrfield(1, 0, doc=None) + + capability_bits = [ + "fast_string", + ] + +class MSR_IA32_VMX_PROCBASED_CTLS2(MSR): + addr = 0x0000048B + + @property + def vmx_procbased_ctls2_vapic(self): + return msrfield.is_vmx_cap_supported(self, 1 << 0) + + @property + def vmx_procbased_ctls2_ept(self): + return msrfield.is_vmx_cap_supported(self, 1 << 1) + + @property + def vmx_procbased_ctls2_vpid(self): + return msrfield.is_vmx_cap_supported(self, 1 << 5) + + @property + def vmx_procbased_ctls2_rdtscp(self): + return msrfield.is_vmx_cap_supported(self, 1 << 3) + + @property + def vmx_procbased_ctls2_unrestrict(self): + return msrfield.is_vmx_cap_supported(self, 1 << 7) + + capability_bits = [ + "vmx_procbased_ctls2_vapic", + "vmx_procbased_ctls2_ept", + "vmx_procbased_ctls2_vpid", + "vmx_procbased_ctls2_rdtscp", + "vmx_procbased_ctls2_unrestrict", + ] + +class MSR_IA32_VMX_PINBASED_CTLS(MSR): + addr = 0x00000481 + + @property + def vmx_pinbased_ctls_irq_exit(self): + return msrfield.is_vmx_cap_supported(self, 1 << 0) + + capability_bits = [ + "vmx_pinbased_ctls_irq_exit", + ] + +class MSR_IA32_VMX_PROCBASED_CTLS(MSR): + addr = 0x00000482 + + @property + def vmx_procbased_ctls_tsc_off(self): + return msrfield.is_vmx_cap_supported(self, 1 << 3) + + @property + def vmx_procbased_ctls_tpr_shadow(self): + return msrfield.is_vmx_cap_supported(self, 1 << 21) + + @property + def vmx_procbased_ctls_io_bitmap(self): + return msrfield.is_vmx_cap_supported(self, 1 << 25) + + @property + def vmx_procbased_ctls_msr_bitmap(self): + return msrfield.is_vmx_cap_supported(self, 1 << 28) + + @property + def vmx_procbased_ctls_hlt(self): + return msrfield.is_vmx_cap_supported(self, 1 << 7) + + @property + def vmx_procbased_ctls_secondary(self): + return msrfield.is_vmx_cap_supported(self, 1 << 31) + + @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 + + @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 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 + + capability_bits = [ + "ept", + "apicv", + "vmx_procbased_ctls_tsc_off", + "vmx_procbased_ctls_tpr_shadow", + "vmx_procbased_ctls_io_bitmap", + "vmx_procbased_ctls_msr_bitmap", + "vmx_procbased_ctls_hlt", + "vmx_procbased_ctls_secondary", + ] + +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) + + capability_bits = [ + "invept", + "invvpid", + "ept_2mb_page", + "vmx_ept_1gb_page", + ] + +class MSR_IA32_VMX_MISC(MSR): + addr = 0x00000485 + unrestricted_guest = msrfield(1, 5) + + capability_bits = [ + "unrestricted_guest", + ] + +class MSR_IA32_VMX_BASIC(MSR): + addr = 0x00000480 + set_32bit_addr_width = msrfield(1, 48) + + capability_bits = [ + "set_32bit_addr_width", + ] + +class MSR_IA32_VMX_EXIT_CTLS(MSR): + addr = 0x00000483 + + @property + def vmx_exit_ctls_ack_irq(self): + return msrfield.is_vmx_cap_supported(self, 1 << 15) + + @property + def vmx_exit_ctls_save_pat(self): + return msrfield.is_vmx_cap_supported(self, 1 << 18) + + @property + def vmx_exit_ctls_load_pat(self): + return msrfield.is_vmx_cap_supported(self, 1 << 19) + + @property + def vmx_exit_ctls_host_addr64(self): + return msrfield.is_vmx_cap_supported(self, 1 << 9) + + capability_bits = [ + "vmx_exit_ctls_ack_irq", + "vmx_exit_ctls_save_pat", + "vmx_exit_ctls_load_pat", + "vmx_exit_ctls_host_addr64", + ] + +class MSR_IA32_VMX_ENTRY_CTLS(MSR): + addr = 0x00000484 + + @property + def vmx_entry_ctls_load_pat(self): + return msrfield.is_vmx_cap_supported(self, 1 << 14) + + @property + def vmx_entry_ctls_ia32e_mode(self): + return msrfield.is_vmx_cap_supported(self, 1 << 9) + + capability_bits = [ + "vmx_entry_ctls_load_pat", + "vmx_entry_ctls_ia32e_mode", + ] diff --git a/misc/config_tools/board_inspector/cpuparser/platformbase.py b/misc/config_tools/board_inspector/cpuparser/platformbase.py index 154f66289..73552a836 100644 --- a/misc/config_tools/board_inspector/cpuparser/platformbase.py +++ b/misc/config_tools/board_inspector/cpuparser/platformbase.py @@ -12,6 +12,7 @@ import functools import inspect import operator import textwrap +import logging from collections import namedtuple _wrapper = textwrap.TextWrapper(width=78, initial_indent=' ', subsequent_indent=' ') @@ -135,8 +136,17 @@ class MSR(object): return self.value != other.value @classmethod - def rdmsr(cls, cpu_id): - r = cls(bits.rdmsr(cpu_id, cls.addr)) + def rdmsr(cls, cpu_id: int) -> int: + try: + with open(f'/dev/cpu/{cpu_id}/msr', 'rb') as msr_reader: + msr_reader.seek(cls.addr) + r = msr_reader.read(8) + r = cls(int.from_bytes(r, 'little')) + except IOError: + logging.critical(f"Missing CPU MSR file at /dev/cpu/{cpu_id}/msr. Check the value of CONFIG_X86_MSR " \ + "in the kernel config. Set it to 'Y' and rebuild the kernel. Then rerun the Board Inspector.") + sys.exit(1) + r.cpu_id = cpu_id return r @@ -187,15 +197,14 @@ class MSR(object): return s class msrfield(property): + def __init__(self, msb, lsb, doc=None): self.msb = msb self.lsb = lsb - - max_value = (1 << (msb - lsb + 1)) - 1 - field_mask = max_value << lsb + bit_mask = self.msb << self.lsb def getter(self): - return (self.value & field_mask) >> lsb + return (self.value & bit_mask) != 0 def setter(self, value): if value > max_value: @@ -209,3 +218,14 @@ 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 diff --git a/misc/config_tools/board_inspector/extractors/10-processors.py b/misc/config_tools/board_inspector/extractors/10-processors.py index 73d9997a3..150f806da 100644 --- a/misc/config_tools/board_inspector/extractors/10-processors.py +++ b/misc/config_tools/board_inspector/extractors/10-processors.py @@ -7,6 +7,7 @@ import logging import lxml.etree from cpuparser import parse_cpuid, get_online_cpu_ids +from cpuparser.msr import * from extractors.helpers import add_child, get_node level_types = { @@ -52,7 +53,16 @@ def extract_model(processors_node, cpu_id, family_id, model_id, core_type, nativ if getattr(leaf_data, cap) == 1: add_child(n, "capability", id=cap) - leaves = [(0x80000008, 0)] + msr_regs = [MSR_IA32_MISC_ENABLE, MSR_IA32_VMX_BASIC, MSR_IA32_VMX_PINBASED_CTLS, + MSR_IA32_VMX_PROCBASED_CTLS, MSR_IA32_VMX_EXIT_CTLS, MSR_IA32_VMX_ENTRY_CTLS, + MSR_IA32_VMX_MISC, MSR_IA32_VMX_PROCBASED_CTLS2, MSR_IA32_VMX_EPT_VPID_CAP] + for msr_reg in msr_regs: + msr_data = msr_reg.rdmsr(cpu_id) + for cap in msr_data.capability_bits: + if getattr(msr_data, cap) == 1: + add_child(n, "capability", id=cap) + + leaves = [(0, 0), (0x80000008, 0)] for leaf in leaves: leaf_data = parse_cpuid(leaf[0], leaf[1], cpu_id) for cap in leaf_data.attribute_bits: diff --git a/misc/config_tools/board_inspector/schema/checks/platform_capabilities.xsd b/misc/config_tools/board_inspector/schema/checks/platform_capabilities.xsd index 6af0241e6..bfb8d322a 100644 --- a/misc/config_tools/board_inspector/schema/checks/platform_capabilities.xsd +++ b/misc/config_tools/board_inspector/schema/checks/platform_capabilities.xsd @@ -5,7 +5,262 @@ - Intel(R) Virtualization Technology Extension shall be enabled in BIOS. + Virtual Machine Extensions (VMX) feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + Long mode (x86-64, 64-bit) feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + The width of the physical addresses used for the VMXON region is limited to 32bit. "Intel 64 architecture" feature is not enabled. ACRN requires this feature to function properly. + + + + + + Instruction CPUID time stamp counter, nominal core crystal clock information leaf and processor frequency information leaf are not supported. ACRN requires this feature to function properly. + + + + + + "Zero linear/physical address size" feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + "1GB large page(Physical-address width > 39)" feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + "Fast string" feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + Enhanced rep movsb/stosb feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + Invariant TSC feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + TSC deadline feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + NX feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + SMEP feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + SMAP feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + MTRR feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + CLFLUSHOPT feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + x2APIC feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + POPCNT feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + SSE feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + RDRAND feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + INVEPT is not supported on this processor. ACRN requires this feature to function properly. + + + + + + Unrestricted guest is not supported on this processor. ACRN requires this feature to function properly. + + + + + + EPT feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + EPT does not support 2MB large pages on this processor. ACRN requires this feature to function properly. + + + + + + INVVPID feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + APICV feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + VMX capability External-interrupt exiting for VM execution controls feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + VMX capability Use TSC offsetting for VM execution controls feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + VMX capability Use TPR shadow for VM execution controls feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + VMX capability Use I/O bitmaps for VM execution controls feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + VMX capability Use MSR bitmaps for VM execution controls feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + VMX capability HLT exiting for VM execution controls feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + VMX capability Activate secondary controls for VM execution controls feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + VMX capability acknowledge interrupt on exit feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + VMX capability save IA32_PAT on VM exit feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + VMX capability load IA32_PAT on VM exit feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + VMX capability Host address-space size on VM exit feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + VMX capability IA32_PAT MSR load on VM entry feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + VMX capability IA-32e mode guest support after VM entry feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + VMX capability Virtualize APIC accesses for VM execution controls feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + VMX capability Enable EPT for VM execution controls feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + VMX capability Enable VPID for VM execution controls feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + VMX capability Enable RDTSCP for VM execution controls feature is not supported on this processor. ACRN requires this feature to function properly. + + + + + + VMX capability Unrestricted guest for VM execution controls feature is not supported on this processor. ACRN requires this feature to function properly.