diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index 4c59a32da..4f9fe9a20 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -1253,7 +1253,7 @@ impl Cpu { #[cfg(feature = "acpi")] impl Aml for Cpu { - fn to_aml_bytes(&self) -> Vec { + fn append_aml_bytes(&self, bytes: &mut Vec) { #[cfg(target_arch = "x86_64")] let mat_data: Vec = self.generate_mat(); @@ -1305,7 +1305,7 @@ impl Aml for Cpu { ), ], ) - .to_aml_bytes() + .append_aml_bytes(bytes) } } @@ -1316,13 +1316,13 @@ struct CpuNotify { #[cfg(feature = "acpi")] impl Aml for CpuNotify { - fn to_aml_bytes(&self) -> Vec { + fn append_aml_bytes(&self, bytes: &mut Vec) { let object = aml::Path::new(&format!("C{:03}", self.cpu_id)); aml::If::new( &aml::Equal::new(&aml::Arg(0), &self.cpu_id), vec![&aml::Notify::new(&object, &aml::Arg(1))], ) - .to_aml_bytes() + .append_aml_bytes(bytes) } } @@ -1333,33 +1333,30 @@ struct CpuMethods { #[cfg(feature = "acpi")] impl Aml for CpuMethods { - fn to_aml_bytes(&self) -> Vec { - let mut bytes = Vec::new(); - bytes.extend_from_slice( - // CPU status method - &aml::Method::new( - "CSTA".into(), - 1, - true, - vec![ - // Take lock defined above - &aml::Acquire::new("\\_SB_.PRES.CPLK".into(), 0xffff), - // Write CPU number (in first argument) to I/O port via field - &aml::Store::new(&aml::Path::new("\\_SB_.PRES.CSEL"), &aml::Arg(0)), - &aml::Store::new(&aml::Local(0), &aml::ZERO), - // Check if CPEN bit is set, if so make the local variable 0xf (see _STA for details of meaning) - &aml::If::new( - &aml::Equal::new(&aml::Path::new("\\_SB_.PRES.CPEN"), &aml::ONE), - vec![&aml::Store::new(&aml::Local(0), &0xfu8)], - ), - // Release lock - &aml::Release::new("\\_SB_.PRES.CPLK".into()), - // Return 0 or 0xf - &aml::Return::new(&aml::Local(0)), - ], - ) - .to_aml_bytes(), - ); + fn append_aml_bytes(&self, bytes: &mut Vec) { + // CPU status method + aml::Method::new( + "CSTA".into(), + 1, + true, + vec![ + // Take lock defined above + &aml::Acquire::new("\\_SB_.PRES.CPLK".into(), 0xffff), + // Write CPU number (in first argument) to I/O port via field + &aml::Store::new(&aml::Path::new("\\_SB_.PRES.CSEL"), &aml::Arg(0)), + &aml::Store::new(&aml::Local(0), &aml::ZERO), + // Check if CPEN bit is set, if so make the local variable 0xf (see _STA for details of meaning) + &aml::If::new( + &aml::Equal::new(&aml::Path::new("\\_SB_.PRES.CPEN"), &aml::ONE), + vec![&aml::Store::new(&aml::Local(0), &0xfu8)], + ), + // Release lock + &aml::Release::new("\\_SB_.PRES.CPLK".into()), + // Return 0 or 0xf + &aml::Return::new(&aml::Local(0)), + ], + ) + .append_aml_bytes(bytes); let mut cpu_notifies = Vec::new(); for cpu_id in 0..self.max_vcpus { @@ -1371,144 +1368,125 @@ impl Aml for CpuMethods { cpu_notifies_refs.push(&cpu_notifies[usize::from(cpu_id)]); } - bytes.extend_from_slice( - &aml::Method::new("CTFY".into(), 2, true, cpu_notifies_refs).to_aml_bytes(), - ); + aml::Method::new("CTFY".into(), 2, true, cpu_notifies_refs).append_aml_bytes(bytes); - bytes.extend_from_slice( - &aml::Method::new( - "CEJ0".into(), - 1, - true, - vec![ - &aml::Acquire::new("\\_SB_.PRES.CPLK".into(), 0xffff), - // Write CPU number (in first argument) to I/O port via field - &aml::Store::new(&aml::Path::new("\\_SB_.PRES.CSEL"), &aml::Arg(0)), - // Set CEJ0 bit - &aml::Store::new(&aml::Path::new("\\_SB_.PRES.CEJ0"), &aml::ONE), - &aml::Release::new("\\_SB_.PRES.CPLK".into()), - ], - ) - .to_aml_bytes(), - ); + aml::Method::new( + "CEJ0".into(), + 1, + true, + vec![ + &aml::Acquire::new("\\_SB_.PRES.CPLK".into(), 0xffff), + // Write CPU number (in first argument) to I/O port via field + &aml::Store::new(&aml::Path::new("\\_SB_.PRES.CSEL"), &aml::Arg(0)), + // Set CEJ0 bit + &aml::Store::new(&aml::Path::new("\\_SB_.PRES.CEJ0"), &aml::ONE), + &aml::Release::new("\\_SB_.PRES.CPLK".into()), + ], + ) + .append_aml_bytes(bytes); - bytes.extend_from_slice( - &aml::Method::new( - "CSCN".into(), - 0, - true, - vec![ - // Take lock defined above - &aml::Acquire::new("\\_SB_.PRES.CPLK".into(), 0xffff), - &aml::Store::new(&aml::Local(0), &aml::ZERO), - &aml::While::new( - &aml::LessThan::new(&aml::Local(0), &self.max_vcpus), - vec![ - // Write CPU number (in first argument) to I/O port via field - &aml::Store::new(&aml::Path::new("\\_SB_.PRES.CSEL"), &aml::Local(0)), - // Check if CINS bit is set - &aml::If::new( - &aml::Equal::new(&aml::Path::new("\\_SB_.PRES.CINS"), &aml::ONE), - // Notify device if it is - vec![ - &aml::MethodCall::new( - "CTFY".into(), - vec![&aml::Local(0), &aml::ONE], - ), - // Reset CINS bit - &aml::Store::new( - &aml::Path::new("\\_SB_.PRES.CINS"), - &aml::ONE, - ), - ], - ), - // Check if CRMV bit is set - &aml::If::new( - &aml::Equal::new(&aml::Path::new("\\_SB_.PRES.CRMV"), &aml::ONE), - // Notify device if it is (with the eject constant 0x3) - vec![ - &aml::MethodCall::new( - "CTFY".into(), - vec![&aml::Local(0), &3u8], - ), - // Reset CRMV bit - &aml::Store::new( - &aml::Path::new("\\_SB_.PRES.CRMV"), - &aml::ONE, - ), - ], - ), - &aml::Add::new(&aml::Local(0), &aml::Local(0), &aml::ONE), - ], - ), - // Release lock - &aml::Release::new("\\_SB_.PRES.CPLK".into()), - ], - ) - .to_aml_bytes(), - ); - bytes + aml::Method::new( + "CSCN".into(), + 0, + true, + vec![ + // Take lock defined above + &aml::Acquire::new("\\_SB_.PRES.CPLK".into(), 0xffff), + &aml::Store::new(&aml::Local(0), &aml::ZERO), + &aml::While::new( + &aml::LessThan::new(&aml::Local(0), &self.max_vcpus), + vec![ + // Write CPU number (in first argument) to I/O port via field + &aml::Store::new(&aml::Path::new("\\_SB_.PRES.CSEL"), &aml::Local(0)), + // Check if CINS bit is set + &aml::If::new( + &aml::Equal::new(&aml::Path::new("\\_SB_.PRES.CINS"), &aml::ONE), + // Notify device if it is + vec![ + &aml::MethodCall::new( + "CTFY".into(), + vec![&aml::Local(0), &aml::ONE], + ), + // Reset CINS bit + &aml::Store::new(&aml::Path::new("\\_SB_.PRES.CINS"), &aml::ONE), + ], + ), + // Check if CRMV bit is set + &aml::If::new( + &aml::Equal::new(&aml::Path::new("\\_SB_.PRES.CRMV"), &aml::ONE), + // Notify device if it is (with the eject constant 0x3) + vec![ + &aml::MethodCall::new("CTFY".into(), vec![&aml::Local(0), &3u8]), + // Reset CRMV bit + &aml::Store::new(&aml::Path::new("\\_SB_.PRES.CRMV"), &aml::ONE), + ], + ), + &aml::Add::new(&aml::Local(0), &aml::Local(0), &aml::ONE), + ], + ), + // Release lock + &aml::Release::new("\\_SB_.PRES.CPLK".into()), + ], + ) + .append_aml_bytes(bytes) } } #[cfg(feature = "acpi")] impl Aml for CpuManager { - fn to_aml_bytes(&self) -> Vec { - let mut bytes = Vec::new(); + fn append_aml_bytes(&self, bytes: &mut Vec) { // CPU hotplug controller #[cfg(target_arch = "x86_64")] - bytes.extend_from_slice( - &aml::Device::new( - "_SB_.PRES".into(), - vec![ - &aml::Name::new("_HID".into(), &aml::EisaName::new("PNP0A06")), - &aml::Name::new("_UID".into(), &"CPU Hotplug Controller"), - // Mutex to protect concurrent access as we write to choose CPU and then read back status - &aml::Mutex::new("CPLK".into(), 0), - &aml::Name::new( - "_CRS".into(), - &aml::ResourceTemplate::new(vec![&aml::AddressSpace::new_memory( - aml::AddressSpaceCachable::NotCacheable, - true, - self.acpi_address.0 as u64, - self.acpi_address.0 + CPU_MANAGER_ACPI_SIZE as u64 - 1, - )]), - ), - // OpRegion and Fields map MMIO range into individual field values - &aml::OpRegion::new( - "PRST".into(), - aml::OpRegionSpace::SystemMemory, - self.acpi_address.0 as usize, - CPU_MANAGER_ACPI_SIZE, - ), - &aml::Field::new( - "PRST".into(), - aml::FieldAccessType::Byte, - aml::FieldUpdateRule::WriteAsZeroes, - vec![ - aml::FieldEntry::Reserved(32), - aml::FieldEntry::Named(*b"CPEN", 1), - aml::FieldEntry::Named(*b"CINS", 1), - aml::FieldEntry::Named(*b"CRMV", 1), - aml::FieldEntry::Named(*b"CEJ0", 1), - aml::FieldEntry::Reserved(4), - aml::FieldEntry::Named(*b"CCMD", 8), - ], - ), - &aml::Field::new( - "PRST".into(), - aml::FieldAccessType::DWord, - aml::FieldUpdateRule::Preserve, - vec![ - aml::FieldEntry::Named(*b"CSEL", 32), - aml::FieldEntry::Reserved(32), - aml::FieldEntry::Named(*b"CDAT", 32), - ], - ), - ], - ) - .to_aml_bytes(), - ); + aml::Device::new( + "_SB_.PRES".into(), + vec![ + &aml::Name::new("_HID".into(), &aml::EisaName::new("PNP0A06")), + &aml::Name::new("_UID".into(), &"CPU Hotplug Controller"), + // Mutex to protect concurrent access as we write to choose CPU and then read back status + &aml::Mutex::new("CPLK".into(), 0), + &aml::Name::new( + "_CRS".into(), + &aml::ResourceTemplate::new(vec![&aml::AddressSpace::new_memory( + aml::AddressSpaceCachable::NotCacheable, + true, + self.acpi_address.0 as u64, + self.acpi_address.0 + CPU_MANAGER_ACPI_SIZE as u64 - 1, + )]), + ), + // OpRegion and Fields map MMIO range into individual field values + &aml::OpRegion::new( + "PRST".into(), + aml::OpRegionSpace::SystemMemory, + self.acpi_address.0 as usize, + CPU_MANAGER_ACPI_SIZE, + ), + &aml::Field::new( + "PRST".into(), + aml::FieldAccessType::Byte, + aml::FieldUpdateRule::WriteAsZeroes, + vec![ + aml::FieldEntry::Reserved(32), + aml::FieldEntry::Named(*b"CPEN", 1), + aml::FieldEntry::Named(*b"CINS", 1), + aml::FieldEntry::Named(*b"CRMV", 1), + aml::FieldEntry::Named(*b"CEJ0", 1), + aml::FieldEntry::Reserved(4), + aml::FieldEntry::Named(*b"CCMD", 8), + ], + ), + &aml::Field::new( + "PRST".into(), + aml::FieldAccessType::DWord, + aml::FieldUpdateRule::Preserve, + vec![ + aml::FieldEntry::Named(*b"CSEL", 32), + aml::FieldEntry::Reserved(32), + aml::FieldEntry::Named(*b"CDAT", 32), + ], + ), + ], + ) + .append_aml_bytes(bytes); // CPU devices let hid = aml::Name::new("_HID".into(), &"ACPI0010"); @@ -1534,10 +1512,7 @@ impl Aml for CpuManager { cpu_data_inner.push(cpu_device); } - bytes.extend_from_slice( - &aml::Device::new("_SB_.CPUS".into(), cpu_data_inner).to_aml_bytes(), - ); - bytes + aml::Device::new("_SB_.CPUS".into(), cpu_data_inner).append_aml_bytes(bytes) } }