[kvm-unit-tests PATCH 4/7] riscv: Add ACPI support for ISA string discovery
Xiang W
wangxiang at iscas.ac.cn
Wed Sep 23 20:39:42 PDT 2026
When a DT is not provided, walk the RHCT Hart Info nodes and parse
the referenced ISA String node instead of aborting in isa_init()
and cpu_has_extension_name().
Match the current hart by ACPI UID (DT still matches by hartid)
and feed the ISA string into the existing isa_parse() helper so
extension detection is shared by both firmware descriptions.
Rename isa_info.hartid to isa_info.id so the same iterator state
can hold either identifier.
Signed-off-by: Xiang W <wangxiang at iscas.ac.cn>
---
lib/acpi.h | 28 ++++++++++++++++++++
lib/riscv/isa.c | 68 ++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 89 insertions(+), 7 deletions(-)
diff --git a/lib/acpi.h b/lib/acpi.h
index 2597e8ce..3db382b7 100644
--- a/lib/acpi.h
+++ b/lib/acpi.h
@@ -337,6 +337,34 @@ struct acpi_table_rhct {
u32 node_offset;
};
+#define ACPI_RHCT_NODE_HEADER_DEF \
+ u16 type; \
+ u16 length; \
+ u16 revision; \
+
+struct acpi_rhct_node {
+ ACPI_RHCT_NODE_HEADER_DEF
+ char data[];
+};
+
+enum acpi_rhct_node_type {
+ RHCT_NODE_ISA_STRING = 0x0,
+ RHCT_NODE_HART_INFO = 0xFFFF
+};
+
+struct acpi_rhct_node_isa_string {
+ ACPI_RHCT_NODE_HEADER_DEF
+ u16 isa_length;
+ char isa[];
+};
+
+struct acpi_rhct_node_hart_info {
+ ACPI_RHCT_NODE_HEADER_DEF
+ u16 num_offsets;
+ u32 uid;
+ u32 nodes[];
+};
+
/* Reset to default packing */
#pragma pack()
diff --git a/lib/riscv/isa.c b/lib/riscv/isa.c
index bc1c9c72..b0257979 100644
--- a/lib/riscv/isa.c
+++ b/lib/riscv/isa.c
@@ -12,7 +12,7 @@
typedef void (*isa_func_t)(const char *, int, void *);
struct isa_info {
- unsigned long hartid;
+ unsigned long id;
isa_func_t func;
void *data;
};
@@ -74,7 +74,7 @@ static void isa_parse_fdt(int cpu_node, u64 hartid, void *data)
const struct fdt_property *prop;
int len;
- if (hartid != info->hartid)
+ if (hartid != info->id)
return;
prop = fdt_get_property(dt_fdt(), cpu_node, "riscv,isa", &len);
@@ -83,32 +83,80 @@ static void isa_parse_fdt(int cpu_node, u64 hartid, void *data)
isa_parse(prop->data, len, info);
}
-static void isa_init_acpi(void)
+#ifdef CONFIG_EFI
+#include <acpi.h>
+
+static void isa_parse_acpi(struct acpi_table_rhct *rhct, struct acpi_rhct_node_hart_info *hart_info, void *data)
+{
+ u32 offset;
+ struct acpi_rhct_node *node;
+ struct acpi_rhct_node_isa_string *isa_string;
+ struct isa_info *info = (struct isa_info *)data;
+
+ if (hart_info->uid != info->id)
+ return;
+
+ for (int i = 0; i < hart_info->num_offsets; i++) {
+ offset = hart_info->nodes[i];
+ if (offset >= rhct->length)
+ break;
+ node = (void *)rhct + offset;
+ if (node->type == RHCT_NODE_ISA_STRING) {
+ isa_string = (void *) node;
+ isa_parse(isa_string->isa, isa_string->isa_length, info);
+ }
+ }
+}
+
+static void acpi_rhct_for_each_hart(
+ void (*func)(struct acpi_table_rhct *, struct acpi_rhct_node_hart_info *, void *), void *data)
{
- assert_msg(false, "ACPI not available");
+ u32 offset;
+ struct acpi_table_rhct *rhct;
+ struct acpi_rhct_node *node;
+ struct acpi_rhct_node_hart_info *hart_info;
+ rhct = find_acpi_table_addr(RHCT_SIGNATURE);
+ assert_msg(rhct, "Cannot find ACPI RHCT");
+ offset = rhct->node_offset;
+ for (int i = 0; i < rhct->node_count; i++) {
+ if (offset >= rhct->length)
+ break;
+ node = (void *)rhct + offset;
+ if (node->type == RHCT_NODE_HART_INFO) {
+ hart_info = (void *)node;
+ func(rhct, hart_info, data);
+ }
+ assert(node->length >= sizeof(*node));
+ offset += node->length;
+ }
}
+#endif
void isa_init(struct thread_info *ti)
{
struct isa_info info = {
- .hartid = ti->hartid,
.func = isa_bit,
.data = ti,
};
int ret;
if (dt_available()) {
+ info.id = ti->hartid;
ret = dt_for_each_cpu_node(isa_parse_fdt, &info);
assert(ret == 0);
} else {
- isa_init_acpi();
+#ifdef CONFIG_EFI
+ info.id = ti->uid;
+ acpi_rhct_for_each_hart(isa_parse_acpi, &info);
+#else
+ assert_msg(false, "ACPI not available");
+#endif
}
}
bool cpu_has_extension_name(int cpu, const char *ext)
{
struct isa_info info = {
- .hartid = cpus[cpu].hartid,
.func = isa_name,
.data = &(struct isa_check){ .ext = ext, },
};
@@ -116,10 +164,16 @@ bool cpu_has_extension_name(int cpu, const char *ext)
int ret;
if (dt_available()) {
+ info.id = cpus[cpu].hartid;
ret = dt_for_each_cpu_node(isa_parse_fdt, &info);
assert(ret == 0);
} else {
+#ifdef CONFIG_EFI
+ info.id = cpus[cpu].uid;
+ acpi_rhct_for_each_hart(isa_parse_acpi, &info);
+#else
assert_msg(false, "ACPI not available");
+#endif
}
return check->found;
--
2.47.3
More information about the kvm-riscv
mailing list