mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-23 04:41:12 +00:00
thermosphere: start exception handling
This commit is contained in:
parent
ada6b180cc
commit
4e0eef2784
7 changed files with 219 additions and 87 deletions
|
@ -135,9 +135,11 @@ SECTIONS
|
||||||
__end__ = ABSOLUTE(.);
|
__end__ = ABSOLUTE(.);
|
||||||
} >main
|
} >main
|
||||||
|
|
||||||
|
. = ALIGN(0x1000);
|
||||||
__end__ = ABSOLUTE(.) ;
|
__end__ = ABSOLUTE(.) ;
|
||||||
|
|
||||||
__stacks_top__ = ABSOLUTE(. + 0x1000);
|
__stacks_top__ = ABSOLUTE(. + 0x2000);
|
||||||
|
__excep_stacks_top__ = ABSOLUTE(. + 0x4000); /* Note: potentially overwrites warmboot firmware. */
|
||||||
|
|
||||||
. = ALIGN(8);
|
. = ALIGN(8);
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,49 @@
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro save_all_regs
|
.macro save_all_regs
|
||||||
sub sp, sp, #0x110
|
stp x30, xzr, [sp, #-0x130]
|
||||||
|
bl _save_all_regs
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro pivot_stack_for_crash
|
||||||
|
// Ditch sp_el0 & elr_el1
|
||||||
|
// We don't use E2H so that's fine.
|
||||||
|
msr elr_el1, x0
|
||||||
|
mov x0, sp
|
||||||
|
msr sp_el0, x0 // save stack pointer for the crash
|
||||||
|
bic x0, x0, #0xFF
|
||||||
|
bic x0, x0, #0x700
|
||||||
|
add x0, x0, #0x1000
|
||||||
|
add x0, x0, #0x800
|
||||||
|
mov sp, x0
|
||||||
|
mrs x0, elr_el1
|
||||||
|
.endm
|
||||||
|
|
||||||
|
/* Actual Vectors for Thermosphere. */
|
||||||
|
.global thermosphere_vectors
|
||||||
|
vector_base thermosphere_vectors
|
||||||
|
|
||||||
|
/* Current EL, SP0 */
|
||||||
|
/* Those are unused by us, except on same-EL double-faults. */
|
||||||
|
.global unknown_exception
|
||||||
|
unknown_exception:
|
||||||
|
vector_entry synch_sp0
|
||||||
|
pivot_stack_for_crash
|
||||||
|
mov x0, x30
|
||||||
|
adr x1, thermosphere_vectors + 4
|
||||||
|
sub x0, x0, x1
|
||||||
|
bl handleUnknownException
|
||||||
|
b .
|
||||||
|
check_vector_size synch_sp0
|
||||||
|
|
||||||
|
vector_entry irq_sp0
|
||||||
|
bl unknown_exception
|
||||||
|
.endfunc
|
||||||
|
.cfi_endproc
|
||||||
|
/* To save space, insert in an unused vector segment. */
|
||||||
|
_save_all_regs:
|
||||||
|
|
||||||
|
sub sp, sp, #0x120
|
||||||
stp x0, x1, [sp, #0x00]
|
stp x0, x1, [sp, #0x00]
|
||||||
stp x2, x3, [sp, #0x10]
|
stp x2, x3, [sp, #0x10]
|
||||||
stp x4, x5, [sp, #0x20]
|
stp x4, x5, [sp, #0x20]
|
||||||
|
@ -68,100 +110,35 @@
|
||||||
stp x26, x27, [sp, #0xD0]
|
stp x26, x27, [sp, #0xD0]
|
||||||
stp x28, x29, [sp, #0xE0]
|
stp x28, x29, [sp, #0xE0]
|
||||||
|
|
||||||
|
mov x29, x30
|
||||||
|
ldp x30, xzr, [sp, #-0x10] // See save_all_regs macro
|
||||||
|
|
||||||
mrs x20, sp_el1
|
mrs x20, sp_el1
|
||||||
mrs x21, elr_el2
|
mrs x21, sp_el0
|
||||||
mrs x22, spsr_el2
|
mrs x22, elr_el2
|
||||||
|
mrs x23, spsr_el2
|
||||||
|
|
||||||
stp x30, x20, [sp, #0xF0]
|
stp x30, x20, [sp, #0xF0]
|
||||||
stp x21, x22, [sp, #0x100]
|
stp x21, x22, [sp, #0x100]
|
||||||
.endm
|
stp x23, xzr, [sp, #0x110]
|
||||||
|
|
||||||
/* Actual Vectors for Exosphere. */
|
mov x30, x29
|
||||||
.global exosphere_vectors
|
ret
|
||||||
vector_base exosphere_vectors
|
|
||||||
|
|
||||||
/* Current EL, SP0 */
|
|
||||||
.global unknown_exception
|
|
||||||
unknown_exception:
|
|
||||||
vector_entry synch_sp0
|
|
||||||
b .
|
|
||||||
check_vector_size synch_sp0
|
|
||||||
|
|
||||||
vector_entry irq_sp0
|
|
||||||
b unknown_exception
|
|
||||||
check_vector_size irq_sp0
|
|
||||||
|
|
||||||
vector_entry fiq_sp0
|
vector_entry fiq_sp0
|
||||||
b unknown_exception
|
bl unknown_exception
|
||||||
check_vector_size fiq_sp0
|
|
||||||
|
|
||||||
vector_entry serror_sp0
|
|
||||||
b unknown_exception
|
|
||||||
check_vector_size serror_sp0
|
|
||||||
|
|
||||||
/* Current EL, SPx */
|
|
||||||
vector_entry synch_spx
|
|
||||||
b unknown_exception
|
|
||||||
check_vector_size synch_spx
|
|
||||||
|
|
||||||
vector_entry irq_spx
|
|
||||||
b unknown_exception
|
|
||||||
check_vector_size irq_spx
|
|
||||||
|
|
||||||
vector_entry fiq_spx
|
|
||||||
b unknown_exception
|
|
||||||
check_vector_size fiq_spx
|
|
||||||
|
|
||||||
vector_entry serror_spx
|
|
||||||
b unknown_exception
|
|
||||||
check_vector_size serror_spx
|
|
||||||
|
|
||||||
/* Lower EL, A64 */
|
|
||||||
vector_entry synch_a64
|
|
||||||
save_all_regs
|
|
||||||
|
|
||||||
mov x0, sp
|
|
||||||
mrs x1, esr_el2
|
|
||||||
|
|
||||||
bl . // FIXME!
|
|
||||||
|
|
||||||
b _restore_all_regs
|
|
||||||
check_vector_size synch_a64
|
|
||||||
|
|
||||||
vector_entry irq_a64
|
|
||||||
b unknown_exception
|
|
||||||
check_vector_size irq_a64
|
|
||||||
|
|
||||||
vector_entry fiq_a64
|
|
||||||
b unknown_exception
|
|
||||||
check_vector_size fiq_a64
|
|
||||||
|
|
||||||
vector_entry serror_a64
|
|
||||||
b unknown_exception
|
|
||||||
check_vector_size serror_a64
|
|
||||||
|
|
||||||
|
|
||||||
/* Lower EL, A32 */
|
|
||||||
vector_entry synch_a32
|
|
||||||
b unknown_exception
|
|
||||||
check_vector_size synch_a32
|
|
||||||
|
|
||||||
vector_entry irq_a32
|
|
||||||
b unknown_exception
|
|
||||||
check_vector_size irq_a32
|
|
||||||
|
|
||||||
vector_entry fiq_a32
|
|
||||||
b fiq_a64
|
|
||||||
.endfunc
|
.endfunc
|
||||||
.cfi_endproc
|
.cfi_endproc
|
||||||
/* To save space, insert in an unused vector segment. */
|
/* To save space, insert in an unused vector segment. */
|
||||||
_restore_all_regs:
|
_restore_all_regs:
|
||||||
ldp x30, x20, [sp, #0xF0]
|
ldp x30, x20, [sp, #0xF0]
|
||||||
ldp x21, x22, [sp, #0x100]
|
ldp x21, x22, [sp, #0x100]
|
||||||
|
ldp x23, xzr, [sp, #0x110]
|
||||||
|
|
||||||
msr sp_el1, x20
|
msr sp_el1, x20
|
||||||
msr elr_el2, x21
|
msr sp_el0, x21
|
||||||
msr spsr_el2, x22
|
msr elr_el2, x22
|
||||||
|
msr spsr_el2, x23
|
||||||
|
|
||||||
ldp x0, x1, [sp, #0x00]
|
ldp x0, x1, [sp, #0x00]
|
||||||
ldp x2, x3, [sp, #0x10]
|
ldp x2, x3, [sp, #0x10]
|
||||||
|
@ -179,9 +156,77 @@ _restore_all_regs:
|
||||||
ldp x26, x27, [sp, #0xD0]
|
ldp x26, x27, [sp, #0xD0]
|
||||||
ldp x28, x29, [sp, #0xE0]
|
ldp x28, x29, [sp, #0xE0]
|
||||||
|
|
||||||
add sp, sp, #0x110
|
add sp, sp, #0x210
|
||||||
eret
|
eret
|
||||||
|
|
||||||
|
vector_entry serror_sp0
|
||||||
|
bl unknown_exception
|
||||||
|
check_vector_size serror_sp0
|
||||||
|
|
||||||
|
/* Current EL, SPx */
|
||||||
|
vector_entry synch_spx
|
||||||
|
/* Only crashes go through there! */
|
||||||
|
pivot_stack_for_crash
|
||||||
|
|
||||||
|
save_all_regs
|
||||||
|
|
||||||
|
mov x0, sp
|
||||||
|
mrs x1, esr_el2
|
||||||
|
|
||||||
|
bl handleSameElSyncException
|
||||||
|
b .
|
||||||
|
check_vector_size synch_spx
|
||||||
|
|
||||||
|
vector_entry irq_spx
|
||||||
|
bl unknown_exception
|
||||||
|
check_vector_size irq_spx
|
||||||
|
|
||||||
|
vector_entry fiq_spx
|
||||||
|
bl unknown_exception
|
||||||
|
check_vector_size fiq_spx
|
||||||
|
|
||||||
|
vector_entry serror_spx
|
||||||
|
bl unknown_exception
|
||||||
|
check_vector_size serror_spx
|
||||||
|
|
||||||
|
/* Lower EL, A64 */
|
||||||
|
vector_entry synch_a64
|
||||||
|
save_all_regs
|
||||||
|
|
||||||
|
mov x0, sp
|
||||||
|
mrs x1, esr_el2
|
||||||
|
|
||||||
|
bl handleLowerElSyncException
|
||||||
|
|
||||||
|
b _restore_all_regs
|
||||||
|
check_vector_size synch_a64
|
||||||
|
|
||||||
|
vector_entry irq_a64
|
||||||
|
bl unknown_exception
|
||||||
|
check_vector_size irq_a64
|
||||||
|
|
||||||
|
vector_entry fiq_a64
|
||||||
|
bl unknown_exception
|
||||||
|
check_vector_size fiq_a64
|
||||||
|
|
||||||
|
vector_entry serror_a64
|
||||||
|
bl unknown_exception
|
||||||
|
check_vector_size serror_a64
|
||||||
|
|
||||||
|
|
||||||
|
/* Lower EL, A32 */
|
||||||
|
vector_entry synch_a32
|
||||||
|
bl unknown_exception
|
||||||
|
check_vector_size synch_a32
|
||||||
|
|
||||||
|
vector_entry irq_a32
|
||||||
|
bl unknown_exception
|
||||||
|
check_vector_size irq_a32
|
||||||
|
|
||||||
|
vector_entry fiq_a32
|
||||||
|
b fiq_a64
|
||||||
|
check_vector_size fiq_a32
|
||||||
|
|
||||||
vector_entry serror_a32
|
vector_entry serror_a32
|
||||||
b unknown_exception
|
bl unknown_exception
|
||||||
check_vector_size serror_a32
|
check_vector_size serror_a32
|
54
thermosphere/src/exceptions.c
Normal file
54
thermosphere/src/exceptions.c
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "exceptions.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
static void dumpStackFrame(const ExceptionStackFrame *frame, bool sameEl)
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
for (u32 i = 0; i < 30; i += 2) {
|
||||||
|
serialLog("x%d\t\t%08lx\t\tx%d\t\t%08lx\r\n", i, frame->x[i], i + 1, frame->x[i + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
serialLog("x30\t\t%08lx\r\n\r\n", frame->x[30]);
|
||||||
|
serialLog("elr_el2\t\t%08lx\r\n", frame->elr_el2);
|
||||||
|
serialLog("spsr_el2\t%08lx\r\n", frame->spsr_el2);
|
||||||
|
if (sameEl) {
|
||||||
|
serialLog("sp_el2\t\t%08lx\r\n", frame->sp_el2);
|
||||||
|
} else {
|
||||||
|
serialLog("sp_el0\t\t%08lx\r\n", frame->sp_el0);
|
||||||
|
}
|
||||||
|
serialLog("sp_el1\t\t%08lx\r\n", frame->sp_el1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleLowerElSyncException(ExceptionStackFrame *frame, u32 esr)
|
||||||
|
{
|
||||||
|
serialLog("Lower EL sync exception, ESR = 0x%08lx\r\n", esr);
|
||||||
|
dumpStackFrame(frame, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleSameElSyncException(ExceptionStackFrame *frame, u32 esr)
|
||||||
|
{
|
||||||
|
serialLog("Same EL sync exception, ESR = 0x%08lx\r\n", esr);
|
||||||
|
dumpStackFrame(frame, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleUnknownException(u32 offset)
|
||||||
|
{
|
||||||
|
serialLog("Unknown exception! (offset 0x%03lx)\r\n", offset);
|
||||||
|
}
|
29
thermosphere/src/exceptions.h
Normal file
29
thermosphere/src/exceptions.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
typedef struct ExceptionStackFrame {
|
||||||
|
u64 x[31]; // x0 .. x30
|
||||||
|
u64 sp_el1;
|
||||||
|
union {
|
||||||
|
u64 sp_el2;
|
||||||
|
u64 sp_el0;
|
||||||
|
};
|
||||||
|
u64 elr_el2;
|
||||||
|
u64 spsr_el2;
|
||||||
|
} ExceptionStackFrame;
|
|
@ -8,5 +8,6 @@ int main(void)
|
||||||
|
|
||||||
//uart_send(UART_C, "0123\n", 3);
|
//uart_send(UART_C, "0123\n", 3);
|
||||||
serialLog("Hello from Thermosphere!\r\n");
|
serialLog("Hello from Thermosphere!\r\n");
|
||||||
|
__builtin_trap();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,9 @@ g_kernelEntrypoint:
|
||||||
.quad 0
|
.quad 0
|
||||||
|
|
||||||
start:
|
start:
|
||||||
// Disable interrupts
|
// Disable interrupts, select sp_el2
|
||||||
msr daifset, 0b1111
|
msr daifset, 0b1111
|
||||||
|
msr spsel, #1
|
||||||
|
|
||||||
// Save arg, load entrypoint & spsr
|
// Save arg, load entrypoint & spsr
|
||||||
mov x19, x0
|
mov x19, x0
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
NULL : ORIGIN = 0, LENGTH = 0x1000
|
NULL : ORIGIN = 0, LENGTH = 0x1000
|
||||||
main : ORIGIN = 0x80000000, LENGTH = 0xD000 - 0x1000 /* 0x1000 for stacks. */
|
main : ORIGIN = 0x80000000, LENGTH = 0xD000 - 0x2000 /* 0x2000 for stacks. */
|
||||||
}
|
}
|
Loading…
Reference in a new issue