[PATCH] [POWERPC] Rework EXC_LEVEL_EXCEPTION_PROLOG code
Kumar Gala
galak at kernel.crashing.org
Thu May 1 08:13:14 EST 2008
On Apr 30, 2008, at 4:54 PM, Benjamin Herrenschmidt wrote:
>
> On Wed, 2008-04-30 at 04:27 -0500, Kumar Gala wrote:
>> * Cleanup the code a bit my allocating an INT_FRAME on our exception
>> stack there by make references go from GPR11-INT_FRAME_SIZE(r8) to
>> just GPR(r8)
> ^^ 11 ?
r8 is correct for my example. My point is s/GPR11-INT_FRAME_SIZE/GPR11/
>> * simplify {lvl}_transfer_to_handler code by moving the copying of
>> the
>> temp registers we use if we come from user space into the PROLOG
>> * If the exception came from kernel mode copy thread_info flags,
>> preempt, and task pointer from the process thread_info.
>>
>> Signed-off-by: Kumar Gala <galak at kernel.crashing.org>
>> ---
>>
>> I'm not sure if the copying of TI_FLAGS, TI_PREEMPT, and TI_TASK
>> are really needed. I'm a bit concerned what to do if we get a
>> CriticalInput while in kernel mode and the handler causes a
>> reschedule.
>
> Well, reschedule or signal, either way, you can't handle them on the
> way
> out. Maybe an option there is to set the flag in the normal kernel
> stack's thread info and trigger an interrupt asap via the PIT so
> things
> get handled ?
If we don't handle reschedule or signal will we actually not function
properly? I assume reschedule isn't an issue, but could we lose a
signal?
>> diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/
>> head_booke.h
>> index d647e05..78baec5 100644
>> --- a/arch/powerpc/kernel/head_booke.h
>> +++ b/arch/powerpc/kernel/head_booke.h
>> @@ -78,12 +78,12 @@
>> slwi r8,r8,2; \
>> addis r8,r8,level##_STACK_TOP at ha; \
>> lwz r8,level##_STACK_TOP at l(r8); \
>> - addi r8,r8,THREAD_SIZE;
>> + addi r8,r8,THREAD_SIZE-INT_FRAME_SIZE;
>> #else
>> #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
>> lis r8,level##_STACK_TOP at ha; \
>> lwz r8,level##_STACK_TOP at l(r8); \
>> - addi r8,r8,THREAD_SIZE;
>> + addi r8,r8,THREAD_SIZE-INT_FRAME_SIZE;
>> #endif
>
> Nothing specific to your patch, but those level##_STACK_TOP seem to
> be pretty badly named if you end up -adding- THREAD_SIZE to actually
> get to the stack's top. Do they really contain the stack top or do
> they in fact contain the stack base/bottom ?
That might be stale from how the old code worked. I can never
remember what we consider the top and bottom of the stack. (please
remind me and I'll fixup the comments and variables).
>> /*
>> @@ -97,22 +97,35 @@
>> #define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, exc_level_srr0,
>> exc_level_srr1) \
>> mtspr exc_level##_SPRG,r8; \
>> BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the
>> exc_level stack*/ \
>> - stw r10,GPR10-INT_FRAME_SIZE(r8); \
>> - stw r11,GPR11-INT_FRAME_SIZE(r8); \
>> + stw r9,GPR9(r8); /* save various registers */\
>> + stw r10,GPR10(r8); \
>> + stw r11,GPR11(r8); \
>> + mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
>> + lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
>> + addi r11,r11,THREAD_SIZE-INT_FRAME_SIZE; /* Alloc exception frm */\
>
> So you do the above whether it will actually be needed or not right ?
good point I can move this down.
>> mfcr r10; /* save CR in r10 for now */\
>> - mfspr r11,exc_level_srr1; /* check whether user or kernel */\
>> - andi. r11,r11,MSR_PR; \
>> - mr r11,r8; \
>> - mfspr r8,exc_level##_SPRG; \
>> + mfspr r9,exc_level_srr1; /* check whether user or kernel */\
>> + andi. r9,r9,MSR_PR; \
>> beq 1f; \
>> /* COMING FROM USER MODE */ \
>> - mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
>> - lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
>> - addi r11,r11,THREAD_SIZE; \
>> -1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame
>> */\
>> + lwz r9,GPR9(r8); /* copy regs from exception stack */\
>> + stw r9,GPR9(r11); \
>> + lwz r9,GPR10(r8); \
>> + stw r9,GPR10(r11); \
>> + lwz r9,GPR11(r8); \
>> + stw r9,GPR11(r11); \
>> + b 2f; \
>
> Are we concerned with performances here or not ? Because using the
> same
> reg all along isn't the best ...
I thought about that. The only case its a bit of an issue is for
CriticalInput. I don't see Watchdog, Debug, or MachineCheck as being
performance critical. I can use r10 if I save and restored the CR or
some other register.
>> + /* COMING FROM PRIV MODE */ \
>> +1: lwz r9,TI_FLAGS-THREAD_SIZE(r11); \
>> + stw r9,TI_FLAGS-THREAD_SIZE(r8); \
>> + lwz r9,TI_PREEMPT-THREAD_SIZE(r11); \
>> + stw r9,TI_PREEMPT-THREAD_SIZE(r8); \
>> + lwz r9,TI_TASK-THREAD_SIZE(r11); \
>> + stw r9,TI_TASK-THREAD_SIZE(r8); \
>> + mr r11,r8; \
>
> Don't you want to also stick in HARDIRQ_OFFSET in preempt_count or
> leave that to C code ?
just leaving it to C code. I assume that preempt_count should be the
same value on entry and exit. Do think we should set HARDIRQ_OFFSET
for debug level exceptions?
> Also, you might want at one point to tell
> lockdep about IRQs being disabled in case they were enabled when
> you took the exception. (Do that after you've saved enough
> stuff of crouse)
Where should I look for an example of how to convey that information
to lockdep?
- k
More information about the Linuxppc-dev
mailing list