• Torsten Duwe's avatar
    arm64: implement ftrace with regs · 3b23e499
    Torsten Duwe authored
    This patch implements FTRACE_WITH_REGS for arm64, which allows a traced
    function's arguments (and some other registers) to be captured into a
    struct pt_regs, allowing these to be inspected and/or modified. This is
    a building block for live-patching, where a function's arguments may be
    forwarded to another function. This is also necessary to enable ftrace
    and in-kernel pointer authentication at the same time, as it allows the
    LR value to be captured and adjusted prior to signing.
    
    Using GCC's -fpatchable-function-entry=N option, we can have the
    compiler insert a configurable number of NOPs between the function entry
    point and the usual prologue. This also ensures functions are AAPCS
    compliant (e.g. disabling inter-procedural register allocation).
    
    For example, with -fpatchable-function-entry=2, GCC 8.1.0 compiles the
    following:
    
    | unsigned long bar(void);
    |
    | unsigned long foo(void)
    | {
    |         return bar() + 1;
    | }
    
    ... to:
    
    | <foo>:
    |         nop
    |         nop
    |         stp     x29, x30, [sp, #-16]!
    |         mov     x29, sp
    |         bl      0 <bar>
    |         add     x0, x0, #0x1
    |         ldp     x29, x30, [sp], #16
    |         ret
    
    This patch builds the kernel with -fpatchable-function-entry=2,
    prefixing each function with two NOPs. To trace a function, we replace
    these NOPs with a sequence that saves the LR into a GPR, then calls an
    ftrace entry assembly function which saves this and other relevant
    registers:
    
    | mov	x9, x30
    | bl	<ftrace-entry>
    
    Since patchable functions are AAPCS compliant (and the kernel does not
    use x18 as a platform register), x9-x18 can be safely clobbered in the
    patched sequence and the ftrace entry code.
    
    There are now two ftrace entry functions, ftrace_regs_entry (which saves
    all GPRs), and ftrace_entry (which saves the bare minimum). A PLT is
    allocated for each within modules.
    Signed-off-by: default avatarTorsten Duwe <duwe@suse.de>
    [Mark: rework asm, comments, PLTs, initialization, commit message]
    Signed-off-by: default avatarMark Rutland <mark.rutland@arm.com>
    Reviewed-by: default avatarAmit Daniel Kachhap <amit.kachhap@arm.com>
    Reviewed-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
    Reviewed-by: default avatarTorsten Duwe <duwe@suse.de>
    Tested-by: default avatarAmit Daniel Kachhap <amit.kachhap@arm.com>
    Tested-by: default avatarTorsten Duwe <duwe@suse.de>
    Cc: AKASHI Takahiro <takahiro.akashi@linaro.org>
    Cc: Catalin Marinas <catalin.marinas@arm.com>
    Cc: Josh Poimboeuf <jpoimboe@redhat.com>
    Cc: Julien Thierry <jthierry@redhat.com>
    Cc: Will Deacon <will@kernel.org>
    3b23e499
module-plts.c 9.85 KB