Skip to content

Commit 40aff86

Browse files
authored
virt_mshv_vtl: Cleanup cross-vtl interrupt checking (#1380)
This extra level of indirection is no longer necessary, now that this code lives purely in HardwareIsolatedBacking.
1 parent 905373e commit 40aff86

File tree

4 files changed

+93
-97
lines changed

4 files changed

+93
-97
lines changed

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

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,14 +1745,8 @@ impl<B: HardwareIsolatedBacking> UhProcessor<'_, B> {
17451745
}
17461746

17471747
/// Handle checking for cross-VTL interrupts, preempting VTL 0, and setting
1748-
/// VINA when appropriate. The `is_interrupt_pending` function should return
1749-
/// true if an interrupt of appropriate priority, or an NMI, is pending for
1750-
/// the given VTL. The boolean specifies whether RFLAGS.IF should be checked.
1751-
/// Returns true if interrupt reprocessing is required.
1752-
pub(crate) fn cvm_handle_cross_vtl_interrupts(
1753-
&mut self,
1754-
is_interrupt_pending: impl Fn(&mut Self, GuestVtl, bool) -> bool,
1755-
) -> Result<bool, UhRunVpError> {
1748+
/// VINA when appropriate. Returns true if interrupt reprocessing is required.
1749+
fn cvm_handle_cross_vtl_interrupts(&mut self, dev: &impl CpuIo) -> Result<bool, UhRunVpError> {
17561750
let cvm_state = self.backing.cvm_state();
17571751

17581752
// If VTL1 is not yet enabled, there is nothing to do.
@@ -1761,7 +1755,8 @@ impl<B: HardwareIsolatedBacking> UhProcessor<'_, B> {
17611755
}
17621756

17631757
// Check for VTL preemption - which ignores RFLAGS.IF
1764-
if cvm_state.exit_vtl == GuestVtl::Vtl0 && is_interrupt_pending(self, GuestVtl::Vtl1, false)
1758+
if cvm_state.exit_vtl == GuestVtl::Vtl0
1759+
&& B::is_interrupt_pending(self, GuestVtl::Vtl1, false, dev)
17651760
{
17661761
self.raise_vtl(GuestVtl::Vtl0, GuestVtl::Vtl1, HvVtlEntryReason::INTERRUPT);
17671762
}
@@ -1770,7 +1765,7 @@ impl<B: HardwareIsolatedBacking> UhProcessor<'_, B> {
17701765

17711766
// Check for VINA
17721767
if self.backing.cvm_state().exit_vtl == GuestVtl::Vtl1
1773-
&& is_interrupt_pending(self, GuestVtl::Vtl0, true)
1768+
&& B::is_interrupt_pending(self, GuestVtl::Vtl0, true, dev)
17741769
{
17751770
let hv = &mut self.backing.cvm_state_mut().hv[GuestVtl::Vtl1];
17761771
let vina = hv.synic.vina();
@@ -2341,7 +2336,8 @@ impl<B: HardwareIsolatedBacking> UhProcessor<'_, B> {
23412336
}
23422337
*first_scan_irr = false;
23432338

2344-
B::handle_cross_vtl_interrupts(self, dev).map_err(VpHaltReason::InvalidVmState)
2339+
self.cvm_handle_cross_vtl_interrupts(dev)
2340+
.map_err(VpHaltReason::InvalidVmState)
23452341
}
23462342

23472343
fn update_synic(&mut self, vtl: GuestVtl, untrusted_synic: bool) {

openhcl/virt_mshv_vtl/src/processor/mod.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -444,12 +444,14 @@ trait HardwareIsolatedBacking: Backing {
444444
/// Vector of the event that is pending injection into the guest state, if
445445
/// valid.
446446
fn pending_event_vector(this: &UhProcessor<'_, Self>, vtl: GuestVtl) -> Option<u8>;
447-
/// Checks interrupt status for all VTLs, and handles cross VTL interrupt preemption and VINA.
448-
/// Returns whether interrupt reprocessing is required.
449-
fn handle_cross_vtl_interrupts(
447+
/// Check if an interrupt of appropriate priority, or an NMI, is pending for
448+
/// the given VTL. `check_rflags` specifies whether RFLAGS.IF should be checked.
449+
fn is_interrupt_pending(
450450
this: &mut UhProcessor<'_, Self>,
451+
vtl: GuestVtl,
452+
check_rflags: bool,
451453
dev: &impl CpuIo,
452-
) -> Result<bool, UhRunVpError>;
454+
) -> bool;
453455
/// Sets the pending exception for the guest state.
454456
///
455457
/// Note that this will overwrite any existing pending exception. It will

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

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -320,44 +320,44 @@ impl HardwareIsolatedBacking for SnpBacked {
320320
.expect("setting intercept control succeeds");
321321
}
322322

323-
fn handle_cross_vtl_interrupts(
323+
fn is_interrupt_pending(
324324
this: &mut UhProcessor<'_, Self>,
325+
vtl: GuestVtl,
326+
check_rflags: bool,
325327
dev: &impl CpuIo,
326-
) -> Result<bool, UhRunVpError> {
327-
this.cvm_handle_cross_vtl_interrupts(|this, vtl, check_rflags| {
328-
let vmsa = this.runner.vmsa_mut(vtl);
329-
if vmsa.event_inject().valid()
330-
&& vmsa.event_inject().interruption_type() == x86defs::snp::SEV_INTR_TYPE_NMI
331-
{
332-
return true;
333-
}
328+
) -> bool {
329+
let vmsa = this.runner.vmsa_mut(vtl);
330+
if vmsa.event_inject().valid()
331+
&& vmsa.event_inject().interruption_type() == x86defs::snp::SEV_INTR_TYPE_NMI
332+
{
333+
return true;
334+
}
334335

335-
let vmsa_priority = vmsa.v_intr_cntrl().priority() as u32;
336-
let lapic = &mut this.backing.cvm.lapics[vtl].lapic;
337-
let ppr = lapic
338-
.access(&mut SnpApicClient {
339-
partition: this.partition,
340-
vmsa,
341-
dev,
342-
vmtime: &this.vmtime,
343-
vtl,
344-
})
345-
.get_ppr();
346-
let ppr_priority = ppr >> 4;
347-
if vmsa_priority <= ppr_priority {
348-
return false;
349-
}
336+
let vmsa_priority = vmsa.v_intr_cntrl().priority() as u32;
337+
let lapic = &mut this.backing.cvm.lapics[vtl].lapic;
338+
let ppr = lapic
339+
.access(&mut SnpApicClient {
340+
partition: this.partition,
341+
vmsa,
342+
dev,
343+
vmtime: &this.vmtime,
344+
vtl,
345+
})
346+
.get_ppr();
347+
let ppr_priority = ppr >> 4;
348+
if vmsa_priority <= ppr_priority {
349+
return false;
350+
}
350351

351-
let vmsa = this.runner.vmsa_mut(vtl);
352-
if (check_rflags && !RFlags::from_bits(vmsa.rflags()).interrupt_enable())
353-
|| vmsa.v_intr_cntrl().intr_shadow()
354-
|| !vmsa.v_intr_cntrl().irq()
355-
{
356-
return false;
357-
}
352+
let vmsa = this.runner.vmsa_mut(vtl);
353+
if (check_rflags && !RFlags::from_bits(vmsa.rflags()).interrupt_enable())
354+
|| vmsa.v_intr_cntrl().intr_shadow()
355+
|| !vmsa.v_intr_cntrl().irq()
356+
{
357+
return false;
358+
}
358359

359-
true
360-
})
360+
true
361361
}
362362

363363
fn untrusted_synic_mut(&mut self) -> Option<&mut ProcessorSynic> {

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

Lines changed: 47 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -657,63 +657,61 @@ impl HardwareIsolatedBacking for TdxBacked {
657657
);
658658
}
659659

660-
fn handle_cross_vtl_interrupts(
660+
fn is_interrupt_pending(
661661
this: &mut UhProcessor<'_, Self>,
662+
vtl: GuestVtl,
663+
check_rflags: bool,
662664
dev: &impl CpuIo,
663-
) -> Result<bool, UhRunVpError> {
664-
this.cvm_handle_cross_vtl_interrupts(|this, vtl, check_rflags| {
665-
let backing_vtl = &this.backing.vtls[vtl];
666-
if backing_vtl.interruption_information.valid()
667-
&& backing_vtl.interruption_information.interruption_type() == INTERRUPT_TYPE_NMI
668-
{
669-
return true;
670-
}
665+
) -> bool {
666+
let backing_vtl = &this.backing.vtls[vtl];
667+
if backing_vtl.interruption_information.valid()
668+
&& backing_vtl.interruption_information.interruption_type() == INTERRUPT_TYPE_NMI
669+
{
670+
return true;
671+
}
671672

672-
let (vector, ppr) = if this.backing.cvm.lapics[vtl].lapic.is_offloaded() {
673-
let vector = backing_vtl.private_regs.rvi;
674-
let ppr = std::cmp::max(
675-
backing_vtl.private_regs.svi.into(),
676-
this.runner.tdx_apic_page(vtl).tpr.value,
677-
);
678-
(vector, ppr)
679-
} else {
680-
let lapic = &mut this.backing.cvm.lapics[vtl].lapic;
681-
let vector = lapic.next_irr().unwrap_or(0);
682-
let ppr = lapic
683-
.access(&mut TdxApicClient {
684-
partition: this.partition,
685-
apic_page: this.runner.tdx_apic_page_mut(vtl),
686-
dev,
687-
vmtime: &this.vmtime,
688-
vtl,
689-
})
690-
.get_ppr();
691-
(vector, ppr)
692-
};
693-
let vector_priority = (vector as u32) >> 4;
694-
let ppr_priority = ppr >> 4;
673+
let (vector, ppr) = if this.backing.cvm.lapics[vtl].lapic.is_offloaded() {
674+
let vector = backing_vtl.private_regs.rvi;
675+
let ppr = std::cmp::max(
676+
backing_vtl.private_regs.svi.into(),
677+
this.runner.tdx_apic_page(vtl).tpr.value,
678+
);
679+
(vector, ppr)
680+
} else {
681+
let lapic = &mut this.backing.cvm.lapics[vtl].lapic;
682+
let vector = lapic.next_irr().unwrap_or(0);
683+
let ppr = lapic
684+
.access(&mut TdxApicClient {
685+
partition: this.partition,
686+
apic_page: this.runner.tdx_apic_page_mut(vtl),
687+
dev,
688+
vmtime: &this.vmtime,
689+
vtl,
690+
})
691+
.get_ppr();
692+
(vector, ppr)
693+
};
694+
let vector_priority = (vector as u32) >> 4;
695+
let ppr_priority = ppr >> 4;
695696

696-
if vector_priority <= ppr_priority {
697-
return false;
698-
}
697+
if vector_priority <= ppr_priority {
698+
return false;
699+
}
699700

700-
if check_rflags
701-
&& !RFlags::from_bits(backing_vtl.private_regs.rflags).interrupt_enable()
702-
{
703-
return false;
704-
}
701+
if check_rflags && !RFlags::from_bits(backing_vtl.private_regs.rflags).interrupt_enable() {
702+
return false;
703+
}
705704

706-
let interruptibility: Interruptibility = this
707-
.runner
708-
.read_vmcs32(vtl, VmcsField::VMX_VMCS_GUEST_INTERRUPTIBILITY)
709-
.into();
705+
let interruptibility: Interruptibility = this
706+
.runner
707+
.read_vmcs32(vtl, VmcsField::VMX_VMCS_GUEST_INTERRUPTIBILITY)
708+
.into();
710709

711-
if interruptibility.blocked_by_sti() || interruptibility.blocked_by_movss() {
712-
return false;
713-
}
710+
if interruptibility.blocked_by_sti() || interruptibility.blocked_by_movss() {
711+
return false;
712+
}
714713

715-
true
716-
})
714+
true
717715
}
718716

719717
fn untrusted_synic_mut(&mut self) -> Option<&mut ProcessorSynic> {

0 commit comments

Comments
 (0)