xref: /DragonOS/kernel/src/driver/acpi/mod.rs (revision 59a6bcf6aee15a11a16431bdf875905c5ecf9157)
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)]
acpi_manager() -> &'static AcpiManager35 pub fn acpi_manager() -> &'static AcpiManager {
36     &AcpiManager
37 }
38 
39 #[inline(always)]
acpi_kset() -> Arc<KSet>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
init(&self) -> Result<(), SystemError>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 
map_tables(&self, acpi_args: BootloaderAcpiArg) -> Result<(), SystemError>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             BootloaderAcpiArg::Rsdp(rsdp) => rsdp,
85             _ => {
86                 error!(
87                     "AcpiManager::map_tables(): unsupported acpi_args: {:?}",
88                     acpi_args
89                 );
90                 return Err(SystemError::ENODEV);
91             }
92         };
93         let res = unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, table_paddr.data()) };
94         match res {
95             Ok(acpi_table) => {
96                 Self::set_acpi_table(acpi_table);
97                 return Ok(());
98             }
99             Err(e) => {
100                 error!(
101                     "AcpiManager::map_tables(): failed to map tables, error: {:?}",
102                     e
103                 );
104                 Self::drop_rsdp_tmp_box();
105                 return Err(SystemError::ENODEV);
106             }
107         }
108     }
109 
110     /// 通过RSDP虚拟地址获取RSDP物理地址
111     ///
112     /// ## 参数
113     ///
114     /// - `rsdp_vaddr`: RSDP的虚拟地址
115     ///
116     /// ## 返回值
117     ///
118     /// RSDP物理地址
rsdp_paddr(rsdp_instance: &acpi::rsdp::Rsdp) -> PhysAddr119     fn rsdp_paddr(rsdp_instance: &acpi::rsdp::Rsdp) -> PhysAddr {
120         unsafe {
121             RSDP_TMP_BOX = Some(AlignedBox::new_zeroed().expect("rs_acpi_init(): failed to alloc"))
122         };
123 
124         let size = core::mem::size_of::<acpi::rsdp::Rsdp>();
125         let tmp_data = unsafe {
126             core::slice::from_raw_parts(
127                 rsdp_instance as *const acpi::rsdp::Rsdp as usize as *const u8,
128                 size,
129             )
130         };
131         unsafe { RSDP_TMP_BOX.as_mut().unwrap()[0..size].copy_from_slice(tmp_data) };
132         let rsdp_paddr = unsafe {
133             MMArch::virt_2_phys(VirtAddr::new(
134                 RSDP_TMP_BOX.as_ref().unwrap().as_ptr() as usize
135             ))
136             .unwrap()
137         };
138 
139         return rsdp_paddr;
140     }
141 
set_acpi_table(acpi_table: AcpiTables<AcpiHandlerImpl>)142     fn set_acpi_table(acpi_table: AcpiTables<AcpiHandlerImpl>) {
143         unsafe {
144             __ACPI_TABLE = Some(acpi_table);
145         }
146     }
147 
drop_rsdp_tmp_box()148     fn drop_rsdp_tmp_box() {
149         unsafe {
150             RSDP_TMP_BOX = None;
151         }
152     }
153 
154     #[allow(dead_code)]
tables(&self) -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>>155     pub fn tables(&self) -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>> {
156         unsafe { __ACPI_TABLE.as_ref() }
157     }
158 
159     /// 从acpi获取平台的信息
160     ///
161     /// 包括:
162     ///
163     /// - PowerProfile
164     /// - InterruptModel
165     /// - ProcessorInfo
166     /// - PmTimer
platform_info(&self) -> Option<PlatformInfo<'_, alloc::alloc::Global>>167     pub fn platform_info(&self) -> Option<PlatformInfo<'_, alloc::alloc::Global>> {
168         let r = self.tables()?.platform_info();
169         if let Err(ref e) = r {
170             error!(
171                 "AcpiManager::platform_info(): failed to get platform info, error: {:?}",
172                 e
173             );
174             return None;
175         }
176 
177         return Some(r.unwrap());
178     }
179 }
180 
181 #[derive(Debug, Clone, Copy)]
182 pub struct AcpiHandlerImpl;
183 
184 impl AcpiHandler for AcpiHandlerImpl {
map_physical_region<T>( &self, physical_address: usize, size: usize, ) -> acpi::PhysicalMapping<Self, T>185     unsafe fn map_physical_region<T>(
186         &self,
187         physical_address: usize,
188         size: usize,
189     ) -> acpi::PhysicalMapping<Self, T> {
190         let offset = physical_address - page_align_down(physical_address);
191         let size_fix = page_align_up(size + offset);
192 
193         let mmio_guard = mmio_pool()
194             .create_mmio(size_fix)
195             .expect("AcpiHandlerImpl::map_physical_region(): failed to create mmio");
196 
197         mmio_guard
198             .map_phys(PhysAddr::new(page_align_down(physical_address)), size_fix)
199             .expect("AcpiHandlerImpl::map_physical_region(): failed to map phys");
200         let virtual_start = mmio_guard.vaddr().data() + offset;
201 
202         let virtual_start = NonNull::new(virtual_start as *mut T).unwrap();
203 
204         let result: acpi::PhysicalMapping<AcpiHandlerImpl, T> = acpi::PhysicalMapping::new(
205             physical_address,
206             virtual_start,
207             size,
208             mmio_guard.size(),
209             AcpiHandlerImpl,
210         );
211 
212         MMIOSpaceGuard::leak(mmio_guard);
213 
214         return result;
215     }
216 
unmap_physical_region<T>(region: &acpi::PhysicalMapping<Self, T>)217     fn unmap_physical_region<T>(region: &acpi::PhysicalMapping<Self, T>) {
218         let mmio_guard = unsafe {
219             MMIOSpaceGuard::from_raw(
220                 VirtAddr::new(page_align_down(
221                     region.virtual_start().as_ref() as *const T as usize
222                 )),
223                 region.mapped_length(),
224                 true,
225             )
226         };
227         drop(mmio_guard);
228     }
229 }
230 
231 #[inline(never)]
acpi_init() -> Result<(), SystemError>232 pub fn acpi_init() -> Result<(), SystemError> {
233     #[cfg(target_arch = "x86_64")]
234     {
235         acpi_manager().init()
236     }
237 
238     #[cfg(not(target_arch = "x86_64"))]
239     {
240         log::warn!("acpi_init(): unsupported arch");
241         return Ok(());
242     }
243 }
244