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, 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 get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE, 95 layout::CMDLINE_START, regs, CpuidFeatureEntry, EntryPoint, 96 }; 97 98 /// Safe wrapper for `sysconf(_SC_PAGESIZE)`. 99 #[cfg(target_arch = "x86_64")] 100 #[inline(always)] 101 fn pagesize() -> usize { 102 // SAFETY: Trivially safe 103 unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize } 104 } 105 106 #[derive(Clone, Default)] 107 pub struct NumaNode { 108 pub memory_regions: Vec<Arc<GuestRegionMmap>>, 109 pub hotplug_regions: Vec<Arc<GuestRegionMmap>>, 110 pub cpus: Vec<u8>, 111 pub distances: BTreeMap<u32, u8>, 112 pub memory_zones: Vec<String>, 113 #[cfg(target_arch = "x86_64")] 114 pub sgx_epc_sections: Vec<SgxEpcSection>, 115 } 116 117 pub type NumaNodes = BTreeMap<u32, NumaNode>; 118 119 /// Type for passing information about the initramfs in the guest memory. 120 pub struct InitramfsConfig { 121 /// Load address of initramfs in guest memory 122 pub address: vm_memory::GuestAddress, 123 /// Size of initramfs in guest memory 124 pub size: usize, 125 } 126 127 /// Types of devices that can get attached to this platform. 128 #[derive(Clone, Debug, PartialEq, Eq, Hash, Copy)] 129 pub enum DeviceType { 130 /// Device Type: Virtio. 131 Virtio(u32), 132 /// Device Type: Serial. 133 #[cfg(target_arch = "aarch64")] 134 Serial, 135 /// Device Type: RTC. 136 #[cfg(target_arch = "aarch64")] 137 Rtc, 138 /// Device Type: GPIO. 139 #[cfg(target_arch = "aarch64")] 140 Gpio, 141 } 142 143 /// Default (smallest) memory page size for the supported architectures. 144 pub const PAGE_SIZE: usize = 4096; 145 146 impl fmt::Display for DeviceType { 147 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 148 write!(f, "{self:?}") 149 } 150 } 151 152 /// Structure to describe MMIO device information 153 #[derive(Clone, Debug)] 154 #[cfg(target_arch = "aarch64")] 155 pub struct MmioDeviceInfo { 156 pub addr: u64, 157 pub len: u64, 158 pub irq: u32, 159 } 160 161 /// Structure to describe PCI space information 162 #[derive(Clone, Debug)] 163 #[cfg(target_arch = "aarch64")] 164 pub struct PciSpaceInfo { 165 pub pci_segment_id: u16, 166 pub mmio_config_address: u64, 167 pub pci_device_space_start: u64, 168 pub pci_device_space_size: u64, 169 } 170 171 #[cfg(target_arch = "aarch64")] 172 impl DeviceInfoForFdt for MmioDeviceInfo { 173 fn addr(&self) -> u64 { 174 self.addr 175 } 176 fn irq(&self) -> u32 { 177 self.irq 178 } 179 fn length(&self) -> u64 { 180 self.len 181 } 182 } 183