Skip to content

Commit 6a5be36

Browse files
committed
arch: add template support for non-x86_64 code
- Refactored crate to support addition of non-x86_64 architectures - Labeled code accordingly - Created a template for adding non-x86_64 code - non-x86_64 code was moved outside x86_64 folder - Adjusted vmm related code Signed-off-by: Diana Popa <[email protected]>
1 parent 971708f commit 6a5be36

File tree

5 files changed

+109
-44
lines changed

5 files changed

+109
-44
lines changed

arch/src/lib.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub enum Error {
1818
ZeroPagePastRamEnd,
1919
/// Error writing the zero page of guest memory.
2020
ZeroPageSetup,
21-
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
21+
#[cfg(target_arch = "x86_64")]
2222
/// X86_64 specific error triggered during system configuration.
2323
X86_64Setup(x86_64::Error),
2424
}
@@ -27,10 +27,20 @@ pub type Result<T> = result::Result<T, Error>;
2727
// 1MB. We don't put anything above here except the kernel itself.
2828
pub const HIMEM_START: usize = 0x100000;
2929

30-
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
31-
pub mod x86_64;
32-
impl From<x86_64::Error> for Error {
33-
fn from(e: x86_64::Error) -> Error {
34-
Error::X86_64Setup(e)
35-
}
36-
}
30+
#[cfg(target_arch = "x86_64")]
31+
mod x86_64;
32+
33+
#[cfg(not(target_arch = "x86_64"))]
34+
mod template;
35+
36+
#[cfg(target_arch = "x86_64")]
37+
pub use x86_64::{
38+
arch_memory_regions, configure_system, get_32bit_gap_start as get_reserved_mem_addr,
39+
interrupts, regs, CMDLINE_START, COMMAND_LINE_SIZE, ZERO_PAGE_START,
40+
};
41+
42+
#[cfg(not(target_arch = "x86_64"))]
43+
pub use template::{
44+
arch_memory_regions, configure_system, get_reserved_mem_addr, CMDLINE_START, COMMAND_LINE_SIZE,
45+
ZERO_PAGE_START,
46+
};

arch/src/template/mod.rs

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use memory_model::{GuestAddress, GuestMemory};
2+
3+
/// Stub function that needs to be implemented every time new architecture support is added.
4+
pub fn arch_memory_regions(size: usize) -> Vec<(GuestAddress, usize)> {
5+
Vec::with_capacity(size)
6+
}
7+
8+
/// Stub function that needs to be implemented every time new architecture support is added.
9+
pub fn configure_system(
10+
_guest_mem: &GuestMemory,
11+
_cmdline_addr: GuestAddress,
12+
_cmdline_size: usize,
13+
_num_cpus: u8,
14+
) -> super::Result<()> {
15+
Ok(())
16+
}
17+
18+
/// Stub function that needs to be implemented every time new architecture support is added.
19+
pub fn get_reserved_mem_addr() -> usize {
20+
0
21+
}
22+
23+
/// Stub variable, should be defined every time new architecture support is added.
24+
pub const CMDLINE_START: usize = 0x0;
25+
26+
/// Stub variable, should be defined every time new architecture support is added.
27+
pub const COMMAND_LINE_SIZE: usize = 0;
28+
29+
/// Stub variable, should be defined every time new architecture support is added.
30+
pub const ZERO_PAGE_START: usize = 0;

arch/src/x86_64/mod.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,18 @@ pub enum Error {
2323
MpTableSetup(mptable::Error),
2424
}
2525

26-
// Magic addresses used to lay out x86_64 VMs.
26+
impl From<Error> for super::Error {
27+
fn from(e: Error) -> super::Error {
28+
super::Error::X86_64Setup(e)
29+
}
30+
}
2731

28-
// Initial stack for the boot CPU.
29-
pub const BOOT_STACK_POINTER: usize = 0x8ff0;
32+
// Magic addresses used to lay out x86_64 VMs.
3033

3134
// Kernel command line.
3235
pub const CMDLINE_START: usize = 0x20000;
33-
pub const CMDLINE_MAX_SIZE: usize = 0x10000;
36+
// As per arch/x86/include/asm/setup.h.
37+
pub const COMMAND_LINE_SIZE: usize = 2048;
3438

3539
// The 'zero page', a.k.a linux kernel bootparams.
3640
pub const ZERO_PAGE_START: usize = 0x7000;

vmm/src/lib.rs

+16-17
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ use std::time::Duration;
5959
use libc::{c_void, siginfo_t};
6060
use timerfd::{ClockId, SetTimeFlags, TimerFd, TimerState};
6161

62-
use arch::x86_64;
6362
use device_manager::legacy::LegacyDeviceManager;
6463
use device_manager::mmio::MMIODeviceManager;
6564
use devices::virtio;
@@ -776,7 +775,7 @@ impl Vmm {
776775
memory_model::GuestMemoryError::MemoryNotInitialized,
777776
))?
778777
<< 20;
779-
let arch_mem_regions = x86_64::arch_memory_regions(mem_size);
778+
let arch_mem_regions = arch::arch_memory_regions(mem_size);
780779
self.guest_memory =
781780
Some(GuestMemory::new(&arch_mem_regions).map_err(StartMicrovmError::GuestMemory)?);
782781
Ok(())
@@ -796,11 +795,11 @@ impl Vmm {
796795
.ok_or(StartMicrovmError::GuestMemory(
797796
memory_model::GuestMemoryError::MemoryNotInitialized,
798797
))?;
798+
799799
// Instantiate the MMIO device manager.
800-
// 'mmio_base' address has to be an address which is protected by the kernel, in this case
801-
// the start of the x86 specific gap of memory (currently hardcoded at 768MiB).
800+
// 'mmio_base' address has to be an address which is protected by the kernel.
802801
let mut device_manager =
803-
MMIODeviceManager::new(guest_mem.clone(), x86_64::get_32bit_gap_start() as u64);
802+
MMIODeviceManager::new(guest_mem.clone(), arch::get_reserved_mem_addr() as u64);
804803

805804
self.attach_block_devices(&mut device_manager)?;
806805
self.attach_net_devices(&mut device_manager)?;
@@ -1052,7 +1051,7 @@ impl Vmm {
10521051
.vm_config
10531052
.vcpu_count
10541053
.ok_or(StartMicrovmError::VcpusNotConfigured)?;
1055-
x86_64::configure_system(
1054+
arch::configure_system(
10561055
vm_memory,
10571056
kernel_config.cmdline_addr,
10581057
cmdline_cstring.to_bytes().len() + 1,
@@ -1318,7 +1317,7 @@ impl Vmm {
13181317
let kernel_file = File::open(kernel_image_path).map_err(|_| {
13191318
VmmActionError::BootSource(ErrorKind::User, BootSourceConfigError::InvalidKernelPath)
13201319
})?;
1321-
let mut cmdline = kernel_cmdline::Cmdline::new(x86_64::CMDLINE_MAX_SIZE);
1320+
let mut cmdline = kernel_cmdline::Cmdline::new(arch::COMMAND_LINE_SIZE);
13221321
cmdline
13231322
.insert_str(kernel_cmdline.unwrap_or(String::from(DEFAULT_KERNEL_CMDLINE)))
13241323
.map_err(|_| {
@@ -1331,7 +1330,7 @@ impl Vmm {
13311330
let kernel_config = KernelConfig {
13321331
kernel_file,
13331332
cmdline,
1334-
cmdline_addr: GuestAddress(x86_64::CMDLINE_START),
1333+
cmdline_addr: GuestAddress(arch::CMDLINE_START),
13351334
};
13361335
self.configure_kernel(kernel_config);
13371336

@@ -1783,12 +1782,12 @@ mod tests {
17831782
let kernel_path = String::from(kernel_file_temp.path().to_path_buf().to_str().unwrap());
17841783
let kernel_file = File::open(kernel_path).unwrap();
17851784

1786-
let mut cmdline = kernel_cmdline::Cmdline::new(x86_64::CMDLINE_MAX_SIZE);
1785+
let mut cmdline = kernel_cmdline::Cmdline::new(arch::COMMAND_LINE_SIZE);
17871786
assert!(cmdline.insert_str(DEFAULT_KERNEL_CMDLINE).is_ok());
17881787
let kernel_cfg = KernelConfig {
17891788
cmdline,
17901789
kernel_file,
1791-
cmdline_addr: GuestAddress(x86_64::CMDLINE_START),
1790+
cmdline_addr: GuestAddress(arch::CMDLINE_START),
17921791
};
17931792
self.configure_kernel(kernel_cfg);
17941793
}
@@ -2356,7 +2355,7 @@ mod tests {
23562355

23572356
let guest_mem = vmm.guest_memory.clone().unwrap();
23582357
let mut device_manager =
2359-
MMIODeviceManager::new(guest_mem.clone(), x86_64::get_32bit_gap_start() as u64);
2358+
MMIODeviceManager::new(guest_mem.clone(), arch::get_reserved_mem_addr() as u64);
23602359
assert!(vmm.attach_block_devices(&mut device_manager).is_ok());
23612360
assert!(vmm.get_kernel_cmdline_str().contains("root=/dev/vda"));
23622361

@@ -2380,7 +2379,7 @@ mod tests {
23802379

23812380
let guest_mem = vmm.guest_memory.clone().unwrap();
23822381
let mut device_manager =
2383-
MMIODeviceManager::new(guest_mem.clone(), x86_64::get_32bit_gap_start() as u64);
2382+
MMIODeviceManager::new(guest_mem.clone(), arch::get_reserved_mem_addr() as u64);
23842383
assert!(vmm.attach_block_devices(&mut device_manager).is_ok());
23852384
assert!(
23862385
vmm.get_kernel_cmdline_str()
@@ -2410,7 +2409,7 @@ mod tests {
24102409

24112410
let guest_mem = vmm.guest_memory.clone().unwrap();
24122411
let mut device_manager =
2413-
MMIODeviceManager::new(guest_mem.clone(), x86_64::get_32bit_gap_start() as u64);
2412+
MMIODeviceManager::new(guest_mem.clone(), arch::get_reserved_mem_addr() as u64);
24142413
assert!(vmm.attach_block_devices(&mut device_manager).is_ok());
24152414
// Test that kernel commandline does not contain either /dev/vda or PARTUUID.
24162415
assert!(!vmm.get_kernel_cmdline_str().contains("root=PARTUUID="));
@@ -2448,7 +2447,7 @@ mod tests {
24482447

24492448
let guest_mem = vmm.guest_memory.clone().unwrap();
24502449
let mut device_manager =
2451-
MMIODeviceManager::new(guest_mem.clone(), x86_64::get_32bit_gap_start() as u64);
2450+
MMIODeviceManager::new(guest_mem.clone(), arch::get_reserved_mem_addr() as u64);
24522451

24532452
// test create network interface
24542453
let network_interface = NetworkInterfaceConfig {
@@ -2491,7 +2490,7 @@ mod tests {
24912490
// Test valid kernel path and invalid cmdline.
24922491
let kernel_file = NamedTempFile::new().expect("Failed to create temporary kernel file.");
24932492
let kernel_path = String::from(kernel_file.path().to_path_buf().to_str().unwrap());
2494-
let invalid_cmdline = String::from_utf8(vec![b'X'; x86_64::CMDLINE_MAX_SIZE + 1]).unwrap();
2493+
let invalid_cmdline = String::from_utf8(vec![b'X'; arch::COMMAND_LINE_SIZE + 1]).unwrap();
24952494
assert!(
24962495
vmm.configure_boot_source(kernel_path.clone(), Some(invalid_cmdline))
24972496
.is_err()
@@ -2549,14 +2548,14 @@ mod tests {
25492548

25502549
let guest_mem = vmm.guest_memory.clone().unwrap();
25512550
let mut device_manager =
2552-
MMIODeviceManager::new(guest_mem.clone(), x86_64::get_32bit_gap_start() as u64);
2551+
MMIODeviceManager::new(guest_mem.clone(), arch::get_reserved_mem_addr() as u64);
25532552

25542553
let dummy_box = Box::new(DummyDevice { dummy: 0 });
25552554
// Use a dummy command line as it is not used in this test.
25562555
let _addr = device_manager
25572556
.register_device(
25582557
dummy_box,
2559-
&mut kernel_cmdline::Cmdline::new(x86_64::CMDLINE_MAX_SIZE),
2558+
&mut kernel_cmdline::Cmdline::new(arch::COMMAND_LINE_SIZE),
25602559
Some(scratch_id.clone()),
25612560
).unwrap();
25622561

vmm/src/vstate.rs

+37-15
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ extern crate sys_util;
1212
use std::result;
1313

1414
use super::KvmContext;
15-
use arch::x86_64;
1615
use cpuid::{c3_template, filter_cpuid, t2_template};
1716
use kvm::*;
1817
use memory_model::{GuestAddress, GuestMemory, GuestMemoryError};
1918
use sys_util::EventFd;
2019
use vmm_config::machine_config::{CpuFeaturesTemplate, VmConfig};
21-
use x86_64::{interrupts, regs};
2220

2321
pub const KVM_TSS_ADDRESS: usize = 0xfffbd000;
22+
// Initial stack for the boot CPU.
23+
const BOOT_STACK_POINTER: usize = 0x8ff0;
2424

2525
/// Errors associated with the wrappers over KVM ioctls.
2626
#[derive(Debug)]
@@ -46,17 +46,21 @@ pub enum Error {
4646
/// The number of configured slots is bigger than the maximum reported by KVM.
4747
NotEnoughMemorySlots,
4848
/// Cannot set the local interruption due to bad configuration.
49-
LocalIntConfiguration(interrupts::Error),
49+
LocalIntConfiguration(arch::interrupts::Error),
5050
/// Cannot set the memory regions.
5151
SetUserMemoryRegion(sys_util::Error),
52+
#[cfg(target_arch = "x86_64")]
5253
/// Error configuring the MSR registers
53-
MSRSConfiguration(regs::Error),
54+
MSRSConfiguration(arch::regs::Error),
55+
#[cfg(target_arch = "x86_64")]
5456
/// Error configuring the general purpose registers
55-
REGSConfiguration(regs::Error),
57+
REGSConfiguration(arch::regs::Error),
58+
#[cfg(target_arch = "x86_64")]
5659
/// Error configuring the special registers
57-
SREGSConfiguration(regs::Error),
60+
SREGSConfiguration(arch::regs::Error),
61+
#[cfg(target_arch = "x86_64")]
5862
/// Error configuring the floating point related registers
59-
FPUConfiguration(regs::Error),
63+
FPUConfiguration(arch::regs::Error),
6064
/// Cannot configure the IRQ.
6165
Irq(sys_util::Error),
6266
}
@@ -165,7 +169,8 @@ impl Vcpu {
165169
})
166170
}
167171

168-
/// /// Configures the vcpu and should be called once per vcpu from the vcpu's thread.
172+
#[cfg(target_arch = "x86_64")]
173+
/// Configures the vcpu and should be called once per vcpu from the vcpu's thread.
169174
///
170175
/// # Arguments
171176
///
@@ -202,20 +207,37 @@ impl Vcpu {
202207
.set_cpuid2(&self.cpuid)
203208
.map_err(Error::SetSupportedCpusFailed)?;
204209

205-
x86_64::regs::setup_msrs(&self.fd).map_err(Error::MSRSConfiguration)?;
210+
arch::regs::setup_msrs(&self.fd).map_err(Error::MSRSConfiguration)?;
206211
// Safe to unwrap because this method is called after the VM is configured
207212
let vm_memory = vm
208213
.get_memory()
209214
.ok_or(Error::GuestMemory(GuestMemoryError::MemoryNotInitialized))?;
210-
x86_64::regs::setup_regs(
215+
arch::regs::setup_regs(
211216
&self.fd,
212217
kernel_start_addr.offset() as u64,
213-
x86_64::BOOT_STACK_POINTER as u64,
214-
x86_64::ZERO_PAGE_START as u64,
218+
BOOT_STACK_POINTER as u64,
219+
arch::ZERO_PAGE_START as u64,
215220
).map_err(Error::REGSConfiguration)?;
216-
x86_64::regs::setup_fpu(&self.fd).map_err(Error::FPUConfiguration)?;
217-
x86_64::regs::setup_sregs(vm_memory, &self.fd).map_err(Error::SREGSConfiguration)?;
218-
x86_64::interrupts::set_lint(&self.fd).map_err(Error::LocalIntConfiguration)?;
221+
arch::regs::setup_fpu(&self.fd).map_err(Error::FPUConfiguration)?;
222+
arch::regs::setup_sregs(vm_memory, &self.fd).map_err(Error::SREGSConfiguration)?;
223+
arch::interrupts::set_lint(&self.fd).map_err(Error::LocalIntConfiguration)?;
224+
Ok(())
225+
}
226+
227+
#[cfg(not(target_arch = "x86_64"))]
228+
/// Stub function that should be used whenever new architecture support is added.
229+
///
230+
/// # Arguments
231+
///
232+
/// * `machine_config` - Specifies necessary info used for the CPUID configuration.
233+
/// * `kernel_start_addr` - Offset from `guest_mem` at which the kernel starts.
234+
/// * `vm` - The virtual machine this vcpu will get attached to.
235+
pub fn configure(
236+
&mut self,
237+
_machine_config: &VmConfig,
238+
_kernel_start_addr: GuestAddress,
239+
_vm: &Vm,
240+
) -> Result<()> {
219241
Ok(())
220242
}
221243

0 commit comments

Comments
 (0)