hypervisor, vmm: Remove shared ownership of VmmOps

This interface is used by the vCPU thread to delegate responsibility for
handling MMIO/PIO operations and to support different approaches than a
VM exit.

During profiling I found that we were spending 13.75% of the boot CPU
uage acquiring access to the object holding the VmmOps via
ArcSwap::load_full()

    13.75%     6.02%  vcpu0            cloud-hypervisor    [.] arc_swap::ArcSwapAny<T,S>::load_full
            |
            ---arc_swap::ArcSwapAny<T,S>::load_full
               |
                --13.43%--<hypervisor::kvm::KvmVcpu as hypervisor::cpu::Vcpu>::run
                          std::sys_common::backtrace::__rust_begin_short_backtrace
                          core::ops::function::FnOnce::call_once{{vtable-shim}}
                          std::sys::unix::thread::Thread::new::thread_start

However since the object implementing VmmOps does not need to be mutable
and it is only used from the vCPU side we can change the ownership to
being a simple Arc<> that is passed in when calling create_vcpu().

This completely removes the above CPU usage from subsequent profiles.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford
2020-11-18 16:37:52 +00:00
committed by Samuel Ortiz
parent 6a591ca81d
commit 0fec326582
5 changed files with 46 additions and 48 deletions

View File

@@ -500,15 +500,14 @@ impl Vm {
let mmio_bus = Arc::clone(device_manager.lock().unwrap().mmio_bus());
// Create the VmOps structure, which implements the VmmOps trait.
// And send it to the hypervisor.
let vm_ops = Box::new(VmOps {
let vm_ops: Arc<Box<dyn VmmOps>> = Arc::new(Box::new(VmOps {
memory,
#[cfg(target_arch = "x86_64")]
io_bus,
mmio_bus,
#[cfg(target_arch = "x86_64")]
timestamp: std::time::Instant::now(),
});
vm.set_vmmops(vm_ops).map_err(Error::SetVmmOpsInterface)?;
}));
let exit_evt_clone = exit_evt.try_clone().map_err(Error::EventFdClone)?;
let cpu_manager = cpu::CpuManager::new(
@@ -520,6 +519,7 @@ impl Vm {
reset_evt,
hypervisor,
seccomp_action.clone(),
vm_ops,
)
.map_err(Error::CpuManager)?;
@@ -2187,7 +2187,7 @@ pub fn test_vm() {
mem.write_slice(&code, load_addr)
.expect("Writing code to memory failed");
let vcpu = vm.create_vcpu(0).expect("new Vcpu failed");
let vcpu = vm.create_vcpu(0, None).expect("new Vcpu failed");
let mut vcpu_sregs = vcpu.get_sregs().expect("get sregs failed");
vcpu_sregs.cs.base = 0;