Skip to content

Commit f82926b

Browse files
committed
Add new online capable vCPUs sockets to MADT
Extend the MADT to contain MAX_SUPPORTED_VCPUS (32) entries. Only the number specified in the machine_config are enabled. The rest are "online capable", meaning they can be brought online. Signed-off-by: James Curtis <[email protected]>
1 parent 4faee33 commit f82926b

File tree

2 files changed

+45
-6
lines changed

2 files changed

+45
-6
lines changed

src/acpi-tables/src/madt.rs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::{checksum, AcpiError, Result, Sdt, SdtHeader};
1313

1414
const MADT_CPU_ENABLE_FLAG: u32 = 0;
1515

16+
const MADT_CPU_ONLINE_CAPABLE_FLAG: u32 = 1;
1617
// clippy doesn't understand that we actually "use" the fields of this struct when we serialize
1718
// them as bytes in guest memory, so here we just ignore dead code to avoid having to name
1819
// everything with an underscore prefix
@@ -28,13 +29,18 @@ pub struct LocalAPIC {
2829
}
2930

3031
impl LocalAPIC {
31-
pub fn new(cpu_id: u8) -> Self {
32+
pub fn new(cpu_id: u8, online: bool) -> Self {
33+
let flags = if online {
34+
U32::new(1u32 << MADT_CPU_ENABLE_FLAG)
35+
} else {
36+
U32::new(1u32 << MADT_CPU_ONLINE_CAPABLE_FLAG)
37+
};
3238
Self {
3339
r#type: 0,
3440
length: 8,
3541
processor_uid: cpu_id,
3642
apic_id: cpu_id,
37-
flags: U32::new(1u32 << MADT_CPU_ENABLE_FLAG),
43+
flags,
3844
}
3945
}
4046
}
@@ -140,3 +146,30 @@ impl Sdt for Madt {
140146
Ok(())
141147
}
142148
}
149+
150+
#[cfg(test)]
151+
mod tests {
152+
use zerocopy::little_endian::U32;
153+
154+
use crate::madt::LocalAPIC;
155+
156+
#[test]
157+
fn test_online_local_apic() {
158+
let online_apic = super::LocalAPIC::new(0, true);
159+
assert_eq!(online_apic.r#type, 0);
160+
assert_eq!(online_apic.length, 8);
161+
assert_eq!(online_apic.processor_uid, 0);
162+
assert_eq!(online_apic.apic_id, 0);
163+
assert_eq!(online_apic.flags, U32::new(1));
164+
}
165+
166+
#[test]
167+
fn test_online_capable_local_apic() {
168+
let online_capable_apic = LocalAPIC::new(1, false);
169+
assert_eq!(online_capable_apic.r#type, 0);
170+
assert_eq!(online_capable_apic.length, 8);
171+
assert_eq!(online_capable_apic.processor_uid, 1);
172+
assert_eq!(online_capable_apic.apic_id, 1);
173+
assert_eq!(online_capable_apic.flags, U32::new(2));
174+
}
175+
}

src/vmm/src/acpi/x86_64.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,21 @@ use zerocopy::AsBytes;
1414

1515
use crate::arch::x86_64::layout;
1616
use crate::device_manager::legacy::PortIODeviceManager;
17+
use crate::vmm_config::machine_config::MAX_SUPPORTED_VCPUS;
1718

1819
#[inline(always)]
1920
pub(crate) fn setup_interrupt_controllers(nr_vcpus: u8) -> Vec<u8> {
20-
let mut ic =
21-
Vec::with_capacity(size_of::<IoAPIC>() + (nr_vcpus as usize) * size_of::<LocalAPIC>());
21+
let mut ic = Vec::with_capacity(
22+
size_of::<IoAPIC>() + (MAX_SUPPORTED_VCPUS as usize) * size_of::<LocalAPIC>(),
23+
);
2224

2325
ic.extend_from_slice(IoAPIC::new(0, layout::IOAPIC_ADDR).as_bytes());
24-
for i in 0..nr_vcpus {
25-
ic.extend_from_slice(LocalAPIC::new(i).as_bytes());
26+
for i in 0..MAX_SUPPORTED_VCPUS {
27+
if i < nr_vcpus {
28+
ic.extend_from_slice(LocalAPIC::new(i, true).as_bytes());
29+
} else {
30+
ic.extend_from_slice(LocalAPIC::new(i, false).as_bytes())
31+
}
2632
}
2733
ic
2834
}

0 commit comments

Comments
 (0)