Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/firecracker/src/generated/prctl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ pub const PR_MTE_TCF_MASK: u32 = 6;
pub const PR_MTE_TAG_SHIFT: u32 = 3;
pub const PR_MTE_TAG_MASK: u32 = 524280;
pub const PR_MTE_TCF_SHIFT: u32 = 1;
pub const PR_PMLEN_SHIFT: u32 = 24;
pub const PR_PMLEN_MASK: u32 = 2130706432;
pub const PR_SET_IO_FLUSHER: u32 = 57;
pub const PR_GET_IO_FLUSHER: u32 = 58;
pub const PR_SET_SYSCALL_USER_DISPATCH: u32 = 59;
Expand Down Expand Up @@ -197,3 +199,9 @@ pub const PR_PPC_DEXCR_CTRL_CLEAR: u32 = 4;
pub const PR_PPC_DEXCR_CTRL_SET_ONEXEC: u32 = 8;
pub const PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC: u32 = 16;
pub const PR_PPC_DEXCR_CTRL_MASK: u32 = 31;
pub const PR_GET_SHADOW_STACK_STATUS: u32 = 74;
pub const PR_SET_SHADOW_STACK_STATUS: u32 = 75;
pub const PR_SHADOW_STACK_ENABLE: u32 = 1;
pub const PR_SHADOW_STACK_WRITE: u32 = 2;
pub const PR_SHADOW_STACK_PUSH: u32 = 4;
pub const PR_LOCK_SHADOW_STACK_STATUS: u32 = 76;
43 changes: 9 additions & 34 deletions src/vmm/src/arch/aarch64/fdt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,17 +275,15 @@ fn create_chosen_node(
Ok(())
}

fn create_vmgenid_node(fdt: &mut FdtWriter, vmgenid: &Option<VmGenId>) -> Result<(), FdtError> {
if let Some(vmgenid_info) = vmgenid {
let vmgenid = fdt.begin_node("vmgenid")?;
fdt.property_string("compatible", "microsoft,vmgenid")?;
fdt.property_array_u64("reg", &[vmgenid_info.guest_address.0, VMGENID_MEM_SIZE])?;
fdt.property_array_u32(
"interrupts",
&[GIC_FDT_IRQ_TYPE_SPI, vmgenid_info.gsi, IRQ_TYPE_EDGE_RISING],
)?;
fdt.end_node(vmgenid)?;
}
fn create_vmgenid_node(fdt: &mut FdtWriter, vmgenid: &VmGenId) -> Result<(), FdtError> {
let vmgenid_node = fdt.begin_node("vmgenid")?;
fdt.property_string("compatible", "microsoft,vmgenid")?;
fdt.property_array_u64("reg", &[vmgenid.guest_address.0, VMGENID_MEM_SIZE])?;
fdt.property_array_u32(
"interrupts",
&[GIC_FDT_IRQ_TYPE_SPI, vmgenid.gsi, IRQ_TYPE_EDGE_RISING],
)?;
fdt.end_node(vmgenid_node)?;
Ok(())
}

Expand Down Expand Up @@ -586,29 +584,6 @@ mod tests {
.unwrap();
}

#[test]
fn test_create_fdt_with_vmgenid() {
let mem = arch_mem(layout::FDT_MAX_SIZE + 0x1000);
let mut device_manager = default_device_manager();
let kvm = Kvm::new(vec![]).unwrap();
let vm = Vm::new(&kvm).unwrap();
let gic = create_gic(vm.fd(), 1, None).unwrap();
let mut cmdline = kernel_cmdline::Cmdline::new(4096).unwrap();
cmdline.insert("console", "/dev/tty0").unwrap();

device_manager.attach_vmgenid_device(&mem, &vm).unwrap();

create_fdt(
&mem,
vec![0],
CString::new("console=tty0").unwrap(),
&device_manager,
&gic,
&None,
)
.unwrap();
}

#[test]
fn test_create_fdt() {
let mem = arch_mem(layout::FDT_MAX_SIZE + 0x1000);
Expand Down
Binary file modified src/vmm/src/arch/aarch64/output_GICv3.dtb
Binary file not shown.
Binary file modified src/vmm/src/arch/aarch64/output_initrd_GICv3.dtb
Binary file not shown.
1 change: 0 additions & 1 deletion src/vmm/src/arch/x86_64/generated/msr_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ pub const MSR_AMD64_OSVW_ID_LENGTH: u32 = 0xc0010140;
pub const MSR_AMD64_OSVW_STATUS: u32 = 0xc0010141;
pub const MSR_AMD_PPIN_CTL: u32 = 0xc00102f0;
pub const MSR_AMD_PPIN: u32 = 0xc00102f1;
pub const MSR_AMD64_CPUID_FN_7: u32 = 0xc0011002;
pub const MSR_AMD64_CPUID_FN_1: u32 = 0xc0011004;
pub const MSR_AMD64_LS_CFG: u32 = 0xc0011020;
pub const MSR_AMD64_DC_CFG: u32 = 0xc0011022;
Expand Down
17 changes: 9 additions & 8 deletions src/vmm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ use crate::device_manager::{
AttachDeviceError, DeviceManager, DeviceManagerCreateError, DevicePersistError,
DeviceRestoreArgs,
};
use crate::devices::acpi::vmgenid::VmGenIdError;
use crate::devices::virtio::balloon::Balloon;
use crate::devices::virtio::block::device::Block;
use crate::devices::virtio::net::Net;
Expand Down Expand Up @@ -76,8 +75,6 @@ pub enum StartMicrovmError {
/// Error creating legacy device: {0}
#[cfg(target_arch = "x86_64")]
CreateLegacyDevice(device_manager::legacy::LegacyDeviceError),
/// Error creating VMGenID device: {0}
CreateVMGenID(VmGenIdError),
/// Error enabling PCIe support: {0}
EnablePciDevices(#[from] PciManagerError),
/// Error enabling pvtime on vcpu: {0}
Expand Down Expand Up @@ -258,7 +255,9 @@ pub fn build_microvm_for_boot(
vm_resources.serial_out_path.as_ref(),
)?;

device_manager.attach_vmgenid_device(vm.guest_memory(), &vm)?;
device_manager.attach_vmgenid_device(&vm)?;
#[cfg(target_arch = "x86_64")]
device_manager.attach_vmclock_device(&vm)?;

#[cfg(target_arch = "aarch64")]
if vcpus[0].kvm_vcpu.supports_pvtime() {
Expand Down Expand Up @@ -943,10 +942,12 @@ pub(crate) mod tests {

#[cfg(target_arch = "x86_64")]
pub(crate) fn insert_vmgenid_device(vmm: &mut Vmm) {
vmm.device_manager
.attach_vmgenid_device(vmm.vm.guest_memory(), &vmm.vm)
.unwrap();
assert!(vmm.device_manager.acpi_devices.vmgenid.is_some());
vmm.device_manager.attach_vmgenid_device(&vmm.vm).unwrap();
}

#[cfg(target_arch = "x86_64")]
pub(crate) fn insert_vmclock_device(vmm: &mut Vmm) {
vmm.device_manager.attach_vmclock_device(&vmm.vm).unwrap();
}

pub(crate) fn insert_balloon_device(
Expand Down
128 changes: 70 additions & 58 deletions src/vmm/src/device_manager/acpi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,84 +2,96 @@
// SPDX-License-Identifier: Apache-2.0

use acpi_tables::{Aml, aml};
use vm_memory::GuestMemoryError;

use crate::Vm;
#[cfg(target_arch = "x86_64")]
use crate::devices::acpi::vmclock::VmClock;
use crate::devices::acpi::vmgenid::VmGenId;
use crate::vstate::resources::ResourceAllocator;

#[derive(Debug, Default)]
#[derive(Debug, thiserror::Error, displaydoc::Display)]
pub enum ACPIDeviceError {
/// Could not register GSI with KVM: {0}
RegisterIrq(#[from] kvm_ioctls::Error),
/// Could not write to guest memory: {0}
WriteGuestMemory(#[from] GuestMemoryError),
}

#[derive(Debug)]
pub struct ACPIDeviceManager {
/// VMGenID device
pub vmgenid: Option<VmGenId>,
pub vmgenid: VmGenId,
/// VMclock device
#[cfg(target_arch = "x86_64")]
pub vmclock: VmClock,
}

impl ACPIDeviceManager {
/// Create a new ACPIDeviceManager object
pub fn new() -> Self {
Default::default()
pub fn new(resource_allocator: &mut ResourceAllocator) -> Self {
ACPIDeviceManager {
vmgenid: VmGenId::new(resource_allocator),
#[cfg(target_arch = "x86_64")]
vmclock: VmClock::new(resource_allocator),
}
}

/// Attach a new VMGenID device to the microVM
///
/// This will register the device's interrupt with KVM
pub fn attach_vmgenid(&mut self, vmgenid: VmGenId, vm: &Vm) -> Result<(), kvm_ioctls::Error> {
vm.register_irq(&vmgenid.interrupt_evt, vmgenid.gsi)?;
self.vmgenid = Some(vmgenid);
pub fn attach_vmgenid(&self, vm: &Vm) -> Result<(), ACPIDeviceError> {
vm.register_irq(&self.vmgenid.interrupt_evt, self.vmgenid.gsi)?;
self.vmgenid.activate(vm.guest_memory())?;
Ok(())
}

/// If it exists, notify guest VMGenID device that we have resumed from a snapshot.
pub fn notify_vmgenid(&mut self) -> Result<(), std::io::Error> {
if let Some(vmgenid) = &mut self.vmgenid {
vmgenid.notify_guest()?;
}
#[cfg(target_arch = "x86_64")]
pub fn attach_vmclock(&self, vm: &Vm) -> Result<(), ACPIDeviceError> {
self.vmclock.activate(vm.guest_memory())?;
Ok(())
}
}

impl Aml for ACPIDeviceManager {
fn append_aml_bytes(&self, v: &mut Vec<u8>) -> Result<(), aml::AmlError> {
// If we have a VMGenID device, create the AML for the device and GED interrupt handler
match self.vmgenid.as_ref() {
Some(vmgenid) => {
// AML for GED
aml::Device::new(
"_SB_.GED_".try_into()?,
vec![
&aml::Name::new("_HID".try_into()?, &"ACPI0013")?,
&aml::Name::new(
"_CRS".try_into()?,
&aml::ResourceTemplate::new(vec![&aml::Interrupt::new(
true,
true,
false,
false,
vmgenid.gsi,
)]),
)?,
&aml::Method::new(
"_EVT".try_into()?,
1,
true,
vec![&aml::If::new(
// We know that the maximum IRQ number fits in a u8. We have up to
// 32 IRQs in x86 and up to 128 in
// ARM (look into
// `vmm::crate::arch::layout::GSI_LEGACY_END`)
#[allow(clippy::cast_possible_truncation)]
&aml::Equal::new(&aml::Arg(0), &(vmgenid.gsi as u8)),
vec![&aml::Notify::new(
&aml::Path::new("\\_SB_.VGEN")?,
&0x80usize,
)],
)],
),
],
)
.append_aml_bytes(v)?;
// AML for VMGenID itself.
vmgenid.append_aml_bytes(v)
}
None => Ok(()),
}
// AML for [`VmGenId`] device.
self.vmgenid.append_aml_bytes(v)?;
// AML for [`VmClock`] device.
#[cfg(target_arch = "x86_64")]
self.vmclock.append_aml_bytes(v)?;

// Create the AML for the GED interrupt handler
aml::Device::new(
"_SB_.GED_".try_into()?,
vec![
&aml::Name::new("_HID".try_into()?, &"ACPI0013")?,
&aml::Name::new(
"_CRS".try_into()?,
&aml::ResourceTemplate::new(vec![&aml::Interrupt::new(
true,
true,
false,
false,
self.vmgenid.gsi,
)]),
)?,
&aml::Method::new(
"_EVT".try_into()?,
1,
true,
vec![&aml::If::new(
// We know that the maximum IRQ number fits in a u8. We have up to
// 32 IRQs in x86 and up to 128 in
// ARM (look into
// `vmm::crate::arch::layout::GSI_LEGACY_END`)
#[allow(clippy::cast_possible_truncation)]
&aml::Equal::new(&aml::Arg(0), &(self.vmgenid.gsi as u8)),
vec![&aml::Notify::new(
&aml::Path::new("\\_SB_.VGEN")?,
&0x80usize,
)],
)],
),
],
)
.append_aml_bytes(v)
}
}
41 changes: 19 additions & 22 deletions src/vmm/src/device_manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ use linux_loader::loader::Cmdline;
use log::{error, info};
use mmio::{MMIODeviceManager, MmioError};
use pci_mngr::{PciDevices, PciDevicesConstructorArgs, PciManagerError};
use persist::{ACPIDeviceManagerConstructorArgs, MMIODevManagerConstructorArgs};
use persist::MMIODevManagerConstructorArgs;
use serde::{Deserialize, Serialize};
use utils::time::TimestampUs;
use vmm_sys_util::eventfd::EventFd;

use crate::devices::acpi::vmgenid::{VmGenId, VmGenIdError};
use crate::device_manager::acpi::ACPIDeviceError;
#[cfg(target_arch = "x86_64")]
use crate::devices::legacy::I8042Device;
#[cfg(target_arch = "aarch64")]
Expand Down Expand Up @@ -70,10 +70,8 @@ pub enum AttachDeviceError {
MmioTransport(#[from] MmioError),
/// Error inserting device in bus: {0}
Bus(#[from] BusError),
/// Error creating VMGenID device: {0}
CreateVmGenID(#[from] VmGenIdError),
/// Error while registering VMGenID with KVM: {0}
AttachVmGenID(#[from] kvm_ioctls::Error),
/// Error while registering ACPI with KVM: {0}
AttachAcpiDevice(#[from] ACPIDeviceError),
#[cfg(target_arch = "aarch64")]
/// Cmdline error
Cmdline,
Expand Down Expand Up @@ -176,7 +174,7 @@ impl DeviceManager {
mmio_devices: MMIODeviceManager::new(),
#[cfg(target_arch = "x86_64")]
legacy_devices,
acpi_devices: ACPIDeviceManager::new(),
acpi_devices: ACPIDeviceManager::new(&mut vm.resource_allocator()),
pci_devices: PciDevices::new(),
})
}
Expand Down Expand Up @@ -234,13 +232,14 @@ impl DeviceManager {
Ok(())
}

pub(crate) fn attach_vmgenid_device(
&mut self,
mem: &GuestMemoryMmap,
vm: &Vm,
) -> Result<(), AttachDeviceError> {
let vmgenid = VmGenId::new(mem, &mut vm.resource_allocator())?;
self.acpi_devices.attach_vmgenid(vmgenid, vm)?;
pub(crate) fn attach_vmgenid_device(&mut self, vm: &Vm) -> Result<(), AttachDeviceError> {
self.acpi_devices.attach_vmgenid(vm)?;
Ok(())
}

#[cfg(target_arch = "x86_64")]
pub(crate) fn attach_vmclock_device(&mut self, vm: &Vm) -> Result<(), AttachDeviceError> {
self.acpi_devices.attach_vmclock(vm)?;
Ok(())
}

Expand Down Expand Up @@ -394,7 +393,7 @@ pub enum DevicePersistError {
/// Error restoring MMIO devices: {0}
MmioRestore(#[from] persist::DevicePersistError),
/// Error restoring ACPI devices: {0}
AcpiRestore(#[from] persist::ACPIDeviceManagerRestoreError),
AcpiRestore(#[from] ACPIDeviceError),
/// Error restoring PCI devices: {0}
PciRestore(#[from] PciManagerError),
/// Error notifying VMGenID device: {0}
Expand Down Expand Up @@ -464,12 +463,8 @@ impl<'a> Persist<'a> for DeviceManager {
let mmio_devices = MMIODeviceManager::restore(mmio_ctor_args, &state.mmio_state)?;

// Restore ACPI devices
let acpi_ctor_args = ACPIDeviceManagerConstructorArgs {
mem: constructor_args.mem,
vm: constructor_args.vm,
};
let mut acpi_devices = ACPIDeviceManager::restore(acpi_ctor_args, &state.acpi_state)?;
acpi_devices.notify_vmgenid()?;
let mut acpi_devices = ACPIDeviceManager::restore(constructor_args.vm, &state.acpi_state)?;
acpi_devices.vmgenid.notify_guest()?;

// Restore PCI devices
let pci_ctor_args = PciDevicesConstructorArgs {
Expand Down Expand Up @@ -542,10 +537,12 @@ pub(crate) mod tests {
use super::*;
#[cfg(target_arch = "aarch64")]
use crate::builder::tests::default_vmm;
use crate::vstate::resources::ResourceAllocator;

pub(crate) fn default_device_manager() -> DeviceManager {
let mut resource_allocator = ResourceAllocator::new();
let mmio_devices = MMIODeviceManager::new();
let acpi_devices = ACPIDeviceManager::new();
let acpi_devices = ACPIDeviceManager::new(&mut resource_allocator);
let pci_devices = PciDevices::new();

#[cfg(target_arch = "x86_64")]
Expand Down
Loading