[PATCH] WIP: RISC-V: Allow support for bundled extensions, and add= Zk*

From: Evan Green
Date: Wed Jul 12 2023 - 13:36:15 EST


---
arch/riscv/include/asm/hwcap.h | 13 ++++++
arch/riscv/kernel/cpufeature.c | 82 +++++++++++++++++++++++++++++-----
2 files changed, 84 insertions(+), 11 deletions(-)

diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.=
h
index b7b58258f6c7..7d2d10b42cf3 100644
--- a/arch/riscv/include/asm/hwcap.h
+++ b/arch/riscv/include/asm/hwcap.h
@@ -58,6 +58,17 @@
#define RISCV_ISA_EXT_ZICSR 40
#define RISCV_ISA_EXT_ZIFENCEI 41
#define RISCV_ISA_EXT_ZIHPM 42
+#define RISCV_ISA_EXT_ZBC 43
+#define RISCV_ISA_EXT_ZBKB 44
+#define RISCV_ISA_EXT_ZBKC 45
+#define RISCV_ISA_EXT_ZBKX 46
+#define RISCV_ISA_EXT_ZKND 47
+#define RISCV_ISA_EXT_ZKNE 48
+#define RISCV_ISA_EXT_ZKNH 49
+#define RISCV_ISA_EXT_ZKR 50
+#define RISCV_ISA_EXT_ZKSED 51
+#define RISCV_ISA_EXT_ZKSH 52
+#define RISCV_ISA_EXT_ZKT 53

#define RISCV_ISA_EXT_MAX 64

@@ -77,6 +88,8 @@ struct riscv_isa_ext_data {
const unsigned int id;
const char *name;
const char *property;
+ const unsigned int *bundled_exts;
+ const unsigned int bundle_size;
};

extern const struct riscv_isa_ext_data riscv_isa_ext[];
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.=
c
index 5945dfc5f806..2a1f958c1777 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -105,6 +105,39 @@ static bool riscv_isa_extension_check(int id)
.id =3D _id, \
}

+#define __RISCV_ISA_EXT_BUNDLE(_name, _bundled_exts) { \
+ .name =3D #_name, \
+ .property =3D #_name, \
+ .bundled_exts =3D _bundled_exts, \
+ .bundle_size =3D ARRAY_SIZE(_bundled_exts) \
+}
+
+static const unsigned int riscv_zk_bundled_exts[] =3D {
+ RISCV_ISA_EXT_ZBKB,
+ RISCV_ISA_EXT_ZBKC,
+ RISCV_ISA_EXT_ZBKX,
+ RISCV_ISA_EXT_ZKND,
+ RISCV_ISA_EXT_ZKNE,
+ RISCV_ISA_EXT_ZKR,
+ RISCV_ISA_EXT_ZKT,
+};
+
+static const unsigned int riscv_zkn_bundled_exts[] =3D {
+ RISCV_ISA_EXT_ZBKB,
+ RISCV_ISA_EXT_ZBKC,
+ RISCV_ISA_EXT_ZBKX,
+ RISCV_ISA_EXT_ZKND,
+ RISCV_ISA_EXT_ZKNE,
+ RISCV_ISA_EXT_ZKNH,
+};
+
+static const unsigned int riscv_zks_bundled_exts[] =3D {
+ RISCV_ISA_EXT_ZBKB,
+ RISCV_ISA_EXT_ZBKC,
+ RISCV_ISA_EXT_ZKSED,
+ RISCV_ISA_EXT_ZKSH
+};
+
/*
* The canonical order of ISA extension names in the ISA string is defined=
in
* chapter 27 of the unprivileged specification.
@@ -167,7 +200,20 @@ const struct riscv_isa_ext_data riscv_isa_ext[] =3D {
__RISCV_ISA_EXT_DATA(zihpm, RISCV_ISA_EXT_ZIHPM),
__RISCV_ISA_EXT_DATA(zba, RISCV_ISA_EXT_ZBA),
__RISCV_ISA_EXT_DATA(zbb, RISCV_ISA_EXT_ZBB),
+ __RISCV_ISA_EXT_DATA(zbc, RISCV_ISA_EXT_ZBC),
+ __RISCV_ISA_EXT_DATA(zbkb, RISCV_ISA_EXT_ZBKB),
+ __RISCV_ISA_EXT_DATA(zbkc, RISCV_ISA_EXT_ZBKC),
+ __RISCV_ISA_EXT_DATA(zbkx, RISCV_ISA_EXT_ZBKX),
__RISCV_ISA_EXT_DATA(zbs, RISCV_ISA_EXT_ZBS),
+ __RISCV_ISA_EXT_BUNDLE(zk, riscv_zk_bundled_exts),
+ __RISCV_ISA_EXT_BUNDLE(zkn, riscv_zkn_bundled_exts),
+ __RISCV_ISA_EXT_DATA(zknd, RISCV_ISA_EXT_ZKND),
+ __RISCV_ISA_EXT_DATA(zkne, RISCV_ISA_EXT_ZKNE),
+ __RISCV_ISA_EXT_DATA(zknh, RISCV_ISA_EXT_ZKNH),
+ __RISCV_ISA_EXT_DATA(zkr, RISCV_ISA_EXT_ZKR),
+ __RISCV_ISA_EXT_BUNDLE(zks, riscv_zks_bundled_exts),
+ __RISCV_ISA_EXT_DATA(zksed, RISCV_ISA_EXT_ZKSED),
+ __RISCV_ISA_EXT_DATA(zksh, RISCV_ISA_EXT_ZKSH),
__RISCV_ISA_EXT_DATA(smaia, RISCV_ISA_EXT_SMAIA),
__RISCV_ISA_EXT_DATA(ssaia, RISCV_ISA_EXT_SSAIA),
__RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF),
@@ -179,6 +225,30 @@ const struct riscv_isa_ext_data riscv_isa_ext[] =3D {

const size_t riscv_isa_ext_count =3D ARRAY_SIZE(riscv_isa_ext);

+static void match_isa_ext(const struct riscv_isa_ext_data *ext, const
char *name,
+ const char *name_end, struct riscv_isainfo *isain=
fo)
+{
+ if ((name_end - name =3D=3D strlen(ext->name)) &&
+ !strncasecmp(name, ext->name, name_end - name)) {
+
+ /*
+ * If this is a bundle, enable all the ISA extensions that
+ * comprise the bundle.
+ */
+ if (ext->bundle_size) {
+ unsigned int i;
+ for (i =3D 0; i < ext->bundle_size; i++) {
+ if
(riscv_isa_extension_check(ext->bundled_exts[i]))
+ set_bit(ext->bundled_exts[i],
isainfo->isa);
+ }
+
+
+ } else if (riscv_isa_extension_check(ext->id)) {
+ set_bit(ext->id, isainfo->isa);
+ }
+ }
+}
+
static void __init riscv_parse_isa_string(unsigned long *this_hwcap,
struct riscv_isainfo *isainfo,
unsigned long *isa2hwcap,
const char *isa)
{
@@ -310,14 +380,6 @@ static void __init
riscv_parse_isa_string(unsigned long *this_hwcap, struct risc
if (*isa =3D=3D '_')
++isa;

-#define SET_ISA_EXT_MAP(name, bit)
\
- do {
\
- if ((ext_end - ext =3D=3D sizeof(name) - 1) &&
\
- !strncasecmp(ext, name, sizeof(name) - 1)
&& \
- riscv_isa_extension_check(bit))
\
- set_bit(bit, isainfo->isa);
\
- } while (false)
\
-
if (unlikely(ext_err))
continue;
if (!ext_long) {
@@ -329,10 +391,8 @@ static void __init
riscv_parse_isa_string(unsigned long *this_hwcap, struct risc
}
} else {
for (int i =3D 0; i < riscv_isa_ext_count; i++)
- SET_ISA_EXT_MAP(riscv_isa_ext[i].name,
- riscv_isa_ext[i].id);
+ match_isa_ext(&riscv_isa_ext[i], ext,
ext_end, isainfo);
}
-#undef SET_ISA_EXT_MAP
}
}