mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-02 11:35:46 +00:00
vmm, devices: Move logging of 0x80 timestamp to its own device
This is a cleaner approach to handling the I/O port write to 0x80. Whilst doing this also use generate the timestamp at the start of the VM creation. For consistency use the same timestamp for the ARM equivalent. Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
c47e3b8689
commit
707cea2182
86
devices/src/legacy/debug_port.rs
Normal file
86
devices/src/legacy/debug_port.rs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
// Copyright © 2022 Intel Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
use std::time::Instant;
|
||||||
|
use vm_device::BusDevice;
|
||||||
|
|
||||||
|
/// Debug I/O port, see:
|
||||||
|
/// https://www.intel.com/content/www/us/en/support/articles/000005500/boards-and-kits.html
|
||||||
|
///
|
||||||
|
/// Since we're not a physical platform, we can freely assign code ranges for
|
||||||
|
/// debugging specific parts of our virtual platform.
|
||||||
|
pub enum DebugIoPortRange {
|
||||||
|
Firmware,
|
||||||
|
Bootloader,
|
||||||
|
Kernel,
|
||||||
|
Userspace,
|
||||||
|
Custom,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
const DEBUG_IOPORT_PREFIX: &str = "Debug I/O port";
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
impl DebugIoPortRange {
|
||||||
|
fn from_u8(value: u8) -> DebugIoPortRange {
|
||||||
|
match value {
|
||||||
|
0x00..=0x1f => DebugIoPortRange::Firmware,
|
||||||
|
0x20..=0x3f => DebugIoPortRange::Bootloader,
|
||||||
|
0x40..=0x5f => DebugIoPortRange::Kernel,
|
||||||
|
0x60..=0x7f => DebugIoPortRange::Userspace,
|
||||||
|
_ => DebugIoPortRange::Custom,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
impl fmt::Display for DebugIoPortRange {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
DebugIoPortRange::Firmware => write!(f, "{}: Firmware", DEBUG_IOPORT_PREFIX),
|
||||||
|
DebugIoPortRange::Bootloader => write!(f, "{}: Bootloader", DEBUG_IOPORT_PREFIX),
|
||||||
|
DebugIoPortRange::Kernel => write!(f, "{}: Kernel", DEBUG_IOPORT_PREFIX),
|
||||||
|
DebugIoPortRange::Userspace => write!(f, "{}: Userspace", DEBUG_IOPORT_PREFIX),
|
||||||
|
DebugIoPortRange::Custom => write!(f, "{}: Custom", DEBUG_IOPORT_PREFIX),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DebugPort {
|
||||||
|
timestamp: Instant,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DebugPort {
|
||||||
|
pub fn new(timestamp: Instant) -> Self {
|
||||||
|
Self { timestamp }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BusDevice for DebugPort {
|
||||||
|
fn read(&mut self, _base: u64, _offset: u64, _data: &mut [u8]) {
|
||||||
|
error!("Invalid read to debug port")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(
|
||||||
|
&mut self,
|
||||||
|
_base: u64,
|
||||||
|
_offset: u64,
|
||||||
|
data: &[u8],
|
||||||
|
) -> Option<std::sync::Arc<std::sync::Barrier>> {
|
||||||
|
let elapsed = self.timestamp.elapsed();
|
||||||
|
|
||||||
|
let code = data[0];
|
||||||
|
info!(
|
||||||
|
"[{} code 0x{:x}] {}.{:>06} seconds",
|
||||||
|
DebugIoPortRange::from_u8(code),
|
||||||
|
code,
|
||||||
|
elapsed.as_secs(),
|
||||||
|
elapsed.as_micros()
|
||||||
|
);
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,8 @@
|
|||||||
// found in the LICENSE-BSD-3-Clause file.
|
// found in the LICENSE-BSD-3-Clause file.
|
||||||
|
|
||||||
mod cmos;
|
mod cmos;
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
mod debug_port;
|
||||||
#[cfg(feature = "fwdebug")]
|
#[cfg(feature = "fwdebug")]
|
||||||
mod fwdebug;
|
mod fwdebug;
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
@ -18,6 +20,8 @@ mod serial;
|
|||||||
mod uart_pl011;
|
mod uart_pl011;
|
||||||
|
|
||||||
pub use self::cmos::Cmos;
|
pub use self::cmos::Cmos;
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
pub use self::debug_port::DebugPort;
|
||||||
#[cfg(feature = "fwdebug")]
|
#[cfg(feature = "fwdebug")]
|
||||||
pub use self::fwdebug::FwDebugDevice;
|
pub use self::fwdebug::FwDebugDevice;
|
||||||
pub use self::i8042::I8042Device;
|
pub use self::i8042::I8042Device;
|
||||||
|
@ -10,6 +10,7 @@ use crate::{read_le_u32, write_le_u32};
|
|||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::{Arc, Barrier};
|
use std::sync::{Arc, Barrier};
|
||||||
|
use std::time::Instant;
|
||||||
use std::{io, result};
|
use std::{io, result};
|
||||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||||
use versionize_derive::Versionize;
|
use versionize_derive::Versionize;
|
||||||
@ -120,6 +121,7 @@ impl Pl011 {
|
|||||||
id: String,
|
id: String,
|
||||||
irq: Arc<dyn InterruptSourceGroup>,
|
irq: Arc<dyn InterruptSourceGroup>,
|
||||||
out: Option<Box<dyn io::Write + Send>>,
|
out: Option<Box<dyn io::Write + Send>>,
|
||||||
|
timestamp: Instant,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
@ -140,7 +142,7 @@ impl Pl011 {
|
|||||||
read_trigger: 1u32,
|
read_trigger: 1u32,
|
||||||
irq,
|
irq,
|
||||||
out,
|
out,
|
||||||
timestamp: std::time::Instant::now(),
|
timestamp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,6 +497,7 @@ mod tests {
|
|||||||
String::from(SERIAL_NAME),
|
String::from(SERIAL_NAME),
|
||||||
Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())),
|
Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())),
|
||||||
Some(Box::new(pl011_out.clone())),
|
Some(Box::new(pl011_out.clone())),
|
||||||
|
Instant::now(),
|
||||||
);
|
);
|
||||||
|
|
||||||
pl011.write(0, UARTDR as u64, &[b'x', b'y']);
|
pl011.write(0, UARTDR as u64, &[b'x', b'y']);
|
||||||
@ -515,6 +518,7 @@ mod tests {
|
|||||||
String::from(SERIAL_NAME),
|
String::from(SERIAL_NAME),
|
||||||
Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())),
|
Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())),
|
||||||
Some(Box::new(pl011_out)),
|
Some(Box::new(pl011_out)),
|
||||||
|
Instant::now(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// write 1 to the interrupt event fd, so that read doesn't block in case the event fd
|
// write 1 to the interrupt event fd, so that read doesn't block in case the event fd
|
||||||
|
@ -83,6 +83,7 @@ use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::time::Instant;
|
||||||
use vfio_ioctls::{VfioContainer, VfioDevice};
|
use vfio_ioctls::{VfioContainer, VfioDevice};
|
||||||
use virtio_devices::transport::VirtioPciDevice;
|
use virtio_devices::transport::VirtioPciDevice;
|
||||||
use virtio_devices::transport::VirtioTransport;
|
use virtio_devices::transport::VirtioTransport;
|
||||||
@ -941,6 +942,9 @@ pub struct DeviceManager {
|
|||||||
|
|
||||||
// List of unique identifiers provided at boot through the configuration.
|
// List of unique identifiers provided at boot through the configuration.
|
||||||
boot_id_list: BTreeSet<String>,
|
boot_id_list: BTreeSet<String>,
|
||||||
|
|
||||||
|
// Start time of the VM
|
||||||
|
timestamp: Instant,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeviceManager {
|
impl DeviceManager {
|
||||||
@ -957,6 +961,7 @@ impl DeviceManager {
|
|||||||
force_iommu: bool,
|
force_iommu: bool,
|
||||||
restoring: bool,
|
restoring: bool,
|
||||||
boot_id_list: BTreeSet<String>,
|
boot_id_list: BTreeSet<String>,
|
||||||
|
timestamp: Instant,
|
||||||
) -> DeviceManagerResult<Arc<Mutex<Self>>> {
|
) -> DeviceManagerResult<Arc<Mutex<Self>>> {
|
||||||
let device_tree = Arc::new(Mutex::new(DeviceTree::new()));
|
let device_tree = Arc::new(Mutex::new(DeviceTree::new()));
|
||||||
|
|
||||||
@ -1080,6 +1085,7 @@ impl DeviceManager {
|
|||||||
restoring,
|
restoring,
|
||||||
io_uring_supported: None,
|
io_uring_supported: None,
|
||||||
boot_id_list,
|
boot_id_list,
|
||||||
|
timestamp,
|
||||||
};
|
};
|
||||||
|
|
||||||
let device_manager = Arc::new(Mutex::new(device_manager));
|
let device_manager = Arc::new(Mutex::new(device_manager));
|
||||||
@ -1521,6 +1527,15 @@ impl DeviceManager {
|
|||||||
.map_err(DeviceManagerError::BusError)?;
|
.map_err(DeviceManagerError::BusError)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 0x80 debug port
|
||||||
|
let debug_port = Arc::new(Mutex::new(devices::legacy::DebugPort::new(self.timestamp)));
|
||||||
|
self.bus_devices
|
||||||
|
.push(Arc::clone(&debug_port) as Arc<Mutex<dyn BusDevice>>);
|
||||||
|
self.address_manager
|
||||||
|
.io_bus
|
||||||
|
.insert(debug_port, 0x80, 0x1)
|
||||||
|
.map_err(DeviceManagerError::BusError)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1722,6 +1737,7 @@ impl DeviceManager {
|
|||||||
id.clone(),
|
id.clone(),
|
||||||
interrupt_group,
|
interrupt_group,
|
||||||
serial_writer,
|
serial_writer,
|
||||||
|
self.timestamp,
|
||||||
)));
|
)));
|
||||||
|
|
||||||
self.bus_devices
|
self.bus_devices
|
||||||
|
@ -66,8 +66,6 @@ use std::cmp;
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
use std::fmt;
|
|
||||||
use std::fs::{File, OpenOptions};
|
use std::fs::{File, OpenOptions};
|
||||||
use std::io::{self, Read, Write};
|
use std::io::{self, Read, Write};
|
||||||
use std::io::{Seek, SeekFrom};
|
use std::io::{Seek, SeekFrom};
|
||||||
@ -78,6 +76,7 @@ use std::ops::Deref;
|
|||||||
use std::os::unix::net::UnixStream;
|
use std::os::unix::net::UnixStream;
|
||||||
use std::panic::AssertUnwindSafe;
|
use std::panic::AssertUnwindSafe;
|
||||||
use std::sync::{Arc, Mutex, RwLock};
|
use std::sync::{Arc, Mutex, RwLock};
|
||||||
|
use std::time::Instant;
|
||||||
use std::{result, str, thread};
|
use std::{result, str, thread};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use vm_device::Bus;
|
use vm_device::Bus;
|
||||||
@ -344,78 +343,15 @@ impl VmState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug I/O port
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
const DEBUG_IOPORT: u16 = 0x80;
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
const DEBUG_IOPORT_PREFIX: &str = "Debug I/O port";
|
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
/// Debug I/O port, see:
|
|
||||||
/// https://www.intel.com/content/www/us/en/support/articles/000005500/boards-and-kits.html
|
|
||||||
///
|
|
||||||
/// Since we're not a physical platform, we can freely assign code ranges for
|
|
||||||
/// debugging specific parts of our virtual platform.
|
|
||||||
pub enum DebugIoPortRange {
|
|
||||||
Firmware,
|
|
||||||
Bootloader,
|
|
||||||
Kernel,
|
|
||||||
Userspace,
|
|
||||||
Custom,
|
|
||||||
}
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
impl DebugIoPortRange {
|
|
||||||
fn from_u8(value: u8) -> DebugIoPortRange {
|
|
||||||
match value {
|
|
||||||
0x00..=0x1f => DebugIoPortRange::Firmware,
|
|
||||||
0x20..=0x3f => DebugIoPortRange::Bootloader,
|
|
||||||
0x40..=0x5f => DebugIoPortRange::Kernel,
|
|
||||||
0x60..=0x7f => DebugIoPortRange::Userspace,
|
|
||||||
_ => DebugIoPortRange::Custom,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
impl fmt::Display for DebugIoPortRange {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
DebugIoPortRange::Firmware => write!(f, "{}: Firmware", DEBUG_IOPORT_PREFIX),
|
|
||||||
DebugIoPortRange::Bootloader => write!(f, "{}: Bootloader", DEBUG_IOPORT_PREFIX),
|
|
||||||
DebugIoPortRange::Kernel => write!(f, "{}: Kernel", DEBUG_IOPORT_PREFIX),
|
|
||||||
DebugIoPortRange::Userspace => write!(f, "{}: Userspace", DEBUG_IOPORT_PREFIX),
|
|
||||||
DebugIoPortRange::Custom => write!(f, "{}: Custom", DEBUG_IOPORT_PREFIX),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct VmOps {
|
struct VmOps {
|
||||||
memory: GuestMemoryAtomic<GuestMemoryMmap>,
|
memory: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
io_bus: Arc<Bus>,
|
io_bus: Arc<Bus>,
|
||||||
mmio_bus: Arc<Bus>,
|
mmio_bus: Arc<Bus>,
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
timestamp: std::time::Instant,
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
pci_config_io: Arc<Mutex<dyn BusDevice>>,
|
pci_config_io: Arc<Mutex<dyn BusDevice>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VmOps {
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
// Log debug io port codes.
|
|
||||||
fn log_debug_ioport(&self, code: u8) {
|
|
||||||
let elapsed = self.timestamp.elapsed();
|
|
||||||
|
|
||||||
info!(
|
|
||||||
"[{} code 0x{:x}] {}.{:>06} seconds",
|
|
||||||
DebugIoPortRange::from_u8(code),
|
|
||||||
code,
|
|
||||||
elapsed.as_secs(),
|
|
||||||
elapsed.as_micros()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VmmOps for VmOps {
|
impl VmmOps for VmOps {
|
||||||
fn guest_mem_write(&self, gpa: u64, buf: &[u8]) -> hypervisor::vm::Result<usize> {
|
fn guest_mem_write(&self, gpa: u64, buf: &[u8]) -> hypervisor::vm::Result<usize> {
|
||||||
self.memory
|
self.memory
|
||||||
@ -476,11 +412,6 @@ impl VmmOps for VmOps {
|
|||||||
fn pio_write(&self, port: u64, data: &[u8]) -> hypervisor::vm::Result<()> {
|
fn pio_write(&self, port: u64, data: &[u8]) -> hypervisor::vm::Result<()> {
|
||||||
use pci::{PCI_CONFIG_IO_PORT, PCI_CONFIG_IO_PORT_SIZE};
|
use pci::{PCI_CONFIG_IO_PORT, PCI_CONFIG_IO_PORT_SIZE};
|
||||||
|
|
||||||
if port == DEBUG_IOPORT as u64 && data.len() == 1 {
|
|
||||||
self.log_debug_ioport(data[0]);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PCI_CONFIG_IO_PORT..(PCI_CONFIG_IO_PORT + PCI_CONFIG_IO_PORT_SIZE)).contains(&port) {
|
if (PCI_CONFIG_IO_PORT..(PCI_CONFIG_IO_PORT + PCI_CONFIG_IO_PORT_SIZE)).contains(&port) {
|
||||||
self.pci_config_io.lock().unwrap().write(
|
self.pci_config_io.lock().unwrap().write(
|
||||||
PCI_CONFIG_IO_PORT,
|
PCI_CONFIG_IO_PORT,
|
||||||
@ -553,6 +484,7 @@ impl Vm {
|
|||||||
hypervisor: Arc<dyn hypervisor::Hypervisor>,
|
hypervisor: Arc<dyn hypervisor::Hypervisor>,
|
||||||
activate_evt: EventFd,
|
activate_evt: EventFd,
|
||||||
restoring: bool,
|
restoring: bool,
|
||||||
|
timestamp: Instant,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let kernel = config
|
let kernel = config
|
||||||
.lock()
|
.lock()
|
||||||
@ -604,6 +536,7 @@ impl Vm {
|
|||||||
force_iommu,
|
force_iommu,
|
||||||
restoring,
|
restoring,
|
||||||
boot_id_list,
|
boot_id_list,
|
||||||
|
timestamp,
|
||||||
)
|
)
|
||||||
.map_err(Error::DeviceManager)?;
|
.map_err(Error::DeviceManager)?;
|
||||||
|
|
||||||
@ -623,8 +556,6 @@ impl Vm {
|
|||||||
io_bus,
|
io_bus,
|
||||||
mmio_bus,
|
mmio_bus,
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
timestamp: std::time::Instant::now(),
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
pci_config_io,
|
pci_config_io,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -780,6 +711,8 @@ impl Vm {
|
|||||||
console_pty: Option<PtyPair>,
|
console_pty: Option<PtyPair>,
|
||||||
console_resize_pipe: Option<File>,
|
console_resize_pipe: Option<File>,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
|
let timestamp = Instant::now();
|
||||||
|
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
let tdx_enabled = config.lock().unwrap().tdx.is_some();
|
let tdx_enabled = config.lock().unwrap().tdx.is_some();
|
||||||
hypervisor.check_required_extensions().unwrap();
|
hypervisor.check_required_extensions().unwrap();
|
||||||
@ -833,6 +766,7 @@ impl Vm {
|
|||||||
hypervisor,
|
hypervisor,
|
||||||
activate_evt,
|
activate_evt,
|
||||||
false,
|
false,
|
||||||
|
timestamp,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// The device manager must create the devices from here as it is part
|
// The device manager must create the devices from here as it is part
|
||||||
@ -859,6 +793,8 @@ impl Vm {
|
|||||||
hypervisor: Arc<dyn hypervisor::Hypervisor>,
|
hypervisor: Arc<dyn hypervisor::Hypervisor>,
|
||||||
activate_evt: EventFd,
|
activate_evt: EventFd,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
|
let timestamp = Instant::now();
|
||||||
|
|
||||||
hypervisor.check_required_extensions().unwrap();
|
hypervisor.check_required_extensions().unwrap();
|
||||||
let vm = hypervisor.create_vm().unwrap();
|
let vm = hypervisor.create_vm().unwrap();
|
||||||
|
|
||||||
@ -907,6 +843,7 @@ impl Vm {
|
|||||||
hypervisor,
|
hypervisor,
|
||||||
activate_evt,
|
activate_evt,
|
||||||
true,
|
true,
|
||||||
|
timestamp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -922,6 +859,8 @@ impl Vm {
|
|||||||
memory_manager_data: &MemoryManagerSnapshotData,
|
memory_manager_data: &MemoryManagerSnapshotData,
|
||||||
existing_memory_files: Option<HashMap<u32, File>>,
|
existing_memory_files: Option<HashMap<u32, File>>,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
|
let timestamp = Instant::now();
|
||||||
|
|
||||||
hypervisor.check_required_extensions().unwrap();
|
hypervisor.check_required_extensions().unwrap();
|
||||||
let vm = hypervisor.create_vm().unwrap();
|
let vm = hypervisor.create_vm().unwrap();
|
||||||
|
|
||||||
@ -961,6 +900,7 @@ impl Vm {
|
|||||||
hypervisor,
|
hypervisor,
|
||||||
activate_evt,
|
activate_evt,
|
||||||
true,
|
true,
|
||||||
|
timestamp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user