mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-10-24 05:09:47 +00:00
Arch: Vfio device could be created and configured at runtime
When a vfio pci device is added through hotplug in, it should be configured at runtime and added into pci_root->devices tree, so pci_root is added into linux. BUG=b:185084350 TEST=Boot a guest with and without passthrough device Change-Id: Ibcb5f4a849134f64fbceeac645bebd80d6ca72d5 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2954672 Tested-by: kokoro <noreply+kokoro@google.com> Commit-Queue: Daniel Verkamp <dverkamp@chromium.org> Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
This commit is contained in:
parent
b56de80b07
commit
8c9fe3ef34
6 changed files with 80 additions and 5 deletions
|
@ -167,6 +167,7 @@ pub enum Error {
|
|||
SetDeviceAttr(base::Error),
|
||||
SetReg(base::Error),
|
||||
SetupGuestMemory(GuestMemoryError),
|
||||
Unsupported,
|
||||
VcpuInit(base::Error),
|
||||
}
|
||||
|
||||
|
@ -206,6 +207,7 @@ impl Display for Error {
|
|||
SetDeviceAttr(e) => write!(f, "failed to set device attr: {}", e),
|
||||
SetReg(e) => write!(f, "failed to set register: {}", e),
|
||||
SetupGuestMemory(e) => write!(f, "failed to set up guest memory: {}", e),
|
||||
Unsupported => write!(f, "this function isn't supported"),
|
||||
VcpuInit(e) => write!(f, "failed to initialize VCPU: {}", e),
|
||||
}
|
||||
}
|
||||
|
@ -457,6 +459,7 @@ impl arch::LinuxArch for AArch64 {
|
|||
delay_rt: components.delay_rt,
|
||||
bat_control: None,
|
||||
resume_notify_devices: Vec::new(),
|
||||
root_config: pci_bus,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -473,6 +476,16 @@ impl arch::LinuxArch for AArch64 {
|
|||
// AArch64 doesn't configure vcpus on the vcpu thread, so nothing to do here.
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn register_pci_device<V: VmAArch64, Vcpu: VcpuAArch64>(
|
||||
_linux: &mut RunnableLinuxVm<V, Vcpu>,
|
||||
_device: Box<dyn PciDevice>,
|
||||
_minijail: Option<Minijail>,
|
||||
_resources: &mut SystemAllocator,
|
||||
) -> std::result::Result<(), Self::Error> {
|
||||
// hotplug function isn't verified on AArch64, so set it unsupported here.
|
||||
Err(Error::Unsupported)
|
||||
}
|
||||
}
|
||||
|
||||
impl AArch64 {
|
||||
|
|
|
@ -35,12 +35,12 @@ use gdbstub_arch::x86::reg::X86_64CoreRegs as GdbStubRegs;
|
|||
|
||||
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
|
||||
use {
|
||||
devices::IrqChipAArch64 as IrqChipArch,
|
||||
devices::{IrqChipAArch64 as IrqChipArch, PciConfigMmio as RootConfigArch},
|
||||
hypervisor::{Hypervisor as HypervisorArch, VcpuAArch64 as VcpuArch, VmAArch64 as VmArch},
|
||||
};
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
use {
|
||||
devices::IrqChipX86_64 as IrqChipArch,
|
||||
devices::{IrqChipX86_64 as IrqChipArch, PciConfigIo as RootConfigArch},
|
||||
hypervisor::{HypervisorX86_64 as HypervisorArch, VcpuX86_64 as VcpuArch, VmX86_64 as VmArch},
|
||||
};
|
||||
|
||||
|
@ -120,6 +120,7 @@ pub struct RunnableLinuxVm<V: VmArch, Vcpu: VcpuArch> {
|
|||
pub gdb: Option<(u32, Tube)>,
|
||||
/// Devices to be notified before the system resumes from the S3 suspended state.
|
||||
pub resume_notify_devices: Vec<Arc<Mutex<dyn BusResumeDevice>>>,
|
||||
pub root_config: Arc<Mutex<RootConfigArch>>,
|
||||
}
|
||||
|
||||
/// The device and optional jail.
|
||||
|
@ -203,6 +204,14 @@ pub trait LinuxArch {
|
|||
no_smt: bool,
|
||||
) -> Result<(), Self::Error>;
|
||||
|
||||
/// Configures and add a pci device into vm
|
||||
fn register_pci_device<V: VmArch, Vcpu: VcpuArch>(
|
||||
linux: &mut RunnableLinuxVm<V, Vcpu>,
|
||||
device: Box<dyn PciDevice>,
|
||||
minijail: Option<Minijail>,
|
||||
resources: &mut SystemAllocator,
|
||||
) -> Result<(), Self::Error>;
|
||||
|
||||
#[cfg(all(target_arch = "x86_64", feature = "gdb"))]
|
||||
/// Reads vCPU's registers.
|
||||
fn debug_read_registers<T: VcpuArch>(vcpu: &T) -> Result<GdbStubRegs, Self::Error>;
|
||||
|
@ -322,7 +331,6 @@ pub fn configure_pci_device<V: VmArch, Vcpu: VcpuArch>(
|
|||
linux: &mut RunnableLinuxVm<V, Vcpu>,
|
||||
mut device: Box<dyn PciDevice>,
|
||||
jail: Option<Minijail>,
|
||||
root: &mut PciRoot,
|
||||
resources: &mut SystemAllocator,
|
||||
) -> Result<(), DeviceRegistrationError> {
|
||||
// Allocate PCI device address before allocating BARs.
|
||||
|
@ -390,7 +398,12 @@ pub fn configure_pci_device<V: VmArch, Vcpu: VcpuArch>(
|
|||
device.on_sandboxed();
|
||||
Arc::new(Mutex::new(device))
|
||||
};
|
||||
root.add_device(pci_address, arced_dev.clone());
|
||||
|
||||
linux
|
||||
.root_config
|
||||
.lock()
|
||||
.add_device(pci_address, arced_dev.clone());
|
||||
|
||||
for range in &mmio_ranges {
|
||||
linux
|
||||
.mmio_bus
|
||||
|
|
|
@ -261,6 +261,10 @@ impl PciConfigIo {
|
|||
};
|
||||
self.config_address = (self.config_address & !mask) | value;
|
||||
}
|
||||
|
||||
pub fn add_device(&mut self, address: PciAddress, device: Arc<Mutex<dyn BusDevice>>) {
|
||||
self.pci_root.add_device(address, device)
|
||||
}
|
||||
}
|
||||
|
||||
impl BusDevice for PciConfigIo {
|
||||
|
@ -321,6 +325,10 @@ impl PciConfigMmio {
|
|||
self.pci_root
|
||||
.config_space_write(address, register, offset, data)
|
||||
}
|
||||
|
||||
pub fn add_device(&mut self, address: PciAddress, device: Arc<Mutex<dyn BusDevice>>) {
|
||||
self.pci_root.add_device(address, device)
|
||||
}
|
||||
}
|
||||
|
||||
impl BusDevice for PciConfigMmio {
|
||||
|
|
|
@ -43,6 +43,7 @@ pub enum Error {
|
|||
CloneEvent(base::Error),
|
||||
CloneVcpu(base::Error),
|
||||
ConfigureVcpu(<Arch as LinuxArch>::Error),
|
||||
ConfigureVfioDevice(<Arch as LinuxArch>::Error),
|
||||
ConnectTube(io::Error),
|
||||
#[cfg(feature = "audio")]
|
||||
CreateAc97(devices::PciDeviceError),
|
||||
|
@ -169,6 +170,7 @@ impl Display for Error {
|
|||
CloneEvent(e) => write!(f, "failed to clone event: {}", e),
|
||||
CloneVcpu(e) => write!(f, "failed to clone vcpu: {}", e),
|
||||
ConfigureVcpu(e) => write!(f, "failed to configure vcpu: {}", e),
|
||||
ConfigureVfioDevice(e) => write!(f, "Failed to configure vfio device:{}", e),
|
||||
ConnectTube(e) => write!(f, "failed to connect to tube: {}", e),
|
||||
#[cfg(feature = "audio")]
|
||||
CreateAc97(e) => write!(f, "failed to create ac97 device: {}", e),
|
||||
|
|
26
src/linux.rs
26
src/linux.rs
|
@ -2512,6 +2512,32 @@ where
|
|||
)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn add_vfio_device<V: VmArch, Vcpu: VcpuArch>(
|
||||
linux: &mut RunnableLinuxVm<V, Vcpu>,
|
||||
sys_allocator: &mut SystemAllocator,
|
||||
cfg: &Config,
|
||||
control_tubes: &mut Vec<TaggedControlTube>,
|
||||
vfio_path: &Path,
|
||||
) -> Result<()> {
|
||||
let vm = &linux.vm;
|
||||
let mut endpoints: BTreeMap<u32, Arc<Mutex<VfioContainer>>> = BTreeMap::new();
|
||||
let (vfio_pci_device, jail) = create_vfio_device(
|
||||
cfg,
|
||||
vm,
|
||||
sys_allocator,
|
||||
control_tubes,
|
||||
vfio_path,
|
||||
&mut endpoints,
|
||||
false,
|
||||
)?;
|
||||
Arch::register_pci_device(linux, vfio_pci_device, jail, sys_allocator)
|
||||
.map_err(Error::ConfigureVfioDevice)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn remove_vfio_device() {}
|
||||
|
||||
/// Signals all running VCPUs to vmexit, sends VcpuControl message to each VCPU tube, and tells
|
||||
/// `irq_chip` to stop blocking halted VCPUs. The channel message is set first because both the
|
||||
/// signal and the irq_chip kick could cause the VCPU thread to continue through the VCPU run
|
||||
|
|
|
@ -83,6 +83,7 @@ pub enum Error {
|
|||
CloneEvent(base::Error),
|
||||
CloneIrqChip(base::Error),
|
||||
Cmdline(kernel_cmdline::Error),
|
||||
ConfigurePciDevice(arch::DeviceRegistrationError),
|
||||
ConfigureSystem,
|
||||
CreateBatDevices(arch::DeviceRegistrationError),
|
||||
CreateDevices(Box<dyn StdError>),
|
||||
|
@ -143,6 +144,7 @@ impl Display for Error {
|
|||
CloneEvent(e) => write!(f, "unable to clone an Event: {}", e),
|
||||
CloneIrqChip(e) => write!(f, "failed to clone IRQ chip: {}", e),
|
||||
Cmdline(e) => write!(f, "the given kernel command line was invalid: {}", e),
|
||||
ConfigurePciDevice(e) => write!(f, "failed to configure hotplugged pci device: {}", e),
|
||||
ConfigureSystem => write!(f, "error configuring the system"),
|
||||
CreateBatDevices(e) => write!(f, "unable to create battery devices: {}", e),
|
||||
CreateDevices(e) => write!(f, "error creating devices: {}", e),
|
||||
|
@ -413,7 +415,7 @@ impl arch::LinuxArch for X8664arch {
|
|||
)
|
||||
.map_err(Error::CreatePciRoot)?;
|
||||
let pci_bus = Arc::new(Mutex::new(PciConfigIo::new(pci)));
|
||||
io_bus.insert(pci_bus, 0xcf8, 0x8).unwrap();
|
||||
io_bus.insert(pci_bus.clone(), 0xcf8, 0x8).unwrap();
|
||||
|
||||
// Event used to notify crosvm that guest OS is trying to suspend.
|
||||
let suspend_evt = Event::new().map_err(Error::CreateEvent)?;
|
||||
|
@ -553,6 +555,7 @@ impl arch::LinuxArch for X8664arch {
|
|||
bat_control,
|
||||
#[cfg(all(target_arch = "x86_64", feature = "gdb"))]
|
||||
gdb: components.gdb,
|
||||
root_config: pci_bus,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -592,6 +595,16 @@ impl arch::LinuxArch for X8664arch {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn register_pci_device<V: VmX86_64, Vcpu: VcpuX86_64>(
|
||||
linux: &mut RunnableLinuxVm<V, Vcpu>,
|
||||
device: Box<dyn PciDevice>,
|
||||
minijail: Option<Minijail>,
|
||||
resources: &mut SystemAllocator,
|
||||
) -> Result<()> {
|
||||
arch::configure_pci_device(linux, device, minijail, resources)
|
||||
.map_err(Error::ConfigurePciDevice)
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "x86_64", feature = "gdb"))]
|
||||
fn debug_read_registers<T: VcpuX86_64>(vcpu: &T) -> Result<X86_64CoreRegs> {
|
||||
// General registers: RAX, RBX, RCX, RDX, RSI, RDI, RBP, RSP, r8-r15
|
||||
|
|
Loading…
Reference in a new issue