[PATCH 4/6] config_tools & hv: generate CPU frequency info code


Zhou, Wu
 

This patch is to generate CPU frequency info from allocation data.

Frequency policy struct and frequency info struct are added in
acrn_common.h.

Frequency policy is generated for each CPU in board.c, and passthrough
pstate flag is generated for each VM in vm_configuration.c.

Signed-off-by: Wu Zhou <wu.zhou@...>
---
hypervisor/include/arch/x86/asm/vm_config.h | 2 ++
hypervisor/include/public/acrn_common.h | 29 +++++++++++++++
misc/config_tools/board_config/board_c.py | 35 +++++++++++++++++++
.../xforms/vm_configurations.c.xsl | 8 +++++
4 files changed, 74 insertions(+)

diff --git a/hypervisor/include/arch/x86/asm/vm_config.h b/hypervisor/include/arch/x86/asm/vm_config.h
index ef80701d6..c6ea4fbe9 100644
--- a/hypervisor/include/arch/x86/asm/vm_config.h
+++ b/hypervisor/include/arch/x86/asm/vm_config.h
@@ -207,6 +207,8 @@ struct acrn_vm_config {

uint16_t pt_intx_num; /* number of pt_intx_config entries pointed by pt_intx */
struct pt_intx_config *pt_intx; /* stores the base address of struct pt_intx_config array */
+
+ bool pt_acpi_pstate; /* whether to passthru acpi pstate */
} __aligned(8);

struct acrn_vm_config *get_vm_config(uint16_t vm_id);
diff --git a/hypervisor/include/public/acrn_common.h b/hypervisor/include/public/acrn_common.h
index fee71a655..b2d3e3d68 100644
--- a/hypervisor/include/public/acrn_common.h
+++ b/hypervisor/include/public/acrn_common.h
@@ -522,6 +522,35 @@ struct acrn_pstate_data {
uint64_t status; /* success indicator */
};

+struct acrn_cpufreq_policy {
+ bool available;
+ /*
+ * Frequency levels:
+ * for HWP, it is the continuous performance level for HWP_REQUEST msr;
+ * for ACPI p-state, it is the APCI Px performance level x
+ */
+ uint8_t policy_guaranteed_lvl;
+ uint8_t policy_highest_lvl;
+ uint8_t policy_lowest_lvl;
+};
+
+enum cpufreq_governor_type {
+ CPUFREQ_GOVERNOR_PERFORMANCE,
+ CPUFREQ_GOVERNOR_NOMINAL,
+};
+
+enum cpufreq_interface_type {
+ CPUFREQ_INTERFACE_NONE = 0,
+ CPUFREQ_INTERFACE_HWP,
+ CPUFREQ_INTERFACE_ACPI,
+};
+
+struct acrn_cpufreq_info {
+ enum cpufreq_governor_type governor_type;
+ enum cpufreq_interface_type interface_type;
+ struct acrn_cpufreq_policy *policy;
+};
+
struct acpi_sx_pkg {
uint8_t val_pm1a;
uint8_t val_pm1b;
diff --git a/misc/config_tools/board_config/board_c.py b/misc/config_tools/board_config/board_c.py
index 655cfc6c4..2597877be 100644
--- a/misc/config_tools/board_config/board_c.py
+++ b/misc/config_tools/board_config/board_c.py
@@ -449,6 +449,39 @@ def gen_known_caps_pci_devs(config):
if i == (bdf_list_len - 1):
print("};", file=config)

+def gen_cpufreq_info(config):
+ allocation_dir = os.path.split(common.SCENARIO_INFO_FILE)[0] + "/configs/allocation.xml"
+ allocation_etree = lxml.etree.parse(allocation_dir)
+ cpu_list = board_cfg_lib.get_processor_info()
+ max_cpu_num = len(cpu_list)
+
+ print("\nstruct acrn_cpufreq_policy cpufreq_policy_info[MAX_PCPU_NUM] = {", file=config)
+ for cpu_id in range(max_cpu_num):
+ available = 'false'
+ policy_node = common.get_node(f"//cpufreq/CPU[@id='{cpu_id}']/policy", allocation_etree)
+ if policy_node != None:
+ available = "true"
+ policy_guaranteed_lvl = common.get_node("./policy_guaranteed_lvl/text()", policy_node)
+ policy_highest_lvl = common.get_node("./policy_highest_lvl/text()", policy_node)
+ policy_lowest_lvl = common.get_node("./policy_lowest_lvl/text()", policy_node)
+
+ print("\t{", file=config)
+ print(f"\t\t.available = {available},", file=config)
+ if available == 'true':
+ print(f"\t\t.policy_guaranteed_lvl = {policy_guaranteed_lvl},", file=config)
+ print(f"\t\t.policy_highest_lvl = {policy_highest_lvl},", file=config)
+ print(f"\t\t.policy_lowest_lvl = {policy_lowest_lvl},", file=config)
+ print("\t},", file=config)
+ print("};", file=config)
+
+ print("\nconst struct acrn_cpufreq_info cpufreq_info = {", file=config)
+
+ governor = common.get_node(f"//cpufreq/governor/text()", allocation_etree)
+ interface = common.get_node(f"//cpufreq/interface/text()", allocation_etree)
+ print(f"\t.governor_type = {governor},", file=config)
+ print(f"\t.interface_type = {interface},", file=config)
+ print("\t.policy = cpufreq_policy_info,", file=config)
+ print("};", file=config)

def generate_file(config):
"""
@@ -479,4 +512,6 @@ def generate_file(config):
# gen known caps of pci dev info for platform
gen_known_caps_pci_devs(config)

+ gen_cpufreq_info(config)
+
return err_dic
diff --git a/misc/config_tools/xforms/vm_configurations.c.xsl b/misc/config_tools/xforms/vm_configurations.c.xsl
index bb2c3e29d..9c35a1392 100644
--- a/misc/config_tools/xforms/vm_configurations.c.xsl
+++ b/misc/config_tools/xforms/vm_configurations.c.xsl
@@ -97,6 +97,7 @@

<xsl:call-template name="load_order" />
<xsl:apply-templates select="name" />
+ <xsl:call-template name="pt_acpi_pstate" />
<xsl:if test="acrn:is-service-vm(load_order)">
<xsl:value-of select="acrn:comment('Allow Service VM to reboot the system since it is the highest priority VM.')" />
<xsl:value-of select="$newline" />
@@ -158,6 +159,13 @@
<xsl:value-of select="acrn:initializer('name', concat($quot, current(), $quot))" />
</xsl:template>

+ <xsl:template name="pt_acpi_pstate">
+ <xsl:variable name="vm_id" select="@id" />
+ <xsl:if test="//allocation-data/acrn-config/vm[@id=$vm_id]/vm_pt_acpi_pstate = 'y'">
+ <xsl:value-of select="acrn:initializer('pt_acpi_pstate', 'true')" />
+ </xsl:if>
+ </xsl:template>
+
<xsl:template name="cpu_affinity">
<xsl:choose>
<xsl:when test="acrn:is-service-vm(load_order)">
--
2.25.1