Skip to content

Commit 23c996f

Browse files
charlie-rivospalmer-dabbelt
authored andcommitted
riscv: Extend cpufeature.c to detect vendor extensions
Instead of grouping all vendor extensions into the same riscv_isa_ext that standard instructions use, create a struct "riscv_isa_vendor_ext_data_list" that allows each vendor to maintain their vendor extensions independently of the standard extensions. xandespmu is currently the only vendor extension so that is the only extension that is affected by this change. An additional benefit of this is that the extensions of each vendor can be conditionally enabled. A config RISCV_ISA_VENDOR_EXT_ANDES has been added to allow for that. Signed-off-by: Charlie Jenkins <charlie@rivosinc.com> Reviewed-by: Conor Dooley <conor.dooley@microchip.com> Reviewed-by: Andy Chiu <andy.chiu@sifive.com> Tested-by: Yu Chien Peter Lin <peterlin@andestech.com> Reviewed-by: Yu Chien Peter Lin <peterlin@andestech.com> Link: https://lore.kernel.org/r/20240719-support_vendor_extensions-v3-1-0af7587bbec0@rivosinc.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
1 parent 5ee121a commit 23c996f

File tree

15 files changed

+324
-56
lines changed

15 files changed

+324
-56
lines changed

arch/riscv/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,8 @@ config RISCV_EFFICIENT_UNALIGNED_ACCESS
808808

809809
endchoice
810810

811+
source "arch/riscv/Kconfig.vendor"
812+
811813
endmenu # "Platform type"
812814

813815
menu "Kernel features"

arch/riscv/Kconfig.vendor

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
menu "Vendor extensions"
2+
3+
config RISCV_ISA_VENDOR_EXT
4+
bool
5+
6+
menu "Andes"
7+
config RISCV_ISA_VENDOR_EXT_ANDES
8+
bool "Andes vendor extension support"
9+
select RISCV_ISA_VENDOR_EXT
10+
default y
11+
help
12+
Say N here if you want to disable all Andes vendor extension
13+
support. This will cause any Andes vendor extensions that are
14+
requested by hardware probing to be ignored.
15+
16+
If you don't know what to do here, say Y.
17+
endmenu
18+
19+
endmenu

arch/riscv/errata/andes/errata.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <asm/processor.h>
1818
#include <asm/sbi.h>
1919
#include <asm/vendorid_list.h>
20+
#include <asm/vendor_extensions.h>
2021

2122
#define ANDES_AX45MP_MARCHID 0x8000000000008a45UL
2223
#define ANDES_AX45MP_MIMPID 0x500UL
@@ -65,6 +66,8 @@ void __init_or_module andes_errata_patch_func(struct alt_entry *begin, struct al
6566
unsigned long archid, unsigned long impid,
6667
unsigned int stage)
6768
{
69+
BUILD_BUG_ON(ERRATA_ANDES_NUMBER >= RISCV_VENDOR_EXT_ALTERNATIVES_BASE);
70+
6871
if (stage == RISCV_ALTERNATIVES_BOOT)
6972
errata_probe_iocp(stage, archid, impid);
7073

arch/riscv/errata/sifive/errata.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <asm/alternative.h>
1313
#include <asm/vendorid_list.h>
1414
#include <asm/errata_list.h>
15+
#include <asm/vendor_extensions.h>
1516

1617
struct errata_info_t {
1718
char name[32];
@@ -96,6 +97,8 @@ void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
9697
u32 cpu_apply_errata = 0;
9798
u32 tmp;
9899

100+
BUILD_BUG_ON(ERRATA_SIFIVE_NUMBER >= RISCV_VENDOR_EXT_ALTERNATIVES_BASE);
101+
99102
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
100103
return;
101104

arch/riscv/errata/thead/errata.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <asm/io.h>
1919
#include <asm/patch.h>
2020
#include <asm/vendorid_list.h>
21+
#include <asm/vendor_extensions.h>
2122

2223
#define CSR_TH_SXSTATUS 0x5c0
2324
#define SXSTATUS_MAEE _AC(0x200000, UL)
@@ -166,6 +167,8 @@ void thead_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
166167
u32 tmp;
167168
void *oldptr, *altptr;
168169

170+
BUILD_BUG_ON(ERRATA_THEAD_NUMBER >= RISCV_VENDOR_EXT_ALTERNATIVES_BASE);
171+
169172
for (alt = begin; alt < end; alt++) {
170173
if (alt->vendor_id != THEAD_VENDOR_ID)
171174
continue;

arch/riscv/include/asm/cpufeature.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,31 @@ extern struct riscv_isainfo hart_isa[NR_CPUS];
3333

3434
void riscv_user_isa_enable(void);
3535

36+
#define _RISCV_ISA_EXT_DATA(_name, _id, _subset_exts, _subset_exts_size, _validate) { \
37+
.name = #_name, \
38+
.property = #_name, \
39+
.id = _id, \
40+
.subset_ext_ids = _subset_exts, \
41+
.subset_ext_size = _subset_exts_size, \
42+
.validate = _validate \
43+
}
44+
45+
#define __RISCV_ISA_EXT_DATA(_name, _id) _RISCV_ISA_EXT_DATA(_name, _id, NULL, 0, NULL)
46+
47+
#define __RISCV_ISA_EXT_DATA_VALIDATE(_name, _id, _validate) \
48+
_RISCV_ISA_EXT_DATA(_name, _id, NULL, 0, _validate)
49+
50+
/* Used to declare pure "lasso" extension (Zk for instance) */
51+
#define __RISCV_ISA_EXT_BUNDLE(_name, _bundled_exts) \
52+
_RISCV_ISA_EXT_DATA(_name, RISCV_ISA_EXT_INVALID, _bundled_exts, \
53+
ARRAY_SIZE(_bundled_exts), NULL)
54+
55+
/* Used to declare extensions that are a superset of other extensions (Zvbb for instance) */
56+
#define __RISCV_ISA_EXT_SUPERSET(_name, _id, _sub_exts) \
57+
_RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), NULL)
58+
#define __RISCV_ISA_EXT_SUPERSET_VALIDATE(_name, _id, _sub_exts, _validate) \
59+
_RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), _validate)
60+
3661
#if defined(CONFIG_RISCV_MISALIGNED)
3762
bool check_unaligned_access_emulated_all_cpus(void);
3863
void unaligned_emulation_finish(void);

arch/riscv/include/asm/hwcap.h

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -80,19 +80,18 @@
8080
#define RISCV_ISA_EXT_ZFA 71
8181
#define RISCV_ISA_EXT_ZTSO 72
8282
#define RISCV_ISA_EXT_ZACAS 73
83-
#define RISCV_ISA_EXT_XANDESPMU 74
84-
#define RISCV_ISA_EXT_ZVE32X 75
85-
#define RISCV_ISA_EXT_ZVE32F 76
86-
#define RISCV_ISA_EXT_ZVE64X 77
87-
#define RISCV_ISA_EXT_ZVE64F 78
88-
#define RISCV_ISA_EXT_ZVE64D 79
89-
#define RISCV_ISA_EXT_ZIMOP 80
90-
#define RISCV_ISA_EXT_ZCA 81
91-
#define RISCV_ISA_EXT_ZCB 82
92-
#define RISCV_ISA_EXT_ZCD 83
93-
#define RISCV_ISA_EXT_ZCF 84
94-
#define RISCV_ISA_EXT_ZCMOP 85
95-
#define RISCV_ISA_EXT_ZAWRS 86
83+
#define RISCV_ISA_EXT_ZVE32X 74
84+
#define RISCV_ISA_EXT_ZVE32F 75
85+
#define RISCV_ISA_EXT_ZVE64X 76
86+
#define RISCV_ISA_EXT_ZVE64F 77
87+
#define RISCV_ISA_EXT_ZVE64D 78
88+
#define RISCV_ISA_EXT_ZIMOP 79
89+
#define RISCV_ISA_EXT_ZCA 80
90+
#define RISCV_ISA_EXT_ZCB 81
91+
#define RISCV_ISA_EXT_ZCD 82
92+
#define RISCV_ISA_EXT_ZCF 83
93+
#define RISCV_ISA_EXT_ZCMOP 84
94+
#define RISCV_ISA_EXT_ZAWRS 85
9695

9796
#define RISCV_ISA_EXT_XLINUXENVCFG 127
9897

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* Copyright 2024 Rivos, Inc
4+
*/
5+
6+
#ifndef _ASM_VENDOR_EXTENSIONS_H
7+
#define _ASM_VENDOR_EXTENSIONS_H
8+
9+
#include <asm/cpufeature.h>
10+
11+
#include <linux/array_size.h>
12+
#include <linux/types.h>
13+
14+
/*
15+
* The extension keys of each vendor must be strictly less than this value.
16+
*/
17+
#define RISCV_ISA_VENDOR_EXT_MAX 32
18+
19+
struct riscv_isavendorinfo {
20+
DECLARE_BITMAP(isa, RISCV_ISA_VENDOR_EXT_MAX);
21+
};
22+
23+
struct riscv_isa_vendor_ext_data_list {
24+
bool is_initialized;
25+
const size_t ext_data_count;
26+
const struct riscv_isa_ext_data *ext_data;
27+
struct riscv_isavendorinfo per_hart_isa_bitmap[NR_CPUS];
28+
struct riscv_isavendorinfo all_harts_isa_bitmap;
29+
};
30+
31+
extern struct riscv_isa_vendor_ext_data_list *riscv_isa_vendor_ext_list[];
32+
33+
extern const size_t riscv_isa_vendor_ext_list_size;
34+
35+
/*
36+
* The alternatives need some way of distinguishing between vendor extensions
37+
* and errata. Incrementing all of the vendor extension keys so they are at
38+
* least 0x8000 accomplishes that.
39+
*/
40+
#define RISCV_VENDOR_EXT_ALTERNATIVES_BASE 0x8000
41+
42+
#define VENDOR_EXT_ALL_CPUS -1
43+
44+
bool __riscv_isa_vendor_extension_available(int cpu, unsigned long vendor, unsigned int bit);
45+
#define riscv_isa_vendor_extension_available(vendor, ext) \
46+
__riscv_isa_vendor_extension_available(VENDOR_EXT_ALL_CPUS, vendor, \
47+
RISCV_ISA_VENDOR_EXT_##ext)
48+
49+
#endif /* _ASM_VENDOR_EXTENSIONS_H */
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef _ASM_RISCV_VENDOR_EXTENSIONS_ANDES_H
3+
#define _ASM_RISCV_VENDOR_EXTENSIONS_ANDES_H
4+
5+
#include <asm/vendor_extensions.h>
6+
7+
#include <linux/types.h>
8+
9+
#define RISCV_ISA_VENDOR_EXT_XANDESPMU 0
10+
11+
/*
12+
* Extension keys should be strictly less than max.
13+
* It is safe to increment this when necessary.
14+
*/
15+
#define RISCV_ISA_VENDOR_EXT_MAX_ANDES 32
16+
17+
extern struct riscv_isa_vendor_ext_data_list riscv_isa_vendor_ext_list_andes;
18+
19+
#endif

arch/riscv/kernel/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ obj-y += riscv_ksyms.o
5858
obj-y += stacktrace.o
5959
obj-y += cacheinfo.o
6060
obj-y += patch.o
61+
obj-y += vendor_extensions.o
62+
obj-y += vendor_extensions/
6163
obj-y += probes/
6264
obj-y += tests/
6365
obj-$(CONFIG_MMU) += vdso.o vdso/

0 commit comments

Comments
 (0)