forked from Minki/linux
a88b5ba8bd
o Move all files from sparc64/kernel/ to sparc/kernel - rename as appropriate o Update sparc/Makefile to the changes o Update sparc/kernel/Makefile to include the sparc64 files NOTE: This commit changes link order on sparc64! Link order had to change for either of sparc32 and sparc64. And assuming sparc64 see more testing than sparc32 change link order on sparc64 where issues will be caught faster. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: David S. Miller <davem@davemloft.net>
77 lines
1.6 KiB
C
77 lines
1.6 KiB
C
#include <linux/spinlock.h>
|
|
#include <linux/hardirq.h>
|
|
#include <linux/ftrace.h>
|
|
#include <linux/percpu.h>
|
|
#include <linux/init.h>
|
|
#include <linux/list.h>
|
|
|
|
#include <asm/ftrace.h>
|
|
|
|
static const u32 ftrace_nop = 0x01000000;
|
|
|
|
unsigned char *ftrace_nop_replace(void)
|
|
{
|
|
return (char *)&ftrace_nop;
|
|
}
|
|
|
|
unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
|
|
{
|
|
static u32 call;
|
|
s32 off;
|
|
|
|
off = ((s32)addr - (s32)ip);
|
|
call = 0x40000000 | ((u32)off >> 2);
|
|
|
|
return (unsigned char *) &call;
|
|
}
|
|
|
|
int
|
|
ftrace_modify_code(unsigned long ip, unsigned char *old_code,
|
|
unsigned char *new_code)
|
|
{
|
|
u32 old = *(u32 *)old_code;
|
|
u32 new = *(u32 *)new_code;
|
|
u32 replaced;
|
|
int faulted;
|
|
|
|
__asm__ __volatile__(
|
|
"1: cas [%[ip]], %[old], %[new]\n"
|
|
" flush %[ip]\n"
|
|
" mov 0, %[faulted]\n"
|
|
"2:\n"
|
|
" .section .fixup,#alloc,#execinstr\n"
|
|
" .align 4\n"
|
|
"3: sethi %%hi(2b), %[faulted]\n"
|
|
" jmpl %[faulted] + %%lo(2b), %%g0\n"
|
|
" mov 1, %[faulted]\n"
|
|
" .previous\n"
|
|
" .section __ex_table,\"a\"\n"
|
|
" .align 4\n"
|
|
" .word 1b, 3b\n"
|
|
" .previous\n"
|
|
: "=r" (replaced), [faulted] "=r" (faulted)
|
|
: [new] "0" (new), [old] "r" (old), [ip] "r" (ip)
|
|
: "memory");
|
|
|
|
if (replaced != old && replaced != new)
|
|
faulted = 2;
|
|
|
|
return faulted;
|
|
}
|
|
|
|
int ftrace_update_ftrace_func(ftrace_func_t func)
|
|
{
|
|
unsigned long ip = (unsigned long)(&ftrace_call);
|
|
unsigned char old[MCOUNT_INSN_SIZE], *new;
|
|
|
|
memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE);
|
|
new = ftrace_call_replace(ip, (unsigned long)func);
|
|
return ftrace_modify_code(ip, old, new);
|
|
}
|
|
|
|
int __init ftrace_dyn_arch_init(void *data)
|
|
{
|
|
ftrace_mcount_set(data);
|
|
return 0;
|
|
}
|