[PATCH] arm64: entry: simplify trampoline data page

Mark Rutland mark.rutland at arm.com
Wed Jun 22 08:04:51 PDT 2022


On Wed, Jun 22, 2022 at 04:41:41PM +0200, Ard Biesheuvel wrote:
> On Wed, 27 Apr 2022 at 12:23, Ard Biesheuvel <ardb at kernel.org> wrote:
> >
> > Get rid of some clunky open coded arithmetic on section addresses, by
> > emitting the trampoline data variables into a separate, dedicated r/o
> > data section, and putting it at the next page boundary. This way, we can
> > access the literals via single LDR instruction.
> >
> > While at it, get rid of other, implicit literals, and use ADRP/ADD or
> > MOVZ/MOVK sequences, as appropriate. Note that the latter are only
> > supported for CONFIG_RELOCATABLE=n (which is usually the case if
> > CONFIG_RANDOMIZE_BASE=n), so update the CPP conditionals to reflect
> > this.
> >
> > Cc: James Morse <james.morse at arm.com>
> > Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
> 
> Ping, in case this one slipped behind the desk.

Sorry for the delay. THis has been on my queue of things to look at with a
bunch of other stuff, and I've had some difficulty prioritizing all that.

> 
> > ---
> >  arch/arm64/include/asm/fixmap.h |  4 +-
> >  arch/arm64/kernel/entry.S       | 45 ++++++--------------
> >  arch/arm64/kernel/vmlinux.lds.S |  3 +-
> >  arch/arm64/mm/mmu.c             | 10 ++---
> >  4 files changed, 22 insertions(+), 40 deletions(-)
> >
> > diff --git a/arch/arm64/include/asm/fixmap.h b/arch/arm64/include/asm/fixmap.h
> > index daff882883f9..71ed5fdf718b 100644
> > --- a/arch/arm64/include/asm/fixmap.h
> > +++ b/arch/arm64/include/asm/fixmap.h
> > @@ -62,10 +62,12 @@ enum fixed_addresses {
> >  #endif /* CONFIG_ACPI_APEI_GHES */
> >
> >  #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
> > +#ifdef CONFIG_RELOCATABLE
> > +       FIX_ENTRY_TRAMP_TEXT4,  /* one extra slot for the data page */
> > +#endif
> >         FIX_ENTRY_TRAMP_TEXT3,
> >         FIX_ENTRY_TRAMP_TEXT2,
> >         FIX_ENTRY_TRAMP_TEXT1,
> > -       FIX_ENTRY_TRAMP_DATA,
> >  #define TRAMP_VALIAS           (__fix_to_virt(FIX_ENTRY_TRAMP_TEXT1))
> >  #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
> >         __end_of_permanent_fixed_addresses,
> > diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
> > index ede028dee81b..aed2b41e05aa 100644
> > --- a/arch/arm64/kernel/entry.S
> > +++ b/arch/arm64/kernel/entry.S
> > @@ -636,18 +636,20 @@ alternative_else_nop_endif
> >          */
> >         .endm
> >
> > -       .macro tramp_data_page  dst
> > -       adr_l   \dst, .entry.tramp.text
> > -       sub     \dst, \dst, PAGE_SIZE
> > -       .endm
> > -
> > -       .macro tramp_data_read_var      dst, var
> > -#ifdef CONFIG_RANDOMIZE_BASE
> > -       tramp_data_page         \dst
> > -       add     \dst, \dst, #:lo12:__entry_tramp_data_\var
> > -       ldr     \dst, [\dst]
> > +       .macro          tramp_data_read_var     dst, var
> > +#ifdef CONFIG_RELOCATABLE
> > +       ldr             \dst, .L__tramp_data_\var
> > +       .ifndef         .L__tramp_data_\var
> > +       .pushsection    ".entry.tramp.rodata", "a", %progbits
> > +       .align          3
> > +.L__tramp_data_\var:
> > +       .quad           \var
> > +       .popsection
> > +       .endif
> >  #else
> > -       ldr     \dst, =\var
> > +       movz            \dst, :abs_g2_s:\var
> > +       movk            \dst, :abs_g1_nc:\var
> > +       movk            \dst, :abs_g0_nc:\var
> >  #endif
> >         .endm

Given the lack of a g3 reloc, I assumme `var` is always an address, and we're
assuming it's always in the upper 48-bits? I think it'd be worth a comment as
to why this is safe, or just use a g3 reloc since then it's always good per
inspection.

I'm a bit confused that we've put the var into the literal; I thought the idea
here was that it was secret and needed to be placed in a page not mapped during
userspace. Is the assumption there that it's pointless for !RELOCATABLE kernels
since it can be known anyway, have I misunderstood, or something else?

Otherwise this all looks good superficially; I just haven't had the time to
page it all in.

Mark.

> >
> > @@ -695,7 +697,7 @@ alternative_else_nop_endif
> >         msr     vbar_el1, x30
> >         isb
> >         .else
> > -       ldr     x30, =vectors
> > +       adr_l   x30, vectors
> >         .endif // \kpti == 1
> >
> >         .if     \bhb == BHB_MITIGATION_FW
> > @@ -764,24 +766,7 @@ SYM_CODE_END(tramp_exit_native)
> >  SYM_CODE_START(tramp_exit_compat)
> >         tramp_exit      32
> >  SYM_CODE_END(tramp_exit_compat)
> > -
> > -       .ltorg
> >         .popsection                             // .entry.tramp.text
> > -#ifdef CONFIG_RANDOMIZE_BASE
> > -       .pushsection ".rodata", "a"
> > -       .align PAGE_SHIFT
> > -SYM_DATA_START(__entry_tramp_data_start)
> > -__entry_tramp_data_vectors:
> > -       .quad   vectors
> > -#ifdef CONFIG_ARM_SDE_INTERFACE
> > -__entry_tramp_data___sdei_asm_handler:
> > -       .quad   __sdei_asm_handler
> > -#endif /* CONFIG_ARM_SDE_INTERFACE */
> > -__entry_tramp_data_this_cpu_vector:
> > -       .quad   this_cpu_vector
> > -SYM_DATA_END(__entry_tramp_data_start)
> > -       .popsection                             // .rodata
> > -#endif /* CONFIG_RANDOMIZE_BASE */
> >  #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
> >
> >  /*
> > @@ -932,7 +917,6 @@ NOKPROBE(call_on_irq_stack)
> >   * This clobbers x4, __sdei_handler() will restore this from firmware's
> >   * copy.
> >   */
> > -.ltorg
> >  .pushsection ".entry.tramp.text", "ax"
> >  SYM_CODE_START(__sdei_asm_entry_trampoline)
> >         mrs     x4, ttbr1_el1
> > @@ -967,7 +951,6 @@ SYM_CODE_START(__sdei_asm_exit_trampoline)
> >  1:     sdei_handler_exit exit_mode=x2
> >  SYM_CODE_END(__sdei_asm_exit_trampoline)
> >  NOKPROBE(__sdei_asm_exit_trampoline)
> > -       .ltorg
> >  .popsection            // .entry.tramp.text
> >  #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
> >
> > diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
> > index edaf0faf766f..17e554be9198 100644
> > --- a/arch/arm64/kernel/vmlinux.lds.S
> > +++ b/arch/arm64/kernel/vmlinux.lds.S
> > @@ -117,7 +117,8 @@ jiffies = jiffies_64;
> >         __entry_tramp_text_start = .;                   \
> >         *(.entry.tramp.text)                            \
> >         . = ALIGN(PAGE_SIZE);                           \
> > -       __entry_tramp_text_end = .;
> > +       __entry_tramp_text_end = .;                     \
> > +       *(.entry.tramp.rodata)
> >  #else
> >  #define TRAMP_TEXT
> >  #endif
> > diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> > index 626ec32873c6..be4d6c3f5692 100644
> > --- a/arch/arm64/mm/mmu.c
> > +++ b/arch/arm64/mm/mmu.c
> > @@ -665,13 +665,9 @@ static int __init map_entry_trampoline(void)
> >                 __set_fixmap(FIX_ENTRY_TRAMP_TEXT1 - i,
> >                              pa_start + i * PAGE_SIZE, prot);
> >
> > -       if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
> > -               extern char __entry_tramp_data_start[];
> > -
> > -               __set_fixmap(FIX_ENTRY_TRAMP_DATA,
> > -                            __pa_symbol(__entry_tramp_data_start),
> > -                            PAGE_KERNEL_RO);
> > -       }
> > +       if (IS_ENABLED(CONFIG_RELOCATABLE))
> > +               __set_fixmap(FIX_ENTRY_TRAMP_TEXT1 - i,
> > +                            pa_start + i * PAGE_SIZE, PAGE_KERNEL_RO);
> >
> >         return 0;
> >  }
> > --
> > 2.30.2
> >



More information about the linux-arm-kernel mailing list