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