diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index c22f5815594847adab8d2ecb24126c79d5197036..32ffef9f6e5b4f116034fb1c65388e80d082c361 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -364,8 +364,13 @@ config RISCV_ISA_SVPBMT select RISCV_ALTERNATIVE default y help - Adds support to dynamically detect the presence of the SVPBMT extension - (Supervisor-mode: page-based memory types) and enable its usage. + Adds support to dynamically detect the presence of the SVPBMT + ISA-extension (Supervisor-mode: page-based memory types) and + enable its usage. + + The memory type for a page contains a combination of attributes + that indicate the cacheability, idempotency, and ordering + properties for access to that page. The SVPBMT extension is only available on 64Bit cpus. diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas index ebfcd5cc6eaf2fc720d603a366f74657c7cab892..457ac72c9b36d6296064201a4bfd5318095c644a 100644 --- a/arch/riscv/Kconfig.erratas +++ b/arch/riscv/Kconfig.erratas @@ -35,6 +35,7 @@ config ERRATA_SIFIVE_CIP_1200 config ERRATA_THEAD bool "T-HEAD errata" + depends on !XIP_KERNEL select RISCV_ALTERNATIVE help All T-HEAD errata Kconfig depend on this Kconfig. Disabling diff --git a/arch/riscv/errata/thead/errata.c b/arch/riscv/errata/thead/errata.c index e5d75270b99ccfadcca58394f438fa38cc1e141c..b37b6fedd53bc50932e87a49a02b59222e93391f 100644 --- a/arch/riscv/errata/thead/errata.c +++ b/arch/riscv/errata/thead/errata.c @@ -14,40 +14,26 @@ #include #include -struct errata_info { - char name[ERRATA_STRING_LENGTH_MAX]; - bool (*check_func)(unsigned long arch_id, unsigned long impid); - unsigned int stage; -}; - -static bool errata_mt_check_func(unsigned long arch_id, unsigned long impid) +static bool errata_probe_pbmt(unsigned int stage, + unsigned long arch_id, unsigned long impid) { if (arch_id != 0 || impid != 0) return false; - return true; -} -static const struct errata_info errata_list[ERRATA_THEAD_NUMBER] = { - { - .name = "memory-types", - .stage = RISCV_ALTERNATIVES_EARLY_BOOT, - .check_func = errata_mt_check_func - }, -}; + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT || + stage == RISCV_ALTERNATIVES_MODULE) + return true; + + return false; +} -static u32 thead_errata_probe(unsigned int stage, unsigned long archid, unsigned long impid) +static u32 thead_errata_probe(unsigned int stage, + unsigned long archid, unsigned long impid) { - const struct errata_info *info; u32 cpu_req_errata = 0; - int idx; - - for (idx = 0; idx < ERRATA_THEAD_NUMBER; idx++) { - info = &errata_list[idx]; - if ((stage == RISCV_ALTERNATIVES_MODULE || - info->stage == stage) && info->check_func(archid, impid)) - cpu_req_errata |= (1U << idx); - } + if (errata_probe_pbmt(stage, archid, impid)) + cpu_req_errata |= (1U << ERRATA_THEAD_PBMT); return cpu_req_errata; } diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c index c9d0d3c532235639cfb680ce2ff95a37907957eb..a7d26a00beeadb5f24a62de5456d49b267a963f5 100644 --- a/arch/riscv/kernel/alternative.c +++ b/arch/riscv/kernel/alternative.c @@ -20,7 +20,7 @@ struct cpu_manufacturer_info_t { unsigned long vendor_id; unsigned long arch_id; unsigned long imp_id; - void (*vendor_patch_func)(struct alt_entry *begin, struct alt_entry *end, + void (*patch_func)(struct alt_entry *begin, struct alt_entry *end, unsigned long archid, unsigned long impid, unsigned int stage); }; @@ -40,16 +40,16 @@ static void __init_or_module riscv_fill_cpu_mfr_info(struct cpu_manufacturer_inf switch (cpu_mfr_info->vendor_id) { #ifdef CONFIG_ERRATA_SIFIVE case SIFIVE_VENDOR_ID: - cpu_mfr_info->vendor_patch_func = sifive_errata_patch_func; + cpu_mfr_info->patch_func = sifive_errata_patch_func; break; #endif #ifdef CONFIG_ERRATA_THEAD case THEAD_VENDOR_ID: - cpu_mfr_info->vendor_patch_func = thead_errata_patch_func; + cpu_mfr_info->patch_func = thead_errata_patch_func; break; #endif default: - cpu_mfr_info->vendor_patch_func = NULL; + cpu_mfr_info->patch_func = NULL; } } @@ -68,13 +68,13 @@ static void __init_or_module _apply_alternatives(struct alt_entry *begin, riscv_cpufeature_patch_func(begin, end, stage); - if (!cpu_mfr_info.vendor_patch_func) + if (!cpu_mfr_info.patch_func) return; - cpu_mfr_info.vendor_patch_func(begin, end, - cpu_mfr_info.arch_id, - cpu_mfr_info.imp_id, - stage); + cpu_mfr_info.patch_func(begin, end, + cpu_mfr_info.arch_id, + cpu_mfr_info.imp_id, + stage); } void __init apply_boot_alternatives(void) diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index 4fbfa1be077e1c56cc32b82b32d7994d5d3ade7b..1b3ec44e25f56ae103451b32c9e31b789e99fe51 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -245,12 +245,7 @@ void __init riscv_fill_hwcap(void) } #ifdef CONFIG_RISCV_ALTERNATIVE -struct cpufeature_info { - char name[ERRATA_STRING_LENGTH_MAX]; - bool (*check_func)(unsigned int stage); -}; - -static bool __init_or_module cpufeature_svpbmt_check_func(unsigned int stage) +static bool __init_or_module cpufeature_probe_svpbmt(unsigned int stage) { #ifdef CONFIG_RISCV_ISA_SVPBMT switch (stage) { @@ -264,26 +259,19 @@ static bool __init_or_module cpufeature_svpbmt_check_func(unsigned int stage) return false; } -static const struct cpufeature_info __initdata_or_module -cpufeature_list[CPUFEATURE_NUMBER] = { - { - .name = "svpbmt", - .check_func = cpufeature_svpbmt_check_func - }, -}; - +/* + * Probe presence of individual extensions. + * + * This code may also be executed before kernel relocation, so we cannot use + * addresses generated by the address-of operator as they won't be valid in + * this context. + */ static u32 __init_or_module cpufeature_probe(unsigned int stage) { - const struct cpufeature_info *info; u32 cpu_req_feature = 0; - int idx; - - for (idx = 0; idx < CPUFEATURE_NUMBER; idx++) { - info = &cpufeature_list[idx]; - if (info->check_func(stage)) - cpu_req_feature |= (1U << idx); - } + if (cpufeature_probe_svpbmt(stage)) + cpu_req_feature |= (1U << CPUFEATURE_SVPBMT); return cpu_req_feature; } @@ -293,7 +281,6 @@ void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin, unsigned int stage) { u32 cpu_req_feature = cpufeature_probe(stage); - u32 cpu_apply_feature = 0; struct alt_entry *alt; u32 tmp; @@ -307,10 +294,8 @@ void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin, } tmp = (1U << alt->errata_id); - if (cpu_req_feature & tmp) { + if (cpu_req_feature & tmp) patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len); - cpu_apply_feature |= tmp; - } } } #endif