powerpc: Don't use 'struct ppc_inst' to reference instruction location
'struct ppc_inst' is an internal representation of an instruction, but in-memory instructions are and will remain a table of 'u32' forever. Replace all 'struct ppc_inst *' used for locating an instruction in memory by 'u32 *'. This removes a lot of undue casts to 'struct ppc_inst *'. It also helps locating ab-use of 'struct ppc_inst' dereference. Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> [mpe: Fix ppc_inst_next(), use u32 instead of unsigned int] Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/7062722b087228e42cbd896e39bfdf526d6a340a.1621516826.git.christophe.leroy@csgroup.eu
This commit is contained in:
committed by
Michael Ellerman
parent
e90a21ea80
commit
69d4d6e5fd
@ -33,18 +33,17 @@ struct fixup_entry {
|
||||
long alt_end_off;
|
||||
};
|
||||
|
||||
static struct ppc_inst *calc_addr(struct fixup_entry *fcur, long offset)
|
||||
static u32 *calc_addr(struct fixup_entry *fcur, long offset)
|
||||
{
|
||||
/*
|
||||
* We store the offset to the code as a negative offset from
|
||||
* the start of the alt_entry, to support the VDSO. This
|
||||
* routine converts that back into an actual address.
|
||||
*/
|
||||
return (struct ppc_inst *)((unsigned long)fcur + offset);
|
||||
return (u32 *)((unsigned long)fcur + offset);
|
||||
}
|
||||
|
||||
static int patch_alt_instruction(struct ppc_inst *src, struct ppc_inst *dest,
|
||||
struct ppc_inst *alt_start, struct ppc_inst *alt_end)
|
||||
static int patch_alt_instruction(u32 *src, u32 *dest, u32 *alt_start, u32 *alt_end)
|
||||
{
|
||||
int err;
|
||||
struct ppc_inst instr;
|
||||
@ -52,7 +51,7 @@ static int patch_alt_instruction(struct ppc_inst *src, struct ppc_inst *dest,
|
||||
instr = ppc_inst_read(src);
|
||||
|
||||
if (instr_is_relative_branch(ppc_inst_read(src))) {
|
||||
struct ppc_inst *target = (struct ppc_inst *)branch_target(src);
|
||||
u32 *target = (u32 *)branch_target(src);
|
||||
|
||||
/* Branch within the section doesn't need translating */
|
||||
if (target < alt_start || target > alt_end) {
|
||||
@ -69,7 +68,7 @@ static int patch_alt_instruction(struct ppc_inst *src, struct ppc_inst *dest,
|
||||
|
||||
static int patch_feature_section(unsigned long value, struct fixup_entry *fcur)
|
||||
{
|
||||
struct ppc_inst *start, *end, *alt_start, *alt_end, *src, *dest, nop;
|
||||
u32 *start, *end, *alt_start, *alt_end, *src, *dest;
|
||||
|
||||
start = calc_addr(fcur, fcur->start_off);
|
||||
end = calc_addr(fcur, fcur->end_off);
|
||||
@ -91,9 +90,8 @@ static int patch_feature_section(unsigned long value, struct fixup_entry *fcur)
|
||||
return 1;
|
||||
}
|
||||
|
||||
nop = ppc_inst(PPC_RAW_NOP());
|
||||
for (; dest < end; dest = ppc_inst_next(dest, &nop))
|
||||
raw_patch_instruction(dest, nop);
|
||||
for (; dest < end; dest++)
|
||||
raw_patch_instruction(dest, ppc_inst(PPC_RAW_NOP()));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -152,14 +150,14 @@ static void do_stf_entry_barrier_fixups(enum stf_barrier_type types)
|
||||
|
||||
// See comment in do_entry_flush_fixups() RE order of patching
|
||||
if (types & STF_BARRIER_FALLBACK) {
|
||||
patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
|
||||
patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
|
||||
patch_branch((struct ppc_inst *)(dest + 1),
|
||||
patch_instruction(dest, ppc_inst(instrs[0]));
|
||||
patch_instruction(dest + 2, ppc_inst(instrs[2]));
|
||||
patch_branch(dest + 1,
|
||||
(unsigned long)&stf_barrier_fallback, BRANCH_SET_LINK);
|
||||
} else {
|
||||
patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instrs[1]));
|
||||
patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
|
||||
patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
|
||||
patch_instruction(dest + 1, ppc_inst(instrs[1]));
|
||||
patch_instruction(dest + 2, ppc_inst(instrs[2]));
|
||||
patch_instruction(dest, ppc_inst(instrs[0]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,12 +210,12 @@ static void do_stf_exit_barrier_fixups(enum stf_barrier_type types)
|
||||
|
||||
pr_devel("patching dest %lx\n", (unsigned long)dest);
|
||||
|
||||
patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
|
||||
patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instrs[1]));
|
||||
patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
|
||||
patch_instruction((struct ppc_inst *)(dest + 3), ppc_inst(instrs[3]));
|
||||
patch_instruction((struct ppc_inst *)(dest + 4), ppc_inst(instrs[4]));
|
||||
patch_instruction((struct ppc_inst *)(dest + 5), ppc_inst(instrs[5]));
|
||||
patch_instruction(dest, ppc_inst(instrs[0]));
|
||||
patch_instruction(dest + 1, ppc_inst(instrs[1]));
|
||||
patch_instruction(dest + 2, ppc_inst(instrs[2]));
|
||||
patch_instruction(dest + 3, ppc_inst(instrs[3]));
|
||||
patch_instruction(dest + 4, ppc_inst(instrs[4]));
|
||||
patch_instruction(dest + 5, ppc_inst(instrs[5]));
|
||||
}
|
||||
printk(KERN_DEBUG "stf-barrier: patched %d exit locations (%s barrier)\n", i,
|
||||
(types == STF_BARRIER_NONE) ? "no" :
|
||||
@ -281,11 +279,11 @@ void do_uaccess_flush_fixups(enum l1d_flush_type types)
|
||||
|
||||
pr_devel("patching dest %lx\n", (unsigned long)dest);
|
||||
|
||||
patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
|
||||
patch_instruction(dest, ppc_inst(instrs[0]));
|
||||
|
||||
patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instrs[1]));
|
||||
patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
|
||||
patch_instruction((struct ppc_inst *)(dest + 3), ppc_inst(instrs[3]));
|
||||
patch_instruction(dest + 1, ppc_inst(instrs[1]));
|
||||
patch_instruction(dest + 2, ppc_inst(instrs[2]));
|
||||
patch_instruction(dest + 3, ppc_inst(instrs[3]));
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG "uaccess-flush: patched %d locations (%s flush)\n", i,
|
||||
@ -357,14 +355,14 @@ static int __do_entry_flush_fixups(void *data)
|
||||
pr_devel("patching dest %lx\n", (unsigned long)dest);
|
||||
|
||||
if (types == L1D_FLUSH_FALLBACK) {
|
||||
patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
|
||||
patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
|
||||
patch_branch((struct ppc_inst *)(dest + 1),
|
||||
patch_instruction(dest, ppc_inst(instrs[0]));
|
||||
patch_instruction(dest + 2, ppc_inst(instrs[2]));
|
||||
patch_branch(dest + 1,
|
||||
(unsigned long)&entry_flush_fallback, BRANCH_SET_LINK);
|
||||
} else {
|
||||
patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instrs[1]));
|
||||
patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
|
||||
patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
|
||||
patch_instruction(dest + 1, ppc_inst(instrs[1]));
|
||||
patch_instruction(dest + 2, ppc_inst(instrs[2]));
|
||||
patch_instruction(dest, ppc_inst(instrs[0]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,14 +374,14 @@ static int __do_entry_flush_fixups(void *data)
|
||||
pr_devel("patching dest %lx\n", (unsigned long)dest);
|
||||
|
||||
if (types == L1D_FLUSH_FALLBACK) {
|
||||
patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
|
||||
patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
|
||||
patch_branch((struct ppc_inst *)(dest + 1),
|
||||
patch_instruction(dest, ppc_inst(instrs[0]));
|
||||
patch_instruction(dest + 2, ppc_inst(instrs[2]));
|
||||
patch_branch(dest + 1,
|
||||
(unsigned long)&scv_entry_flush_fallback, BRANCH_SET_LINK);
|
||||
} else {
|
||||
patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instrs[1]));
|
||||
patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
|
||||
patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
|
||||
patch_instruction(dest + 1, ppc_inst(instrs[1]));
|
||||
patch_instruction(dest + 2, ppc_inst(instrs[2]));
|
||||
patch_instruction(dest, ppc_inst(instrs[0]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -442,9 +440,9 @@ void do_rfi_flush_fixups(enum l1d_flush_type types)
|
||||
|
||||
pr_devel("patching dest %lx\n", (unsigned long)dest);
|
||||
|
||||
patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
|
||||
patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instrs[1]));
|
||||
patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
|
||||
patch_instruction(dest, ppc_inst(instrs[0]));
|
||||
patch_instruction(dest + 1, ppc_inst(instrs[1]));
|
||||
patch_instruction(dest + 2, ppc_inst(instrs[2]));
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG "rfi-flush: patched %d locations (%s flush)\n", i,
|
||||
@ -477,7 +475,7 @@ void do_barrier_nospec_fixups_range(bool enable, void *fixup_start, void *fixup_
|
||||
dest = (void *)start + *start;
|
||||
|
||||
pr_devel("patching dest %lx\n", (unsigned long)dest);
|
||||
patch_instruction((struct ppc_inst *)dest, ppc_inst(instr));
|
||||
patch_instruction(dest, ppc_inst(instr));
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i);
|
||||
@ -520,8 +518,8 @@ void do_barrier_nospec_fixups_range(bool enable, void *fixup_start, void *fixup_
|
||||
dest = (void *)start + *start;
|
||||
|
||||
pr_devel("patching dest %lx\n", (unsigned long)dest);
|
||||
patch_instruction((struct ppc_inst *)dest, ppc_inst(instr[0]));
|
||||
patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instr[1]));
|
||||
patch_instruction(dest, ppc_inst(instr[0]));
|
||||
patch_instruction(dest + 1, ppc_inst(instr[1]));
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i);
|
||||
@ -535,7 +533,7 @@ static void patch_btb_flush_section(long *curr)
|
||||
end = (void *)curr + *(curr + 1);
|
||||
for (; start < end; start++) {
|
||||
pr_devel("patching dest %lx\n", (unsigned long)start);
|
||||
patch_instruction((struct ppc_inst *)start, ppc_inst(PPC_RAW_NOP()));
|
||||
patch_instruction(start, ppc_inst(PPC_RAW_NOP()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -554,7 +552,7 @@ void do_btb_flush_fixups(void)
|
||||
void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
|
||||
{
|
||||
long *start, *end;
|
||||
struct ppc_inst *dest;
|
||||
u32 *dest;
|
||||
|
||||
if (!(value & CPU_FTR_LWSYNC))
|
||||
return ;
|
||||
@ -571,13 +569,14 @@ void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
|
||||
static void do_final_fixups(void)
|
||||
{
|
||||
#if defined(CONFIG_PPC64) && defined(CONFIG_RELOCATABLE)
|
||||
struct ppc_inst inst, *src, *dest, *end;
|
||||
struct ppc_inst inst;
|
||||
u32 *src, *dest, *end;
|
||||
|
||||
if (PHYSICAL_START == 0)
|
||||
return;
|
||||
|
||||
src = (struct ppc_inst *)(KERNELBASE + PHYSICAL_START);
|
||||
dest = (struct ppc_inst *)KERNELBASE;
|
||||
src = (u32 *)(KERNELBASE + PHYSICAL_START);
|
||||
dest = (u32 *)KERNELBASE;
|
||||
end = (void *)src + (__end_interrupts - _stext);
|
||||
|
||||
while (src < end) {
|
||||
|
Reference in New Issue
Block a user