Skip to main content

axvm_types/
lib.rs

1// Copyright 2025 The Axvisor Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Shared base types for AxVM and virtualization capability components.
16//!
17//! This crate intentionally contains only small value types and aliases. It is
18//! not a host capability API and must not depend on any OS-specific crate.
19
20#![no_std]
21
22extern crate alloc;
23
24use alloc::{string::String, vec::Vec};
25use core::fmt::{Display, Formatter};
26
27use ax_memory_addr::{AddrRange, PhysAddr, VirtAddr, def_usize_addr, def_usize_addr_formatter};
28
29/// Virtual machine identifier.
30pub type VMId = usize;
31
32/// Virtual CPU identifier within a VM.
33pub type VCpuId = usize;
34
35/// Interrupt vector number injected into a guest.
36pub type InterruptVector = u8;
37
38/// Interrupt trigger mode.
39///
40/// Represents the trigger mode of an interrupt in a platform-neutral way.
41/// Architectures that do not distinguish between edge and level triggering
42/// can ignore this parameter.
43#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub enum InterruptTriggerMode {
45    /// Edge-triggered interrupt.
46    EdgeTriggered,
47    /// Level-triggered interrupt.
48    LevelTriggered,
49}
50
51/// Identifier of an interrupt line within a virtual machine.
52#[derive(Clone, Copy, Debug, Eq, PartialEq)]
53pub struct IrqLineId(pub usize);
54
55/// The maximum number of virtual CPUs supported in a virtual machine.
56pub const MAX_VCPU_NUM: usize = 64;
57
58/// A set of virtual CPUs.
59pub type VCpuSet = ax_cpumask::CpuMask<MAX_VCPU_NUM>;
60
61/// Host virtual address.
62pub type HostVirtAddr = VirtAddr;
63
64/// Host physical address.
65pub type HostPhysAddr = PhysAddr;
66
67def_usize_addr! {
68    /// Guest virtual address.
69    pub type GuestVirtAddr;
70
71    /// Guest physical address.
72    pub type GuestPhysAddr;
73}
74
75def_usize_addr_formatter! {
76    GuestVirtAddr = "GVA:{}";
77    GuestPhysAddr = "GPA:{}";
78}
79
80/// Guest virtual address range.
81pub type GuestVirtAddrRange = AddrRange<GuestVirtAddr>;
82
83/// Guest physical address range.
84pub type GuestPhysAddrRange = AddrRange<GuestPhysAddr>;
85
86/// Common AxVM result type.
87pub type AxVmResult<T = ()> = ax_errno::AxResult<T>;
88
89/// Common AxVM error type.
90pub type AxVmError = ax_errno::AxError;
91
92/// A part of `AxVMConfig`, which represents guest VM type.
93#[derive(Default, Clone, Copy, PartialEq, Eq, Debug)]
94pub enum VMType {
95    /// Host VM, used for boot from Linux like Jailhouse do, named "type1.5".
96    VMTHostVM = 0,
97    /// Guest RTOS, generally a simple guest OS with most of the resource passthrough.
98    #[default]
99    VMTRTOS   = 1,
100    /// Guest Linux, generally a full-featured guest OS with complicated device emulation requirements.
101    VMTLinux  = 2,
102}
103
104impl From<usize> for VMType {
105    fn from(value: usize) -> Self {
106        match value {
107            0 => Self::VMTHostVM,
108            1 => Self::VMTRTOS,
109            2 => Self::VMTLinux,
110            _ => Self::default(),
111        }
112    }
113}
114
115impl From<VMType> for usize {
116    fn from(value: VMType) -> Self {
117        value as usize
118    }
119}
120
121/// The type of memory mapping used for VM memory regions.
122#[derive(Debug, Default, Clone, PartialEq, Eq)]
123#[repr(u8)]
124pub enum VmMemMappingType {
125    /// The memory region is allocated by the VM monitor.
126    #[default]
127    MapAlloc     = 0,
128    /// The memory region is identical to the host physical memory region.
129    MapIdentical = 1,
130    /// The memory region is reserved memory for the guest OS.
131    MapReserved  = 2,
132}
133
134/// Configuration for a virtual machine memory region.
135#[derive(Debug, Default, Clone)]
136pub struct VmMemConfig {
137    /// The start address of the memory region in GPA (Guest Physical Address).
138    pub gpa: usize,
139    /// The size of the memory region in bytes.
140    pub size: usize,
141    /// The mappings flags of the memory region.
142    pub flags: usize,
143    /// The type of memory mapping.
144    pub map_type: VmMemMappingType,
145}
146
147/// A part of `AxVMConfig`, which represents the configuration of an emulated device for a virtual machine.
148#[derive(Debug, Default, Clone)]
149pub struct EmulatedDeviceConfig {
150    /// The name of the device.
151    pub name: String,
152    /// The base GPA (Guest Physical Address) of the device.
153    pub base_gpa: usize,
154    /// The address length of the device.
155    pub length: usize,
156    /// The IRQ (Interrupt Request) ID of the device.
157    pub irq_id: usize,
158    /// The type of emulated device.
159    pub emu_type: EmulatedDeviceType,
160    /// The config list of the device.
161    pub cfg_list: Vec<usize>,
162}
163
164/// A part of `AxVMConfig`, which represents the configuration of a pass-through device for a virtual machine.
165#[derive(Debug, Default, Clone, PartialEq)]
166pub struct PassThroughDeviceConfig {
167    /// The name of the device.
168    pub name: String,
169    /// The base GPA (Guest Physical Address) of the device.
170    pub base_gpa: usize,
171    /// The base HPA (Host Physical Address) of the device.
172    pub base_hpa: usize,
173    /// The address length of the device.
174    pub length: usize,
175    /// The IRQ (Interrupt Request) ID of the device.
176    pub irq_id: usize,
177}
178
179/// A part of `AxVMConfig`, which represents the configuration of a pass-through address for a virtual machine.
180#[derive(Debug, Default, Clone, PartialEq)]
181pub struct PassThroughAddressConfig {
182    /// The base GPA (Guest Physical Address).
183    pub base_gpa: usize,
184    /// The address length.
185    pub length: usize,
186}
187
188/// Describes how a guest VM should enter its boot image.
189#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
190pub enum VMBootProtocol {
191    /// Enter the configured kernel entry directly without a firmware image.
192    #[default]
193    Direct,
194    /// Use the legacy x86 axvm-bios/multiboot trampoline.
195    Multiboot,
196    /// Load an external UEFI firmware image and enter it without multiboot patching.
197    Uefi,
198}
199
200/// Specifies how the VM should handle interrupts and interrupt controllers.
201#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
202pub enum VMInterruptMode {
203    /// The VM will not handle interrupts, and the guest OS should not use interrupts.
204    #[default]
205    NoIrq,
206    /// The VM will use the emulated interrupt controller to handle interrupts.
207    Emulated,
208    /// The VM will use the passthrough interrupt controller (including GPPT) to handle interrupts.
209    Passthrough,
210}
211
212/// The type of emulated device.
213///
214/// Allocation scheme:
215/// - 0x00 - 0x1F: Special devices, and abstract device types that does not specify a concrete
216///   interface or implementation. The device objects created from these types depend on the target
217///   architecture and the specific implementation of the hypervisor.
218/// - 0x20 - 0x7F: Concrete emulated device types.
219///   - 0x20 - 0x2F: Interrupt controller devices.
220///   - 0x30 - 0x3F: Reserved for future use.
221/// - 0x80 - 0xDF: Reserved for future use.
222/// - 0xE0 - 0xEF: Virtio devices.
223/// - 0xF0 - 0xFF: Reserved for future use.
224#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
225#[repr(u8)]
226pub enum EmulatedDeviceType {
227    // Special devices and abstract device types.
228    /// Dummy device type.
229    #[default]
230    Dummy               = 0x0,
231    /// Interrupt controller device, e.g. vGICv2 in aarch64, vLAPIC in x86.
232    InterruptController = 0x1,
233    /// Console (serial) device.
234    Console             = 0x2,
235    /// An emulated device that provides Inter-VM Communication (IVC) channel.
236    ///
237    /// This device is used for communication between different VMs,
238    /// the corresponding memory region of this device should be marked as `Reserved` in
239    /// device tree or ACPI table.
240    IVCChannel          = 0xA,
241
242    // Arch-specific interrupt controller devices.
243    // 0x20 - 0x22: GPPT (GIC Partial Passthrough) devices.
244    /// ARM GIC Partial Passthrough Redistributor device.
245    GPPTRedistributor   = 0x20,
246    /// ARM GIC Partial Passthrough Distributor device.
247    GPPTDistributor     = 0x21,
248    /// ARM GIC Partial Passthrough Interrupt Translation Service device.
249    GPPTITS             = 0x22,
250
251    // 0x23 - 0x24: x86 platform devices.
252    /// x86 virtual IO APIC device.
253    X86IoApic           = 0x23,
254    /// x86 virtual PIT/8254 timer device.
255    X86Pit              = 0x24,
256
257    // 0x30: PPPT (PLIC Partial Passthrough) devices.
258    /// RISC-V PLIC Partial Passthrough Global device.
259    PPPTGlobal          = 0x30,
260
261    // Virtio devices.
262    /// Virtio block device.
263    VirtioBlk           = 0xE1,
264    /// Virtio net device.
265    VirtioNet           = 0xE2,
266    /// Virtio console device.
267    VirtioConsole       = 0xE3,
268    // Following are some other emulated devices that are not currently used and removed from the enum temporarily.
269    // /// IOMMU device.
270    // IOMMU = 0x6,
271    // /// Interrupt ICC SRE device.
272    // ICCSRE = 0x7,
273    // /// Interrupt ICC SGIR device.
274    // SGIR = 0x8,
275    // /// Interrupt controller GICR device.
276    // GICR = 0x9,
277}
278
279impl Display for EmulatedDeviceType {
280    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
281        match self {
282            EmulatedDeviceType::Console => write!(f, "console"),
283            EmulatedDeviceType::InterruptController => write!(f, "interrupt controller"),
284            EmulatedDeviceType::GPPTRedistributor => {
285                write!(f, "gic partial passthrough redistributor")
286            }
287            EmulatedDeviceType::GPPTDistributor => write!(f, "gic partial passthrough distributor"),
288            EmulatedDeviceType::GPPTITS => write!(f, "gic partial passthrough its"),
289            EmulatedDeviceType::X86IoApic => write!(f, "x86 io apic"),
290            EmulatedDeviceType::X86Pit => write!(f, "x86 pit"),
291            EmulatedDeviceType::PPPTGlobal => write!(f, "plic partial passthrough global"),
292            // EmulatedDeviceType::IOMMU => write!(f, "iommu"),
293            // EmulatedDeviceType::ICCSRE => write!(f, "interrupt icc sre"),
294            // EmulatedDeviceType::SGIR => write!(f, "interrupt icc sgir"),
295            // EmulatedDeviceType::GICR => write!(f, "interrupt controller gicr"),
296            EmulatedDeviceType::IVCChannel => write!(f, "ivc channel"),
297            EmulatedDeviceType::Dummy => write!(f, "meta device"),
298            EmulatedDeviceType::VirtioBlk => write!(f, "virtio block"),
299            EmulatedDeviceType::VirtioNet => write!(f, "virtio net"),
300            EmulatedDeviceType::VirtioConsole => write!(f, "virtio console"),
301        }
302    }
303}
304
305impl EmulatedDeviceType {
306    /// All known emulated device types.
307    pub const ALL: [Self; 13] = [
308        EmulatedDeviceType::Dummy,
309        EmulatedDeviceType::InterruptController,
310        EmulatedDeviceType::Console,
311        EmulatedDeviceType::IVCChannel,
312        EmulatedDeviceType::GPPTRedistributor,
313        EmulatedDeviceType::GPPTDistributor,
314        EmulatedDeviceType::GPPTITS,
315        EmulatedDeviceType::X86IoApic,
316        EmulatedDeviceType::X86Pit,
317        EmulatedDeviceType::PPPTGlobal,
318        EmulatedDeviceType::VirtioBlk,
319        EmulatedDeviceType::VirtioNet,
320        EmulatedDeviceType::VirtioConsole,
321    ];
322
323    /// Returns all known emulated device types.
324    pub const fn all() -> &'static [Self] {
325        &Self::ALL
326    }
327
328    /// Returns true if the device is removable.
329    pub fn removable(&self) -> bool {
330        matches!(
331            *self,
332            EmulatedDeviceType::InterruptController
333                // | EmulatedDeviceType::SGIR
334                // | EmulatedDeviceType::ICCSRE
335                | EmulatedDeviceType::GPPTRedistributor
336                | EmulatedDeviceType::X86IoApic
337                | EmulatedDeviceType::X86Pit
338                | EmulatedDeviceType::VirtioBlk
339                | EmulatedDeviceType::VirtioNet
340                // | EmulatedDeviceType::GICR
341                | EmulatedDeviceType::VirtioConsole
342        )
343    }
344
345    /// Converts a `usize` value to an `EmulatedDeviceType`.
346    pub const fn from_usize(value: usize) -> Option<Self> {
347        match value {
348            0x0 => Some(EmulatedDeviceType::Dummy),
349            0x1 => Some(EmulatedDeviceType::InterruptController),
350            0x2 => Some(EmulatedDeviceType::Console),
351            0xA => Some(EmulatedDeviceType::IVCChannel),
352            0x20 => Some(EmulatedDeviceType::GPPTRedistributor),
353            0x21 => Some(EmulatedDeviceType::GPPTDistributor),
354            0x22 => Some(EmulatedDeviceType::GPPTITS),
355            0x23 => Some(EmulatedDeviceType::X86IoApic),
356            0x24 => Some(EmulatedDeviceType::X86Pit),
357            0x30 => Some(EmulatedDeviceType::PPPTGlobal),
358            0xE1 => Some(EmulatedDeviceType::VirtioBlk),
359            0xE2 => Some(EmulatedDeviceType::VirtioNet),
360            0xE3 => Some(EmulatedDeviceType::VirtioConsole),
361            // 0x6 => EmulatedDeviceType::IOMMU,
362            // 0x7 => EmulatedDeviceType::ICCSRE,
363            // 0x8 => EmulatedDeviceType::SGIR,
364            // 0x9 => EmulatedDeviceType::GICR,
365            _ => None,
366        }
367    }
368}
369
370#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
371impl ax_page_table_multiarch::riscv::SvVirtAddr for GuestPhysAddr {
372    /// Flushes the TLB for the entire address space.
373    ///
374    /// `hfence.vvma` does not access host memory.
375    fn flush_tlb(_vaddr: Option<Self>) {
376        unsafe {
377            core::arch::asm!("hfence.vvma", options(nostack, nomem, preserves_flags));
378        }
379    }
380}