git: 3e01ebda6829 - main - riscv: support the new "riscv,isa-extensions" string-array.

From: Ruslan Bukin <br_at_FreeBSD.org>
Date: Tue, 06 Oct 2026 19:10:42 UTC
The branch main has been updated by br:

URL: https://cgit.FreeBSD.org/src/commit/?id=3e01ebda68291db307a5e6c23d4995c638be9228

commit 3e01ebda68291db307a5e6c23d4995c638be9228
Author:     Ruslan Bukin <br@FreeBSD.org>
AuthorDate: 2026-10-06 18:55:39 +0000
Commit:     Ruslan Bukin <br@FreeBSD.org>
CommitDate: 2026-10-06 19:09:04 +0000

    riscv: support the new "riscv,isa-extensions" string-array.
    
    Support the new "riscv,isa-extensions" property on RISC-V hart nodes
    in FDT.
    
    The "riscv,isa" property is deprecated, but cannot be removed because
    doing so would break compatibility with existing DTBs. The new properties
    replace it: "riscv,isa-base" describes the base ISA and
    "riscv,isa-extensions" is a string array containing the supported ISA
    extensions.
    
    The "riscv,isa-extensions" property can be relatively large; on the
    Spacemit K3 SoC it is approximately 300 bytes.
    
    The FreeBSD OFW interface does not provide access to the underlying FDT
    property data without copying it, and memory allocation is not possible
    this early. So allocate a static buffer for the property instead.
    
    Reuse the existing parse_riscv_isa() implementation to parse both the new
    extension property and the legacy "riscv,isa" property.
    
    Reviewed by:    bnovkov, mhorne
    Sponsored by:   EPSRC ("UKRI3001: CHERI Research Centre")
    Differential Revision:  https://reviews.freebsd.org/D60209
---
 sys/riscv/riscv/identcpu.c | 106 ++++++++++++++++++++++++++++++++++-----------
 1 file changed, 80 insertions(+), 26 deletions(-)

diff --git a/sys/riscv/riscv/identcpu.c b/sys/riscv/riscv/identcpu.c
index ca1b2b9ae1af..81e8afde8499 100644
--- a/sys/riscv/riscv/identcpu.c
+++ b/sys/riscv/riscv/identcpu.c
@@ -86,6 +86,8 @@ bool has_zicbom;
 bool has_zicboz;
 bool has_zicbop;
 
+static char isa_extensions[PAGE_SIZE];
+
 struct cpu_desc {
 	const char	*cpu_mvendor_name;
 	const char	*cpu_march_name;
@@ -271,14 +273,7 @@ parse_riscv_isa(struct cpu_desc *desc, char *isa, int len)
 {
 	int i;
 
-	/* Check the string prefix. */
-	if (strncmp(isa, ISA_PREFIX, ISA_PREFIX_LEN) != 0) {
-		printf("%s: Unrecognized ISA string: %s\n", __func__, isa);
-		return (-1);
-	}
-
-	i = ISA_PREFIX_LEN;
-	while (i < len) {
+	for (i = 0; i < len; ) {
 		switch(isa[i]) {
 		case 'a':
 		case 'b':
@@ -372,14 +367,82 @@ parse_cbo_fdt(struct cpu_desc *desc, phandle_t node)
 		desc->cboz_block_size = 0;
 }
 
+static int
+parse_isa_extensions(phandle_t node, u_int cpu, struct cpu_desc *desc)
+{
+	ssize_t len, off, i;
+	char *ext;
+
+	len = OF_getprop(node, "riscv,isa-extensions", isa_extensions,
+	    sizeof(isa_extensions));
+	if (len == -1)
+		return (ESRCH);
+	if (len > sizeof(isa_extensions))
+		panic("isa_extensions string truncated");
+
+	for (i = 0; i < len; i++)
+		isa_extensions[i] = tolower(isa_extensions[i]);
+
+	for (off = 0; off < len; ) {
+		ext = isa_extensions + off;
+		if (*ext == '\0')
+			break;
+		if (bootverbose)
+			printf("riscv extension: %s\n", ext);
+		parse_riscv_isa(desc, ext, strlen(ext));
+		off += strlen(ext) + 1;
+	}
+
+	return (0);
+}
+
+static int
+parse_riscv_isa_legacy(phandle_t node, u_int cpu, struct cpu_desc *desc)
+{
+	u_int hart;
+	ssize_t len;
+	int i;
+
+	hart = pcpu_find(cpu)->pc_hart;
+
+	len = OF_getprop(node, "riscv,isa", isa_extensions,
+	    sizeof(isa_extensions));
+	if (len == -1) {
+		printf("%s: could not find 'riscv,isa' property "
+		    "for CPU %d, hart %u\n", __func__, cpu, hart);
+		return (ESRCH);
+	}
+	if (len > sizeof(isa_extensions))
+		panic("isa string truncated");
+
+	if (bootverbose)
+		printf("hart %d isa: %s\n", hart, isa_extensions);
+
+	/*
+	 * The string is specified to be lowercase, but let's be
+	 * certain.
+	 */
+	for (i = 0; i < len; i++)
+		isa_extensions[i] = tolower(isa_extensions[i]);
+
+	/* Check the string prefix. */
+	if (strncmp(isa_extensions, ISA_PREFIX, ISA_PREFIX_LEN) != 0) {
+		printf("%s: Unrecognized ISA string: %s\n", __func__,
+		    isa_extensions);
+		return (-1);
+	}
+
+	return (parse_riscv_isa(desc, &isa_extensions[ISA_PREFIX_LEN],
+	    len - ISA_PREFIX_LEN));
+}
+
 static void
 identify_cpu_features_fdt(u_int cpu, struct cpu_desc *desc)
 {
-	char isa[1024];
 	phandle_t node;
-	ssize_t len;
 	pcell_t reg;
 	u_int hart;
+	int error;
 
 	node = OF_finddevice("/cpus");
 	if (node == -1) {
@@ -403,26 +466,17 @@ identify_cpu_features_fdt(u_int cpu, struct cpu_desc *desc)
 		    reg != hart)
 			continue;
 
-		len = OF_getprop(node, "riscv,isa", isa, sizeof(isa));
-		KASSERT(len <= sizeof(isa), ("ISA string truncated"));
-		if (len == -1) {
-			printf("%s: could not find 'riscv,isa' property "
+		error = parse_isa_extensions(node, cpu, desc);
+		if (error != 0) {
+			/* Fall-back to the legacy riscv,isa string. */
+			error = parse_riscv_isa_legacy(node, cpu, desc);
+		}
+		if (error != 0) {
+			printf("%s: could not parse ISA string "
 			    "for CPU %d, hart %u\n", __func__, cpu, hart);
 			return;
 		}
 
-		if (bootverbose)
-			printf("hart %d isa: %s\n", hart, isa);
-
-		/*
-		 * The string is specified to be lowercase, but let's be
-		 * certain.
-		 */
-		for (int i = 0; i < len; i++)
-			isa[i] = tolower(isa[i]);
-		if (parse_riscv_isa(desc, isa, len) != 0)
-			return;
-
 		/* Check MMU features. */
 		parse_mmu_fdt(desc, node);