1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 00:07:36 +00:00
serenity/Kernel/Arch/riscv64/trap_handler.S
Sönke Holz efdc433ebc Kernel/riscv64: Implement thread_context_first_enter
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.
2024-02-24 16:42:58 -07:00

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