switch.h

Go to the documentation of this file.
00001 
00041 #ifndef CPU_ARM_HW_SWITCH_H
00042 #define CPU_ARM_HW_SWITCH_H
00043 
00044 #include <kern/proc_p.h>
00045 
00050 #define SCHEDULER_IRQ_ENTRY \
00051     asm volatile("sub   lr, lr, #4          \n\t"  /* Adjust LR */ \
00052                  "stmfd sp!, {r0}           \n\t"  /* Save r0 */ \
00053                  "stmfd sp, {sp}^           \n\t"  /* Save user SP */ \
00054                  "sub   sp, sp, #4          \n\t"  /* Decrement irq SP, writeback is illegal */ \
00055                  "ldmfd sp!, {r0}           \n\t"  /* Restore user SP immedately in r0 */ \
00056                  "stmfd r0!, {lr}       \n\t"  /* Store system LR in user stack */ \
00057                  "stmfd r0, {r1-r12,lr}^    \n\t"  /* Store registers on user stack (user LR too) */ \
00058                  "sub   r0, r0, #52         \n\t"  /* Decrement r0, writeback is illegal */ \
00059                  "ldmfd sp!, {r1}           \n\t"  /* Restore r0 */ \
00060                  "stmfd r0!, {r1}           \n\t"  /* Store r0 in user stack too */ \
00061                  "mrs   r1, spsr            \n\t"  /* Save SPSR... */ \
00062                  "stmfd r0!, {r1}           \n\t"  /*  ... in user stack */ \
00063                  "ldr   r1, =CurrentProcess \n\t"  /* Load in r1 &CurrentProcess->stack */ \
00064                  "ldr   r1, [r1, %0]        \n\t"  \
00065                  "str   r0, [r1]            \n\t"  /* Store the process SP */ \
00066                  "sub   fp, sp, #4          \n\t"  /* Store the process SP */ \
00067                  : /* no output */ \
00068                  : "n" (offsetof(Process, stack)) \
00069     )
00070 
00071 
00072 #define SCHEDULER_IRQ_EXIT \
00073     asm volatile("ldr   lr, =CurrentProcess \n\t"  /* Load &CurrentProcess->stack */ \
00074                  "ldr   lr, [lr, %0]        \n\t"  \
00075                  "ldr   lr, [lr]            \n\t"  /* Load current process SP */ \
00076                  "ldr   r0, =0xFFFFF000     \n\t"  /* End of interrupt for AT91 */ \
00077                  "str   r0, [r0, #0x130]    \n\t"  /* */ \
00078                  "ldmfd lr!, {r0}           \n\t"  /* Pop status reg */ \
00079                  "msr   spsr, r0            \n\t"  /* ... */ \
00080                  "ldmfd lr, {r0-r12,lr}^    \n\t"  /* Restore user regs */ \
00081                  "add   lr, lr, #56         \n\t"  /* 52 + irq link register (extracted below) */ \
00082              "stmfd sp!, {lr}           \n\t"  /* Push user stack pointer in irq stack */ \
00083              "ldmfd sp,  {sp}^          \n\t"  /* Restore user SP */ \
00084              "sub   sp, sp, #4          \n\t"  /* Align irq SP */ \
00085              "ldmdb lr, {pc}^           \n\t"  /* And return to user space (We use ldmdb cause lr is sp+4) */ \
00086                  : /* no output */ \
00087                  : "n" (offsetof(Process, stack))  \
00088     )
00089 
00090 #endif /* CPU_ARM_HW_SWITCH_H */