From 9f02e6ff372d2d1b20ec221a37aba3983e3de38d Mon Sep 17 00:00:00 2001 From: Changyuan Lyu Date: Tue, 25 Jun 2024 22:13:05 -0700 Subject: [PATCH] acpi_tables: fix the access_size of GenericAddress Without the fix, the code gives 1 for Byte access 2 for Word access 4 for Dword access 8 for QWord access. However, As per ACPI 6.4 spec Sec.5.2.3.2 [1], the access_size should be 1 for Byte access 2 for Word access 3 for Dword access 4 for QWord access. The fix takes QEMU's implementation[2] as a reference. A related patch[3] has been merged into crosvm. [1] https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/05_ACPI_Software_Programming_Model/ACPI_Software_Programming_Model.html#generic-address-structure-gas [2] https://github.com/qemu/qemu/blob/6a4180af9686830d88c387baab6d79563ce42a15/hw/acpi/erst.c#L218 [3] https://chromium-review.googlesource.com/c/crosvm/crosvm/+/5394229 Signed-off-by: Changyuan Lyu --- src/sdt.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/sdt.rs b/src/sdt.rs index 409fa1a..0da4a22 100644 --- a/src/sdt.rs +++ b/src/sdt.rs @@ -25,7 +25,7 @@ impl GenericAddress { address_space_id: 1, register_bit_width: 8 * core::mem::size_of::() as u8, register_bit_offset: 0, - access_size: core::mem::size_of::() as u8, + access_size: core::mem::size_of::().trailing_zeros() as u8 + 1, address: u64::from(address), } } @@ -34,7 +34,7 @@ impl GenericAddress { address_space_id: 0, register_bit_width: 8 * core::mem::size_of::() as u8, register_bit_offset: 0, - access_size: core::mem::size_of::() as u8, + access_size: core::mem::size_of::().trailing_zeros() as u8 + 1, address, } } @@ -151,7 +151,7 @@ impl Aml for Sdt { #[cfg(test)] mod tests { - use super::Sdt; + use super::{GenericAddress, Sdt}; #[test] fn test_sdt() { @@ -168,4 +168,16 @@ mod tests { .fold(0u8, |acc, x| acc.wrapping_add(*x)); assert_eq!(sum, 0); } + + #[test] + fn test_generic_address_access_size() { + let byte_mmio = GenericAddress::mmio_address::(0x1000); + assert_eq!(byte_mmio.access_size, 1); + let word_mmio = GenericAddress::mmio_address::(0x1000); + assert_eq!(word_mmio.access_size, 2); + let dword_mmio = GenericAddress::mmio_address::(0x1000); + assert_eq!(dword_mmio.access_size, 3); + let qword_mmio = GenericAddress::mmio_address::(0x1000); + assert_eq!(qword_mmio.access_size, 4); + } }