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;
11use percpu::PerCPU;
12use platform::CpuId;
13
14pub use crate::platform::PlatformInfoKind;
15use crate::{
16 mem::PhysAddr,
17 platform::{self, cpu_list},
18};
19
20mod percpu;
21
22pub struct GlobalVal {
23 pub platform_info: PlatformInfoKind,
24 pub kstack_top: PhysAddr,
25 pub main_memory: Range<PhysAddr>,
26 percpu: BTreeMap<CpuId, percpu::PerCPU>,
27}
28
29struct LazyGlobal {
30 g_ok: AtomicBool,
31 cpu_ok: AtomicBool,
32 g: UnsafeCell<Option<GlobalVal>>,
33}
34
35unsafe impl Sync for LazyGlobal {}
36
37static GLOBAL: LazyGlobal = LazyGlobal::new();
38
39pub fn global_val() -> &'static GlobalVal {
40 global_val_meybeuninit().expect("GlobalVal is not init!")
41}
42
43pub fn global_val_meybeuninit() -> Option<&'static GlobalVal> {
44 if !GLOBAL.g_ok.load(Ordering::SeqCst) {
45 return None;
46 }
47 Some(unsafe { (*GLOBAL.g.get()).as_ref().unwrap() })
48}
49
50impl LazyGlobal {
51 const fn new() -> Self {
52 Self {
53 g_ok: AtomicBool::new(false),
54 cpu_ok: AtomicBool::new(false),
55 g: UnsafeCell::new(None),
56 }
57 }
58}
59
60pub(crate) unsafe fn edit(f: impl FnOnce(&mut GlobalVal)) {
65 unsafe {
66 let global = (*GLOBAL.g.get()).as_mut().unwrap();
67 f(global);
68 }
69}
70
71unsafe fn get_mut() -> &'static mut GlobalVal {
72 unsafe { (*GLOBAL.g.get()).as_mut().unwrap() }
73}
74
75pub(crate) unsafe fn setup(platform_info: PlatformInfoKind) -> Result<(), &'static str> {
78 let main_memory = platform_info
79 .main_memory()
80 .ok_or("No memory in platform info")?;
81
82 let g = GlobalVal {
83 platform_info,
84 kstack_top: main_memory.end,
85 main_memory,
86 percpu: Default::default(),
87 };
88
89 unsafe {
90 GLOBAL.g.get().write(Some(g));
91 GLOBAL.g_ok.store(true, Ordering::SeqCst);
92
93 match &mut get_mut().platform_info {
94 PlatformInfoKind::DeviceTree(fdt) => {
95 fdt.setup()?;
96 }
97 }
98 }
99 Ok(())
100}
101
102pub(crate) unsafe fn setup_percpu() {
105 let cpus = cpu_list();
106 let g = unsafe { get_mut() };
107 for cpu in cpus {
108 let percpu = PerCPU::default();
109 g.percpu.insert(cpu.cpu_id, percpu);
110 }
111 GLOBAL.cpu_ok.store(true, Ordering::SeqCst);
112
113 debug!("per cpu data ok");
114}
115
116pub(crate) fn cpu_global() -> &'static PerCPU {
117 cpu_global_meybeuninit().expect("CPU global is not init!")
118}
119
120pub(crate) fn cpu_global_meybeuninit() -> Option<&'static PerCPU> {
121 if !GLOBAL.cpu_ok.load(Ordering::SeqCst) {
122 return None;
123 }
124
125 let g = unsafe { get_mut() };
126 Some(g.percpu.get(&platform::cpu_id()).unwrap())
127}
128
129pub(crate) unsafe fn cpu_global_mut() -> &'static mut PerCPU {
130 unsafe { cpu_global_mut_meybeunint().expect("CPU global is not init!") }
131}
132
133pub(crate) unsafe fn cpu_global_mut_meybeunint() -> Option<&'static mut PerCPU> {
134 if !GLOBAL.cpu_ok.load(Ordering::SeqCst) {
135 return None;
136 }
137
138 let g = unsafe { get_mut() };
139 Some(g.percpu.get_mut(&platform::cpu_id()).unwrap())
140}