Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'parisc-4.6-4' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux

Pull parisc ftrace fixes from Helge Deller:
"This is (most likely) the last pull request for v4.6 for the parisc
architecture.

It fixes the FTRACE feature for parisc, which is horribly broken since
quite some time and doesn't even compile. This patch just fixes the
bare minimum (it actually removes more lines than it adds), so that
the function tracer works again on 32- and 64bit kernels.

I've queued up additional patches on top of this patch which e.g. add
the syscall tracer, but those have to wait for the merge window for
v4.7."

* 'parisc-4.6-4' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
parisc: Fix ftrace function tracer

+117 -171
+2 -2
arch/parisc/Kconfig
··· 4 4 select ARCH_MIGHT_HAVE_PC_PARPORT 5 5 select HAVE_IDE 6 6 select HAVE_OPROFILE 7 - select HAVE_FUNCTION_TRACER if 64BIT 8 - select HAVE_FUNCTION_GRAPH_TRACER if 64BIT 7 + select HAVE_FUNCTION_TRACER 8 + select HAVE_FUNCTION_GRAPH_TRACER 9 9 select ARCH_WANT_FRAME_POINTERS 10 10 select RTC_CLASS 11 11 select RTC_DRV_GENERIC
+4
arch/parisc/Kconfig.debug
··· 2 2 3 3 source "lib/Kconfig.debug" 4 4 5 + config TRACE_IRQFLAGS_SUPPORT 6 + def_bool y 7 + 5 8 config DEBUG_RODATA 6 9 bool "Write protect kernel read-only data structures" 7 10 depends on DEBUG_KERNEL 11 + default y 8 12 help 9 13 Mark the kernel read-only data as write-protected in the pagetables, 10 14 in order to catch accidental (and incorrect) writes to such const
+1 -3
arch/parisc/Makefile
··· 62 62 63 63 # Without this, "ld -r" results in .text sections that are too big 64 64 # (> 0x40000) for branches to reach stubs. 65 - ifndef CONFIG_FUNCTION_TRACER 66 - cflags-y += -ffunction-sections 67 - endif 65 + cflags-y += -ffunction-sections 68 66 69 67 # Use long jumps instead of long branches (needed if your linker fails to 70 68 # link a too big vmlinux executable). Not enabled for building modules.
+1 -17
arch/parisc/include/asm/ftrace.h
··· 4 4 #ifndef __ASSEMBLY__ 5 5 extern void mcount(void); 6 6 7 - /* 8 - * Stack of return addresses for functions of a thread. 9 - * Used in struct thread_info 10 - */ 11 - struct ftrace_ret_stack { 12 - unsigned long ret; 13 - unsigned long func; 14 - unsigned long long calltime; 15 - }; 16 - 17 - /* 18 - * Primary handler of a function return. 19 - * It relays on ftrace_return_to_handler. 20 - * Defined in entry.S 21 - */ 22 - extern void return_to_handler(void); 23 - 7 + #define MCOUNT_INSN_SIZE 4 24 8 25 9 extern unsigned long return_address(unsigned int); 26 10
-4
arch/parisc/kernel/Makefile
··· 15 15 # Do not profile debug and lowlevel utilities 16 16 CFLAGS_REMOVE_ftrace.o = -pg 17 17 CFLAGS_REMOVE_cache.o = -pg 18 - CFLAGS_REMOVE_irq.o = -pg 19 - CFLAGS_REMOVE_pacache.o = -pg 20 18 CFLAGS_REMOVE_perf.o = -pg 21 - CFLAGS_REMOVE_traps.o = -pg 22 - CFLAGS_REMOVE_unaligned.o = -pg 23 19 CFLAGS_REMOVE_unwind.o = -pg 24 20 endif 25 21
+76 -21
arch/parisc/kernel/entry.S
··· 1970 1970 b intr_restore 1971 1971 copy %r25,%r16 1972 1972 1973 - .import schedule,code 1974 1973 syscall_do_resched: 1975 - BL schedule,%r2 1974 + load32 syscall_check_resched,%r2 /* if resched, we start over again */ 1975 + load32 schedule,%r19 1976 + bv %r0(%r19) /* jumps to schedule() */ 1976 1977 #ifdef CONFIG_64BIT 1977 1978 ldo -16(%r30),%r29 /* Reference param save area */ 1978 1979 #else 1979 1980 nop 1980 1981 #endif 1981 - b syscall_check_resched /* if resched, we start over again */ 1982 - nop 1983 1982 ENDPROC(syscall_exit) 1984 1983 1985 1984 1986 1985 #ifdef CONFIG_FUNCTION_TRACER 1986 + 1987 1987 .import ftrace_function_trampoline,code 1988 - ENTRY(_mcount) 1989 - copy %r3, %arg2 1988 + .align L1_CACHE_BYTES 1989 + .globl mcount 1990 + .type mcount, @function 1991 + ENTRY(mcount) 1992 + _mcount: 1993 + .export _mcount,data 1994 + .proc 1995 + .callinfo caller,frame=0 1996 + .entry 1997 + /* 1998 + * The 64bit mcount() function pointer needs 4 dwords, of which the 1999 + * first two are free. We optimize it here and put 2 instructions for 2000 + * calling mcount(), and 2 instructions for ftrace_stub(). That way we 2001 + * have all on one L1 cacheline. 2002 + */ 1990 2003 b ftrace_function_trampoline 1991 - nop 1992 - ENDPROC(_mcount) 1993 - 1994 - ENTRY(return_to_handler) 1995 - load32 return_trampoline, %rp 1996 - copy %ret0, %arg0 1997 - copy %ret1, %arg1 1998 - b ftrace_return_to_handler 1999 - nop 2000 - return_trampoline: 2001 - copy %ret0, %rp 2002 - copy %r23, %ret0 2003 - copy %r24, %ret1 2004 - 2005 - .globl ftrace_stub 2004 + copy %r3, %arg2 /* caller original %sp */ 2006 2005 ftrace_stub: 2006 + .globl ftrace_stub 2007 + .type ftrace_stub, @function 2008 + #ifdef CONFIG_64BIT 2009 + bve (%rp) 2010 + #else 2007 2011 bv %r0(%rp) 2012 + #endif 2008 2013 nop 2014 + #ifdef CONFIG_64BIT 2015 + .dword mcount 2016 + .dword 0 /* code in head.S puts value of global gp here */ 2017 + #endif 2018 + .exit 2019 + .procend 2020 + ENDPROC(mcount) 2021 + 2022 + .align 8 2023 + .globl return_to_handler 2024 + .type return_to_handler, @function 2025 + ENTRY(return_to_handler) 2026 + .proc 2027 + .callinfo caller,frame=FRAME_SIZE 2028 + .entry 2029 + .export parisc_return_to_handler,data 2030 + parisc_return_to_handler: 2031 + copy %r3,%r1 2032 + STREG %r0,-RP_OFFSET(%sp) /* store 0 as %rp */ 2033 + copy %sp,%r3 2034 + STREGM %r1,FRAME_SIZE(%sp) 2035 + STREG %ret0,8(%r3) 2036 + STREG %ret1,16(%r3) 2037 + 2038 + #ifdef CONFIG_64BIT 2039 + loadgp 2040 + #endif 2041 + 2042 + /* call ftrace_return_to_handler(0) */ 2043 + #ifdef CONFIG_64BIT 2044 + ldo -16(%sp),%ret1 /* Reference param save area */ 2045 + #endif 2046 + BL ftrace_return_to_handler,%r2 2047 + ldi 0,%r26 2048 + copy %ret0,%rp 2049 + 2050 + /* restore original return values */ 2051 + LDREG 8(%r3),%ret0 2052 + LDREG 16(%r3),%ret1 2053 + 2054 + /* return from function */ 2055 + #ifdef CONFIG_64BIT 2056 + bve (%rp) 2057 + #else 2058 + bv %r0(%rp) 2059 + #endif 2060 + LDREGM -FRAME_SIZE(%sp),%r3 2061 + .exit 2062 + .procend 2009 2063 ENDPROC(return_to_handler) 2064 + 2010 2065 #endif /* CONFIG_FUNCTION_TRACER */ 2011 2066 2012 2067 #ifdef CONFIG_IRQSTACKS
+24 -124
arch/parisc/kernel/ftrace.c
··· 1 1 /* 2 2 * Code for tracing calls in Linux kernel. 3 - * Copyright (C) 2009 Helge Deller <deller@gmx.de> 3 + * Copyright (C) 2009-2016 Helge Deller <deller@gmx.de> 4 4 * 5 5 * based on code for x86 which is: 6 6 * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com> ··· 13 13 #include <linux/init.h> 14 14 #include <linux/ftrace.h> 15 15 16 + #include <asm/assembly.h> 16 17 #include <asm/sections.h> 17 18 #include <asm/ftrace.h> 18 19 19 20 20 - 21 21 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 22 - 23 - /* Add a function return address to the trace stack on thread info.*/ 24 - static int push_return_trace(unsigned long ret, unsigned long long time, 25 - unsigned long func, int *depth) 26 - { 27 - int index; 28 - 29 - if (!current->ret_stack) 30 - return -EBUSY; 31 - 32 - /* The return trace stack is full */ 33 - if (current->curr_ret_stack == FTRACE_RETFUNC_DEPTH - 1) { 34 - atomic_inc(&current->trace_overrun); 35 - return -EBUSY; 36 - } 37 - 38 - index = ++current->curr_ret_stack; 39 - barrier(); 40 - current->ret_stack[index].ret = ret; 41 - current->ret_stack[index].func = func; 42 - current->ret_stack[index].calltime = time; 43 - *depth = index; 44 - 45 - return 0; 46 - } 47 - 48 - /* Retrieve a function return address to the trace stack on thread info.*/ 49 - static void pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret) 50 - { 51 - int index; 52 - 53 - index = current->curr_ret_stack; 54 - 55 - if (unlikely(index < 0)) { 56 - ftrace_graph_stop(); 57 - WARN_ON(1); 58 - /* Might as well panic, otherwise we have no where to go */ 59 - *ret = (unsigned long) 60 - dereference_function_descriptor(&panic); 61 - return; 62 - } 63 - 64 - *ret = current->ret_stack[index].ret; 65 - trace->func = current->ret_stack[index].func; 66 - trace->calltime = current->ret_stack[index].calltime; 67 - trace->overrun = atomic_read(&current->trace_overrun); 68 - trace->depth = index; 69 - barrier(); 70 - current->curr_ret_stack--; 71 - 72 - } 73 - 74 - /* 75 - * Send the trace to the ring-buffer. 76 - * @return the original return address. 77 - */ 78 - unsigned long ftrace_return_to_handler(unsigned long retval0, 79 - unsigned long retval1) 80 - { 81 - struct ftrace_graph_ret trace; 82 - unsigned long ret; 83 - 84 - pop_return_trace(&trace, &ret); 85 - trace.rettime = local_clock(); 86 - ftrace_graph_return(&trace); 87 - 88 - if (unlikely(!ret)) { 89 - ftrace_graph_stop(); 90 - WARN_ON(1); 91 - /* Might as well panic. What else to do? */ 92 - ret = (unsigned long) 93 - dereference_function_descriptor(&panic); 94 - } 95 - 96 - /* HACK: we hand over the old functions' return values 97 - in %r23 and %r24. Assembly in entry.S will take care 98 - and move those to their final registers %ret0 and %ret1 */ 99 - asm( "copy %0, %%r23 \n\t" 100 - "copy %1, %%r24 \n" : : "r" (retval0), "r" (retval1) ); 101 - 102 - return ret; 103 - } 104 - 105 22 /* 106 23 * Hook the return address and push it in the stack of return addrs 107 24 * in current thread info. 108 25 */ 109 - void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) 26 + static void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) 110 27 { 111 28 unsigned long old; 112 - unsigned long long calltime; 113 29 struct ftrace_graph_ent trace; 30 + extern int parisc_return_to_handler; 114 31 115 32 if (unlikely(ftrace_graph_is_dead())) 116 33 return; ··· 36 119 return; 37 120 38 121 old = *parent; 39 - *parent = (unsigned long) 40 - dereference_function_descriptor(&return_to_handler); 41 - 42 - if (unlikely(!__kernel_text_address(old))) { 43 - ftrace_graph_stop(); 44 - *parent = old; 45 - WARN_ON(1); 46 - return; 47 - } 48 - 49 - calltime = local_clock(); 50 - 51 - if (push_return_trace(old, calltime, 52 - self_addr, &trace.depth) == -EBUSY) { 53 - *parent = old; 54 - return; 55 - } 56 122 57 123 trace.func = self_addr; 124 + trace.depth = current->curr_ret_stack + 1; 58 125 59 126 /* Only trace if the calling function expects to */ 60 - if (!ftrace_graph_entry(&trace)) { 61 - current->curr_ret_stack--; 62 - *parent = old; 63 - } 64 - } 127 + if (!ftrace_graph_entry(&trace)) 128 + return; 65 129 130 + if (ftrace_push_return_trace(old, self_addr, &trace.depth, 131 + 0 ) == -EBUSY) 132 + return; 133 + 134 + /* activate parisc_return_to_handler() as return point */ 135 + *parent = (unsigned long) &parisc_return_to_handler; 136 + } 66 137 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 67 138 68 - 69 - void ftrace_function_trampoline(unsigned long parent, 139 + void notrace ftrace_function_trampoline(unsigned long parent, 70 140 unsigned long self_addr, 71 141 unsigned long org_sp_gr3) 72 142 { 73 - extern ftrace_func_t ftrace_trace_function; 143 + extern ftrace_func_t ftrace_trace_function; /* depends on CONFIG_DYNAMIC_FTRACE */ 144 + extern int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace); 74 145 75 146 if (ftrace_trace_function != ftrace_stub) { 76 - ftrace_trace_function(parent, self_addr); 147 + /* struct ftrace_ops *op, struct pt_regs *regs); */ 148 + ftrace_trace_function(parent, self_addr, NULL, NULL); 77 149 return; 78 150 } 151 + 79 152 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 80 - if (ftrace_graph_entry && ftrace_graph_return) { 81 - unsigned long sp; 153 + if (ftrace_graph_return != (trace_func_graph_ret_t) ftrace_stub || 154 + ftrace_graph_entry != ftrace_graph_entry_stub) { 82 155 unsigned long *parent_rp; 83 156 84 - asm volatile ("copy %%r30, %0" : "=r"(sp)); 85 - /* sanity check: is stack pointer which we got from 86 - assembler function in entry.S in a reasonable 87 - range compared to current stack pointer? */ 88 - if ((sp - org_sp_gr3) > 0x400) 89 - return; 90 - 91 157 /* calculate pointer to %rp in stack */ 92 - parent_rp = (unsigned long *) org_sp_gr3 - 0x10; 158 + parent_rp = (unsigned long *) (org_sp_gr3 - RP_OFFSET); 93 159 /* sanity check: parent_rp should hold parent */ 94 160 if (*parent_rp != parent) 95 161 return; 96 - 162 + 97 163 prepare_ftrace_return(parent_rp, self_addr); 98 164 return; 99 165 }
+9
arch/parisc/kernel/head.S
··· 129 129 /* And the stack pointer too */ 130 130 ldo THREAD_SZ_ALGN(%r6),%sp 131 131 132 + #if defined(CONFIG_64BIT) && defined(CONFIG_FUNCTION_TRACER) 133 + .import _mcount,data 134 + /* initialize mcount FPTR */ 135 + /* Get the global data pointer */ 136 + loadgp 137 + load32 PA(_mcount), %r10 138 + std %dp,0x18(%r10) 139 + #endif 140 + 132 141 #ifdef CONFIG_SMP 133 142 /* Set the smp rendezvous address into page zero. 134 143 ** It would be safer to do this in init_smp_config() but