xref: /DragonOS/kernel/src/driver/acpi/mod.rs (revision 886ce28516f9e3e5940840d1ae64ec3e9c8875fa)
1 use core::{fmt::Debug, ptr::NonNull};
2 
3 use acpi::{AcpiHandler, AcpiTables, PlatformInfo};
4 use alloc::{string::ToString, sync::Arc};
5 use log::{error, info};
6 
7 use crate::{
8     arch::MMArch,
9     driver::base::firmware::sys_firmware_kset,
10     init::{boot::BootloaderAcpiArg, boot_params},
11     libs::align::{page_align_down, page_align_up, AlignedBox},
12     mm::{
13         mmio_buddy::{mmio_pool, MMIOSpaceGuard},
14         MemoryManagementArch, PhysAddr, VirtAddr,
15     },
16 };
17 use system_error::SystemError;
18 
19 use super::base::kset::KSet;
20 
21 extern crate acpi;
22 
23 pub mod bus;
24 pub mod glue;
25 pub mod pmtmr;
26 mod sysfs;
27 
28 static mut __ACPI_TABLE: Option<acpi::AcpiTables<AcpiHandlerImpl>> = None;
29 /// `/sys/firmware/acpi`的kset
30 static mut ACPI_KSET_INSTANCE: Option<Arc<KSet>> = None;
31 
32 static mut RSDP_TMP_BOX: Option<AlignedBox<[u8; 4096], 4096>> = None;
33 
34 #[inline(always)]
35 pub fn acpi_manager() -> &'static AcpiManager {
36     &AcpiManager
37 }
38 
39 #[inline(always)]
40 pub fn acpi_kset() -> Arc<KSet> {
41     unsafe { ACPI_KSET_INSTANCE.clone().unwrap() }
42 }
43 
44 #[derive(Debug)]
45 pub struct AcpiManager;
46 
47 impl AcpiManager {
48     /// 初始化ACPI
49     ///
50     /// ## 参数
51     ///
52     /// - `rsdp_vaddr1`: RSDP(v1)的虚拟地址
53     /// - `rsdp_vaddr2`: RSDP(v2)的虚拟地址
54     ///
55     ///
56     /// ## 参考资料
57     ///
58     /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1390
59     fn init(&self) -> Result<(), SystemError> {
60         info!("Initializing Acpi Manager...");
61 
62         // 初始化`/sys/firmware/acpi`的kset
63         let kset = KSet::new("acpi".to_string());
64         kset.register(Some(sys_firmware_kset()))?;
65         unsafe {
66             ACPI_KSET_INSTANCE = Some(kset.clone());
67         }
68         let acpi_args = boot_params().read().acpi;
69         if let BootloaderAcpiArg::NotProvided = acpi_args {
70             error!("acpi_init(): ACPI not provided by bootloader");
71             return Err(SystemError::ENODEV);
72         }
73 
74         self.map_tables(acpi_args)?;
75         self.bus_init()?;
76         info!("Acpi Manager initialized.");
77         return Ok(());
78     }
79 
80     fn map_tables(&self, acpi_args: BootloaderAcpiArg) -> Result<(), SystemError> {
81         let table_paddr: PhysAddr = match acpi_args {
82             BootloaderAcpiArg::Rsdt(rsdpv1) => Self::rsdp_paddr(&rsdpv1),
83             BootloaderAcpiArg::Xsdt(rsdpv2) => Self::rsdp_paddr(&rsdpv2),
84             _ => {
85                 error!(
86                     "AcpiManager::map_tables(): unsupported acpi_args: {:?}",
87                     acpi_args
88                 );
89                 return Err(SystemError::ENODEV);
90             }
91         };
92         let res = unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, table_paddr.data()) };
93         match res {
94             Ok(acpi_table) => {
95                 Self::set_acpi_table(acpi_table);
96                 return Ok(());
97             }
98             Err(e) => {
99                 error!(
100                     "AcpiManager::map_tables(): failed to map tables, error: {:?}",
101                     e
102                 );
103                 Self::drop_rsdp_tmp_box();
104                 return Err(SystemError::ENODEV);
105             }
106         }
107     }
108 
109     /// 通过RSDP虚拟地址获取RSDP物理地址
110     ///
111     /// ## 参数
112     ///
113     /// - `rsdp_vaddr`: RSDP的虚拟地址
114     ///
115     /// ## 返回值
116     ///
117     /// RSDP物理地址
118     fn rsdp_paddr(rsdp_instance: &acpi::rsdp::Rsdp) -> PhysAddr {
119         unsafe {
120             RSDP_TMP_BOX = Some(AlignedBox::new_zeroed().expect("rs_acpi_init(): failed to alloc"))
121         };
122 
123         let size = core::mem::size_of::<acpi::rsdp::Rsdp>();
124         let tmp_data = unsafe {
125             core::slice::from_raw_parts(
126                 rsdp_instance as *const acpi::rsdp::Rsdp as usize as *const u8,
127                 size,
128             )
129         };
130         unsafe { RSDP_TMP_BOX.as_mut().unwrap()[0..size].copy_from_slice(tmp_data) };
131         let rsdp_paddr = unsafe {
132             MMArch::virt_2_phys(VirtAddr::new(
133                 RSDP_TMP_BOX.as_ref().unwrap().as_ptr() as usize
134             ))
135             .unwrap()
136         };
137 
138         return rsdp_paddr;
139     }
140 
141     fn set_acpi_table(acpi_table: AcpiTables<AcpiHandlerImpl>) {
142         unsafe {
143             __ACPI_TABLE = Some(acpi_table);
144         }
145     }
146 
147     fn drop_rsdp_tmp_box() {
148         unsafe {
149             RSDP_TMP_BOX = None;
150         }
151     }
152 
153     #[allow(dead_code)]
154     pub fn tables(&self) -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>> {
155         unsafe { __ACPI_TABLE.as_ref() }
156     }
157 
158     /// 从acpi获取平台的信息
159     ///
160     /// 包括:
161     ///
162     /// - PowerProfile
163     /// - InterruptModel
164     /// - ProcessorInfo
165     /// - PmTimer
166     pub fn platform_info(&self) -> Option<PlatformInfo<'_, alloc::alloc::Global>> {
167         let r = self.tables()?.platform_info();
168         if let Err(ref e) = r {
169             error!(
170                 "AcpiManager::platform_info(): failed to get platform info, error: {:?}",
171                 e
172             );
173             return None;
174         }
175 
176         return Some(r.unwrap());
177     }
178 }
179 
180 #[derive(Debug, Clone, Copy)]
181 pub struct AcpiHandlerImpl;
182 
183 impl AcpiHandler for AcpiHandlerImpl {
184     unsafe fn map_physical_region<T>(
185         &self,
186         physical_address: usize,
187         size: usize,
188     ) -> acpi::PhysicalMapping<Self, T> {
189         let offset = physical_address - page_align_down(physical_address);
190         let size_fix = page_align_up(size + offset);
191 
192         let mmio_guard = mmio_pool()
193             .create_mmio(size_fix)
194             .expect("AcpiHandlerImpl::map_physical_region(): failed to create mmio");
195 
196         mmio_guard
197             .map_phys(PhysAddr::new(page_align_down(physical_address)), size_fix)
198             .expect("AcpiHandlerImpl::map_physical_region(): failed to map phys");
199         let virtual_start = mmio_guard.vaddr().data() + offset;
200 
201         let virtual_start = NonNull::new(virtual_start as *mut T).unwrap();
202 
203         let result: acpi::PhysicalMapping<AcpiHandlerImpl, T> = acpi::PhysicalMapping::new(
204             physical_address,
205             virtual_start,
206             size,
207             mmio_guard.size(),
208             AcpiHandlerImpl,
209         );
210 
211         MMIOSpaceGuard::leak(mmio_guard);
212 
213         return result;
214     }
215 
216     fn unmap_physical_region<T>(region: &acpi::PhysicalMapping<Self, T>) {
217         let mmio_guard = unsafe {
218             MMIOSpaceGuard::from_raw(
219                 VirtAddr::new(page_align_down(
220                     region.virtual_start().as_ref() as *const T as usize
221                 )),
222                 region.mapped_length(),
223                 true,
224             )
225         };
226         drop(mmio_guard);
227     }
228 }
229 
230 #[inline(never)]
231 pub fn acpi_init() -> Result<(), SystemError> {
232     #[cfg(target_arch = "x86_64")]
233     {
234         acpi_manager().init()
235     }
236 
237     #[cfg(not(target_arch = "x86_64"))]
238     {
239         log::warn!("acpi_init(): unsupported arch");
240         return Ok(());
241     }
242 }
243