rv64: implement M-/S-mode trap stubs
This commit is contained in:
parent
86eb2d3252
commit
f46f3ddc31
@ -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;
|
||||
|
@ -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
|
||||
|
28
kernel/src/arch/riscv64/exception.rs
Normal file
28
kernel/src/arch/riscv64/exception.rs
Normal 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
|
||||
);
|
@ -11,6 +11,7 @@ use libk_mm::table::EntryLevel;
|
||||
use super::Platform;
|
||||
|
||||
pub mod boot;
|
||||
pub mod exception;
|
||||
|
||||
pub struct Riscv64;
|
||||
|
||||
|
62
kernel/src/arch/riscv64/vectors.S
Normal file
62
kernel/src/arch/riscv64/vectors.S
Normal 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
|
Loading…
x
Reference in New Issue
Block a user