Skip to content

Commit d1e1dcd

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 a8819ed commit d1e1dcd

File tree

2 files changed

+48
-4
lines changed

2 files changed

+48
-4
lines changed

src/acpi-tables/src/madt.rs

Lines changed: 38 additions & 0 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
@@ -37,6 +38,16 @@ impl LocalAPIC {
3738
flags: U32::new(1u32 << MADT_CPU_ENABLE_FLAG),
3839
}
3940
}
41+
42+
pub fn new_online_capable(cpu_id: u8) -> Self {
43+
Self {
44+
r#type: 0,
45+
length: 8,
46+
processor_uid: cpu_id,
47+
apic_id: cpu_id,
48+
flags: U32::new(1u32 << MADT_CPU_ONLINE_CAPABLE_FLAG),
49+
}
50+
}
4051
}
4152

4253
// clippy doesn't understand that we actually "use" the fields of this struct when we serialize
@@ -140,3 +151,30 @@ impl Sdt for Madt {
140151
Ok(())
141152
}
142153
}
154+
155+
#[cfg(test)]
156+
mod tests {
157+
use zerocopy::little_endian::U32;
158+
159+
use crate::madt::LocalAPIC;
160+
161+
#[test]
162+
fn test_online_local_apic() {
163+
let online_apic = super::LocalAPIC::new(0);
164+
assert_eq!(online_apic.r#type, 0);
165+
assert_eq!(online_apic.length, 8);
166+
assert_eq!(online_apic.processor_uid, 0);
167+
assert_eq!(online_apic.apic_id, 0);
168+
assert_eq!(online_apic.flags, U32::new(1));
169+
}
170+
171+
#[test]
172+
fn test_online_capable_local_apic() {
173+
let online_capable_apic = LocalAPIC::new_online_capable(1);
174+
assert_eq!(online_capable_apic.r#type, 0);
175+
assert_eq!(online_capable_apic.length, 8);
176+
assert_eq!(online_capable_apic.processor_uid, 1);
177+
assert_eq!(online_capable_apic.apic_id, 1);
178+
assert_eq!(online_capable_apic.flags, U32::new(2));
179+
}
180+
}

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).as_bytes());
29+
} else {
30+
ic.extend_from_slice(LocalAPIC::new_online_capable(i).as_bytes())
31+
}
2632
}
2733
ic
2834
}

0 commit comments

Comments
 (0)