Skip to content

Commit 1985f1f

Browse files
committed
More plumbing
1 parent 907ec0b commit 1985f1f

File tree

10 files changed

+106
-22
lines changed

10 files changed

+106
-22
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -9501,6 +9501,7 @@ dependencies = [
95019501
"arbitrary",
95029502
"bitfield-struct 0.10.1",
95039503
"open_enum",
9504+
"static_assertions",
95049505
"zerocopy 0.8.23",
95059506
]
95069507

openhcl/hcl/src/ioctl.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ use crate::protocol::EnterModes;
2020
use crate::protocol::HCL_REG_PAGE_OFFSET;
2121
use crate::protocol::HCL_VMSA_GUEST_VSM_PAGE_OFFSET;
2222
use crate::protocol::HCL_VMSA_PAGE_OFFSET;
23-
use crate::protocol::MSHV_APIC_PAGE_OFFSET;
23+
use crate::protocol::MSHV_SEV_AVIC_PAGE_OFFSET;
24+
use crate::protocol::MSHV_TDX_APIC_PAGE_OFFSET;
2425
use crate::protocol::hcl_intr_offload_flags;
2526
use crate::protocol::hcl_run;
2627
use deferred::RegisteredDeferredActions;
@@ -77,9 +78,10 @@ use std::sync::atomic::Ordering;
7778
use thiserror::Error;
7879
use user_driver::DmaClient;
7980
use user_driver::memory::MemoryBlock;
81+
use x86defs::snp::SevAvicPage;
8082
use x86defs::snp::SevVmsa;
8183
use x86defs::tdx::TdCallResultCode;
82-
use x86defs::vmx::ApicPage;
84+
use x86defs::vmx::VmxApicPage;
8385
use zerocopy::FromBytes;
8486
use zerocopy::FromZeros;
8587
use zerocopy::Immutable;
@@ -1548,9 +1550,11 @@ enum BackingState {
15481550
},
15491551
Snp {
15501552
vmsa: VtlArray<MappedPage<SevVmsa>, 2>,
1553+
vtl0_apic_page: MappedPage<SevAvicPage>,
1554+
vtl1_apic_page: MemoryBlock,
15511555
},
15521556
Tdx {
1553-
vtl0_apic_page: MappedPage<ApicPage>,
1557+
vtl0_apic_page: MappedPage<VmxApicPage>,
15541558
vtl1_apic_page: MemoryBlock,
15551559
},
15561560
}
@@ -1602,10 +1606,16 @@ impl HclVp {
16021606
.map_err(|e| Error::MmapVp(e, Some(Vtl::Vtl1)))?;
16031607
BackingState::Snp {
16041608
vmsa: [vmsa_vtl0, vmsa_vtl1].into(),
1609+
vtl0_apic_page: MappedPage::new(fd, MSHV_SEV_AVIC_PAGE_OFFSET | vp as i64)
1610+
.map_err(|e| Error::MmapVp(e, Some(Vtl::Vtl0)))?,
1611+
vtl1_apic_page: private_dma_client
1612+
.ok_or(Error::MissingPrivateMemory)?
1613+
.allocate_dma_buffer(HV_PAGE_SIZE as usize)
1614+
.map_err(Error::AllocVp)?,
16051615
}
16061616
}
16071617
IsolationType::Tdx => BackingState::Tdx {
1608-
vtl0_apic_page: MappedPage::new(fd, MSHV_APIC_PAGE_OFFSET | vp as i64)
1618+
vtl0_apic_page: MappedPage::new(fd, MSHV_TDX_APIC_PAGE_OFFSET | vp as i64)
16091619
.map_err(|e| Error::MmapVp(e, Some(Vtl::Vtl0)))?,
16101620
vtl1_apic_page: private_dma_client
16111621
.ok_or(Error::MissingPrivateMemory)?

openhcl/hcl/src/ioctl/snp.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@ use sidecar_client::SidecarVp;
2525
use std::cell::UnsafeCell;
2626
use std::os::fd::AsRawFd;
2727
use thiserror::Error;
28+
use x86defs::snp::SevAvicPage;
2829
use x86defs::snp::SevRmpAdjust;
2930
use x86defs::snp::SevVmsa;
3031

3132
/// Runner backing for SNP partitions.
3233
pub struct Snp<'a> {
3334
vmsa: VtlArray<&'a UnsafeCell<SevVmsa>, 2>,
35+
apic_pages: VtlArray<&'a UnsafeCell<SevAvicPage>, 2>,
3436
}
3537

3638
/// Error returned by failing SNP operations.
@@ -176,11 +178,28 @@ impl MshvVtl {
176178
impl<'a> super::private::BackingPrivate<'a> for Snp<'a> {
177179
fn new(vp: &'a HclVp, sidecar: Option<&SidecarVp<'_>>, _hcl: &Hcl) -> Result<Self, NoRunner> {
178180
assert!(sidecar.is_none());
179-
let super::BackingState::Snp { vmsa } = &vp.backing else {
181+
let super::BackingState::Snp {
182+
vtl0_apic_page,
183+
vtl1_apic_page,
184+
vmsa,
185+
} = &vp.backing
186+
else {
180187
return Err(NoRunner::MismatchedIsolation);
181188
};
182189

190+
// TODO: Register the VTL 1 AVIC page with the hypervisor.
191+
// Specification: "SEV-ES Guest-Hypervisor Communication Block Standartization",
192+
// 4.1.16.1 "Backing page support".
193+
//
194+
// The VTL 0 APIC page is registered by the kernel.
195+
let vtl1_apic_page_addr = vtl1_apic_page.pfns()[0] * user_driver::memory::PAGE_SIZE64;
196+
197+
// SAFETY: The mapping is held for the appropriate lifetime, and the
198+
// APIC page is never accessed as any other type, or by any other location.
199+
let vtl1_apic_page = unsafe { &*vtl1_apic_page.base().cast() };
200+
183201
Ok(Self {
202+
apic_pages: [vtl0_apic_page.as_ref(), vtl1_apic_page].into(),
184203
vmsa: vmsa.each_ref().map(|mp| mp.as_ref()),
185204
})
186205
}

openhcl/hcl/src/ioctl/tdx.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@ use x86defs::tdx::TdxGlaListInfo;
3838
use x86defs::tdx::TdxL2Ctls;
3939
use x86defs::tdx::TdxL2EnterGuestState;
4040
use x86defs::tdx::TdxVmFlags;
41-
use x86defs::vmx::ApicPage;
4241
use x86defs::vmx::VmcsField;
42+
use x86defs::vmx::VmxApicPage;
4343

4444
/// Runner backing for TDX partitions.
4545
pub struct Tdx<'a> {
46-
apic_pages: VtlArray<&'a UnsafeCell<ApicPage>, 2>,
46+
apic_pages: VtlArray<&'a UnsafeCell<VmxApicPage>, 2>,
4747
}
4848

4949
impl MshvVtl {
@@ -122,14 +122,14 @@ impl<'a> ProcessorRunner<'a, Tdx<'a>> {
122122
}
123123

124124
/// Gets a reference to the tdx APIC page for the given VTL.
125-
pub fn tdx_apic_page(&self, vtl: GuestVtl) -> &ApicPage {
125+
pub fn tdx_apic_page(&self, vtl: GuestVtl) -> &VmxApicPage {
126126
// SAFETY: the APIC pages will not be concurrently accessed by the processor
127127
// while this VP is in VTL2.
128128
unsafe { &*self.state.apic_pages[vtl].get() }
129129
}
130130

131131
/// Gets a mutable reference to the tdx APIC page for the given VTL.
132-
pub fn tdx_apic_page_mut(&mut self, vtl: GuestVtl) -> &mut ApicPage {
132+
pub fn tdx_apic_page_mut(&mut self, vtl: GuestVtl) -> &mut VmxApicPage {
133133
// SAFETY: the APIC pages will not be concurrently accessed by the processor
134134
// while this VP is in VTL2.
135135
unsafe { &mut *self.state.apic_pages[vtl].get() }

openhcl/hcl/src/protocol.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,9 @@ pub struct hcl_hvcall {
175175

176176
pub const HCL_REG_PAGE_OFFSET: i64 = 1 << 16;
177177
pub const HCL_VMSA_PAGE_OFFSET: i64 = 2 << 16;
178-
pub const MSHV_APIC_PAGE_OFFSET: i64 = 3 << 16;
178+
pub const MSHV_TDX_APIC_PAGE_OFFSET: i64 = 3 << 16;
179179
pub const HCL_VMSA_GUEST_VSM_PAGE_OFFSET: i64 = 4 << 16;
180+
pub const MSHV_SEV_AVIC_PAGE_OFFSET: i64 = 5 << 16;
180181

181182
open_enum::open_enum! {
182183
/// 4 bits represent VTL0 enter mode.

openhcl/virt_mshv_vtl/src/processor/tdx/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ use virt_support_x86emu::emulate::emulate_io;
7575
use virt_support_x86emu::emulate::emulate_translate_gva;
7676
use virt_support_x86emu::translate::TranslationRegisters;
7777
use vmcore::vmtime::VmTimeAccess;
78+
use x86defs::ApicRegister;
7879
use x86defs::RFlags;
7980
use x86defs::X64_CR0_ET;
8081
use x86defs::X64_CR0_NE;
@@ -95,8 +96,6 @@ use x86defs::tdx::TdxGp;
9596
use x86defs::tdx::TdxInstructionInfo;
9697
use x86defs::tdx::TdxL2Ctls;
9798
use x86defs::tdx::TdxVpEnterRaxResult;
98-
use x86defs::vmx::ApicPage;
99-
use x86defs::vmx::ApicRegister;
10099
use x86defs::vmx::CR_ACCESS_TYPE_LMSW;
101100
use x86defs::vmx::CR_ACCESS_TYPE_MOV_TO_CR;
102101
use x86defs::vmx::CrAccessQualification;
@@ -114,6 +113,7 @@ use x86defs::vmx::SecondaryProcessorControls;
114113
use x86defs::vmx::VMX_ENTRY_CONTROL_LONG_MODE_GUEST;
115114
use x86defs::vmx::VMX_FEATURE_CONTROL_LOCKED;
116115
use x86defs::vmx::VmcsField;
116+
use x86defs::vmx::VmxApicPage;
117117
use x86defs::vmx::VmxEptExitQualification;
118118
use x86defs::vmx::VmxExit;
119119
use x86defs::vmx::VmxExitBasic;
@@ -2915,7 +2915,7 @@ impl UhProcessor<'_, TdxBacked> {
29152915

29162916
struct TdxApicClient<'a, T> {
29172917
partition: &'a UhPartitionInner,
2918-
apic_page: &'a mut ApicPage,
2918+
apic_page: &'a mut VmxApicPage,
29192919
dev: &'a T,
29202920
vmtime: &'a VmTimeAccess,
29212921
vtl: GuestVtl,
@@ -2952,7 +2952,7 @@ impl<T: CpuIo> ApicClient for TdxApicClient<'_, T> {
29522952
}
29532953
}
29542954

2955-
fn pull_apic_offload(page: &mut ApicPage) -> ([u32; 8], [u32; 8]) {
2955+
fn pull_apic_offload(page: &mut VmxApicPage) -> ([u32; 8], [u32; 8]) {
29562956
let mut irr = [0; 8];
29572957
let mut isr = [0; 8];
29582958
for (((irr, page_irr), isr), page_isr) in irr

vm/x86/x86defs/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ open_enum.workspace = true
1111

1212
arbitrary = { workspace = true, optional = true }
1313
bitfield-struct.workspace = true
14+
static_assertions.workspace = true
1415
zerocopy.workspace = true
1516
[lints]
1617
workspace = true

vm/x86/x86defs/src/lib.rs

+7
Original file line numberDiff line numberDiff line change
@@ -482,3 +482,10 @@ pub struct X86xMcgStatusRegister {
482482
#[bits(61)]
483483
pub reserved0: u64,
484484
}
485+
486+
#[repr(C)]
487+
#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
488+
pub struct ApicRegister {
489+
pub value: u32,
490+
_reserved: [u32; 3],
491+
}

vm/x86/x86defs/src/snp.rs

+48
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33

44
//! AMD SEV-SNP specific definitions.
55
6+
use crate::ApicRegister;
67
use bitfield_struct::bitfield;
8+
use static_assertions::const_assert_eq;
79
use zerocopy::FromBytes;
810
use zerocopy::Immutable;
911
use zerocopy::IntoBytes;
@@ -414,6 +416,52 @@ pub struct SevVmsa {
414416
pub ymm_registers: [SevXmmRegister; 16],
415417
}
416418

419+
#[repr(C)]
420+
#[derive(Debug, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
421+
/// Structure representing the SEV-ES AVIC backing page.
422+
/// Specification: "AMD64 PPR Vol3 System Programming", 15.29.3 AVIC Backing Page.
423+
pub struct SevAvicPage {
424+
pub reserved_0: [ApicRegister; 2],
425+
pub id: ApicRegister,
426+
pub version: ApicRegister,
427+
pub reserved_4: [ApicRegister; 4],
428+
pub tpr: ApicRegister,
429+
pub apr: ApicRegister,
430+
pub ppr: ApicRegister,
431+
pub eoi: ApicRegister,
432+
pub rrd: ApicRegister,
433+
pub ldr: ApicRegister,
434+
pub dfr: ApicRegister,
435+
pub svr: ApicRegister,
436+
pub isr: [ApicRegister; 8],
437+
pub tmr: [ApicRegister; 8],
438+
pub irr: [ApicRegister; 8],
439+
pub esr: ApicRegister,
440+
pub reserved_29: [ApicRegister; 6],
441+
pub lvt_cmci: ApicRegister,
442+
pub icr: [ApicRegister; 2],
443+
pub lvt_timer: ApicRegister,
444+
pub lvt_thermal: ApicRegister,
445+
pub lvt_pmc: ApicRegister,
446+
pub lvt_lint0: ApicRegister,
447+
pub lvt_lint1: ApicRegister,
448+
pub lvt_error: ApicRegister,
449+
pub timer_icr: ApicRegister,
450+
pub timer_ccr: ApicRegister,
451+
pub reserved_3a: [ApicRegister; 4],
452+
pub timer_dcr: ApicRegister,
453+
pub self_ipi: ApicRegister,
454+
pub eafr: ApicRegister,
455+
pub eacr: ApicRegister,
456+
pub seoi: ApicRegister,
457+
pub reserved_44: [ApicRegister; 0x5],
458+
pub ier: [ApicRegister; 8],
459+
pub ei_lv_tr: [ApicRegister; 3],
460+
pub reserved_54: [ApicRegister; 0xad],
461+
}
462+
463+
const_assert_eq!(size_of::<SevAvicPage>(), 4096);
464+
417465
// Info codes for the GHCB MSR protocol.
418466
open_enum::open_enum! {
419467
pub enum GhcbInfo: u64 {

vm/x86/x86defs/src/vmx.rs

+5-8
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
66
// TODO: move VMX defs somewhere?
77

8+
use crate::ApicRegister;
89
use bitfield_struct::bitfield;
910
use open_enum::open_enum;
11+
use static_assertions::const_assert_eq;
1012
use zerocopy::FromBytes;
1113
use zerocopy::Immutable;
1214
use zerocopy::IntoBytes;
@@ -379,16 +381,9 @@ pub struct SecondaryProcessorControls {
379381
pub instruction_timeout: bool,
380382
}
381383

382-
#[repr(C)]
383-
#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
384-
pub struct ApicRegister {
385-
pub value: u32,
386-
_reserved: [u32; 3],
387-
}
388-
389384
#[repr(C)]
390385
#[derive(Debug, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
391-
pub struct ApicPage {
386+
pub struct VmxApicPage {
392387
pub reserved_0: [ApicRegister; 2],
393388
pub id: ApicRegister,
394389
pub version: ApicRegister,
@@ -421,3 +416,5 @@ pub struct ApicPage {
421416
pub reserved_3f: ApicRegister,
422417
pub reserved_40: [ApicRegister; 0xc0],
423418
}
419+
420+
const_assert_eq!(size_of::<VmxApicPage>(), 4096);

0 commit comments

Comments
 (0)