mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
aarch64: Porting fdt related files from Firecracker
When booting VM on AArch64 machines, we need to construct the flattened device tree before loading kernel. Hence here we add the implementation of the flattened device tree for AArch64. Signed-off-by: Henry Wang <Henry.Wang@arm.com>
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
// Copyright 2020 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/// Module for the flattened device tree.
|
||||
pub mod fdt;
|
||||
/// Module for the global interrupt controller configuration.
|
||||
pub mod gic;
|
||||
mod gicv2;
|
||||
@@ -11,26 +14,15 @@ pub mod layout;
|
||||
pub mod regs;
|
||||
|
||||
use crate::RegionType;
|
||||
use aarch64::gic::GICDevice;
|
||||
use kvm_ioctls::*;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::CStr;
|
||||
use std::fmt::Debug;
|
||||
use vm_memory::{
|
||||
Address, GuestAddress, GuestMemory, 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.
|
||||
pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, RegionType)> {
|
||||
vec![(GuestAddress(0), size as usize, RegionType::Ram)]
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
/// Specifies the entry point address where the guest must start
|
||||
/// executing code.
|
||||
@@ -48,20 +40,88 @@ pub fn configure_vcpu(
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
/// Stub function that needs to be implemented when aarch64 functionality is added.
|
||||
pub fn configure_system(
|
||||
_guest_mem: &GuestMemoryMmap,
|
||||
_cmdline_addr: GuestAddress,
|
||||
_cmdline_size: usize,
|
||||
_num_cpus: u8,
|
||||
_rsdp_addr: Option<GuestAddress>,
|
||||
/// Errors thrown while configuring aarch64 system.
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// Failed to create a Flattened Device Tree for this aarch64 VM.
|
||||
SetupFDT(fdt::Error),
|
||||
/// Failed to compute the initrd address.
|
||||
InitrdAddress,
|
||||
}
|
||||
|
||||
impl From<Error> for super::Error {
|
||||
fn from(e: Error) -> super::Error {
|
||||
super::Error::AArch64Setup(e)
|
||||
}
|
||||
}
|
||||
|
||||
pub use self::fdt::DeviceInfoForFDT;
|
||||
use crate::DeviceType;
|
||||
|
||||
pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, RegionType)> {
|
||||
let mut regions = Vec::new();
|
||||
// 0 ~ 256 MiB: Reserved
|
||||
regions.push((
|
||||
GuestAddress(0),
|
||||
layout::PCI_DEVICES_MAPPED_IO_START as usize,
|
||||
RegionType::Reserved,
|
||||
));
|
||||
|
||||
// 256 MiB ~ 1 G: MMIO space
|
||||
regions.push((
|
||||
GuestAddress(layout::PCI_DEVICES_MAPPED_IO_START),
|
||||
layout::PCI_DEVICES_MAPPED_IO_SIZE as usize,
|
||||
RegionType::SubRegion,
|
||||
));
|
||||
|
||||
// 1G ~ 2G: reserved. The leading 256M for PCIe MMCONFIG space
|
||||
regions.push((
|
||||
layout::PCI_MMCONFIG_START,
|
||||
(layout::RAM_64BIT_START - layout::PCI_MMCONFIG_START.0) as usize,
|
||||
RegionType::Reserved,
|
||||
));
|
||||
|
||||
regions.push((
|
||||
GuestAddress(layout::RAM_64BIT_START),
|
||||
size as usize,
|
||||
RegionType::Ram,
|
||||
));
|
||||
|
||||
regions
|
||||
}
|
||||
|
||||
/// Configures the system and should be called once per vm before starting vcpu threads.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `guest_mem` - The memory to be used by the guest.
|
||||
/// * `num_cpus` - Number of virtual CPUs the guest will have.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[allow(unused_variables)]
|
||||
pub fn configure_system<T: DeviceInfoForFDT + Clone + Debug>(
|
||||
guest_mem: &GuestMemoryMmap,
|
||||
cmdline_cstring: &CStr,
|
||||
vcpu_mpidr: Vec<u64>,
|
||||
device_info: &HashMap<(DeviceType, String), T>,
|
||||
gic_device: &Box<dyn GICDevice>,
|
||||
initrd: &Option<super::InitrdConfig>,
|
||||
) -> super::Result<()> {
|
||||
let dtb = fdt::create_fdt(
|
||||
guest_mem,
|
||||
cmdline_cstring,
|
||||
vcpu_mpidr,
|
||||
device_info,
|
||||
gic_device,
|
||||
initrd,
|
||||
)
|
||||
.map_err(Error::SetupFDT)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Stub function that needs to be implemented when aarch64 functionality is added.
|
||||
pub fn get_reserved_mem_addr() -> usize {
|
||||
0
|
||||
/// Returns the memory address where the kernel could be loaded.
|
||||
pub fn get_kernel_start() -> u64 {
|
||||
layout::RAM_64BIT_START
|
||||
}
|
||||
|
||||
// Auxiliary function to get the address where the device tree blob is loaded.
|
||||
@@ -104,3 +164,46 @@ pub fn check_required_kvm_extensions(kvm: &Kvm) -> super::Result<()> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_arch_memory_regions_dram() {
|
||||
let regions = arch_memory_regions((1usize << 32) as u64); //4GB
|
||||
assert_eq!(4, regions.len());
|
||||
assert_eq!(GuestAddress(layout::RAM_64BIT_START), regions[3].0);
|
||||
assert_eq!(1usize << 32, regions[3].1);
|
||||
assert_eq!(RegionType::Ram, regions[3].2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_fdt_addr() {
|
||||
let mut regions = Vec::new();
|
||||
|
||||
regions.push((
|
||||
GuestAddress(layout::RAM_64BIT_START),
|
||||
(layout::FDT_MAX_SIZE - 0x1000) as usize,
|
||||
));
|
||||
let mem = GuestMemoryMmap::from_ranges(®ions).expect("Cannot initialize memory");
|
||||
assert_eq!(get_fdt_addr(&mem), layout::RAM_64BIT_START);
|
||||
regions.clear();
|
||||
|
||||
regions.push((
|
||||
GuestAddress(layout::RAM_64BIT_START),
|
||||
(layout::FDT_MAX_SIZE) as usize,
|
||||
));
|
||||
let mem = GuestMemoryMmap::from_ranges(®ions).expect("Cannot initialize memory");
|
||||
assert_eq!(get_fdt_addr(&mem), layout::RAM_64BIT_START);
|
||||
regions.clear();
|
||||
|
||||
regions.push((
|
||||
GuestAddress(layout::RAM_64BIT_START),
|
||||
(layout::FDT_MAX_SIZE + 0x1000) as usize,
|
||||
));
|
||||
let mem = GuestMemoryMmap::from_ranges(®ions).expect("Cannot initialize memory");
|
||||
assert_eq!(get_fdt_addr(&mem), 0x1000 + layout::RAM_64BIT_START);
|
||||
regions.clear();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user