microsoft/openvmm

Public

mirrored from https://github.com/microsoft/openvmmAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
release/2411-fork

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

openhcl/hcl/src/protocol.rs

259lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Structures and definitions used between the underhill kernel and HvLite.
5
6#![allow(dead_code)]
7#![allow(
8 non_upper_case_globals,
9 clippy::upper_case_acronyms,
10 non_camel_case_types,
11 missing_docs
12)]
13
14use bitfield_struct::bitfield;
15use hvdef::hypercall::HvInputVtl;
16use hvdef::HV_MESSAGE_SIZE;
17use libc::c_void;
18use zerocopy::AsBytes;
19use zerocopy::FromBytes;
20use zerocopy::FromZeroes;
21
22#[repr(C)]
23#[derive(Copy, Clone, Debug, Default)]
24pub struct hcl_translate_address_info {
25 pub gva_pfn: u64,
26 pub gpa_pfn: u64,
27}
28
29#[repr(C)]
30#[derive(Copy, Clone, Debug, Default)]
31pub struct hcl_signal_event_direct_t {
32 pub vp: u32,
33 pub flag: u16,
34 pub sint: u8,
35 pub vtl: u8,
36 pub pad: u32,
37 pub pad1: u16,
38 pub pad2: u8,
39 pub newly_signaled: u8,
40}
41
42pub const HV_VP_ASSIST_PAGE_SIGNAL_EVENT_COUNT: usize = 16;
43pub const HV_VP_ASSIST_PAGE_ACTION_TYPE_SIGNAL_EVENT: u64 = 1;
44
45#[repr(C)]
46#[derive(Copy, Clone, AsBytes, FromBytes, FromZeroes)]
47pub struct hv_vp_assist_page_signal_event {
48 pub action_type: u64,
49 pub vp: u32,
50 pub vtl: u8,
51 pub sint: u8,
52 pub flag: u16,
53}
54
55#[repr(C)]
56#[derive(Copy, Clone, Debug)]
57pub struct hcl_post_message_direct_t {
58 pub vp: u32,
59 pub sint: u32,
60 pub pad: u32,
61 pub pad2: u8,
62 pub vtl: u8,
63 pub size: u16,
64 pub message: *const u8,
65}
66
67#[repr(C, packed)]
68#[derive(Copy, Clone, Debug, Default)]
69pub struct hcl_pfn_range_t {
70 pub start_pfn: u64,
71 pub last_pfn: u64,
72}
73
74#[derive(FromBytes, FromZeroes, AsBytes)]
75#[repr(C)]
76pub struct hcl_cpu_context_x64 {
77 pub gps: [u64; 16],
78 pub fx_state: x86defs::xsave::Fxsave,
79 pub reserved: [u8; 384],
80}
81
82const _: () = assert!(size_of::<hcl_cpu_context_x64>() == 1024);
83
84#[derive(FromBytes, FromZeroes, AsBytes)]
85#[repr(C)]
86// NOTE: x18 is managed by the hypervisor. It is assumed here be available
87// for easier offset arithmetic.
88pub struct hcl_cpu_context_aarch64 {
89 pub x: [u64; 31],
90 pub _rsvd: u64,
91 pub q: [u128; 32],
92 pub reserved: [u8; 256],
93}
94
95const _: () = assert!(size_of::<hcl_cpu_context_aarch64>() == 1024);
96
97pub const RAX: usize = 0;
98pub const RCX: usize = 1;
99pub const RDX: usize = 2;
100pub const RBX: usize = 3;
101pub const CR2: usize = 4; // RSP on TdxL2EnterGuestState, CR2 on hcl_cpu_context_x64
102pub const RBP: usize = 5;
103pub const RSI: usize = 6;
104pub const RDI: usize = 7;
105pub const R8: usize = 8;
106pub const R9: usize = 9;
107pub const R10: usize = 10;
108pub const R11: usize = 11;
109pub const R12: usize = 12;
110pub const R13: usize = 13;
111pub const R14: usize = 14;
112pub const R15: usize = 15;
113
114pub const VTL_RETURN_ACTION_SIZE: usize = 256;
115
116#[repr(C)]
117pub struct hcl_run {
118 pub cancel: u32,
119 pub vtl_ret_action_size: u32,
120 pub flags: u32,
121 pub scan_proxy_irr: u8,
122 pub pad: [u8; 2],
123 pub mode: EnterModes,
124 pub exit_message: [u8; HV_MESSAGE_SIZE],
125 pub context: [u8; 1024],
126 pub vtl_ret_actions: [u8; VTL_RETURN_ACTION_SIZE],
127 pub proxy_irr: [u32; 8],
128 pub target_vtl: HvInputVtl,
129}
130
131// The size of hcl_run must be less than or equal to a single 4K page.
132const _: () = assert!(size_of::<hcl_run>() <= 4096);
133
134pub const MSHV_VTL_RUN_FLAG_HALTED: u32 = 1 << 0;
135
136#[repr(C)]
137pub struct hcl_set_poll_file {
138 pub cpu: i32,
139 pub fd: i32,
140}
141
142#[repr(C)]
143pub struct hcl_hvcall_setup {
144 pub allow_bitmap_size: u64,
145 pub allow_bitmap_ptr: *const u64,
146}
147
148#[repr(C)]
149pub struct hcl_hvcall {
150 pub control: hvdef::hypercall::Control,
151 pub input_size: usize,
152 pub input_data: *const c_void,
153 pub status: hvdef::hypercall::HypercallOutput,
154 pub output_size: usize,
155 pub output_data: *const c_void,
156}
157
158pub const HCL_REG_PAGE_OFFSET: i64 = 1 << 16;
159pub const HCL_VMSA_PAGE_OFFSET: i64 = 2 << 16;
160pub const MSHV_APIC_PAGE_OFFSET: i64 = 3 << 16;
161pub const HCL_VMSA_GUEST_VSM_PAGE_OFFSET: i64 = 4 << 16;
162
163open_enum::open_enum! {
164 /// 4 bits represent VTL0 enter mode.
165 pub enum EnterMode: u8 {
166 /// "Fast" mode: Enters VTL0 with scheduler ticks on, no extra cost on turning off the scheduler
167 /// timers, therefore it's fast.
168 FAST = 0,
169 /// "Play idle" mode: Enters VTL0 with scheduler ticks off (setting the current kernel thread to
170 /// idle).
171 PLAY_IDLE = 1,
172 /// "Idle to VTL0 idle" mode: Switches to the idle thread, and the idle thread enters VTL0 with
173 /// scheduler ticks off.
174 IDLE_TO_VTL0 = 2,
175 }
176}
177
178impl EnterMode {
179 const fn into_bits(self) -> u8 {
180 self.0
181 }
182
183 const fn from_bits(bits: u8) -> Self {
184 Self(bits)
185 }
186}
187
188/// Controls how to enter VTL0.
189#[bitfield(u8)]
190pub struct EnterModes {
191 /// [`Mode`] used when entering VTL0 the first time.
192 #[bits(4)]
193 pub first: EnterMode,
194 /// [`Mode`] used when interrupted from the previous enter to VTL0.
195 #[bits(4)]
196 pub second: EnterMode,
197}
198
199/// The register values returned from a TDG.VP.ENTER call. These are readable
200/// via mmaping the mshv_vtl driver inside `hcl_run`, and returned on a run_vp
201/// ioctl exit. See the TDX ABI specification for output operands for
202/// TDG.VP.ENTER.
203#[repr(C)]
204#[derive(Debug, AsBytes, FromBytes, FromZeroes)]
205pub struct tdx_tdg_vp_enter_exit_info {
206 pub rax: u64,
207 pub rcx: u64,
208 pub rdx: u64,
209 pub rsi: u64,
210 pub rdi: u64,
211 pub r8: u64,
212 pub r9: u64,
213 pub r10: u64,
214 pub r11: u64,
215 pub r12: u64,
216 pub r13: u64,
217}
218
219#[bitfield(u64)]
220#[derive(AsBytes, FromBytes, FromZeroes)]
221pub struct tdx_vp_state_flags {
222 /// Issue a cache flush for a WBINVD before calling VP.ENTER.
223 pub wbinvd: bool,
224 /// Issue a cache flush for a WBNOINVD before calling VP.ENTER.
225 pub wbnoinvd: bool,
226 #[bits(62)]
227 reserved: u64,
228}
229
230/// Additional VP state that is save/restored across TDG.VP.ENTER.
231#[repr(C)]
232#[derive(Debug, AsBytes, FromBytes, FromZeroes)]
233pub struct tdx_vp_state {
234 pub msr_kernel_gs_base: u64,
235 pub msr_star: u64,
236 pub msr_lstar: u64,
237 pub msr_sfmask: u64,
238 pub msr_xss: u64,
239 pub cr2: u64,
240 pub msr_tsc_aux: u64,
241 pub flags: tdx_vp_state_flags,
242}
243
244#[repr(C)]
245#[derive(Debug, AsBytes, FromBytes, FromZeroes)]
246pub struct tdx_vp_context {
247 pub exit_info: tdx_tdg_vp_enter_exit_info,
248 pub pad1: [u8; 48],
249 pub vp_state: tdx_vp_state,
250 pub pad2: [u8; 32],
251 pub entry_rcx: x86defs::tdx::TdxVmFlags,
252 pub gpr_list: x86defs::tdx::TdxL2EnterGuestState,
253 pub pad3: [u8; 96],
254 pub fx_state: x86defs::xsave::Fxsave,
255 pub pad4: [u8; 16],
256}
257
258const _: () = assert!(core::mem::offset_of!(tdx_vp_context, gpr_list) + 272 == 512);
259const _: () = assert!(size_of::<tdx_vp_context>() == 1024);
260