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 } 52 53 /// Type for returning public functions outcome. 54 pub type Result<T> = result::Result<T, Error>; 55 56 /// Type for memory region types. 57 #[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize, Versionize)] 58 pub enum RegionType { 59 /// RAM type 60 Ram, 61 62 /// SubRegion memory region. 63 /// A SubRegion is a memory region sub-region, allowing for a region 64 /// to be split into sub regions managed separately. 65 /// For example, the x86 32-bit memory hole is a SubRegion. 66 SubRegion, 67 68 /// Reserved type. 69 /// A Reserved memory region is one that should not be used for memory 70 /// allocation. This type can be used to prevent the VMM from allocating 71 /// memory ranges in a specific address range. 72 Reserved, 73 } 74 75 impl VersionMapped for RegionType {} 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