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 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 {
|
pub mod satp {
|
||||||
use tock_registers::register_bitfields;
|
use tock_registers::register_bitfields;
|
||||||
|
|
||||||
@ -177,7 +234,80 @@ pub mod satp {
|
|||||||
pub const SATP: Reg = Reg;
|
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 mepc::MEPC;
|
||||||
|
pub use mideleg::MIDELEG;
|
||||||
pub use misa::MISA;
|
pub use misa::MISA;
|
||||||
pub use mstatus::MSTATUS;
|
pub use mstatus::MSTATUS;
|
||||||
|
pub use mtvec::MTVEC;
|
||||||
pub use satp::SATP;
|
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},
|
table::{PageAttributes, PageEntry, PageTable, L1},
|
||||||
KERNEL_VIRT_OFFSET,
|
KERNEL_VIRT_OFFSET,
|
||||||
},
|
},
|
||||||
registers::{MEPC, MSTATUS, SATP},
|
registers::{MEDELEG, MEPC, MIDELEG, MSTATUS, MTVEC, SATP},
|
||||||
};
|
};
|
||||||
use libk_mm::{address::PhysicalAddress, table::EntryLevel};
|
use libk_mm::{address::PhysicalAddress, table::EntryLevel};
|
||||||
use tock_registers::interfaces::{ReadWriteable, Writeable};
|
use tock_registers::interfaces::{ReadWriteable, Writeable};
|
||||||
|
|
||||||
|
use super::exception;
|
||||||
|
|
||||||
const BOOT_STACK_SIZE: usize = 65536;
|
const BOOT_STACK_SIZE: usize = 65536;
|
||||||
|
|
||||||
#[repr(C, align(0x10))]
|
#[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() -> ! {
|
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 {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,8 +75,18 @@ unsafe extern "C" fn __rv64_bsp_entry_upper() -> ! {
|
|||||||
unsafe extern "C" fn __rv64_bsp_mmode_entry_lower() -> ! {
|
unsafe extern "C" fn __rv64_bsp_mmode_entry_lower() -> ! {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn __rv64_smode_entry() -> !;
|
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(
|
MSTATUS.modify(
|
||||||
// Mask S-mode interrupts
|
// Mask S-mode interrupts
|
||||||
MSTATUS::SIE::CLEAR
|
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;
|
use super::Platform;
|
||||||
|
|
||||||
pub mod boot;
|
pub mod boot;
|
||||||
|
pub mod exception;
|
||||||
|
|
||||||
pub struct Riscv64;
|
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