RISC-V: Some Svpbmt fixes and cleanups
Some additionals comments and notes from autobuilders received after the series got applied, warranted some changes. * 'riscv-svpbmt' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/palmer/linux: riscv: remove usage of function-pointers from cpufeatures and t-head errata riscv: make patch-function pointer more generic in cpu_manufacturer_info struct riscv: Improve description for RISCV_ISA_SVPBMT Kconfig symbol riscv: drop cpufeature_apply_feature tracking variable riscv: fix dependency for t-head errata
This commit is contained in:
commit
73448ae620
|
@ -364,8 +364,13 @@ config RISCV_ISA_SVPBMT
|
||||||
select RISCV_ALTERNATIVE
|
select RISCV_ALTERNATIVE
|
||||||
default y
|
default y
|
||||||
help
|
help
|
||||||
Adds support to dynamically detect the presence of the SVPBMT extension
|
Adds support to dynamically detect the presence of the SVPBMT
|
||||||
(Supervisor-mode: page-based memory types) and enable its usage.
|
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.
|
The SVPBMT extension is only available on 64Bit cpus.
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ config ERRATA_SIFIVE_CIP_1200
|
||||||
|
|
||||||
config ERRATA_THEAD
|
config ERRATA_THEAD
|
||||||
bool "T-HEAD errata"
|
bool "T-HEAD errata"
|
||||||
|
depends on !XIP_KERNEL
|
||||||
select RISCV_ALTERNATIVE
|
select RISCV_ALTERNATIVE
|
||||||
help
|
help
|
||||||
All T-HEAD errata Kconfig depend on this Kconfig. Disabling
|
All T-HEAD errata Kconfig depend on this Kconfig. Disabling
|
||||||
|
|
|
@ -14,40 +14,26 @@
|
||||||
#include <asm/patch.h>
|
#include <asm/patch.h>
|
||||||
#include <asm/vendorid_list.h>
|
#include <asm/vendorid_list.h>
|
||||||
|
|
||||||
struct errata_info {
|
static bool errata_probe_pbmt(unsigned int stage,
|
||||||
char name[ERRATA_STRING_LENGTH_MAX];
|
unsigned long arch_id, unsigned long impid)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
if (arch_id != 0 || impid != 0)
|
if (arch_id != 0 || impid != 0)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
|
||||||
|
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT ||
|
||||||
|
stage == RISCV_ALTERNATIVES_MODULE)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct errata_info errata_list[ERRATA_THEAD_NUMBER] = {
|
static u32 thead_errata_probe(unsigned int stage,
|
||||||
{
|
unsigned long archid, unsigned long impid)
|
||||||
.name = "memory-types",
|
|
||||||
.stage = RISCV_ALTERNATIVES_EARLY_BOOT,
|
|
||||||
.check_func = errata_mt_check_func
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static u32 thead_errata_probe(unsigned int stage, unsigned long archid, unsigned long impid)
|
|
||||||
{
|
{
|
||||||
const struct errata_info *info;
|
|
||||||
u32 cpu_req_errata = 0;
|
u32 cpu_req_errata = 0;
|
||||||
int idx;
|
|
||||||
|
|
||||||
for (idx = 0; idx < ERRATA_THEAD_NUMBER; idx++) {
|
if (errata_probe_pbmt(stage, archid, impid))
|
||||||
info = &errata_list[idx];
|
cpu_req_errata |= (1U << ERRATA_THEAD_PBMT);
|
||||||
|
|
||||||
if ((stage == RISCV_ALTERNATIVES_MODULE ||
|
|
||||||
info->stage == stage) && info->check_func(archid, impid))
|
|
||||||
cpu_req_errata |= (1U << idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cpu_req_errata;
|
return cpu_req_errata;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ struct cpu_manufacturer_info_t {
|
||||||
unsigned long vendor_id;
|
unsigned long vendor_id;
|
||||||
unsigned long arch_id;
|
unsigned long arch_id;
|
||||||
unsigned long imp_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 long archid, unsigned long impid,
|
||||||
unsigned int stage);
|
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) {
|
switch (cpu_mfr_info->vendor_id) {
|
||||||
#ifdef CONFIG_ERRATA_SIFIVE
|
#ifdef CONFIG_ERRATA_SIFIVE
|
||||||
case SIFIVE_VENDOR_ID:
|
case SIFIVE_VENDOR_ID:
|
||||||
cpu_mfr_info->vendor_patch_func = sifive_errata_patch_func;
|
cpu_mfr_info->patch_func = sifive_errata_patch_func;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_ERRATA_THEAD
|
#ifdef CONFIG_ERRATA_THEAD
|
||||||
case THEAD_VENDOR_ID:
|
case THEAD_VENDOR_ID:
|
||||||
cpu_mfr_info->vendor_patch_func = thead_errata_patch_func;
|
cpu_mfr_info->patch_func = thead_errata_patch_func;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
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);
|
riscv_cpufeature_patch_func(begin, end, stage);
|
||||||
|
|
||||||
if (!cpu_mfr_info.vendor_patch_func)
|
if (!cpu_mfr_info.patch_func)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cpu_mfr_info.vendor_patch_func(begin, end,
|
cpu_mfr_info.patch_func(begin, end,
|
||||||
cpu_mfr_info.arch_id,
|
cpu_mfr_info.arch_id,
|
||||||
cpu_mfr_info.imp_id,
|
cpu_mfr_info.imp_id,
|
||||||
stage);
|
stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init apply_boot_alternatives(void)
|
void __init apply_boot_alternatives(void)
|
||||||
|
|
|
@ -245,12 +245,7 @@ void __init riscv_fill_hwcap(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_RISCV_ALTERNATIVE
|
#ifdef CONFIG_RISCV_ALTERNATIVE
|
||||||
struct cpufeature_info {
|
static bool __init_or_module cpufeature_probe_svpbmt(unsigned int stage)
|
||||||
char name[ERRATA_STRING_LENGTH_MAX];
|
|
||||||
bool (*check_func)(unsigned int stage);
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool __init_or_module cpufeature_svpbmt_check_func(unsigned int stage)
|
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_RISCV_ISA_SVPBMT
|
#ifdef CONFIG_RISCV_ISA_SVPBMT
|
||||||
switch (stage) {
|
switch (stage) {
|
||||||
|
@ -264,26 +259,19 @@ static bool __init_or_module cpufeature_svpbmt_check_func(unsigned int stage)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct cpufeature_info __initdata_or_module
|
/*
|
||||||
cpufeature_list[CPUFEATURE_NUMBER] = {
|
* Probe presence of individual extensions.
|
||||||
{
|
*
|
||||||
.name = "svpbmt",
|
* This code may also be executed before kernel relocation, so we cannot use
|
||||||
.check_func = cpufeature_svpbmt_check_func
|
* 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)
|
static u32 __init_or_module cpufeature_probe(unsigned int stage)
|
||||||
{
|
{
|
||||||
const struct cpufeature_info *info;
|
|
||||||
u32 cpu_req_feature = 0;
|
u32 cpu_req_feature = 0;
|
||||||
int idx;
|
|
||||||
|
|
||||||
for (idx = 0; idx < CPUFEATURE_NUMBER; idx++) {
|
if (cpufeature_probe_svpbmt(stage))
|
||||||
info = &cpufeature_list[idx];
|
cpu_req_feature |= (1U << CPUFEATURE_SVPBMT);
|
||||||
|
|
||||||
if (info->check_func(stage))
|
|
||||||
cpu_req_feature |= (1U << idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cpu_req_feature;
|
return cpu_req_feature;
|
||||||
}
|
}
|
||||||
|
@ -293,7 +281,6 @@ void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin,
|
||||||
unsigned int stage)
|
unsigned int stage)
|
||||||
{
|
{
|
||||||
u32 cpu_req_feature = cpufeature_probe(stage);
|
u32 cpu_req_feature = cpufeature_probe(stage);
|
||||||
u32 cpu_apply_feature = 0;
|
|
||||||
struct alt_entry *alt;
|
struct alt_entry *alt;
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
|
@ -307,10 +294,8 @@ void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin,
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = (1U << alt->errata_id);
|
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);
|
patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
|
||||||
cpu_apply_feature |= tmp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue