use ax_memory_addr::{PhysAddr, VirtAddr};
use riscv::{
asm,
register::{satp, sstatus, stvec},
};
#[inline]
pub fn enable_irqs() {
unsafe { sstatus::set_sie() }
}
#[inline]
pub fn disable_irqs() {
unsafe { sstatus::clear_sie() }
}
#[inline]
pub fn irqs_enabled() -> bool {
sstatus::read().sie()
}
#[inline]
pub fn wait_for_irqs() {
riscv::asm::wfi()
}
#[inline]
pub fn halt() {
disable_irqs();
riscv::asm::wfi() }
#[inline]
pub fn read_user_page_table() -> PhysAddr {
pa!(satp::read().ppn() << 12)
}
#[inline]
pub fn read_kernel_page_table() -> PhysAddr {
read_user_page_table()
}
#[inline]
pub unsafe fn write_user_page_table(root_paddr: PhysAddr) {
unsafe { satp::set(satp::Mode::Sv39, 0, root_paddr.as_usize() >> 12) };
}
#[inline]
pub unsafe fn write_kernel_page_table(root_paddr: PhysAddr) {
unsafe { write_user_page_table(root_paddr) };
}
#[inline]
pub fn flush_tlb(vaddr: Option<VirtAddr>) {
if let Some(vaddr) = vaddr {
asm::sfence_vma(0, vaddr.as_usize())
} else {
asm::sfence_vma_all();
}
}
#[inline]
pub unsafe fn write_trap_vector_base(stvec: usize) {
let mut reg = stvec::read();
reg.set_address(stvec);
reg.set_trap_mode(stvec::TrapMode::Direct);
unsafe { stvec::write(reg) }
}
#[inline]
pub fn read_thread_pointer() -> usize {
let tp;
unsafe { core::arch::asm!("mv {}, tp", out(reg) tp) };
tp
}
#[inline]
pub unsafe fn write_thread_pointer(tp: usize) {
unsafe { core::arch::asm!("mv tp, {}", in(reg) tp) }
}
#[cfg(feature = "uspace")]
core::arch::global_asm!(include_asm_macros!(), include_str!("user_copy.S"));
#[cfg(feature = "uspace")]
unsafe extern "C" {
pub fn user_copy(dst: *mut u8, src: *const u8, size: usize) -> usize;
}