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