diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2008-11-11 00:41:22 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2008-11-11 00:41:22 +0000 |
commit | 733adb3c87afca8b4f50623aa3cad407cf203e88 (patch) | |
tree | 7d53d95b4f2b25b9b6f172595ba8cbc20be2ca78 /nuttx | |
parent | fca8049832b607144e4b68d2ec3022eb0385ae86 (diff) | |
download | px4-nuttx-733adb3c87afca8b4f50623aa3cad407cf203e88.tar.gz px4-nuttx-733adb3c87afca8b4f50623aa3cad407cf203e88.tar.bz2 px4-nuttx-733adb3c87afca8b4f50623aa3cad407cf203e88.zip |
Fix several context switching bugs
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1187 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx')
-rw-r--r-- | nuttx/arch/sh/include/sh1/irq.h | 54 | ||||
-rw-r--r-- | nuttx/arch/sh/src/sh1/sh1_saveusercontext.S | 7 | ||||
-rw-r--r-- | nuttx/arch/sh/src/sh1/sh1_vector.S | 247 |
3 files changed, 210 insertions, 98 deletions
diff --git a/nuttx/arch/sh/include/sh1/irq.h b/nuttx/arch/sh/include/sh1/irq.h index 3c169db57..186e6834b 100644 --- a/nuttx/arch/sh/include/sh1/irq.h +++ b/nuttx/arch/sh/include/sh1/irq.h @@ -349,38 +349,44 @@ /* Saved to the stacked by up_vector */ -#define REG_R0 (0) -#define REG_R1 (1) -#define REG_R2 (2) -#define REG_R3 (3) -#define REG_R5 (5) -#define REG_R6 (6) -#define REG_R7 (7) -#define REG_R8 (8) -#define REG_R9 (9) -#define REG_R10 (10) -#define REG_R11 (11) -#define REG_R12 (12) -#define REG_R13 (13) -#define REG_R14 (14) - -#define REG_PR (15) -#define REG_GBR (16) -#define REG_MACH (17) -#define REG_MACL (18) +#define REG_R8 (0) +#define REG_R9 (1) +#define REG_R10 (2) +#define REG_R11 (3) +#define REG_R12 (4) +#define REG_R13 (5) +#define REG_R14 (6) + +#define REG_PR (7) +#define REG_GBR (8) + +/* The value of the stack pointer *before* the interrupt occurred */ + +#define REG_R15 (9) +#define REG_SP REG_R15 + +/* These registers do not need to be preserved by up_saveusercontext */ + +#define REG_MACL (10) +#define REG_MACH (11) +#define REG_R0 (12) +#define REG_R1 (13) +#define REG_R2 (14) +#define REG_R3 (15) +#define REG_R5 (16) +#define REG_R6 (17) +#define REG_R7 (18) /* Saved to the stack by the trampoline logic */ #define REG_R4 (19) -#define REG_R15 (20) -#define REG_SP REG_R15 /* Pushed by hardware when the exception is taken */ -#define REG_PC (21) -#define REG_SR (22) +#define REG_PC (20) +#define REG_SR (21) -#define XCPTCONTEXT_REGS (23) +#define XCPTCONTEXT_REGS (22) #define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS) /************************************************************************************ diff --git a/nuttx/arch/sh/src/sh1/sh1_saveusercontext.S b/nuttx/arch/sh/src/sh1/sh1_saveusercontext.S index 1a80cd642..d9a430816 100644 --- a/nuttx/arch/sh/src/sh1/sh1_saveusercontext.S +++ b/nuttx/arch/sh/src/sh1/sh1_saveusercontext.S @@ -97,8 +97,8 @@ _up_saveusercontext: stc sr, r0 /* Get and save the SR */ mov.l r0, @-r4 sts.l pr, @-r4 /* The return address is the restore PC */ + add #-(10*4), r4 /* Skip over r0-r7, mach and macl */ mov.l r15, @-r4 - add #-(4*3), r4 /* Skip of mach, macl, r4 */ stc.l gbr, @-r4 sts.l pr, @-r4 @@ -110,11 +110,6 @@ _up_saveusercontext: mov.l r9, @-r4 mov.l r8, @-r4 - /* Omit r1-r7. They do not matter when saving user state.. - * the calling conventions do not require that the values of these - * registers persist across function calls. - */ - /* And return zero */ rts diff --git a/nuttx/arch/sh/src/sh1/sh1_vector.S b/nuttx/arch/sh/src/sh1/sh1_vector.S index 5afb0e99a..2dab495d1 100644 --- a/nuttx/arch/sh/src/sh1/sh1_vector.S +++ b/nuttx/arch/sh/src/sh1/sh1_vector.S @@ -73,15 +73,14 @@ * * R4 : IRQ vector number * SP -> Saved R4 - * Saved SP (R15) * PC * SR * ************************************************************************************/ .macro trampoline, irq, label - mov.l r4, @-r15 /* Save R4 on the stack */ - mov.w .L\label, r4 /* With the IRQ number in R4 */ + mov.l r4, @-r15 /* Save the value of R4 on the stack */ + mov.w .L\label, r4 /* R4=IRQ number */ bra _up_vector /* Jump to the common vector handling logic */ nop .L\label: @@ -245,39 +244,15 @@ _up_cmi_handler: #endif /***************************************************************************** - * Name: _up_fullcontextrestore - * - * Description: - * restore context from a set of save registers - * - * R4 : Points to a the register save structure - * - *****************************************************************************/ - - .global _up_fullcontextrestore - .type _up_fullcontextrestore, #function - -_up_fullcontextrestore: - stc sr, r8 /* Mask all interrupts */ - mov.l .Lintmask, r9 - or r9, r8 - ldc r8, sr - - mov r5, r15 /* Replace stack pointer with the context save */ - bra _up_restoreregs - .size _up_fullcontextrestore, .-_up_fullcontextrestore - -/***************************************************************************** * Name: _up_vector * * Description: * Execption entry point. Upon entry: * * R4 : Holds IRQ number - * SP -> Saved R4 - * Saved SP (R15) - * PC - * SR + * SP -> Saved R4 (REG_R4=19) See irq.h + * PC (REG_PC=20) + * SR (REG_SR=21) * *****************************************************************************/ @@ -285,10 +260,66 @@ _up_fullcontextrestore: .type _up_vector, #function _up_vector: - /* Save the registers on the stack. (R4 is already saved) */ + /* Save r0-r3, r5-r7 on the stack so that we have a registers to work with. + * After this, the stack will look like: + * + * SP -> macl (REG_MACL=10) See irq.h + * mach (REG_MACH=11) + * r0 (REG_R0=12) + * r1 (REG_R1=13) + * r2 (REG_R2=14) + * r3 (REG_R3=15) + * r5 (REG_R5=16) + * r6 (REG_R6=17) + * r7 (REG_R7=18) + * R4 (REG_R4=19) + * ... + */ + + mov.l r7, @-r15 + mov.l r6, @-r15 + + stc sr, r6 /* Mask all interrupts */ + mov.l .Lintmask, r7 + or r7, r6 + ldc r6, sr + + mov.l r5, @-r15 + mov.l r3, @-r15 + mov.l r2, @-r15 + mov.l r1, @-r15 + mov.l r0, @-r15 - sts.l macl, @-r15 sts.l mach, @-r15 + sts.l macl, @-r15 + + /* Then save the value of the SP *before* the interrupt ocurred + * + * SP -> SP (REG_SP=9) See irq.h + * macl (REG_MACL=10) + * mach (REG_MACH=11) + * ... + */ + + mov r15, r5 /* R5 = current SP */ + add #(12*4), r5 /* Account for sr, pc, r0-r7, mach, and macl */ + mov.l r5, @-r15 /* Save the SP before the interrupt */ + + /* Save the remaining registers on the stack: + * + * SP -> r8 (REG_R8=0) See irq.h + * r9 (REG_R9=1) + * r10 (REG_R10=2) + * r11 (REG_R11=3) + * r12 (REG_R12=4) + * r13 (REG_R13=5) + * r14 (REG_R14=6) + * pr (REG_PR=7) + * gbr (REG_GBR=8) + * SP (REG_SP=9) + * ... + */ + stc.l gbr, @-r15 sts.l pr, @-r15 @@ -300,19 +331,6 @@ _up_vector: mov.l r9, @-r15 mov.l r8, @-r15 - stc sr, r8 /* Mask all interrupts */ - mov.l .Lintmask, r9 - or r9, r8 - ldc r8, sr - - mov.l r7, @-r15 - mov.l r6, @-r15 - mov.l r5, @-r15 - mov.l r3, @-r15 - mov.l r2, @-r15 - mov.l r1, @-r15 - mov.l r0, @r15 - /* Setup parameters: R4=IRQ number, R5=base of saved state */ mov r15, r5 @@ -321,35 +339,102 @@ _up_vector: #if CONFIG_ARCH_INTERRUPTSTACK > 3 mov.l .Lintstack, r15 /* SP = interrupt stack base */ - mov.l r5, @sp /* Save the user stack pointer */ -#endif + mov.l r5, @sp /* Save the user stack pointer (pre-decremented) */ + /* Dispatch the interrupt */ mov.l .Ldoirq, r0 jsr @r0 mov r15, r14 + /* Recover the user stack point */ + + mov.l @sp, r15 +#else + /* Dispatch the interrupt */ + + mov.l .Ldoirq, r0 + jsr @r0 + mov r15, r14 +#endif /* On return, R0 holds the address of the base of the XCPTCONTEXT - * structure to use for the return (may not be the same as the - * one that we passed in via r5. + * structure to use for the return -- may not be the same as the + * one that we passed in via r5. If the value is different, then + * we cannot assume that the values lie on the stack and we will + * need to execute some more complete logic. */ - add #-XCPTCONTEXT_SIZE, r0 + cmp/eq r0, r15 + bf .Lcontextswitch mov r0, r15 - /* Restore registers. R15 may point to either the stack or a saved - * context structure inside of a TCB. - */ + /* Restore registers from the stack. */ -_up_restoreregs: - mov.l @r15+, r0 + mov.l @r15+, r8 /* 0-8: r8-r14, pr, and gbr */ + mov.l @r15+, r9 + mov.l @r15+, r10 + mov.l @r15+, r11 + mov.l @r15+, r12 + mov.l @r15+, r13 + mov.l @r15+, r14 + + lds.l @r15+, pr + ldc.l @r15+, gbr + + add #4, r15 /* 9: Skip SP restore */ + + lds.l @r15+, macl /* 10-11: mach and macl */ + lds.l @r15+, mach + + mov.l @r15+, r0 /* 12-18: r0-r3, r5-r7 */ mov.l @r15+, r1 mov.l @r15+, r2 mov.l @r15+, r3 mov.l @r15+, r5 mov.l @r15+, r6 mov.l @r15+, r7 - mov.l @r15+, r8 + + mov.l @r15+, r4 /* 19: r4 */ + rte /* 20-21: pc and sr */ + nop + .align 2 +#if CONFIG_ARCH_INTERRUPTSTACK > 3 +.Lintstack: + .long _up_stackbase +#endif +.Ldoirq: + .long _up_doirq + .size _up_vector, .-_up_vector + +/***************************************************************************** + * Name: _up_fullcontextrestore + * + * Description: + * restore context from a set of save registers + * + * R4 : Points to a the register save structure + * + *****************************************************************************/ + + .global _up_fullcontextrestore + .type _up_fullcontextrestore, #function + +_up_fullcontextrestore: + /* Mask all interrupts */ + + stc sr, r8 + mov.l .Lintmask, r9 + or r9, r8 + ldc r8, sr + + /* Replace stack pointer with the context save */ + + mov r4, r15 + + /* Restore registers from a context structure */ + +.Lcontextswitch: + mov.l @r15+, r8 /* 0-8: r8-r14, pr, and gbr */ mov.l @r15+, r9 mov.l @r15+, r10 mov.l @r15+, r11 @@ -359,24 +444,50 @@ _up_restoreregs: lds.l @r15+, pr ldc.l @r15+, gbr + + mov.l @r15+, r4 /* r4: Saved SP */ + + lds.l @r15+, macl /* 10-11: mach and macl */ lds.l @r15+, mach - lds.l @r15+, macl + mov.l @r15+, r0 /* 12-17: r0-r3, r5-r6 */ + mov.l @r15+, r1 + mov.l @r15+, r2 + mov.l @r15+, r3 + mov.l @r15+, r5 + mov.l @r15+, r6 + + /* Copy the remainder of the stack context to the target stack. + * At this point r15 points to offset REG_R6. + */ + + add #-16, r4 /* R4 points to offset REG_R7 in the new stack */ + mov.l @r15+, r7 /* R7=Saved R7 value */ + mov.l r7, @r4 /* Save at offset REG_R7 in the new stack */ + mov.l @r15+, r7 /* R7=Save R4 value */ + mov.l r7, @(4,r4) /* Save at offset REG_R4 in the new stack */ + mov.l @r15+, r7 /* R7=Save PC value */ + mov.l r7, @(8,r4) /* Save at offset REG_PC in the new stack */ + mov.l @r15+, r7 /* R7=Save SR value */ + mov.l r7, @(12,r4) /* Save at offset REG_SR in the new stack */ + + /* Set the new stack pointer */ + + mov r4, r15 + + /* Then recover the final register values from the new stack */ + + mov.l @r15+, r7 mov.l @r15+, r4 - mov.l @r15, r15 /* The real stack pointer */ + + /* And return from interrupt */ + rte nop - .align 2 .Lintmask: .long 0x000000f0 -#if CONFIG_ARCH_INTERRUPTSTACK > 3 -.Lintstack: - .long _up_stackbase -#endif -.Ldoirq: - .long _up_doirq - .size _up_vector, .-_up_vector + .size _up_fullcontextrestore, .-_up_fullcontextrestore /************************************************************************************ * Name: up_interruptstack/g_userstack @@ -388,14 +499,14 @@ _up_restoreregs: #if CONFIG_ARCH_INTERRUPTSTACK > 3 .bss - .align 4 + .align 2 .globl _g_userstack .type _g_userstack, object _up_interruptstack: .skip ((CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4) _g_userstack: _up_stackbase: - .skip 4 + .skip 2 .size _g_userstack, 4 .size _up_interruptstack, (CONFIG_ARCH_INTERRUPTSTACK & ~3) #endif |