xref: /cloud-hypervisor/arch/src/lib.rs (revision 7d7bfb2034001d4cb15df2ddc56d2d350c8da30f)
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