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:
+11
-8
@@ -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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user