Skip to content

Commit

Permalink
arch: prepare crate for aarch64 code
Browse files Browse the repository at this point in the history
- Refactored crate to support addition of non-x86_64 architectures
- Labeled code accordingly
- non-x86_64 code was moved outside x86_64 folder
- Adjusted vmm related code
- Added aarch64 dummy template

Signed-off-by: Diana Popa <[email protected]>
  • Loading branch information
dianpopa authored and acatangiu committed Jan 18, 2019
1 parent a4aa837 commit b004709
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 49 deletions.
7 changes: 7 additions & 0 deletions arch/src/aarch64/layout.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

/// Kernel command line start address.
pub const CMDLINE_START: usize = 0x0;
/// Kernel command line start address maximum size.
pub const CMDLINE_MAX_SIZE: usize = 0x0;
26 changes: 26 additions & 0 deletions arch/src/aarch64/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

pub mod layout;

use memory_model::{GuestAddress, GuestMemory};

/// Stub function that needs to be implemented when aarch64 functionality is added.
pub fn arch_memory_regions(size: usize) -> Vec<(GuestAddress, usize)> {
vec![(GuestAddress(0), size)]
}

/// Stub function that needs to be implemented when aarch64 functionality is added.
pub fn configure_system(
_guest_mem: &GuestMemory,
_cmdline_addr: GuestAddress,
_cmdline_size: usize,
_num_cpus: u8,
) -> super::Result<()> {
Ok(())
}

/// Stub function that needs to be implemented when aarch64 functionality is added.
pub fn get_reserved_mem_addr() -> usize {
0
}
26 changes: 18 additions & 8 deletions arch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,33 @@ use std::result;

#[derive(Debug, PartialEq)]
pub enum Error {
#[cfg(target_arch = "x86_64")]
/// X86_64 specific error triggered during system configuration.
X86_64Setup(x86_64::Error),
/// The zero page extends past the end of guest_mem.
ZeroPagePastRamEnd,
/// Error writing the zero page of guest memory.
ZeroPageSetup,
#[cfg(target_arch = "x86_64")]
/// X86_64 specific error triggered during system configuration.
X86_64Setup(x86_64::Error),
}
pub type Result<T> = result::Result<T, Error>;

// 1MB. We don't put anything above here except the kernel itself.
pub const HIMEM_START: usize = 0x100000;

#[cfg(target_arch = "aarch64")]
pub mod aarch64;

#[cfg(target_arch = "aarch64")]
pub use aarch64::{
arch_memory_regions, configure_system, get_reserved_mem_addr, layout::CMDLINE_MAX_SIZE,
layout::CMDLINE_START,
};

#[cfg(target_arch = "x86_64")]
pub mod x86_64;
impl From<x86_64::Error> for Error {
fn from(e: x86_64::Error) -> Error {
Error::X86_64Setup(e)
}
}

#[cfg(target_arch = "x86_64")]
pub use x86_64::{
arch_memory_regions, configure_system, get_32bit_gap_start as get_reserved_mem_addr,
layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START,
};
3 changes: 3 additions & 0 deletions arch/src/x86_64/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,8 @@ pub const CMDLINE_START: usize = 0x20000;
/// Kernel command line start address maximum size.
pub const CMDLINE_MAX_SIZE: usize = 0x10000;

/// Address for the TSS setup.
pub const KVM_TSS_ADDRESS: usize = 0xfffbd000;

/// The 'zero page', a.k.a linux kernel bootparams.
pub const ZERO_PAGE_START: usize = 0x7000;
16 changes: 11 additions & 5 deletions arch/src/x86_64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@ use std::mem;
use arch_gen::x86::bootparam::{boot_params, E820_RAM};
use memory_model::{GuestAddress, GuestMemory};

// Where BIOS/VGA magic would live on a real PC.
const EBDA_START: u64 = 0x9fc00;
const FIRST_ADDR_PAST_32BITS: usize = (1 << 32);
const MEM_32BIT_GAP_SIZE: usize = (768 << 20);

#[derive(Debug, PartialEq)]
pub enum Error {
/// Invalid e820 setup params.
Expand All @@ -29,6 +24,17 @@ pub enum Error {
MpTableSetup(mptable::Error),
}

impl From<Error> for super::Error {
fn from(e: Error) -> super::Error {
super::Error::X86_64Setup(e)
}
}

// Where BIOS/VGA magic would live on a real PC.
const EBDA_START: u64 = 0x9fc00;
const FIRST_ADDR_PAST_32BITS: usize = (1 << 32);
const MEM_32BIT_GAP_SIZE: usize = (768 << 20);

/// Returns a Vec of the valid memory addresses.
/// 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
Expand Down
34 changes: 16 additions & 18 deletions vmm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ use std::time::Duration;
use libc::{c_void, siginfo_t};
use timerfd::{ClockId, SetTimeFlags, TimerFd, TimerState};

use arch::x86_64;
use device_manager::legacy::LegacyDeviceManager;
use device_manager::mmio::MMIODeviceManager;
use devices::virtio;
Expand Down Expand Up @@ -822,7 +821,7 @@ impl Vmm {
memory_model::GuestMemoryError::MemoryNotInitialized,
))?
<< 20;
let arch_mem_regions = x86_64::arch_memory_regions(mem_size);
let arch_mem_regions = arch::arch_memory_regions(mem_size);
self.guest_memory =
Some(GuestMemory::new(&arch_mem_regions).map_err(StartMicrovmError::GuestMemory)?);
Ok(())
Expand All @@ -842,11 +841,11 @@ impl Vmm {
.ok_or(StartMicrovmError::GuestMemory(
memory_model::GuestMemoryError::MemoryNotInitialized,
))?;

// Instantiate the MMIO device manager.
// 'mmio_base' address has to be an address which is protected by the kernel, in this case
// the start of the x86 specific gap of memory (currently hardcoded at 768MiB).
// 'mmio_base' address has to be an address which is protected by the kernel.
let mut device_manager =
MMIODeviceManager::new(guest_mem.clone(), x86_64::get_32bit_gap_start() as u64);
MMIODeviceManager::new(guest_mem.clone(), arch::get_reserved_mem_addr() as u64);

self.attach_block_devices(&mut device_manager)?;
self.attach_net_devices(&mut device_manager)?;
Expand Down Expand Up @@ -1105,7 +1104,7 @@ impl Vmm {
.vm_config
.vcpu_count
.ok_or(StartMicrovmError::VcpusNotConfigured)?;
x86_64::configure_system(
arch::configure_system(
vm_memory,
kernel_config.cmdline_addr,
cmdline_cstring.to_bytes().len() + 1,
Expand Down Expand Up @@ -1406,7 +1405,7 @@ impl Vmm {
let kernel_file = File::open(kernel_image_path).map_err(|_| {
VmmActionError::BootSource(ErrorKind::User, BootSourceConfigError::InvalidKernelPath)
})?;
let mut cmdline = kernel_cmdline::Cmdline::new(x86_64::layout::CMDLINE_MAX_SIZE);
let mut cmdline = kernel_cmdline::Cmdline::new(arch::CMDLINE_MAX_SIZE);
cmdline
.insert_str(kernel_cmdline.unwrap_or(String::from(DEFAULT_KERNEL_CMDLINE)))
.map_err(|_| {
Expand All @@ -1419,7 +1418,7 @@ impl Vmm {
let kernel_config = KernelConfig {
kernel_file,
cmdline,
cmdline_addr: GuestAddress(x86_64::layout::CMDLINE_START),
cmdline_addr: GuestAddress(arch::CMDLINE_START),
};
self.configure_kernel(kernel_config);

Expand Down Expand Up @@ -1881,12 +1880,12 @@ mod tests {
let kernel_path = String::from(kernel_file_temp.path().to_path_buf().to_str().unwrap());
let kernel_file = File::open(kernel_path).unwrap();

let mut cmdline = kernel_cmdline::Cmdline::new(x86_64::layout::CMDLINE_MAX_SIZE);
let mut cmdline = kernel_cmdline::Cmdline::new(arch::CMDLINE_MAX_SIZE);
assert!(cmdline.insert_str(DEFAULT_KERNEL_CMDLINE).is_ok());
let kernel_cfg = KernelConfig {
cmdline,
kernel_file,
cmdline_addr: GuestAddress(x86_64::layout::CMDLINE_START),
cmdline_addr: GuestAddress(arch::CMDLINE_START),
};
self.configure_kernel(kernel_cfg);
}
Expand Down Expand Up @@ -2450,7 +2449,7 @@ mod tests {

let guest_mem = vmm.guest_memory.clone().unwrap();
let mut device_manager =
MMIODeviceManager::new(guest_mem.clone(), x86_64::get_32bit_gap_start() as u64);
MMIODeviceManager::new(guest_mem.clone(), arch::get_reserved_mem_addr() as u64);
assert!(vmm.attach_block_devices(&mut device_manager).is_ok());
assert!(vmm.get_kernel_cmdline_str().contains("root=/dev/vda"));

Expand All @@ -2474,7 +2473,7 @@ mod tests {

let guest_mem = vmm.guest_memory.clone().unwrap();
let mut device_manager =
MMIODeviceManager::new(guest_mem.clone(), x86_64::get_32bit_gap_start() as u64);
MMIODeviceManager::new(guest_mem.clone(), arch::get_reserved_mem_addr() as u64);
assert!(vmm.attach_block_devices(&mut device_manager).is_ok());
assert!(vmm
.get_kernel_cmdline_str()
Expand Down Expand Up @@ -2502,7 +2501,7 @@ mod tests {

let guest_mem = vmm.guest_memory.clone().unwrap();
let mut device_manager =
MMIODeviceManager::new(guest_mem.clone(), x86_64::get_32bit_gap_start() as u64);
MMIODeviceManager::new(guest_mem.clone(), arch::get_reserved_mem_addr() as u64);
assert!(vmm.attach_block_devices(&mut device_manager).is_ok());
// Test that kernel commandline does not contain either /dev/vda or PARTUUID.
assert!(!vmm.get_kernel_cmdline_str().contains("root=PARTUUID="));
Expand Down Expand Up @@ -2536,7 +2535,7 @@ mod tests {

let guest_mem = vmm.guest_memory.clone().unwrap();
let mut device_manager =
MMIODeviceManager::new(guest_mem.clone(), x86_64::get_32bit_gap_start() as u64);
MMIODeviceManager::new(guest_mem.clone(), arch::get_reserved_mem_addr() as u64);

// test create network interface
let network_interface = NetworkInterfaceConfig {
Expand Down Expand Up @@ -2578,8 +2577,7 @@ mod tests {
// Test valid kernel path and invalid cmdline.
let kernel_file = NamedTempFile::new().expect("Failed to create temporary kernel file.");
let kernel_path = String::from(kernel_file.path().to_path_buf().to_str().unwrap());
let invalid_cmdline =
String::from_utf8(vec![b'X'; x86_64::layout::CMDLINE_MAX_SIZE + 1]).unwrap();
let invalid_cmdline = String::from_utf8(vec![b'X'; arch::CMDLINE_MAX_SIZE + 1]).unwrap();
assert!(vmm
.configure_boot_source(kernel_path.clone(), Some(invalid_cmdline))
.is_err());
Expand Down Expand Up @@ -2633,14 +2631,14 @@ mod tests {

let guest_mem = vmm.guest_memory.clone().unwrap();
let mut device_manager =
MMIODeviceManager::new(guest_mem.clone(), x86_64::get_32bit_gap_start() as u64);
MMIODeviceManager::new(guest_mem.clone(), arch::get_reserved_mem_addr() as u64);

let dummy_box = Box::new(DummyDevice { dummy: 0 });
// Use a dummy command line as it is not used in this test.
let _addr = device_manager
.register_device(
dummy_box,
&mut kernel_cmdline::Cmdline::new(x86_64::layout::CMDLINE_MAX_SIZE),
&mut kernel_cmdline::Cmdline::new(arch::CMDLINE_MAX_SIZE),
Some(scratch_id.clone()),
)
.unwrap();
Expand Down
39 changes: 21 additions & 18 deletions vmm/src/vstate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,14 @@ extern crate sys_util;
use std::result;

use super::KvmContext;
use arch::x86_64;
use cpuid::{c3_template, filter_cpuid, t2_template};
use kvm::*;
use logger::{LogOption, LOGGER};
use logger::{Metric, METRICS};
use memory_model::{GuestAddress, GuestMemory, GuestMemoryError};
use sys_util::EventFd;
use vmm_config::machine_config::{CpuFeaturesTemplate, VmConfig};
use x86_64::{interrupts, regs};

pub const KVM_TSS_ADDRESS: usize = 0xfffbd000;
const KVM_MEM_LOG_DIRTY_PAGES: u32 = 0x1;

/// Errors associated with the wrappers over KVM ioctls.
Expand All @@ -47,18 +44,23 @@ pub enum Error {
SetSupportedCpusFailed(sys_util::Error),
/// The number of configured slots is bigger than the maximum reported by KVM.
NotEnoughMemorySlots,
#[cfg(target_arch = "x86_64")]
/// Cannot set the local interruption due to bad configuration.
LocalIntConfiguration(interrupts::Error),
LocalIntConfiguration(arch::x86_64::interrupts::Error),
/// Cannot set the memory regions.
SetUserMemoryRegion(sys_util::Error),
#[cfg(target_arch = "x86_64")]
/// Error configuring the MSR registers
MSRSConfiguration(regs::Error),
MSRSConfiguration(arch::x86_64::regs::Error),
#[cfg(target_arch = "x86_64")]
/// Error configuring the general purpose registers
REGSConfiguration(regs::Error),
REGSConfiguration(arch::x86_64::regs::Error),
#[cfg(target_arch = "x86_64")]
/// Error configuring the special registers
SREGSConfiguration(regs::Error),
SREGSConfiguration(arch::x86_64::regs::Error),
#[cfg(target_arch = "x86_64")]
/// Error configuring the floating point related registers
FPUConfiguration(regs::Error),
FPUConfiguration(arch::x86_64::regs::Error),
/// Cannot configure the IRQ.
Irq(sys_util::Error),
}
Expand Down Expand Up @@ -113,9 +115,9 @@ impl Vm {
})?;
self.guest_mem = Some(guest_mem);

let tss_addr = GuestAddress(KVM_TSS_ADDRESS);
#[cfg(target_arch = "x86_64")]
self.fd
.set_tss_address(tss_addr.offset())
.set_tss_address(GuestAddress(arch::x86_64::layout::KVM_TSS_ADDRESS).offset())
.map_err(Error::VmSetup)?;

Ok(())
Expand Down Expand Up @@ -173,7 +175,8 @@ impl Vcpu {
})
}

/// /// Configures the vcpu and should be called once per vcpu from the vcpu's thread.
#[cfg(target_arch = "x86_64")]
/// Configures the vcpu and should be called once per vcpu from the vcpu's thread.
///
/// # Arguments
///
Expand Down Expand Up @@ -217,21 +220,21 @@ impl Vcpu {
.set_cpuid2(&self.cpuid)
.map_err(Error::SetSupportedCpusFailed)?;

x86_64::regs::setup_msrs(&self.fd).map_err(Error::MSRSConfiguration)?;
arch::x86_64::regs::setup_msrs(&self.fd).map_err(Error::MSRSConfiguration)?;
// Safe to unwrap because this method is called after the VM is configured
let vm_memory = vm
.get_memory()
.ok_or(Error::GuestMemory(GuestMemoryError::MemoryNotInitialized))?;
x86_64::regs::setup_regs(
arch::x86_64::regs::setup_regs(
&self.fd,
kernel_start_addr.offset() as u64,
x86_64::layout::BOOT_STACK_POINTER as u64,
x86_64::layout::ZERO_PAGE_START as u64,
arch::x86_64::layout::BOOT_STACK_POINTER as u64,
arch::x86_64::layout::ZERO_PAGE_START as u64,
)
.map_err(Error::REGSConfiguration)?;
x86_64::regs::setup_fpu(&self.fd).map_err(Error::FPUConfiguration)?;
x86_64::regs::setup_sregs(vm_memory, &self.fd).map_err(Error::SREGSConfiguration)?;
x86_64::interrupts::set_lint(&self.fd).map_err(Error::LocalIntConfiguration)?;
arch::x86_64::regs::setup_fpu(&self.fd).map_err(Error::FPUConfiguration)?;
arch::x86_64::regs::setup_sregs(vm_memory, &self.fd).map_err(Error::SREGSConfiguration)?;
arch::x86_64::interrupts::set_lint(&self.fd).map_err(Error::LocalIntConfiguration)?;
Ok(())
}

Expand Down

0 comments on commit b004709

Please sign in to comment.