Skip to content

Commit

Permalink
Add support for the WAET ACPI table (theseus-os#1050)
Browse files Browse the repository at this point in the history
* Currently not used, but fully working.
* Can be used to optimize RTC and ACPI PM timer usage.
  • Loading branch information
kevinaboos authored Oct 3, 2023
1 parent 810e12f commit 1be62d4
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 1 deletion.
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions kernel/acpi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ path = "rsdt"
[dependencies.fadt]
path = "fadt"

[dependencies.waet]
path = "waet"

[dependencies.madt]
path = "madt"

Expand Down
3 changes: 3 additions & 0 deletions kernel/acpi/acpi_table_handler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ path = "../rsdt"
[dependencies.fadt]
path = "../fadt"

[dependencies.waet]
path = "../waet"

[dependencies.hpet]
path = "../hpet"

Expand Down
1 change: 1 addition & 0 deletions kernel/acpi/acpi_table_handler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
13 changes: 12 additions & 1 deletion kernel/acpi/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -63,6 +63,17 @@ pub fn init(rsdp_address: Option<PhysicalAddress>, 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.
{
Expand Down
19 changes: 19 additions & 0 deletions kernel/acpi/waet/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "waet"
version = "0.1.0"
authors = ["Kevin Boos <kevinaboos@gmail.com>"]
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"

63 changes: 63 additions & 0 deletions kernel/acpi/waet/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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.
///
/// <https://download.microsoft.com/download/7/E/7/7E7662CF-CBEA-470B-A97E-CE7CE0D98DC2/WAET.docx>
#[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::<Waet>() == 40);
const _: () = assert!(core::mem::align_of::<Waet>() == 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
}
}

0 comments on commit 1be62d4

Please sign in to comment.