1use std::fmt;
5use std::sync::LazyLock;
6
7use log::warn;
8use serde::{Deserialize, Serialize};
9use vm_memory::GuestAddress;
10
11#[cfg(target_arch = "aarch64")]
13pub mod aarch64;
14
15#[cfg(target_arch = "aarch64")]
16pub use aarch64::kvm::{Kvm, KvmArchError, OptionalCapabilities};
17#[cfg(target_arch = "aarch64")]
18pub use aarch64::vcpu::*;
19#[cfg(target_arch = "aarch64")]
20pub use aarch64::vm::{ArchVm, ArchVmError, VmState};
21#[cfg(target_arch = "aarch64")]
22pub use aarch64::{
23 ConfigurationError, arch_memory_regions, configure_system_for_boot, get_kernel_start,
24 initrd_load_addr, layout::*, load_kernel,
25};
26
27#[cfg(target_arch = "x86_64")]
29pub mod x86_64;
30
31#[cfg(target_arch = "x86_64")]
32pub use x86_64::kvm::{Kvm, KvmArchError};
33#[cfg(target_arch = "x86_64")]
34pub use x86_64::vcpu::*;
35#[cfg(target_arch = "x86_64")]
36pub use x86_64::vm::{ArchVm, ArchVmError, VmState};
37
38#[cfg(target_arch = "x86_64")]
39pub use crate::arch::x86_64::{
40 ConfigurationError, arch_memory_regions, configure_system_for_boot, get_kernel_start,
41 initrd_load_addr, layout::*, load_kernel,
42};
43
44#[derive(Clone, Debug, PartialEq, Eq, Hash, Copy, Serialize, Deserialize)]
46pub enum DeviceType {
47 Virtio(u32),
49 #[cfg(target_arch = "aarch64")]
51 Serial,
52 #[cfg(target_arch = "aarch64")]
54 Rtc,
55 BootTimer,
57}
58
59pub const GUEST_PAGE_SIZE: usize = 4096;
61
62pub fn host_page_size() -> usize {
64 static PAGE_SIZE: LazyLock<usize> = LazyLock::new(|| {
66 let r = unsafe { libc::sysconf(libc::_SC_PAGESIZE) };
68 usize::try_from(r).unwrap_or_else(|_| {
69 warn!("Could not get host page size with sysconf, assuming default 4K host pages");
70 4096
71 })
72 });
73
74 *PAGE_SIZE
75}
76
77impl fmt::Display for DeviceType {
78 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
79 write!(f, "{:?}", self)
80 }
81}
82
83#[derive(Debug, Copy, Clone, PartialEq)]
85pub enum BootProtocol {
86 LinuxBoot,
88 #[cfg(target_arch = "x86_64")]
89 PvhBoot,
91}
92
93impl fmt::Display for BootProtocol {
94 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
95 match self {
96 BootProtocol::LinuxBoot => write!(f, "Linux 64-bit boot protocol"),
97 #[cfg(target_arch = "x86_64")]
98 BootProtocol::PvhBoot => write!(f, "PVH boot protocol"),
99 }
100 }
101}
102
103#[derive(Debug, Copy, Clone)]
104pub struct EntryPoint {
108 pub entry_addr: GuestAddress,
110 pub protocol: BootProtocol,
112}
113
114fn arch_memory_regions_with_gap(
117 regions: &mut Vec<(GuestAddress, usize)>,
118 region_start: usize,
119 region_size: usize,
120 gap_start: usize,
121 gap_size: usize,
122) -> Option<(usize, usize)> {
123 assert!(gap_size > 0);
125
126 let first_addr_past_gap = gap_start + gap_size;
127 match (region_start + region_size).checked_sub(gap_start) {
128 None | Some(0) => {
130 regions.push((GuestAddress(region_start as u64), region_size));
131 None
132 }
133 Some(remaining) if region_start < gap_start => {
135 regions.push((GuestAddress(region_start as u64), gap_start - region_start));
136 Some((first_addr_past_gap, remaining))
137 }
138 Some(_) => Some((first_addr_past_gap.max(region_start), region_size)),
140 }
141}