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