[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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user