[arch][arm] add new v6 irq glue, refactor user space regs out of context switch

Add new mechanism for v6 style mode bouncing, leave the old one in as an
arch conditional. Have the irq glue save user space regs and move it out of
the main context switch mechanism.
This commit is contained in:
Travis Geiselbrecht
2013-01-12 20:34:11 -08:00
parent 5c6b69d313
commit 787cda90d2
5 changed files with 113 additions and 66 deletions

View File

@@ -21,11 +21,9 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <asm.h>
#include <arch/arm/cores.h>
/* context switch frame is as follows:
* ulr
* usp
* lr
* r11
* r10
@@ -38,29 +36,26 @@
*/
/* arm_context_switch(addr_t *old_sp, addr_t new_sp) */
FUNCTION(arm_context_switch)
/* save all the usual registers + user regs */
/* the spsr is saved and restored in the iframe by exceptions.S */
sub r3, sp, #(11*4) /* can't use sp in user mode stm */
mov r12, lr
stmia r3, { r4-r11, r12, r13, r14 }^
/* save non callee trashed supervisor registers */
/* spsr and user mode registers are saved and restored in the iframe by exceptions.S */
push { r4-r11, lr }
/* save old sp */
str r3, [r0]
str sp, [r0]
/* clear any exlusive locks that the old thread holds */
#if ARM_ISA_ARMV7
#if ARM_ARCH_LEVEL >= 7
/* can clear it directly */
.word 0xf57ff01f // clrex
#elif ARM_ISA_ARMV6
clrex
#elif ARM_ARCH_LEVEL == 6
/* have to do a fake strex to clear it */
ldr r0, =strex_spot
strex r3, r2, [r0]
#endif
/* load new regs */
ldmia r1, { r4-r11, r12, r13, r14 }^
mov lr, r12 /* restore lr */
add sp, r1, #(11*4) /* restore sp */
mov sp, r1
pop { r4-r11, lr }
bx lr
.ltorg

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
* Copyright (c) 2008-2013 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
@@ -21,6 +21,78 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <asm.h>
#include <arch/arm/cores.h>
#if ARM_ARCH_LEVEL >= 6
.macro save, offset
/* save spsr and r14 onto the svc stack */
sub lr, #\offset
srsdb #0x13!
/* switch to svc mode, interrupts disabled */
cpsid i,#0x13
/* save callee trashed regs and lr */
push { r0-r3, r12, lr }
/* save user space sp/lr */
sub sp, #8
stmia sp, { r13, r14 }^
.endm
.macro restore
/* restore user space sp/lr */
ldmia sp, { r13, r14 }^
add sp, #8
pop { r0-r3, r12, lr }
/* return to whence we came from */
rfeia sp!
.endm
#else
.macro save, offset
/* XXX only deals with interrupting supervisor mode */
/* save r4-r6 and use as a temporary place to save while we switch into supervisor mode */
stmia r13, { r4-r6 }
mov r4, r13
sub r5, lr, #\offset
mrs r6, spsr
/* move into supervisor mode. irq/fiq disabled */
msr cpsr_c, #(3<<6 | 0x13)
/* save the return address */
stmfd sp!, { r5 }
/* save C trashed regs, supervisor lr */
stmfd sp!, { r0-r3, r12, lr }
/* save spsr */
stmfd sp!, { r6 }
/* restore r4-r6 */
ldmia r4, { r4-r6 }
/* save user space sp/lr */
sub sp, #8
stmia sp, { r13, r14 }^
.endm
.macro restore
/* restore user space sp/lr */
ldmia sp, { r13, r14 }^
add sp, #8
/* restore spsr */
ldmfd sp!, { r0 }
msr spsr_cxsf, r0
/* restore back to where we came from */
ldmfd sp!, { r0-r3, r12, lr, pc }^
.endm
#endif
FUNCTION(arm_undefined)
stmfd sp!, { r0-r12, r14 }
@@ -39,7 +111,7 @@ FUNCTION(arm_syscall)
stmia r0, { r1, r13-r14 }^
b arm_syscall_handler
b .
FUNCTION(arm_prefetch_abort)
stmfd sp!, { r0-r12, r14 }
sub sp, sp, #12
@@ -57,40 +129,19 @@ FUNCTION(arm_data_abort)
stmia r0, { r1, r13-r14 }^
b arm_data_abort_handler
b .
FUNCTION(arm_reserved)
b .
FUNCTION(arm_irq)
/* XXX only deals with interrupting supervisor mode */
/* save r4-r6 and use as a temporary place to save while we switch into supervisor mode */
stmia r13, { r4-r6 }
mov r4, r13
sub r5, lr, #4
mrs r6, spsr
/* move into supervisor mode. irq/fiq disabled */
msr cpsr_c, #(3<<6 | 0x13)
/* save the return address */
stmfd sp!, { r5 }
/* save C trashed regs, supervisor lr */
stmfd sp!, { r0-r3, r12, lr }
/* save spsr */
stmfd sp!, { r6 }
/* restore r4-r6 */
ldmia r4, { r4-r6 }
save 4
/* increment the global critical section count */
ldr r1, =critical_section_count
ldr r0, [r1]
add r0, r0, #1
str r0, [r1]
/* call into higher level code */
mov r0, sp /* iframe */
bl platform_irq
@@ -105,28 +156,22 @@ FUNCTION(arm_irq)
sub r0, r0, #1
str r0, [r1]
/* restore spsr */
ldmfd sp!, { r0 }
msr spsr_cxsf, r0
restore
/* restore back to where we came from */
ldmfd sp!, { r0-r3, r12, lr, pc }^
.bss
.align 2
.global irq_save_spot
irq_save_spot:
.word 0 /* r4 */
.word 0 /* r5 */
.word 0 /* r6 */
.text
FUNCTION(arm_fiq)
sub lr, lr, #4
stmfd sp!, { r0-r3, r12, lr }
bl platform_fiq
ldmfd sp!, { r0-r3, r12, pc }^
.bss
.align 2
DATA(irq_save_spot)
.word 0 /* r4 */
.word 0 /* r5 */
.word 0 /* r6 */
.ltorg

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
* Copyright (c) 2008-2013 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
@@ -20,6 +20,9 @@
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <asm.h>
#include <arch/arm/cores.h>
.section ".text.boot"
.globl _start
_start:
@@ -82,7 +85,7 @@ reset:
orr r1, r0, #0x12 // irq
msr cpsr_c, r1
ldr r13, =irq_save_spot /* save a pointer to a temporary dumping spot used during irq delivery */
orr r1, r0, #0x11 // fiq
msr cpsr_c, r1
mov sp, r2
@@ -133,15 +136,15 @@ reset:
.ltorg
.bss
.align 2
.align 3
/* the abort stack is for unrecoverable errors.
* also note the initial working stack is set to here.
* when the threading system starts up it'll switch to a new
* dynamically allocated stack, so we don't need it for very long
*/
abort_stack:
LOCAL_DATA(abort_stack)
.skip 1024
abort_stack_top:
LOCAL_DATA(abort_stack_top)
.data
.align 2
@@ -149,6 +152,5 @@ abort_stack_top:
/* define the heap end a variable containing the end defined in the
* linker script. this could be updated during init.
*/
.global _heap_end
_heap_end:
DATA(_heap_end)
.int _end_of_ram

View File

@@ -37,8 +37,6 @@ struct context_switch_frame {
vaddr_t r10;
vaddr_t r11;
vaddr_t lr;
vaddr_t usp;
vaddr_t ulr;
};
extern void arm_context_switch(addr_t *old_sp, addr_t new_sp);

View File

@@ -43,7 +43,11 @@ static inline uint32_t read_cpsr()
}
struct arm_iframe {
uint32_t usp;
uint32_t ulr;
#if ARM_ARCH_LEVEL < 6
uint32_t spsr;
#endif
uint32_t r0;
uint32_t r1;
uint32_t r2;
@@ -51,6 +55,9 @@ struct arm_iframe {
uint32_t r12;
uint32_t lr;
uint32_t pc;
#if ARM_ARCH_LEVEL >= 6
uint32_t spsr;
#endif
};
struct arm_fault_frame {