rv64: implement M-/S-mode trap stubs

This commit is contained in:
Mark Poliakov 2025-01-17 03:28:00 +02:00
parent 86eb2d3252
commit f46f3ddc31
5 changed files with 236 additions and 1 deletions

View File

@ -149,6 +149,63 @@ pub mod mepc {
pub const MEPC: Reg = Reg;
}
pub mod mtvec {
use tock_registers::{interfaces::ReadWriteable, register_bitfields};
use super::{impl_csr_read, impl_csr_write};
pub struct Reg;
register_bitfields!(
u64,
pub MTVEC [
MODE OFFSET(0) NUMBITS(2) [
Direct = 0,
Vectored = 1
],
BASE OFFSET(2) NUMBITS(62) [],
]
);
impl_csr_read!(Reg, u64, mtvec, MTVEC::Register);
impl_csr_write!(Reg, u64, mtvec, MTVEC::Register);
impl Reg {
pub fn set_base(&self, base: usize) {
debug_assert_eq!(base & 0xF, 0);
let mask = match base & 63 != 0 {
false => 0,
true => 0x3 << 62,
};
self.modify(MTVEC::BASE.val(((base as u64) >> 2) | mask));
}
}
pub const MTVEC: Reg = Reg;
}
pub mod medeleg {
use super::{impl_csr_read, impl_csr_write};
pub struct Reg;
impl_csr_read!(Reg, u64, medeleg, ());
impl_csr_write!(Reg, u64, medeleg, ());
pub const MEDELEG: Reg = Reg;
}
pub mod mideleg {
use super::{impl_csr_read, impl_csr_write};
pub struct Reg;
impl_csr_read!(Reg, u64, mideleg, ());
impl_csr_write!(Reg, u64, mideleg, ());
pub const MIDELEG: Reg = Reg;
}
pub mod satp {
use tock_registers::register_bitfields;
@ -177,7 +234,80 @@ pub mod satp {
pub const SATP: Reg = Reg;
}
pub mod stvec {
use tock_registers::{interfaces::ReadWriteable, register_bitfields};
use super::{impl_csr_read, impl_csr_write};
register_bitfields!(
u64,
pub STVEC [
MODE OFFSET(0) NUMBITS(2) [
Direct = 0,
Vectored = 1
],
BASE OFFSET(2) NUMBITS(62) [],
]
);
pub struct Reg;
impl_csr_read!(Reg, u64, stvec, STVEC::Register);
impl_csr_write!(Reg, u64, stvec, STVEC::Register);
impl Reg {
pub fn set_base(&self, base: usize) {
debug_assert_eq!(base & 0xF, 0);
let mask = match base & 63 != 0 {
false => 0,
true => 0x3 << 62,
};
self.modify(STVEC::BASE.val(((base as u64) >> 2) | mask));
}
}
pub const STVEC: Reg = Reg;
}
pub mod scause {
use tock_registers::register_bitfields;
use super::{impl_csr_read, impl_csr_write};
register_bitfields!(
u64,
pub SCAUSE [
CODE OFFSET(0) NUMBITS(63) [],
INTERRUPT OFFSET(63) NUMBITS(1) [],
]
);
pub struct Reg;
impl_csr_read!(Reg, u64, scause, SCAUSE::Register);
impl_csr_write!(Reg, u64, scause, SCAUSE::Register);
pub const SCAUSE: Reg = Reg;
}
pub mod sepc {
use super::{impl_csr_read, impl_csr_write};
pub struct Reg;
impl_csr_read!(Reg, u64, sepc, ());
impl_csr_write!(Reg, u64, sepc, ());
pub const SEPC: Reg = Reg;
}
pub use medeleg::MEDELEG;
pub use mepc::MEPC;
pub use mideleg::MIDELEG;
pub use misa::MISA;
pub use mstatus::MSTATUS;
pub use mtvec::MTVEC;
pub use satp::SATP;
pub use scause::SCAUSE;
pub use sepc::SEPC;
pub use stvec::STVEC;

View File

@ -5,11 +5,13 @@ use kernel_arch_riscv64::{
table::{PageAttributes, PageEntry, PageTable, L1},
KERNEL_VIRT_OFFSET,
},
registers::{MEPC, MSTATUS, SATP},
registers::{MEDELEG, MEPC, MIDELEG, MSTATUS, MTVEC, SATP},
};
use libk_mm::{address::PhysicalAddress, table::EntryLevel};
use tock_registers::interfaces::{ReadWriteable, Writeable};
use super::exception;
const BOOT_STACK_SIZE: usize = 65536;
#[repr(C, align(0x10))]
@ -64,6 +66,8 @@ unsafe extern "C" fn __rv64_bsp_smode_entry_lower() -> ! {
}
unsafe extern "C" fn __rv64_bsp_entry_upper() -> ! {
// TODO set up per-CPU pointer, pass DTB from M-mode, figure out the rest of the boot process
exception::init_smode_exceptions();
loop {}
}
@ -71,8 +75,18 @@ unsafe extern "C" fn __rv64_bsp_entry_upper() -> ! {
unsafe extern "C" fn __rv64_bsp_mmode_entry_lower() -> ! {
extern "C" {
fn __rv64_smode_entry() -> !;
static __rv64_mmode_trap_vectors: u8;
}
// Setup trap vector for M-mode
let mtvec = (&raw const __rv64_mmode_trap_vectors).addr() - KERNEL_VIRT_OFFSET;
MTVEC.set_base(mtvec);
MTVEC.modify(MTVEC::MODE::Direct);
// Setup trap delegation to S-mode
MIDELEG.set(u64::MAX);
MEDELEG.set(u64::MAX);
MSTATUS.modify(
// Mask S-mode interrupts
MSTATUS::SIE::CLEAR

View File

@ -0,0 +1,28 @@
use core::arch::global_asm;
use tock_registers::interfaces::{ReadWriteable, Readable};
use kernel_arch_riscv64::registers::{SCAUSE, SEPC, STVEC};
pub fn init_smode_exceptions() {
extern "C" {
static __rv64_smode_trap_vectors: u8;
}
let address = (&raw const __rv64_smode_trap_vectors).addr();
STVEC.set_base(address);
STVEC.modify(STVEC::MODE::Vectored);
}
unsafe extern "C" fn smode_trap_handler() {
let cause = SCAUSE.read(SCAUSE::CODE);
let pc = SEPC.get();
// Just put these into t0/t1 until I complete the rest of the kernel, lol
core::arch::asm!("j .", in("t0") cause, in("t1") pc);
loop {}
}
global_asm!(
include_str!("vectors.S"),
smode_handler = sym smode_trap_handler
);

View File

@ -11,6 +11,7 @@ use libk_mm::table::EntryLevel;
use super::Platform;
pub mod boot;
pub mod exception;
pub struct Riscv64;

View File

@ -0,0 +1,62 @@
.section .text
.macro SMODE_TRAP n
.type __rv64_smode_trap_\n, @function
__rv64_smode_trap_\n:
// TODO store registers
j {smode_handler}
// TODO restore registers and return
.size __rv64_smode_trap_\n, . - __rv64_smode_trap_\n
.endm
.option push
.option norvc
.global __rv64_smode_trap_vectors
.global __rv64_mmode_trap_vectors
.type __rv64_smode_trap_vectors, @function
.p2align 4
__rv64_smode_trap_vectors:
j __rv64_smode_trap_0
j __rv64_smode_trap_1
j __rv64_smode_trap_2
j __rv64_smode_trap_3
j __rv64_smode_trap_4
j __rv64_smode_trap_5
j __rv64_smode_trap_6
j __rv64_smode_trap_7
j __rv64_smode_trap_8
j __rv64_smode_trap_9
j __rv64_smode_trap_10
j __rv64_smode_trap_11
j __rv64_smode_trap_12
j __rv64_smode_trap_13
j __rv64_smode_trap_14
j __rv64_smode_trap_15
.size __rv64_smode_trap_vectors, . - __rv64_smode_trap_vectors
.type __rv64_mmode_trap_vectors, @function
.p2align 4
__rv64_mmode_trap_vectors:
j .
.size __rv64_mmode_trap_vectors, . - __rv64_mmode_trap_vectors
SMODE_TRAP 0
SMODE_TRAP 1
SMODE_TRAP 2
SMODE_TRAP 3
SMODE_TRAP 4
SMODE_TRAP 5
SMODE_TRAP 6
SMODE_TRAP 7
SMODE_TRAP 8
SMODE_TRAP 9
SMODE_TRAP 10
SMODE_TRAP 11
SMODE_TRAP 12
SMODE_TRAP 13
SMODE_TRAP 14
SMODE_TRAP 15
.option pop