Adding support for a single stack, GCC check in will follow

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9697 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
AJFISH 2010-01-08 21:12:20 +00:00
parent 05d612fd39
commit 8a4d81e693
5 changed files with 215 additions and 103 deletions

View File

@ -14,6 +14,9 @@
#include "CpuDxe.h" #include "CpuDxe.h"
BOOLEAN gExceptionContext = FALSE;
BOOLEAN mInterruptState = FALSE;
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
CpuFlushCpuDataCache ( CpuFlushCpuDataCache (
@ -25,13 +28,13 @@ CpuFlushCpuDataCache (
{ {
switch (FlushType) { switch (FlushType) {
case EfiCpuFlushTypeWriteBack: case EfiCpuFlushTypeWriteBack:
WriteBackDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length); WriteBackDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length);
break; break;
case EfiCpuFlushTypeInvalidate: case EfiCpuFlushTypeInvalidate:
InvalidateDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length); InvalidateDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length);
break; break;
case EfiCpuFlushTypeWriteBackInvalidate: case EfiCpuFlushTypeWriteBackInvalidate:
WriteBackInvalidateDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length); WriteBackInvalidateDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length);
break; break;
default: default:
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
@ -46,9 +49,11 @@ CpuEnableInterrupt (
IN EFI_CPU_ARCH_PROTOCOL *This IN EFI_CPU_ARCH_PROTOCOL *This
) )
{ {
if (ArmProcessorMode() != ARM_PROCESSOR_MODE_IRQ) { if (!gExceptionContext) {
ArmEnableInterrupts(); ArmEnableInterrupts ();
} }
mInterruptState = TRUE;
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -59,9 +64,11 @@ CpuDisableInterrupt (
IN EFI_CPU_ARCH_PROTOCOL *This IN EFI_CPU_ARCH_PROTOCOL *This
) )
{ {
if (ArmProcessorMode() != ARM_PROCESSOR_MODE_IRQ) { if (!gExceptionContext) {
ArmDisableInterrupts(); ArmDisableInterrupts ();
} }
mInterruptState = FALSE;
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -76,7 +83,7 @@ CpuGetInterruptState (
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
*State = ArmGetInterruptState(); *State = mInterruptState;
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -98,7 +105,7 @@ CpuRegisterInterruptHandler (
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
) )
{ {
return RegisterInterruptHandler(InterruptType, InterruptHandler); return RegisterInterruptHandler (InterruptType, InterruptHandler);
} }
EFI_STATUS EFI_STATUS
@ -148,7 +155,7 @@ CpuDxeInitialize (
IN EFI_SYSTEM_TABLE *SystemTable IN EFI_SYSTEM_TABLE *SystemTable
) )
{ {
InitializeExceptions(&mCpu); InitializeExceptions (&mCpu);
return gBS->InstallMultipleProtocolInterfaces(&mCpuHandle, &gEfiCpuArchProtocolGuid, &mCpu, NULL); return gBS->InstallMultipleProtocolInterfaces (&mCpuHandle, &gEfiCpuArchProtocolGuid, &mCpu, NULL);
} }

View File

@ -1,4 +1,3 @@
#%HEADER%
#/** @file #/** @file
# #
# DXE CPU driver # DXE CPU driver
@ -28,9 +27,19 @@
CpuDxe.h CpuDxe.h
DebugSupport.c DebugSupport.c
Exception.c Exception.c
ExceptionSupport.asm | RVCT
#
# Prior to ARMv6 we have multiple stacks, one per mode
#
# ExceptionSupport.asm | RVCT
ExceptionSupport.S | GCC ExceptionSupport.S | GCC
#
# ARMv6 or later uses a single stack via srs/stm instructions
#
ExceptionSupport.ARMv6.asm | RVCT
# ExceptionSupport.ARMv6.S | GCC
[Packages] [Packages]
ArmPkg/ArmPkg.dec ArmPkg/ArmPkg.dec
EmbeddedPkg/EmbeddedPkg.dec EmbeddedPkg/EmbeddedPkg.dec

View File

@ -15,6 +15,8 @@
#include "CpuDxe.h" #include "CpuDxe.h"
#include <Library/CacheMaintenanceLib.h> #include <Library/CacheMaintenanceLib.h>
extern BOOLEAN gExceptionContext;
VOID VOID
ExceptionHandlersStart ( ExceptionHandlersStart (
VOID VOID
@ -120,7 +122,16 @@ RegisterDebuggerInterruptHandler (
return EFI_SUCCESS; return EFI_SUCCESS;
} }
CHAR8 *gExceptionTypeString[] = {
"Reset",
"Undefined Instruction",
"SWI",
"Prefetch Abort",
"Data Abort",
"Undefined",
"IRQ",
"FIQ"
};
VOID VOID
EFIAPI EFIAPI
@ -131,6 +142,8 @@ CommonCExceptionHandler (
{ {
BOOLEAN Dispatched = FALSE; BOOLEAN Dispatched = FALSE;
gExceptionContext = TRUE;
if (ExceptionType <= MAX_ARM_EXCEPTION) { if (ExceptionType <= MAX_ARM_EXCEPTION) {
if (gDebuggerExceptionHandlers[ExceptionType]) { if (gDebuggerExceptionHandlers[ExceptionType]) {
// //
@ -144,8 +157,13 @@ CommonCExceptionHandler (
gExceptionHandlers[ExceptionType] (ExceptionType, SystemContext); gExceptionHandlers[ExceptionType] (ExceptionType, SystemContext);
Dispatched = TRUE; Dispatched = TRUE;
} }
} else {
DEBUG ((EFI_D_ERROR, "Unknown exception type %d from %08x\n", ExceptionType, SystemContext.SystemContextArm->PC));
ASSERT (FALSE);
} }
gExceptionContext = FALSE;
if (Dispatched) { if (Dispatched) {
// //
// We did work so this was an expected ExceptionType // We did work so this was an expected ExceptionType
@ -163,7 +181,7 @@ CommonCExceptionHandler (
// //
// Code after here is the default exception handler... // Code after here is the default exception handler...
// //
DEBUG ((EFI_D_ERROR, "Exception %d from %08x\n", ExceptionType, SystemContext.SystemContextArm->PC)); DEBUG ((EFI_D_ERROR, "%a Exception from %08x\n", gExceptionTypeString[ExceptionType], SystemContext.SystemContextArm->PC));
ASSERT (FALSE); ASSERT (FALSE);
} }
@ -200,7 +218,7 @@ InitializeExceptions (
} }
// //
// Copy an implementation of the ARM exception vectors to 0x0. // Copy an implementation of the ARM exception vectors to PcdCpuVectorBaseAddress.
// //
Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart; Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;
@ -225,7 +243,7 @@ InitializeExceptions (
*(UINTN *) ((UINT8 *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress) + Offset) = (UINTN)AsmCommonExceptionEntry; *(UINTN *) ((UINT8 *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress) + Offset) = (UINTN)AsmCommonExceptionEntry;
// Flush Caches since we updated executable stuff // Flush Caches since we updated executable stuff
InvalidateInstructionCacheRange((VOID *)PcdGet32(PcdCpuVectorBaseAddress), Length); InvalidateInstructionCacheRange ((VOID *)PcdGet32(PcdCpuVectorBaseAddress), Length);
if (Enabled) { if (Enabled) {
// //

View File

@ -1,6 +1,6 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// //
// Copyright (c) 2008-2009 Apple Inc. All rights reserved. // Copyright (c) 2008-2010 Apple Inc. All rights reserved.
// //
// All rights reserved. This program and the accompanying materials // All rights reserved. This program and the accompanying materials
// are licensed and made available under the terms and conditions of the BSD License // are licensed and made available under the terms and conditions of the BSD License
@ -16,8 +16,10 @@
/* /*
This is the stack constructed by the exception handler This is the stack constructed by the exception handler (low address to high address)
# R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM
Reg Offset
=== ======
R0 0x00 # stmfd SP!,{R0-R12} R0 0x00 # stmfd SP!,{R0-R12}
R1 0x04 R1 0x04
R2 0x08 R2 0x08
@ -43,7 +45,7 @@ This is the stack constructed by the exception handler
LR 0x54 # SVC Link register (we need to restore it) LR 0x54 # SVC Link register (we need to restore it)
LR 0x58 # pushed by srsfd LR 0x58 # pushed by srsfd
CPSR 0x5c # pushed by srsfd CPSR 0x5c
*/ */
@ -57,6 +59,10 @@ This is the stack constructed by the exception handler
PRESERVE8 PRESERVE8
AREA DxeExceptionHandlers, CODE, READONLY AREA DxeExceptionHandlers, CODE, READONLY
//
// This code gets copied to the ARM vector table
// ExceptionHandlersStart - ExceptionHandlersEnd gets copied
//
ExceptionHandlersStart ExceptionHandlersStart
Reset Reset
@ -85,101 +91,109 @@ Fiq
ResetEntry ResetEntry
srsfd #0x13! ; Store return state on SVC stack srsfd #0x13! ; Store return state on SVC stack
cpsid if,#0x13 ; Switch to SVC for common stack ; We are already in SVC mode
stmfd SP!,{LR} ; Store the link register for the current mode stmfd SP!,{LR} ; Store the link register for the current mode
sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} ; Store the register state stmfd SP!,{R0-R12} ; Store the register state
mov R0,#0 mov R0,#0 ; ExceptionType
ldr R1,CommonExceptionEntry ldr R1,CommonExceptionEntry
bx R1 bx R1
UndefinedInstructionEntry UndefinedInstructionEntry
srsfd #0x13! ; Store return state on SVC stack srsfd #0x13! ; Store return state on SVC stack
cpsid i,#0x13 ; Switch to SVC for common stack cps #0x13 ; Switch to SVC for common stack
stmfd SP!,{LR} ; Store the link register for the current mode stmfd SP!,{LR} ; Store the link register for the current mode
sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} ; Store the register state stmfd SP!,{R0-R12} ; Store the register state
mov R0,#1 mov R0,#1 ; ExceptionType
ldr R1,CommonExceptionEntry ldr R1,CommonExceptionEntry;
bx R1 bx R1
SoftwareInterruptEntry SoftwareInterruptEntry
srsfd #0x13! ; Store return state on SVC stack srsfd #0x13! ; Store return state on SVC stack
cpsid i,#0x13 ; Switch to SVC for common stack ; We are already in SVC mode
stmfd SP!,{LR} ; Store the link register for the current mode stmfd SP!,{LR} ; Store the link register for the current mode
sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} ; Store the register state stmfd SP!,{R0-R12} ; Store the register state
mov R0,#2 mov R0,#2 ; ExceptionType
ldr R1,CommonExceptionEntry ldr R1,CommonExceptionEntry
bx R1 bx R1
PrefetchAbortEntry PrefetchAbortEntry
sub LR,LR,#4 sub LR,LR,#4
srsfd #0x13! ; Store return state on SVC stack srsfd #0x13! ; Store return state on SVC stack
cpsid i,#0x13 ; Switch to SVC for common stack cps #0x13 ; Switch to SVC for common stack
stmfd SP!,{LR} ; Store the link register for the current mode stmfd SP!,{LR} ; Store the link register for the current mode
sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} ; Store the register state stmfd SP!,{R0-R12} ; Store the register state
mov R0,#3 mov R0,#3 ; ExceptionType
ldr R1,CommonExceptionEntry ldr R1,CommonExceptionEntry
bx R1 bx R1
DataAbortEntry DataAbortEntry
sub LR,LR,#8 sub LR,LR,#8
srsfd #0x13! ; Store return state on SVC stack srsfd #0x13! ; Store return state on SVC stack
cpsid i,#0x13 ; Switch to SVC for common stack cps #0x13 ; Switch to SVC for common stack
stmfd SP!,{LR} ; Store the link register for the current mode stmfd SP!,{LR} ; Store the link register for the current mode
sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} ; Store the register state stmfd SP!,{R0-R12} ; Store the register state
mov R0,#4 mov R0,#4 ; ExceptionType
ldr R1,CommonExceptionEntry ldr R1,CommonExceptionEntry
bx R1 bx R1
ReservedExceptionEntry ReservedExceptionEntry
srsfd #0x13! ; Store return state on SVC stack srsfd #0x13! ; Store return state on SVC stack
cpsid if,#0x13 ; Switch to SVC for common stack cps #0x13 ; Switch to SVC for common stack
stmfd SP!,{LR} ; Store the link register for the current mode stmfd SP!,{LR} ; Store the link register for the current mode
sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} ; Store the register state stmfd SP!,{R0-R12} ; Store the register state
mov R0,#5 mov R0,#5 ; ExceptionType
ldr R1,CommonExceptionEntry ldr R1,CommonExceptionEntry
bx R1 bx R1
IrqEntry IrqEntry
sub LR,LR,#4 sub LR,LR,#4
srsfd #0x13! ; Store return state on SVC stack srsfd #0x13! ; Store return state on SVC stack
cpsid i,#0x13 ; Switch to SVC for common stack cps #0x13 ; Switch to SVC for common stack
stmfd SP!,{LR} ; Store the link register for the current mode stmfd SP!,{LR} ; Store the link register for the current mode
sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} ; Store the register state stmfd SP!,{R0-R12} ; Store the register state
mov R0,#6 mov R0,#6 ; ExceptionType
ldr R1,CommonExceptionEntry ldr R1,CommonExceptionEntry
bx R1 bx R1
FiqEntry FiqEntry
sub LR,LR,#4 sub LR,LR,#4
srsfd #0x13! ; Store return state on SVC stack srsfd #0x13! ; Store return state on SVC stack
cpsid if,#0x13 ; Switch to SVC for common stack cps #0x13 ; Switch to SVC for common stack
stmfd SP!,{LR} ; Store the link register for the current mode stmfd SP!,{LR} ; Store the link register for the current mode
sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} ; Store the register state stmfd SP!,{R0-R12} ; Store the register state
; Since we have already switch to SVC R8_fiq - R12_fiq
mov R0,#7 ; never get used or saved
mov R0,#7 ; ExceptionType
ldr R1,CommonExceptionEntry ldr R1,CommonExceptionEntry
bx R1 bx R1
//
// This gets patched by the C code that patches in the vector table
//
CommonExceptionEntry CommonExceptionEntry
dcd 0x12345678 dcd 0x12345678
ExceptionHandlersEnd ExceptionHandlersEnd
//
// This code runs from CpuDxe driver loaded address. It is patched into
// CommonExceptionEntry.
//
AsmCommonExceptionEntry AsmCommonExceptionEntry
mrc p15, 0, R1, c6, c0, 2 ; Read IFAR mrc p15, 0, R1, c6, c0, 2 ; Read IFAR
str R1, [SP, #0x50] ; Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR str R1, [SP, #0x50] ; Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR
@ -196,25 +210,50 @@ AsmCommonExceptionEntry
ldr R1, [SP, #0x5c] ; srsfd saved pre-exception CPSR on the stack ldr R1, [SP, #0x5c] ; srsfd saved pre-exception CPSR on the stack
str R1, [SP, #0x40] ; Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR str R1, [SP, #0x40] ; Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR
add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
and R1, R1, #0x1f ; Check CPSR to see if User or System Mode
cmp R1, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1df))
cmpne R1, #0x10 ;
stmeqed R2, {lr}^ ; save unbanked lr
; else
stmneed R2, {lr} ; save SVC lr
ldr R1, [SP, #0x58] ; PC is the LR pushed by srsfd ldr R1, [SP, #0x58] ; PC is the LR pushed by srsfd
str R1, [SP, #0x3c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.PC str R1, [SP, #0x3c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.PC
str R1, [SP, #0x38] ; Store it in EFI_SYSTEM_CONTEXT_ARM.LR
sub R1, SP, #0x60 ; We pused 0x60 bytes on the stack sub R1, SP, #0x60 ; We pused 0x60 bytes on the stack
str R1, [SP, #0x34] ; Store it in EFI_SYSTEM_CONTEXT_ARM.SP str R1, [SP, #0x34] ; Store it in EFI_SYSTEM_CONTEXT_ARM.SP
; R0 is exception type ; R0 is ExceptionType
mov R1,SP ; Prepare System Context pointer as an argument for the exception handler mov R1,SP ; R1 is SystemContext
/*
VOID
EFIAPI
CommonCExceptionHandler (
IN EFI_EXCEPTION_TYPE ExceptionType, R0
IN OUT EFI_SYSTEM_CONTEXT SystemContext R1
)
*/
blx CommonCExceptionHandler ; Call exception handler blx CommonCExceptionHandler ; Call exception handler
ldr R2,[SP,#0x40] ; EFI_SYSTEM_CONTEXT_ARM.CPSR ldr R1,[SP,#0x3c] ; EFI_SYSTEM_CONTEXT_ARM.PC
str R2,[SP,#0x5c] ; Store it back to srsfd stack slot so it can be restored str R1,[SP,#0x58] ; Store it back to srsfd stack slot so it can be restored
ldr R2,[SP,#0x3c] ; EFI_SYSTEM_CONTEXT_ARM.PC ldr R1,[SP,#0x40] ; EFI_SYSTEM_CONTEXT_ARM.CPSR
str R2,[SP,#0x58] ; Store it back to srsfd stack slot so it can be restored str R1,[SP,#0x5c] ; Store it back to srsfd stack slot so it can be restored
add R3, SP, #0x54 ; Make R3 point to SVC LR saved on entry
add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
and R1, R1, #0x1f ; Check to see if User or System Mode
cmp R1, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1df))
cmpne R1, #0x10 ;
ldmeqed R2, {lr}^ ; restore unbanked lr
; else
ldmneed R3, {lr} ; restore SVC lr, via ldmfd SP!, {LR}
ldmfd SP!,{R0-R12} ; Restore general purpose registers ldmfd SP!,{R0-R12} ; Restore general purpose registers
; Exception handler can not change SP or LR as we would blow chunks ; Exception handler can not change SP
add SP,SP,#0x20 ; Clear out the remaining stack space add SP,SP,#0x20 ; Clear out the remaining stack space
ldmfd SP!,{LR} ; restore the link register for this context ldmfd SP!,{LR} ; restore the link register for this context

View File

@ -1,6 +1,6 @@
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# #
# Copyright (c) 2008-2009 Apple Inc. All rights reserved. # Copyright (c) 2008-2010 Apple Inc. All rights reserved.
# #
# All rights reserved. This program and the accompanying materials # All rights reserved. This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License # are licensed and made available under the terms and conditions of the BSD License
@ -48,54 +48,92 @@ ASM_PFX(Fiq):
b ASM_PFX(FiqEntry) b ASM_PFX(FiqEntry)
ASM_PFX(ResetEntry): ASM_PFX(ResetEntry):
stmfd sp!,{r0-r1} srsdb #0x13! @ Store return state on SVC stack
mov r0,#0 stmfd SP!,{LR} @ Store the link register for the current mode
ldr r1,ASM_PFX(CommonExceptionEntry) sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
bx r1 stmfd SP!,{R0-R12} @ Store the register state
mov R0,#0
ldr R1,ASM_PFX(CommonExceptionEntry)
bx R1
ASM_PFX(UndefinedInstructionEntry): ASM_PFX(UndefinedInstructionEntry):
stmfd sp!,{r0-r1} srsdb #0x13! @ Store return state on SVC stack
cps #0x13 @ Switch to SVC for common stack
stmfd SP!,{LR} @ Store the link register for the current mode
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} @ Store the register state
mov r0,#1 mov r0,#1
ldr r1,ASM_PFX(CommonExceptionEntry) ldr r1,ASM_PFX(CommonExceptionEntry)
bx r1 bx r1
ASM_PFX(SoftwareInterruptEntry): ASM_PFX(SoftwareInterruptEntry):
stmfd sp!,{r0-r1} srsdb #0x13! @ Store return state on SVC stack
stmfd SP!,{LR} @ Store the link register for the current mode
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} @ Store the register state
mov r0,#2 mov r0,#2
ldr r1,ASM_PFX(CommonExceptionEntry) ldr r1,ASM_PFX(CommonExceptionEntry)
bx r1 bx r1
ASM_PFX(PrefetchAbortEntry): ASM_PFX(PrefetchAbortEntry):
stmfd sp!,{r0-r1} sub LR,LR,#4
srsdb #0x13! @ Store return state on SVC stack
cps #0x13 @ Switch to SVC for common stack
stmfd SP!,{LR} @ Store the link register for the current mode
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} @ Store the register state
mov r0,#3 mov r0,#3
sub lr,lr,#4
ldr r1,ASM_PFX(CommonExceptionEntry) ldr r1,ASM_PFX(CommonExceptionEntry)
bx r1 bx r1
ASM_PFX(DataAbortEntry): ASM_PFX(DataAbortEntry):
stmfd sp!,{r0-r1} sub LR,LR,#8
srsdb #0x13! @ Store return state on SVC stack
cps #0x13 @ Switch to SVC for common stack
stmfd SP!,{LR} @ Store the link register for the current mode
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} @ Store the register state
mov r0,#4 mov r0,#4
sub lr,lr,#8
ldr r1,ASM_PFX(CommonExceptionEntry) ldr r1,ASM_PFX(CommonExceptionEntry)
bx r1 bx r1
ASM_PFX(ReservedExceptionEntry): ASM_PFX(ReservedExceptionEntry):
stmfd sp!,{r0-r1} srsdb #0x13! @ Store return state on SVC stack
cps #0x13 @ Switch to SVC for common stack
stmfd SP!,{LR} @ Store the link register for the current mode
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} @ Store the register state
mov r0,#5 mov r0,#5
ldr r1,ASM_PFX(CommonExceptionEntry) ldr r1,ASM_PFX(CommonExceptionEntry)
bx r1 bx r1
ASM_PFX(IrqEntry): ASM_PFX(IrqEntry):
stmfd sp!,{r0-r1} sub LR,LR,#4
srsdb #0x13! @ Store return state on SVC stack
cps #0x13 @ Switch to SVC for common stack
stmfd SP!,{LR} @ Store the link register for the current mode
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} @ Store the register state
mov r0,#6 mov r0,#6
sub lr,lr,#4
ldr r1,ASM_PFX(CommonExceptionEntry) ldr r1,ASM_PFX(CommonExceptionEntry)
bx r1 bx r1
ASM_PFX(FiqEntry): ASM_PFX(FiqEntry):
stmfd sp!,{r0-r1} sub LR,LR,#4
srsdb #0x13! @ Store return state on SVC stack
cps #0x13 @ Switch to SVC for common stack
stmfd SP!,{LR} @ Store the link register for the current mode
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} @ Store the register state
mov r0,#7 mov r0,#7
sub lr,lr,#4
ldr r1,ASM_PFX(CommonExceptionEntry) ldr r1,ASM_PFX(CommonExceptionEntry)
bx r1 bx r1
@ -108,45 +146,46 @@ ASM_PFX(CommonExceptionEntry):
ASM_PFX(ExceptionHandlersEnd): ASM_PFX(ExceptionHandlersEnd):
ASM_PFX(AsmCommonExceptionEntry): ASM_PFX(AsmCommonExceptionEntry):
mrc p15, 0, r1, c6, c0, 2 @ Read IFAR mrc p15, 0, R1, c6, c0, 2 @ Read IFAR
stmfd sp!,{r1} @ Store the IFAR str R1, [SP, #0x50] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR
mrc p15, 0, r1, c5, c0, 1 @ Read IFSR mrc p15, 0, R1, c5, c0, 1 @ Read IFSR
stmfd sp!,{r1} @ Store the IFSR str R1, [SP, #0x4c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR
mrc p15, 0, r1, c6, c0, 0 @ Read DFAR mrc p15, 0, R1, c6, c0, 0 @ Read DFAR
stmfd sp!,{r1} @ Store the DFAR str R1, [SP, #0x48] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR
mrc p15, 0, r1, c5, c0, 0 @ Read DFSR mrc p15, 0, R1, c5, c0, 0 @ Read DFSR
stmfd sp!,{r1} @ Store the DFSR str R1, [SP, #0x44] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR
mrs r1,spsr @ Read SPSR (which is the pre-exception CPSR) ldr R1, [SP, #0x5c] @ srsdb saved pre-exception CPSR on the stack
stmfd sp!,{r1} @ Store the SPSR str R1, [SP, #0x40] @ Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR
and r1, r1, #0x1f @ Check to see if User or System Mode
cmp r1, #0x1f
cmpne r1, #0x10
add R2, SP, #0x38 @ Store it in EFI_SYSTEM_CONTEXT_ARM.LR
ldmneed r2, {lr}^ @ User or System mode, use unbanked register
ldmneed r2, {lr} @ All other modes used banked register
stmfd sp!,{lr} @ Store the link register (which is the pre-exception PC) ldr R1, [SP, #0x58] @ PC is the LR pushed by srsdb
stmfd sp,{sp,lr}^ @ Store user/system mode stack pointer and link register str R1, [SP, #0x3c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC
nop @ Required by ARM architecture
sub sp,sp,#0x08 @ Adjust stack pointer
stmfd sp!,{r2-r12} @ Store general purpose registers
ldr r3,[sp,#0x50] @ Read saved R1 from the stack (it was saved by the exception entry routine) sub R1, SP, #0x60 @ We pused 0x60 bytes on the stack
ldr r2,[sp,#0x4C] @ Read saved R0 from the stack (it was saved by the exception entry routine) str R1, [SP, #0x34] @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP
stmfd sp!,{r2-r3} @ Store general purpose registers R0 and R1
mov r1,sp @ Prepare System Context pointer as an argument for the exception handler @ R0 is exception type
mov R1,SP @ Prepare System Context pointer as an argument for the exception handler
blx ASM_PFX(CommonCExceptionHandler) @ Call exception handler
sub sp,sp,#4 @ Adjust SP to preserve 8-byte alignment ldr R2,[SP,#0x40] @ EFI_SYSTEM_CONTEXT_ARM.CPSR
bl ASM_PFX(CommonCExceptionHandler) @ Call exception handler str R2,[SP,#0x5c] @ Store it back to srsdb stack slot so it can be restored
add sp,sp,#4 @ Adjust SP back to where we were
ldr r2,[sp,#0x40] @ Load CPSR from context, in case it has changed ldr R2,[SP,#0x3c] @ EFI_SYSTEM_CONTEXT_ARM.PC
msr SPSR_cxsf,r2 @ Store it back to the SPSR to be restored when exiting this handler str R2,[SP,#0x58] @ Store it back to srsdb stack slot so it can be restored
ldmfd sp!,{r0-r12} @ Restore general purpose registers ldmfd SP!,{R0-R12} @ Restore general purpose registers
ldmia sp,{sp,lr}^ @ Restore user/system mode stack pointer and link register @ Exception handler can not change SP or LR as we would blow chunks
nop @ Required by ARM architecture
add sp,sp,#0x08 @ Adjust stack pointer
ldmfd sp!,{lr} @ Restore the link register (which is the pre-exception PC)
add sp,sp,#0x1C @ Clear out the remaining stack space
movs pc,lr @ Return from exception
add SP,SP,#0x20 @ Clear out the remaining stack space
ldmfd SP!,{LR} @ restore the link register for this context
rfefd SP! @ return from exception via srsdb stack slot