Skip to content

Commit

Permalink
virt_support_apic: scan IRR for self IPIs and timers (microsoft#331)
Browse files Browse the repository at this point in the history
When an interrupt is delivered locally (for self IPIs and timers), we
don't notify the partition to wake the processor, and so we never scan
IRR to find and deliver these interrupts.

Fix this.
  • Loading branch information
jstarks authored Nov 14, 2024
1 parent b30c2e4 commit f130ef8
Showing 1 changed file with 10 additions and 4 deletions.
14 changes: 10 additions & 4 deletions vmm_core/virt_support_apic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ pub struct LocalApic {
active_auto_eoi: bool,
is_offloaded: bool,
needs_offload_reeval: bool,
scan_irr: bool,

stats: Stats,
}
Expand Down Expand Up @@ -397,6 +398,7 @@ impl LocalApicSet {
active_auto_eoi: false,
needs_offload_reeval: false,
is_offloaded: false,
scan_irr: false,
stats: Stats::default(),
};
apic.reset();
Expand Down Expand Up @@ -1029,7 +1031,7 @@ impl<T: ApicClient> LocalApicAccess<'_, T> {
}
ApicRegister::SELF_IPI if self.apic.x2apic_enabled() => {
self.apic.stats.self_ipi.increment();
self.apic.shared.request_interrupt(
self.apic.scan_irr |= self.apic.shared.request_interrupt(
self.apic.software_enabled(),
DeliveryMode::FIXED,
value as u8,
Expand Down Expand Up @@ -1108,7 +1110,7 @@ impl<T: ApicClient> LocalApicAccess<'_, T> {
}
DestinationShorthand::SELF => {
self.apic.stats.self_ipi.increment();
self.apic.shared.request_interrupt(
self.apic.scan_irr |= self.apic.shared.request_interrupt(
self.apic.software_enabled(),
delivery_mode,
icr.vector(),
Expand Down Expand Up @@ -1143,6 +1145,7 @@ impl<T: ApicClient> LocalApicAccess<'_, T> {

impl SharedState {
/// Returns true if the VP should be woken up to scan the APIC.
#[must_use]
fn request_interrupt(
&self,
software_enabled: bool,
Expand Down Expand Up @@ -1457,7 +1460,7 @@ impl LocalApic {
}

let mut r = self.flush();
if scan_irr {
if scan_irr || self.scan_irr {
self.pull_irr();
}
if !self.is_offloaded {
Expand Down Expand Up @@ -1649,7 +1652,7 @@ impl LocalApic {
let lvt = Lvt::from(self.lvt_timer);
if counts >= self.timer_ccr as u64 {
if !lvt.masked() {
self.shared.request_interrupt(
self.scan_irr |= self.shared.request_interrupt(
self.software_enabled(),
DeliveryMode::FIXED,
lvt.vector(),
Expand Down Expand Up @@ -1734,6 +1737,7 @@ impl LocalApic {
timer_dcr,
active_auto_eoi,
needs_offload_reeval,
scan_irr,
is_offloaded: _,
stats: _,
} = self;
Expand All @@ -1750,6 +1754,7 @@ impl LocalApic {
// disabled state.
*irr = [0; 8];
*needs_offload_reeval = false;
*scan_irr = false;
*tmr = [0; 8];
*auto_eoi = [0; 8];
*active_auto_eoi = false;
Expand Down Expand Up @@ -1974,6 +1979,7 @@ impl LocalApic {
}
}
self.recompute_next_irr();
self.scan_irr = false;
}

fn id_register(&self) -> u32 {
Expand Down

0 comments on commit f130ef8

Please sign in to comment.