1#[cfg(guest_arch = "aarch64")]
7pub use Aarch64Register as Register;
8#[cfg(guest_arch = "x86_64")]
9pub use X86Register as Register;
10
11#[derive(Debug, PartialEq, Eq, Clone, Copy)]
14pub enum BootPageAcceptance {
15 Exclusive,
18 ExclusiveUnmeasured,
21 VpContext,
23 ErrorPage,
25 SecretsPage,
28 CpuidPage,
30 CpuidExtendedStatePage,
32 Shared,
34}
35
36#[derive(Debug, PartialEq, Eq)]
38pub enum IsolationType {
39 None,
41 Vbs,
43 Snp,
45 Tdx,
47}
48
49#[derive(Debug, PartialEq, Eq)]
52pub enum StartupMemoryType {
53 Ram,
55 Vtl2ProtectableRam,
58}
59
60#[derive(Copy, Clone, Debug, PartialEq, Eq)]
62pub struct TableRegister {
63 pub base: u64,
64 pub limit: u16,
65}
66
67impl From<igvm::registers::TableRegister> for TableRegister {
68 fn from(value: igvm::registers::TableRegister) -> Self {
69 Self {
70 base: value.base,
71 limit: value.limit,
72 }
73 }
74}
75
76impl From<TableRegister> for igvm::registers::TableRegister {
77 fn from(value: TableRegister) -> Self {
78 Self {
79 base: value.base,
80 limit: value.limit,
81 }
82 }
83}
84
85#[derive(Copy, Clone, Debug, PartialEq, Eq)]
87pub struct SegmentRegister {
88 pub base: u64,
89 pub limit: u32,
90 pub selector: u16,
91 pub attributes: u16,
92}
93
94impl From<igvm::registers::SegmentRegister> for SegmentRegister {
95 fn from(value: igvm::registers::SegmentRegister) -> Self {
96 Self {
97 base: value.base,
98 limit: value.limit,
99 selector: value.selector,
100 attributes: value.attributes,
101 }
102 }
103}
104
105impl From<SegmentRegister> for igvm::registers::SegmentRegister {
106 fn from(value: SegmentRegister) -> Self {
107 Self {
108 base: value.base,
109 limit: value.limit,
110 selector: value.selector,
111 attributes: value.attributes,
112 }
113 }
114}
115
116#[derive(Debug, Clone, Copy, PartialEq, Eq)]
118pub enum X86Register {
119 Gdtr(TableRegister),
120 Idtr(TableRegister),
121 Ds(SegmentRegister),
122 Es(SegmentRegister),
123 Fs(SegmentRegister),
124 Gs(SegmentRegister),
125 Ss(SegmentRegister),
126 Cs(SegmentRegister),
127 Tr(SegmentRegister),
128 Cr0(u64),
129 Cr3(u64),
130 Cr4(u64),
131 Efer(u64),
132 Pat(u64),
133 Rbp(u64),
134 Rip(u64),
135 Rsi(u64),
136 Rsp(u64),
137 R8(u64),
138 R9(u64),
139 R10(u64),
140 R11(u64),
141 R12(u64),
142 Rflags(u64),
143 MtrrDefType(u64),
144 MtrrPhysBase0(u64),
145 MtrrPhysMask0(u64),
146 MtrrPhysBase1(u64),
147 MtrrPhysMask1(u64),
148 MtrrPhysBase2(u64),
149 MtrrPhysMask2(u64),
150 MtrrPhysBase3(u64),
151 MtrrPhysMask3(u64),
152 MtrrPhysBase4(u64),
153 MtrrPhysMask4(u64),
154 MtrrFix64k00000(u64),
155 MtrrFix16k80000(u64),
156 MtrrFix4kE0000(u64),
158 MtrrFix4kE8000(u64),
159 MtrrFix4kF0000(u64),
160 MtrrFix4kF8000(u64),
161}
162
163impl From<igvm::registers::X86Register> for X86Register {
164 fn from(value: igvm::registers::X86Register) -> Self {
165 use igvm::registers::X86Register as igvm_reg;
166 match value {
167 igvm_reg::Gdtr(v) => X86Register::Gdtr(v.into()),
168 igvm_reg::Idtr(v) => X86Register::Idtr(v.into()),
169 igvm_reg::Ds(v) => X86Register::Ds(v.into()),
170 igvm_reg::Es(v) => X86Register::Es(v.into()),
171 igvm_reg::Fs(v) => X86Register::Fs(v.into()),
172 igvm_reg::Gs(v) => X86Register::Gs(v.into()),
173 igvm_reg::Ss(v) => X86Register::Ss(v.into()),
174 igvm_reg::Cs(v) => X86Register::Cs(v.into()),
175 igvm_reg::Tr(v) => X86Register::Tr(v.into()),
176 igvm_reg::Cr0(v) => X86Register::Cr0(v),
177 igvm_reg::Cr3(v) => X86Register::Cr3(v),
178 igvm_reg::Cr4(v) => X86Register::Cr4(v),
179 igvm_reg::Efer(v) => X86Register::Efer(v),
180 igvm_reg::Pat(v) => X86Register::Pat(v),
181 igvm_reg::Rbp(v) => X86Register::Rbp(v),
182 igvm_reg::Rip(v) => X86Register::Rip(v),
183 igvm_reg::Rsi(v) => X86Register::Rsi(v),
184 igvm_reg::Rsp(v) => X86Register::Rsp(v),
185 igvm_reg::R8(v) => X86Register::R8(v),
186 igvm_reg::R9(v) => X86Register::R9(v),
187 igvm_reg::R10(v) => X86Register::R10(v),
188 igvm_reg::R11(v) => X86Register::R11(v),
189 igvm_reg::R12(v) => X86Register::R12(v),
190 igvm_reg::Rflags(v) => X86Register::Rflags(v),
191 igvm_reg::MtrrDefType(v) => X86Register::MtrrDefType(v),
192 igvm_reg::MtrrPhysBase0(v) => X86Register::MtrrPhysBase0(v),
193 igvm_reg::MtrrPhysMask0(v) => X86Register::MtrrPhysMask0(v),
194 igvm_reg::MtrrPhysBase1(v) => X86Register::MtrrPhysBase1(v),
195 igvm_reg::MtrrPhysMask1(v) => X86Register::MtrrPhysMask1(v),
196 igvm_reg::MtrrPhysBase2(v) => X86Register::MtrrPhysBase2(v),
197 igvm_reg::MtrrPhysMask2(v) => X86Register::MtrrPhysMask2(v),
198 igvm_reg::MtrrPhysBase3(v) => X86Register::MtrrPhysBase3(v),
199 igvm_reg::MtrrPhysMask3(v) => X86Register::MtrrPhysMask3(v),
200 igvm_reg::MtrrPhysBase4(v) => X86Register::MtrrPhysBase4(v),
201 igvm_reg::MtrrPhysMask4(v) => X86Register::MtrrPhysMask4(v),
202 igvm_reg::MtrrFix64k00000(v) => X86Register::MtrrFix64k00000(v),
203 igvm_reg::MtrrFix16k80000(v) => X86Register::MtrrFix16k80000(v),
204 igvm_reg::MtrrFix4kE0000(v) => X86Register::MtrrFix4kE0000(v),
205 igvm_reg::MtrrFix4kE8000(v) => X86Register::MtrrFix4kE8000(v),
206 igvm_reg::MtrrFix4kF0000(v) => X86Register::MtrrFix4kF0000(v),
207 igvm_reg::MtrrFix4kF8000(v) => X86Register::MtrrFix4kF8000(v),
208 }
209 }
210}
211
212impl From<X86Register> for igvm::registers::X86Register {
213 fn from(value: X86Register) -> Self {
214 use igvm::registers::X86Register as igvm_reg;
215 match value {
216 X86Register::Gdtr(v) => igvm_reg::Gdtr(v.into()),
217 X86Register::Idtr(v) => igvm_reg::Idtr(v.into()),
218 X86Register::Ds(v) => igvm_reg::Ds(v.into()),
219 X86Register::Es(v) => igvm_reg::Es(v.into()),
220 X86Register::Fs(v) => igvm_reg::Fs(v.into()),
221 X86Register::Gs(v) => igvm_reg::Gs(v.into()),
222 X86Register::Ss(v) => igvm_reg::Ss(v.into()),
223 X86Register::Cs(v) => igvm_reg::Cs(v.into()),
224 X86Register::Tr(v) => igvm_reg::Tr(v.into()),
225 X86Register::Cr0(v) => igvm_reg::Cr0(v),
226 X86Register::Cr3(v) => igvm_reg::Cr3(v),
227 X86Register::Cr4(v) => igvm_reg::Cr4(v),
228 X86Register::Efer(v) => igvm_reg::Efer(v),
229 X86Register::Pat(v) => igvm_reg::Pat(v),
230 X86Register::Rbp(v) => igvm_reg::Rbp(v),
231 X86Register::Rip(v) => igvm_reg::Rip(v),
232 X86Register::Rsi(v) => igvm_reg::Rsi(v),
233 X86Register::Rsp(v) => igvm_reg::Rsp(v),
234 X86Register::R8(v) => igvm_reg::R8(v),
235 X86Register::R9(v) => igvm_reg::R9(v),
236 X86Register::R10(v) => igvm_reg::R10(v),
237 X86Register::R11(v) => igvm_reg::R11(v),
238 X86Register::R12(v) => igvm_reg::R12(v),
239 X86Register::Rflags(v) => igvm_reg::Rflags(v),
240 X86Register::MtrrDefType(v) => igvm_reg::MtrrDefType(v),
241 X86Register::MtrrPhysBase0(v) => igvm_reg::MtrrPhysBase0(v),
242 X86Register::MtrrPhysMask0(v) => igvm_reg::MtrrPhysMask0(v),
243 X86Register::MtrrPhysBase1(v) => igvm_reg::MtrrPhysBase1(v),
244 X86Register::MtrrPhysMask1(v) => igvm_reg::MtrrPhysMask1(v),
245 X86Register::MtrrPhysBase2(v) => igvm_reg::MtrrPhysBase2(v),
246 X86Register::MtrrPhysMask2(v) => igvm_reg::MtrrPhysMask2(v),
247 X86Register::MtrrPhysBase3(v) => igvm_reg::MtrrPhysBase3(v),
248 X86Register::MtrrPhysMask3(v) => igvm_reg::MtrrPhysMask3(v),
249 X86Register::MtrrPhysBase4(v) => igvm_reg::MtrrPhysBase4(v),
250 X86Register::MtrrPhysMask4(v) => igvm_reg::MtrrPhysMask4(v),
251 X86Register::MtrrFix64k00000(v) => igvm_reg::MtrrFix64k00000(v),
252 X86Register::MtrrFix16k80000(v) => igvm_reg::MtrrFix16k80000(v),
253 X86Register::MtrrFix4kE0000(v) => igvm_reg::MtrrFix4kE0000(v),
254 X86Register::MtrrFix4kE8000(v) => igvm_reg::MtrrFix4kE8000(v),
255 X86Register::MtrrFix4kF0000(v) => igvm_reg::MtrrFix4kF0000(v),
256 X86Register::MtrrFix4kF8000(v) => igvm_reg::MtrrFix4kF8000(v),
257 }
258 }
259}
260
261#[derive(Debug, Clone, Copy, PartialEq, Eq)]
262pub enum Aarch64Register {
263 Pc(u64),
264 X0(u64),
265 X1(u64),
266 Cpsr(u64),
267 VbarEl1(u64),
268 Ttbr0El1(u64),
269 Ttbr1El1(u64),
270 MairEl1(u64),
271 SctlrEl1(u64),
272 TcrEl1(u64),
273}
274
275impl From<igvm::registers::AArch64Register> for Aarch64Register {
276 fn from(value: igvm::registers::AArch64Register) -> Self {
277 use igvm::registers::AArch64Register as igvm_reg;
278 match value {
279 igvm_reg::Pc(v) => Aarch64Register::Pc(v),
280 igvm_reg::X0(v) => Aarch64Register::X0(v),
281 igvm_reg::X1(v) => Aarch64Register::X1(v),
282 igvm_reg::Cpsr(v) => Aarch64Register::Cpsr(v),
283 igvm_reg::SctlrEl1(v) => Aarch64Register::SctlrEl1(v),
284 igvm_reg::TcrEl1(v) => Aarch64Register::TcrEl1(v),
285 igvm_reg::MairEl1(v) => Aarch64Register::MairEl1(v),
286 igvm_reg::VbarEl1(v) => Aarch64Register::VbarEl1(v),
287 igvm_reg::Ttbr0El1(v) => Aarch64Register::Ttbr0El1(v),
288 igvm_reg::Ttbr1El1(v) => Aarch64Register::Ttbr1El1(v),
289 }
290 }
291}
292
293impl From<Aarch64Register> for igvm::registers::AArch64Register {
294 fn from(value: Aarch64Register) -> Self {
295 use igvm::registers::AArch64Register as igvm_reg;
296 match value {
297 Aarch64Register::Pc(v) => igvm_reg::Pc(v),
298 Aarch64Register::X0(v) => igvm_reg::X0(v),
299 Aarch64Register::X1(v) => igvm_reg::X1(v),
300 Aarch64Register::Cpsr(v) => igvm_reg::Cpsr(v),
301 Aarch64Register::SctlrEl1(v) => igvm_reg::SctlrEl1(v),
302 Aarch64Register::TcrEl1(v) => igvm_reg::TcrEl1(v),
303 Aarch64Register::MairEl1(v) => igvm_reg::MairEl1(v),
304 Aarch64Register::VbarEl1(v) => igvm_reg::VbarEl1(v),
305 Aarch64Register::Ttbr0El1(v) => igvm_reg::Ttbr0El1(v),
306 Aarch64Register::Ttbr1El1(v) => igvm_reg::Ttbr1El1(v),
307 }
308 }
309}
310
311#[derive(Debug)]
313pub struct IsolationConfig {
314 pub paravisor_present: bool,
316
317 pub isolation_type: IsolationType,
319
320 pub shared_gpa_boundary_bits: Option<u8>,
322}
323
324#[derive(Debug, Default)]
325pub struct CpuidResult {
326 pub eax: u32,
327 pub ebx: u32,
328 pub ecx: u32,
329 pub edx: u32,
330}
331
332impl IsolationConfig {
333 pub fn get_cpuid(&self) -> CpuidResult {
335 let eax = if self.paravisor_present { 1 } else { 0 };
337
338 let mut ebx = 0;
339 match self.isolation_type {
340 IsolationType::None => {}
341 IsolationType::Vbs => ebx = hvdef::HvPartitionIsolationType::VBS.0 as _,
342 IsolationType::Snp => ebx = hvdef::HvPartitionIsolationType::SNP.0 as _,
343 IsolationType::Tdx => ebx = hvdef::HvPartitionIsolationType::TDX.0 as _,
344 }
345
346 match self.shared_gpa_boundary_bits {
347 None => {}
348 Some(bits) => {
349 ebx |= 1 << 5;
350 ebx |= ((bits & 0x3F) as u32) << 6;
351 }
352 }
353
354 CpuidResult {
355 eax,
356 ebx,
357 ecx: 0,
358 edx: 0,
359 }
360 }
361}
362
363#[derive(Debug)]
364pub struct ImportRegion {
365 pub page_base: u64,
366 pub page_count: u64,
367 pub acceptance: BootPageAcceptance,
368}
369
370#[derive(Debug, PartialEq, Eq)]
371pub struct PageRegion {
372 pub page_base: u64,
373 pub page_count: u64,
374}
375
376#[derive(Debug)]
377pub enum IgvmParameterType {
378 VpCount,
379 Srat,
380 Madt,
381 MmioRanges,
382 MemoryMap,
383 CommandLine,
384 Slit,
385 Pptt,
386 DeviceTree,
387}
388
389#[repr(transparent)]
390#[derive(Debug, Clone, Copy)]
391pub struct ParameterAreaIndex(pub u32);
392
393#[derive(Debug, Clone, Copy, PartialEq, Eq)]
394pub enum GuestArchKind {
395 X86_64,
396 Aarch64,
397}
398
399pub trait GuestArch {
400 fn arch() -> GuestArchKind;
401}
402
403impl GuestArch for X86Register {
404 fn arch() -> GuestArchKind {
405 GuestArchKind::X86_64
406 }
407}
408
409impl GuestArch for Aarch64Register {
410 fn arch() -> GuestArchKind {
411 GuestArchKind::Aarch64
412 }
413}
414
415pub trait ImageLoad<R>
416where
417 R: GuestArch,
418{
419 fn isolation_config(&self) -> IsolationConfig;
422
423 fn create_parameter_area(
429 &mut self,
430 page_base: u64,
431 page_count: u32,
432 debug_tag: &str,
433 ) -> anyhow::Result<ParameterAreaIndex>;
434
435 fn create_parameter_area_with_data(
441 &mut self,
442 page_base: u64,
443 page_count: u32,
444 debug_tag: &str,
445 initial_data: &[u8],
446 ) -> anyhow::Result<ParameterAreaIndex>;
447
448 fn import_parameter(
454 &mut self,
455 parameter_area: ParameterAreaIndex,
456 byte_offset: u32,
457 parameter_type: IgvmParameterType,
458 ) -> anyhow::Result<()>;
459
460 fn import_pages(
466 &mut self,
467 page_base: u64,
468 page_count: u64,
469 debug_tag: &str,
470 acceptance: BootPageAcceptance,
471 data: &[u8],
472 ) -> anyhow::Result<()>;
473
474 fn import_vp_register(&mut self, register: R) -> anyhow::Result<()>;
476
477 fn verify_startup_memory_available(
479 &mut self,
480 page_base: u64,
481 page_count: u64,
482 memory_type: StartupMemoryType,
483 ) -> anyhow::Result<()>;
484
485 fn set_vp_context_page(&mut self, page_base: u64) -> anyhow::Result<()>;
489
490 fn relocation_region(
492 &mut self,
493 gpa: u64,
494 size_bytes: u64,
495 relocation_alignment: u64,
496 minimum_relocation_gpa: u64,
497 maximum_relocation_gpa: u64,
498 apply_rip_offset: bool,
499 apply_gdtr_offset: bool,
500 vp_index: u16,
501 ) -> anyhow::Result<()>;
502
503 fn page_table_relocation(
505 &mut self,
506 page_table_gpa: u64,
507 size_pages: u64,
508 used_pages: u64,
509 vp_index: u16,
510 ) -> anyhow::Result<()>;
511
512 fn set_imported_regions_config_page(&mut self, page_base: u64);
522}