1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * Copyright 2024 Rivos, Inc
6 #ifndef _ASM_VENDOR_EXTENSIONS_H
7 #define _ASM_VENDOR_EXTENSIONS_H
9 #include <asm/cpufeature.h>
11 #include <linux/array_size.h>
12 #include <linux/types.h>
15 * The extension keys of each vendor must be strictly less than this value.
17 #define RISCV_ISA_VENDOR_EXT_MAX 32
19 struct riscv_isavendorinfo
{
20 DECLARE_BITMAP(isa
, RISCV_ISA_VENDOR_EXT_MAX
);
23 struct riscv_isa_vendor_ext_data_list
{
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
;
31 extern struct riscv_isa_vendor_ext_data_list
*riscv_isa_vendor_ext_list
[];
33 extern const size_t riscv_isa_vendor_ext_list_size
;
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.
40 #define RISCV_VENDOR_EXT_ALTERNATIVES_BASE 0x8000
42 #define VENDOR_EXT_ALL_CPUS -1
44 bool __riscv_isa_vendor_extension_available(int cpu
, unsigned long vendor
, unsigned int bit
);
45 #define riscv_cpu_isa_vendor_extension_available(cpu, vendor, ext) \
46 __riscv_isa_vendor_extension_available(cpu, vendor, RISCV_ISA_VENDOR_EXT_##ext)
47 #define riscv_isa_vendor_extension_available(vendor, ext) \
48 __riscv_isa_vendor_extension_available(VENDOR_EXT_ALL_CPUS, vendor, \
49 RISCV_ISA_VENDOR_EXT_##ext)
51 static __always_inline
bool riscv_has_vendor_extension_likely(const unsigned long vendor
,
52 const unsigned long ext
)
54 if (!IS_ENABLED(CONFIG_RISCV_ISA_VENDOR_EXT
))
57 if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE
))
58 return __riscv_has_extension_likely(vendor
,
59 ext
+ RISCV_VENDOR_EXT_ALTERNATIVES_BASE
);
61 return __riscv_isa_vendor_extension_available(VENDOR_EXT_ALL_CPUS
, vendor
, ext
);
64 static __always_inline
bool riscv_has_vendor_extension_unlikely(const unsigned long vendor
,
65 const unsigned long ext
)
67 if (!IS_ENABLED(CONFIG_RISCV_ISA_VENDOR_EXT
))
70 if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE
))
71 return __riscv_has_extension_unlikely(vendor
,
72 ext
+ RISCV_VENDOR_EXT_ALTERNATIVES_BASE
);
74 return __riscv_isa_vendor_extension_available(VENDOR_EXT_ALL_CPUS
, vendor
, ext
);
77 static __always_inline
bool riscv_cpu_has_vendor_extension_likely(const unsigned long vendor
,
78 int cpu
, const unsigned long ext
)
80 if (!IS_ENABLED(CONFIG_RISCV_ISA_VENDOR_EXT
))
83 if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE
) &&
84 __riscv_has_extension_likely(vendor
, ext
+ RISCV_VENDOR_EXT_ALTERNATIVES_BASE
))
87 return __riscv_isa_vendor_extension_available(cpu
, vendor
, ext
);
90 static __always_inline
bool riscv_cpu_has_vendor_extension_unlikely(const unsigned long vendor
,
92 const unsigned long ext
)
94 if (!IS_ENABLED(CONFIG_RISCV_ISA_VENDOR_EXT
))
97 if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE
) &&
98 __riscv_has_extension_unlikely(vendor
, ext
+ RISCV_VENDOR_EXT_ALTERNATIVES_BASE
))
101 return __riscv_isa_vendor_extension_available(cpu
, vendor
, ext
);
104 #endif /* _ASM_VENDOR_EXTENSIONS_H */