mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 00:07:36 +00:00

thread_context_first_enter reuses the context restoring code in the trap handler, just like other arches already do. The `ld x2, 1*8(sp)` is unnecessary in the trap handler, as the stack pointer should be equal to the stack pointer slot in the RegisterState if the trap is from supervisor mode (and we currently don't support user traps). This load will however make us unable to reuse that code for thread_context_first_enter.
138 lines
3 KiB
ArmAsm
138 lines
3 KiB
ArmAsm
/*
|
|
* Copyright (c) 2024, Sönke Holz <sholz830@gmail.com>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
.section .text.asm_trap_handler
|
|
|
|
#define REGISTER_STATE_SIZE (36 * 8)
|
|
#if REGISTER_STATE_SIZE % 16 != 0
|
|
# error "REGISTER_STATE_SIZE is not a multiple of 16 bytes!"
|
|
#endif
|
|
|
|
#define SSTATUS_SLOT (31 * 8)
|
|
#define SEPC_SLOT (32 * 8)
|
|
#define SCAUSE_SLOT (33 * 8)
|
|
#define STVAL_SLOT (34 * 8)
|
|
#define USERSPACE_SP_SLOT (35 * 8)
|
|
|
|
.extern trap_handler
|
|
|
|
.p2align 2
|
|
.global asm_trap_handler
|
|
asm_trap_handler:
|
|
// FIXME: Handle traps from userspace
|
|
|
|
// Save the current register state to the current stack
|
|
// and enter the C++ trap handler
|
|
|
|
// Allocate stack space for trap frame
|
|
addi sp, sp, -REGISTER_STATE_SIZE
|
|
|
|
sd x1, 0*8(sp)
|
|
sd x2, 1*8(sp)
|
|
sd x3, 2*8(sp)
|
|
sd x4, 3*8(sp)
|
|
sd x5, 4*8(sp)
|
|
sd x6, 5*8(sp)
|
|
sd x7, 6*8(sp)
|
|
sd x8, 7*8(sp)
|
|
sd x9, 8*8(sp)
|
|
sd x10, 9*8(sp)
|
|
sd x11, 10*8(sp)
|
|
sd x12, 11*8(sp)
|
|
sd x13, 12*8(sp)
|
|
sd x14, 13*8(sp)
|
|
sd x15, 14*8(sp)
|
|
sd x16, 15*8(sp)
|
|
sd x17, 16*8(sp)
|
|
sd x18, 17*8(sp)
|
|
sd x19, 18*8(sp)
|
|
sd x20, 19*8(sp)
|
|
sd x21, 20*8(sp)
|
|
sd x22, 21*8(sp)
|
|
sd x23, 22*8(sp)
|
|
sd x24, 23*8(sp)
|
|
sd x25, 24*8(sp)
|
|
sd x26, 25*8(sp)
|
|
sd x27, 26*8(sp)
|
|
sd x28, 27*8(sp)
|
|
sd x29, 28*8(sp)
|
|
sd x30, 29*8(sp)
|
|
sd x31, 30*8(sp)
|
|
|
|
// Let's save some special registers
|
|
csrr t0, sstatus
|
|
sd t0, SSTATUS_SLOT(sp)
|
|
csrr t0, sepc
|
|
sd t0, SEPC_SLOT(sp)
|
|
|
|
// We also have to save those registers as interrupts are enabled during the page fault handling code.
|
|
// A page fault exception may be reported as an interrupt in the register dump, if we wouldn't do that.
|
|
csrr t0, scause
|
|
sd t0, SCAUSE_SLOT(sp)
|
|
csrr t0, stval
|
|
sd t0, STVAL_SLOT(sp)
|
|
|
|
// TODO
|
|
sd zero, USERSPACE_SP_SLOT(sp)
|
|
|
|
// Set up TrapFrame struct on the stack
|
|
mv t0, sp
|
|
addi sp, sp, -16
|
|
sd t0, 1*8(sp)
|
|
sd zero, 0*8(sp)
|
|
|
|
// Move stack pointer into first argument register
|
|
// and jump to the C++ trap handler
|
|
mv a0, sp
|
|
|
|
call trap_handler
|
|
|
|
.global restore_context_and_sret
|
|
restore_context_and_sret:
|
|
|
|
// Remove TrapFrame from the stack
|
|
addi sp, sp, 16
|
|
|
|
// Restore special registers first
|
|
ld t0, SSTATUS_SLOT(sp)
|
|
csrw sstatus, t0
|
|
ld t0, SEPC_SLOT(sp)
|
|
csrw sepc, t0
|
|
|
|
ld x1, 0*8(sp)
|
|
// sp
|
|
ld x3, 2*8(sp)
|
|
ld x4, 3*8(sp)
|
|
ld x5, 4*8(sp)
|
|
ld x6, 5*8(sp)
|
|
ld x7, 6*8(sp)
|
|
ld x8, 7*8(sp)
|
|
ld x9, 8*8(sp)
|
|
ld x10, 9*8(sp)
|
|
ld x11, 10*8(sp)
|
|
ld x12, 11*8(sp)
|
|
ld x13, 12*8(sp)
|
|
ld x14, 13*8(sp)
|
|
ld x15, 14*8(sp)
|
|
ld x16, 15*8(sp)
|
|
ld x17, 16*8(sp)
|
|
ld x18, 17*8(sp)
|
|
ld x19, 18*8(sp)
|
|
ld x20, 19*8(sp)
|
|
ld x21, 20*8(sp)
|
|
ld x22, 21*8(sp)
|
|
ld x23, 22*8(sp)
|
|
ld x24, 23*8(sp)
|
|
ld x25, 24*8(sp)
|
|
ld x26, 25*8(sp)
|
|
ld x27, 26*8(sp)
|
|
ld x28, 27*8(sp)
|
|
ld x29, 28*8(sp)
|
|
ld x30, 29*8(sp)
|
|
ld x31, 30*8(sp)
|
|
|
|
addi sp, sp, REGISTER_STATE_SIZE
|
|
sret
|