135 строки
2.8 KiB
ArmAsm
135 строки
2.8 KiB
ArmAsm
/*
|
|
* Code to prepare detour buffer for optprobes in Kernel.
|
|
*
|
|
* Copyright 2017, Anju T, IBM Corp.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
*/
|
|
|
|
#include <asm/ppc_asm.h>
|
|
#include <asm/ptrace.h>
|
|
#include <asm/asm-offsets.h>
|
|
|
|
#define OPT_SLOT_SIZE 65536
|
|
|
|
.balign 4
|
|
|
|
/*
|
|
* Reserve an area to allocate slots for detour buffer.
|
|
* This is part of .text section (rather than vmalloc area)
|
|
* as this needs to be within 32MB of the probed address.
|
|
*/
|
|
.global optinsn_slot
|
|
optinsn_slot:
|
|
.space OPT_SLOT_SIZE
|
|
|
|
/*
|
|
* Optprobe template:
|
|
* This template gets copied into one of the slots in optinsn_slot
|
|
* and gets fixed up with real optprobe structures et al.
|
|
*/
|
|
.global optprobe_template_entry
|
|
optprobe_template_entry:
|
|
/* Create an in-memory pt_regs */
|
|
stdu r1,-INT_FRAME_SIZE(r1)
|
|
SAVE_GPR(0,r1)
|
|
/* Save the previous SP into stack */
|
|
addi r0,r1,INT_FRAME_SIZE
|
|
std r0,GPR1(r1)
|
|
SAVE_10GPRS(2,r1)
|
|
SAVE_10GPRS(12,r1)
|
|
SAVE_10GPRS(22,r1)
|
|
/* Save SPRS */
|
|
mfmsr r5
|
|
std r5,_MSR(r1)
|
|
li r5,0x700
|
|
std r5,_TRAP(r1)
|
|
li r5,0
|
|
std r5,ORIG_GPR3(r1)
|
|
std r5,RESULT(r1)
|
|
mfctr r5
|
|
std r5,_CTR(r1)
|
|
mflr r5
|
|
std r5,_LINK(r1)
|
|
mfspr r5,SPRN_XER
|
|
std r5,_XER(r1)
|
|
mfcr r5
|
|
std r5,_CCR(r1)
|
|
lbz r5,PACAIRQSOFTMASK(r13)
|
|
std r5,SOFTE(r1)
|
|
|
|
/*
|
|
* We may get here from a module, so load the kernel TOC in r2.
|
|
* The original TOC gets restored when pt_regs is restored
|
|
* further below.
|
|
*/
|
|
ld r2,PACATOC(r13)
|
|
|
|
.global optprobe_template_op_address
|
|
optprobe_template_op_address:
|
|
/*
|
|
* Parameters to optimized_callback():
|
|
* 1. optimized_kprobe structure in r3
|
|
*/
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
/* 2. pt_regs pointer in r4 */
|
|
addi r4,r1,STACK_FRAME_OVERHEAD
|
|
|
|
.global optprobe_template_call_handler
|
|
optprobe_template_call_handler:
|
|
/* Branch to optimized_callback() */
|
|
nop
|
|
|
|
/*
|
|
* Parameters for instruction emulation:
|
|
* 1. Pass SP in register r3.
|
|
*/
|
|
addi r3,r1,STACK_FRAME_OVERHEAD
|
|
|
|
.global optprobe_template_insn
|
|
optprobe_template_insn:
|
|
/* 2, Pass instruction to be emulated in r4 */
|
|
nop
|
|
nop
|
|
|
|
.global optprobe_template_call_emulate
|
|
optprobe_template_call_emulate:
|
|
/* Branch to emulate_step() */
|
|
nop
|
|
|
|
/*
|
|
* All done.
|
|
* Now, restore the registers...
|
|
*/
|
|
ld r5,_MSR(r1)
|
|
mtmsr r5
|
|
ld r5,_CTR(r1)
|
|
mtctr r5
|
|
ld r5,_LINK(r1)
|
|
mtlr r5
|
|
ld r5,_XER(r1)
|
|
mtxer r5
|
|
ld r5,_CCR(r1)
|
|
mtcr r5
|
|
REST_GPR(0,r1)
|
|
REST_10GPRS(2,r1)
|
|
REST_10GPRS(12,r1)
|
|
REST_10GPRS(22,r1)
|
|
/* Restore the previous SP */
|
|
addi r1,r1,INT_FRAME_SIZE
|
|
|
|
.global optprobe_template_ret
|
|
optprobe_template_ret:
|
|
/* ... and jump back from trampoline */
|
|
nop
|
|
|
|
.global optprobe_template_end
|
|
optprobe_template_end:
|