135 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
		
			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:
 | 
