Commit 73448ae6 authored by Palmer Dabbelt's avatar Palmer Dabbelt

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
parents 89793a61 1771c8c9
...@@ -364,8 +364,13 @@ config RISCV_ISA_SVPBMT ...@@ -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 ...@@ -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 @@ ...@@ -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;
}
static const struct errata_info errata_list[ERRATA_THEAD_NUMBER] = { if (stage == RISCV_ALTERNATIVES_EARLY_BOOT ||
{ stage == RISCV_ALTERNATIVES_MODULE)
.name = "memory-types", return true;
.stage = RISCV_ALTERNATIVES_EARLY_BOOT,
.check_func = errata_mt_check_func 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; u32 cpu_req_errata = 0;
int idx;
for (idx = 0; idx < ERRATA_THEAD_NUMBER; idx++) {
info = &errata_list[idx];
if ((stage == RISCV_ALTERNATIVES_MODULE || if (errata_probe_pbmt(stage, archid, impid))
info->stage == stage) && info->check_func(archid, impid)) cpu_req_errata |= (1U << ERRATA_THEAD_PBMT);
cpu_req_errata |= (1U << idx);
}
return cpu_req_errata; return cpu_req_errata;
} }
......
...@@ -20,7 +20,7 @@ struct cpu_manufacturer_info_t { ...@@ -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 ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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++) {
info = &cpufeature_list[idx];
if (info->check_func(stage)) if (cpufeature_probe_svpbmt(stage))
cpu_req_feature |= (1U << idx); cpu_req_feature |= (1U << CPUFEATURE_SVPBMT);
}
return cpu_req_feature; return cpu_req_feature;
} }
...@@ -293,7 +281,6 @@ void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin, ...@@ -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, ...@@ -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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment