mirror of https://github.com/dynup/kpatch
68 lines
1.5 KiB
ArmAsm
68 lines
1.5 KiB
ArmAsm
#include <linux/linkage.h>
|
|
#include <asm/calling.h>
|
|
|
|
GLOBAL(kpatch_trampoline)
|
|
|
|
pushq %rcx
|
|
pushq %rdi
|
|
|
|
callq kpatch_ftrace_hacks
|
|
|
|
leaq kpatch_funcs, %r10
|
|
|
|
/*
|
|
* TODO: if preemption is possible then we'll need to think about how
|
|
* to ensure atomic access to the array and how to ensure activeness
|
|
* safety here. if preemption is enabled then we need to make sure the
|
|
* IP isn't inside kpatch_trampoline for any task.
|
|
*/
|
|
|
|
/* TODO: save/restore flags? */
|
|
|
|
/* find new function in func_list */
|
|
popq %rdi
|
|
loop:
|
|
movq (%r10), %r9
|
|
cmpq %r9, %rdi
|
|
je found
|
|
|
|
/*
|
|
* Check for the rare case where we don't have a new function to call.
|
|
* This can happen in the small window of time during patch module
|
|
* insmod after it has called register_ftrace_function() but before it
|
|
* has called stop_machine() to do the activeness safety check and the
|
|
* array update. In this case we just return and let the old function
|
|
* run.
|
|
*/
|
|
cmpq $0, %r9
|
|
je bail
|
|
|
|
addq $40, %r10 /* FIXME http://docs.blackfin.uclinux.org/doku.php?id=toolchain:gas:structs */
|
|
jmp loop
|
|
|
|
found:
|
|
/* get new function address */
|
|
movq 8(%r10), %r10
|
|
|
|
/* restore regs owned by original calling function */
|
|
popq %rax
|
|
movq RBP(%rax), %rbp
|
|
movq RBX(%rax), %rbx
|
|
movq R12(%rax), %r12
|
|
movq R13(%rax), %r13
|
|
movq R14(%rax), %r14
|
|
movq R15(%rax), %r15
|
|
|
|
/* restore arg registers and stack for new function */
|
|
movq RDI(%rax), %rdi
|
|
movq RSI(%rax), %rsi
|
|
movq RDX(%rax), %rdx
|
|
movq RCX(%rax), %rcx
|
|
movq RSP(%rax), %rsp
|
|
|
|
/* jump to new function */
|
|
jmpq *%r10
|
|
|
|
bail:
|
|
ret
|