From 27b118342f2dcd6f0c2cd64453cc5a0289c4b3c9 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 14 May 2010 19:08:26 +0800 Subject: MIPS: Tracing: Merge adjacent #ifdefs with same condition. Signed-off-by: Wu Zhangjin Cc: linux-mips Cc: David Daney Patchwork: http://patchwork.linux-mips.org/patch/1224/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/mcount.S | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S index 6851fc97a511..e256bf98249a 100644 --- a/arch/mips/kernel/mcount.S +++ b/arch/mips/kernel/mcount.S @@ -45,8 +45,6 @@ PTR_L a5, PT_R9(sp) PTR_L a6, PT_R10(sp) PTR_L a7, PT_R11(sp) -#endif -#ifdef CONFIG_64BIT PTR_ADDIU sp, PT_SIZE #else PTR_ADDIU sp, (PT_SIZE + 8) -- cgit v1.2.3 From cbe555b01b0da9e89afa4babf3b8942d2b052fb8 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 14 May 2010 19:08:27 +0800 Subject: MIPS: Tracing: Cleanup the arguments passing of prepare_ftrace_return Signed-off-by: Wu Zhangjin Cc: linux-mips Cc: David Daney Patchwork: http://patchwork.linux-mips.org/patch/1226/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/mcount.S | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S index e256bf98249a..d4a00d29c0bf 100644 --- a/arch/mips/kernel/mcount.S +++ b/arch/mips/kernel/mcount.S @@ -132,28 +132,34 @@ ftrace_stub: #ifdef CONFIG_FUNCTION_GRAPH_TRACER NESTED(ftrace_graph_caller, PT_SIZE, ra) -#ifdef CONFIG_DYNAMIC_FTRACE - PTR_L a1, PT_R31(sp) /* load the original ra from the stack */ -#ifdef KBUILD_MCOUNT_RA_ADDRESS - PTR_L t0, PT_R12(sp) /* load the original t0 from the stack */ -#endif -#else +#ifndef CONFIG_DYNAMIC_FTRACE MCOUNT_SAVE_REGS - move a1, ra /* arg2: next ip, selfaddr */ #endif + /* arg1: Get the location of the parent's return address */ #ifdef KBUILD_MCOUNT_RA_ADDRESS - bnez t0, 1f /* non-leaf func: t0 saved the location of the return address */ +#ifdef CONFIG_DYNAMIC_FTRACE + PTR_L a0, PT_R12(sp) +#else + move a0, t0 +#endif + bnez a0, 1f /* non-leaf func: stored in t0 */ nop - PTR_LA t0, PT_R1(sp) /* leaf func: get the location of at(old ra) from our own stack */ -1: move a0, t0 /* arg1: the location of the return address */ +#endif + PTR_LA a0, PT_R1(sp) /* leaf func: the location in current stack */ +1: + + /* arg2: Get self return address */ +#ifdef CONFIG_DYNAMIC_FTRACE + PTR_L a1, PT_R31(sp) #else - PTR_LA a0, PT_R1(sp) /* arg1: &AT -> a0 */ + move a1, ra #endif - jal prepare_ftrace_return + + /* arg3: Get frame pointer of current stack */ #ifdef CONFIG_FRAME_POINTER - move a2, fp /* arg3: frame pointer */ -#else + move a2, fp +#else /* ! CONFIG_FRAME_POINTER */ #ifdef CONFIG_64BIT PTR_LA a2, PT_SIZE(sp) #else @@ -161,6 +167,8 @@ NESTED(ftrace_graph_caller, PT_SIZE, ra) #endif #endif + jal prepare_ftrace_return + nop MCOUNT_RESTORE_REGS RETURN_BACK END(ftrace_graph_caller) -- cgit v1.2.3 From 042e571d224707b777d0995317c74812b960bfeb Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 14 May 2010 19:08:28 +0800 Subject: MIPS: Tracing: Cleanup comments Signed-off-by: Wu Zhangjin Cc: linux-mips Cc: David Daney Patchwork: http://patchwork.linux-mips.org/patch/1225/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/mcount.S | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S index d4a00d29c0bf..9a029d40f6cf 100644 --- a/arch/mips/kernel/mcount.S +++ b/arch/mips/kernel/mcount.S @@ -6,6 +6,7 @@ * more details. * * Copyright (C) 2009 Lemote Inc. & DSLab, Lanzhou University, China + * Copyright (C) 2010 DSLab, Lanzhou University, China * Author: Wu Zhangjin */ @@ -69,14 +70,14 @@ _mcount: MCOUNT_SAVE_REGS #ifdef KBUILD_MCOUNT_RA_ADDRESS - PTR_S t0, PT_R12(sp) /* t0 saved the location of the return address(at) by -mmcount-ra-address */ + PTR_S t0, PT_R12(sp) /* save location of parent's return address */ #endif - move a0, ra /* arg1: next ip, selfaddr */ + move a0, ra /* arg1: self return address */ .globl ftrace_call ftrace_call: nop /* a placeholder for the call to a real tracing function */ - move a1, AT /* arg2: the caller's next ip, parent */ + move a1, AT /* arg2: parent's return address */ #ifdef CONFIG_FUNCTION_GRAPH_TRACER .globl ftrace_graph_call @@ -117,9 +118,9 @@ NESTED(_mcount, PT_SIZE, ra) static_trace: MCOUNT_SAVE_REGS - move a0, ra /* arg1: next ip, selfaddr */ + move a0, ra /* arg1: self return address */ jalr t2 /* (1) call *ftrace_trace_function */ - move a1, AT /* arg2: the caller's next ip, parent */ + move a1, AT /* arg2: parent's return address */ MCOUNT_RESTORE_REGS .globl ftrace_stub -- cgit v1.2.3 From 56b49cd35fd56e29adb8f97ba051a1670d24d133 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 14 May 2010 19:08:29 +0800 Subject: MIPS: Tracing: Fix argument passing of the 32bit support with gcc 4.5 As documented in the GCC 4.5 docs [1] -mmcount-ra-address uses register $12 to pass the stack offset of the return address to the _mcount function. On 64-bit kernels $12 is t0 but in 32-bit kernels it is t4 so we need to use $12 instead of t0 here to be correct for both kernel types. [1] GCC documentation: MIPS Options http://gcc.gnu.org/onlinedocs/gcc/MIPS-Options.html Signed-off-by: Wu Zhangjin Cc: linux-mips Cc: David Daney Patchwork: http://patchwork.linux-mips.org/patch/1227/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/mcount.S | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S index 9a029d40f6cf..6bfcb7a00ec6 100644 --- a/arch/mips/kernel/mcount.S +++ b/arch/mips/kernel/mcount.S @@ -57,6 +57,12 @@ move ra, AT .endm +/* + * The -mmcount-ra-address option of gcc 4.5 uses register $12 to pass + * the location of the parent's return address. + */ +#define MCOUNT_RA_ADDRESS_REG $12 + #ifdef CONFIG_DYNAMIC_FTRACE NESTED(ftrace_caller, PT_SIZE, ra) @@ -70,7 +76,7 @@ _mcount: MCOUNT_SAVE_REGS #ifdef KBUILD_MCOUNT_RA_ADDRESS - PTR_S t0, PT_R12(sp) /* save location of parent's return address */ + PTR_S MCOUNT_RA_ADDRESS_REG, PT_R12(sp) #endif move a0, ra /* arg1: self return address */ @@ -142,9 +148,9 @@ NESTED(ftrace_graph_caller, PT_SIZE, ra) #ifdef CONFIG_DYNAMIC_FTRACE PTR_L a0, PT_R12(sp) #else - move a0, t0 + move a0, MCOUNT_RA_ADDRESS_REG #endif - bnez a0, 1f /* non-leaf func: stored in t0 */ + bnez a0, 1f /* non-leaf func: stored in MCOUNT_RA_ADDRESS_REG */ nop #endif PTR_LA a0, PT_R1(sp) /* leaf func: the location in current stack */ -- cgit v1.2.3 From 3a2af2dc1bcbfe86b1f39e9e5f9c2c5447943f16 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 14 May 2010 19:08:30 +0800 Subject: MIPS: Tracing: Fix 32-bit support with -mmcount-ra-address For 32-bit kernel the -mmcount-ra-address option of gcc 4.5 emits one extra instruction before calling to _mcount so we need to use a different "b 1f" for it. Signed-off-by: Wu Zhangjin Cc: linux-mips Cc: David Daney Patchwork: http://patchwork.linux-mips.org/patch/1228/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/ftrace.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c index e9e64e0ff7aa..37aa7677e76d 100644 --- a/arch/mips/kernel/ftrace.c +++ b/arch/mips/kernel/ftrace.c @@ -62,14 +62,26 @@ int ftrace_make_nop(struct module *mod, return -EFAULT; } +#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) + /* lui v1, hi_16bit_of_mcount --> b 1f (0x10000005) + * addiu v1, v1, low_16bit_of_mcount + * move at, ra + * move $12, ra_address + * jalr v1 + * sub sp, sp, 8 + * 1: offset = 5 instructions + */ + new = 0x10000005; +#else /* lui v1, hi_16bit_of_mcount --> b 1f (0x10000004) * addiu v1, v1, low_16bit_of_mcount * move at, ra * jalr v1 - * nop - * 1f: (ip + 12) + * nop | move $12, ra_address | sub sp, sp, 8 + * 1: offset = 4 instructions */ new = 0x10000004; +#endif } else { /* record/calculate it for ftrace_make_call */ if (jal_mcount == 0) { -- cgit v1.2.3 From 4d6829f92a02d96e1bec2ffe6ee674ef3b49722b Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 14 May 2010 19:08:31 +0800 Subject: MIPS: Tracing: Cleanup of instructions used This patch adds some cleanups of the instructions: o use macros instead of magic numbers o use macros instead of variables to reduce some overhead o add new macro for the jal instruction Signed-off-by: Wu Zhangjin Cc: linux-mips Cc: David Daney Patchwork: http://patchwork.linux-mips.org/patch/1229/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/ftrace.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c index 37aa7677e76d..b1b8fec2432f 100644 --- a/arch/mips/kernel/ftrace.c +++ b/arch/mips/kernel/ftrace.c @@ -23,7 +23,10 @@ #define jump_insn_encode(op_code, addr) \ ((unsigned int)((op_code) | (((addr) >> 2) & ADDR_MASK))) -static unsigned int ftrace_nop = 0x00000000; +#define INSN_B_1F_4 0x10000004 /* b 1f; offset = 4 */ +#define INSN_B_1F_5 0x10000005 /* b 1f; offset = 5 */ +#define INSN_NOP 0x00000000 /* nop */ +#define INSN_JAL(addr) jump_insn_encode(JAL, addr) static int ftrace_modify_code(unsigned long ip, unsigned int new_code) { @@ -71,7 +74,7 @@ int ftrace_make_nop(struct module *mod, * sub sp, sp, 8 * 1: offset = 5 instructions */ - new = 0x10000005; + new = INSN_B_1F_5; #else /* lui v1, hi_16bit_of_mcount --> b 1f (0x10000004) * addiu v1, v1, low_16bit_of_mcount @@ -80,7 +83,7 @@ int ftrace_make_nop(struct module *mod, * nop | move $12, ra_address | sub sp, sp, 8 * 1: offset = 4 instructions */ - new = 0x10000004; + new = INSN_B_1F_4; #endif } else { /* record/calculate it for ftrace_make_call */ @@ -88,13 +91,13 @@ int ftrace_make_nop(struct module *mod, /* We can record it directly like this: * jal_mcount = *(unsigned int *)ip; * Herein, jump over the first two nop instructions */ - jal_mcount = jump_insn_encode(JAL, (MCOUNT_ADDR + 8)); + jal_mcount = INSN_JAL(MCOUNT_ADDR + 8); } /* move at, ra * jalr v1 --> nop */ - new = ftrace_nop; + new = INSN_NOP; } return ftrace_modify_code(ip, new); } @@ -109,7 +112,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) /* We just need to remove the "b ftrace_stub" at the fist time! */ if (modified == 0) { modified = 1; - ftrace_modify_code(addr, ftrace_nop); + ftrace_modify_code(addr, INSN_NOP); } /* ip, module: 0xc0000000, kernel: 0x80000000 */ new = (ip & 0x40000000) ? lui_v1 : jal_mcount; @@ -123,7 +126,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func) { unsigned int new; - new = jump_insn_encode(JAL, (unsigned long)func); + new = INSN_JAL((unsigned long)func); return ftrace_modify_code(FTRACE_CALL_IP, new); } @@ -155,7 +158,7 @@ int ftrace_enable_ftrace_graph_caller(void) int ftrace_disable_ftrace_graph_caller(void) { - return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, ftrace_nop); + return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, INSN_NOP); } #endif /* !CONFIG_DYNAMIC_FTRACE */ -- cgit v1.2.3 From e424054000878d7eb11e44289242886d6e219d22 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 14 May 2010 19:08:32 +0800 Subject: MIPS: Tracing: Reduce the overhead of dynamic Function Tracer With the help of uasm this patch encodes the instructions of the dynamic function tracer in ftrace_dyn_arch_init() when initializing it. As a result we can remove the dynamic encoding of instructions in ftrace_make_nop()/call(), ftrace_enable_ftrace_graph_caller() and remove the macro jump_insn_encode() and at last this reduce the overhead of dynamic Function Tracer. This also is cleaner. Signed-off-by: Wu Zhangjin Cc: linux-mips Cc: David Daney Patchwork: http://patchwork.linux-mips.org/patch/1230/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/ftrace.c | 93 +++++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 44 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c index b1b8fec2432f..c4042cad836e 100644 --- a/arch/mips/kernel/ftrace.c +++ b/arch/mips/kernel/ftrace.c @@ -2,7 +2,7 @@ * Code for replacing ftrace calls with jumps. * * Copyright (C) 2007-2008 Steven Rostedt - * Copyright (C) 2009 DSLab, Lanzhou University, China + * Copyright (C) 2009, 2010 DSLab, Lanzhou University, China * Author: Wu Zhangjin * * Thanks goes to Steven Rostedt for writing the original x86 version. @@ -12,21 +12,46 @@ #include #include -#include #include #include +#include +#include #ifdef CONFIG_DYNAMIC_FTRACE #define JAL 0x0c000000 /* jump & link: ip --> ra, jump to target */ #define ADDR_MASK 0x03ffffff /* op_code|addr : 31...26|25 ....0 */ -#define jump_insn_encode(op_code, addr) \ - ((unsigned int)((op_code) | (((addr) >> 2) & ADDR_MASK))) #define INSN_B_1F_4 0x10000004 /* b 1f; offset = 4 */ #define INSN_B_1F_5 0x10000005 /* b 1f; offset = 5 */ #define INSN_NOP 0x00000000 /* nop */ -#define INSN_JAL(addr) jump_insn_encode(JAL, addr) +#define INSN_JAL(addr) \ + ((unsigned int)(JAL | (((addr) >> 2) & ADDR_MASK))) + +static unsigned int insn_jal_ftrace_caller __read_mostly; +static unsigned int insn_lui_v1_hi16_mcount __read_mostly; +static unsigned int insn_j_ftrace_graph_caller __maybe_unused __read_mostly; + +static inline void ftrace_dyn_arch_init_insns(void) +{ + u32 *buf; + unsigned int v1; + + /* lui v1, hi16_mcount */ + v1 = 3; + buf = (u32 *)&insn_lui_v1_hi16_mcount; + UASM_i_LA_mostly(&buf, v1, MCOUNT_ADDR); + + /* jal (ftrace_caller + 8), jump over the first two instruction */ + buf = (u32 *)&insn_jal_ftrace_caller; + uasm_i_jal(&buf, (FTRACE_ADDR + 8)); + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + /* j ftrace_graph_caller */ + buf = (u32 *)&insn_j_ftrace_graph_caller; + uasm_i_j(&buf, (unsigned long)ftrace_graph_caller); +#endif +} static int ftrace_modify_code(unsigned long ip, unsigned int new_code) { @@ -43,30 +68,20 @@ static int ftrace_modify_code(unsigned long ip, unsigned int new_code) return 0; } -static int lui_v1; -static int jal_mcount; - int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr) { unsigned int new; - int faulted; unsigned long ip = rec->ip; - /* We have compiled module with -mlong-calls, but compiled the kernel - * without it, we need to cope with them respectively. */ + /* + * We have compiled module with -mlong-calls, but compiled the kernel + * without it, we need to cope with them respectively. + */ if (ip & 0x40000000) { - /* record it for ftrace_make_call */ - if (lui_v1 == 0) { - /* lui_v1 = *(unsigned int *)ip; */ - safe_load_code(lui_v1, ip, faulted); - - if (unlikely(faulted)) - return -EFAULT; - } - #if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) - /* lui v1, hi_16bit_of_mcount --> b 1f (0x10000005) + /* + * lui v1, hi_16bit_of_mcount --> b 1f (0x10000005) * addiu v1, v1, low_16bit_of_mcount * move at, ra * move $12, ra_address @@ -76,7 +91,8 @@ int ftrace_make_nop(struct module *mod, */ new = INSN_B_1F_5; #else - /* lui v1, hi_16bit_of_mcount --> b 1f (0x10000004) + /* + * lui v1, hi_16bit_of_mcount --> b 1f (0x10000004) * addiu v1, v1, low_16bit_of_mcount * move at, ra * jalr v1 @@ -86,36 +102,22 @@ int ftrace_make_nop(struct module *mod, new = INSN_B_1F_4; #endif } else { - /* record/calculate it for ftrace_make_call */ - if (jal_mcount == 0) { - /* We can record it directly like this: - * jal_mcount = *(unsigned int *)ip; - * Herein, jump over the first two nop instructions */ - jal_mcount = INSN_JAL(MCOUNT_ADDR + 8); - } - - /* move at, ra - * jalr v1 --> nop + /* + * move at, ra + * jal _mcount --> nop */ new = INSN_NOP; } return ftrace_modify_code(ip, new); } -static int modified; /* initialized as 0 by default */ - int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) { unsigned int new; unsigned long ip = rec->ip; - /* We just need to remove the "b ftrace_stub" at the fist time! */ - if (modified == 0) { - modified = 1; - ftrace_modify_code(addr, INSN_NOP); - } /* ip, module: 0xc0000000, kernel: 0x80000000 */ - new = (ip & 0x40000000) ? lui_v1 : jal_mcount; + new = (ip & 0x40000000) ? insn_lui_v1_hi16_mcount : insn_jal_ftrace_caller; return ftrace_modify_code(ip, new); } @@ -133,6 +135,12 @@ int ftrace_update_ftrace_func(ftrace_func_t func) int __init ftrace_dyn_arch_init(void *data) { + /* Encode the instructions when booting */ + ftrace_dyn_arch_init_insns(); + + /* Remove "b ftrace_stub" to ensure ftrace_caller() is executed */ + ftrace_modify_code(MCOUNT_ADDR, INSN_NOP); + /* The return code is retured via data */ *(unsigned long *)data = 0; @@ -145,15 +153,12 @@ int __init ftrace_dyn_arch_init(void *data) #ifdef CONFIG_DYNAMIC_FTRACE extern void ftrace_graph_call(void); -#define JMP 0x08000000 /* jump to target directly */ -#define CALL_FTRACE_GRAPH_CALLER \ - jump_insn_encode(JMP, (unsigned long)(&ftrace_graph_caller)) #define FTRACE_GRAPH_CALL_IP ((unsigned long)(&ftrace_graph_call)) int ftrace_enable_ftrace_graph_caller(void) { return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, - CALL_FTRACE_GRAPH_CALLER); + insn_j_ftrace_graph_caller); } int ftrace_disable_ftrace_graph_caller(void) -- cgit v1.2.3 From 68ccf7521dc89bfcf01432fd1bf8cb4d7d534e4c Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 14 May 2010 19:08:33 +0800 Subject: MIPS: Tracing: Cleanup of function graph tracer Cleans up comments and ftrace_get_parent_addr() of function graph tracer. Signed-off-by: Wu Zhangjin Cc: linux-mips Cc: David Daney Patchwork: http://patchwork.linux-mips.org/patch/1231/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/ftrace.c | 48 +++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c index c4042cad836e..628e90b992d1 100644 --- a/arch/mips/kernel/ftrace.c +++ b/arch/mips/kernel/ftrace.c @@ -146,7 +146,7 @@ int __init ftrace_dyn_arch_init(void *data) return 0; } -#endif /* CONFIG_DYNAMIC_FTRACE */ +#endif /* CONFIG_DYNAMIC_FTRACE */ #ifdef CONFIG_FUNCTION_GRAPH_TRACER @@ -166,9 +166,10 @@ int ftrace_disable_ftrace_graph_caller(void) return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, INSN_NOP); } -#endif /* !CONFIG_DYNAMIC_FTRACE */ +#endif /* CONFIG_DYNAMIC_FTRACE */ #ifndef KBUILD_MCOUNT_RA_ADDRESS + #define S_RA_SP (0xafbf << 16) /* s{d,w} ra, offset(sp) */ #define S_R_SP (0xafb0 << 16) /* s{d,w} R, offset(sp) */ #define OFFSET_MASK 0xffff /* stack offset range: 0 ~ PT_SIZE */ @@ -182,17 +183,17 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr, unsigned int code; int faulted; - /* in module or kernel? */ - if (self_addr & 0x40000000) { - /* module: move to the instruction "lui v1, HI_16BIT_OF_MCOUNT" */ - ip = self_addr - 20; - } else { - /* kernel: move to the instruction "move ra, at" */ - ip = self_addr - 12; - } + /* + * For module, move the ip from calling site of mcount to the + * instruction "lui v1, hi_16bit_of_mcount"(offset is 20), but for + * kernel, move to the instruction "move ra, at"(offset is 12) + */ + ip = self_addr - ((self_addr & 0x40000000) ? 20 : 12); - /* search the text until finding the non-store instruction or "s{d,w} - * ra, offset(sp)" instruction */ + /* + * search the text until finding the non-store instruction or "s{d,w} + * ra, offset(sp)" instruction + */ do { ip -= 4; @@ -201,10 +202,11 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr, if (unlikely(faulted)) return 0; - - /* If we hit the non-store instruction before finding where the + /* + * If we hit the non-store instruction before finding where the * ra is stored, then this is a leaf function and it does not - * store the ra on the stack. */ + * store the ra on the stack + */ if ((code & S_R_SP) != S_R_SP) return parent_addr; @@ -222,7 +224,7 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr, return 0; } -#endif +#endif /* !KBUILD_MCOUNT_RA_ADDRESS */ /* * Hook the return address and push it in the stack of return addrs @@ -240,7 +242,8 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, if (unlikely(atomic_read(¤t->tracing_graph_pause))) return; - /* "parent" is the stack address saved the return address of the caller + /* + * "parent" is the stack address saved the return address of the caller * of _mcount. * * if the gcc < 4.5, a leaf function does not save the return address @@ -262,10 +265,11 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, goto out; #ifndef KBUILD_MCOUNT_RA_ADDRESS parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old, - (unsigned long)parent, - fp); - /* If fails when getting the stack address of the non-leaf function's - * ra, stop function graph tracer and return */ + (unsigned long)parent, fp); + /* + * If fails when getting the stack address of the non-leaf function's + * ra, stop function graph tracer and return + */ if (parent == 0) goto out; #endif @@ -292,4 +296,4 @@ out: ftrace_graph_stop(); WARN_ON(1); } -#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ -- cgit v1.2.3 From c9f84873c1231621508cd438bb2991ddba770a69 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 14 May 2010 19:08:34 +0800 Subject: MIPS: Tracing: Cleanup of address space checking This patch adds an inline function in_module() to check which space the instruction pointer in, kernel space or module space. Note: This will not work when the kernel space and module space are the same. If they are the same, we need to modify scripts/recordmcount.pl, ftrace_make_nop/call() and the other related parts to ensure the enabling/disabling of the calling site to _mcount is right for both kernel and module. [Ralf: It also is still incorrect for some 64-bit kernels.] Signed-off-by: Wu Zhangjin Cc: linux-mips Cc: David Daney Patchwork: http://patchwork.linux-mips.org/patch/1232/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/ftrace.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c index 628e90b992d1..5a84a1f11231 100644 --- a/arch/mips/kernel/ftrace.c +++ b/arch/mips/kernel/ftrace.c @@ -17,6 +17,22 @@ #include #include +/* + * If the Instruction Pointer is in module space (0xc0000000), return true; + * otherwise, it is in kernel space (0x80000000), return false. + * + * FIXME: This will not work when the kernel space and module space are the + * same. If they are the same, we need to modify scripts/recordmcount.pl, + * ftrace_make_nop/call() and the other related parts to ensure the + * enabling/disabling of the calling site to _mcount is right for both kernel + * and module. + */ + +static inline int in_module(unsigned long ip) +{ + return ip & 0x40000000; +} + #ifdef CONFIG_DYNAMIC_FTRACE #define JAL 0x0c000000 /* jump & link: ip --> ra, jump to target */ @@ -78,7 +94,7 @@ int ftrace_make_nop(struct module *mod, * We have compiled module with -mlong-calls, but compiled the kernel * without it, we need to cope with them respectively. */ - if (ip & 0x40000000) { + if (in_module(ip)) { #if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) /* * lui v1, hi_16bit_of_mcount --> b 1f (0x10000005) @@ -117,7 +133,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) unsigned long ip = rec->ip; /* ip, module: 0xc0000000, kernel: 0x80000000 */ - new = (ip & 0x40000000) ? insn_lui_v1_hi16_mcount : insn_jal_ftrace_caller; + new = in_module(ip) ? insn_lui_v1_hi16_mcount : insn_jal_ftrace_caller; return ftrace_modify_code(ip, new); } @@ -188,7 +204,7 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr, * instruction "lui v1, hi_16bit_of_mcount"(offset is 20), but for * kernel, move to the instruction "move ra, at"(offset is 12) */ - ip = self_addr - ((self_addr & 0x40000000) ? 20 : 12); + ip = self_addr - (in_module(self_addr) ? 20 : 12); /* * search the text until finding the non-store instruction or "s{d,w} -- cgit v1.2.3 From 17c04139fd2aeaef30fda380bb91b32de7b41a8f Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 29 May 2010 03:19:57 +0100 Subject: MIPS: MT: Fix FPU affinity. The fragile MT sys_sched_setaffinity wrapper needs its regular dose of fixes. Nose-poked-at-pile-o-crap-by: Julia Lawall Signed-off-by: Ralf Baechle --- arch/mips/kernel/mips-mt-fpaff.c | 87 ++++++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 26 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c index f5981c499109..2340f11dc29c 100644 --- a/arch/mips/kernel/mips-mt-fpaff.c +++ b/arch/mips/kernel/mips-mt-fpaff.c @@ -3,6 +3,7 @@ * Copyright (C) 2005 Mips Technologies, Inc */ #include +#include #include #include #include @@ -39,6 +40,21 @@ static inline struct task_struct *find_process_by_pid(pid_t pid) return pid ? find_task_by_vpid(pid) : current; } +/* + * check the target process has a UID that matches the current process's + */ +static bool check_same_owner(struct task_struct *p) +{ + const struct cred *cred = current_cred(), *pcred; + bool match; + + rcu_read_lock(); + pcred = __task_cred(p); + match = (cred->euid == pcred->euid || + cred->euid == pcred->uid); + rcu_read_unlock(); + return match; +} /* * mipsmt_sys_sched_setaffinity - set the cpu affinity of a process @@ -46,12 +62,10 @@ static inline struct task_struct *find_process_by_pid(pid_t pid) asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len, unsigned long __user *user_mask_ptr) { - cpumask_t new_mask; - cpumask_t effective_mask; - int retval; - struct task_struct *p; + cpumask_var_t cpus_allowed, new_mask, effective_mask; struct thread_info *ti; - uid_t euid; + struct task_struct *p; + int retval; if (len < sizeof(new_mask)) return -EINVAL; @@ -60,53 +74,74 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len, return -EFAULT; get_online_cpus(); - read_lock(&tasklist_lock); + rcu_read_lock(); p = find_process_by_pid(pid); if (!p) { - read_unlock(&tasklist_lock); + rcu_read_unlock(); put_online_cpus(); return -ESRCH; } - /* - * It is not safe to call set_cpus_allowed with the - * tasklist_lock held. We will bump the task_struct's - * usage count and drop tasklist_lock before invoking - * set_cpus_allowed. - */ + /* Prevent p going away */ get_task_struct(p); + rcu_read_unlock(); - euid = current_euid(); + if (!alloc_cpumask_var(&cpus_allowed, GFP_KERNEL)) { + retval = -ENOMEM; + goto out_put_task; + } + if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) { + retval = -ENOMEM; + goto out_free_cpus_allowed; + } + if (!alloc_cpumask_var(&effective_mask, GFP_KERNEL)) { + retval = -ENOMEM; + goto out_free_new_mask; + } retval = -EPERM; - if (euid != p->cred->euid && euid != p->cred->uid && - !capable(CAP_SYS_NICE)) { - read_unlock(&tasklist_lock); + if (!check_same_owner(p) && !capable(CAP_SYS_NICE)) goto out_unlock; - } retval = security_task_setscheduler(p, 0, NULL); if (retval) goto out_unlock; /* Record new user-specified CPU set for future reference */ - p->thread.user_cpus_allowed = new_mask; - - /* Unlock the task list */ - read_unlock(&tasklist_lock); + cpumask_copy(&p->thread.user_cpus_allowed, new_mask); + again: /* Compute new global allowed CPU set if necessary */ ti = task_thread_info(p); if (test_ti_thread_flag(ti, TIF_FPUBOUND) && - cpus_intersects(new_mask, mt_fpu_cpumask)) { - cpus_and(effective_mask, new_mask, mt_fpu_cpumask); - retval = set_cpus_allowed_ptr(p, &effective_mask); + cpus_intersects(*new_mask, mt_fpu_cpumask)) { + cpus_and(*effective_mask, *new_mask, mt_fpu_cpumask); + retval = set_cpus_allowed_ptr(p, effective_mask); } else { + cpumask_copy(effective_mask, new_mask); clear_ti_thread_flag(ti, TIF_FPUBOUND); - retval = set_cpus_allowed_ptr(p, &new_mask); + retval = set_cpus_allowed_ptr(p, new_mask); } + if (!retval) { + cpuset_cpus_allowed(p, cpus_allowed); + if (!cpumask_subset(effective_mask, cpus_allowed)) { + /* + * We must have raced with a concurrent cpuset + * update. Just reset the cpus_allowed to the + * cpuset's cpus_allowed + */ + cpumask_copy(new_mask, cpus_allowed); + goto again; + } + } out_unlock: + free_cpumask_var(effective_mask); +out_free_new_mask: + free_cpumask_var(new_mask); +out_free_cpus_allowed: + free_cpumask_var(cpus_allowed); +out_put_task: put_task_struct(p); put_online_cpus(); return retval; -- cgit v1.2.3 From 55dc9d51a89ba10a1f7b3ed15f1262eb83e87e74 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Thu, 17 Jun 2010 15:25:54 +0200 Subject: MIPS: Return after handling coprocessor 2 exception Breaking here dropped us to the default code which always sends a SIGILL to the current process, no matter what the CU2 notifier says. [Ralf: Currently this only hurts on Cavium and possibly some out of tree platforms.] Signed-off-by: Jesper Nilsson To: linux-mips@linux-mips.org To: linux-kernel@vger.kernel.org Patchwork: http://patchwork.linux-mips.org/patch/1391/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/traps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 8bdd6a663c7f..852780868fb4 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -976,7 +976,7 @@ asmlinkage void do_cpu(struct pt_regs *regs) case 2: raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs); - break; + return; case 3: break; -- cgit v1.2.3 From 57d15018aa48ecc5fafef3374dcebcf0bbbfa764 Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 16 Jun 2010 15:00:27 -0700 Subject: MIPS: "Fix" useless 'init_vdso successfully' message. In addition to being useless, it was mis-spelled. Signed-off-by: David Daney To: linux-mips@linux-mips.org Cc: David Daney Patchwork: http://patchwork.linux-mips.org/patch/1385/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/vdso.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c index b773c1112b14..6c6ee94378d5 100644 --- a/arch/mips/kernel/vdso.c +++ b/arch/mips/kernel/vdso.c @@ -61,8 +61,6 @@ static int __init init_vdso(void) vunmap(vdso); - pr_notice("init_vdso successfull\n"); - return 0; } device_initcall(init_vdso); -- cgit v1.2.3 From 1ed845375b1f2938acc4496a186e180892b00c71 Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 16 Jun 2010 15:00:28 -0700 Subject: MIPS: Make init_vdso a subsys_initcall. Quoting from Jiri Slaby's patch of a similar nature for x86: When initrd is in use and a driver does request_module() in its module_init (i.e. __initcall or device_initcall), a modprobe process is created with VDSO mapping. But VDSO is inited even in __initcall, i.e. on the same level (at the same time), so it may not be inited yet (link order matters). Move init_vdso up to subsys_initcall to avoid the issue. Signed-off-by: David Daney To: linux-mips@linux-mips.org Cc: David Daney Cc: Jiri Slaby Patchwork: http://patchwork.linux-mips.org/patch/1386/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/vdso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c index 6c6ee94378d5..e5cdfd603f8f 100644 --- a/arch/mips/kernel/vdso.c +++ b/arch/mips/kernel/vdso.c @@ -63,7 +63,7 @@ static int __init init_vdso(void) return 0; } -device_initcall(init_vdso); +subsys_initcall(init_vdso); static unsigned long vdso_addr(unsigned long start) { -- cgit v1.2.3 From 31c984a5acabea5d8c7224dc226453022be46f33 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 21 Jul 2010 21:20:25 -0400 Subject: MIPS: N32: Define getdents64. As a relativly new ABI N32 should only have received the getdents64(2) but instead it only had getdents(2). This was noticed as a performance anomaly in glibc. Signed-off-by: Ralf Baechle --- arch/mips/kernel/scall64-n32.S | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index a5297e2a353a..a4faceea9d88 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -419,4 +419,5 @@ EXPORT(sysn32_call_table) PTR sys_perf_event_open PTR sys_accept4 PTR compat_sys_recvmmsg + PTR sys_getdents .size sysn32_call_table,.-sysn32_call_table -- cgit v1.2.3