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 #[macro_use] 13 extern crate serde_derive; 14 15 #[cfg(target_arch = "x86_64")] 16 use crate::x86_64::SgxEpcSection; 17 use std::collections::BTreeMap; 18 use std::fmt; 19 use std::result; 20 use std::sync::Arc; 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)] 30 pub enum Error { 31 #[cfg(target_arch = "x86_64")] 32 /// X86_64 specific error triggered during system configuration. 33 X86_64Setup(x86_64::Error), 34 #[cfg(target_arch = "aarch64")] 35 /// AArch64 specific error triggered during system configuration. 36 AArch64Setup(aarch64::Error), 37 /// The zero page extends past the end of guest_mem. 38 ZeroPagePastRamEnd, 39 /// Error writing the zero page of guest memory. 40 ZeroPageSetup(vm_memory::GuestMemoryError), 41 /// The memory map table extends past the end of guest memory. 42 MemmapTablePastRamEnd, 43 /// Error writing memory map table to guest memory. 44 MemmapTableSetup, 45 /// The hvm_start_info structure extends past the end of guest memory. 46 StartInfoPastRamEnd, 47 /// Error writing hvm_start_info to guest memory. 48 StartInfoSetup, 49 /// Failed to compute initramfs address. 50 InitramfsAddress, 51 /// Error writing module entry to guest memory. 52 ModlistSetup(vm_memory::GuestMemoryError), 53 /// RSDP Beyond Guest Memory 54 RsdpPastRamEnd, 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, 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, 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 get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE, 99 layout::CMDLINE_START, regs, CpuidFeatureEntry, EntryPoint, 100 }; 101 102 /// Safe wrapper for `sysconf(_SC_PAGESIZE)`. 103 #[cfg(target_arch = "x86_64")] 104 #[inline(always)] 105 fn pagesize() -> usize { 106 // Trivially safe 107 unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize } 108 } 109 110 #[derive(Clone, Default)] 111 pub struct NumaNode { 112 pub memory_regions: Vec<Arc<GuestRegionMmap>>, 113 pub hotplug_regions: Vec<Arc<GuestRegionMmap>>, 114 pub cpus: Vec<u8>, 115 pub distances: BTreeMap<u32, u8>, 116 pub memory_zones: Vec<String>, 117 #[cfg(target_arch = "x86_64")] 118 pub sgx_epc_sections: Vec<SgxEpcSection>, 119 } 120 121 pub type NumaNodes = BTreeMap<u32, NumaNode>; 122 123 /// Type for passing information about the initramfs in the guest memory. 124 pub struct InitramfsConfig { 125 /// Load address of initramfs in guest memory 126 pub address: vm_memory::GuestAddress, 127 /// Size of initramfs in guest memory 128 pub size: usize, 129 } 130 131 /// Types of devices that can get attached to this platform. 132 #[derive(Clone, Debug, PartialEq, Eq, Hash, Copy)] 133 pub enum DeviceType { 134 /// Device Type: Virtio. 135 Virtio(u32), 136 /// Device Type: Serial. 137 #[cfg(target_arch = "aarch64")] 138 Serial, 139 /// Device Type: RTC. 140 #[cfg(target_arch = "aarch64")] 141 Rtc, 142 /// Device Type: GPIO. 143 #[cfg(target_arch = "aarch64")] 144 Gpio, 145 } 146 147 /// Default (smallest) memory page size for the supported architectures. 148 pub const PAGE_SIZE: usize = 4096; 149 150 impl fmt::Display for DeviceType { 151 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 152 write!(f, "{:?}", self) 153 } 154 } 155 156 /// Structure to describe MMIO device information 157 #[derive(Clone, Debug)] 158 #[cfg(target_arch = "aarch64")] 159 pub struct MmioDeviceInfo { 160 pub addr: u64, 161 pub len: u64, 162 pub irq: u32, 163 } 164 165 /// Structure to describe PCI space information 166 #[derive(Clone, Debug)] 167 #[cfg(target_arch = "aarch64")] 168 pub struct PciSpaceInfo { 169 pub pci_segment_id: u16, 170 pub mmio_config_address: u64, 171 pub pci_device_space_start: u64, 172 pub pci_device_space_size: u64, 173 } 174 175 #[cfg(target_arch = "aarch64")] 176 impl DeviceInfoForFdt for MmioDeviceInfo { 177 fn addr(&self) -> u64 { 178 self.addr 179 } 180 fn irq(&self) -> u32 { 181 self.irq 182 } 183 fn length(&self) -> u64 { 184 self.len 185 } 186 } 187