mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-02-22 11:22:26 +00:00
vmm: Move Vcpu::configure() to arch crate
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
This commit is contained in:
parent
969e5e0b51
commit
8f7dc73562
@ -5,7 +5,16 @@ pub mod layout;
|
|||||||
|
|
||||||
use crate::RegionType;
|
use crate::RegionType;
|
||||||
use kvm_ioctls::*;
|
use kvm_ioctls::*;
|
||||||
use vm_memory::{GuestAddress, GuestMemoryMmap, GuestUsize};
|
use vm_memory::{GuestAddress, GuestMemoryAtomic, GuestMemoryMmap, GuestUsize};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {}
|
||||||
|
|
||||||
|
impl From<Error> for super::Error {
|
||||||
|
fn from(e: Error) -> super::Error {
|
||||||
|
super::Error::AArch64Setup(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Stub function that needs to be implemented when aarch64 functionality is added.
|
/// Stub function that needs to be implemented when aarch64 functionality is added.
|
||||||
pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, RegionType)> {
|
pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, RegionType)> {
|
||||||
@ -20,6 +29,15 @@ pub struct EntryPoint {
|
|||||||
pub entry_addr: GuestAddress,
|
pub entry_addr: GuestAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn configure_vcpu(
|
||||||
|
_fd: &VcpuFd,
|
||||||
|
_id: u8,
|
||||||
|
_kernel_entry_point: Option<EntryPoint>,
|
||||||
|
_vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
||||||
|
) -> super::Result<()> {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
/// Stub function that needs to be implemented when aarch64 functionality is added.
|
/// Stub function that needs to be implemented when aarch64 functionality is added.
|
||||||
pub fn configure_system(
|
pub fn configure_system(
|
||||||
_guest_mem: &GuestMemoryMmap,
|
_guest_mem: &GuestMemoryMmap,
|
||||||
|
@ -30,6 +30,9 @@ pub enum Error {
|
|||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
/// X86_64 specific error triggered during system configuration.
|
/// X86_64 specific error triggered during system configuration.
|
||||||
X86_64Setup(x86_64::Error),
|
X86_64Setup(x86_64::Error),
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
/// AArch64 specific error triggered during system configuration.
|
||||||
|
AArch64Setup(aarch64::Error),
|
||||||
/// The zero page extends past the end of guest_mem.
|
/// The zero page extends past the end of guest_mem.
|
||||||
ZeroPagePastRamEnd,
|
ZeroPagePastRamEnd,
|
||||||
/// Error writing the zero page of guest memory.
|
/// Error writing the zero page of guest memory.
|
||||||
@ -76,8 +79,9 @@ pub mod aarch64;
|
|||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
pub use aarch64::{
|
pub use aarch64::{
|
||||||
arch_memory_regions, check_required_kvm_extensions, configure_system, get_host_cpu_phys_bits,
|
arch_memory_regions, check_required_kvm_extensions, configure_system, configure_vcpu,
|
||||||
get_reserved_mem_addr, layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START, EntryPoint,
|
get_host_cpu_phys_bits, get_reserved_mem_addr, layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START,
|
||||||
|
EntryPoint,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
@ -85,9 +89,9 @@ pub mod x86_64;
|
|||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub use x86_64::{
|
pub use x86_64::{
|
||||||
arch_memory_regions, check_required_kvm_extensions, configure_system, get_host_cpu_phys_bits,
|
arch_memory_regions, check_required_kvm_extensions, configure_system, configure_vcpu,
|
||||||
initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START, regs,
|
get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE,
|
||||||
BootProtocol, EntryPoint,
|
layout::CMDLINE_START, regs, BootProtocol, CpuidPatch, CpuidReg, EntryPoint,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Safe wrapper for `sysconf(_SC_PAGESIZE)`.
|
/// Safe wrapper for `sysconf(_SC_PAGESIZE)`.
|
||||||
|
@ -15,6 +15,7 @@ mod mptable;
|
|||||||
pub mod regs;
|
pub mod regs;
|
||||||
use crate::InitramfsConfig;
|
use crate::InitramfsConfig;
|
||||||
use crate::RegionType;
|
use crate::RegionType;
|
||||||
|
use kvm_bindings::CpuId;
|
||||||
use kvm_ioctls::*;
|
use kvm_ioctls::*;
|
||||||
use linux_loader::loader::bootparam::{boot_params, setup_header};
|
use linux_loader::loader::bootparam::{boot_params, setup_header};
|
||||||
use linux_loader::loader::elf::start_info::{
|
use linux_loader::loader::elf::start_info::{
|
||||||
@ -22,8 +23,8 @@ use linux_loader::loader::elf::start_info::{
|
|||||||
};
|
};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use vm_memory::{
|
use vm_memory::{
|
||||||
Address, ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap, GuestMemoryRegion,
|
Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic,
|
||||||
GuestUsize,
|
GuestMemoryMmap, GuestMemoryRegion, GuestUsize,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
@ -96,6 +97,24 @@ pub enum Error {
|
|||||||
#[cfg(not(feature = "acpi"))]
|
#[cfg(not(feature = "acpi"))]
|
||||||
/// Error writing MP table to memory.
|
/// Error writing MP table to memory.
|
||||||
MpTableSetup(mptable::Error),
|
MpTableSetup(mptable::Error),
|
||||||
|
|
||||||
|
/// Error configuring the general purpose registers
|
||||||
|
REGSConfiguration(regs::Error),
|
||||||
|
|
||||||
|
/// Error configuring the special registers
|
||||||
|
SREGSConfiguration(regs::Error),
|
||||||
|
|
||||||
|
/// Error configuring the floating point related registers
|
||||||
|
FPUConfiguration(regs::Error),
|
||||||
|
|
||||||
|
/// Error configuring the MSR registers
|
||||||
|
MSRSConfiguration(regs::Error),
|
||||||
|
|
||||||
|
/// The call to KVM_SET_CPUID2 failed.
|
||||||
|
SetSupportedCpusFailed(kvm_ioctls::Error),
|
||||||
|
|
||||||
|
/// Cannot set the local interruption due to bad configuration.
|
||||||
|
LocalIntConfiguration(interrupts::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Error> for super::Error {
|
impl From<Error> for super::Error {
|
||||||
@ -104,6 +123,113 @@ impl From<Error> for super::Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub enum CpuidReg {
|
||||||
|
EAX,
|
||||||
|
EBX,
|
||||||
|
ECX,
|
||||||
|
EDX,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CpuidPatch {
|
||||||
|
pub function: u32,
|
||||||
|
pub index: u32,
|
||||||
|
pub flags_bit: Option<u8>,
|
||||||
|
pub eax_bit: Option<u8>,
|
||||||
|
pub ebx_bit: Option<u8>,
|
||||||
|
pub ecx_bit: Option<u8>,
|
||||||
|
pub edx_bit: Option<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CpuidPatch {
|
||||||
|
pub fn set_cpuid_reg(
|
||||||
|
cpuid: &mut CpuId,
|
||||||
|
function: u32,
|
||||||
|
index: Option<u32>,
|
||||||
|
reg: CpuidReg,
|
||||||
|
value: u32,
|
||||||
|
) {
|
||||||
|
let entries = cpuid.as_mut_slice();
|
||||||
|
|
||||||
|
for entry in entries.iter_mut() {
|
||||||
|
if entry.function == function && (index == None || index.unwrap() == entry.index) {
|
||||||
|
match reg {
|
||||||
|
CpuidReg::EAX => {
|
||||||
|
entry.eax = value;
|
||||||
|
}
|
||||||
|
CpuidReg::EBX => {
|
||||||
|
entry.ebx = value;
|
||||||
|
}
|
||||||
|
CpuidReg::ECX => {
|
||||||
|
entry.ecx = value;
|
||||||
|
}
|
||||||
|
CpuidReg::EDX => {
|
||||||
|
entry.edx = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn patch_cpuid(cpuid: &mut CpuId, patches: Vec<CpuidPatch>) {
|
||||||
|
let entries = cpuid.as_mut_slice();
|
||||||
|
|
||||||
|
for entry in entries.iter_mut() {
|
||||||
|
for patch in patches.iter() {
|
||||||
|
if entry.function == patch.function && entry.index == patch.index {
|
||||||
|
if let Some(flags_bit) = patch.flags_bit {
|
||||||
|
entry.flags |= 1 << flags_bit;
|
||||||
|
}
|
||||||
|
if let Some(eax_bit) = patch.eax_bit {
|
||||||
|
entry.eax |= 1 << eax_bit;
|
||||||
|
}
|
||||||
|
if let Some(ebx_bit) = patch.ebx_bit {
|
||||||
|
entry.ebx |= 1 << ebx_bit;
|
||||||
|
}
|
||||||
|
if let Some(ecx_bit) = patch.ecx_bit {
|
||||||
|
entry.ecx |= 1 << ecx_bit;
|
||||||
|
}
|
||||||
|
if let Some(edx_bit) = patch.edx_bit {
|
||||||
|
entry.edx |= 1 << edx_bit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn configure_vcpu(
|
||||||
|
fd: &VcpuFd,
|
||||||
|
id: u8,
|
||||||
|
kernel_entry_point: Option<EntryPoint>,
|
||||||
|
vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
||||||
|
cpuid: CpuId,
|
||||||
|
) -> super::Result<()> {
|
||||||
|
let mut cpuid = cpuid;
|
||||||
|
CpuidPatch::set_cpuid_reg(&mut cpuid, 0xb, None, CpuidReg::EDX, u32::from(id));
|
||||||
|
fd.set_cpuid2(&cpuid)
|
||||||
|
.map_err(Error::SetSupportedCpusFailed)?;
|
||||||
|
|
||||||
|
regs::setup_msrs(fd).map_err(Error::MSRSConfiguration)?;
|
||||||
|
if let Some(kernel_entry_point) = kernel_entry_point {
|
||||||
|
// Safe to unwrap because this method is called after the VM is configured
|
||||||
|
regs::setup_regs(
|
||||||
|
fd,
|
||||||
|
kernel_entry_point.entry_addr.raw_value(),
|
||||||
|
layout::BOOT_STACK_POINTER.raw_value(),
|
||||||
|
layout::ZERO_PAGE_START.raw_value(),
|
||||||
|
kernel_entry_point.protocol,
|
||||||
|
)
|
||||||
|
.map_err(Error::REGSConfiguration)?;
|
||||||
|
regs::setup_fpu(fd).map_err(Error::FPUConfiguration)?;
|
||||||
|
regs::setup_sregs(&vm_memory.memory(), fd, kernel_entry_point.protocol)
|
||||||
|
.map_err(Error::SREGSConfiguration)?;
|
||||||
|
}
|
||||||
|
interrupts::set_lint(fd).map_err(Error::LocalIntConfiguration)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a Vec of the valid memory addresses.
|
/// Returns a Vec of the valid memory addresses.
|
||||||
/// These should be used to configure the GuestMemory structure for the platform.
|
/// These should be used to configure the GuestMemory structure for the platform.
|
||||||
/// For x86_64 all addresses are valid from the start of the kernel except a
|
/// For x86_64 all addresses are valid from the start of the kernel except a
|
||||||
|
159
vmm/src/cpu.rs
159
vmm/src/cpu.rs
@ -20,6 +20,8 @@ use anyhow::anyhow;
|
|||||||
#[cfg(feature = "acpi")]
|
#[cfg(feature = "acpi")]
|
||||||
use arch::layout;
|
use arch::layout;
|
||||||
use arch::EntryPoint;
|
use arch::EntryPoint;
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
use arch::{CpuidPatch, CpuidReg};
|
||||||
use devices::{interrupt_controller::InterruptController, BusDevice};
|
use devices::{interrupt_controller::InterruptController, BusDevice};
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use kvm_bindings::{
|
use kvm_bindings::{
|
||||||
@ -35,8 +37,6 @@ use std::os::unix::thread::JoinHandleExt;
|
|||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::{Arc, Barrier, Mutex};
|
use std::sync::{Arc, Barrier, Mutex};
|
||||||
use std::{cmp, io, result, thread};
|
use std::{cmp, io, result, thread};
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
use vm_memory::{Address, GuestAddressSpace};
|
|
||||||
use vm_memory::{GuestAddress, GuestMemoryAtomic, GuestMemoryMmap};
|
use vm_memory::{GuestAddress, GuestMemoryAtomic, GuestMemoryMmap};
|
||||||
use vm_migration::{
|
use vm_migration::{
|
||||||
Migratable, MigratableError, Pausable, Snapshot, SnapshotDataSection, Snapshottable,
|
Migratable, MigratableError, Pausable, Snapshot, SnapshotDataSection, Snapshottable,
|
||||||
@ -110,18 +110,6 @@ pub enum Error {
|
|||||||
/// Cannot patch the CPU ID
|
/// Cannot patch the CPU ID
|
||||||
PatchCpuId(kvm_ioctls::Error),
|
PatchCpuId(kvm_ioctls::Error),
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
/// Error configuring the general purpose registers
|
|
||||||
REGSConfiguration(arch::x86_64::regs::Error),
|
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
/// Error configuring the special registers
|
|
||||||
SREGSConfiguration(arch::x86_64::regs::Error),
|
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
/// Error configuring the floating point related registers
|
|
||||||
FPUConfiguration(arch::x86_64::regs::Error),
|
|
||||||
|
|
||||||
/// The call to KVM_SET_CPUID2 failed.
|
/// The call to KVM_SET_CPUID2 failed.
|
||||||
SetSupportedCpusFailed(kvm_ioctls::Error),
|
SetSupportedCpusFailed(kvm_ioctls::Error),
|
||||||
|
|
||||||
@ -129,9 +117,8 @@ pub enum Error {
|
|||||||
/// Cannot set the local interruption due to bad configuration.
|
/// Cannot set the local interruption due to bad configuration.
|
||||||
LocalIntConfiguration(arch::x86_64::interrupts::Error),
|
LocalIntConfiguration(arch::x86_64::interrupts::Error),
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
/// Error configuring VCPU
|
||||||
/// Error configuring the MSR registers
|
VcpuConfiguration(arch::Error),
|
||||||
MSRSConfiguration(arch::x86_64::regs::Error),
|
|
||||||
|
|
||||||
/// Unexpected KVM_RUN exit reason
|
/// Unexpected KVM_RUN exit reason
|
||||||
VcpuUnhandledKvmExit,
|
VcpuUnhandledKvmExit,
|
||||||
@ -207,85 +194,6 @@ pub enum Error {
|
|||||||
}
|
}
|
||||||
pub type Result<T> = result::Result<T, Error>;
|
pub type Result<T> = result::Result<T, Error>;
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
enum CpuidReg {
|
|
||||||
EAX,
|
|
||||||
EBX,
|
|
||||||
ECX,
|
|
||||||
EDX,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
pub struct CpuidPatch {
|
|
||||||
pub function: u32,
|
|
||||||
pub index: u32,
|
|
||||||
pub flags_bit: Option<u8>,
|
|
||||||
pub eax_bit: Option<u8>,
|
|
||||||
pub ebx_bit: Option<u8>,
|
|
||||||
pub ecx_bit: Option<u8>,
|
|
||||||
pub edx_bit: Option<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
impl CpuidPatch {
|
|
||||||
fn set_cpuid_reg(
|
|
||||||
cpuid: &mut CpuId,
|
|
||||||
function: u32,
|
|
||||||
index: Option<u32>,
|
|
||||||
reg: CpuidReg,
|
|
||||||
value: u32,
|
|
||||||
) {
|
|
||||||
let entries = cpuid.as_mut_slice();
|
|
||||||
|
|
||||||
for entry in entries.iter_mut() {
|
|
||||||
if entry.function == function && (index == None || index.unwrap() == entry.index) {
|
|
||||||
match reg {
|
|
||||||
CpuidReg::EAX => {
|
|
||||||
entry.eax = value;
|
|
||||||
}
|
|
||||||
CpuidReg::EBX => {
|
|
||||||
entry.ebx = value;
|
|
||||||
}
|
|
||||||
CpuidReg::ECX => {
|
|
||||||
entry.ecx = value;
|
|
||||||
}
|
|
||||||
CpuidReg::EDX => {
|
|
||||||
entry.edx = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn patch_cpuid(cpuid: &mut CpuId, patches: Vec<CpuidPatch>) {
|
|
||||||
let entries = cpuid.as_mut_slice();
|
|
||||||
|
|
||||||
for entry in entries.iter_mut() {
|
|
||||||
for patch in patches.iter() {
|
|
||||||
if entry.function == patch.function && entry.index == patch.index {
|
|
||||||
if let Some(flags_bit) = patch.flags_bit {
|
|
||||||
entry.flags |= 1 << flags_bit;
|
|
||||||
}
|
|
||||||
if let Some(eax_bit) = patch.eax_bit {
|
|
||||||
entry.eax |= 1 << eax_bit;
|
|
||||||
}
|
|
||||||
if let Some(ebx_bit) = patch.ebx_bit {
|
|
||||||
entry.ebx |= 1 << ebx_bit;
|
|
||||||
}
|
|
||||||
if let Some(ecx_bit) = patch.ecx_bit {
|
|
||||||
entry.ecx |= 1 << ecx_bit;
|
|
||||||
}
|
|
||||||
if let Some(edx_bit) = patch.edx_bit {
|
|
||||||
entry.edx |= 1 << edx_bit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "acpi")]
|
#[cfg(feature = "acpi")]
|
||||||
#[repr(packed)]
|
#[repr(packed)]
|
||||||
struct LocalAPIC {
|
struct LocalAPIC {
|
||||||
@ -376,63 +284,28 @@ impl Vcpu {
|
|||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
/// Configures a vcpu and should be called once per vcpu when created.
|
||||||
/// Configures a aarch64 specific vcpu and should be called once per vcpu when created.
|
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `machine_config` - Specifies necessary info used for the CPUID configuration.
|
/// * `fd` - VcpuFd.
|
||||||
/// * `kernel_entry_point` - Kernel entry point address in guest memory and boot protocol used.
|
/// * `kernel_entry_point` - Kernel entry point address in guest memory and boot protocol used.
|
||||||
/// * `vm_memory` - Guest memory.
|
/// * `vm_memory` - Guest memory.
|
||||||
|
/// * `cpuid` - (x86_64) CpuId, wrapper over the `kvm_cpuid2` structure.
|
||||||
pub fn configure(
|
pub fn configure(
|
||||||
&mut self,
|
&self,
|
||||||
_kernel_entry_point: Option<EntryPoint>,
|
|
||||||
_vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
|
||||||
) -> Result<()> {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
/// Configures a x86_64 specific vcpu and should be called once per vcpu when created.
|
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `machine_config` - Specifies necessary info used for the CPUID configuration.
|
|
||||||
/// * `kernel_entry_point` - Kernel entry point address in guest memory and boot protocol used.
|
|
||||||
/// * `vm_memory` - Guest memory.
|
|
||||||
/// * `cpuid` - CpuId, wrapper over the `kvm_cpuid2` structure.
|
|
||||||
pub fn configure(
|
|
||||||
&mut self,
|
|
||||||
kernel_entry_point: Option<EntryPoint>,
|
kernel_entry_point: Option<EntryPoint>,
|
||||||
vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
||||||
cpuid: CpuId,
|
#[cfg(target_arch = "x86_64")] cpuid: CpuId,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut cpuid = cpuid;
|
#[cfg(target_arch = "aarch64")]
|
||||||
CpuidPatch::set_cpuid_reg(&mut cpuid, 0xb, None, CpuidReg::EDX, u32::from(self.id));
|
arch::configure_vcpu(&self.fd, self.id, kernel_entry_point, vm_memory)
|
||||||
self.fd
|
.map_err(Error::VcpuConfiguration)?;
|
||||||
.set_cpuid2(&cpuid)
|
|
||||||
.map_err(Error::SetSupportedCpusFailed)?;
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
arch::configure_vcpu(&self.fd, self.id, kernel_entry_point, vm_memory, cpuid)
|
||||||
|
.map_err(Error::VcpuConfiguration)?;
|
||||||
|
|
||||||
arch::x86_64::regs::setup_msrs(&self.fd).map_err(Error::MSRSConfiguration)?;
|
|
||||||
if let Some(kernel_entry_point) = kernel_entry_point {
|
|
||||||
// Safe to unwrap because this method is called after the VM is configured
|
|
||||||
arch::x86_64::regs::setup_regs(
|
|
||||||
&self.fd,
|
|
||||||
kernel_entry_point.entry_addr.raw_value(),
|
|
||||||
arch::x86_64::layout::BOOT_STACK_POINTER.raw_value(),
|
|
||||||
arch::x86_64::layout::ZERO_PAGE_START.raw_value(),
|
|
||||||
kernel_entry_point.protocol,
|
|
||||||
)
|
|
||||||
.map_err(Error::REGSConfiguration)?;
|
|
||||||
arch::x86_64::regs::setup_fpu(&self.fd).map_err(Error::FPUConfiguration)?;
|
|
||||||
arch::x86_64::regs::setup_sregs(
|
|
||||||
&vm_memory.memory(),
|
|
||||||
&self.fd,
|
|
||||||
kernel_entry_point.protocol,
|
|
||||||
)
|
|
||||||
.map_err(Error::SREGSConfiguration)?;
|
|
||||||
}
|
|
||||||
arch::x86_64::interrupts::set_lint(&self.fd).map_err(Error::LocalIntConfiguration)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user