1#![no_std]
2#![cfg_attr(not(test), no_main)]
3#![cfg_attr(target_arch = "x86_64", feature(abi_x86_interrupt))]
4
5#[allow(unused_imports)]
6#[macro_use]
7extern crate alloc;
8
9#[macro_use]
10extern crate core;
11
12#[macro_use]
13extern crate log;
14
15#[macro_use]
16pub mod console;
17
18#[cfg(target_arch = "loongarch64")]
19#[path = "arch/loongarch64/mod.rs"]
20pub mod arch;
21
22#[cfg(target_arch = "aarch64")]
23#[path = "arch/aarch64/mod.rs"]
24pub mod arch;
25
26#[cfg(target_arch = "x86_64")]
27#[path = "arch/x86_64/mod.rs"]
28pub mod arch;
29
30#[cfg(target_arch = "riscv64")]
31#[path = "arch/riscv64/mod.rs"]
32pub mod arch;
33
34mod acpi;
35mod cmdline;
36pub(crate) mod consts;
37#[cfg(efi)]
38mod efi_stub;
39mod elf;
40mod entropy;
41mod entry;
42mod err;
43pub(crate) mod fdt;
44pub mod irq;
45pub mod mem;
46pub mod power;
47
48pub mod rtc;
49pub mod smp;
50pub mod timer;
51
52pub use acpi::rsdp_addr_phys;
53pub use cmdline::cmdline;
54pub use entropy::boot_entropy;
55pub use fdt::{fdt_addr, fdt_addr_phys, platform_name};
56pub use page_table_generic::*;
57pub use somehal_macros::{entry, someboot_secondary_entry as secondary_entry};
58
59use crate::{
60 irq::IrqId,
61 mem::{PageTableInfo, cpu_area_phys_to_virt},
62 power::CpuOnError,
63};
64
65#[allow(unused)]
66pub trait ArchTrait {
67 type P: TableMeta;
68 type Console: console::ArchConsoleOps;
69
70 fn _va(paddr: usize) -> *mut u8;
71 fn _io(paddr: usize) -> *mut u8 {
72 Self::_va(paddr)
73 }
74 fn ioremap_device(_addr: usize, _size: usize) -> Option<*mut u8> {
75 None
76 }
77 fn cpu_area_phys_to_virt(paddr: usize) -> *mut u8 {
78 Self::_va(paddr)
79 }
80
81 fn cpu_current_hartid() -> usize;
82
83 fn jump_to(entry: usize, sp: usize) -> !;
84
85 fn post_allocator();
86
87 fn init_boot_tls() {}
88
89 fn per_cpu_trap_init(is_primary: bool);
90 fn trap_addr() -> usize;
91
92 fn virt_to_phys(vaddr: *const u8) -> usize;
93
94 fn canonicalize_paddr(addr: usize) -> usize {
95 addr
96 }
97 fn user_aspace_needs_kernel_mappings() -> bool {
98 true
99 }
100
101 fn kernel_space() -> core::ops::Range<usize>;
102 fn is_kernel_relocated_at(addr: usize) -> bool {
103 (crate::consts::VM_LOAD_ADDRESS..usize::MAX).contains(&addr)
104 }
105
106 fn is_mmu_enabled() -> bool;
107
108 fn kernel_page_table() -> PageTableInfo;
109 fn set_kernel_page_table(val: PageTableInfo);
110 #[cfg(uspace)]
111 fn user_page_table() -> PageTableInfo;
112 #[cfg(uspace)]
113 fn set_user_page_table(val: PageTableInfo);
114
115 fn shutdown() -> !;
116 fn reset() -> ! {
117 Self::shutdown()
118 }
119 fn secondary_entry_fn_address() -> *const ();
120 fn kick_secondary_cpu(hartid: usize, entry: usize, arg: usize) -> Result<(), CpuOnError>;
126
127 fn systimer_freq() -> usize;
129 fn systimer_tick() -> usize;
131 fn systimer_stability() -> timer::CounterStability;
133
134 fn irq_all_is_enabled() -> bool;
135 fn irq_all_set_enable(enable: bool);
136
137 fn dcache_range(op: DCacheOp, addr: usize, size: usize);
138
139 fn dma_coherent_before_map_uncached(addr: usize, size: usize) {
141 Self::dcache_range(DCacheOp::CleanInvalidate, addr, size);
142 }
143
144 fn dma_coherent_before_unmap_uncached(_addr: usize, _size: usize) {}
146
147 fn dma_coherent_after_mapping_update() {}
149
150 unsafe fn efi_enter_kernel(_system_table: *const ::core::ffi::c_void) -> bool {
158 false
159 }
160}
161
162pub trait SystimerArch: ArchTrait {
177 fn systimer_irq_id() -> IrqId;
179 fn systimer_enable();
180 fn systimer_irq_enable();
181 fn systimer_irq_disable();
182 fn systimer_irq_is_enabled() -> bool;
183 fn systimer_set_interval(ticks: usize);
185
186 fn systimer_ack() {}
189
190 fn irq_is_enabled(irq: IrqId) -> bool {
193 irq == Self::systimer_irq_id() && Self::systimer_irq_is_enabled()
194 }
195
196 fn irq_set_enable(irq: IrqId, enable: bool) {
199 if irq == Self::systimer_irq_id() {
200 if enable {
201 Self::systimer_irq_enable();
202 } else {
203 Self::systimer_irq_disable();
204 }
205 }
206 }
207
208 fn set_next_event_in_ticks(ticks: usize) {
210 Self::systimer_set_interval(ticks);
211 }
212
213 fn set_next_event(interval: core::time::Duration) {
215 const NANOS_PER_SEC: u128 = 1_000_000_000;
216 let ticks = (interval.as_nanos() * Self::systimer_freq() as u128 / NANOS_PER_SEC) as usize;
217 Self::systimer_set_interval(ticks);
218 }
219}
220
221#[derive(Debug, Clone, Copy)]
222pub enum DCacheOp {
223 Clean,
224 Invalidate,
225 CleanInvalidate,
226}
227
228pub fn post_allocator() {
229 fdt::init_with_alloc();
230 smp::finalize_secondary_boot_metadata();
231 debug!("Setup after allocator");
232 arch::Arch::post_allocator();
233}
234
235pub fn bootargs() -> Option<&'static str> {
237 cmdline::cmdline()
238}
239
240pub fn kernel_page_table_paddr() -> usize {
242 arch::Arch::kernel_page_table().addr
243}
244
245pub fn set_kernel_page_table_paddr(paddr: usize) {
247 arch::Arch::set_kernel_page_table(PageTableInfo {
248 asid: 0,
249 addr: paddr,
250 });
251}
252
253#[cfg(uspace)]
254pub fn user_page_table() -> PageTableInfo {
255 arch::Arch::user_page_table()
256}
257
258#[cfg(uspace)]
259pub fn set_user_page_table(pt: PageTableInfo) {
260 arch::Arch::set_user_page_table(pt);
261}
262
263fn prime_entry() -> ! {
265 fdt::setup_earlycon();
266 let _ = acpi::earlycon::acpi_setup_earlycon();
267
268 println!("Trap vector at {:#x}", arch::Arch::trap_addr());
269
270 mem::memory_map_setup();
272 mem::print_memory_map();
273
274 smp::initialize_percpu_layout();
275
276 unsafe extern "C" {
277 fn __someboot_main() -> !;
278 }
279
280 let entry = __someboot_main as *const () as usize;
281 let cpu_idx = crate::smp::early_current_cpu_idx();
282 let sp = crate::smp::cpu_meta(cpu_idx).unwrap().stack_top;
283 let sp = cpu_area_phys_to_virt(sp);
284 println!(
285 "Jumping to main entry point at {:#x} with SP {:#p}",
286 entry, sp
287 );
288 arch::Arch::jump_to(entry, sp as _)
289}