[kvm-unit-tests PATCH v2 4/8] riscv: Add ACPI support for ISA string discovery
Xiang W
wangxiang at iscas.ac.cn
Thu Nov 5 00:20:31 PST 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 | 81 ++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 102 insertions(+), 7 deletions(-)
diff --git a/lib/acpi.h b/lib/acpi.h
index 0589669b..d5e238a9 100644
--- a/lib/acpi.h
+++ b/lib/acpi.h
@@ -334,6 +334,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 {
+ ACPI_RHCT_NODE_TYPE_ISA_STRING = 0x0,
+ ACPI_RHCT_NODE_TYPE_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..91c7302c 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,92 @@ 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)
{
- assert_msg(false, "ACPI not available");
+ 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 == ACPI_RHCT_NODE_TYPE_ISA_STRING) {
+ isa_string = (void *) node;
+ isa_parse(isa_string->isa, isa_string->isa_length, info);
+ }
+ }
+}
+
+static int acpi_rhct_for_each_hart(void (*func)(struct acpi_table_rhct *,
+ struct acpi_rhct_node_hart_info *,
+ void *), void *data)
+{
+ 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);
+ if (rhct == NULL)
+ return -1;
+
+ offset = rhct->node_offset;
+ for (int i = 0; i < rhct->node_count; i++) {
+ if (offset >= rhct->length)
+ return -1;
+
+ node = (void *)rhct + offset;
+ if (node->length < sizeof(*node))
+ return -1;
+
+ if (node->type == ACPI_RHCT_NODE_TYPE_HART_INFO) {
+ hart_info = (void *)node;
+ func(rhct, hart_info, data);
+ }
+
+ offset += node->length;
+ }
+
+ return 0;
}
+#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;
+ ret = acpi_rhct_for_each_hart(isa_parse_acpi, &info);
+ assert(ret == 0);
+#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 +176,17 @@ 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;
+ ret = acpi_rhct_for_each_hart(isa_parse_acpi, &info);
+ assert(ret == 0);
+#else
assert_msg(false, "ACPI not available");
+#endif
}
return check->found;
--
2.47.3
More information about the kvm-riscv
mailing list