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}