mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 05:16:47 +00:00
Respect local X2Apic MADT entry
This commit is contained in:
parent
07792a1b1c
commit
09a8ab8800
@ -27,6 +27,8 @@
|
|||||||
//! This sequence does not need to be strictly followed, and there may be
|
//! This sequence does not need to be strictly followed, and there may be
|
||||||
//! different considerations in different systems.
|
//! different considerations in different systems.
|
||||||
|
|
||||||
|
use acpi::madt::MadtEntry;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::x86::kernel::{
|
arch::x86::kernel::{
|
||||||
acpi::get_acpi_tables,
|
acpi::get_acpi_tables,
|
||||||
@ -45,19 +47,54 @@ use crate::{
|
|||||||
/// This function needs to be called after the OS initializes the ACPI table.
|
/// This function needs to be called after the OS initializes the ACPI table.
|
||||||
pub(crate) fn get_num_processors() -> Option<u32> {
|
pub(crate) fn get_num_processors() -> Option<u32> {
|
||||||
let acpi_tables = get_acpi_tables()?;
|
let acpi_tables = get_acpi_tables()?;
|
||||||
let mut local_apic_counts = 0;
|
let madt_table = acpi_tables.find_table::<acpi::madt::Madt>().ok()?;
|
||||||
acpi_tables
|
|
||||||
.find_table::<acpi::madt::Madt>()
|
// In the UEFI spec [1], for compatibility, the firmware will provide
|
||||||
.unwrap()
|
// "Processor X2APIC structure" for local APIC ID values >= 255 and
|
||||||
|
// "Processor APIC structure" for local APIC ID values < 255, even if it is
|
||||||
|
// in the x2APIC mode.
|
||||||
|
// [1]: https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/05_ACPI_Software_Programming_Model/ACPI_Software_Programming_Model.html#processor-local-x2apic-structure
|
||||||
|
let local_apic_counts = madt_table
|
||||||
.get()
|
.get()
|
||||||
.entries()
|
.entries()
|
||||||
.for_each(|entry| {
|
.filter(|e| match e {
|
||||||
if let acpi::madt::MadtEntry::LocalApic(_) = entry {
|
MadtEntry::LocalX2Apic(entry) => {
|
||||||
local_apic_counts += 1;
|
let processor_uid = entry.processor_uid;
|
||||||
|
let x2apic_id = entry.x2apic_id;
|
||||||
|
log::trace!(
|
||||||
|
"Found a local x2APIC entry in MADT: processor UID = {}, x2APIC ID = {}",
|
||||||
|
processor_uid,
|
||||||
|
x2apic_id,
|
||||||
|
);
|
||||||
|
true
|
||||||
}
|
}
|
||||||
});
|
MadtEntry::LocalApic(entry) => {
|
||||||
|
let processor_id = entry.processor_id;
|
||||||
|
let apic_id = entry.apic_id as u32;
|
||||||
|
log::trace!(
|
||||||
|
"Found a local APIC entry in MADT: processor ID = {}, APIC ID = {}",
|
||||||
|
processor_id,
|
||||||
|
apic_id,
|
||||||
|
);
|
||||||
|
// Check if APIC entries also show up as x2APIC entries.
|
||||||
|
if madt_table
|
||||||
|
.get()
|
||||||
|
.entries()
|
||||||
|
.any(|e| matches!(e, MadtEntry::LocalX2Apic(e) if e.x2apic_id == apic_id))
|
||||||
|
{
|
||||||
|
log::warn!(
|
||||||
|
"Firmware bug: in MADT, APIC ID {} is also listed as a x2APIC ID",
|
||||||
|
apic_id
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
.count();
|
||||||
|
|
||||||
Some(local_apic_counts)
|
Some(local_apic_counts as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Brings up all application processors.
|
/// Brings up all application processors.
|
||||||
|
@ -8,8 +8,8 @@ use core::sync::atomic::{AtomicBool, Ordering};
|
|||||||
use spin::Once;
|
use spin::Once;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::boot::smp::{bringup_all_aps, get_num_processors},
|
arch::boot::smp::bringup_all_aps,
|
||||||
cpu,
|
cpu::{self, num_cpus},
|
||||||
mm::{
|
mm::{
|
||||||
frame::{meta::KernelMeta, Segment},
|
frame::{meta::KernelMeta, Segment},
|
||||||
paddr_to_vaddr, FrameAllocOptions, PAGE_SIZE,
|
paddr_to_vaddr, FrameAllocOptions, PAGE_SIZE,
|
||||||
@ -49,12 +49,11 @@ static AP_LATE_ENTRY: Once<fn()> = Once::new();
|
|||||||
/// However, the function need to be called before any `cpu_local!` variables are
|
/// However, the function need to be called before any `cpu_local!` variables are
|
||||||
/// accessed, including the APIC instance.
|
/// accessed, including the APIC instance.
|
||||||
pub fn boot_all_aps() {
|
pub fn boot_all_aps() {
|
||||||
// TODO: support boot protocols without ACPI tables, e.g., Multiboot
|
let num_cpus = num_cpus() as u32;
|
||||||
let Some(num_cpus) = get_num_processors() else {
|
if num_cpus == 1 {
|
||||||
log::warn!("No processor information found. The kernel operates with a single processor.");
|
|
||||||
return;
|
return;
|
||||||
};
|
}
|
||||||
log::info!("Found {} processors.", num_cpus);
|
log::info!("Booting {} processors.", num_cpus - 1);
|
||||||
|
|
||||||
// We currently assumes that bootstrap processor (BSP) have always the
|
// We currently assumes that bootstrap processor (BSP) have always the
|
||||||
// processor ID 0. And the processor ID starts from 0 to `num_cpus - 1`.
|
// processor ID 0. And the processor ID starts from 0 to `num_cpus - 1`.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user