Skip to main content

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);