@@ -72,6 +72,7 @@ int main(void)
DEFINE(THREAD, offsetof(struct task_struct, thread));
DEFINE(MM, offsetof(struct task_struct, mm));
DEFINE(MMCONTEXTID, offsetof(struct mm_struct, context.id));
+ DEFINE(TASK_TRACEREC, offsetof(struct task_struct, trace_recursion));
#ifdef CONFIG_PPC64
DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context));
DEFINE(SIGSEGV, SIGSEGV);
@@ -1202,7 +1202,13 @@ _GLOBAL(ftrace_caller)
SAVE_8GPRS(16,r1)
SAVE_8GPRS(24,r1)
-
+ ld r3, PACACURRENT(r13)
+ ld r4, TASK_TRACEREC(r3)
+ andi. r5, r4, 0x0010 // ( 1 << TRACE_FTRACE_BIT )
+ ori r4, r4, 0x0010
+ std r4, TASK_TRACEREC(r3)
+ bne- 3f // ftrace in progress - avoid recursion!
+
LOAD_REG_IMMEDIATE(r3,function_trace_op)
ld r5,0(r3)
@@ -1224,9 +1230,14 @@ ftrace_call:
bl ftrace_stub
nop
+ ld r3, PACACURRENT(r13)
+ ld r4, TASK_TRACEREC(r3)
+ andi. r4, r4, 0xffef // ~( 1 << TRACE_FTRACE_BIT )
+ std r4, TASK_TRACEREC(r3)
+
ld r3, _NIP(r1)
mtlr r3
-
+3:
REST_8GPRS(0,r1)
REST_8GPRS(8,r1)
REST_8GPRS(16,r1)
This is an *emergency* parachute to avoid an endless recursion and consecutively a kernel stack overflow, should any function within some ftrace framework cause an access fault, which calls _mcount / ftrace_caller in return and so on. It might also call an ftrace'd function directly. As Michael Ellerman pointed out, it is a tedious and error-prone task to maintain a complete list of those functions that _might_ get called from *_access_fault or any dynamic tracer function. So we'll concentrate on the most frequent cases to enhance performance later, while for now sticking with this fill-in. It will later serve as a backup protection. * arch/powerpc/kernel/entry_64.S: - test-and-set TRACE_FTRACE_BIT in task_struct's trace_recursion, do not call the actual tracer function if set, clear flag on return. Signed-off-by: Torsten Duwe <duwe@suse.de> --- arch/powerpc/kernel/asm-offsets.c | 1 + arch/powerpc/kernel/entry_64.S | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-)