sev_guest_device_tio/lib.rs
1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4#![forbid(unsafe_code)]
5
6//! The module includes the definitions of data structures according to the SEV-TIO Firmware Interface Specification.
7//! <https://docs.amd.com/v/u/en-US/58271_0.91> AMD Document #58271 2025-07-02
8
9use bitfield_struct::bitfield;
10use zerocopy::FromBytes;
11use zerocopy::Immutable;
12use zerocopy::IntoBytes;
13use zerocopy::KnownLayout;
14
15/// See `TIO_MSG_TDI_INFO_REQ` in Table 60, "SEV-TIO Firmware Interface Specification", Revision 0.91.
16#[repr(C)]
17#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Debug)]
18pub struct TioMsgTdiInfoReq {
19 /// Hypervisor supplied guest id.
20 pub guest_device_id: u16,
21 /// Reserved
22 pub _reserved0: [u8; 14],
23}
24
25static_assertions::const_assert_eq!(16, size_of::<TioMsgTdiInfoReq>());
26
27/// See `TIO_MSG_TDI_INFO_RSP` in Table 61, "SEV-TIO Firmware Interface Specification", Revision 0.91.
28#[repr(C)]
29#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Debug)]
30pub struct TioMsgTdiInfoRsp {
31 /// Hypervisor supplied guest id.
32 pub guest_device_id: u16,
33 /// TDI status.
34 pub tdi_status: u16,
35 /// Reserved
36 pub _reserved0: [u8; 12],
37 /// MEAS_DIGEST info
38 pub meas_digest_info: u32,
39 /// Device lock flags
40 pub lock_flags: u32,
41 /// SPDM algorithms
42 pub spdm_algos: u64,
43 /// Certs digest
44 pub certs_digest: [u8; 48],
45 /// MEAS digest
46 pub meas_digest: [u8; 48],
47 /// Interface report digest
48 pub interface_report_digest: [u8; 48],
49 /// Tdi report count
50 pub tdi_report_count: u64,
51 /// Reserved
52 pub _reserved1: u64,
53}
54
55/// Encoding of the `tdi_status` field of [`TioMsgTdiInfoRsp`]. See "SEV-TIO
56/// Firmware Interface Specification", Revision 0.91, Table 61.
57///
58/// Despite the name, this is NOT the TDISP TDI state enumeration. It is a
59/// SEV-TIO firmware status code describing the outcome of the `TDI_INFO` lookup
60/// for the given guest device id.
61#[repr(u16)]
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub enum TioMsgTdiStatus {
64 /// The TDI is bound to the guest and currently in the RUN state.
65 Success = 0,
66 /// The firmware considers the request invalid (for example, an unknown
67 /// guest device id or a mismatch against the firmware's bookkeeping).
68 Invalid = 1,
69 /// The TDI exists but is currently unbound (i.e. in the CONFIG_UNLOCKED
70 /// state from the TDISP perspective).
71 Unbound = 2,
72}
73
74impl TioMsgTdiStatus {
75 /// Convert a raw `tdi_status` value from a firmware response into
76 /// [`TioMsgTdiStatus`]. Returns `None` if the value is not a known
77 /// encoding.
78 pub fn from_u16(value: u16) -> Option<Self> {
79 match value {
80 0 => Some(Self::Success),
81 1 => Some(Self::Invalid),
82 2 => Some(Self::Unbound),
83 _ => None,
84 }
85 }
86}
87
88// Assert the size of the response field
89static_assertions::const_assert_eq!(192, size_of::<TioMsgTdiInfoRsp>());
90
91/// See `TIO_MSG_MMIO_VALIDATE_REQ` in Table 63, "SEV-TIO Firmware Interface Specification", Revision 0.91.
92#[bitfield(u16)]
93#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
94pub struct TioMsgMmioValidateReqFlags {
95 /// Desired value to set RMP. Validated for the range.
96 pub validated: bool,
97
98 /// 0: If subrange does not have RMP. Validated
99 /// set uniformly, fail.
100 /// 1: If subrange does not have RMP. Validated
101 /// set uniformly, force to requested value.
102 pub force_validated: bool,
103
104 #[bits(14)]
105 _reserved0: u16,
106}
107
108/// See `TIO_MSG_MMIO_VALIDATE_REQ` in Table 63, "SEV-TIO Firmware Interface Specification", Revision 0.91.
109#[repr(C)]
110#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Debug)]
111pub struct TioMsgMmioValidateReq {
112 /// Hypervisor provided identifier used by the guest to identify the TDI in guest messages.
113 pub guest_device_id: u16,
114 /// Reserved.
115 pub _reserved0: [u8; 14],
116 /// Guest physical address of the subrange.
117 pub subrange_base: u64,
118 /// Number of 4 KB pages in the subrange.
119 pub subrange_page_count: u32,
120 /// Offset of the subrange within the MMIO range.
121 pub range_offset: u32,
122 /// Validated flags
123 pub validated_flags: TioMsgMmioValidateReqFlags,
124 /// RangeID of MMIO range.
125 pub range_id: u16,
126 /// Reserved.
127 pub _reserved2: [u8; 12],
128}
129
130static_assertions::const_assert_eq!(48, size_of::<TioMsgMmioValidateReq>());
131
132/// See `TIO_MSG_MMIO_VALIDATE_RSP` in Table 64, "SEV-TIO Firmware Interface Specification", Revision 0.91.
133#[bitfield(u16)]
134#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
135pub struct TioMsgMmioValidateResFlags {
136 /// Indicates that the Validated bit has changed due to this operation.
137 pub changed: bool,
138
139 #[bits(15)]
140 _reserved0: u16,
141}
142
143/// See `TIO_MSG_MMIO_VALIDATE_RSP` in Table 64, "SEV-TIO Firmware Interface Specification", Revision 0.91.
144#[repr(C)]
145#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Debug)]
146pub struct TioMsgMmioValidateRsp {
147 /// Hypervisor provided PCIe Routing ID used by the guest to identify the TDI.
148 pub guest_device_id: u16,
149 /// Status of the operation.
150 pub status: u16,
151 /// Reserved.
152 pub _reserved0: [u8; 12],
153 /// Guest physical address of the subrange.
154 pub subrange_base: u64,
155 /// Number of 4 KB pages in the subrange.
156 pub subrange_page_count: u32,
157 /// Offset of the subrange within the MMIO range.
158 pub range_offset: u32,
159 /// Validated flags
160 pub flag_bits: TioMsgMmioValidateResFlags,
161 /// Range of the MMIO.
162 pub range_id: u16,
163 /// Reserved.
164 pub _reserved2: [u8; 12],
165}
166
167static_assertions::const_assert_eq!(48, size_of::<TioMsgMmioValidateRsp>());
168
169/// See `TIO_MSG_MMIO_CONFIG_REQ` flags in Table 65, "SEV-TIO Firmware Interface Specification", Revision 0.91.
170#[bitfield(u16)]
171#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
172pub struct TioMsgMmioConfigReqFlags {
173 #[bits(2)]
174 _reserved0: u16,
175
176 /// 0: Can be mapped only into guest private memory.
177 /// 1: Can be mapped into either guest private memory or shared memory.
178 /// Ignored if WRITE is 0.
179 pub non_tee_mem: bool,
180
181 #[bits(13)]
182 _reserved1: u16,
183}
184
185/// See `TIO_MSG_MMIO_CONFIG_REQ` in Table 65, "SEV-TIO Firmware Interface Specification", Revision 0.91.
186#[repr(C)]
187#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Debug)]
188pub struct TioMsgMmioConfigReq {
189 /// Hypervisor provided identifier used by the guest to identify the TDI in guest messages.
190 pub guest_device_id: u16,
191 /// Reserved.
192 pub _reserved0: [u8; 2],
193 /// Flags for the range.
194 pub flags: TioMsgMmioConfigReqFlags,
195 /// Range ID of the MMIO range.
196 pub range_id: u16,
197 /// WRITE flag.
198 pub write: u32,
199 /// Reserved.
200 pub _reserved2: [u8; 4],
201}
202
203static_assertions::const_assert_eq!(16, size_of::<TioMsgMmioConfigReq>());
204
205/// See `TIO_MSG_MMIO_CONFIG_RSP` flags in Table 66, "SEV-TIO Firmware Interface Specification", Revision 0.91.
206#[bitfield(u16)]
207#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
208pub struct TioMsgMmioConfigRspFlags {
209 /// Indicates if the range maps MSI-X table.
210 pub msix_table: bool,
211 /// Indicates if this range maps MSI-X PBA.
212 pub msix_pba: bool,
213 /// Indicates if the range can be mapped into either guest private memory or shared memory.
214 pub non_tee_mem: bool,
215 /// Indicates if certain TDISP flags can be updated.
216 pub mem_attr_updateable: bool,
217 #[bits(12)]
218 _reserved0: u16,
219}
220
221/// See `TIO_MSG_MMIO_CONFIG_RSP` in Table 66, "SEV-TIO Firmware Interface Specification", Revision 0.91.
222#[repr(C)]
223#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Debug)]
224pub struct TioMsgMmioConfigRsp {
225 /// Hypervisor provided identifier used by the guest to identify the TDI in guest messages.
226 pub guest_device_id: u16,
227 /// Status of the operation.
228 pub status: u16,
229 /// Flags for the range.
230 pub flags: TioMsgMmioConfigRspFlags,
231 /// Range ID of the MMIO range.
232 pub range_id: u16,
233 /// WRITE flag.
234 pub write: u32,
235 /// Reserved.
236 pub _reserved1: [u8; 4],
237}
238
239static_assertions::const_assert_eq!(16, size_of::<TioMsgMmioConfigRsp>());
240
241/// See `Layout of the SDTE Structure` in Table 68, "SEV-TIO Firmware Interface Specification", Revision 0.91.
242#[bitfield(u64)]
243#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
244pub struct SdtePart1 {
245 // [0]
246 pub v: bool,
247
248 #[bits(60)]
249 _reserved0: u64,
250
251 pub ir: bool,
252
253 pub iw: bool,
254
255 _reserved1: bool,
256}
257
258/// See `Layout of the SDTE Structure` in Table 68, "SEV-TIO Firmware Interface Specification", Revision 0.91.
259#[bitfield(u64)]
260#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
261pub struct SdtePart2 {
262 #[bits(49)]
263 _reserved0: u64,
264
265 #[bits(2)]
266 pub vmpl: u64,
267
268 #[bits(13)]
269 _reserved1: u64,
270}
271
272/// See `Layout of the SDTE Structure` in Table 68, "SEV-TIO Firmware Interface Specification", Revision 0.91.
273#[bitfield(u64)]
274#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
275pub struct SdtePart3 {
276 pub vtom_en: bool,
277
278 #[bits(31)]
279 pub virtual_tom: u32,
280
281 #[bits(32)]
282 _reserved1: u64,
283}
284
285/// See `Layout of the SDTE Structure` in Table 68, "SEV-TIO Firmware Interface Specification", Revision 0.91.
286#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Debug)]
287#[repr(C)]
288pub struct Sdte {
289 /// Part 1 of the guest writable portion of the SDTE structure. These are split out to preserve specific alignment requirements from the spec.
290 pub part1: SdtePart1,
291 /// Reserved. Set to 0.
292 pub _reserved0: u64,
293 /// Reserved. Set to 0.
294 pub _reserved1: u64,
295 /// Part 2 of the guest writable portion of the SDTE structure. These are split out to preserve specific alignment requirements from the spec.
296 pub part2: SdtePart2,
297 /// Reserved. Set to 0.
298 pub _reserved2: u64,
299
300 /// Part 3 of the guest writable portion of the SDTE structure. These are split out to preserve specific alignment requirements from the spec.
301 pub part3: SdtePart3,
302 /// Reserved. Set to 0.
303 pub _reserved3: u64,
304 /// Reserved. Set to 0.
305 pub _reserved4: u64,
306}
307
308static_assertions::const_assert_eq!(size_of::<Sdte>(), 64);
309
310/// See `TIO_MSG_SDTE_WRITE_REQ` in Table 67, "SEV-TIO Firmware Interface Specification", Revision 0.91.
311#[repr(C)]
312#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Debug)]
313pub struct TioMsgSdteWriteReq {
314 /// Hypervisor provided identifier used by the guest to identify the TDI in guest messages.
315 pub guest_device_id: u16,
316
317 /// Reserved. Set to 0.
318 pub _reserved0: [u8; 14],
319
320 /// sDTE to use to configure the guest controlled fields.
321 pub sdte: Sdte,
322}
323
324static_assertions::const_assert_eq!(size_of::<TioMsgSdteWriteReq>(), 80);
325
326/// See `TIO_MSG_SDTE_WRITE_RSP` in Table 69, "SEV-TIO Firmware Interface Specification", Revision 0.91.
327#[repr(C)]
328#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Debug)]
329pub struct TioMsgSdteWriteRsp {
330 /// Hypervisor provided PCIe Routing ID used by the guest to identify the TDI.
331 pub guest_device_id: u16,
332 /// Status of the operation.
333 pub status: u16,
334 /// Reserved.
335 pub _reserved0: [u8; 12],
336}
337
338static_assertions::const_assert_eq!(size_of::<TioMsgSdteWriteRsp>(), 16);