123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445 |
- /*++
- Copyright (c) 2012 Minoca Corp. All Rights Reserved
- Module Name:
- trap.S
- Abstract:
- This module implements interrupt and exception trap management, such as
- saving and restoring registers.
- Author:
- Evan Green 11-Aug-2012
- Environment:
- Kernel mode
- --*/
- ##
- ## ------------------------------------------------------------------- Includes
- ##
- #include <minoca/kernel/arm.inc>
- ##
- ## ---------------------------------------------------------------- Definitions
- ##
- ##
- ## ---------------------------------------------------------------------- Code
- ##
- ASSEMBLY_FILE_HEADER
- ##
- ## VOID
- ## ArpInitializeExceptionStacks (
- ## PVOID ExceptionStacksBase,
- ## ULONG ExceptionStackSize
- ## )
- ##
- /*++
- Routine Description:
- This routine initializes the stack pointer for all privileged ARM modes. It
- switches into each mode and initializes the banked r13. This function
- should be called with interrupts disabled and returns with interrupts
- disabled.
- Arguments:
- ExceptionStacksBase - Supplies a pointer to the lowest address that should
- be used for exception stacks. Each stack takes up 16 bytes and there are
- 4 modes, so at least 64 bytes are needed.
- ExceptionStackSize - Supplies the size of each exception stack.
- Return Value:
- None.
- --*/
- FUNCTION ArpInitializeExceptionStacks
- ##
- ## Load R1 with an individual stack size.
- ##
- add %r0, %r0, %r1
- ##
- ## Disable interrupts and switch into IRQ mode. Note that this also
- ## clobbers the flags register.
- ##
- mov %r2, #(PSR_FLAG_IRQ | ARM_MODE_IRQ)
- msr CPSR_cxsf, %r2
- mov %sp, %r0
- add %r0, %r0, %r1
- ##
- ## Initialize the FIQ stack.
- ##
- mov %r2, #(PSR_FLAG_IRQ | ARM_MODE_FIQ)
- msr CPSR_cxsf, %r2
- mov %sp, %r0
- add %r0, %r0, %r1
- ##
- ## Initialize the undefined instruction stack.
- ##
- mov %r2, #(PSR_FLAG_IRQ | ARM_MODE_UNDEF)
- msr CPSR_cxsf, %r2
- mov %sp, %r0
- add %r0, %r0, %r1
- ##
- ## Initialize the data fetch abort stack.
- ##
- mov %r2, #(PSR_FLAG_IRQ | ARM_MODE_ABORT)
- msr CPSR_cxsf, %r2
- mov %sp, %r0
- ##
- ## Switch back to SVC mode and return.
- ##
- mov %r2, #(PSR_FLAG_IRQ | ARM_MODE_SVC)
- msr CPSR_cxsf, %r2
- bx %lr
- END_FUNCTION ArpInitializeExceptionStacks
- ##
- ## VOID
- ## ArpUndefinedInstructionEntry (
- ## VOID
- ## )
- ##
- /*++
- Routine Description:
- This routine directly handles an exception generated by an undefined
- instruction. It uses a largely separate code path from normal exceptions
- to avoid recursively breaking into the debugger.
- Arguments:
- None.
- Return Value:
- None.
- --*/
- FUNCTION ArpUndefinedInstructionEntry
- ##
- ## Save state and create a trap frame.
- ##
- ARM_ENTER_INTERRUPT
- ##
- ## Call the main dispatch routine routine with a pointer to the trap frame
- ## as the only parameter. Align the stack down even though it shouldn't be
- ## strictly necessary in case something bad happened.
- ##
- mov %r0, %sp
- mov %r4, %sp
- and %r1, %r4, #0xFFFFFFF0 @ Align stack down for fear of badness.
- mov %sp, %r1
- bl KeDispatchUndefinedInstructionException
- mov %sp, %r4
- ##
- ## Restore state and return.
- ##
- ARM_EXIT_INTERRUPT
- END_FUNCTION ArpUndefinedInstructionEntry
- ##
- ## VOID
- ## ArpSoftwareInterruptEntry (
- ## VOID
- ## )
- ##
- /*++
- Routine Description:
- This routine directly handles an exception generated by a software
- interrupt (a system call).
- Arguments:
- None.
- Return Value:
- None.
- --*/
- FUNCTION ArpSoftwareInterruptEntry
- srsdb %sp!, #ARM_MODE_SVC @ Push lr and spsr.
- mov %lr, #0 @ Zero SVC link register.
- stmdb %sp!, {%r1-%r12, %lr} @ Push general registers.
- mrs %r2, cpsr @ Get the "exception" CPSR.
- stmdb %sp!, {%r0, %r2} @ Push exception CPSR and R0.
- mov %r4, %sp @ Get stack.
- sub %sp, #8 @ Account for pushes.
- cps #ARM_MODE_SYSTEM @ Switch to system mode.
- str %lr, [%r4, #-4] @ Save usermode SP.
- str %sp, [%r4, #-8] @ Save usermode LR.
- cpsie i, #ARM_MODE_SVC @ Enable interrupts, svc mode.
- sub %sp, #4 @ Allocate room for sp.
- str %sp, [%sp] @ Save SP.
- ##
- ## The system call routine takes three parameters: the system call number,
- ## system call parameter, and a pointer to the trap frame. User-mode already
- ## set up the first two parameters in R0 and R1, and they were preserved
- ## throughout the context save process here. So all that's left is to put a
- ## pointer to the trap frame in R2.
- ##
- mov %r2, %sp
- bl KeSystemCallHandler
- ##
- ## Restore state and return.
- ##
- ARM_EXIT_INTERRUPT
- END_FUNCTION ArpSoftwareInterruptEntry
- ##
- ## VOID
- ## ArpPrefetchAbortEntry (
- ## VOID
- ## )
- ##
- /*++
- Routine Description:
- This routine directly handles an exception generated by a prefetch abort
- (page fault).
- Arguments:
- None.
- Return Value:
- None.
- --*/
- FUNCTION ArpPrefetchAbortEntry
- ##
- ## In ARM mode, prefect aborts save the PC-4 in LR. For Thumb mode, data
- ## aborts save the PC in LR. Thus, the PC is always 4 bytes head of the
- ## faulting address.
- ##
- sub %lr, %lr, #4 @ Prefetches go too far by 4.
- ##
- ## Save state and create a trap frame.
- ##
- ARM_ENTER_INTERRUPT
- ##
- ## Call the main dispatch routine routine with a pointer to the trap frame
- ## and 1 to indicate a prefetch abort.
- ##
- mov %r0, %sp
- mov %r1, #1
- blx KeDispatchException
- ##
- ## Restore state and return.
- ##
- ARM_EXIT_INTERRUPT
- END_FUNCTION ArpPrefetchAbortEntry
- ##
- ## VOID
- ## ArpDataAbortEntry (
- ## VOID
- ## )
- ##
- /*++
- Routine Description:
- This routine directly handles an exception generated by a data abort (page
- fault).
- Arguments:
- None.
- Return Value:
- None.
- --*/
- FUNCTION ArpDataAbortEntry
- ##
- ## In ARM mode, data aborts save the PC in LR. For Thumb mode, data aborts
- ## save the PC+4 in LR. Thus, the PC is always 8 bytes head of the faulting
- ## address.
- ##
- sub %lr, %lr, #8
- ##
- ## Save state and create a trap frame.
- ##
- ARM_ENTER_INTERRUPT
- ##
- ## Call the main dispatch routine routine with a pointer to the trap frame
- ## and 0 to indicate a prefetch abort.
- ##
- mov %r0, %sp
- mov %r1, #0
- blx KeDispatchException
- ##
- ## Restore state and return.
- ##
- ARM_EXIT_INTERRUPT
- END_FUNCTION ArpDataAbortEntry
- ##
- ## VOID
- ## ArpIrqEntry (
- ## VOID
- ## )
- ##
- /*++
- Routine Description:
- This routine directly handles an exception generated by an external
- interrupt on the IRQ pin.
- Arguments:
- None.
- Return Value:
- None.
- --*/
- FUNCTION ArpIrqEntry
- b ArpCommonInterruptEntry
- END_FUNCTION ArpIrqEntry
- ##
- ## VOID
- ## ArpFiqEntry (
- ## VOID
- ## )
- ##
- /*++
- Routine Description:
- This routine directly handles an exception generated by an external
- interrupt on the FIQ pin.
- Arguments:
- None.
- Return Value:
- None.
- --*/
- FUNCTION ArpFiqEntry
- b ArpCommonInterruptEntry
- END_FUNCTION ArpFiqEntry
- ##
- ## --------------------------------------------------------- Internal Functions
- ##
- ##
- ## This code is entered as the result of any interrupt or exception. Its job is
- ## to transition back to the SVC stack and then call the real interrupt
- ## dispatch routine.
- ##
- ArpCommonInterruptEntry:
- ##
- ## Save state and create a trap frame.
- ##
- ARM_ENTER_INTERRUPT
- ##
- ## Call the main dispatch routine routine with a pointer to the trap frame
- ## as the only parameter. Align the stack down in case the exception
- ## interrupted something unaligned.
- ##
- mov %r0, %sp
- mov %r4, %sp
- and %r5, %r4, #0xFFFFFFF0
- mov %sp, %r5
- bl KeDispatchException
- mov %sp, %r4
- ##
- ## Restore state and return.
- ##
- ARM_EXIT_INTERRUPT
|