Le 25/10/2022 à 06:44, Benjamin Gray a écrit : > With the temp mm context support, there are CPU local variables to hold > the patch address and pte. Use these in the non-temp mm path as well > instead of adding a level of indirection through the text_poke_area > vm_struct and pointer chasing the pte. > > As both paths use these fields now, there is no need to let unreferenced > variables be dropped by the compiler, so it is cleaner to merge them into > a single context struct. This has the additional benefit of removing a > redundant CPU local pointer, as only one of cpu_patching_mm / > text_poke_area is ever used, while remaining well-typed.
Another advantage is to group all data for a given CPU in the same cacheline. > > Signed-off-by: Benjamin Gray <bg...@linux.ibm.com> > --- > v9: * Consolidate patching context into single struct > --- > arch/powerpc/lib/code-patching.c | 58 ++++++++++++++++++-------------- > 1 file changed, 33 insertions(+), 25 deletions(-) > > diff --git a/arch/powerpc/lib/code-patching.c > b/arch/powerpc/lib/code-patching.c > index 3fe99d0086fc..cefb938f7217 100644 > --- a/arch/powerpc/lib/code-patching.c > +++ b/arch/powerpc/lib/code-patching.c > @@ -48,10 +48,16 @@ int raw_patch_instruction(u32 *addr, ppc_inst_t instr) > > #ifdef CONFIG_STRICT_KERNEL_RWX > > -static DEFINE_PER_CPU(struct vm_struct *, text_poke_area); > -static DEFINE_PER_CPU(struct mm_struct *, cpu_patching_mm); > -static DEFINE_PER_CPU(unsigned long, cpu_patching_addr); > -static DEFINE_PER_CPU(pte_t *, cpu_patching_pte); > +struct patch_context { > + union { > + struct vm_struct *text_poke_area; > + struct mm_struct *mm; > + }; > + unsigned long addr; > + pte_t * pte; > +}; > + > +static DEFINE_PER_CPU(struct patch_context, cpu_patching_context); > > static int map_patch_area(void *addr, unsigned long text_poke_addr); > static void unmap_patch_area(unsigned long addr); > @@ -116,15 +122,19 @@ static int text_area_cpu_up(unsigned int cpu) > > unmap_patch_area(addr); > > - this_cpu_write(text_poke_area, area); > + this_cpu_write(cpu_patching_context.text_poke_area, area); > + this_cpu_write(cpu_patching_context.addr, addr); > + this_cpu_write(cpu_patching_context.pte, virt_to_kpte(addr)); > > return 0; > } > > static int text_area_cpu_down(unsigned int cpu) > { > - free_vm_area(this_cpu_read(text_poke_area)); > - this_cpu_write(text_poke_area, NULL); > + free_vm_area(this_cpu_read(cpu_patching_context.text_poke_area)); > + this_cpu_write(cpu_patching_context.text_poke_area, NULL); > + this_cpu_write(cpu_patching_context.addr, 0); > + this_cpu_write(cpu_patching_context.pte, NULL); > return 0; > } > > @@ -172,9 +182,9 @@ static int text_area_cpu_up_mm(unsigned int cpu) > if (WARN_ON(!ptep)) > goto fail_no_pte; > > - this_cpu_write(cpu_patching_mm, mm); > - this_cpu_write(cpu_patching_addr, addr); > - this_cpu_write(cpu_patching_pte, ptep); > + this_cpu_write(cpu_patching_context.mm, mm); > + this_cpu_write(cpu_patching_context.addr, addr); > + this_cpu_write(cpu_patching_context.pte, ptep); > > return 0; > > @@ -202,8 +212,8 @@ static int text_area_cpu_down_mm(unsigned int cpu) > p4d_t *p4dp; > pgd_t *pgdp; > > - mm = this_cpu_read(cpu_patching_mm); > - addr = this_cpu_read(cpu_patching_addr); > + mm = this_cpu_read(cpu_patching_context.mm); > + addr = this_cpu_read(cpu_patching_context.addr); > > pgdp = pgd_offset(mm, addr); > p4dp = p4d_offset(pgdp, addr); > @@ -223,9 +233,9 @@ static int text_area_cpu_down_mm(unsigned int cpu) > > mmput(mm); > > - this_cpu_write(cpu_patching_mm, NULL); > - this_cpu_write(cpu_patching_addr, 0); > - this_cpu_write(cpu_patching_pte, NULL); > + this_cpu_write(cpu_patching_context.mm, NULL); > + this_cpu_write(cpu_patching_context.addr, 0); > + this_cpu_write(cpu_patching_context.pte, NULL); > > return 0; > } > @@ -316,9 +326,9 @@ static int __do_patch_instruction_mm(u32 *addr, > ppc_inst_t instr) > struct mm_struct *patching_mm; > struct mm_struct *orig_mm; > > - patching_mm = __this_cpu_read(cpu_patching_mm); > - pte = __this_cpu_read(cpu_patching_pte); > - text_poke_addr = __this_cpu_read(cpu_patching_addr); > + patching_mm = __this_cpu_read(cpu_patching_context.mm); > + pte = __this_cpu_read(cpu_patching_context.pte); > + text_poke_addr = __this_cpu_read(cpu_patching_context.addr); > patch_addr = (u32 *)(text_poke_addr + offset_in_page(addr)); > > if (unlikely(!patching_mm)) > @@ -357,19 +367,17 @@ static int __do_patch_instruction(u32 *addr, ppc_inst_t > instr) > { > int err; > u32 *patch_addr; > - struct vm_struct *area; > unsigned long text_poke_addr; > pte_t *pte; > unsigned long pfn = get_patch_pfn(addr); > > - area = __this_cpu_read(text_poke_area); > - if (unlikely(!area)) > - return -ENOMEM; > - > - text_poke_addr = (unsigned long)area->addr & PAGE_MASK; > + text_poke_addr = (unsigned > long)__this_cpu_read(cpu_patching_context.addr) & PAGE_MASK; > patch_addr = (u32 *)(text_poke_addr + offset_in_page(addr)); > > - pte = virt_to_kpte(text_poke_addr); > + if (unlikely(!text_poke_addr)) > + return -ENOMEM; > + > + pte = __this_cpu_read(cpu_patching_context.pte); > __set_pte_at(&init_mm, text_poke_addr, pte, pfn_pte(pfn, PAGE_KERNEL), > 0); > /* See ptesync comment in radix__set_pte_at() */ > if (radix_enabled())