pub mod fpu; pub mod io; mod lock; pub mod msr; pub mod rand; pub mod reg; use core::{arch::asm, ops::Range}; use bitop_ex::BitOpEx; use paging::LAddr; pub use self::lock::{mutex::*, rwlock::*, IntrState, PreemptState, PreemptStateGuard}; /// The address space that should never be valid due to hardware constraints. pub const INCANONICAL: Range = LAddr::new(0x8000_0000_0000 as *mut u8)..LAddr::new(0xFFFF_8000_0000_0000 as *mut u8); /// Check if the address is not permanently invalid. pub fn canonical(addr: LAddr) -> bool { !INCANONICAL.contains(&addr) } /// Automatically fix an incanonical address to its most likely target location. /// /// NOTE: It should not be misused to hard-correct addresses pub fn fix_canonical(addr: LAddr) -> LAddr { let ret = LAddr::from(addr.val() & 0xFFFF_FFFF_FFFF); if canonical(ret) { ret } else { LAddr::new(unsafe { ret.add(0xFFFF_0000_0000_0000) }) } } /// # Safety /// /// Invalid use of this function can cause CPU's unrecoverable fault. #[inline] pub unsafe fn halt() { asm!("hlt"); } /// # Safety /// /// Invalid use of this function can cause CPU unrecoverable fault. #[inline] pub unsafe fn pause_intr() -> u64 { let rflags = reg::rflags::read(); asm!("cli"); rflags } /// # Safety /// /// Invalid use of this function can cause CPU unrecoverable fault. #[inline] pub unsafe fn resume_intr(rflags: Option) { if rflags.map_or(true, |rflags| rflags.contains_bit(reg::rflags::IF)) { asm!("sti"); } } /// # Safety /// /// Invalid use of this function can cause CPU unrecoverable fault. #[inline(always)] pub unsafe fn halt_loop(intr_op: Option) -> ! { let f = match intr_op { Some(op) => { if op { || resume_intr(None) } else { || { pause_intr(); } } } None => || {}, }; loop { f(); halt(); } }