Merge 371e684edf
into 7966925c1c
This commit is contained in:
commit
890309853e
|
@ -1,3 +1,36 @@
|
|||
// Copyright 2022 Arm Limited (or its affiliates). All rights reserved.
|
||||
|
||||
pub mod gic;
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
|
||||
pub struct StandardRegisters {
|
||||
pub gpr: [u64; 31usize], // 31 General Purpose Registers
|
||||
pub sp: u64, // Stack Pointer
|
||||
pub pc: u64, // Program Counter
|
||||
pub pstate: u64, // Program Status Register
|
||||
pub sp_el1: u64, // Stack Pointer for EL1
|
||||
pub elr_el1: u64, // Exception Link Register for EL1
|
||||
pub spsr: [u64; 5usize], // Saved Program Status Registers
|
||||
pub vregs: [u128; 32usize], // 32 Floating Point Registers
|
||||
pub fpsr: u64, // Floating point status register
|
||||
pub fpcr: u64, // Floating point control register
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
|
||||
pub struct Register {
|
||||
pub id: u64,
|
||||
pub addr: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
|
||||
pub struct VcpuInit {
|
||||
pub target: u32,
|
||||
pub features: [u32; 7usize],
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
|
||||
pub struct RegList(pub Vec<u64>);
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
//
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use crate::aarch64::{RegList, StandardRegisters, VcpuInit};
|
||||
use crate::arch::aarch64::{RegList, StandardRegisters, VcpuInit};
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use crate::arch::x86::{
|
||||
CpuIdEntry, FpuState, LapicState, MsrEntry, SpecialRegisters, StandardRegisters,
|
||||
|
|
|
@ -206,6 +206,7 @@ pub fn construct_gicr_typers(vcpu_states: &[CpuState]) -> Vec<u64> {
|
|||
.sys_regs
|
||||
.into_iter()
|
||||
.filter(|reg| reg.id == KVM_ARM64_SYSREG_MPIDR_EL1)
|
||||
.map(|reg| reg.into())
|
||||
.collect();
|
||||
//calculate affinity
|
||||
let mut cpu_affid = mpidr[0].addr & 1095233437695;
|
||||
|
|
|
@ -10,14 +10,13 @@
|
|||
|
||||
pub mod gic;
|
||||
|
||||
use crate::arch::aarch64::{Register, StandardRegisters, VcpuInit};
|
||||
use crate::kvm::{KvmError, KvmResult};
|
||||
use kvm_bindings::{
|
||||
kvm_mp_state, kvm_one_reg, kvm_regs, KVM_REG_ARM_COPROC_MASK, KVM_REG_ARM_CORE,
|
||||
KVM_REG_SIZE_MASK, KVM_REG_SIZE_U32, KVM_REG_SIZE_U64,
|
||||
};
|
||||
pub use kvm_bindings::{
|
||||
kvm_one_reg as Register, kvm_regs as StandardRegisters, kvm_vcpu_init as VcpuInit, RegList,
|
||||
};
|
||||
pub use kvm_bindings::{kvm_vcpu_init, user_fpsimd_state, user_pt_regs};
|
||||
use serde::{Deserialize, Serialize};
|
||||
pub use {kvm_ioctls::Cap, kvm_ioctls::Kvm};
|
||||
|
||||
|
@ -121,3 +120,79 @@ pub struct VcpuKvmState {
|
|||
pub core_regs: kvm_regs,
|
||||
pub sys_regs: Vec<kvm_one_reg>,
|
||||
}
|
||||
|
||||
impl From<StandardRegisters> for kvm_regs {
|
||||
fn from(regs: StandardRegisters) -> Self {
|
||||
Self {
|
||||
regs: user_pt_regs {
|
||||
regs: regs.gpr,
|
||||
sp: regs.sp,
|
||||
pc: regs.pc,
|
||||
pstate: regs.pstate,
|
||||
},
|
||||
sp_el1: regs.sp_el1,
|
||||
elr_el1: regs.elr_el1,
|
||||
spsr: regs.spsr,
|
||||
fp_regs: user_fpsimd_state {
|
||||
vregs: regs.vregs,
|
||||
fpsr: regs.fpsr as u32,
|
||||
fpcr: regs.fpcr as u32,
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<kvm_regs> for StandardRegisters {
|
||||
fn from(regs: kvm_regs) -> Self {
|
||||
Self {
|
||||
gpr: regs.regs.regs,
|
||||
sp: regs.regs.sp,
|
||||
pc: regs.regs.pc,
|
||||
pstate: regs.regs.pstate,
|
||||
sp_el1: regs.sp_el1,
|
||||
elr_el1: regs.elr_el1,
|
||||
spsr: regs.spsr,
|
||||
vregs: regs.fp_regs.vregs,
|
||||
fpsr: regs.fp_regs.fpsr as u64,
|
||||
fpcr: regs.fp_regs.fpcr as u64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Register> for kvm_one_reg {
|
||||
fn from(reg: Register) -> Self {
|
||||
Self {
|
||||
id: reg.id,
|
||||
addr: reg.addr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<kvm_one_reg> for Register {
|
||||
fn from(reg: kvm_one_reg) -> Self {
|
||||
Self {
|
||||
id: reg.id,
|
||||
addr: reg.addr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VcpuInit> for kvm_vcpu_init {
|
||||
fn from(vcpu_init: VcpuInit) -> Self {
|
||||
Self {
|
||||
target: vcpu_init.target,
|
||||
features: vcpu_init.features,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<kvm_vcpu_init> for VcpuInit {
|
||||
fn from(vcpu_init: kvm_vcpu_init) -> Self {
|
||||
Self {
|
||||
target: vcpu_init.target,
|
||||
features: vcpu_init.features,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,7 @@
|
|||
use crate::aarch64::gic::KvmGicV3Its;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub use crate::aarch64::{
|
||||
check_required_kvm_extensions, gic::Gicv3ItsState as GicState, is_system_register, VcpuInit,
|
||||
VcpuKvmState,
|
||||
check_required_kvm_extensions, gic::Gicv3ItsState as GicState, is_system_register, VcpuKvmState,
|
||||
};
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use crate::arch::aarch64::gic::{Vgic, VgicConfig};
|
||||
|
@ -43,6 +42,8 @@ use vmm_sys_util::eventfd::EventFd;
|
|||
// x86_64 dependencies
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub mod x86_64;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use crate::arch::aarch64::{RegList, Register, StandardRegisters, VcpuInit};
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use crate::arch::x86::{
|
||||
CpuIdEntry, FpuState, LapicState, MsrEntry, SpecialRegisters, StandardRegisters, XsaveState,
|
||||
|
@ -54,8 +55,6 @@ use crate::{
|
|||
CpuState, IoEventAddress, IrqRoutingEntry, MpState, UserMemoryRegion,
|
||||
USER_MEMORY_REGION_LOG_DIRTY, USER_MEMORY_REGION_READ, USER_MEMORY_REGION_WRITE,
|
||||
};
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use aarch64::{RegList, Register, StandardRegisters};
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use kvm_bindings::{
|
||||
kvm_enable_cap, kvm_msr_entry, MsrList, KVM_CAP_HYPERV_SYNIC, KVM_CAP_SPLIT_IRQCHIP,
|
||||
|
@ -77,10 +76,11 @@ pub use kvm_bindings::{
|
|||
};
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use kvm_bindings::{
|
||||
kvm_regs, user_fpsimd_state, user_pt_regs, KVM_GUESTDBG_USE_HW, KVM_NR_SPSR, KVM_REG_ARM64,
|
||||
KVM_REG_ARM64_SYSREG, KVM_REG_ARM64_SYSREG_CRM_MASK, KVM_REG_ARM64_SYSREG_CRN_MASK,
|
||||
KVM_REG_ARM64_SYSREG_OP0_MASK, KVM_REG_ARM64_SYSREG_OP1_MASK, KVM_REG_ARM64_SYSREG_OP2_MASK,
|
||||
KVM_REG_ARM_CORE, KVM_REG_SIZE_U128, KVM_REG_SIZE_U32, KVM_REG_SIZE_U64,
|
||||
kvm_regs, user_fpsimd_state, user_pt_regs, RegList as KvmRegList, KVM_GUESTDBG_USE_HW,
|
||||
KVM_NR_SPSR, KVM_REG_ARM64, KVM_REG_ARM64_SYSREG, KVM_REG_ARM64_SYSREG_CRM_MASK,
|
||||
KVM_REG_ARM64_SYSREG_CRN_MASK, KVM_REG_ARM64_SYSREG_OP0_MASK, KVM_REG_ARM64_SYSREG_OP1_MASK,
|
||||
KVM_REG_ARM64_SYSREG_OP2_MASK, KVM_REG_ARM_CORE, KVM_REG_SIZE_U128, KVM_REG_SIZE_U32,
|
||||
KVM_REG_SIZE_U64,
|
||||
};
|
||||
#[cfg(feature = "tdx")]
|
||||
use kvm_bindings::{kvm_run__bindgen_ty_1, KVMIO};
|
||||
|
@ -691,8 +691,9 @@ impl vm::Vm for KvmVm {
|
|||
///
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn get_preferred_target(&self, kvi: &mut VcpuInit) -> vm::Result<()> {
|
||||
let mut kvi = (*kvi).into();
|
||||
self.fd
|
||||
.get_preferred_target(kvi)
|
||||
.get_preferred_target(&mut kvi)
|
||||
.map_err(|e| vm::HypervisorVmError::GetPreferredTarget(e.into()))
|
||||
}
|
||||
|
||||
|
@ -1210,7 +1211,7 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
///
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn get_regs(&self) -> cpu::Result<StandardRegisters> {
|
||||
let mut state: StandardRegisters = kvm_regs::default();
|
||||
let mut state = kvm_regs::default();
|
||||
let mut off = offset_of!(user_pt_regs, regs);
|
||||
// There are 31 user_pt_regs:
|
||||
// https://elixir.free-electrons.com/linux/v4.14.174/source/arch/arm64/include/uapi/asm/ptrace.h#L72
|
||||
|
@ -1305,7 +1306,7 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U32, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.fp_regs.fpcr = u32::from_le_bytes(bytes);
|
||||
Ok(state)
|
||||
Ok(state.into())
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
|
@ -1328,6 +1329,7 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
fn set_regs(&self, state: &StandardRegisters) -> cpu::Result<()> {
|
||||
// The function follows the exact identical order from `state`. Look there
|
||||
// for some additional info on registers.
|
||||
let state: kvm_regs = (*state).into();
|
||||
let mut off = offset_of!(user_pt_regs, regs);
|
||||
for i in 0..31 {
|
||||
self.fd
|
||||
|
@ -1776,8 +1778,9 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn vcpu_init(&self, kvi: &VcpuInit) -> cpu::Result<()> {
|
||||
let kvi = (*kvi).into();
|
||||
self.fd
|
||||
.vcpu_init(kvi)
|
||||
.vcpu_init(&kvi)
|
||||
.map_err(|e| cpu::HypervisorCpuError::VcpuInit(e.into()))
|
||||
}
|
||||
|
||||
|
@ -1787,8 +1790,10 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
///
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn get_reg_list(&self, reg_list: &mut RegList) -> cpu::Result<()> {
|
||||
let mut kvm_reg_list: KvmRegList = KvmRegList::from_entries(reg_list.0.as_slice())
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into()))?;
|
||||
self.fd
|
||||
.get_reg_list(reg_list)
|
||||
.get_reg_list(&mut kvm_reg_list)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into()))
|
||||
}
|
||||
|
||||
|
@ -2013,13 +2018,13 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
..Default::default()
|
||||
};
|
||||
// Get core registers
|
||||
state.core_regs = self.get_regs()?;
|
||||
state.core_regs = self.get_regs()?.into();
|
||||
|
||||
// Get systerm register
|
||||
// Call KVM_GET_REG_LIST to get all registers available to the guest.
|
||||
// For ArmV8 there are around 500 registers.
|
||||
let mut sys_regs: Vec<Register> = Vec::new();
|
||||
let mut reg_list = RegList::new(500).unwrap();
|
||||
let mut reg_list = KvmRegList::new(500).unwrap();
|
||||
self.fd
|
||||
.get_reg_list(&mut reg_list)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into()))?;
|
||||
|
@ -2041,13 +2046,16 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
self.fd
|
||||
.get_one_reg(*index, &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetSysRegister(e.into()))?;
|
||||
sys_regs.push(kvm_bindings::kvm_one_reg {
|
||||
id: *index,
|
||||
addr: u64::from_le_bytes(bytes),
|
||||
});
|
||||
sys_regs.push(
|
||||
kvm_bindings::kvm_one_reg {
|
||||
id: *index,
|
||||
addr: u64::from_le_bytes(bytes),
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
|
||||
state.sys_regs = sys_regs;
|
||||
state.sys_regs = sys_regs.into_iter().map(|reg| reg.into()).collect();
|
||||
|
||||
Ok(state.into())
|
||||
}
|
||||
|
@ -2149,7 +2157,7 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
fn set_state(&self, state: &CpuState) -> cpu::Result<()> {
|
||||
let state: VcpuKvmState = state.clone().into();
|
||||
// Set core registers
|
||||
self.set_regs(&state.core_regs)?;
|
||||
self.set_regs(&state.core_regs.into())?;
|
||||
// Set system registers
|
||||
for reg in &state.sys_regs {
|
||||
self.fd
|
||||
|
|
|
@ -1191,12 +1191,12 @@ impl cpu::Vcpu for MshvVcpu {
|
|||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn set_regs(&self, regs: &StandardRegisters) -> cpu::Result<()> {
|
||||
fn set_regs(&self, regs: &crate::arch::aarch64::StandardRegisters) -> cpu::Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn get_regs(&self) -> cpu::Result<StandardRegisters> {
|
||||
fn get_regs(&self) -> cpu::Result<crate::arch::aarch64::StandardRegisters> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
//
|
||||
//
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use crate::aarch64::VcpuInit;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use crate::arch::aarch64::gic::{Vgic, VgicConfig};
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use crate::arch::aarch64::VcpuInit;
|
||||
#[cfg(feature = "tdx")]
|
||||
use crate::arch::x86::CpuIdEntry;
|
||||
use crate::cpu::Vcpu;
|
||||
|
|
|
@ -43,7 +43,9 @@ use gdbstub_arch::aarch64::reg::AArch64CoreRegs as CoreRegs;
|
|||
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
|
||||
use gdbstub_arch::x86::reg::{X86SegmentRegs, X86_64CoreRegs as CoreRegs};
|
||||
#[cfg(all(target_arch = "aarch64", feature = "guest_debug"))]
|
||||
use hypervisor::aarch64::StandardRegisters;
|
||||
use hypervisor::arch::aarch64::StandardRegisters;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use hypervisor::arch::aarch64::VcpuInit;
|
||||
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
|
||||
use hypervisor::arch::x86::msr_index;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
|
@ -413,7 +415,7 @@ impl Vcpu {
|
|||
/// Initializes an aarch64 specific vcpu for booting Linux.
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub fn init(&self, vm: &Arc<dyn hypervisor::Vm>) -> Result<()> {
|
||||
let mut kvi: kvm_bindings::kvm_vcpu_init = kvm_bindings::kvm_vcpu_init::default();
|
||||
let mut kvi = VcpuInit::default();
|
||||
|
||||
// This reads back the kernel's preferred target type.
|
||||
vm.get_preferred_target(&mut kvi)
|
||||
|
@ -2383,9 +2385,9 @@ impl Debuggable for CpuManager {
|
|||
.get_regs(cpu_id as u8)
|
||||
.map_err(DebuggableError::ReadRegs)?;
|
||||
Ok(CoreRegs {
|
||||
x: gregs.regs.regs,
|
||||
sp: gregs.regs.sp,
|
||||
pc: gregs.regs.pc,
|
||||
x: gregs.gpr,
|
||||
sp: gregs.sp,
|
||||
pc: gregs.pc,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
@ -2454,9 +2456,9 @@ impl Debuggable for CpuManager {
|
|||
.get_regs(cpu_id as u8)
|
||||
.map_err(DebuggableError::ReadRegs)?;
|
||||
|
||||
gregs.regs.regs = regs.x;
|
||||
gregs.regs.sp = regs.sp;
|
||||
gregs.regs.pc = regs.pc;
|
||||
gregs.gpr = regs.x;
|
||||
gregs.sp = regs.sp;
|
||||
gregs.pc = regs.pc;
|
||||
|
||||
self.set_regs(cpu_id as u8, &gregs)
|
||||
.map_err(DebuggableError::WriteRegs)?;
|
||||
|
@ -2889,10 +2891,10 @@ mod tests {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use arch::{aarch64::regs, layout};
|
||||
use hypervisor::arch::aarch64::{StandardRegisters, VcpuInit};
|
||||
use hypervisor::kvm::aarch64::is_system_register;
|
||||
use hypervisor::kvm::kvm_bindings::{
|
||||
kvm_regs, kvm_vcpu_init, user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM64_SYSREG,
|
||||
KVM_REG_ARM_CORE, KVM_REG_SIZE_U64,
|
||||
user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM64_SYSREG, KVM_REG_ARM_CORE, KVM_REG_SIZE_U64,
|
||||
};
|
||||
use hypervisor::{arm64_core_reg_id, offset_of};
|
||||
use std::mem;
|
||||
|
@ -2907,7 +2909,7 @@ mod tests {
|
|||
// Must fail when vcpu is not initialized yet.
|
||||
assert!(res.is_err());
|
||||
|
||||
let mut kvi: kvm_vcpu_init = kvm_vcpu_init::default();
|
||||
let mut kvi = VcpuInit::default();
|
||||
vm.get_preferred_target(&mut kvi).unwrap();
|
||||
vcpu.vcpu_init(&kvi).unwrap();
|
||||
|
||||
|
@ -2919,7 +2921,7 @@ mod tests {
|
|||
let hv = hypervisor::new().unwrap();
|
||||
let vm = hv.create_vm().unwrap();
|
||||
let vcpu = vm.create_vcpu(0, None).unwrap();
|
||||
let mut kvi: kvm_vcpu_init = kvm_vcpu_init::default();
|
||||
let mut kvi = VcpuInit::default();
|
||||
vm.get_preferred_target(&mut kvi).unwrap();
|
||||
|
||||
// Must fail when vcpu is not initialized yet.
|
||||
|
@ -2943,7 +2945,7 @@ mod tests {
|
|||
let hv = hypervisor::new().unwrap();
|
||||
let vm = hv.create_vm().unwrap();
|
||||
let vcpu = vm.create_vcpu(0, None).unwrap();
|
||||
let mut kvi: kvm_vcpu_init = kvm_vcpu_init::default();
|
||||
let mut kvi = VcpuInit::default();
|
||||
vm.get_preferred_target(&mut kvi).unwrap();
|
||||
|
||||
// Must fail when vcpu is not initialized yet.
|
||||
|
@ -2954,7 +2956,7 @@ mod tests {
|
|||
"Failed to get core register: Exec format error (os error 8)"
|
||||
);
|
||||
|
||||
let mut state = kvm_regs::default();
|
||||
let mut state = StandardRegisters::default();
|
||||
let res = vcpu.set_regs(&state);
|
||||
assert!(res.is_err());
|
||||
assert_eq!(
|
||||
|
@ -2966,7 +2968,7 @@ mod tests {
|
|||
let res = vcpu.get_regs();
|
||||
assert!(res.is_ok());
|
||||
state = res.unwrap();
|
||||
assert_eq!(state.regs.pstate, 0x3C5);
|
||||
assert_eq!(state.pstate, 0x3C5);
|
||||
|
||||
assert!(vcpu.set_regs(&state).is_ok());
|
||||
}
|
||||
|
@ -2976,7 +2978,7 @@ mod tests {
|
|||
let hv = hypervisor::new().unwrap();
|
||||
let vm = hv.create_vm().unwrap();
|
||||
let vcpu = vm.create_vcpu(0, None).unwrap();
|
||||
let mut kvi: kvm_vcpu_init = kvm_vcpu_init::default();
|
||||
let mut kvi = VcpuInit::default();
|
||||
vm.get_preferred_target(&mut kvi).unwrap();
|
||||
|
||||
let res = vcpu.get_mp_state();
|
||||
|
|
Loading…
Reference in New Issue