[Barrelfish-users] CPSR condition bits destroied by ensure_user_mode_policy
Wang Nan
wangnan0 at huawei.com
Fri Jul 12 07:54:11 CEST 2013
Hi,
I meet some strange problems and digg into context switching code, and I found that I can't understand ensure_user_mode_policy() in kernel/arch/arm/exec.c.
That function is called by resume(). I believe the original intention is to make sure CPSR is in user mode and make interruption enabled.
Following I list its code and add some comments:
static inline void
ensure_user_mode_policy(arch_registers_state_t *state)
{
/*
* CPSR_F_MASK is 0x40, which is for FIQ, and 1 means
* exception disabled. Do you deliberately mask FIQ and allow IRQ?
* In our system, setting F bit takes no effect: it always restore to 0 by the processor.
*/
uintptr_t cpsr_if_mode = CPSR_F_MASK | ARM_MODE_USR;
if ((state->named.cpsr & (CPSR_IF_MASK | ARM_MODE_MASK)) != cpsr_if_mode) {
assert(0 == (state->named.cpsr & ARM_MODE_PRIV));
/*
* all condition flags are zeroed, only A and I bits are kept.
*/
state->named.cpsr &= CPSR_IF_MASK | ARM_MODE_MASK;
/*
* the final result is to set cpsr to 0x50 | (original A and I bits),
* if original cpsr is interruption disabled (I bit is set), the resuling cpsr still mask interruption.
*/
state->named.cpsr |= cpsr_if_mode;
}
}
The above code makes obscure problems:
Follwoing is assembly code for disp_save:
004854ec <disp_save>:
4854ec: e1a0c00d mov ip, sp
4854f0: e92dd9f0 push {r4, r5, r6, r7, r8, fp, ip, lr, pc}
4854f4: e24cb004 sub fp, ip, #4
4854f8: e1a05009 mov r5, r9
4854fc: e1500005 cmp r0, r5
485500: e24dd00c sub sp, sp, #12
485504: e1a04000 mov r4, r0
485508: e1a06001 mov r6, r1
48550c: e1a07002 mov r7, r2
485510: e1a08003 mov r8, r3
485514: 0a000025 beq 4855b0 <disp_save+0xc4>
...
If interruption (currently, only timer generates interruption) raise at 485510, the condition bits become incorrect after it resume. The
phenomenon is assertion failure: the program report that curdispatcher != handle. This problem takes us a full day on debugging.
Following is my suggestion about this function:
static inline void
ensure_user_mode_policy(arch_registers_state_t *state)
{
uintptr_t cpsr_if_mode = ARM_MODE_USR;
if ((state->named.cpsr & (CPSR_IF_MASK | ARM_MODE_MASK)) != cpsr_if_mode) {
state->named.cpsr &= ~(CPSR_IF_MASK | ARM_MODE_MASK);
state->named.cpsr |= cpsr_if_mode;
}
}
I'm not very familiary to FIQ, but in our system F bit can't be set. Could anyone can review my code and check for F bit stuff?
Thank you.
More information about the Barrelfish-users
mailing list