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
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.
......
......@@ -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
......
......@@ -14,40 +14,26 @@
#include <asm/patch.h>
#include <asm/vendorid_list.h>
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;
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT ||
stage == RISCV_ALTERNATIVES_MODULE)
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
},
};
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;
}
......
......@@ -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,10 +68,10 @@ 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.patch_func(begin, end,
cpu_mfr_info.arch_id,
cpu_mfr_info.imp_id,
stage);
......
......@@ -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
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