Skip to content

Commit

Permalink
adjust ACPI for UEFI via its own init_uefi function and remove mappin…
Browse files Browse the repository at this point in the history
…g for UEFI ACPI tables since that's already given
  • Loading branch information
sarahspberrypi committed Jan 4, 2024
1 parent 6a3b4c5 commit b715bd6
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 18 deletions.
31 changes: 28 additions & 3 deletions src/arch/x86_64/kernel/acpi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,10 +431,19 @@ fn parse_fadt(fadt: AcpiTable<'_>) {
} else {
// For UEFI Systems, the tables are already mapped so we only need to return a proper reference to the table
let table = unsafe { (dsdt_address.0 as *const AcpiSdtHeader).as_ref().unwrap() };
let mut length = table.length as u64;
let res = length % BasePageSize::SIZE;
//ACPI tables are 4KiB aligned, so the length can span the entire pagetable
//-> necessary since the tables are dropped (and virtual memory is deallocated) after use
//somehow, this table is larger than 4KiB, so we bumb it up to the entire page
if res != 0 {
length += 0x1000 - res;
}

AcpiTable {
header: table,
allocated_virtual_address: VirtAddr(dsdt_address.0),
allocated_length: table.length as usize,
allocated_length: length as usize,
}
};

Expand Down Expand Up @@ -610,10 +619,17 @@ pub fn init_uefi() {
verify_checksum(table.header_start_address(), table.length as usize).is_ok(),
"MADT at {table_physical_address:#x} has invalid checksum"
);
//ACPI tables are 4KiB aligned, so the length can span the entire pagetable
//-> necessary since the tables are dropped (and virtual memory is deallocated) after use
let mut length = table.length as u64;
if length < 0x1000 {
length = 0x1000;
}

let madt: AcpiTable<'static> = AcpiTable {
header: table,
allocated_virtual_address: VirtAddr(table_physical_address.0),
allocated_length: table.length as usize,
allocated_length: length as usize,
};
MADT.set(madt).unwrap();
trace!("setting MADT successful");
Expand All @@ -624,11 +640,20 @@ pub fn init_uefi() {
verify_checksum(table.header_start_address(), table.length as usize).is_ok(),
"FADT at {table_physical_address:#x} has invalid checksum"
);
//ACPI tables are 4KiB aligned, so the length can span the entire pagetable
//-> necessary since the tables are dropped (and virtual memory is deallocated) after use
let mut length = table.length as u64;
if length < 0x1000 {
length = 0x1000;
}
trace!("length of FACP: {length:x?}");
let fadt: AcpiTable<'static> = AcpiTable {
header: table,
allocated_virtual_address: VirtAddr(table_physical_address.0),
allocated_length: table.length as usize,
allocated_length: length as usize,
};

trace!("fadt: {fadt:#?}");
parse_fadt(fadt);
}
}
Expand Down
42 changes: 27 additions & 15 deletions src/arch/x86_64/kernel/apic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,13 +246,18 @@ pub fn local_apic_id_count() -> u32 {
}

fn init_ioapic_address(phys_addr: PhysAddr) {
let ioapic_address = virtualmem::allocate(BasePageSize::SIZE as usize).unwrap();
IOAPIC_ADDRESS.set(ioapic_address).unwrap();
debug!("Mapping IOAPIC at {phys_addr:p} to virtual address {ioapic_address:p}",);
if !crate::kernel::is_uefi() {
let ioapic_address = virtualmem::allocate(BasePageSize::SIZE as usize).unwrap();
IOAPIC_ADDRESS.set(ioapic_address).unwrap();
debug!("Mapping IOAPIC at {phys_addr:p} to virtual address {ioapic_address:p}",);

let mut flags = PageTableEntryFlags::empty();
flags.device().writable().execute_disable();
paging::map::<BasePageSize>(ioapic_address, phys_addr, 1, flags);
let mut flags = PageTableEntryFlags::empty();
flags.device().writable().execute_disable();
paging::map::<BasePageSize>(ioapic_address, phys_addr, 1, flags);
} else {
// UEFI systems have already id mapped everything, so we can just set the physical address as the virtual one
IOAPIC_ADDRESS.set(VirtAddr(phys_addr.as_u64())).unwrap();
}
}

#[cfg(not(feature = "acpi"))]
Expand Down Expand Up @@ -455,16 +460,23 @@ pub fn init() {
if !processor::supports_x2apic() {
// We use the traditional xAPIC mode available on all x86-64 CPUs.
// It uses a mapped page for communication.
let local_apic_address = virtualmem::allocate(BasePageSize::SIZE as usize).unwrap();
LOCAL_APIC_ADDRESS.set(local_apic_address).unwrap();
debug!(
"Mapping Local APIC at {:p} to virtual address {:p}",
local_apic_physical_address, local_apic_address
);
if crate::kernel::is_uefi() {
//already id mapped in UEFI systems, just use the physical address as virtual one
LOCAL_APIC_ADDRESS
.set(VirtAddr(local_apic_physical_address.as_u64()))
.unwrap();
} else {
let local_apic_address = virtualmem::allocate(BasePageSize::SIZE as usize).unwrap();
LOCAL_APIC_ADDRESS.set(local_apic_address).unwrap();
debug!(
"Mapping Local APIC at {:p} to virtual address {:p}",
local_apic_physical_address, local_apic_address
);

let mut flags = PageTableEntryFlags::empty();
flags.device().writable().execute_disable();
paging::map::<BasePageSize>(local_apic_address, local_apic_physical_address, 1, flags);
let mut flags = PageTableEntryFlags::empty();
flags.device().writable().execute_disable();
paging::map::<BasePageSize>(local_apic_address, local_apic_physical_address, 1, flags);
}
}

// Set gates to ISRs for the APIC interrupts we are going to enable.
Expand Down

0 comments on commit b715bd6

Please sign in to comment.