diff --git a/Cargo.lock b/Cargo.lock index 2675ed3d05..d6baaea72b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,6 +19,7 @@ dependencies = [ "rsdt", "spin 0.9.4", "time", + "waet", ] [[package]] @@ -43,6 +44,7 @@ dependencies = [ "madt", "memory", "rsdt", + "waet", ] [[package]] @@ -4318,6 +4320,16 @@ dependencies = [ "quote", ] +[[package]] +name = "waet" +version = "0.1.0" +dependencies = [ + "acpi_table", + "memory", + "sdt", + "zerocopy", +] + [[package]] name = "wait_condition" version = "0.1.0" diff --git a/kernel/acpi/Cargo.toml b/kernel/acpi/Cargo.toml index 82c87197a3..c39a2505a7 100644 --- a/kernel/acpi/Cargo.toml +++ b/kernel/acpi/Cargo.toml @@ -27,6 +27,9 @@ path = "rsdt" [dependencies.fadt] path = "fadt" +[dependencies.waet] +path = "waet" + [dependencies.madt] path = "madt" diff --git a/kernel/acpi/acpi_table_handler/Cargo.toml b/kernel/acpi/acpi_table_handler/Cargo.toml index 4ab735e4c7..d089c1075b 100644 --- a/kernel/acpi/acpi_table_handler/Cargo.toml +++ b/kernel/acpi/acpi_table_handler/Cargo.toml @@ -20,6 +20,9 @@ path = "../rsdt" [dependencies.fadt] path = "../fadt" +[dependencies.waet] +path = "../waet" + [dependencies.hpet] path = "../hpet" diff --git a/kernel/acpi/acpi_table_handler/src/lib.rs b/kernel/acpi/acpi_table_handler/src/lib.rs index 4f212124c6..1b4c4e28ad 100644 --- a/kernel/acpi/acpi_table_handler/src/lib.rs +++ b/kernel/acpi/acpi_table_handler/src/lib.rs @@ -35,6 +35,7 @@ pub fn acpi_table_handler( rsdt::RSDT_SIGNATURE | rsdt::XSDT_SIGNATURE => rsdt::handle(acpi_tables, signature, length, phys_addr), fadt::FADT_SIGNATURE => fadt::handle(acpi_tables, signature, length, phys_addr), + waet::WAET_SIGNATURE => waet::handle(acpi_tables, signature, length, phys_addr), hpet::HPET_SIGNATURE => hpet::handle(acpi_tables, signature, length, phys_addr), madt::MADT_SIGNATURE => madt::handle(acpi_tables, signature, length, phys_addr), dmar::DMAR_SIGNATURE => dmar::handle(acpi_tables, signature, length, phys_addr), diff --git a/kernel/acpi/src/lib.rs b/kernel/acpi/src/lib.rs index ec62370b85..25f27f4d24 100644 --- a/kernel/acpi/src/lib.rs +++ b/kernel/acpi/src/lib.rs @@ -1,4 +1,4 @@ -//! Code to parse the ACPI tables, based off of Redox. +//! Code to parse the ACPI tables. #![no_std] extern crate alloc; @@ -63,6 +63,17 @@ pub fn init(rsdp_address: Option, page_table: &mut PageTable) - // here: do something with the DSDT here, when needed. // debug!("DSDT physical address: {:#X}", {_fadt.dsdt}); } + + // WAET is optional, and contains info about potentially optimizing timer-related actions. + { + let acpi_tables = ACPI_TABLES.lock(); + if let Some(waet) = waet::Waet::get(&acpi_tables) { + // here: do something with the WAET here, if desired. + debug!("WAET: RTC? {:?}. ACPI PM timer? {:?}", + waet.rtc_good(), waet.acpi_pm_timer_good(), + ); + } + } // HPET is optional, but usually present. { diff --git a/kernel/acpi/waet/Cargo.toml b/kernel/acpi/waet/Cargo.toml new file mode 100644 index 0000000000..e1c2172fd8 --- /dev/null +++ b/kernel/acpi/waet/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "waet" +version = "0.1.0" +authors = ["Kevin Boos "] +description = "Support for ACPI WAET" +edition = "2021" + +[dependencies] +zerocopy = "0.5.0" + +[dependencies.memory] +path = "../../memory" + +[dependencies.sdt] +path = "../sdt" + +[dependencies.acpi_table] +path = "../acpi_table" + diff --git a/kernel/acpi/waet/src/lib.rs b/kernel/acpi/waet/src/lib.rs new file mode 100644 index 0000000000..3a33ceb7f5 --- /dev/null +++ b/kernel/acpi/waet/src/lib.rs @@ -0,0 +1,63 @@ +//! Definitions for WAET, the Windows ACPI Emulated devices Table. + +#![no_std] + +use memory::PhysicalAddress; +use sdt::Sdt; +use acpi_table::{AcpiSignature, AcpiTables}; +use zerocopy::FromBytes; + + +pub const WAET_SIGNATURE: &[u8; 4] = b"WAET"; + + +/// The handler for parsing the WAET table and adding it to the ACPI tables list. +pub fn handle( + acpi_tables: &mut AcpiTables, + signature: AcpiSignature, + _length: usize, + phys_addr: PhysicalAddress +) -> Result<(), &'static str> { + acpi_tables.add_table_location(signature, phys_addr, None) +} + + +/// The Windows ACPI Emulated devices Table (WAET) allows virtualized OSes +/// to avoid workarounds for errata on physical devices. +/// +/// +#[repr(C, packed)] +#[derive(Clone, Copy, Debug, FromBytes)] +pub struct Waet { + pub header: Sdt, + pub emulated_device_flags: u32, +} +const _: () = assert!(core::mem::size_of::() == 40); +const _: () = assert!(core::mem::align_of::() == 1); + +impl Waet { + /// Finds the WAET in the given `AcpiTables` and returns a reference to it. + pub fn get(acpi_tables: &AcpiTables) -> Option<&Waet> { + acpi_tables.table(WAET_SIGNATURE).ok() + } + + /// Returns whether the RTC has been enhanced not to require + /// acknowledgment after it asserts an interrupt. + /// + /// If this returns `true`, an interrupt handler can bypass + /// reading the RTC register to unlatch the pending interrupt. + pub fn rtc_good(&self) -> bool { + const RTC_GOOD: u32 = 1 << 0; + self.emulated_device_flags & RTC_GOOD == RTC_GOOD + } + + /// Returns whether the ACPI PM timer has been enhanced not to require + /// multiple reads. + /// + /// If this returns `true`, only a single read of the ACPI PM timer is + /// necessary to obtain a reliable value from it. + pub fn acpi_pm_timer_good(&self) -> bool { + const ACPI_PM_TIMER_GOOD: u32 = 1 << 1; + self.emulated_device_flags & ACPI_PM_TIMER_GOOD == ACPI_PM_TIMER_GOOD + } +}