1 // Copyright 2020 Arm Limited (or its affiliates). All rights reserved. 2 // Copyright © 2020, Oracle and/or its affiliates. 3 // 4 // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 // SPDX-License-Identifier: Apache-2.0 6 7 //! Implements platform specific functionality. 8 //! Supported platforms: x86_64, aarch64. 9 10 #[macro_use] 11 extern crate log; 12 13 use std::collections::BTreeMap; 14 use std::sync::Arc; 15 use std::{fmt, result}; 16 17 use serde::{Deserialize, Serialize}; 18 use thiserror::Error; 19 20 #[cfg(target_arch = "x86_64")] 21 use crate::x86_64::SgxEpcSection; 22 23 type GuestMemoryMmap = vm_memory::GuestMemoryMmap<vm_memory::bitmap::AtomicBitmap>; 24 type GuestRegionMmap = vm_memory::GuestRegionMmap<vm_memory::bitmap::AtomicBitmap>; 25 26 /// Type for returning error code. 27 #[derive(Debug, Error)] 28 pub enum Error { 29 #[cfg(target_arch = "x86_64")] 30 #[error("Platform specific error (x86_64): {0:?}")] 31 PlatformSpecific(x86_64::Error), 32 #[cfg(target_arch = "aarch64")] 33 #[error("Platform specific error (aarch64): {0:?}")] 34 PlatformSpecific(aarch64::Error), 35 #[error("The memory map table extends past the end of guest memory")] 36 MemmapTablePastRamEnd, 37 #[error("Error writing memory map table to guest memory")] 38 MemmapTableSetup, 39 #[error("The hvm_start_info structure extends past the end of guest memory")] 40 StartInfoPastRamEnd, 41 #[error("Error writing hvm_start_info to guest memory")] 42 StartInfoSetup, 43 #[error("Failed to compute initramfs address")] 44 InitramfsAddress, 45 #[error("Error writing module entry to guest memory: {0}")] 46 ModlistSetup(#[source] vm_memory::GuestMemoryError), 47 #[error("RSDP extends past the end of guest memory")] 48 RsdpPastRamEnd, 49 #[error("Failed to setup Zero Page for bzImage")] 50 ZeroPageSetup(#[source] vm_memory::GuestMemoryError), 51 #[error("Zero Page for bzImage past RAM end")] 52 ZeroPagePastRamEnd, 53 } 54 55 /// Type for returning public functions outcome. 56 pub type Result<T> = result::Result<T, Error>; 57 58 /// Type for memory region types. 59 #[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)] 60 pub enum RegionType { 61 /// RAM type 62 Ram, 63 64 /// SubRegion memory region. 65 /// A SubRegion is a memory region sub-region, allowing for a region 66 /// to be split into sub regions managed separately. 67 /// For example, the x86 32-bit memory hole is a SubRegion. 68 SubRegion, 69 70 /// Reserved type. 71 /// A Reserved memory region is one that should not be used for memory 72 /// allocation. This type can be used to prevent the VMM from allocating 73 /// memory ranges in a specific address range. 74 Reserved, 75 } 76 77 /// Module for aarch64 related functionality. 78 #[cfg(target_arch = "aarch64")] 79 pub mod aarch64; 80 81 #[cfg(target_arch = "aarch64")] 82 pub use aarch64::{ 83 arch_memory_regions, configure_system, configure_vcpu, fdt::DeviceInfoForFdt, 84 get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE, 85 layout::IRQ_BASE, uefi, EntryPoint, _NSIG, 86 }; 87 88 #[cfg(target_arch = "x86_64")] 89 pub mod x86_64; 90 91 #[cfg(target_arch = "x86_64")] 92 pub use x86_64::{ 93 arch_memory_regions, configure_system, configure_vcpu, generate_common_cpuid, 94 generate_ram_ranges, get_host_cpu_phys_bits, initramfs_load_addr, layout, 95 layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START, regs, CpuidConfig, CpuidFeatureEntry, 96 EntryPoint, _NSIG, 97 }; 98 99 /// Safe wrapper for `sysconf(_SC_PAGESIZE)`. 100 #[cfg(target_arch = "x86_64")] 101 #[inline(always)] 102 fn pagesize() -> usize { 103 // SAFETY: Trivially safe 104 unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize } 105 } 106 107 #[derive(Clone, Default)] 108 pub struct NumaNode { 109 pub memory_regions: Vec<Arc<GuestRegionMmap>>, 110 pub hotplug_regions: Vec<Arc<GuestRegionMmap>>, 111 pub cpus: Vec<u8>, 112 pub pci_segments: Vec<u16>, 113 pub distances: BTreeMap<u32, u8>, 114 pub memory_zones: Vec<String>, 115 #[cfg(target_arch = "x86_64")] 116 pub sgx_epc_sections: Vec<SgxEpcSection>, 117 } 118 119 pub type NumaNodes = BTreeMap<u32, NumaNode>; 120 121 /// Type for passing information about the initramfs in the guest memory. 122 pub struct InitramfsConfig { 123 /// Load address of initramfs in guest memory 124 pub address: vm_memory::GuestAddress, 125 /// Size of initramfs in guest memory 126 pub size: usize, 127 } 128 129 /// Types of devices that can get attached to this platform. 130 #[derive(Clone, Debug, PartialEq, Eq, Hash, Copy)] 131 pub enum DeviceType { 132 /// Device Type: Virtio. 133 Virtio(u32), 134 /// Device Type: Serial. 135 #[cfg(target_arch = "aarch64")] 136 Serial, 137 /// Device Type: RTC. 138 #[cfg(target_arch = "aarch64")] 139 Rtc, 140 /// Device Type: GPIO. 141 #[cfg(target_arch = "aarch64")] 142 Gpio, 143 } 144 145 /// Default (smallest) memory page size for the supported architectures. 146 pub const PAGE_SIZE: usize = 4096; 147 148 impl fmt::Display for DeviceType { 149 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 150 write!(f, "{self:?}") 151 } 152 } 153 154 /// Structure to describe MMIO device information 155 #[derive(Clone, Debug)] 156 #[cfg(target_arch = "aarch64")] 157 pub struct MmioDeviceInfo { 158 pub addr: u64, 159 pub len: u64, 160 pub irq: u32, 161 } 162 163 /// Structure to describe PCI space information 164 #[derive(Clone, Debug)] 165 #[cfg(target_arch = "aarch64")] 166 pub struct PciSpaceInfo { 167 pub pci_segment_id: u16, 168 pub mmio_config_address: u64, 169 pub pci_device_space_start: u64, 170 pub pci_device_space_size: u64, 171 } 172 173 #[cfg(target_arch = "aarch64")] 174 impl DeviceInfoForFdt for MmioDeviceInfo { 175 fn addr(&self) -> u64 { 176 self.addr 177 } 178 fn irq(&self) -> u32 { 179 self.irq 180 } 181 fn length(&self) -> u64 { 182 self.len 183 } 184 } 185