[PATCH 1/3] powerpc/code-patching: Add generic memory patching
Benjamin Gray
bgray at linux.ibm.com
Fri Feb 10 11:45:12 AEDT 2023
On Thu, 2023-02-09 at 07:15 +0000, Christophe Leroy wrote:
> > +static inline int patch_uint(u32 *addr, unsigned int val)
> > +{
> > + return patch_instruction(addr, ppc_inst(val));
>
> Would it make more sense that patch_instruction() calls patch_uint()
> instead of the reverse ?
>
That's what I had originally, but I figured it would be nicer to see
'patch_instruction' in the disassembly given it's still the main usage.
It's equivalent otherwise though.
> > diff --git a/arch/powerpc/lib/code-patching.c
> > b/arch/powerpc/lib/code-patching.c
> > index b00112d7ad46..0f7e9949faf0 100644
> > --- a/arch/powerpc/lib/code-patching.c
> > +++ b/arch/powerpc/lib/code-patching.c
> > @@ -20,16 +20,14 @@
> > #include <asm/code-patching.h>
> > #include <asm/inst.h>
> >
> > -static int __patch_instruction(u32 *exec_addr, ppc_inst_t instr,
> > u32 *patch_addr)
> > +static int __patch_memory(void *exec_addr, unsigned long val, void
> > *patch_addr,
> > + bool is_dword)
> > {
> > - if (!ppc_inst_prefixed(instr)) {
> > - u32 val = ppc_inst_val(instr);
> > -
> > - __put_kernel_nofault(patch_addr, &val, u32,
> > failed);
> > - } else {
> > - u64 val = ppc_inst_as_ulong(instr);
> > -
> > + if (IS_ENABLED(CONFIG_PPC64) && unlikely(is_dword)) {
> > __put_kernel_nofault(patch_addr, &val, u64,
> > failed);
> > + } else {
> > + unsigned int val32 = val;
>
> Why unsigned int and not u32 as before ?
>
No particular reason, I just tend to use int/long over 32/64 in code
compiled on 32 bit as well and there was a long period of time between
removing the original vars and fixing the big endian issue.
> > +#ifdef CONFIG_PPC64
> > +
> > +int patch_instruction(u32 *addr, ppc_inst_t instr)
> > +{
> > + if (ppc_inst_prefixed(instr))
> > + return patch_memory(addr, ppc_inst_as_ulong(instr),
> > true);
> > + else
> > + return patch_memory(addr, ppc_inst_val(instr),
> > false);
> > +}
> > +NOKPROBE_SYMBOL(patch_instruction)
> > +
> > +int patch_uint(void *addr, unsigned int val)
> > +{
> > + return patch_memory(addr, val, false);
> > +}
> > +NOKPROBE_SYMBOL(patch_uint)
> > +
> > +int patch_ulong(void *addr, unsigned long val)
> > +{
> > + return patch_memory(addr, val, true);
> > +}
> > +NOKPROBE_SYMBOL(patch_ulong)
> > +
> > +#else
> > +
> > +noinline int patch_instruction(u32 *addr, ppc_inst_t instr)
> > +{
> > + return patch_memory(addr, ppc_inst_val(instr), false);
> > +}
>
> A comment explaining the reason for the noinline would be welcome
> here.
Yeah makes sense
> By the way, would the noinline change anything on PPC64 ? If not we
> could have a common function as ppc_inst_prefixed() constant folds to
> false in PPC32.
On ppc64 that prevents patch_branch() from calling patch_memory()
directly with is_dword=false.
More information about the Linuxppc-dev
mailing list