sparreal_kernel/globals/
mod.rs1#![allow(unused)]
2
3use core::{
4 cell::UnsafeCell,
5 ops::Range,
6 sync::atomic::{AtomicBool, Ordering},
7};
8
9use alloc::collections::btree_map::BTreeMap;
10use log::debug;
11
12pub use crate::platform::PlatformInfoKind;
13use crate::{
14 mem::{self, PhysAddr},
15 platform::{self, CPUHardId, CPUId, cpu_list, fdt::Fdt},
16};
17
18mod once;
19mod percpu;
20
21pub(crate) use percpu::*;
22
23pub struct GlobalVal {
24 pub platform_info: PlatformInfoKind,
25 pub main_memory: Range<PhysAddr>,
26 percpu: BTreeMap<CPUId, percpu::PerCPU>,
27}
28
29struct LazyGlobal {
30 g_ok: AtomicBool,
31 g: UnsafeCell<Option<GlobalVal>>,
32}
33
34unsafe impl Sync for LazyGlobal {}
35
36static GLOBAL: LazyGlobal = LazyGlobal::new();
37
38pub fn global_val() -> &'static GlobalVal {
39 global_val_meybeuninit().expect("GlobalVal is not init!")
40}
41
42pub fn global_val_meybeuninit() -> Option<&'static GlobalVal> {
43 if !GLOBAL.g_ok.load(Ordering::SeqCst) {
44 return None;
45 }
46 Some(unsafe { (*GLOBAL.g.get()).as_ref().unwrap() })
47}
48
49impl LazyGlobal {
50 const fn new() -> Self {
51 Self {
52 g_ok: AtomicBool::new(false),
53 g: UnsafeCell::new(None),
54 }
55 }
56}
57
58pub(crate) unsafe fn edit(f: impl FnOnce(&mut GlobalVal)) {
63 unsafe {
64 let global = (*GLOBAL.g.get()).as_mut().unwrap();
65 f(global);
66 }
67}
68
69unsafe fn get_mut() -> &'static mut GlobalVal {
70 unsafe { (*GLOBAL.g.get()).as_mut().unwrap() }
71}
72
73pub(crate) unsafe fn setup(platform_info: PlatformInfoKind) -> Result<(), &'static str> {
76 let main = crate::mem::find_main_memory().ok_or("can not find main memory")?;
77 let start = main.range.start.align_up(platform::page_size());
78 let range = start..main.range.end;
79 let g = GlobalVal {
80 platform_info,
81 main_memory: range,
82 percpu: Default::default(),
83 };
84
85 unsafe {
86 GLOBAL.g.get().write(Some(g));
87 GLOBAL.g_ok.store(true, Ordering::SeqCst);
88 }
89 Ok(())
90}