1bd8db86bSRuoqing He // Copyright © 2024 Institute of Software, CAS. All rights reserved.
2ce624a6dSMichael Zhao // Copyright 2020 Arm Limited (or its affiliates). All rights reserved.
398b95688SAlejandro Jimenez // Copyright © 2020, Oracle and/or its affiliates.
498b95688SAlejandro Jimenez //
5b56b4ca8SSamuel Ortiz // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
6b56b4ca8SSamuel Ortiz // SPDX-License-Identifier: Apache-2.0
7b56b4ca8SSamuel Ortiz
82d13751dSHenry Wang //! Implements platform specific functionality.
9bd8db86bSRuoqing He //! Supported platforms: x86_64, aarch64, riscv64.
10b56b4ca8SSamuel Ortiz
11e10d9b13SSebastien Boeuf #[macro_use]
12e10d9b13SSebastien Boeuf extern crate log;
13b56b4ca8SSamuel Ortiz
14165364e0SHenry Wang use std::collections::BTreeMap;
15165364e0SHenry Wang use std::sync::Arc;
1661e57e1cSRuoqing He use std::{fmt, result};
1788a9f799SRob Bradford
1888a9f799SRob Bradford use serde::{Deserialize, Serialize};
1947529796SRob Bradford use thiserror::Error;
20b56b4ca8SSamuel Ortiz
2188a9f799SRob Bradford #[cfg(target_arch = "x86_64")]
2288a9f799SRob Bradford use crate::x86_64::SgxEpcSection;
2388a9f799SRob Bradford
24b5bcdbafSBo Chen type GuestMemoryMmap = vm_memory::GuestMemoryMmap<vm_memory::bitmap::AtomicBitmap>;
25165364e0SHenry Wang type GuestRegionMmap = vm_memory::GuestRegionMmap<vm_memory::bitmap::AtomicBitmap>;
26b5bcdbafSBo Chen
272d13751dSHenry Wang /// Type for returning error code.
2847529796SRob Bradford #[derive(Debug, Error)]
29b56b4ca8SSamuel Ortiz pub enum Error {
30b56b4ca8SSamuel Ortiz #[cfg(target_arch = "x86_64")]
31*06a868cbSPhilipp Schuster #[error("Platform specific error (x86_64)")]
329bd9c0cbSPhilipp Schuster PlatformSpecific(#[from] x86_64::Error),
338f7dc735SMichael Zhao #[cfg(target_arch = "aarch64")]
34*06a868cbSPhilipp Schuster #[error("Platform specific error (aarch64)")]
359bd9c0cbSPhilipp Schuster PlatformSpecific(#[from] aarch64::Error),
36bd8db86bSRuoqing He #[cfg(target_arch = "riscv64")]
37*06a868cbSPhilipp Schuster #[error("Platform specific error (riscv64)")]
389bd9c0cbSPhilipp Schuster PlatformSpecific(#[from] riscv64::Error),
3947529796SRob Bradford #[error("The memory map table extends past the end of guest memory")]
4098b95688SAlejandro Jimenez MemmapTablePastRamEnd,
4147529796SRob Bradford #[error("Error writing memory map table to guest memory")]
4298b95688SAlejandro Jimenez MemmapTableSetup,
4347529796SRob Bradford #[error("The hvm_start_info structure extends past the end of guest memory")]
4498b95688SAlejandro Jimenez StartInfoPastRamEnd,
4547529796SRob Bradford #[error("Error writing hvm_start_info to guest memory")]
4698b95688SAlejandro Jimenez StartInfoSetup,
4747529796SRob Bradford #[error("Failed to compute initramfs address")]
486cce7b95SDamjan Georgievski InitramfsAddress,
49*06a868cbSPhilipp Schuster #[error("Error writing module entry to guest memory")]
5047529796SRob Bradford ModlistSetup(#[source] vm_memory::GuestMemoryError),
5147529796SRob Bradford #[error("RSDP extends past the end of guest memory")]
5285ad7249SRob Bradford RsdpPastRamEnd,
5309cf8c31SStefan Nuernberger #[error("Failed to setup Zero Page for bzImage")]
5409cf8c31SStefan Nuernberger ZeroPageSetup(#[source] vm_memory::GuestMemoryError),
5509cf8c31SStefan Nuernberger #[error("Zero Page for bzImage past RAM end")]
5609cf8c31SStefan Nuernberger ZeroPagePastRamEnd,
57b56b4ca8SSamuel Ortiz }
582d13751dSHenry Wang
592d13751dSHenry Wang /// Type for returning public functions outcome.
60b56b4ca8SSamuel Ortiz pub type Result<T> = result::Result<T, Error>;
61b56b4ca8SSamuel Ortiz
622d13751dSHenry Wang /// Type for memory region types.
6310ab87d6SRob Bradford #[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)]
64f98a69f4SSebastien Boeuf pub enum RegionType {
65f98a69f4SSebastien Boeuf /// RAM type
66f98a69f4SSebastien Boeuf Ram,
67299d8878SSamuel Ortiz
68299d8878SSamuel Ortiz /// SubRegion memory region.
69299d8878SSamuel Ortiz /// A SubRegion is a memory region sub-region, allowing for a region
70299d8878SSamuel Ortiz /// to be split into sub regions managed separately.
71299d8878SSamuel Ortiz /// For example, the x86 32-bit memory hole is a SubRegion.
72299d8878SSamuel Ortiz SubRegion,
73299d8878SSamuel Ortiz
74299d8878SSamuel Ortiz /// Reserved type.
75299d8878SSamuel Ortiz /// A Reserved memory region is one that should not be used for memory
76299d8878SSamuel Ortiz /// allocation. This type can be used to prevent the VMM from allocating
77299d8878SSamuel Ortiz /// memory ranges in a specific address range.
78f98a69f4SSebastien Boeuf Reserved,
79f98a69f4SSebastien Boeuf }
80f98a69f4SSebastien Boeuf
812d13751dSHenry Wang /// Module for aarch64 related functionality.
82b56b4ca8SSamuel Ortiz #[cfg(target_arch = "aarch64")]
83b56b4ca8SSamuel Ortiz pub mod aarch64;
84b56b4ca8SSamuel Ortiz
85b56b4ca8SSamuel Ortiz #[cfg(target_arch = "aarch64")]
86b56b4ca8SSamuel Ortiz pub use aarch64::{
8740da6210SRob Bradford arch_memory_regions, configure_system, configure_vcpu, fdt::DeviceInfoForFdt,
88298a5580SMichael Zhao get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE,
89c1f555cdSAlyssa Ross layout::IRQ_BASE, uefi, EntryPoint, _NSIG,
90b56b4ca8SSamuel Ortiz };
91b56b4ca8SSamuel Ortiz
92bd8db86bSRuoqing He /// Module for riscv64 related functionality.
93bd8db86bSRuoqing He #[cfg(target_arch = "riscv64")]
94bd8db86bSRuoqing He pub mod riscv64;
95bd8db86bSRuoqing He
96bd8db86bSRuoqing He #[cfg(target_arch = "riscv64")]
97bd8db86bSRuoqing He pub use riscv64::{
98bd8db86bSRuoqing He arch_memory_regions, configure_system, configure_vcpu, fdt::DeviceInfoForFdt,
99bd8db86bSRuoqing He get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE,
100bd8db86bSRuoqing He layout::IRQ_BASE, EntryPoint, _NSIG,
101bd8db86bSRuoqing He };
102bd8db86bSRuoqing He
103b56b4ca8SSamuel Ortiz #[cfg(target_arch = "x86_64")]
104b56b4ca8SSamuel Ortiz pub mod x86_64;
105b56b4ca8SSamuel Ortiz
106b56b4ca8SSamuel Ortiz #[cfg(target_arch = "x86_64")]
107b56b4ca8SSamuel Ortiz pub use x86_64::{
108569be6e7SBo Chen arch_memory_regions, configure_system, configure_vcpu, generate_common_cpuid,
10938a2808dSBo Chen generate_ram_ranges, get_host_cpu_phys_bits, initramfs_load_addr, layout,
11038a2808dSBo Chen layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START, regs, CpuidConfig, CpuidFeatureEntry,
11138a2808dSBo Chen EntryPoint, _NSIG,
112b56b4ca8SSamuel Ortiz };
1130ce7de3eSDamjan Georgievski
1140ce7de3eSDamjan Georgievski /// Safe wrapper for `sysconf(_SC_PAGESIZE)`.
1151befae87SMichael Zhao #[cfg(target_arch = "x86_64")]
1160ce7de3eSDamjan Georgievski #[inline(always)]
pagesize() -> usize1170ce7de3eSDamjan Georgievski fn pagesize() -> usize {
118f16b5771SWei Liu // SAFETY: Trivially safe
1190ce7de3eSDamjan Georgievski unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
1200ce7de3eSDamjan Georgievski }
1216cce7b95SDamjan Georgievski
122165364e0SHenry Wang #[derive(Clone, Default)]
123165364e0SHenry Wang pub struct NumaNode {
124165364e0SHenry Wang pub memory_regions: Vec<Arc<GuestRegionMmap>>,
125165364e0SHenry Wang pub hotplug_regions: Vec<Arc<GuestRegionMmap>>,
126165364e0SHenry Wang pub cpus: Vec<u8>,
1273029fbeaSThomas Barrett pub pci_segments: Vec<u16>,
128165364e0SHenry Wang pub distances: BTreeMap<u32, u8>,
129165364e0SHenry Wang pub memory_zones: Vec<String>,
130165364e0SHenry Wang #[cfg(target_arch = "x86_64")]
131165364e0SHenry Wang pub sgx_epc_sections: Vec<SgxEpcSection>,
132165364e0SHenry Wang }
133165364e0SHenry Wang
134165364e0SHenry Wang pub type NumaNodes = BTreeMap<u32, NumaNode>;
135165364e0SHenry Wang
1366cce7b95SDamjan Georgievski /// Type for passing information about the initramfs in the guest memory.
1376cce7b95SDamjan Georgievski pub struct InitramfsConfig {
1386cce7b95SDamjan Georgievski /// Load address of initramfs in guest memory
1396cce7b95SDamjan Georgievski pub address: vm_memory::GuestAddress,
1406cce7b95SDamjan Georgievski /// Size of initramfs in guest memory
1416cce7b95SDamjan Georgievski pub size: usize,
1426cce7b95SDamjan Georgievski }
1432d13751dSHenry Wang
1442d13751dSHenry Wang /// Types of devices that can get attached to this platform.
1452d13751dSHenry Wang #[derive(Clone, Debug, PartialEq, Eq, Hash, Copy)]
1462d13751dSHenry Wang pub enum DeviceType {
1472d13751dSHenry Wang /// Device Type: Virtio.
1482d13751dSHenry Wang Virtio(u32),
1492d13751dSHenry Wang /// Device Type: Serial.
150bd8db86bSRuoqing He #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
1512d13751dSHenry Wang Serial,
1522d13751dSHenry Wang /// Device Type: RTC.
1532d13751dSHenry Wang #[cfg(target_arch = "aarch64")]
15440da6210SRob Bradford Rtc,
155a59ff42aSHenry Wang /// Device Type: GPIO.
156a59ff42aSHenry Wang #[cfg(target_arch = "aarch64")]
15740da6210SRob Bradford Gpio,
1582d13751dSHenry Wang }
1592d13751dSHenry Wang
1602d13751dSHenry Wang /// Default (smallest) memory page size for the supported architectures.
1612d13751dSHenry Wang pub const PAGE_SIZE: usize = 4096;
1622d13751dSHenry Wang
1632d13751dSHenry Wang impl fmt::Display for DeviceType {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1642d13751dSHenry Wang fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1655e527294SRob Bradford write!(f, "{self:?}")
1662d13751dSHenry Wang }
1672d13751dSHenry Wang }
1682d13751dSHenry Wang
1692d13751dSHenry Wang /// Structure to describe MMIO device information
1702d13751dSHenry Wang #[derive(Clone, Debug)]
171bd8db86bSRuoqing He #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
17240da6210SRob Bradford pub struct MmioDeviceInfo {
1732d13751dSHenry Wang pub addr: u64,
1744cf22e4eSWei Liu pub len: u64,
1752d13751dSHenry Wang pub irq: u32,
1762d13751dSHenry Wang }
1772d13751dSHenry Wang
17807bef815SHenry Wang /// Structure to describe PCI space information
17907bef815SHenry Wang #[derive(Clone, Debug)]
180bd8db86bSRuoqing He #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
18107bef815SHenry Wang pub struct PciSpaceInfo {
18207bef815SHenry Wang pub pci_segment_id: u16,
18307bef815SHenry Wang pub mmio_config_address: u64,
18407bef815SHenry Wang pub pci_device_space_start: u64,
18507bef815SHenry Wang pub pci_device_space_size: u64,
18607bef815SHenry Wang }
18707bef815SHenry Wang
188bd8db86bSRuoqing He #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
18940da6210SRob Bradford impl DeviceInfoForFdt for MmioDeviceInfo {
addr(&self) -> u641902d13751dSHenry Wang fn addr(&self) -> u64 {
1912d13751dSHenry Wang self.addr
1922d13751dSHenry Wang }
irq(&self) -> u321932d13751dSHenry Wang fn irq(&self) -> u32 {
1942d13751dSHenry Wang self.irq
1952d13751dSHenry Wang }
length(&self) -> u641962d13751dSHenry Wang fn length(&self) -> u64 {
1974cf22e4eSWei Liu self.len
1982d13751dSHenry Wang }
1992d13751dSHenry Wang }
200