Skip to content

Commit 85ab7fa

Browse files
committed
cleanup
1 parent d20c2ee commit 85ab7fa

File tree

5 files changed

+201
-228
lines changed

5 files changed

+201
-228
lines changed

Diff for: openhcl/virt_mshv_vtl/src/lib.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,15 @@ struct GuestVsmVpState {
350350
reg_intercept: SecureRegisterInterceptState,
351351
}
352352

353+
impl GuestVsmVpState {
354+
fn new() -> Self {
355+
GuestVsmVpState {
356+
vtl0_exit_pending_event: None,
357+
reg_intercept: Default::default(),
358+
}
359+
}
360+
}
361+
353362
#[cfg(guest_arch = "x86_64")]
354363
#[derive(Inspect)]
355364
/// VP state for CVMs.
@@ -365,7 +374,6 @@ struct UhCvmVpState {
365374
lapics: VtlArray<LapicState, 2>,
366375
/// Guest VSM state for this vp. Some when VTL 1 is enabled.
367376
vtl1: Option<GuestVsmVpState>,
368-
vtl1_reg_intercept: SecureRegisterInterceptState, // TODO: move into vtl 1 state
369377
}
370378

371379
#[cfg(guest_arch = "x86_64")]
@@ -413,13 +421,13 @@ impl UhCvmVpState {
413421
hv,
414422
lapics,
415423
vtl1: None,
416-
vtl1_reg_intercept: Default::default(),
417424
})
418425
}
419426
}
420427

421428
#[cfg(guest_arch = "x86_64")]
422429
#[derive(Inspect, Default)]
430+
/// Configuration of VTL 1 registration for intercepts on certain registers
423431
pub struct SecureRegisterInterceptState {
424432
#[inspect(with = "|x| inspect::AsHex(u64::from(*x))")]
425433
intercept_control: hvdef::HvRegisterCrInterceptControl,

Diff for: openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs

+49-79
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ use virt_support_x86emu::emulate::TranslateGvaSupport;
4646
use virt_support_x86emu::translate::TranslateCachingInfo;
4747
use virt_support_x86emu::translate::TranslationRegisters;
4848
use zerocopy::FromZeros;
49-
use zerocopy::IntoBytes;
5049

5150
impl<T, B: HardwareIsolatedBacking> UhHypercallHandler<'_, '_, T, B> {
5251
fn validate_register_access(
@@ -603,7 +602,11 @@ impl<T, B: HardwareIsolatedBacking> UhHypercallHandler<'_, '_, T, B> {
603602
.with_msr_sysenter_eip_write(true)
604603
.with_msr_sysenter_esp_write(true)
605604
.with_msr_sfmask_write(true)
606-
.with_msr_tsc_aux_write(true);
605+
.with_msr_tsc_aux_write(true)
606+
.with_msr_xss_write(true)
607+
.with_msr_scet_write(true)
608+
.with_msr_pls_ssp_write(true)
609+
.with_msr_interrupt_ssp_table_addr_write(true);
607610

608611
if reg.value.as_u64() & !u64::from(supported_controls) != 0 {
609612
return Err(HvError::InvalidRegisterValue);
@@ -613,21 +616,22 @@ impl<T, B: HardwareIsolatedBacking> UhHypercallHandler<'_, '_, T, B> {
613616
hvdef::HvRegisterCrInterceptControl::from(reg.value.as_u64());
614617

615618
if let virt::IsolationType::Snp = self.vp.partition.isolation {
616-
// TODO: panic if this fails?
617-
self.vp.runner.set_vp_registers_hvcall(
618-
Vtl::Vtl1,
619-
[(
620-
HvX64RegisterName::CrInterceptControl,
621-
u64::from(intercept_control),
622-
)],
623-
)?;
619+
// Intercept control is always managed by the hypervisor, so any request
620+
// here is only opportunistic. Make the request directly with the
621+
// hypervisor. Since intercept control always applies to VTL 1 control of
622+
// VTL 0 state, the VTL 1 intercept control register is set here.
623+
self.vp
624+
.runner
625+
.set_vp_registers_hvcall(
626+
Vtl::Vtl1,
627+
[(
628+
HvX64RegisterName::CrInterceptControl,
629+
u64::from(intercept_control),
630+
)],
631+
)
632+
.expect("setting intercept control succeeds");
624633
}
625634

626-
tracing::info!(
627-
"setting intecept control for vp {}",
628-
self.vp.vp_index().index()
629-
);
630-
631635
self.vp
632636
.backing
633637
.cvm_state_mut()
@@ -650,7 +654,7 @@ impl<T, B: HardwareIsolatedBacking> UhHypercallHandler<'_, '_, T, B> {
650654
vtl1.reg_intercept.cr4_mask = reg.value.as_u64();
651655
}
652656
HvX64RegisterName::CrInterceptIa32MiscEnableMask => {
653-
vtl1.reg_intercept.ia32_misc_enable_mask = reg.value.as_u64(); // TODO is this ever used?
657+
vtl1.reg_intercept.ia32_misc_enable_mask = reg.value.as_u64();
654658
}
655659
_ => unreachable!(),
656660
}
@@ -1029,7 +1033,7 @@ impl<T, B: HardwareIsolatedBacking>
10291033
target_vtl: Vtl,
10301034
vp_context: &hvdef::hypercall::InitialVpContextX64,
10311035
) -> HvResult<()> {
1032-
tracing::info!(
1036+
tracing::debug!(
10331037
vp_index = self.vp.vp_index().index(),
10341038
target_vp,
10351039
?target_vtl,
@@ -1683,10 +1687,7 @@ impl<B: HardwareIsolatedBacking> UhProcessor<'_, B> {
16831687
if vtl == GuestVtl::Vtl1 {
16841688
assert!(*self.cvm_vp_inner().vtl1_enable_called.lock());
16851689
if let InitialVpContextOperation::EnableVpVtl = start_enable_vtl_state.operation {
1686-
self.backing.cvm_state_mut().vtl1 = Some(crate::GuestVsmVpState {
1687-
vtl0_exit_pending_event: None,
1688-
reg_intercept: Default::default(),
1689-
});
1690+
self.backing.cvm_state_mut().vtl1 = Some(crate::GuestVsmVpState::new());
16901691
}
16911692
}
16921693

@@ -1722,15 +1723,9 @@ impl<B: HardwareIsolatedBacking> UhProcessor<'_, B> {
17221723
for (reg, value) in protected_registers {
17231724
if self.cvm_is_protected_register_write(vtl, reg, value) {
17241725
// In this case, it doesn't matter what VTL the calling
1725-
// VP was in, fail the startup. No need to send an
1726+
// VP was in, just fail the startup. No need to send an
17261727
// intercept message.
1727-
//
1728-
// TODO: figure out the correct return error type
1729-
return Err(UhRunVpError::State(
1730-
crate::processor::vp_state::Error::SetRegisters(
1731-
hcl::ioctl::Error::SetRegisters(HvError::AccessDenied),
1732-
),
1733-
));
1728+
return Err(UhRunVpError::StateAccessDenied);
17341729
}
17351730
}
17361731
}
@@ -1877,6 +1872,8 @@ impl<B: HardwareIsolatedBacking> UhProcessor<'_, B> {
18771872
self.backing.cvm_state().vtl1.is_some()
18781873
}
18791874

1875+
/// Returns whether a higher VTL has registered for write intercepts on the
1876+
/// register.
18801877
pub(crate) fn cvm_is_protected_register_write(
18811878
&self,
18821879
vtl: GuestVtl,
@@ -1918,20 +1915,21 @@ impl<B: HardwareIsolatedBacking> UhProcessor<'_, B> {
19181915
false
19191916
}
19201917

1921-
pub(crate) fn cvm_handle_secure_register_write(
1918+
/// Checks if a higher VTL registered for write intercepts on the register,
1919+
/// and sends the intercept as required.
1920+
pub(crate) fn cvm_protect_secure_register_write(
19221921
&mut self,
19231922
vtl: GuestVtl,
19241923
reg: HvX64RegisterName,
19251924
value: u64,
1926-
) {
1927-
if self.cvm_is_protected_register_write(vtl, reg, value) {
1928-
let intercept_message =
1929-
B::generate_register_intercept_message(self, vtl, self.vp_index(), reg, value);
1930-
1931-
let hv_message = hvdef::HvMessage::new(
1932-
hvdef::HvMessageType::HvMessageTypeRegisterIntercept,
1933-
0,
1934-
intercept_message.as_bytes(),
1925+
) -> bool {
1926+
let send_intercept = self.cvm_is_protected_register_write(vtl, reg, value);
1927+
if send_intercept {
1928+
let intercept_message = B::generate_intercept_message(
1929+
self,
1930+
vtl,
1931+
self.vp_index(),
1932+
crate::processor::InterceptMessageType::Register { reg, value },
19351933
);
19361934

19371935
tracing::debug!(
@@ -1943,42 +1941,16 @@ impl<B: HardwareIsolatedBacking> UhProcessor<'_, B> {
19431941
self.inner.post_message(
19441942
GuestVtl::Vtl1,
19451943
hvdef::HV_SYNIC_INTERCEPTION_SINT_INDEX,
1946-
&hv_message,
1944+
&intercept_message,
19471945
);
1948-
1949-
// Once the intercept message has been posted, no further
1950-
// processing is required. Do not advance the instruction
1951-
// pointer here, since the instruction pointer must continue to
1952-
// point to the instruction that generated the intercept.
1953-
1954-
return;
19551946
}
19561947

1957-
match reg {
1958-
HvX64RegisterName::Cr0 => {
1959-
B::set_cr0(self, vtl, value);
1960-
}
1961-
HvX64RegisterName::Cr4 => {
1962-
B::set_cr4(self, vtl, value);
1963-
}
1964-
HvX64RegisterName::Xfem => self
1965-
.access_state(vtl.into())
1966-
.set_xcr(&virt::vp::Xcr0 { value })
1967-
.unwrap(),
1968-
_ => {
1969-
// If an unexpected intercept has been received, then the host
1970-
// must have enabled an intercept that was not desired. Since
1971-
// the intercept cannot correctly be emulated, this must be
1972-
// treated as a fatal error.
1973-
panic!("unexpected secure register")
1974-
}
1975-
}
1976-
1977-
B::advance_to_next_instruction(self, vtl);
1948+
send_intercept
19781949
}
19791950

1980-
// TODO: maybe rename this, since it does sent the intercept message.
1981-
pub(crate) fn cvm_is_protected_msr_write(&self, vtl: GuestVtl, msr: u32) -> bool {
1951+
/// Checks if a higher VTL registered for write intercepts on the MSR, and
1952+
/// sends the intercept as required.
1953+
pub(crate) fn cvm_protect_msr_write(&self, vtl: GuestVtl, msr: u32) -> bool {
19821954
if vtl == GuestVtl::Vtl0 && self.backing.cvm_state().vtl1.is_some() {
19831955
let configured_intercepts = self
19841956
.backing
@@ -2015,21 +1987,19 @@ impl<B: HardwareIsolatedBacking> UhProcessor<'_, B> {
20151987
};
20161988

20171989
if generate_intercept {
2018-
let intercept_message =
2019-
B::generate_msr_intercept_message(self, vtl, self.vp_index(), msr);
2020-
2021-
let hv_message = hvdef::HvMessage::new(
2022-
hvdef::HvMessageType::HvMessageTypeMsrIntercept,
2023-
0,
2024-
intercept_message.as_bytes(),
1990+
let intercept_message = B::generate_intercept_message(
1991+
self,
1992+
vtl,
1993+
self.vp_index(),
1994+
crate::processor::InterceptMessageType::Msr { msr },
20251995
);
20261996

2027-
tracing::info!(?msr, "sending intercept to vtl 1 for secure msr write");
1997+
tracing::debug!(?msr, "sending intercept to vtl 1 for secure msr write");
20281998

20291999
self.inner.post_message(
20302000
GuestVtl::Vtl1,
20312001
hvdef::HV_SYNIC_INTERCEPTION_SINT_INDEX,
2032-
&hv_message,
2002+
&intercept_message,
20332003
);
20342004

20352005
return true;

Diff for: openhcl/virt_mshv_vtl/src/processor/mod.rs

+10-15
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,11 @@ pub(crate) struct BackingSharedParams {
274274
pub guest_vsm_available: bool,
275275
}
276276

277+
enum InterceptMessageType {
278+
Register { reg: HvX64RegisterName, value: u64 },
279+
Msr { msr: u32 },
280+
}
281+
277282
/// Trait for processor backings that have hardware isolation support.
278283
#[cfg(guest_arch = "x86_64")]
279284
trait HardwareIsolatedBacking: Backing {
@@ -309,27 +314,15 @@ trait HardwareIsolatedBacking: Backing {
309314
event: hvdef::HvX64PendingExceptionEvent,
310315
);
311316

312-
fn generate_register_intercept_message(
313-
this: &UhProcessor<'_, Self>,
314-
vtl: GuestVtl,
315-
vp_index: VpIndex,
316-
reg: HvX64RegisterName,
317-
value: u64,
318-
) -> hvdef::HvX64RegisterInterceptMessage;
319-
320-
fn generate_msr_intercept_message(
317+
fn generate_intercept_message(
321318
this: &UhProcessor<'_, Self>,
322319
vtl: GuestVtl,
323320
vp_index: VpIndex,
324-
msr: u32,
325-
) -> hvdef::HvX64MsrInterceptMessage;
321+
message_type: InterceptMessageType,
322+
) -> HvMessage;
326323

327324
fn cr0(this: &UhProcessor<'_, Self>, vtl: GuestVtl) -> u64;
328325
fn cr4(this: &UhProcessor<'_, Self>, vtl: GuestVtl) -> u64;
329-
330-
fn set_cr0(this: &mut UhProcessor<'_, Self>, vtl: GuestVtl, cr0: u64);
331-
fn set_cr4(this: &mut UhProcessor<'_, Self>, vtl: GuestVtl, cr4: u64);
332-
fn advance_to_next_instruction(this: &mut UhProcessor<'_, Self>, vtl: GuestVtl);
333326
}
334327

335328
#[cfg_attr(guest_arch = "aarch64", expect(dead_code))]
@@ -468,6 +461,8 @@ pub enum UhRunVpError {
468461
/// Handling an intercept on behalf of an invalid Lower VTL
469462
#[error("invalid intercepted vtl {0:?}")]
470463
InvalidInterceptedVtl(u8),
464+
#[error("access to state blocked by another vtl")]
465+
StateAccessDenied,
471466
}
472467

473468
/// Underhill processor run error

0 commit comments

Comments
 (0)