瀏覽代碼

refactor(driver/acpi): 重构ACPI表读取逻辑并优化栈内存使用 (#1178)

重构了ACPI表读取逻辑,使用宏定义表结构体并拆分读取函数以减少栈内存使用。

Signed-off-by: longjin <longjin@DragonOS.org>
LoGin 3 天之前
父節點
當前提交
1032474cbf
共有 1 個文件被更改,包括 209 次插入163 次删除
  1. 209 163
      kernel/src/driver/acpi/sysfs.rs

+ 209 - 163
kernel/src/driver/acpi/sysfs.rs

@@ -23,6 +23,41 @@ use system_error::SystemError;
 
 use super::{acpi_kset, AcpiManager};
 
+// 定义所有ACPI表结构体
+macro_rules! define_acpi_tables {
+    ($($name:ident),*) => {
+        $(
+            #[repr(transparent)]
+            #[allow(non_snake_case)]
+            #[allow(non_camel_case_types)]
+            struct $name {
+                header: SdtHeader,
+            }
+
+            unsafe impl acpi::AcpiTable for $name {
+                const SIGNATURE: acpi::sdt::Signature = acpi::sdt::Signature::$name;
+                fn header(&self) -> &acpi::sdt::SdtHeader {
+                    return &self.header;
+                }
+            }
+        )*
+    };
+}
+
+define_acpi_tables!(
+    RSDT, XSDT, FADT, HPET, MADT, MCFG, SSDT, BERT, BGRT, CPEP, DSDT, ECDT, EINJ, ERST, FACS, FPDT,
+    GTDT, HEST, MSCT, MPST, NFIT, PCCT, PHAT, PMTT, PSDT, RASF, SBST, SDEV, SLIT, SRAT, AEST, BDAT,
+    CDIT, CEDT, CRAT, CSRT, DBGP, DBG2, DMAR, DRTM, ETDT, IBFT, IORT, IVRS, LPIT, MCHI, MPAM, MSDM,
+    PRMT, RGRT, SDEI, SLIC, SPCR, SPMI, STAO, SVKL, TCPA, TPM2, UEFI, WAET, WDAT, WDRT, WPBT, WSMT,
+    XENV
+);
+
+macro_rules! handle_read_table {
+    ($name: ident, $name_str: expr, $tables: expr, $buf: expr, $offset: expr) => {{
+        AttrAcpiTable::do_binattr_read_table::<$name>($tables, $name_str, $buf, $offset)
+    }};
+}
+
 static mut __HOTPLUG_KSET_INSTANCE: Option<Arc<KSet>> = None;
 static mut __ACPI_TABLES_KSET_INSTANCE: Option<Arc<KSet>> = None;
 static mut __ACPI_TABLES_DATA_KSET_INSTANCE: Option<Arc<KSet>> = None;
@@ -202,308 +237,319 @@ impl AttrAcpiTable {
         )?;
         return Ok(result);
     }
-}
-
-impl Attribute for AttrAcpiTable {
-    fn show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
-        return Err(SystemError::ENOSYS);
-    }
-
-    fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
-        return Err(SystemError::ENOSYS);
-    }
 
-    fn name(&self) -> &str {
-        return &self.filename;
-    }
-
-    fn mode(&self) -> ModeType {
-        return ModeType::from_bits_truncate(0o400);
-    }
-
-    fn support(&self) -> SysFSOpsSupport {
-        return SysFSOpsSupport::empty();
-    }
-}
-
-impl BinAttribute for AttrAcpiTable {
-    fn support_battr(&self) -> SysFSOpsSupport {
-        return SysFSOpsSupport::BATTR_READ;
-    }
-    fn write(
-        &self,
-        _kobj: Arc<dyn KObject>,
-        _buf: &[u8],
-        _offset: usize,
+    #[inline(never)]
+    fn do_binattr_read_table<T: acpi::AcpiTable>(
+        tables: &'static acpi::AcpiTables<crate::driver::acpi::AcpiHandlerImpl>,
+        name: &str,
+        buf: &mut [u8],
+        offset: usize,
     ) -> Result<usize, SystemError> {
-        return Err(SystemError::ENOSYS);
+        let table = tables.find_entire_table::<T>().map_err(|e| {
+            warn!(
+                "AttrAcpiTable::read(): failed to find table. name: {}, error: {:?}",
+                name, e
+            );
+            SystemError::ENODEV
+        })?;
+
+        let from = unsafe {
+            core::slice::from_raw_parts(
+                table.virtual_start().as_ptr() as *const u8,
+                table.region_length(),
+            )
+        };
+        if offset >= from.len() {
+            return Ok(0);
+        }
+        let mut count = buf.len();
+        if count > from.len() - offset {
+            count = from.len() - offset;
+        }
+        buf[0..count].copy_from_slice(&from[offset..offset + count]);
+        return Ok(count);
     }
 
-    /// 展示 ACPI 表的内容
-    ///
-    /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/acpi/sysfs.c?fi=acpi_sysfs_init#320
-    fn read(
+    #[inline(never)]
+    fn do_binattr_read_1(
         &self,
-        _kobj: Arc<dyn KObject>,
+        tables: &'static acpi::AcpiTables<crate::driver::acpi::AcpiHandlerImpl>,
+        name_str: &str,
         buf: &mut [u8],
         offset: usize,
     ) -> Result<usize, SystemError> {
-        macro_rules! copy_data {
-            ($table:expr) => {
-                let from = unsafe {
-                    core::slice::from_raw_parts(
-                        $table.virtual_start().as_ptr() as *const u8,
-                        $table.region_length(),
-                    )
-                };
-                if offset >= from.len() {
-                    return Ok(0);
-                }
-                let mut count = buf.len();
-                if count > from.len() - offset {
-                    count = from.len() - offset;
-                }
-                buf[0..count].copy_from_slice(&from[offset..offset + count]);
-                return Ok(count);
-            };
-        }
-
-        macro_rules! define_struct {
-            ($name:ident) => {
-                #[repr(transparent)]
-                #[allow(non_snake_case)]
-                #[allow(non_camel_case_types)]
-                struct $name {
-                    header: SdtHeader,
-                }
-
-                unsafe impl acpi::AcpiTable for $name {
-                    const SIGNATURE: acpi::sdt::Signature = acpi::sdt::Signature::$name;
-                    fn header(&self) -> &acpi::sdt::SdtHeader {
-                        return &self.header;
-                    }
-                }
-            };
-        }
-
-        macro_rules! handle {
-            ($name: ident, $tables: expr) => {
-                define_struct!($name);
-                let table = $tables.find_entire_table::<$name>().map_err(|e| {
-                    warn!(
-                        "AttrAcpiTable::read(): failed to find table. name: {}, error: {:?}",
-                        self.name, e
-                    );
-                    SystemError::ENODEV
-                })?;
-
-                copy_data!(table);
-            };
-        }
-
-        let tables = acpi_manager().tables().unwrap();
-        match self.name.as_str() {
+        match name_str {
             "RSDT" => {
-                handle!(RSDT, tables);
+                handle_read_table!(RSDT, name_str, tables, buf, offset)
             }
             "XSDT" => {
-                handle!(XSDT, tables);
+                handle_read_table!(XSDT, name_str, tables, buf, offset)
             }
             "FACP" => {
-                handle!(FADT, tables);
+                handle_read_table!(FADT, name_str, tables, buf, offset)
             }
             "HPET" => {
-                handle!(HPET, tables);
+                handle_read_table!(HPET, name_str, tables, buf, offset)
             }
             "APIC" => {
-                handle!(MADT, tables);
+                handle_read_table!(MADT, name_str, tables, buf, offset)
             }
             "MCFG" => {
-                handle!(MCFG, tables);
+                handle_read_table!(MCFG, name_str, tables, buf, offset)
             }
             "SSDT" => {
-                handle!(SSDT, tables);
+                handle_read_table!(SSDT, name_str, tables, buf, offset)
             }
             "BERT" => {
-                handle!(BERT, tables);
+                handle_read_table!(BERT, name_str, tables, buf, offset)
             }
             "BGRT" => {
-                handle!(BGRT, tables);
+                handle_read_table!(BGRT, name_str, tables, buf, offset)
             }
             "CPEP" => {
-                handle!(CPEP, tables);
+                handle_read_table!(CPEP, name_str, tables, buf, offset)
             }
             "DSDT" => {
-                handle!(DSDT, tables);
+                handle_read_table!(DSDT, name_str, tables, buf, offset)
             }
             "ECDT" => {
-                handle!(ECDT, tables);
+                handle_read_table!(ECDT, name_str, tables, buf, offset)
             }
             "EINJ" => {
-                handle!(EINJ, tables);
+                handle_read_table!(EINJ, name_str, tables, buf, offset)
             }
             "ERST" => {
-                handle!(ERST, tables);
+                handle_read_table!(ERST, name_str, tables, buf, offset)
             }
             "FACS" => {
-                handle!(FACS, tables);
+                handle_read_table!(FACS, name_str, tables, buf, offset)
             }
             "FPDT" => {
-                handle!(FPDT, tables);
+                handle_read_table!(FPDT, name_str, tables, buf, offset)
             }
             "GTDT" => {
-                handle!(GTDT, tables);
+                handle_read_table!(GTDT, name_str, tables, buf, offset)
             }
             "HEST" => {
-                handle!(HEST, tables);
+                handle_read_table!(HEST, name_str, tables, buf, offset)
             }
+
+            _ => Err(SystemError::ENODEV),
+        }
+    }
+
+    #[inline(never)]
+    fn do_binattr_read_2(
+        &self,
+        tables: &'static acpi::AcpiTables<crate::driver::acpi::AcpiHandlerImpl>,
+        name_str: &str,
+        buf: &mut [u8],
+        offset: usize,
+    ) -> Result<usize, SystemError> {
+        match name_str {
             "MSCT" => {
-                handle!(MSCT, tables);
+                handle_read_table!(MSCT, name_str, tables, buf, offset)
             }
             "MPST" => {
-                handle!(MPST, tables);
+                handle_read_table!(MPST, name_str, tables, buf, offset)
             }
             "NFIT" => {
-                handle!(NFIT, tables);
+                handle_read_table!(NFIT, name_str, tables, buf, offset)
             }
             "PCCT" => {
-                handle!(PCCT, tables);
+                handle_read_table!(PCCT, name_str, tables, buf, offset)
             }
             "PHAT" => {
-                handle!(PHAT, tables);
+                handle_read_table!(PHAT, name_str, tables, buf, offset)
             }
             "PMTT" => {
-                handle!(PMTT, tables);
+                handle_read_table!(PMTT, name_str, tables, buf, offset)
             }
             "PSDT" => {
-                handle!(PSDT, tables);
+                handle_read_table!(PSDT, name_str, tables, buf, offset)
             }
             "RASF" => {
-                handle!(RASF, tables);
+                handle_read_table!(RASF, name_str, tables, buf, offset)
             }
             "SBST" => {
-                handle!(SBST, tables);
+                handle_read_table!(SBST, name_str, tables, buf, offset)
             }
             "SDEV" => {
-                handle!(SDEV, tables);
+                handle_read_table!(SDEV, name_str, tables, buf, offset)
             }
             "SLIT" => {
-                handle!(SLIT, tables);
+                handle_read_table!(SLIT, name_str, tables, buf, offset)
             }
             "SRAT" => {
-                handle!(SRAT, tables);
+                handle_read_table!(SRAT, name_str, tables, buf, offset)
             }
             "AEST" => {
-                handle!(AEST, tables);
+                handle_read_table!(AEST, name_str, tables, buf, offset)
             }
             "BDAT" => {
-                handle!(BDAT, tables);
+                handle_read_table!(BDAT, name_str, tables, buf, offset)
             }
             "CDIT" => {
-                handle!(CDIT, tables);
+                handle_read_table!(CDIT, name_str, tables, buf, offset)
             }
             "CEDT" => {
-                handle!(CEDT, tables);
+                handle_read_table!(CEDT, name_str, tables, buf, offset)
             }
             "CRAT" => {
-                handle!(CRAT, tables);
+                handle_read_table!(CRAT, name_str, tables, buf, offset)
             }
             "CSRT" => {
-                handle!(CSRT, tables);
+                handle_read_table!(CSRT, name_str, tables, buf, offset)
             }
             "DBGP" => {
-                handle!(DBGP, tables);
+                handle_read_table!(DBGP, name_str, tables, buf, offset)
             }
             "DBG2" => {
-                handle!(DBG2, tables);
+                handle_read_table!(DBG2, name_str, tables, buf, offset)
             }
             "DMAR" => {
-                handle!(DMAR, tables);
+                handle_read_table!(DMAR, name_str, tables, buf, offset)
             }
             "DRTM" => {
-                handle!(DRTM, tables);
+                handle_read_table!(DRTM, name_str, tables, buf, offset)
             }
             "ETDT" => {
-                handle!(ETDT, tables);
+                handle_read_table!(ETDT, name_str, tables, buf, offset)
             }
             "IBFT" => {
-                handle!(IBFT, tables);
+                handle_read_table!(IBFT, name_str, tables, buf, offset)
             }
             "IORT" => {
-                handle!(IORT, tables);
+                handle_read_table!(IORT, name_str, tables, buf, offset)
             }
             "IVRS" => {
-                handle!(IVRS, tables);
+                handle_read_table!(IVRS, name_str, tables, buf, offset)
             }
             "LPIT" => {
-                handle!(LPIT, tables);
+                handle_read_table!(LPIT, name_str, tables, buf, offset)
             }
             "MCHI" => {
-                handle!(MCHI, tables);
+                handle_read_table!(MCHI, name_str, tables, buf, offset)
             }
             "MPAM" => {
-                handle!(MPAM, tables);
+                handle_read_table!(MPAM, name_str, tables, buf, offset)
             }
             "MSDM" => {
-                handle!(MSDM, tables);
+                handle_read_table!(MSDM, name_str, tables, buf, offset)
             }
             "PRMT" => {
-                handle!(PRMT, tables);
+                handle_read_table!(PRMT, name_str, tables, buf, offset)
             }
             "RGRT" => {
-                handle!(RGRT, tables);
+                handle_read_table!(RGRT, name_str, tables, buf, offset)
             }
             "SDEI" => {
-                handle!(SDEI, tables);
+                handle_read_table!(SDEI, name_str, tables, buf, offset)
             }
             "SLIC" => {
-                handle!(SLIC, tables);
+                handle_read_table!(SLIC, name_str, tables, buf, offset)
             }
             "SPCR" => {
-                handle!(SPCR, tables);
+                handle_read_table!(SPCR, name_str, tables, buf, offset)
             }
             "SPMI" => {
-                handle!(SPMI, tables);
+                handle_read_table!(SPMI, name_str, tables, buf, offset)
             }
             "STAO" => {
-                handle!(STAO, tables);
+                handle_read_table!(STAO, name_str, tables, buf, offset)
             }
             "SVKL" => {
-                handle!(SVKL, tables);
+                handle_read_table!(SVKL, name_str, tables, buf, offset)
             }
             "TCPA" => {
-                handle!(TCPA, tables);
+                handle_read_table!(TCPA, name_str, tables, buf, offset)
             }
             "TPM2" => {
-                handle!(TPM2, tables);
+                handle_read_table!(TPM2, name_str, tables, buf, offset)
             }
             "UEFI" => {
-                handle!(UEFI, tables);
+                handle_read_table!(UEFI, name_str, tables, buf, offset)
             }
             "WAET" => {
-                handle!(WAET, tables);
+                handle_read_table!(WAET, name_str, tables, buf, offset)
             }
             "WDAT" => {
-                handle!(WDAT, tables);
+                handle_read_table!(WDAT, name_str, tables, buf, offset)
             }
             "WDRT" => {
-                handle!(WDRT, tables);
+                handle_read_table!(WDRT, name_str, tables, buf, offset)
             }
             "WPBT" => {
-                handle!(WPBT, tables);
+                handle_read_table!(WPBT, name_str, tables, buf, offset)
             }
             "WSMT" => {
-                handle!(WSMT, tables);
+                handle_read_table!(WSMT, name_str, tables, buf, offset)
             }
             "XENV" => {
-                handle!(XENV, tables);
+                handle_read_table!(XENV, name_str, tables, buf, offset)
             }
+            _ => Err(SystemError::ENODEV),
+        }
+    }
+}
 
-            _ => {
-                error!("AttrAcpiTable::read(): unknown table. name: {}", self.name);
-                return Err(SystemError::ENODEV);
-            }
-        };
+impl Attribute for AttrAcpiTable {
+    fn show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
+        return Err(SystemError::ENOSYS);
+    }
+
+    fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
+        return Err(SystemError::ENOSYS);
+    }
+
+    fn name(&self) -> &str {
+        return &self.filename;
+    }
+
+    fn mode(&self) -> ModeType {
+        return ModeType::from_bits_truncate(0o400);
+    }
+
+    fn support(&self) -> SysFSOpsSupport {
+        return SysFSOpsSupport::empty();
+    }
+}
+
+impl BinAttribute for AttrAcpiTable {
+    fn support_battr(&self) -> SysFSOpsSupport {
+        return SysFSOpsSupport::BATTR_READ;
+    }
+    fn write(
+        &self,
+        _kobj: Arc<dyn KObject>,
+        _buf: &[u8],
+        _offset: usize,
+    ) -> Result<usize, SystemError> {
+        return Err(SystemError::ENOSYS);
+    }
+
+    /// 展示 ACPI 表的内容
+    ///
+    /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/acpi/sysfs.c?fi=acpi_sysfs_init#320
+    fn read(
+        &self,
+        _kobj: Arc<dyn KObject>,
+        buf: &mut [u8],
+        offset: usize,
+    ) -> Result<usize, SystemError> {
+        let tables = acpi_manager().tables().unwrap();
+        let name_str = self.name.as_str();
+        // 这里分多个函数进行处理,是为了减小栈内存的使用。
+        if let Ok(x) = self.do_binattr_read_1(tables, name_str, buf, offset) {
+            return Ok(x);
+        }
+
+        if let Ok(x) = self.do_binattr_read_2(tables, name_str, buf, offset) {
+            return Ok(x);
+        }
+
+        error!("AttrAcpiTable::read(): unknown table. name: {}", self.name);
+        return Err(SystemError::ENODEV);
     }
 
     fn size(&self) -> usize {