mycelium_kernel/arch/x86_64/
acpi.rs1use acpi::{AcpiError, AcpiHandler, AcpiTables};
2use core::fmt;
3use hal_core::{Address, PAddr};
4use hal_x86_64::mm;
5
6#[derive(Debug)]
7pub enum Error {
8 Acpi(AcpiError),
9 Other(&'static str),
10}
11
12pub(super) fn acpi_tables(
13 rsdp_addr: PAddr,
14) -> Result<AcpiTables<IdentityMappedAcpiHandler>, AcpiError> {
15 tracing::info!("trying to parse ACPI tables from RSDP...");
16 let tables = unsafe { AcpiTables::from_rsdp(IdentityMappedAcpiHandler, rsdp_addr.as_usize()) }?;
17 tracing::info!("found ACPI tables!");
18 Ok(tables)
19}
20
21#[tracing::instrument(err, skip(platform))]
22pub fn bringup_smp(platform: &acpi::PlatformInfo) -> Result<(), Error> {
23 use acpi::platform::{self, interrupt::InterruptModel};
24
25 tracing::info!(?platform.power_profile);
26
27 let apic = match platform.interrupt_model {
28 acpi::InterruptModel::Apic(ref apic) => {
29 tracing::info!("APIC interrupt model detected");
30 apic
31 }
32 InterruptModel::Unknown => {
33 return Err(Error::Other(
34 "MADT does not indicate support for APIC interrupt model!",
35 ));
36 }
37 ref model => {
38 tracing::warn!(?model, "unknown interrupt model detected");
39 return Err(Error::Other(
40 "MADT does not indicate support for APIC interrupt model!",
41 ));
42 }
43 };
44
45 tracing::debug!(?apic);
46
47 let platform::ProcessorInfo {
48 ref application_processors,
49 ref boot_processor,
50 } = platform
51 .processor_info
52 .as_ref()
53 .ok_or(Error::Other("no processor information found in MADT!"))?;
54 tracing::info!("boot processor seems normalish");
55 tracing::debug!(?boot_processor);
56 tracing::info!(
57 "found {} application processors",
58 application_processors.len()
59 );
60 tracing::debug!(?application_processors);
61 tracing::warn!("not starting app processors (SMP support isn't done yet)");
62
63 Ok(())
64}
65
66#[derive(Clone)]
67pub(super) struct IdentityMappedAcpiHandler;
68
69impl AcpiHandler for IdentityMappedAcpiHandler {
70 unsafe fn map_physical_region<T>(
71 &self,
72 physical_address: usize,
73 size: usize,
74 ) -> acpi::PhysicalMapping<Self, T> {
75 let paddr = PAddr::from_u64(physical_address as u64);
76 let vaddr = mm::kernel_vaddr_of(paddr);
77 let vptr = vaddr
78 .as_non_null()
79 .expect("virtual address for ACPI region is not null");
80 acpi::PhysicalMapping::new(physical_address, vptr, size, size, Self)
84 }
85
86 fn unmap_physical_region<T>(_region: &acpi::PhysicalMapping<Self, T>) {
87 }
89}
90
91impl From<AcpiError> for Error {
94 fn from(inner: AcpiError) -> Self {
95 Self::Acpi(inner)
96 }
97}
98
99impl fmt::Display for Error {
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 match self {
102 Self::Acpi(inner) => write!(f, "ACPI error: {inner:?}"),
107 Self::Other(msg) => fmt::Display::fmt(msg, f),
108 }
109 }
110}