pvh 0.1.0

Xen's x86/HVM direct boot ABI (PVH).
Documentation
use num_enum::{FromPrimitive, IntoPrimitive};

use super::Sif;

/// Xen HVM start magic value.
///
/// This is contained in [`StartInfo::magic`].
///
/// This corresponds to `start_info.h`'s `XEN_HVM_START_MAGIC_VALUE`.
#[doc(alias = "XEN_HVM_START_MAGIC_VALUE")]
pub const START_MAGIC_VALUE: u32 = 0x336e_c578;

/// A memory map type.
///
/// The values used in the type field of the memory map table entries are
/// defined below and match the Address Range Types as defined in the "System
/// Address Map Interfaces" section of the ACPI Specification.
///
/// For details, see [15. System Address Map Interfaces — ACPI Specification 6.6
/// documentation].
///
/// This corresponds to `start_info.h`'s `XEN_HVM_MEMMAP_TYPE_*`.
///
/// [15. System Address Map Interfaces — ACPI Specification 6.6 documentation]: https://uefi.org/specs/ACPI/6.6/15_System_Address_Map_Interfaces.html
#[doc(alias = "XEN_HVM_MEMMAP_TYPE")]
#[derive(IntoPrimitive, FromPrimitive, Hash, PartialEq, Eq, Clone, Copy, Debug)]
#[non_exhaustive]
#[repr(u32)]
pub enum MemmapType {
    /// This range is available RAM usable by the operating system.
    #[doc(alias = "XEN_HVM_MEMMAP_TYPE_RAM")]
    Ram = 1,

    /// This range of addresses is in use or reserved by the system and is not
    /// to be included in the allocatable memory pool of the operating system’s
    /// memory manager.
    #[doc(alias = "XEN_HVM_MEMMAP_TYPE_RESERVED")]
    Reserved = 2,

    /// ACPI Reclaim Memory. This range is available RAM usable by the OS after
    /// it reads the ACPI tables.
    #[doc(alias = "XEN_HVM_MEMMAP_TYPE_ACPI")]
    Acpi = 3,

    /// ACPI NVS Memory. This range of addresses is in use or reserved by the
    /// system and must not be used by the operating system. This range is
    /// required to be saved and restored across an NVS sleep.
    #[doc(alias = "XEN_HVM_MEMMAP_TYPE_NVS")]
    Nvs = 4,

    /// This range of addresses contains memory in which errors have been
    /// detected. This range must not be used by OSPM.
    #[doc(alias = "XEN_HVM_MEMMAP_TYPE_UNUSABLE")]
    Unusable = 5,

    /// This range of addresses contains memory that is not enabled. This range
    /// must not be used by OSPM.
    #[doc(alias = "XEN_HVM_MEMMAP_TYPE_DISABLED")]
    Disabled = 6,

    /// OSPM must comprehend this memory as having non-volatile attributes and
    /// handle distinct from conventional volatile memory. The memory region
    /// supports byte-addressable non-volatility.
    #[doc(alias = "XEN_HVM_MEMMAP_TYPE_PMEM")]
    Pmem = 7,

    /// Unknown memory map type.
    #[num_enum(catch_all)]
    Unknown(u32),
}

/// Start of day structure passed to PVH guests and to HVM guests in `ebx`.
///
/// NOTE: nothing will be loaded at physical address 0, so a 0 value in any
/// of the address fields should be treated as not present.
///
/// ```text
///  0 +----------------+
///    | magic          | Contains the magic value XEN_HVM_START_MAGIC_VALUE
///    |                | ("xEn3" with the 0x80 bit of the "E" set).
///  4 +----------------+
///    | version        | Version of this structure. Current version is 1. New
///    |                | versions are guaranteed to be backwards-compatible.
///  8 +----------------+
///    | flags          | SIF_xxx flags.
/// 12 +----------------+
///    | nr_modules     | Number of modules passed to the kernel.
/// 16 +----------------+
///    | modlist_paddr  | Physical address of an array of modules
///    |                | (layout of the structure below).
/// 24 +----------------+
///    | cmdline_paddr  | Physical address of the command line,
///    |                | a zero-terminated ASCII string.
/// 32 +----------------+
///    | rsdp_paddr     | Physical address of the RSDP ACPI data structure.
/// 40 +----------------+
///    | memmap_paddr   | Physical address of the (optional) memory map. Only
///    |                | present in version 1 and newer of the structure.
/// 48 +----------------+
///    | memmap_entries | Number of entries in the memory map table. Zero
///    |                | if there is no memory map being provided. Only
///    |                | present in version 1 and newer of the structure.
/// 52 +----------------+
///    | reserved       | Version 1 and newer only.
/// 56 +----------------+
/// ```
///
/// The address and sizes are always a 64bit little endian unsigned integer.
///
/// NB: Xen on x86 will always try to place all the data below the 4GiB
/// boundary.
///
/// Version numbers of the `hvm_start_info` structure have evolved like this:
///
/// Version 0:  Initial implementation.
///
/// Version 1:  Added the `memmap_paddr`/`memmap_entries` fields (plus 4 bytes
///             of padding) to the end of the `hvm_start_info` struct. These new
///             fields can be used to pass a memory map to the guest. The
///             memory map is optional and so guests that understand version 1
///             of the structure must check that `memmap_entries` is non-zero
///             before trying to read the memory map.
///
/// This corresponds to `start_info.h`'s `hvm_start_info`.
#[doc(alias = "hvm_start_info")]
#[derive(Default, Hash, PartialEq, Eq, Clone, Copy, Debug)]
#[repr(C)]
pub struct StartInfo {
    /// Contains the magic value 0x336ec578 ("xEn3" with the 0x80 bit of the "E"
    /// set).
    ///
    /// See [`START_MAGIC_VALUE`] for a definition of the magic value.
    pub magic: u32,

    /// Version of this structure.
    pub version: u32,

    /// `SIF_xxx` flags.
    pub flags: Sif,

    /// Number of modules passed to the kernel.
    pub nr_modules: u32,

    /// Physical address of an array of `hvm_modlist_entry`.
    pub modlist_paddr: u64,

    /// Physical address of the command line.
    pub cmdline_paddr: u64,

    /// Physical address of the RSDP ACPI data structure.
    pub rsdp_paddr: u64,

    // All following fields only present in version 1 and newer
    /// Physical address of an array of `hvm_memmap_table_entry`.
    pub memmap_paddr: u64,

    /// Number of entries in the memmap table.
    ///
    /// Value will be zero if there is no memory map being provided.
    pub memmap_entries: u32,

    /// Must be zero.
    pub reserved: u32,
}

/// A module list entry.
///
/// The layout of each entry in the module structure is the following:
///
/// ```text
///  0 +----------------+
///    | paddr          | Physical address of the module.
///  8 +----------------+
///    | size           | Size of the module in bytes.
/// 16 +----------------+
///    | cmdline_paddr  | Physical address of the command line,
///    |                | a zero-terminated ASCII string.
/// 24 +----------------+
///    | reserved       |
/// 32 +----------------+
/// ```
///
/// This corresponds to `start_info.h`'s `hvm_modlist_entry`.
#[doc(alias = "hvm_modlist_entry")]
#[derive(Default, Hash, PartialEq, Eq, Clone, Copy, Debug)]
#[repr(C)]
pub struct ModlistEntry {
    /// Physical address of the module.
    pub paddr: u64,

    /// Size of the module in bytes.
    pub size: u64,

    /// Physical address of the command line.
    pub cmdline_paddr: u64,

    /// Must be zero.
    pub reserved: u64,
}

/// A memory map table entry.
///
/// The layout of each entry in the memory map table is as follows:
///
/// ```text
///  0 +----------------+
///    | addr           | Base address
///  8 +----------------+
///    | size           | Size of mapping in bytes
/// 16 +----------------+
///    | type           | Type of mapping as defined between the hypervisor
///    |                | and guest. See XEN_HVM_MEMMAP_TYPE_* values below.
/// 20 +----------------|
///    | reserved       |
/// 24 +----------------+
/// ```
///
/// This corresponds to `start_info.h`'s `hvm_memmap_table_entry`.
#[doc(alias = "hvm_memmap_table_entry")]
#[derive(Default, Hash, PartialEq, Eq, Clone, Copy, Debug)]
#[repr(C)]
pub struct MemmapTableEntry {
    /// Base address of the memory region
    pub addr: u64,

    /// Size of the memory region in bytes
    pub size: u64,

    /// Mapping type
    #[doc(alias = "type")]
    pub ty: u32,

    /// Must be zero for Version 1.
    pub reserved: u32,
}