Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion openhcl/virt_mshv_vtl/src/processor/hardware_cvm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1448,7 +1448,7 @@ impl<B: HardwareIsolatedBacking> hv1_hypercall::EnablePartitionVtl
GuestVsmState::NotGuestEnabled => (),
GuestVsmState::Enabled { vtl1: _ } => {
// VTL 1 cannot be already enabled
return Err(HvError::VtlAlreadyEnabled);
return Err(HvError::InvalidVtlState);
}
Comment thread
smalis-msft marked this conversation as resolved.
}

Expand Down
2 changes: 1 addition & 1 deletion opentmk/src/platform/hyperv/arch/hypercall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ impl HvCall {

let output = self.dispatch_hvcall(hvdef::HypercallCode::HvCallEnablePartitionVtl, None);
match output.result() {
Ok(()) | Err(hvdef::HvError::VtlAlreadyEnabled) => Ok(()),
Ok(()) | Err(hvdef::HvError::InvalidVtlState) => Ok(()),
Comment thread
smalis-msft marked this conversation as resolved.
err => err,
}
}
Expand Down
51 changes: 47 additions & 4 deletions vmm_core/virt_whp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,26 @@ impl Vplc {
start_vp_context: Default::default(),
}
}

/// Resets the pending per-VTL VP signals to the initial state from `Vplc::new`.
///
/// This is used when resetting the partition or scrubbing a VTL, so that
/// the freshly-reinitialized VTL does not observe stale events queued
/// before the reset.
fn reset(&self) {
let Self {
message_queues,
check_queues,
extint_pending,
start_vp_context,
start_vp,
} = self;
message_queues.clear();
check_queues.store(false, Ordering::Relaxed);
extint_pending.store(false, Ordering::Relaxed);
*start_vp_context.lock() = None;
start_vp.store(false, Ordering::Relaxed);
}
}

impl<'a> WhpVpRef<'a> {
Expand Down Expand Up @@ -1642,13 +1662,18 @@ impl<'p> virt::Processor for WhpProcessor<'p> {
let is_bsp = self.inner.vp_info.base.is_bsp();
self.state.reset(false, is_bsp);

// For each enabled VTL: apply arch fixups that WHP doesn't handle
// and clear any pending `start_vp_context` (via `finish_reset`),
// then clear stale pending per-VTL VP signal flags (via
// `Vplc::reset`).
Comment thread
smalis-msft marked this conversation as resolved.
// VTL0 is always present.
self.finish_reset(Vtl::Vtl0);
self.vplc(Vtl::Vtl0).message_queues.clear();
self.vplc(Vtl::Vtl0).reset();
if self.state.vtls.vtl2.is_some() {
self.finish_reset(Vtl::Vtl2);
self.vplc(Vtl::Vtl2).message_queues.clear();
self.vplc(Vtl::Vtl2).reset();
Comment thread
smalis-msft marked this conversation as resolved.
}
self.inner.vtl2_wake.store(false, Ordering::Relaxed);

if cfg!(debug_assertions) {
let vp_info = &self.inner.vp_info;
Expand All @@ -1663,11 +1688,29 @@ impl<'p> virt::Processor for WhpProcessor<'p> {
fn scrub(&mut self, vtl: Vtl) -> Result<(), impl std::error::Error + Send + Sync + 'static> {
assert_eq!(vtl, Vtl::Vtl2);
let is_bsp = self.inner.vp_info.base.is_bsp();

// Reset per-VP VTL2-enable state on non-BSP VPs. The new VTL2
// will re-issue `HvCallEnableVpVtl` on each AP to program its startup
// context (RIP/RSP/CR3/GDT/IDT). Clear VTL2 from `enabled_vtls`
// before `state.reset` so that `runnable_vtls` and `active_vtl` are
// derived from the post-scrub set rather than the pre-scrub one.
if !is_bsp {
self.inner.vtl2_enable.store(false, Ordering::Relaxed);
self.state.enabled_vtls.clear(Vtl::Vtl2);
}

self.state.reset(true, is_bsp);

// Scrub only resets VTL2.
// Scrub only resets VTL2. Reset the Vplc to clear any stale pending
// signals (message queue notifications, external interrupts, start-VP
// requests, etc.) -- the hypervisor zeroes the equivalent per-VTL
// activity flags during a VTL scrub.
self.finish_reset(Vtl::Vtl2);
self.vplc(Vtl::Vtl2).message_queues.clear();
self.vplc(Vtl::Vtl2).reset();

// Clear any pending VTL2 wake signal, since VTL2 is now back in
// startup suspend and any prior wake request is stale.
self.inner.vtl2_wake.store(false, Ordering::Relaxed);

if cfg!(debug_assertions) {
let vp_info = &self.inner.vp_info;
Expand Down
Loading