[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