#![no_std]
extern crate alloc;
use alloc::{string::String, vec::Vec};
use core::fmt::{Display, Formatter};
use ax_memory_addr::{AddrRange, PhysAddr, VirtAddr, def_usize_addr, def_usize_addr_formatter};
pub type VMId = usize;
pub type VCpuId = usize;
pub type InterruptVector = u8;
pub const MAX_VCPU_NUM: usize = 64;
pub type VCpuSet = ax_cpumask::CpuMask<MAX_VCPU_NUM>;
pub type HostVirtAddr = VirtAddr;
pub type HostPhysAddr = PhysAddr;
def_usize_addr! {
pub type GuestVirtAddr;
pub type GuestPhysAddr;
}
def_usize_addr_formatter! {
GuestVirtAddr = "GVA:{}";
GuestPhysAddr = "GPA:{}";
}
pub type GuestVirtAddrRange = AddrRange<GuestVirtAddr>;
pub type GuestPhysAddrRange = AddrRange<GuestPhysAddr>;
pub type AxVmResult<T = ()> = ax_errno::AxResult<T>;
pub type AxVmError = ax_errno::AxError;
#[derive(Default, Clone, Copy, PartialEq, Eq, Debug)]
pub enum VMType {
VMTHostVM = 0,
#[default]
VMTRTOS = 1,
VMTLinux = 2,
}
impl From<usize> for VMType {
fn from(value: usize) -> Self {
match value {
0 => Self::VMTHostVM,
1 => Self::VMTRTOS,
2 => Self::VMTLinux,
_ => Self::default(),
}
}
}
impl From<VMType> for usize {
fn from(value: VMType) -> Self {
value as usize
}
}
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum VmMemMappingType {
#[default]
MapAlloc = 0,
MapIdentical = 1,
MapReserved = 2,
}
#[derive(Debug, Default, Clone)]
pub struct VmMemConfig {
pub gpa: usize,
pub size: usize,
pub flags: usize,
pub map_type: VmMemMappingType,
}
#[derive(Debug, Default, Clone)]
pub struct EmulatedDeviceConfig {
pub name: String,
pub base_gpa: usize,
pub length: usize,
pub irq_id: usize,
pub emu_type: EmulatedDeviceType,
pub cfg_list: Vec<usize>,
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct PassThroughDeviceConfig {
pub name: String,
pub base_gpa: usize,
pub base_hpa: usize,
pub length: usize,
pub irq_id: usize,
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct PassThroughAddressConfig {
pub base_gpa: usize,
pub length: usize,
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum VMBootProtocol {
#[default]
Direct,
Multiboot,
Uefi,
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum VMInterruptMode {
#[default]
NoIrq,
Emulated,
Passthrough,
}
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum EmulatedDeviceType {
#[default]
Dummy = 0x0,
InterruptController = 0x1,
Console = 0x2,
IVCChannel = 0xA,
GPPTRedistributor = 0x20,
GPPTDistributor = 0x21,
GPPTITS = 0x22,
X86IoApic = 0x23,
X86Pit = 0x24,
PPPTGlobal = 0x30,
VirtioBlk = 0xE1,
VirtioNet = 0xE2,
VirtioConsole = 0xE3,
}
impl Display for EmulatedDeviceType {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
EmulatedDeviceType::Console => write!(f, "console"),
EmulatedDeviceType::InterruptController => write!(f, "interrupt controller"),
EmulatedDeviceType::GPPTRedistributor => {
write!(f, "gic partial passthrough redistributor")
}
EmulatedDeviceType::GPPTDistributor => write!(f, "gic partial passthrough distributor"),
EmulatedDeviceType::GPPTITS => write!(f, "gic partial passthrough its"),
EmulatedDeviceType::X86IoApic => write!(f, "x86 io apic"),
EmulatedDeviceType::X86Pit => write!(f, "x86 pit"),
EmulatedDeviceType::PPPTGlobal => write!(f, "plic partial passthrough global"),
EmulatedDeviceType::IVCChannel => write!(f, "ivc channel"),
EmulatedDeviceType::Dummy => write!(f, "meta device"),
EmulatedDeviceType::VirtioBlk => write!(f, "virtio block"),
EmulatedDeviceType::VirtioNet => write!(f, "virtio net"),
EmulatedDeviceType::VirtioConsole => write!(f, "virtio console"),
}
}
}
impl EmulatedDeviceType {
pub const ALL: [Self; 13] = [
EmulatedDeviceType::Dummy,
EmulatedDeviceType::InterruptController,
EmulatedDeviceType::Console,
EmulatedDeviceType::IVCChannel,
EmulatedDeviceType::GPPTRedistributor,
EmulatedDeviceType::GPPTDistributor,
EmulatedDeviceType::GPPTITS,
EmulatedDeviceType::X86IoApic,
EmulatedDeviceType::X86Pit,
EmulatedDeviceType::PPPTGlobal,
EmulatedDeviceType::VirtioBlk,
EmulatedDeviceType::VirtioNet,
EmulatedDeviceType::VirtioConsole,
];
pub const fn all() -> &'static [Self] {
&Self::ALL
}
pub fn removable(&self) -> bool {
matches!(
*self,
EmulatedDeviceType::InterruptController
| EmulatedDeviceType::GPPTRedistributor
| EmulatedDeviceType::X86IoApic
| EmulatedDeviceType::X86Pit
| EmulatedDeviceType::VirtioBlk
| EmulatedDeviceType::VirtioNet
| EmulatedDeviceType::VirtioConsole
)
}
pub const fn from_usize(value: usize) -> Option<Self> {
match value {
0x0 => Some(EmulatedDeviceType::Dummy),
0x1 => Some(EmulatedDeviceType::InterruptController),
0x2 => Some(EmulatedDeviceType::Console),
0xA => Some(EmulatedDeviceType::IVCChannel),
0x20 => Some(EmulatedDeviceType::GPPTRedistributor),
0x21 => Some(EmulatedDeviceType::GPPTDistributor),
0x22 => Some(EmulatedDeviceType::GPPTITS),
0x23 => Some(EmulatedDeviceType::X86IoApic),
0x24 => Some(EmulatedDeviceType::X86Pit),
0x30 => Some(EmulatedDeviceType::PPPTGlobal),
0xE1 => Some(EmulatedDeviceType::VirtioBlk),
0xE2 => Some(EmulatedDeviceType::VirtioNet),
0xE3 => Some(EmulatedDeviceType::VirtioConsole),
_ => None,
}
}
}
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
impl ax_page_table_multiarch::riscv::SvVirtAddr for GuestPhysAddr {
fn flush_tlb(_vaddr: Option<Self>) {
unsafe {
core::arch::asm!("hfence.vvma", options(nostack, nomem, preserves_flags));
}
}
}