Subject: [RFC][PATCH]Kprobes for PPC32(BOOKE)

From: [email-masked]
Date: Fri, 20 Apr 2007 12:24:19 +0500

Hi Kumar,

This is regarding the kprobes patches for
PPC32 BOOKE version. The attached patches
contain the implementation for this version.

I saw your earlier postings and commits to 2.6.21
regarding kprobes for PPC32. Since the single 
step mechanism in BookE is quite different, I
thought i can share some of the issues faced 
in this implementation and get your review 
feedback for those patches.

Last month, i had posted the patches for 
PPC32(BookE) version in the below thread.

http://ozlabs.org/pipermail/linuxppc-dev/2007-March/033058.html

Kernel Version:- 2.6.16.39
Target: Ebony (ppc440_gp processor)

I had mentioned some issues regarding the preempt count
in the above thread with some issues. In today released patches,
these issues are fixed with some additional patches to 
head_booke.h and traps.c. With these changes, there are no 
issues noticed and kprobes behavior is same as other 
architetcures. 

Regarding the below issue mentioned in my earlier mail...
> 2. It was noticed that having preempt_disable() at the beginning of
> kprobe_handler, generates OOPS and kprobes doesnot work. But this is 
> against the original kprobes design implemented in other 
> already working 
> archs (that is, preemption is disabled for the entire 
> duration of pre and post
> handlers execution). The basic problem noticed is, change in 
> the preempt
> count after generating single step exception. Even though the 
> preemption
> is disabled at the beginning of kprobe_handler(), after generating the
> single step exception, preempt count gets printed as zero in 
> DebugException() 
> handler of traps.c. This causes the problem and system 
> generates OOPS!!
> 

The core issue was the way debug exception was getting handled
in PPC32 BookE versions. The debug exception gets executed
using exception stack which doesnot contain the original stack
preempt count status. This exact sequence can be explained 
as below

After executing pre handler, the DEBUG_EXCEPTION gets called 
because of setting DE bit in MSR and IC, IDM bits of DBCR0. 
As part of  DEBUG_EXCEPTION in head_booke.h, the exception 
stack is prepared by storing current registers and original sp. But the 
current preempt count value is not set in exception stack. Because of 
this, preempt_count=ZERO. This will enable preemption and at any point,
it can be rescheduled because of higher priority interrupts. Also as part
of post_kprobe_handler(), preempt_enable_no_resched() gets called,
which will try to decrement the preempt_count value by 1. But since
exception stack contains the preempt_count as ZERO, this operation
will make its value as NEGATIVE and that results in OOPS. Execution  
stops after this point and system reboots

Two solutions are incorporated to solve this fix
1. The head_booke.h is modified before setting the exception stack. This
patch takes care of copying the original stack preempt_count value to 
exception stack before Stack Pointer gets changed 
2. Also as part of traps.c within DebugException(), the original stack 
thread_info contents are copied to exception stack since other contents 
of current thread_info is also required.

With the above 2 fixes, the system is stable and the kprobes behavior 
is same as other architectures.

I am porting these patches to 2.6.21-rc7 and will resubmit these 
patches after testing.

Originally i thought of combining the 2nd patch contents as part of 1st 
patch in the form of assembly, but i could not do it because of my 
limited PPC assembly knowledge. 
If you have any comments regarding the above patches or better 
solution, please let me know and i shall try it in 2.6.21.rc7..

Regards
Madhvesh