Blame | Last modification | View Log | Download | RSS feed
#
# Copyright (c) 2009 Vineeth Pillai
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
.text
.global irq_exception_entry
.global fiq_exception_entry
.global data_abort_exception_entry
.global prefetch_abort_exception_entry
.global undef_instr_exception_entry
.global swi_exception_entry
.global reset_exception_entry
# Switches to kernel stack and saves all registers there.
#
# The stack frame created by the function looks like:
#
# |_________________|
# | |
# | SPSR |
# | |
# |_________________|
# | Stack Pointer |
# | of |
# | Previous Mode |
# |_________________|
# | Return address |
# | of |
# | Previous Mode |
# |_________________|
# | R0 - R12 |
# | of |
# | Previous Mode |
# |_________________|
# | Return address |
# | from |
# |Exception Handler|
# |_________________|
# | |
#
#
.macro SAVE_REGS_TO_STACK
stmfd r13!, {r0-r3}
mov r3, sp
add sp, sp, #16
mrs r1, cpsr
bic r1, r1, #0x1f
mrs r2, spsr
and r0, r2, #0x1f
cmp r0, #0x10
bne 1f
# prev mode was usermode
mov r0, lr
# Switch to supervisor mode
orr r1, r1, #0x13
msr cpsr_c, r1
# Load sp with [supervisor_sp]
ldr r13, =supervisor_sp
ldr r13, [r13]
# Populate the stack frame
msr spsr, r2
mov lr, r0
stmfd r13!, {lr}
stmfd r13!, {r4-r12}
ldmfd r3!, {r4-r7}
stmfd r13!, {r4-r7}
stmfd r13!, {r13, lr}^
stmfd r13!, {r2}
b 2f
# mode was not usermode
1:
# Switch to previous mode which is undoubtedly the supervisor mode
orr r1, r1, r0
mov r0, lr
msr cpsr_c, r1
# Populate the stack frame
mov r1, sp
stmfd r13!, {r0}
stmfd r13!, {r4-r12}
# Store r0-r3 in r4-r7 and then push it on to stack
ldmfd r3!, {r4-r7}
stmfd r13!, {r4-r7}
# Push return address and stack pointer on to stack
stmfd r13!, {lr}
stmfd r13!, {r1}
mov lr, r0
msr spsr, r2
stmfd r13!, {r2}
2:
.endm
.macro LOAD_REGS_FROM_STACK
ldmfd r13!, {r0}
msr spsr, r0
and r0, r0, #0x1f
cmp r0, #0x10
bne 1f
# return to user mode
ldmfd r13!, {r13, lr}^
b 2f
# return to non-user mode
1:
ldmfd r13!, {r1, lr}
2:
ldmfd r13!, {r0-r12, pc}^
.endm
reset_exception_entry:
SAVE_REGS_TO_STACK
mov r0, #0
mov r1, r13
bl exc_dispatch
LOAD_REGS_FROM_STACK
irq_exception_entry:
sub lr, lr, #4
SAVE_REGS_TO_STACK
mov r0, #5
mov r1, r13
bl exc_dispatch
LOAD_REGS_FROM_STACK
fiq_exception_entry:
sub lr, lr, #4
SAVE_REGS_TO_STACK
mov r0, #6
mov r1, r13
bl exc_dispatch
LOAD_REGS_FROM_STACK
undef_instr_exception_entry:
SAVE_REGS_TO_STACK
mov r0, #1
mov r1, r13
bl exc_dispatch
LOAD_REGS_FROM_STACK
prefetch_abort_exception_entry:
sub lr, lr, #4
SAVE_REGS_TO_STACK
mov r0, #3
mov r1, r13
bl exc_dispatch
LOAD_REGS_FROM_STACK
data_abort_exception_entry:
sub lr, lr, #8
SAVE_REGS_TO_STACK
mov r0, #4
mov r1, r13
bl exc_dispatch
LOAD_REGS_FROM_STACK
swi_exception_entry:
ldr r13, =exc_stack
SAVE_REGS_TO_STACK
mov r0, #2
mov r1, r13
bl exc_dispatch
LOAD_REGS_FROM_STACK