#[macro_use]
mod _macros;
mod addrspace;
mod console;
pub(crate) mod entry;
mod head;
pub(crate) mod irq;
mod paging;
pub(crate) mod power;
pub(crate) mod relocate;
mod trap;
use core::ptr::null;
pub(crate) use entry::_secondary_entry;
pub use paging::Entry;
pub use relocate::relocate;
use crate::{
ArchTrait, DCacheOp,
mem::{PageTableInfo, mmu},
power::CpuOnError,
};
pub struct Arch;
impl ArchTrait for Arch {
type P = paging::Generic;
type Console = console::Console;
fn _va(paddr: usize) -> *mut u8 {
if mmu::is_mmu_enabled() {
paddr.wrapping_add(addrspace::PHYS_VIRT_OFFSET) as *mut u8
} else {
paddr as *mut u8
}
}
fn _io(paddr: usize) -> *mut u8 {
Self::_va(paddr)
}
fn _percpu(paddr: usize) -> *mut u8 {
(paddr + addrspace::PERCPU_BASE) as *mut u8
}
fn cpu_current_hartid() -> usize {
x86::cpuid::CpuId::new()
.get_feature_info()
.map(|info| info.initial_local_apic_id() as usize)
.unwrap_or(0)
}
fn jump_to(entry: usize, sp: usize) -> ! {
let sp = sp - core::mem::size_of::<usize>();
unsafe {
(sp as *mut usize).write(0);
}
unsafe {
core::arch::asm!(
"mov rsp, {sp}",
"xor rbp, rbp",
"jmp {entry}",
sp = in(reg) sp,
entry = in(reg) entry,
options(noreturn)
);
}
}
fn post_allocator() {}
fn per_cpu_trap_init(_is_primary: bool) {
trap::setup();
trap::init_local();
}
fn trap_addr() -> usize {
trap::trap_addr()
}
fn virt_to_phys(vaddr: *const u8) -> usize {
paging::virt_to_phys(vaddr)
}
fn kernel_space() -> core::ops::Range<usize> {
addrspace::KERNEL_SPACE_BASE..usize::MAX
}
fn kernel_page_table() -> PageTableInfo {
paging::current_table()
}
fn set_kernel_page_table(val: PageTableInfo) {
paging::set_table(val);
}
#[cfg(uspace)]
fn user_page_table() -> PageTableInfo {
PageTableInfo { asid: 0, addr: 0 }
}
#[cfg(uspace)]
fn set_user_page_table(_val: PageTableInfo) {}
fn shutdown() -> ! {
unsafe {
x86::irq::disable();
x86::io::outw(0x604, 0x2000);
x86::io::outw(0xb004, 0x2000);
}
loop {
unsafe { x86::halt() };
}
}
fn reset() -> ! {
unsafe {
x86::irq::disable();
x86::io::outb(0x64, 0xfe);
}
loop {
unsafe { x86::halt() };
}
}
fn secondary_entry_fn_address() -> *const () {
_secondary_entry as *const ()
}
fn cpu_on(hartid: usize, entry: usize, arg: usize) -> Result<(), CpuOnError> {
power::cpu_on(hartid, entry, arg)
}
fn systimer_enable() {
trap::timer_enable();
}
fn systimer_irq_enable() {
trap::timer_irq_enable();
}
fn systimer_irq_disable() {
trap::timer_irq_disable();
}
fn systimer_irq_is_enabled() -> bool {
trap::timer_irq_is_enabled()
}
fn systimer_set_interval(ticks: usize) {
trap::timer_set_deadline_in_ticks(ticks);
}
fn systimer_ack() {
trap::timer_ack();
}
fn systimer_freq() -> usize {
trap::tsc_freq()
}
fn systimer_tick() -> usize {
trap::ticks_now() as usize
}
fn irq_all_is_enabled() -> bool {
trap::irq_local_enabled()
}
fn irq_all_set_enable(enable: bool) {
trap::irq_local_set_enabled(enable);
}
fn irq_is_enabled(irq: crate::irq::IrqId) -> bool {
irq == irq::systimer_irq() && trap::timer_irq_is_enabled()
}
fn irq_set_enable(irq: crate::irq::IrqId, enable: bool) {
if irq == irq::systimer_irq() {
if enable {
trap::timer_irq_enable();
} else {
trap::timer_irq_disable();
}
}
}
fn dcache_range(_op: DCacheOp, _addr: usize, _size: usize) {
unsafe {
core::arch::asm!("mfence", options(nomem, nostack, preserves_flags));
}
}
unsafe fn efi_enter_kernel(system_table: *const ::core::ffi::c_void) -> bool {
crate::arch::entry::kernel_entry(1, null(), system_table)
}
}