linux/arch/powerpc/kernel/optprobes_head.S
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-or-later */
   2/*
   3 * Code to prepare detour buffer for optprobes in Kernel.
   4 *
   5 * Copyright 2017, Anju T, IBM Corp.
   6 */
   7
   8#include <asm/ppc_asm.h>
   9#include <asm/ptrace.h>
  10#include <asm/asm-offsets.h>
  11
  12#ifdef CONFIG_PPC64
  13#define SAVE_30GPRS(base) SAVE_10GPRS(2,base); SAVE_10GPRS(12,base); SAVE_10GPRS(22,base)
  14#define REST_30GPRS(base) REST_10GPRS(2,base); REST_10GPRS(12,base); REST_10GPRS(22,base)
  15#define TEMPLATE_FOR_IMM_LOAD_INSNS     nop; nop; nop; nop; nop
  16#else
  17#define SAVE_30GPRS(base) stmw  r2, GPR2(base)
  18#define REST_30GPRS(base) lmw   r2, GPR2(base)
  19#define TEMPLATE_FOR_IMM_LOAD_INSNS     nop; nop; nop
  20#endif
  21
  22#define OPT_SLOT_SIZE   65536
  23
  24        .balign 4
  25
  26        /*
  27         * Reserve an area to allocate slots for detour buffer.
  28         * This is part of .text section (rather than vmalloc area)
  29         * as this needs to be within 32MB of the probed address.
  30         */
  31        .global optinsn_slot
  32optinsn_slot:
  33        .space  OPT_SLOT_SIZE
  34
  35        /*
  36         * Optprobe template:
  37         * This template gets copied into one of the slots in optinsn_slot
  38         * and gets fixed up with real optprobe structures et al.
  39         */
  40        .global optprobe_template_entry
  41optprobe_template_entry:
  42        /* Create an in-memory pt_regs */
  43        PPC_STLU        r1,-INT_FRAME_SIZE(r1)
  44        SAVE_GPR(0,r1)
  45        /* Save the previous SP into stack */
  46        addi    r0,r1,INT_FRAME_SIZE
  47        PPC_STL r0,GPR1(r1)
  48        SAVE_30GPRS(r1)
  49        /* Save SPRS */
  50        mfmsr   r5
  51        PPC_STL r5,_MSR(r1)
  52        li      r5,0x700
  53        PPC_STL r5,_TRAP(r1)
  54        li      r5,0
  55        PPC_STL r5,ORIG_GPR3(r1)
  56        PPC_STL r5,RESULT(r1)
  57        mfctr   r5
  58        PPC_STL r5,_CTR(r1)
  59        mflr    r5
  60        PPC_STL r5,_LINK(r1)
  61        mfspr   r5,SPRN_XER
  62        PPC_STL r5,_XER(r1)
  63        mfcr    r5
  64        PPC_STL r5,_CCR(r1)
  65#ifdef CONFIG_PPC64
  66        lbz     r5,PACAIRQSOFTMASK(r13)
  67        std     r5,SOFTE(r1)
  68#endif
  69
  70        /*
  71         * We may get here from a module, so load the kernel TOC in r2.
  72         * The original TOC gets restored when pt_regs is restored
  73         * further below.
  74         */
  75#ifdef CONFIG_PPC64
  76        ld      r2,PACATOC(r13)
  77#endif
  78
  79        .global optprobe_template_op_address
  80optprobe_template_op_address:
  81        /*
  82         * Parameters to optimized_callback():
  83         * 1. optimized_kprobe structure in r3
  84         */
  85        TEMPLATE_FOR_IMM_LOAD_INSNS
  86
  87        /* 2. pt_regs pointer in r4 */
  88        addi    r4,r1,STACK_FRAME_OVERHEAD
  89
  90        .global optprobe_template_call_handler
  91optprobe_template_call_handler:
  92        /* Branch to optimized_callback() */
  93        nop
  94
  95        /*
  96         * Parameters for instruction emulation:
  97         * 1. Pass SP in register r3.
  98         */
  99        addi    r3,r1,STACK_FRAME_OVERHEAD
 100
 101        .global optprobe_template_insn
 102optprobe_template_insn:
 103        /* 2, Pass instruction to be emulated in r4 */
 104        TEMPLATE_FOR_IMM_LOAD_INSNS
 105
 106        .global optprobe_template_call_emulate
 107optprobe_template_call_emulate:
 108        /* Branch to emulate_step()  */
 109        nop
 110
 111        /*
 112         * All done.
 113         * Now, restore the registers...
 114         */
 115        PPC_LL  r5,_MSR(r1)
 116        mtmsr   r5
 117        PPC_LL  r5,_CTR(r1)
 118        mtctr   r5
 119        PPC_LL  r5,_LINK(r1)
 120        mtlr    r5
 121        PPC_LL  r5,_XER(r1)
 122        mtxer   r5
 123        PPC_LL  r5,_CCR(r1)
 124        mtcr    r5
 125        REST_GPR(0,r1)
 126        REST_30GPRS(r1)
 127        /* Restore the previous SP */
 128        addi    r1,r1,INT_FRAME_SIZE
 129
 130        .global optprobe_template_ret
 131optprobe_template_ret:
 132        /* ... and jump back from trampoline */
 133        nop
 134
 135        .global optprobe_template_end
 136optprobe_template_end:
 137