316 lines
7.3 KiB
ArmAsm
316 lines
7.3 KiB
ArmAsm
/*
|
|
* Copyright (C) 2011-2012, 2014 Apple Computer, Inc. All rights reserved.
|
|
*
|
|
* This document is the property of Apple Computer, Inc.
|
|
* It is considered confidential and proprietary.
|
|
*
|
|
* This document may not be reproduced or transmitted in any form,
|
|
* in whole or in part, without the express written permission of
|
|
* Apple Computer, Inc.
|
|
*/
|
|
|
|
#if !WITH_EL3
|
|
#error "This file should only be built for platforms WITH_EL3"
|
|
#endif
|
|
|
|
////////////////////////////////////////////////////////////
|
|
// This is what exception frame looks like:
|
|
//
|
|
// struct arm_exception_frame64 {
|
|
// uint64_t regs[29]; // x0-x28
|
|
// uint64_t fp;
|
|
// uint64_t lr;
|
|
// uint64_t sp;
|
|
// uint32_t spsr;
|
|
// uint32_t reserved0;
|
|
// uint64_t pc;
|
|
// uint64_t far;
|
|
// uint32_t esr;
|
|
// uint32_t reserved1;
|
|
// uint64_t reserved2; // stp requires multiple of 16 in imm field
|
|
// uint64_t reserved3; // stp requires multiple of 16 in imm field
|
|
// union {
|
|
// uint128_t q;
|
|
// uint64_t d;
|
|
// uint32_t s;
|
|
// } vregs[32]; // v0-v31
|
|
// uint32_t fpsr;
|
|
// uint32_t reserved4;
|
|
// uint32_t fpcr;
|
|
// uint32_t reserved5;
|
|
// };
|
|
////////////////////////////////////////////////////////////
|
|
|
|
.macro EL3_SP0_VECTOR
|
|
msr SPSel, #0 // Switch to SP0
|
|
sub sp, sp, #832 // Create exception frame
|
|
stp x0, x1, [sp, #0] // Save x0, x1 to exception frame
|
|
add x0, sp, #832 // Calculate the original stack pointer
|
|
str x0, [sp, #248] // Save stack pointer to exception frame
|
|
stp fp, lr, [sp, #232] // Save fp and lr to exception frame
|
|
mrs lr, ELR_EL3 // Get exception link reg so _dispatch64 can make a frame
|
|
mov x0, sp // Copy saved state pointer to x0
|
|
.endmacro
|
|
|
|
.macro FASTSIM_DEBUG_HINT
|
|
hint 0x45 // make fastsim drop to debugger (nop on hardware)
|
|
.endmacro
|
|
|
|
.text
|
|
.align 12
|
|
.globl _exception_vector_base
|
|
_exception_vector_base:
|
|
L__el3_sp0_synchronous_vector:
|
|
EL3_SP0_VECTOR
|
|
mrs x1, ESR_EL3 // Load exception syndrome
|
|
str x1, [x0, #280]
|
|
mrs x1, FAR_EL3 // Load fault address
|
|
str x1, [x0, #272]
|
|
adrp x1, _arm_synchronous_exception@page
|
|
add x1, x1, _arm_synchronous_exception@pageoff
|
|
b __dispatch64
|
|
|
|
.text
|
|
.align 7
|
|
L__el3_sp0_irq_vector:
|
|
EL3_SP0_VECTOR
|
|
adrp x1, _interrupt_stack_top@page
|
|
add x1, x1, _interrupt_stack_top@pageoff
|
|
ldr x1, [x1]
|
|
mov sp, x1
|
|
adrp x1, _arm_irq@page
|
|
add x1, x1, _arm_irq@pageoff
|
|
b __dispatch64
|
|
|
|
.text
|
|
.align 7
|
|
L__el3_sp0_fiq_vector:
|
|
EL3_SP0_VECTOR
|
|
adrp x1, _interrupt_stack_top@page
|
|
add x1, x1, _interrupt_stack_top@pageoff
|
|
ldr x1, [x1]
|
|
mov sp, x1
|
|
adrp x1, _arm_fiq@page
|
|
add x1, x1, _arm_fiq@pageoff
|
|
b __dispatch64
|
|
|
|
.text
|
|
.align 7
|
|
L__el3_sp0_serror_vector:
|
|
EL3_SP0_VECTOR
|
|
mrs x1, ESR_EL3 // Load exception syndrome
|
|
str x1, [x0, #280]
|
|
mrs x1, FAR_EL3 // Load fault address
|
|
str x1, [x0, #272]
|
|
adrp x1, _arm_serror_exception@page
|
|
add x1, x1, _arm_serror_exception@pageoff
|
|
b __dispatch64
|
|
|
|
.text
|
|
.align 7
|
|
L__el3_sp3_synchronous_vector:
|
|
FASTSIM_DEBUG_HINT
|
|
b .
|
|
|
|
.text
|
|
.align 7
|
|
L__el3_sp3_irq_vector:
|
|
FASTSIM_DEBUG_HINT
|
|
b .
|
|
|
|
.text
|
|
.align 7
|
|
L__el3_sp3_fiq_vector:
|
|
FASTSIM_DEBUG_HINT
|
|
b .
|
|
|
|
.text
|
|
.align 7
|
|
L__el3_sp3_serror_vector:
|
|
FASTSIM_DEBUG_HINT
|
|
b .
|
|
|
|
.text
|
|
.align 7
|
|
L__elx_64_synchronous_vector:
|
|
// Monitor (EL3) call.
|
|
// Check "smc #0x5ec3" was executed and no other reason code.
|
|
movz x1, #0x5ec3
|
|
movk x1, #0x5e00, lsl #16
|
|
mrs x2, ESR_EL3
|
|
cmp x1, x2
|
|
b.eq 1f
|
|
FASTSIM_DEBUG_HINT
|
|
b .
|
|
1: // Got here from an "smc". Branch to x0.
|
|
br x0
|
|
|
|
.text
|
|
.align 7
|
|
L__elx_64_irq_vector:
|
|
FASTSIM_DEBUG_HINT
|
|
b .
|
|
|
|
.text
|
|
.align 7
|
|
L__elx_64_fiq_vector:
|
|
FASTSIM_DEBUG_HINT
|
|
b .
|
|
|
|
.text
|
|
.align 7
|
|
L__elx_64_serror_vector:
|
|
FASTSIM_DEBUG_HINT
|
|
b .
|
|
|
|
.text
|
|
.align 7
|
|
L__elx_32_synchronous_vector:
|
|
FASTSIM_DEBUG_HINT
|
|
b .
|
|
|
|
.text
|
|
.align 7
|
|
L__elx_32_irq_vector:
|
|
FASTSIM_DEBUG_HINT
|
|
b .
|
|
|
|
.text
|
|
.align 7
|
|
L__elx_32_fiq_vector:
|
|
FASTSIM_DEBUG_HINT
|
|
b .
|
|
|
|
.text
|
|
.align 7
|
|
L__elx_32_serror_vector:
|
|
FASTSIM_DEBUG_HINT
|
|
b .
|
|
|
|
/* Placeholder for macho_post_process.py. Placing the UUID here
|
|
allows debuggers to locate the UUID based on the value of VBAR */
|
|
.text
|
|
.align 7
|
|
_UUID:
|
|
.space 32
|
|
|
|
/* 64-bit first level exception handler dispatcher.
|
|
* Completes register context saving and branches to FLEH.
|
|
* Expects:
|
|
* {x0, x1, fp, lr, sp} - saved
|
|
* x0 - arm_context_t
|
|
* x1 - address of FLEH
|
|
* fp - previous stack frame if EL1
|
|
* lr - unused
|
|
* sp - kernel stack
|
|
*/
|
|
.text
|
|
.align 2
|
|
__dispatch64:
|
|
stp fp, lr, [sp, #-16]! // Create a frame to help debuggers unwind
|
|
mov fp, sp // past the exception handler
|
|
stp x2, x3, [x0, #16] // Save remaining GPRs
|
|
stp x4, x5, [x0, #32]
|
|
stp x6, x7, [x0, #48]
|
|
stp x8, x9, [x0, #64]
|
|
stp x10, x11, [x0, #80]
|
|
stp x12, x13, [x0, #96]
|
|
stp x14, x15, [x0, #112]
|
|
stp x16, x17, [x0, #128]
|
|
stp x18, x19, [x0, #144]
|
|
stp x20, x21, [x0, #160]
|
|
stp x22, x23, [x0, #176]
|
|
stp x24, x25, [x0, #192]
|
|
stp x26, x27, [x0, #208]
|
|
str x28, [x0, #224]
|
|
mrs lr, ELR_EL3 // Get exception link register
|
|
str lr, [x0, #264] // Save ELR to PCB
|
|
mrs x2, SPSR_EL3 // Get CPSR
|
|
str w2, [x0, #256] // Save CPSR to PCB
|
|
|
|
#if WITH_VFP
|
|
stp q0, q1, [x0, #304]
|
|
stp q2, q3, [x0, #336]
|
|
stp q4, q5, [x0, #368]
|
|
stp q6, q7, [x0, #400]
|
|
stp q8, q9, [x0, #432]
|
|
stp q10, q11, [x0, #464]
|
|
stp q12, q13, [x0, #496]
|
|
stp q14, q15, [x0, #528]
|
|
stp q16, q17, [x0, #560]
|
|
stp q18, q19, [x0, #592]
|
|
stp q20, q21, [x0, #624]
|
|
stp q22, q23, [x0, #656]
|
|
stp q24, q25, [x0, #688]
|
|
stp q26, q27, [x0, #720]
|
|
stp q28, q29, [x0, #752]
|
|
stp q30, q31, [x0, #784]
|
|
mrs x2, FPSR
|
|
str w2, [x0, #816]
|
|
mrs x2, FPCR
|
|
str w2, [x0, #820]
|
|
#endif
|
|
|
|
mov x21, x0 // Copy arm_context_t pointer to x21
|
|
blr x1
|
|
b __exception_return
|
|
|
|
.text
|
|
.align 2
|
|
__exception_return:
|
|
mov sp, x21 // Reload the arm_context_t pointer
|
|
|
|
#if WITH_VFP
|
|
ldp q0, q1, [sp, #304]
|
|
ldp q2, q3, [sp, #336]
|
|
ldp q4, q5, [sp, #368]
|
|
ldp q6, q7, [sp, #400]
|
|
ldp q8, q9, [sp, #432]
|
|
ldp q10, q11, [sp, #464]
|
|
ldp q12, q13, [sp, #496]
|
|
ldp q14, q15, [sp, #528]
|
|
ldp q16, q17, [sp, #560]
|
|
ldp q18, q19, [sp, #592]
|
|
ldp q20, q21, [sp, #624]
|
|
ldp q22, q23, [sp, #656]
|
|
ldp q24, q25, [sp, #688]
|
|
ldp q26, q27, [sp, #720]
|
|
ldp q28, q29, [sp, #752]
|
|
ldp q30, q31, [sp, #784]
|
|
ldr w3, [sp, #816]
|
|
msr FPSR, x3
|
|
ldr w4, [sp, #820]
|
|
msr FPCR, x4
|
|
#endif
|
|
|
|
ldr x0, [sp, #264] // Get the return address
|
|
msr ELR_EL3, x0 // Load the return address into ELR
|
|
ldr w1, [sp, #256] // Get the return CPSR
|
|
msr SPSR_EL3, x1 // Load the return CPSR into SPSR
|
|
ldp x0, x1, [sp, #0] // Restore the GPRs
|
|
ldp x2, x3, [sp, #16]
|
|
ldp x4, x5, [sp, #32]
|
|
ldp x6, x7, [sp, #48]
|
|
ldp x8, x9, [sp, #64]
|
|
ldp x10, x11, [sp, #80]
|
|
ldp x12, x13, [sp, #96]
|
|
ldp x14, x15, [sp, #112]
|
|
ldp x16, x17, [sp, #128]
|
|
ldp x18, x19, [sp, #144]
|
|
ldp x20, x21, [sp, #160]
|
|
ldp x22, x23, [sp, #176]
|
|
ldp x24, x25, [sp, #192]
|
|
ldp x26, x27, [sp, #208]
|
|
ldr x28, [sp, #224]
|
|
ldp fp, lr, [sp, #232]
|
|
|
|
/* Use exception stack to restore SP0 */
|
|
|
|
msr SPSel, #1 // Switch to SPx
|
|
stp x0, x1, [sp, #-16]! // Save x0 and x1
|
|
mrs x0, SP_EL0 // Reload the pcb pointer from SP0
|
|
ldr x1, [x0, #248] // Get the saved SP from the pcb
|
|
msr SP_EL0, x1 // Restore SP0
|
|
ldp x0, x1, [sp], #16 // Restore x0 and x1
|
|
eret
|