x86_64: map FACS physical address before parsing in acpi::init

The FACS address from FADT x_firmware_ctrl is a physical address.
Dereferencing it directly caused a page fault after the FADT offset fix
yielded a valid (but unmapped) physical address. Use get_sdt() to map it
into kernel space before passing it to facs::init.

Author: vasilito <adminpupkin@gmail.com>
This commit is contained in:
2026-07-06 02:24:44 +03:00
parent 51f6a7712e
commit d4d9961d41
+11 -8
View File
@@ -190,23 +190,26 @@ pub unsafe fn init(already_supplied_rsdp: Option<NonNull<u8>>) {
let facs_addr = fadt::x_firmware_ctrl();
info!("FACS x_firmware_ctrl = {:#x}", facs_addr);
if facs_addr != 0 {
// SAFETY: The FACS address is a physical
// address stored in the FADT. The boot-time page
// table maps the FACS into the kernel's address
// space (firmware tables are below 4GB on x86_64).
let facs_sdt = unsafe { &*(facs_addr as *const Sdt) };
// The FACS address from the FADT is a physical
// address. Map it into kernel space before parsing.
let facs_sdt = get_sdt(
PhysicalAddress::new(facs_addr as usize),
&mut KernelMapper::lock_rw(),
);
facs::init(facs_sdt);
} else {
let facs_addr = fadt::firmware_ctrl() as u64;
if facs_addr != 0 {
// SAFETY: same as above.
let facs_sdt =
unsafe { &*(facs_addr as *const Sdt) };
let facs_sdt = get_sdt(
PhysicalAddress::new(facs_addr as usize),
&mut KernelMapper::lock_rw(),
);
facs::init(facs_sdt);
} else {
warn!("ACPI: no FACS found (neither x_firmware_ctrl nor firmware_ctrl), S3 resume path disabled");
}
}
info!("GSBASE after facs::init: {:#x}", x86::msr::rdmsr(x86::msr::IA32_GS_BASE));
} else {
error!("NO RSDP FOUND");
}