Coverage Report

Created: 2026-02-14 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/MigTD/deps/td-shim/tdx-tdcall/src/lib.rs
Line
Count
Source
1
// Copyright (c) 2020-2025 Intel Corporation
2
//
3
// SPDX-License-Identifier: BSD-2-Clause-Patent
4
5
//! Guest-Side (TDCALL) Interface Helper Functions
6
//!
7
//! This crate implements the helper functions for the TDCALL interface functions defined in
8
//! Intel TDX Module specifiction and the TDVMCALL sub-functions defined in Intel TDX
9
//! Guest-Hypervisor Communication Interface specification. It also provides the constants
10
//! and data structures that are defined in the specifications.
11
//!
12
//! Please refer to following links for detail:
13
//! [Intel TDX Module v1.0 Spec](https://www.intel.com/content/dam/develop/external/us/en/documents/tdx-module-1.0-public-spec-v0.931.pdf)
14
//! [Intel TDX Module v1.5 Spec](https://www.intel.com/content/dam/develop/external/us/en/documents/intel-tdx-module-1.5-abi-spec-348551001.pdf)
15
//! [Intel TDX Guest-Hypervisor Communication Interface Spec](https://cdrdv2.intel.com/v1/dl/getContent/726790)
16
//! [Intel TDX Guest-Hypervisor Communication Interface Spec v1.5](https://cdrdv2.intel.com/v1/dl/getContent/726792)
17
//!
18
//! A subset of TDCALL interface functions is defined in crate::tdx, and the TDG.MR.REPORT
19
//! leaf function and TDREPORT_STRUCT related definitions are defined in crate::tdreport
20
//! separately.
21
22
#![no_std]
23
24
use core::ffi::c_void;
25
26
#[cfg(feature = "use_tdx_emulation")]
27
pub const USE_TDX_EMULATION: bool = true;
28
#[cfg(not(feature = "use_tdx_emulation"))]
29
pub const USE_TDX_EMULATION: bool = false;
30
31
#[cfg(not(feature = "no-tdaccept"))]
32
pub const TDACCEPT_SUPPORT: bool = true;
33
#[cfg(feature = "no-tdaccept")]
34
pub const TDACCEPT_SUPPORT: bool = false;
35
36
pub mod asm;
37
pub mod tdreport;
38
pub mod tdx;
39
40
// Guest-Side (TDCALL) interface functions leaf numbers
41
const TDCALL_TDINFO: u64 = 1;
42
const TDCALL_TDEXTENDRTMR: u64 = 2;
43
const TDCALL_TDGETVEINFO: u64 = 3;
44
const TDCALL_TDREPORT: u64 = 4;
45
#[cfg(not(feature = "no-tdaccept"))]
46
const TDCALL_TDACCEPTPAGE: u64 = 6;
47
const TDCALL_VM_RD: u64 = 7;
48
const TDCALL_VM_WR: u64 = 8;
49
const TDCALL_VP_RD: u64 = 9;
50
const TDCALL_VP_WR: u64 = 10;
51
const TDCALL_SYS_RD: u64 = 11;
52
const TDCALL_SERVTD_RD: u64 = 18;
53
const TDCALL_SERVTD_WR: u64 = 20;
54
const TDCALL_VERIFYREPORT: u64 = 22;
55
const TDCALL_MEM_PAGE_ATTR_WR: u64 = 24;
56
const TDCALL_VP_ENTER: u64 = 25;
57
const TDCALL_VP_INVEPT: u64 = 26;
58
const TDCALL_VP_INVVPID: u64 = 27;
59
#[cfg(feature = "tdg_dbg")]
60
const TDCALL_TDG_DEBUG: u64 = 254;
61
62
// TDCALL completion status code
63
const TDCALL_STATUS_SUCCESS: u64 = 0;
64
65
// leaf-specific completion status code
66
pub const TDCALL_STATUS_PAGE_ALREADY_ACCEPTED: u64 = 0x00000B0A00000000;
67
pub const TDCALL_STATUS_PAGE_SIZE_MISMATCH: u64 = 0xC0000B0B00000001;
68
69
cfg_if::cfg_if! {
70
    if #[cfg(not(feature = "no-tdvmcall"))] {
71
        // GTDG.VP.VMCALL leaf sub-function numbers
72
        const TDVMCALL_CPUID: u64 = 0x0000a;
73
        const TDVMCALL_HALT: u64 = 0x0000c;
74
        const TDVMCALL_IO: u64 = 0x0001e;
75
        const TDVMCALL_RDMSR: u64 = 0x0001f;
76
        const TDVMCALL_WRMSR: u64 = 0x00020;
77
        const TDVMCALL_MMIO: u64 = 0x00030;
78
        const TDVMCALL_MAPGPA: u64 = 0x10001;
79
        const TDVMCALL_GETQUOTE: u64 = 0x10002;
80
        const TDVMCALL_SETUPEVENTNOTIFY: u64 = 0x10004;
81
        const TDVMCALL_SERVICE: u64 = 0x10005;
82
        const TDVMCALL_MIGTD: u64 = 0x10006;
83
84
        // TDVMCALL completion status code
85
        const TDVMCALL_STATUS_SUCCESS: u64 = 0;
86
        const TDVMCALL_STATUS_RETRY: u64 = 1;
87
88
        // TDVMCALL<MigTD> leaf function numbers
89
        const TDVMCALL_MIGTD_WAITFORREQUEST: u16 = 1;
90
        const TDVMCALL_MIGTD_REPORTSTATUS: u16 = 2;
91
        const TDVMCALL_MIGTD_SEND: u16= 3;
92
        const TDVMCALL_MIGTD_RECEIVE: u16 = 4;
93
    }
94
}
95
96
// A public wrapper for use of asm_td_vmcall, this function takes a mutable reference of a
97
// TdcallArgs structure to ensure the input is valid
98
//
99
// ## TDVMCALL ABI
100
// Defined in GHCI Spec section 'TDCALL [TDG.VP.VMCALL] leaf'
101
//
102
// ### Input Operands:
103
// * RAX - TDCALL instruction leaf number (0 - TDG.VP.VMCALL)
104
// * RCX - A bitmap that controls which part of guest TD GPR is exposed to VMM.
105
// * R10 - Set to 0 indicates leaf-function used in R11 is defined in standard GHCI Spec.
106
// * R11 - TDG.VP.VMCALL sub-function is R10 is zero
107
// * RBX, RBP, RDI, RSI, R8-R10, R12-R15 - Used to pass values to VMM in sub-functions.
108
//
109
// ### Output Operands:
110
// * RAX - TDCALL instruction return code, always return Success(0).
111
// * R10 - TDG.VP.VMCALL sub-function return value
112
// * R11 - Correspond to each TDG.VP.VMCALL.
113
// * R8-R9, R12-R15, RBX, RBP, RDI, RSI - Correspond to each TDG.VP.VMCALL sub-function.
114
//
115
#[cfg(not(feature = "no-tdvmcall"))]
116
0
pub fn td_vmcall(args: &mut TdVmcallArgs) -> u64 {
117
0
    unsafe { asm::asm_td_vmcall(args as *mut TdVmcallArgs as *mut c_void, 0) }
118
0
}
119
120
// An extended public wrapper for use of asm_td_vmcall.
121
//
122
// `do_sti` is a flag used to determine whether to execute `sti` instruction before `tdcall`
123
#[cfg(not(feature = "no-tdvmcall"))]
124
0
pub fn td_vmcall_ex(args: &mut TdVmcallArgs, do_sti: bool) -> u64 {
125
0
    unsafe { asm::asm_td_vmcall(args as *mut TdVmcallArgs as *mut c_void, do_sti as u64) }
126
0
}
127
128
// An extended public wrapper for use of asm_td_vmcall_ex.
129
//
130
// `do_sti` is a flag used to determine whether to execute `sti` instruction before `tdcall`
131
#[cfg(not(feature = "no-tdvmcall"))]
132
0
pub fn td_vmcall_ex2(args: &mut TdVmcallArgsEx, do_sti: bool) -> u64 {
133
0
    unsafe { asm::asm_td_vmcall_ex(args as *mut TdVmcallArgsEx as *mut c_void, do_sti as u64) }
134
0
}
135
136
// Wrapper for use of asm_td_call, this function takes a mutable reference of a
137
// TdVmcallArgs structure to ensure the input is valid
138
//
139
// ## TDCALL ABI
140
// Defined in TDX Module 1.0 Spec section 'TDCALL Instruction (Common)'
141
//
142
// ### Input Operands:
143
//  * RAX - Leaf and version numbers.
144
//  * Other - Used by leaf functions as input values.
145
//
146
// ### Output Operands:
147
//  * RAX - Instruction return code.
148
//  * Other - Used by leaf functions as output values.
149
//
150
0
pub fn td_call(args: &mut TdcallArgs) -> u64 {
151
0
    unsafe { asm::asm_td_call(args as *mut TdcallArgs as *mut c_void) }
152
0
}
153
154
// Used to pass the values of input/output register when performing TDVMCALL
155
// instruction
156
#[repr(C)]
157
#[derive(Default)]
158
pub struct TdcallArgs {
159
    pub rax: u64,
160
    pub rcx: u64,
161
    pub rdx: u64,
162
    pub r8: u64,
163
    pub r9: u64,
164
    pub r10: u64,
165
    pub r11: u64,
166
    pub r12: u64,
167
    pub r13: u64,
168
    pub r14: u64,
169
}
170
171
// Used to pass the values of input/output register when performing TDVMCALL
172
// instruction
173
#[cfg(not(feature = "no-tdvmcall"))]
174
#[repr(C)]
175
#[derive(Default)]
176
pub struct TdVmcallArgs {
177
    // Input: Always 0 for  (standard VMCALL)
178
    // Output: Sub-function
179
    pub r10: u64,
180
    pub r11: u64,
181
    pub r12: u64,
182
    pub r13: u64,
183
    pub r14: u64,
184
    pub r15: u64,
185
}
186
187
// Used to pass the values of input/output register when performing TDVMCALL
188
// instruction
189
#[cfg(not(feature = "no-tdvmcall"))]
190
#[repr(C)]
191
#[derive(Default)]
192
pub struct TdVmcallArgsEx {
193
    // Input: Always 0 for  (standard VMCALL)
194
    // Output: Sub-function
195
    pub rdx: u64,
196
    pub rbx: u64,
197
    pub rsi: u64,
198
    pub rdi: u64,
199
    pub r8: u64,
200
    pub r9: u64,
201
    pub r10: u64,
202
    pub r11: u64,
203
    pub r12: u64,
204
    pub r13: u64,
205
    pub r14: u64,
206
    pub r15: u64,
207
}
208
209
/// TDCALL instruction return error code
210
///
211
/// Refer to Intel TDX Module 1.0 Specifiction section 'TDCALL Instruction (Common)'
212
#[derive(Debug, PartialEq)]
213
pub enum TdCallError {
214
    // Invalid parameters
215
    TdxExitInvalidParameters,
216
217
    // The operand is busy (e.g., it is locked in Exclusive mode)
218
    TdxExitReasonOperandBusy(u32),
219
220
    // Operand is invalid (e.g., illegal leaf number)
221
    TdxExitReasonOperandInvalid(u32),
222
223
    // Error code defined by individual leaf function
224
    LeafSpecific(u64),
225
}
226
227
// TDCALL Completion Status Codes (Returned in RAX) Definition
228
impl From<u64> for TdCallError {
229
0
    fn from(val: u64) -> Self {
230
0
        match val >> 32 {
231
0
            0x8000_0200 => Self::TdxExitReasonOperandBusy(val as u32),
232
0
            0xC000_0100 => Self::TdxExitReasonOperandInvalid(val as u32),
233
0
            _ => Self::LeafSpecific(val),
234
        }
235
0
    }
236
}
237
238
/// TDVMCALL sub-function return error code
239
///
240
/// Refer to Guest-Host-Communication-Interface(GHCI) for Intel TDX
241
/// table 'TDCALL[TDG.VP.VMCALL]- Sub-function Completion-Status Codes'
242
#[cfg(not(feature = "no-tdvmcall"))]
243
#[derive(Debug, PartialEq)]
244
pub enum TdVmcallError {
245
    // TDCALL[TDG.VP.VMCALL] sub-function invocation must be retried
246
    VmcallRetry,
247
248
    // Invalid operand to TDG.VP.VMCALL sub-function
249
    VmcallOperandInvalid,
250
251
    // GPA already mapped
252
    VmcallGpaInuse,
253
254
    // Operand (address) alignment error
255
    VmcallAlignError,
256
257
    Other,
258
}
259
260
#[cfg(not(feature = "no-tdvmcall"))]
261
impl From<u64> for TdVmcallError {
262
0
    fn from(val: u64) -> Self {
263
0
        match val {
264
0
            0x1 => TdVmcallError::VmcallRetry,
265
0
            0x8000_0000_0000_0000 => TdVmcallError::VmcallOperandInvalid,
266
0
            0x8000_0000_0000_0001 => TdVmcallError::VmcallGpaInuse,
267
0
            0x8000_0000_0000_0002 => TdVmcallError::VmcallAlignError,
268
0
            _ => TdVmcallError::Other,
269
        }
270
0
    }
271
}