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 22 type GuestMemoryMmap = vm_memory::GuestMemoryMmap<vm_memory::bitmap::AtomicBitmap>; 23 type GuestRegionMmap = vm_memory::GuestRegionMmap<vm_memory::bitmap::AtomicBitmap>; 24 25 /// Type for returning error code. 26 #[derive(Debug, Error)] 27 pub enum Error { 28 #[cfg(target_arch = "x86_64")] 29 #[error("Platform specific error (x86_64): {0:?}")] 30 PlatformSpecific(x86_64::Error), 31 #[cfg(target_arch = "aarch64")] 32 #[error("Platform specific error (aarch64): {0:?}")] 33 PlatformSpecific(aarch64::Error), 34 #[error("The memory map table extends past the end of guest memory")] 35 MemmapTablePastRamEnd, 36 #[error("Error writing memory map table to guest memory")] 37 MemmapTableSetup, 38 #[error("The hvm_start_info structure extends past the end of guest memory")] 39 StartInfoPastRamEnd, 40 #[error("Error writing hvm_start_info to guest memory")] 41 StartInfoSetup, 42 #[error("Failed to compute initramfs address")] 43 InitramfsAddress, 44 #[error("Error writing module entry to guest memory: {0}")] 45 ModlistSetup(#[source] vm_memory::GuestMemoryError), 46 #[error("RSDP extends past the end of guest memory")] 47 RsdpPastRamEnd, 48 #[error("Failed to setup Zero Page for bzImage")] 49 ZeroPageSetup(#[source] vm_memory::GuestMemoryError), 50 #[error("Zero Page for bzImage past RAM end")] 51 ZeroPagePastRamEnd, 52 } 53 54 /// Type for returning public functions outcome. 55 pub type Result<T> = result::Result<T, Error>; 56 57 /// Type for memory region types. 58 #[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)] 59 pub enum RegionType { 60 /// RAM type 61 Ram, 62 63 /// SubRegion memory region. 64 /// A SubRegion is a memory region sub-region, allowing for a region 65 /// to be split into sub regions managed separately. 66 /// For example, the x86 32-bit memory hole is a SubRegion. 67 SubRegion, 68 69 /// Reserved type. 70 /// A Reserved memory region is one that should not be used for memory 71 /// allocation. This type can be used to prevent the VMM from allocating 72 /// memory ranges in a specific address range. 73 Reserved, 74 } 75 76 /// Module for aarch64 related functionality. 77 #[cfg(target_arch = "aarch64")] 78 pub mod aarch64; 79 80 #[cfg(target_arch = "aarch64")] 81 pub use aarch64::{ 82 arch_memory_regions, configure_system, configure_vcpu, fdt::DeviceInfoForFdt, 83 get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE, 84 layout::IRQ_BASE, uefi, EntryPoint, _NSIG, 85 }; 86 87 #[cfg(target_arch = "x86_64")] 88 pub mod x86_64; 89 90 #[cfg(target_arch = "x86_64")] 91 pub use x86_64::{ 92 arch_memory_regions, configure_system, configure_vcpu, generate_common_cpuid, 93 generate_ram_ranges, get_host_cpu_phys_bits, initramfs_load_addr, layout, 94 layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START, regs, CpuidConfig, CpuidFeatureEntry, 95 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