Commit 0d8295ed authored by Evan Green's avatar Evan Green Committed by Palmer Dabbelt

riscv: add ISA extension parsing for scalar crypto

The Scalar Crypto specification defines Zk as a shorthand for the
Zkn, Zkr and Zkt extensions. The same follows for both Zkn, Zks and Zbk,
which are all shorthands for various other extensions. The detailed
breakdown can be found in their dt-binding entries.

Since Zkn also implies the Zbkb, Zbkc and Zbkx extensions, simply passing
"zk" through a DT should enable all of Zbkb, Zbkc, Zbkx, Zkn, Zkr and Zkt.
For example, setting the "riscv,isa" DT property to "rv64imafdc_zk"
should generate the following cpuinfo output:
"rv64imafdc_zicntr_zicsr_zifencei_zihpm_zbkb_zbkc_zbkx_zknd_zkne_zknh_zkr_zkt"

riscv_isa_ext_data grows a pair of new members, to permit setting the
relevant bits for "bundled" extensions, both while parsing the ISA string
and the new dedicated extension properties.
Co-developed-by: default avatarConor Dooley <conor.dooley@microchip.com>
Signed-off-by: default avatarConor Dooley <conor.dooley@microchip.com>
Signed-off-by: default avatarEvan Green <evan@rivosinc.com>
Signed-off-by: default avatarClément Léger <cleger@rivosinc.com>
Acked-by: default avatarConor Dooley <conor.dooley@microchip.com>
Link: https://lore.kernel.org/r/20231114141256.126749-4-cleger@rivosinc.comSigned-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parent be6bef2a
...@@ -59,6 +59,8 @@ struct riscv_isa_ext_data { ...@@ -59,6 +59,8 @@ struct riscv_isa_ext_data {
const unsigned int id; const unsigned int id;
const char *name; const char *name;
const char *property; const char *property;
const unsigned int *subset_ext_ids;
const unsigned int subset_ext_size;
}; };
extern const struct riscv_isa_ext_data riscv_isa_ext[]; extern const struct riscv_isa_ext_data riscv_isa_ext[];
...@@ -67,7 +69,7 @@ extern bool riscv_isa_fallback; ...@@ -67,7 +69,7 @@ extern bool riscv_isa_fallback;
unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap); unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit); bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, unsigned int bit);
#define riscv_isa_extension_available(isa_bitmap, ext) \ #define riscv_isa_extension_available(isa_bitmap, ext) \
__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext) __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
......
...@@ -58,8 +58,19 @@ ...@@ -58,8 +58,19 @@
#define RISCV_ISA_EXT_SMSTATEEN 43 #define RISCV_ISA_EXT_SMSTATEEN 43
#define RISCV_ISA_EXT_ZICOND 44 #define RISCV_ISA_EXT_ZICOND 44
#define RISCV_ISA_EXT_ZBC 45 #define RISCV_ISA_EXT_ZBC 45
#define RISCV_ISA_EXT_ZBKB 46
#define RISCV_ISA_EXT_ZBKC 47
#define RISCV_ISA_EXT_ZBKX 48
#define RISCV_ISA_EXT_ZKND 49
#define RISCV_ISA_EXT_ZKNE 50
#define RISCV_ISA_EXT_ZKNH 51
#define RISCV_ISA_EXT_ZKR 52
#define RISCV_ISA_EXT_ZKSED 53
#define RISCV_ISA_EXT_ZKSH 54
#define RISCV_ISA_EXT_ZKT 55
#define RISCV_ISA_EXT_MAX 64 #define RISCV_ISA_EXT_MAX 64
#define RISCV_ISA_EXT_INVALID U32_MAX
#ifdef CONFIG_RISCV_M_MODE #ifdef CONFIG_RISCV_M_MODE
#define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SMAIA #define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SMAIA
......
...@@ -70,7 +70,7 @@ EXPORT_SYMBOL_GPL(riscv_isa_extension_base); ...@@ -70,7 +70,7 @@ EXPORT_SYMBOL_GPL(riscv_isa_extension_base);
* *
* NOTE: If isa_bitmap is NULL then Host ISA bitmap will be used. * NOTE: If isa_bitmap is NULL then Host ISA bitmap will be used.
*/ */
bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit) bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, unsigned int bit)
{ {
const unsigned long *bmap = (isa_bitmap) ? isa_bitmap : riscv_isa; const unsigned long *bmap = (isa_bitmap) ? isa_bitmap : riscv_isa;
...@@ -102,17 +102,53 @@ static bool riscv_isa_extension_check(int id) ...@@ -102,17 +102,53 @@ static bool riscv_isa_extension_check(int id)
return false; return false;
} }
return true; return true;
case RISCV_ISA_EXT_INVALID:
return false;
} }
return true; return true;
} }
#define __RISCV_ISA_EXT_DATA(_name, _id) { \ #define _RISCV_ISA_EXT_DATA(_name, _id, _subset_exts, _subset_exts_size) { \
.name = #_name, \ .name = #_name, \
.property = #_name, \ .property = #_name, \
.id = _id, \ .id = _id, \
.subset_ext_ids = _subset_exts, \
.subset_ext_size = _subset_exts_size \
} }
#define __RISCV_ISA_EXT_DATA(_name, _id) _RISCV_ISA_EXT_DATA(_name, _id, NULL, 0)
/* Used to declare pure "lasso" extension (Zk for instance) */
#define __RISCV_ISA_EXT_BUNDLE(_name, _bundled_exts) \
_RISCV_ISA_EXT_DATA(_name, RISCV_ISA_EXT_INVALID, _bundled_exts, ARRAY_SIZE(_bundled_exts))
static const unsigned int riscv_zk_bundled_exts[] = {
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[] = {
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[] = {
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 * The canonical order of ISA extension names in the ISA string is defined in
* chapter 27 of the unprivileged specification. * chapter 27 of the unprivileged specification.
...@@ -177,7 +213,20 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = { ...@@ -177,7 +213,20 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
__RISCV_ISA_EXT_DATA(zba, RISCV_ISA_EXT_ZBA), __RISCV_ISA_EXT_DATA(zba, RISCV_ISA_EXT_ZBA),
__RISCV_ISA_EXT_DATA(zbb, RISCV_ISA_EXT_ZBB), __RISCV_ISA_EXT_DATA(zbb, RISCV_ISA_EXT_ZBB),
__RISCV_ISA_EXT_DATA(zbc, RISCV_ISA_EXT_ZBC), __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_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(zkt, RISCV_ISA_EXT_ZKT),
__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(smaia, RISCV_ISA_EXT_SMAIA),
__RISCV_ISA_EXT_DATA(smstateen, RISCV_ISA_EXT_SMSTATEEN), __RISCV_ISA_EXT_DATA(smstateen, RISCV_ISA_EXT_SMSTATEEN),
__RISCV_ISA_EXT_DATA(ssaia, RISCV_ISA_EXT_SSAIA), __RISCV_ISA_EXT_DATA(ssaia, RISCV_ISA_EXT_SSAIA),
...@@ -190,6 +239,31 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = { ...@@ -190,6 +239,31 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
const size_t riscv_isa_ext_count = ARRAY_SIZE(riscv_isa_ext); const size_t riscv_isa_ext_count = ARRAY_SIZE(riscv_isa_ext);
static void __init match_isa_ext(const struct riscv_isa_ext_data *ext, const char *name,
const char *name_end, struct riscv_isainfo *isainfo)
{
if ((name_end - name == 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->subset_ext_size) {
for (int i = 0; i < ext->subset_ext_size; i++) {
if (riscv_isa_extension_check(ext->subset_ext_ids[i]))
set_bit(ext->subset_ext_ids[i], isainfo->isa);
}
}
/*
* This is valid even for bundle extensions which uses the RISCV_ISA_EXT_INVALID id
* (rejected by riscv_isa_extension_check()).
*/
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, static void __init riscv_parse_isa_string(unsigned long *this_hwcap, struct riscv_isainfo *isainfo,
unsigned long *isa2hwcap, const char *isa) unsigned long *isa2hwcap, const char *isa)
{ {
...@@ -322,14 +396,6 @@ static void __init riscv_parse_isa_string(unsigned long *this_hwcap, struct risc ...@@ -322,14 +396,6 @@ static void __init riscv_parse_isa_string(unsigned long *this_hwcap, struct risc
if (*isa == '_') if (*isa == '_')
++isa; ++isa;
#define SET_ISA_EXT_MAP(name, bit) \
do { \
if ((ext_end - ext == strlen(name)) && \
!strncasecmp(ext, name, strlen(name)) && \
riscv_isa_extension_check(bit)) \
set_bit(bit, isainfo->isa); \
} while (false) \
if (unlikely(ext_err)) if (unlikely(ext_err))
continue; continue;
if (!ext_long) { if (!ext_long) {
...@@ -341,10 +407,8 @@ static void __init riscv_parse_isa_string(unsigned long *this_hwcap, struct risc ...@@ -341,10 +407,8 @@ static void __init riscv_parse_isa_string(unsigned long *this_hwcap, struct risc
} }
} else { } else {
for (int i = 0; i < riscv_isa_ext_count; i++) for (int i = 0; i < riscv_isa_ext_count; i++)
SET_ISA_EXT_MAP(riscv_isa_ext[i].name, match_isa_ext(&riscv_isa_ext[i], ext, ext_end, isainfo);
riscv_isa_ext[i].id);
} }
#undef SET_ISA_EXT_MAP
} }
} }
...@@ -443,18 +507,26 @@ static int __init riscv_fill_hwcap_from_ext_list(unsigned long *isa2hwcap) ...@@ -443,18 +507,26 @@ static int __init riscv_fill_hwcap_from_ext_list(unsigned long *isa2hwcap)
} }
for (int i = 0; i < riscv_isa_ext_count; i++) { for (int i = 0; i < riscv_isa_ext_count; i++) {
const struct riscv_isa_ext_data *ext = &riscv_isa_ext[i];
if (of_property_match_string(cpu_node, "riscv,isa-extensions", if (of_property_match_string(cpu_node, "riscv,isa-extensions",
riscv_isa_ext[i].property) < 0) ext->property) < 0)
continue; continue;
if (!riscv_isa_extension_check(riscv_isa_ext[i].id)) if (ext->subset_ext_size) {
continue; for (int j = 0; j < ext->subset_ext_size; j++) {
if (riscv_isa_extension_check(ext->subset_ext_ids[i]))
set_bit(ext->subset_ext_ids[j], isainfo->isa);
}
}
/* Only single letter extensions get set in hwcap */ if (riscv_isa_extension_check(ext->id)) {
if (strnlen(riscv_isa_ext[i].name, 2) == 1) set_bit(ext->id, isainfo->isa);
this_hwcap |= isa2hwcap[riscv_isa_ext[i].id];
set_bit(riscv_isa_ext[i].id, isainfo->isa); /* Only single letter extensions get set in hwcap */
if (strnlen(riscv_isa_ext[i].name, 2) == 1)
this_hwcap |= isa2hwcap[riscv_isa_ext[i].id];
}
} }
of_node_put(cpu_node); of_node_put(cpu_node);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment