Future features may need to be applied at a different time during boot, so allow defining stages for alternatives and handling them differently depending on the stage. Also make the alternatives-location more flexible so that future stages may provide their own location. Signed-off-by: Heiko Stuebner <heiko@xxxxxxxxx> --- arch/riscv/errata/sifive/errata.c | 3 ++- arch/riscv/include/asm/alternative.h | 5 ++++- arch/riscv/kernel/alternative.c | 26 +++++++++++++++++--------- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/arch/riscv/errata/sifive/errata.c b/arch/riscv/errata/sifive/errata.c index f5e5ae70e829..4fe03ac41fd7 100644 --- a/arch/riscv/errata/sifive/errata.c +++ b/arch/riscv/errata/sifive/errata.c @@ -80,7 +80,8 @@ static void __init warn_miss_errata(u32 miss_errata) } void __init sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end, - unsigned long archid, unsigned long impid) + unsigned long archid, unsigned long impid, + unsigned int stage) { struct alt_entry *alt; u32 cpu_req_errata = sifive_errata_probe(archid, impid); diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h index e625d3cafbed..811bdd8027db 100644 --- a/arch/riscv/include/asm/alternative.h +++ b/arch/riscv/include/asm/alternative.h @@ -17,6 +17,8 @@ #include <linux/stddef.h> #include <asm/hwcap.h> +#define RISCV_ALTERNATIVES_BOOT 0 /* alternatives applied during regular boot */ + void __init apply_boot_alternatives(void); struct alt_entry { @@ -33,7 +35,8 @@ struct errata_checkfunc_id { }; void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end, - unsigned long archid, unsigned long impid); + unsigned long archid, unsigned long impid, + unsigned int stage); #endif #endif diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c index e8b4a0fe488c..02db62f55bac 100644 --- a/arch/riscv/kernel/alternative.c +++ b/arch/riscv/kernel/alternative.c @@ -22,8 +22,8 @@ static struct cpu_manufacturer_info_t { } cpu_mfr_info; static void (*vendor_patch_func)(struct alt_entry *begin, struct alt_entry *end, - unsigned long archid, - unsigned long impid) __initdata; + unsigned long archid, unsigned long impid, + unsigned int stage) __initdata; static inline void __init riscv_fill_cpu_mfr_info(void) { @@ -58,6 +58,18 @@ static void __init init_alternative(void) * a feature detect on the boot CPU). No need to worry about other CPUs * here. */ +static void __init _apply_alternatives(struct alt_entry *begin, + struct alt_entry *end, + unsigned int stage) +{ + if (!vendor_patch_func) + return; + + vendor_patch_func(begin, end, + cpu_mfr_info.arch_id, cpu_mfr_info.imp_id, + stage); +} + void __init apply_boot_alternatives(void) { /* If called on non-boot cpu things could go wrong */ @@ -65,11 +77,7 @@ void __init apply_boot_alternatives(void) init_alternative(); - if (!vendor_patch_func) - return; - - vendor_patch_func((struct alt_entry *)__alt_start, - (struct alt_entry *)__alt_end, - cpu_mfr_info.arch_id, cpu_mfr_info.imp_id); + _apply_alternatives((struct alt_entry *)__alt_start, + (struct alt_entry *)__alt_end, + RISCV_ALTERNATIVES_BOOT); } - -- 2.30.2