Skip to main content

rvm_types/
ids.rs

1//! Identifier types for partitions, vCPUs, and other RVM entities.
2//!
3//! Strongly-typed newtypes prevent accidental mixing of identifiers
4//! across different kernel object domains. All identifiers are `Copy +
5//! Clone + Eq + Hash` compatible.
6
7/// Unique identifier for a coherence partition.
8///
9/// Partitions are the primary isolation boundary in RVM. Each partition
10/// runs one or more vCPUs and has its own memory map, capability space,
11/// and coherence score.
12///
13/// The lower 8 bits serve as the hardware VMID for stage-2 TLB tagging
14/// on `AArch64` (ADR-133, Section 3). VMID 0 is reserved for the hypervisor.
15#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
16#[repr(transparent)]
17pub struct PartitionId(u32);
18
19impl PartitionId {
20    /// The hypervisor's own partition identifier (not schedulable).
21    pub const HYPERVISOR: Self = Self(0);
22
23    /// Maximum logical partition count (DC-12).
24    ///
25    /// Hardware VMID space is bounded (e.g., 256 on ARM). Agent workloads
26    /// can exceed this, so logical partitions are multiplexed over physical
27    /// VMID slots.
28    pub const MAX_LOGICAL: u32 = 4096;
29
30    /// Create a new partition identifier.
31    ///
32    /// # Note
33    ///
34    /// This constructor is unchecked -- callers that accept untrusted input
35    /// should use [`try_new`](Self::try_new) instead to reject reserved and
36    /// out-of-range identifiers.
37    #[must_use]
38    pub const fn new(id: u32) -> Self {
39        Self(id)
40    }
41
42    /// Create a validated partition identifier, returning `None` for
43    /// reserved or out-of-range values.
44    ///
45    /// - Rejects `0` (reserved for the hypervisor -- use [`PartitionId::HYPERVISOR`]).
46    /// - Rejects values greater than [`MAX_LOGICAL`](Self::MAX_LOGICAL).
47    #[must_use]
48    pub const fn try_new(id: u32) -> Option<Self> {
49        if id == 0 || id > Self::MAX_LOGICAL {
50            None
51        } else {
52            Some(Self(id))
53        }
54    }
55
56    /// Return the hypervisor's reserved partition identifier.
57    #[must_use]
58    pub const fn hypervisor() -> Self {
59        Self::HYPERVISOR
60    }
61
62    /// Return the raw identifier value.
63    #[must_use]
64    pub const fn as_u32(self) -> u32 {
65        self.0
66    }
67
68    /// Extract the hardware VMID (lower 8 bits) for stage-2 TLB tagging.
69    ///
70    /// On `AArch64`, `VTTBR_EL2` encodes the VMID in bits \[55:48\]. Only 8 bits
71    /// are used for 256 physical VMID slots; logical partitions exceeding
72    /// this are multiplexed per DC-12.
73    #[must_use]
74    pub const fn vmid(self) -> u16 {
75        (self.0 & 0xFF) as u16
76    }
77
78    /// Whether this is the hypervisor's own partition.
79    #[must_use]
80    pub const fn is_hypervisor(self) -> bool {
81        self.0 == 0
82    }
83}
84
85/// Virtual CPU identifier within a partition.
86///
87/// A vCPU represents a schedulable execution context. Each vCPU belongs
88/// to exactly one partition and carries its own register state and
89/// witness trail.
90#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
91pub struct VcpuId {
92    /// The partition this vCPU belongs to.
93    partition: PartitionId,
94    /// The local index of the vCPU within the partition.
95    index: u16,
96}
97
98impl VcpuId {
99    /// Create a new vCPU identifier.
100    #[must_use]
101    pub const fn new(partition: PartitionId, index: u16) -> Self {
102        Self { partition, index }
103    }
104
105    /// Return the owning partition.
106    #[must_use]
107    pub const fn partition(self) -> PartitionId {
108        self.partition
109    }
110
111    /// Return the local vCPU index.
112    #[must_use]
113    pub const fn index(self) -> u16 {
114        self.index
115    }
116}