Skip to content
Permalink
Browse files
riscv: add cpufeature handling via alternatives
Some cpufeatures should be handled via the alternatives mechanism
to not incur penalties on unsupporting variants.

So add a mechanism to handle these similar to cpu erratas.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
  • Loading branch information
mmind authored and guoren83 committed Jan 18, 2022
1 parent e28ce4c commit 414a3c26e45780d9f957d3721666dfe099b8643c
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 1 deletion.
@@ -39,5 +39,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 int stage);

void riscv_cpufeature_patch_func(struct alt_entry *begin, struct alt_entry *end,
unsigned int stage);
#endif
#endif
@@ -14,6 +14,8 @@
#define ERRATA_SIFIVE_NUMBER 2
#endif

#define CPUFEATURE_NUMBER 0

#ifdef __ASSEMBLY__

#define ALT_INSN_FAULT(x) \
@@ -63,6 +63,8 @@ static void __init_or_module _apply_alternatives(struct alt_entry *begin,
struct alt_entry *end,
unsigned int stage)
{
riscv_cpufeature_patch_func(begin, end, stage);

if (!vendor_patch_func)
return;

@@ -8,8 +8,12 @@

#include <linux/bitmap.h>
#include <linux/of.h>
#include <asm/processor.h>
#include <asm/alternative.h>
#include <asm/errata_list.h>
#include <asm/hwcap.h>
#include <asm/patch.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/smp.h>
#include <asm/switch_to.h>

@@ -149,3 +153,51 @@ void __init riscv_fill_hwcap(void)
static_branch_enable(&cpu_hwcap_fpu);
#endif
}

struct cpufeature_info {
char name[ERRATA_STRING_LENGTH_MAX];
bool (*check_func)(unsigned int stage);
};

static const struct cpufeature_info cpufeature_list[CPUFEATURE_NUMBER] = {
};

static u32 __init 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);
}

return cpu_req_feature;
}

void riscv_cpufeature_patch_func(struct alt_entry *begin, struct alt_entry *end,
unsigned int stage)
{
u32 cpu_req_feature = cpufeature_probe(stage);
u32 cpu_apply_feature = 0;
struct alt_entry *alt;
u32 tmp;

for (alt = begin; alt < end; alt++) {
if (alt->vendor_id != 0)
continue;
if (alt->errata_id >= CPUFEATURE_NUMBER) {
WARN(1, "This feature id:%d is not in kernel cpufeature list", alt->errata_id);
continue;
}

tmp = (1U << alt->errata_id);
if (cpu_req_feature & tmp) {
patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
cpu_apply_feature |= tmp;
}
}
}

0 comments on commit 414a3c2

Please sign in to comment.