Supervisor mode

This commit is contained in:
2026-01-30 16:22:53 +01:00
parent 7a25e89d4c
commit 53043fd3cd
11 changed files with 457 additions and 108 deletions

View File

@@ -1,17 +1,40 @@
use core::arch::asm;
#![allow(unused)]
const MSTATUS_MIE: usize = 0x8;
use core::arch::naked_asm;
use crate::clear_csr;
use crate::read_csr;
use crate::set_csr;
pub struct MStatus;
pub struct SStatus;
impl MStatus {
pub const MIE: usize = 1 << 3;
pub const MPIE: usize = 1 << 7;
}
impl SStatus {
pub const SIE: usize = 1 << 1;
pub const SPIE: usize = 1 << 5;
}
pub fn get_interrupt_state() -> bool {
let res: u64;
unsafe { asm!("csrr {}, mstatus", out(reg) res) };
(res & MSTATUS_MIE as u64) != 0
(read_csr!(mstatus) & MStatus::MIE as u64) != 0
}
pub fn get_supervisor_interrupt_state() -> bool {
(read_csr!(sstatus) & SStatus::SIE as u64) != 0
}
pub fn enable_interrupt() {
unsafe { asm!("csrs mstatus, {}", in(reg) MSTATUS_MIE) };
set_csr!(mstatus, MStatus::MIE);
}
pub fn enable_supervisor_interrupt() {
set_csr!(sstatus, SStatus::SIE);
}
pub fn disable_interrupt() {
unsafe { asm!("csrc mstatus, {}", in(reg) MSTATUS_MIE) };
clear_csr!(mstatus, MStatus::MIE);
}
pub fn disable_supervisor_interrupt() {
clear_csr!(sstatus, SStatus::SIE);
}
pub fn restore_interrupt(previous_state: bool) {
if previous_state {
@@ -20,3 +43,59 @@ pub fn restore_interrupt(previous_state: bool) {
disable_interrupt();
}
}
pub fn restore_supervisor_interrupt(previous_state: bool) {
if previous_state {
enable_supervisor_interrupt();
} else {
disable_supervisor_interrupt();
}
}
#[macro_export]
macro_rules! read_csr {
($name:ident) => {{
let res: u64;
unsafe { core::arch::asm!(concat!("csrr {}, ", stringify!($name)), out(reg) res, options(nomem, nostack)) };
res
}};
}
#[macro_export]
macro_rules! write_csr {
($name:ident, $value:expr) => {
let val = $value;
unsafe { core::arch::asm!(concat!("csrw ", stringify!($name), ", {}"), in(reg) val, options(nomem, nostack)) };
};
}
#[macro_export]
macro_rules! set_csr {
($name:ident, $value:expr) => {
let val = $value;
unsafe { core::arch::asm!(concat!("csrs ", stringify!($name), ", {}"), in(reg) val, options(nomem, nostack)) };
};
}
#[macro_export]
macro_rules! clear_csr {
($name:ident, $value:expr) => {
let val = $value;
unsafe { core::arch::asm!(concat!("csrc ", stringify!($name), ", {}"), in(reg) val, options(nomem, nostack)) };
};
}
#[macro_export]
macro_rules! mret {
() => {
unsafe { core::arch::asm!("mret", options(noreturn)) }
};
}
#[unsafe(naked)]
pub extern "C" fn exit_qemu() {
naked_asm!(
"
li a0, 0x100000
li a1, 0x5555
sw a1, 0(a0)
wfi
"
)
}