use core::arch::asm;
use ax_memory_addr::{PhysAddr, VirtAddr};
use loongArch64::register::{crmd, ecfg, eentry, pgdh, pgdl};
#[inline]
pub fn enable_irqs() {
crmd::set_ie(true)
}
#[inline]
pub fn disable_irqs() {
crmd::set_ie(false)
}
#[inline]
pub fn irqs_enabled() -> bool {
crmd::read().ie()
}
#[inline]
pub fn wait_for_irqs() {
unsafe { loongArch64::asm::idle() }
}
#[inline]
pub fn halt() {
disable_irqs();
unsafe { loongArch64::asm::idle() }
}
#[inline]
pub fn read_user_page_table() -> PhysAddr {
PhysAddr::from(pgdl::read().base())
}
#[inline]
pub fn read_kernel_page_table() -> PhysAddr {
PhysAddr::from(pgdh::read().base())
}
pub unsafe fn write_user_page_table(root_paddr: PhysAddr) {
pgdl::set_base(root_paddr.as_usize() as _);
}
pub unsafe fn write_kernel_page_table(root_paddr: PhysAddr) {
pgdh::set_base(root_paddr.as_usize());
}
#[inline]
pub fn flush_icache_all() {
unsafe { asm!("ibar 0") };
}
#[inline]
pub fn flush_tlb(vaddr: Option<VirtAddr>) {
unsafe {
if let Some(vaddr) = vaddr {
asm!("dbar 0; invtlb 0x05, $r0, {reg}", reg = in(reg) vaddr.as_usize());
} else {
asm!("dbar 0; invtlb 0x00, $r0, $r0");
}
}
}
#[inline]
pub unsafe fn write_exception_entry_base(eentry: usize) {
ecfg::set_vs(0);
eentry::set_eentry(eentry);
}
#[inline]
pub unsafe fn write_pwc(pwcl: u32, pwch: u32) {
unsafe {
asm!(
include_asm_macros!(),
"csrwr {}, LA_CSR_PWCL",
"csrwr {}, LA_CSR_PWCH",
in(reg) pwcl,
in(reg) pwch
)
}
}
#[inline]
pub fn read_thread_pointer() -> usize {
let tp;
unsafe { asm!("move {}, $tp", out(reg) tp) };
tp
}
#[inline]
pub unsafe fn write_thread_pointer(tp: usize) {
unsafe { asm!("move $tp, {}", in(reg) tp) }
}
#[inline]
pub fn enable_fp() {
loongArch64::register::euen::set_fpe(true);
}
pub fn enable_lsx() {
loongArch64::register::euen::set_sxe(true);
}
#[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;
}