Commit 6b289911 authored by Christophe Leroy's avatar Christophe Leroy Committed by Michael Ellerman

powerpc/features: Add capability to update mmu features later

On powerpc32, features fixup is performed very early and that's too
early to read the cmdline and take into account 'nosmap' parameter.

On the other hand, no userspace access is performed that early and
KUAP feature fixup can be performed later.

Add a function to update mmu features. The function is passed a
mask with the features that can be updated.
Signed-off-by: default avatarChristophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/31b27ee2c9d338f4f82cd8cd69d6bff979495290.1689091022.git.christophe.leroy@csgroup.eu
parent 38bb171b
......@@ -292,6 +292,7 @@ extern long __start___barrier_nospec_fixup, __stop___barrier_nospec_fixup;
extern long __start__btb_flush_fixup, __stop__btb_flush_fixup;
void apply_feature_fixups(void);
void update_mmu_feature_fixups(unsigned long mask);
void setup_feature_keys(void);
#endif
......
......@@ -67,7 +67,8 @@ static int patch_alt_instruction(u32 *src, u32 *dest, u32 *alt_start, u32 *alt_e
return 0;
}
static int patch_feature_section(unsigned long value, struct fixup_entry *fcur)
static int patch_feature_section_mask(unsigned long value, unsigned long mask,
struct fixup_entry *fcur)
{
u32 *start, *end, *alt_start, *alt_end, *src, *dest;
......@@ -79,7 +80,7 @@ static int patch_feature_section(unsigned long value, struct fixup_entry *fcur)
if ((alt_end - alt_start) > (end - start))
return 1;
if ((value & fcur->mask) == fcur->value)
if ((value & fcur->mask & mask) == (fcur->value & mask))
return 0;
src = alt_start;
......@@ -97,7 +98,8 @@ static int patch_feature_section(unsigned long value, struct fixup_entry *fcur)
return 0;
}
void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
static void do_feature_fixups_mask(unsigned long value, unsigned long mask,
void *fixup_start, void *fixup_end)
{
struct fixup_entry *fcur, *fend;
......@@ -105,7 +107,7 @@ void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
fend = fixup_end;
for (; fcur < fend; fcur++) {
if (patch_feature_section(value, fcur)) {
if (patch_feature_section_mask(value, mask, fcur)) {
WARN_ON(1);
printk("Unable to patch feature section at %p - %p" \
" with %p - %p\n",
......@@ -117,6 +119,11 @@ void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
}
}
void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
{
do_feature_fixups_mask(value, ~0, fixup_start, fixup_end);
}
#ifdef CONFIG_PPC_BARRIER_NOSPEC
static bool is_fixup_addr_valid(void *dest, size_t size)
{
......@@ -651,6 +658,17 @@ void __init apply_feature_fixups(void)
do_final_fixups();
}
void __init update_mmu_feature_fixups(unsigned long mask)
{
saved_mmu_features &= ~mask;
saved_mmu_features |= cur_cpu_spec->mmu_features & mask;
do_feature_fixups_mask(cur_cpu_spec->mmu_features, mask,
PTRRELOC(&__start___mmu_ftr_fixup),
PTRRELOC(&__stop___mmu_ftr_fixup));
mmu_feature_keys_init();
}
void __init setup_feature_keys(void)
{
/*
......@@ -683,6 +701,11 @@ late_initcall(check_features);
#define check(x) \
if (!(x)) printk("feature-fixups: test failed at line %d\n", __LINE__);
static int patch_feature_section(unsigned long value, struct fixup_entry *fcur)
{
return patch_feature_section_mask(value, ~0, fcur);
}
/* This must be after the text it fixes up, vmlinux.lds.S enforces that atm */
static struct fixup_entry fixup;
......
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