From 635120e3f2fb40e769bdeebed36f33eb8fd17440 Mon Sep 17 00:00:00 2001 From: Wu Zhou Date: Fri, 2 Sep 2022 15:29:04 +0800 Subject: [PATCH] config-tools: extract CPU frequency info in board_inspector This patch adds CPU frequency info extraction for board_inspector. It is supposed to be used by ACRN CPU performance management. Including those: - Capabilities for HWP base regs, and turbo boost, by reading cpuids. - Reporting all CPUID bits in LEAF 06H. - Max none turbo ratio and max turbo ratio, by reading MSRs. - HWP capabilities, by reading IA32_HWP_CAPABILITIES. Reading this register requires HWP enabled in IA32_PM_ENABLE. (SDM Vol3 14.4.2: Additional MSRs associated with HWP may only be accessed after HWP is enabled) - ACPI _PSD info, by reading sys nodes of Linux acpi-pstate driver. This table describes frequency domains in which CPUs shares the same frequency. Tracked-On: #8168 Signed-off-by: Wu Zhou Reviewed-by: Junjie Mao --- .../board_inspector/cpuparser/cpuids.py | 76 +++++++++++++++++++ .../board_inspector/cpuparser/msr.py | 32 ++++++++ .../extractors/10-processors.py | 44 ++++++++++- 3 files changed, 151 insertions(+), 1 deletion(-) diff --git a/misc/config_tools/board_inspector/cpuparser/cpuids.py b/misc/config_tools/board_inspector/cpuparser/cpuids.py index 6013ffeb9..73abac066 100644 --- a/misc/config_tools/board_inspector/cpuparser/cpuids.py +++ b/misc/config_tools/board_inspector/cpuparser/cpuids.py @@ -286,11 +286,87 @@ class LEAF_6(CPUID): pln_supported = cpuidfield(EAX, 4, 4, doc = "Power limit notification controls are supported if set") ecmd_supported = cpuidfield(EAX, 5, 5, doc = "Clock modulation duty cycle extension is supported if set") package_thermal_management_supported = cpuidfield(EAX, 6, 6, doc = "Package thermal management is supported if set") + hwp_supported = cpuidfield(EAX, 7, 7, doc = "HWP base registers (IA32_PM_ENABLE[bit 0], IA32_HWP_CAPABILITIES, IA32_HWP_REQUEST, IA32_HWP_STATUS) are supported if set") + hwp_notification = cpuidfield(EAX, 8, 8, doc = "HWP_Notification. IA32_HWP_INTERRUPT MSR is supported if set.") + hwp_activity_window = cpuidfield(EAX, 9, 9, doc = "HWP_Activity_Window. IA32_HWP_REQUEST[bits 41:32] is supported if set.") + hwp_energy_performance_preference = cpuidfield(EAX, 10, 10, doc = "HWP_Energy_Performance_Preference. IA32_HWP_REQUEST[bits 31:24] is supported if set.") + hwp_package_level_request = cpuidfield(EAX, 11, 11, doc = "HWP_Package_Level_Request. IA32_HWP_REQUEST_PKG MSR is supported if set.") + hdc = cpuidfield(EAX, 13, 13, doc = "HDC. HDC base registers IA32_PKG_HDC_CTL, IA32_PM_CTL1, IA32_THREAD_STALL MSRs are supported if set.") + turbo_boost_30 = cpuidfield(EAX, 14, 14, doc = "Intel® Turbo Boost Max Technology 3.0 available.") + hwp_capabilities = cpuidfield(EAX, 15, 15, doc = "HWP Capabilities. Highest Performance change is supported if set.") + hwp_peci_override = cpuidfield(EAX, 16, 16, doc = "HWP PECI override is supported if set.") + flexible_hwp = cpuidfield(EAX, 17, 17, doc = "Flexible HWP is supported if set.") + fast_hwp_request = cpuidfield(EAX, 18, 18, doc = "Fast access mode for the IA32_HWP_REQUEST MSR is supported if set.") + hw_feedback = cpuidfield(EAX, 19, 19, doc = "HW_FEEDBACK. IA32_HW_FEEDBACK_PTR MSR, IA32_HW_FEEDBACK_CONFIG MSR, IA32_PACKAGE_THERM_STATUS MSR bit 26, and IA32_PACKAGE_THERM_INTERRUPT MSR bit 25 are supported if set.") + ignoring_idle_hwp = cpuidfield(EAX, 20, 20, doc = "Ignoring Idle Logical Processor HWP request is supported if set.") + thread_director = cpuidfield(EAX, 23, 23, doc = "Intel® Thread Director supported if set. IA32_HW_FEEDBACK_CHAR and IA32_HW_FEEDBACK_THREAD_CONFIG MSRs are supported if set.") num_interrupt_thresholds = cpuidfield(EBX, 3, 0, doc="Number of interrupt thresholds in digital thermal sensor") hardware_coordination_feedback_capability = cpuidfield(ECX, 0, 0, doc="Hardware coordination feedback capability") performance_energy_bias = cpuidfield(ECX, 3, 3, doc="Performance-energy bias preference support") + num_thread_director_classes = cpuidfield(ECX, 15, 8, "Number of Intel® Thread Director classes supported by the processor. Information for that many classes is written into the Intel Thread Director Table by the hardware.") + + hardware_feedback_interface_bitmap = cpuidfield(EDX, 7, 0, doc = "Bitmap of supported hardware feedback interface capabilities.") + hardware_feedback_interface_structure_size = cpuidfield(EDX, 11, 8, doc = "Enumerates the size of the hardware feedback interface structure in number of 4 KB pages.") + hardware_feedback_index = cpuidfield(EDX, 31, 16, doc = "Index (starting at 0) of this logical processor's row in the hardware feedback interface structure.") + + capability_bits = [ + "digital_temperature_sensor_supported", + "turbo_boost_available", + "arat_supported", + "pln_supported", + "ecmd_supported", + "package_thermal_management_supported", + "hwp_supported", + "hwp_notification", + "hwp_activity_window", + "hwp_energy_performance_preference", + "hwp_package_level_request", + "hdc", + "turbo_boost_30", + "hwp_capabilities", + "hwp_peci_override", + "flexible_hwp", + "fast_hwp_request", + "hw_feedback", + "ignoring_idle_hwp", + "thread_director", + "num_interrupt_thresholds", + "hardware_coordination_feedback_capability", + "performance_energy_bias", + "num_thread_director_classes", + "hardware_feedback_interface_bitmap", + "hardware_feedback_interface_structure_size", + "hardware_feedback_index", + "digital_temperature_sensor_supported", + "turbo_boost_available", + "arat_supported", + "pln_supported", + "ecmd_supported", + "package_thermal_management_supported", + "hwp_supported", + "hwp_notification", + "hwp_activity_window", + "hwp_energy_performance_preference", + "hwp_package_level_request", + "hdc", + "turbo_boost_30", + "hwp_capabilities", + "hwp_peci_override", + "flexible_hwp", + "fast_hwp_request", + "hw_feedback", + "ignoring_idle_hwp", + "thread_director", + "num_interrupt_thresholds", + "hardware_coordination_feedback_capability", + "performance_energy_bias", + "num_thread_director_classes", + "hardware_feedback_interface_bitmap", + "hardware_feedback_interface_structure_size", + "hardware_feedback_index", + ] class LEAF_7(CPUID): """Structured Extended Feature Flags Enumeration Leaf diff --git a/misc/config_tools/board_inspector/cpuparser/msr.py b/misc/config_tools/board_inspector/cpuparser/msr.py index 0d482f877..688f83357 100644 --- a/misc/config_tools/board_inspector/cpuparser/msr.py +++ b/misc/config_tools/board_inspector/cpuparser/msr.py @@ -270,3 +270,35 @@ def MSR_IA32_L3_MASK_n(n): bit_mask = msrfield(32, 0, doc="Capacity bit mask") return IA32_L3_MASK_n + +class MSR_IA32_PM_ENABLE(MSR): + addr = 0x00000770 + hwp_enable = msrfield(0, 0, doc=None) + +class MSR_IA32_HWP_CAPABILITIES(MSR): + addr = 0x00000771 + highest_performance_lvl = msrfield(7, 0, doc=None) + guaranteed_performance_lvl = msrfield(15, 8, doc=None) + lowest_performance_lvl = msrfield(31, 24, doc=None) + + attribute_bits = [ + "highest_performance_lvl", + "guaranteed_performance_lvl", + "lowest_performance_lvl", + ] + +class MSR_TURBO_RATIO_LIMIT(MSR): + addr = 0x000001ad + max_ratio_1core = msrfield(7, 0, doc=None) + + attribute_bits = [ + "max_ratio_1core", + ] + +class MSR_TURBO_ACTIVATION_RATIO(MSR): + addr = 0x0000064c + max_none_turbo_ratio = msrfield(7, 0, doc=None) + + attribute_bits = [ + "max_none_turbo_ratio", + ] diff --git a/misc/config_tools/board_inspector/extractors/10-processors.py b/misc/config_tools/board_inspector/extractors/10-processors.py index 11c3dcd76..e56fb8606 100644 --- a/misc/config_tools/board_inspector/extractors/10-processors.py +++ b/misc/config_tools/board_inspector/extractors/10-processors.py @@ -4,6 +4,7 @@ # import logging +import subprocess import lxml.etree import re @@ -47,7 +48,7 @@ def extract_model(processors_node, cpu_id, family_id, model_id, core_type, nativ brandstring += leaf_data.brandstring n.set("description", re.sub('[^!-~]+', ' ', brandstring.decode()).strip()) - leaves = [(1, 0), (7, 0), (0x80000001, 0), (0x80000007, 0)] + leaves = [(1, 0), (6, 0), (7, 0), (0x80000001, 0), (0x80000007, 0)] for leaf in leaves: leaf_data = parse_cpuid(leaf[0], leaf[1], cpu_id) for cap in leaf_data.capability_bits: @@ -70,6 +71,12 @@ def extract_model(processors_node, cpu_id, family_id, model_id, core_type, nativ for cap in leaf_data.attribute_bits: add_child(n, "attribute", str(getattr(leaf_data, cap)), id=cap) + msr_regs = [MSR_TURBO_RATIO_LIMIT, MSR_TURBO_ACTIVATION_RATIO] + for msr_reg in msr_regs: + msr_data = msr_reg.rdmsr(cpu_id) + for attr in msr_data.attribute_bits: + add_child(n, "attribute", str(getattr(msr_data, attr)), id=attr) + def extract_topology(processors_node): cpu_ids = get_online_cpu_ids() for cpu_id in cpu_ids: @@ -130,6 +137,41 @@ def extract_topology(processors_node): last_shift = leaf_topo.num_bit_shift subleaf += 1 +def extract_hwp_info(processors_node): + if processors_node.xpath("//capability[@id = 'hwp_supported']") is None: + return + + # SDM Vol3 14.4.2: Additional MSRs associated with HWP may only be accessed after HWP is enabled + msr_hwp_en = MSR_IA32_PM_ENABLE() + msr_hwp_en.hwp_enable = 1 + msr_hwp_en.wrmsr(0) + + threads = processors_node.xpath("//thread") + for thread in threads: + cpu_id = get_node(thread, "cpu_id/text()") + msr_regs = [MSR_IA32_HWP_CAPABILITIES,] + for msr_reg in msr_regs: + msr_data = msr_reg.rdmsr(cpu_id) + for attr in msr_data.attribute_bits: + add_child(thread, attr, str(getattr(msr_data, attr))) + +def extract_psd_info(processors_node): + sysnode = '/sys/devices/system/cpu/' + threads = processors_node.xpath("//thread") + for thread in threads: + cpu_id = get_node(thread, "cpu_id/text()") + try: + with open(sysnode + "cpu{cpu_id}/cpufreq/freqdomain_cpus", 'r') as f_node: + freqdomain_cpus = f_node.read() + except IOError: + logging.info("No _PSD info for cpu {cpu_id}") + freqdomain_cpus = cpu_id + + freqdomain_cpus.replace('\n','') + add_child(thread, "freqdomain_cpus", freqdomain_cpus) + def extract(args, board_etree): processors_node = get_node(board_etree, "//processors") extract_topology(processors_node) + extract_hwp_info(processors_node) + extract_psd_info(processors_node)