[PATCH v8 5/6] powerpc/code-patching: Use temporary mm for Radix MMU

Benjamin Gray bgray at linux.ibm.com
Mon Oct 24 16:17:10 AEDT 2022


On Mon, 2022-10-24 at 14:45 +1100, Russell Currey wrote:
> On Fri, 2022-10-21 at 16:22 +1100, Benjamin Gray wrote:
> > From: "Christopher M. Riedl" <cmr at bluescreens.de>
> > 
> > x86 supports the notion of a temporary mm which restricts access to
> > temporary PTEs to a single CPU. A temporary mm is useful for
> > situations
> > where a CPU needs to perform sensitive operations (such as patching
> > a
> > STRICT_KERNEL_RWX kernel) requiring temporary mappings without
> > exposing
> > said mappings to other CPUs. Another benefit is that other CPU TLBs
> > do
> > not need to be flushed when the temporary mm is torn down.
> > 
> > Mappings in the temporary mm can be set in the userspace portion of
> > the
> > address-space.
> > 
> > Interrupts must be disabled while the temporary mm is in use. HW
> > breakpoints, which may have been set by userspace as watchpoints on
> > addresses now within the temporary mm, are saved and disabled when
> > loading the temporary mm. The HW breakpoints are restored when
> > unloading
> > the temporary mm. All HW breakpoints are indiscriminately disabled
> > while
> > the temporary mm is in use - this may include breakpoints set by
> > perf.
> > 
> > Use the `poking_init` init hook to prepare a temporary mm and
> > patching
> > address. Initialize the temporary mm by copying the init mm. Choose
> > a
> > randomized patching address inside the temporary mm userspace
> > address
> > space. The patching address is randomized between PAGE_SIZE and
> > DEFAULT_MAP_WINDOW-PAGE_SIZE.
> > 
> > Bits of entropy with 64K page size on BOOK3S_64:
> > 
> >         bits of entropy = log2(DEFAULT_MAP_WINDOW_USER64 /
> > PAGE_SIZE)
> > 
> >         PAGE_SIZE=64K, DEFAULT_MAP_WINDOW_USER64=128TB
> >         bits of entropy = log2(128TB / 64K)
> >         bits of entropy = 31
> > 
> > The upper limit is DEFAULT_MAP_WINDOW due to how the Book3s64 Hash
> > MMU
> > operates - by default the space above DEFAULT_MAP_WINDOW is not
> > available. Currently the Hash MMU does not use a temporary mm so
> > technically this upper limit isn't necessary; however, a larger
> > randomization range does not further "harden" this overall approach
> > and
> > future work may introduce patching with a temporary mm on Hash as
> > well.
> > 
> > Randomization occurs only once during initialization for each CPU
> > as
> > it
> > comes online.
> > 
> > The patching page is mapped with PAGE_KERNEL to set EAA[0] for the
> > PTE
> > which ignores the AMR (so no need to unlock/lock KUAP) according to
> > PowerISA v3.0b Figure 35 on Radix.
> > 
> > Based on x86 implementation:
> > 
> > commit 4fc19708b165
> > ("x86/alternatives: Initialize temporary mm for patching")
> > 
> > and:
> > 
> > commit b3fd8e83ada0
> > ("x86/alternatives: Use temporary mm for text poking")
> > 
> > ---
> 
> Is the section following the --- your addendum to Chris' patch?  That
> cuts it off from git, including your signoff.  It'd be better to have
> it together as one commit message and note the bits you contributed
> below the --- after your signoff.
> 
> Commits where you're modifying someone else's previous work should
> include their signoff above yours, as well.

Addendum to his wording, to break it off from the "From..." section
(which is me splicing together his comments from previous patches with
some minor changes to account for the patch changes). I found out
earlier today that Git will treat it as a comment :(

I'll add the signed off by back, I wasn't sure whether to leave it
there after making changes (same in patch 2).
 
> > +static int __do_patch_instruction_mm(u32 *addr, ppc_inst_t instr)
> > +{
> > +       int err;
> > +       u32 *patch_addr;
> > +       unsigned long text_poke_addr;
> > +       pte_t *pte;
> > +       unsigned long pfn = get_patch_pfn(addr);
> > +       struct mm_struct *patching_mm;
> > +       struct temp_mm_state prev;
> 
> Reverse christmas tree?  If we care

Currently it's mirroring the __do_patch_instruction declarations, with
extra ones at the bottom.


More information about the Linuxppc-dev mailing list