Skip to content

Commit 0dc7d89

Browse files
jiangliualxiord
authored andcommitted
x86_64: limit maximum number of supported CPUs
With APIC/xAPIC interrupt controllers, there are only 256 APIC IDs available. One is used for broadcasting, another is one is used for IOAPIC/IOxAPIC, so only 254 CPUs at maximum may be supported. Actually 254 is a large number for firecracker's usage cases. This also fixes the panicking when starting a VM with 255 vCPUs. Signed-off-by: Liu Jiang <[email protected]>
1 parent 919c23b commit 0dc7d89

File tree

1 file changed

+27
-4
lines changed

1 file changed

+27
-4
lines changed

arch/src/x86_64/mptable.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ pub enum Error {
2626
AddressOverflow,
2727
/// Failure while zeroing out the memory for the MP table.
2828
Clear,
29+
/// Number of CPUs exceeds the maximum supported CPUs
30+
TooManyCpus,
2931
/// Failure to write the MP floating pointer.
3032
WriteMpfIntel,
3133
/// Failure to write MP CPU entry.
@@ -44,6 +46,11 @@ pub enum Error {
4446

4547
pub type Result<T> = result::Result<T, Error>;
4648

49+
// With APIC/xAPIC, there are only 255 APIC IDs available. And IOAPIC occupies
50+
// one APIC ID, so only 254 CPUs at maximum may be supported. Actually it's
51+
// a large number for FC usecases.
52+
pub const MAX_SUPPORTED_CPUS: u32 = 254;
53+
4754
// Convenience macro for making arrays of diverse character types.
4855
macro_rules! char_array {
4956
($t:ty; $( $c:expr ),*) => ( [ $( $c as $t ),* ] )
@@ -90,6 +97,10 @@ fn compute_mp_size(num_cpus: u8) -> usize {
9097

9198
/// Performs setup of the MP table for the given `num_cpus`.
9299
pub fn setup_mptable(mem: &GuestMemory, num_cpus: u8) -> Result<()> {
100+
if num_cpus as u32 > MAX_SUPPORTED_CPUS {
101+
return Err(Error::TooManyCpus);
102+
}
103+
93104
// Used to keep track of the next base pointer into the MP table.
94105
let mut base_mp = GuestAddress(MPTABLE_START);
95106

@@ -321,11 +332,13 @@ mod tests {
321332

322333
#[test]
323334
fn cpu_entry_count() {
324-
const MAX_CPUS: u8 = 0xff;
325-
let mem =
326-
GuestMemory::new(&[(GuestAddress(MPTABLE_START), compute_mp_size(MAX_CPUS))]).unwrap();
335+
let mem = GuestMemory::new(&[(
336+
GuestAddress(MPTABLE_START),
337+
compute_mp_size(MAX_SUPPORTED_CPUS as u8),
338+
)])
339+
.unwrap();
327340

328-
for i in 0..MAX_CPUS {
341+
for i in 0..MAX_SUPPORTED_CPUS as u8 {
329342
setup_mptable(&mem, i).unwrap();
330343

331344
let mpf_intel: mpspec::mpf_intel =
@@ -351,4 +364,14 @@ mod tests {
351364
assert_eq!(cpu_count, i);
352365
}
353366
}
367+
368+
#[test]
369+
fn cpu_entry_count_max() {
370+
let cpus = MAX_SUPPORTED_CPUS + 1;
371+
let mem = GuestMemory::new(&[(GuestAddress(MPTABLE_START), compute_mp_size(cpus as u8))])
372+
.unwrap();
373+
374+
let result = setup_mptable(&mem, cpus as u8).unwrap_err();
375+
assert_eq!(result, Error::TooManyCpus);
376+
}
354377
}

0 commit comments

Comments
 (0)