mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-12-18 16:32:05 +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(.);
|
||||
} >main
|
||||
|
||||
. = ALIGN(0x1000);
|
||||
__end__ = ABSOLUTE(.) ;
|
||||
|
||||
__stacks_top__ = ABSOLUTE(. + 0x1000);
|
||||
__stacks_top__ = ABSOLUTE(. + 0x2000);
|
||||
__excep_stacks_top__ = ABSOLUTE(. + 0x4000); /* Note: potentially overwrites warmboot firmware. */
|
||||
|
||||
. = ALIGN(8);
|
||||
|
||||
|
|
|
@ -51,7 +51,49 @@
|
|||
.endm
|
||||
|
||||
.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 x2, x3, [sp, #0x10]
|
||||
stp x4, x5, [sp, #0x20]
|
||||
|
@ -68,100 +110,35 @@
|
|||
stp x26, x27, [sp, #0xD0]
|
||||
stp x28, x29, [sp, #0xE0]
|
||||
|
||||
mov x29, x30
|
||||
ldp x30, xzr, [sp, #-0x10] // See save_all_regs macro
|
||||
|
||||
mrs x20, sp_el1
|
||||
mrs x21, elr_el2
|
||||
mrs x22, spsr_el2
|
||||
mrs x21, sp_el0
|
||||
mrs x22, elr_el2
|
||||
mrs x23, spsr_el2
|
||||
|
||||
stp x30, x20, [sp, #0xF0]
|
||||
stp x21, x22, [sp, #0x100]
|
||||
.endm
|
||||
stp x23, xzr, [sp, #0x110]
|
||||
|
||||
/* Actual Vectors for Exosphere. */
|
||||
.global exosphere_vectors
|
||||
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
|
||||
mov x30, x29
|
||||
ret
|
||||
|
||||
vector_entry fiq_sp0
|
||||
b 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
|
||||
bl unknown_exception
|
||||
.endfunc
|
||||
.cfi_endproc
|
||||
/* To save space, insert in an unused vector segment. */
|
||||
_restore_all_regs:
|
||||
/* To save space, insert in an unused vector segment. */
|
||||
_restore_all_regs:
|
||||
ldp x30, x20, [sp, #0xF0]
|
||||
ldp x21, x22, [sp, #0x100]
|
||||
ldp x23, xzr, [sp, #0x110]
|
||||
|
||||
msr sp_el1, x20
|
||||
msr elr_el2, x21
|
||||
msr spsr_el2, x22
|
||||
msr sp_el0, x21
|
||||
msr elr_el2, x22
|
||||
msr spsr_el2, x23
|
||||
|
||||
ldp x0, x1, [sp, #0x00]
|
||||
ldp x2, x3, [sp, #0x10]
|
||||
|
@ -179,9 +156,77 @@ _restore_all_regs:
|
|||
ldp x26, x27, [sp, #0xD0]
|
||||
ldp x28, x29, [sp, #0xE0]
|
||||
|
||||
add sp, sp, #0x110
|
||||
add sp, sp, #0x210
|
||||
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
|
||||
b unknown_exception
|
||||
bl unknown_exception
|
||||
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);
|
||||
serialLog("Hello from Thermosphere!\r\n");
|
||||
__builtin_trap();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -32,8 +32,9 @@ g_kernelEntrypoint:
|
|||
.quad 0
|
||||
|
||||
start:
|
||||
// Disable interrupts
|
||||
// Disable interrupts, select sp_el2
|
||||
msr daifset, 0b1111
|
||||
msr spsel, #1
|
||||
|
||||
// Save arg, load entrypoint & spsr
|
||||
mov x19, x0
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
MEMORY
|
||||
{
|
||||
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