summaryrefslogtreecommitdiff
path: root/arch/mips/kernel/ftrace.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-08-07 08:47:00 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-07 08:47:00 -0700
commite669830526a0abaf301bf408df69cde33901ac63 (patch)
tree0b6043375006d1754bbd1ab2370b0a0536546cc9 /arch/mips/kernel/ftrace.c
parentebb067d2f4e2db59b076f9c9cba0375a8ad1e07c (diff)
parent475d5928b79bb78326a645863d46ff95c5e25e5a (diff)
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS updates from Ralf Baechle: "This is the main pull request for 3.17. It contains: - misc Cavium Octeon, BCM47xx, BCM63xx and Alchemy updates - MIPS ptrace updates and cleanups - various fixes that will also go to -stable - a number of cleanups and small non-critical fixes. - NUMA support for the Loongson 3. - more support for MSA - support for MAAR - various FP enhancements and fixes" * 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (139 commits) MIPS: jz4740: remove unnecessary null test before debugfs_remove MIPS: Octeon: remove unnecessary null test before debugfs_remove_recursive MIPS: ZBOOT: implement stack protector in compressed boot phase MIPS: mipsreg: remove duplicate MIPS_CONF4_FTLBSETS_SHIFT MIPS: Bonito64: remove a duplicate define MIPS: Malta: initialise MAARs MIPS: Initialise MAARs MIPS: detect presence of MAARs MIPS: define MAAR register accessors & bits MIPS: mark MSA experimental MIPS: Don't build MSA support unless it can be used MIPS: consistently clear MSA flags when starting & copying threads MIPS: 16 byte align MSA vector context MIPS: disable preemption whilst initialising MSA MIPS: ensure MSA gets disabled during boot MIPS: fix read_msa_* & write_msa_* functions on non-MSA toolchains MIPS: fix MSA context for tasks which don't use FP first MIPS: init upper 64b of vector registers when MSA is first used MIPS: save/disable MSA in lose_fpu MIPS: preserve scalar FP CSR when switching vector context ...
Diffstat (limited to 'arch/mips/kernel/ftrace.c')
-rw-r--r--arch/mips/kernel/ftrace.c56
1 files changed, 47 insertions, 9 deletions
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index 8b6538750fe1..937c54bc8ccc 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -63,7 +63,7 @@ static inline int in_kernel_space(unsigned long ip)
((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_la_mcount[2] __read_mostly;
static unsigned int insn_j_ftrace_graph_caller __maybe_unused __read_mostly;
static inline void ftrace_dyn_arch_init_insns(void)
@@ -71,10 +71,10 @@ static inline void ftrace_dyn_arch_init_insns(void)
u32 *buf;
unsigned int v1;
- /* lui v1, hi16_mcount */
+ /* la v1, _mcount */
v1 = 3;
- buf = (u32 *)&insn_lui_v1_hi16_mcount;
- UASM_i_LA_mostly(&buf, v1, MCOUNT_ADDR);
+ buf = (u32 *)&insn_la_mcount[0];
+ UASM_i_LA(&buf, v1, MCOUNT_ADDR);
/* jal (ftrace_caller + 8), jump over the first two instruction */
buf = (u32 *)&insn_jal_ftrace_caller;
@@ -111,14 +111,47 @@ static int ftrace_modify_code_2(unsigned long ip, unsigned int new_code1,
unsigned int new_code2)
{
int faulted;
+ mm_segment_t old_fs;
safe_store_code(new_code1, ip, faulted);
if (unlikely(faulted))
return -EFAULT;
- safe_store_code(new_code2, ip + 4, faulted);
+
+ ip += 4;
+ safe_store_code(new_code2, ip, faulted);
if (unlikely(faulted))
return -EFAULT;
+
+ ip -= 4;
+ old_fs = get_fs();
+ set_fs(get_ds());
flush_icache_range(ip, ip + 8);
+ set_fs(old_fs);
+
+ return 0;
+}
+
+static int ftrace_modify_code_2r(unsigned long ip, unsigned int new_code1,
+ unsigned int new_code2)
+{
+ int faulted;
+ mm_segment_t old_fs;
+
+ ip += 4;
+ safe_store_code(new_code2, ip, faulted);
+ if (unlikely(faulted))
+ return -EFAULT;
+
+ ip -= 4;
+ safe_store_code(new_code1, ip, faulted);
+ if (unlikely(faulted))
+ return -EFAULT;
+
+ old_fs = get_fs();
+ set_fs(get_ds());
+ flush_icache_range(ip, ip + 8);
+ set_fs(old_fs);
+
return 0;
}
#endif
@@ -130,13 +163,14 @@ static int ftrace_modify_code_2(unsigned long ip, unsigned int new_code1,
*
* move at, ra
* jal _mcount --> nop
+ * sub sp, sp, 8 --> nop (CONFIG_32BIT)
*
* 2. For modules:
*
* 2.1 For KBUILD_MCOUNT_RA_ADDRESS and CONFIG_32BIT
*
* lui v1, hi_16bit_of_mcount --> b 1f (0x10000005)
- * addiu v1, v1, low_16bit_of_mcount
+ * addiu v1, v1, low_16bit_of_mcount --> nop (CONFIG_32BIT)
* move at, ra
* move $12, ra_address
* jalr v1
@@ -145,7 +179,7 @@ static int ftrace_modify_code_2(unsigned long ip, unsigned int new_code1,
* 2.2 For the Other situations
*
* lui v1, hi_16bit_of_mcount --> b 1f (0x10000004)
- * addiu v1, v1, low_16bit_of_mcount
+ * addiu v1, v1, low_16bit_of_mcount --> nop (CONFIG_32BIT)
* move at, ra
* jalr v1
* nop | move $12, ra_address | sub sp, sp, 8
@@ -184,10 +218,14 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
unsigned int new;
unsigned long ip = rec->ip;
- new = in_kernel_space(ip) ? insn_jal_ftrace_caller :
- insn_lui_v1_hi16_mcount;
+ new = in_kernel_space(ip) ? insn_jal_ftrace_caller : insn_la_mcount[0];
+#ifdef CONFIG_64BIT
return ftrace_modify_code(ip, new);
+#else
+ return ftrace_modify_code_2r(ip, new, in_kernel_space(ip) ?
+ INSN_NOP : insn_la_mcount[1]);
+#endif
}
#define FTRACE_CALL_IP ((unsigned long)(&ftrace_call))