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