zodiac 0.1.0

Rust OS framework that offers safe interfaces for kernel development
Documentation
use alloc::collections::BTreeMap;
use limine::request::MpRequest;
use spin::{Lazy, RwLock};

use crate::hal::cpu::Cpu;

use super::ap_entry;
use super::trap::gdt::CpuInfo;

#[used]
#[unsafe(link_section = ".requests")]
pub(super) static MP_REQUEST: MpRequest = MpRequest::new();

pub static BSP_LAPIC_ID: Lazy<u32> =
    Lazy::new(|| MP_REQUEST.get_response().unwrap().bsp_lapic_id());

pub static CPUS: Lazy<Cpus> = Lazy::new(Cpus::default);

pub struct Cpus(RwLock<BTreeMap<Cpu, CpuInfo>>);

impl Default for Cpus {
    fn default() -> Self {
        let mut cpus = BTreeMap::new();
        cpus.insert(Cpu::bsp(), CpuInfo::default());
        Cpus(RwLock::new(cpus))
    }
}

impl Cpus {
    pub fn len(&self) -> usize {
        self.0.read().len()
    }
}

impl Cpus {
    pub fn load(&self, cpu: Cpu) {
        let mut inner = self.0.write();
        let cpu_info = inner.get_mut(&cpu).unwrap();
        cpu_info.init();
    }

    pub fn add_cpu(&self, cpu: Cpu) {
        let cpu_info = CpuInfo::default();
        self.0.write().insert(cpu, cpu_info);
    }

    pub fn init_ap(&self) {
        let response = MP_REQUEST.get_response().unwrap();

        for cpu in response.cpus() {
            if cpu.lapic_id != *BSP_LAPIC_ID {
                self.add_cpu(Cpu::new(cpu.lapic_id));
                cpu.goto_address.write(ap_entry);
            }
        }
    }

    pub fn with_cpu_info<F>(&self, cpu: Cpu, f: F)
    where
        F: FnOnce(&CpuInfo),
    {
        let inner = self.0.read();
        let cpu_info = inner.get(&cpu).unwrap();
        f(cpu_info);
    }

    pub fn with_cpu_info_mut<F>(&self, cpu: Cpu, f: F)
    where
        F: FnOnce(&mut CpuInfo),
    {
        let mut inner = self.0.write();
        let cpu_info = inner.get_mut(&cpu).unwrap();
        f(cpu_info);
    }
}