On Fri, Apr 26, 2024 at 02:29:20PM -0700, Charlie Jenkins wrote: > index c073494519eb..dd7e8e0c0af1 100644 > --- a/arch/riscv/kernel/cpufeature.c > +++ b/arch/riscv/kernel/cpufeature.c > @@ -844,25 +844,41 @@ void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin, > { > struct alt_entry *alt; > void *oldptr, *altptr; > - u16 id, value; > + u16 id, value, vendor; > > if (stage == RISCV_ALTERNATIVES_EARLY_BOOT) > return; > > for (alt = begin; alt < end; alt++) { > - if (alt->vendor_id != 0) > - continue; > - > id = PATCH_ID_CPUFEATURE_ID(alt->patch_id); > + vendor = PATCH_ID_CPUFEATURE_ID(alt->vendor_id); > > - if (id >= RISCV_ISA_EXT_MAX) { > + /* > + * Any alternative with a patch_id that is less than > + * RISCV_ISA_EXT_MAX is interpreted as a standard extension. > + * > + * Any alternative with patch_id that is greater than or equal > + * to RISCV_VENDOR_EXT_ALTERNATIVES_BASE is interpreted as a > + * vendor extension. I think this stuff is all fine, since we can always re-jig things in the future if needs be. > + */ > + if (id < RISCV_ISA_EXT_MAX) { > + /* > + * This patch should be treated as errata so skip > + * processing here. > + */ > + if (alt->vendor_id != 0) > + continue; > + > + if (!__riscv_isa_extension_available(NULL, id)) > + continue; > + } else if (id >= RISCV_VENDOR_EXT_ALTERNATIVES_BASE) { > + if (!__riscv_isa_vendor_extension_available(VENDOR_EXT_ALL_CPUS, vendor, id)) > + continue; > + } else { > WARN(1, "This extension id:%d is not in ISA extension list", id); > continue; > } > > - if (!__riscv_isa_extension_available(NULL, id)) > - continue; > - > value = PATCH_ID_CPUFEATURE_VALUE(alt->patch_id); > if (!riscv_cpufeature_patch_check(id, value)) > continue; > diff --git a/arch/riscv/kernel/vendor_extensions.c b/arch/riscv/kernel/vendor_extensions.c > index f76cb3013c2d..eced93eec5a6 100644 > --- a/arch/riscv/kernel/vendor_extensions.c > +++ b/arch/riscv/kernel/vendor_extensions.c > @@ -3,6 +3,7 @@ > * Copyright 2024 Rivos, Inc > */ > > +#include <asm/vendorid_list.h> > #include <asm/vendor_extensions.h> > #include <asm/vendor_extensions/thead.h> > > @@ -16,3 +17,42 @@ const struct riscv_isa_vendor_ext_data_list *riscv_isa_vendor_ext_list[] = { > }; > > const size_t riscv_isa_vendor_ext_list_size = ARRAY_SIZE(riscv_isa_vendor_ext_list); > + > +/** > + * __riscv_isa_vendor_extension_available() - Check whether given vendor > + * extension is available or not. > + * > + * @cpu: check if extension is available on this cpu > + * @vendor: vendor that the extension is a member of > + * @bit: bit position of the desired extension > + * Return: true or false > + * > + * NOTE: When cpu is -1, will check if extension is available on all cpus > + */ > +bool __riscv_isa_vendor_extension_available(int cpu, unsigned long vendor, unsigned int bit) > +{ > + unsigned long *bmap; > + struct riscv_isainfo *cpu_bmap; > + size_t bmap_size; > + > + switch (vendor) { > +#ifdef CONFIG_RISCV_ISA_VENDOR_EXT_THEAD > + case THEAD_VENDOR_ID: > + bmap = riscv_isa_vendor_ext_list_thead.vendor_bitmap; > + cpu_bmap = riscv_isa_vendor_ext_list_thead.per_hart_vendor_bitmap; > + bmap_size = riscv_isa_vendor_ext_list_thead.bitmap_size; > + break; > +#endif > + default: > + return false; > + } > + > + if (cpu != -1) > + bmap = cpu_bmap[cpu].isa; > + > + if (bit >= bmap_size) > + return false; > + > + return test_bit(bit, bmap) ? true : false; > +} > +EXPORT_SYMBOL_GPL(__riscv_isa_vendor_extension_available); I wonder if we care to implement a non __ prefixed version of this, like the standard stuff? The only __ version users of the standard one are in kvm and core arch code, the "external" users all use the non-prefixed version. In any case, Reviewed-by: Conor Dooley <conor.dooley@xxxxxxxxxxxxx> Cheers, Conor.
Attachment:
signature.asc
Description: PGP signature