Re: [EXTERNAL] The problem of KVM checking Alternate Injection guest events
Melody Wang <[email protected]> Mon, 18 Aug 2025 08:45:48 -0700
| Newsgroups | dev.linux.lists.coconut-svsm |
|---|---|
| Message-ID | <[email protected]> |
Hi Jon, Both interrupts are targeted at VMPL2. Vector 33 is IOAPIC device interrupt, and 236 is APIC timer interrupt. The problem is, I think, not multiple interrupts injection - this is just one of the incarnations. The problem as I see it now is that after the SVSM injects the interrupt into VMPL2's VintrCtrl, and SVSM switches to run VMPL2 but there is no injection happening. I can see in the traces that the VMPL2 guest runs a couple of times but for some reason, the interrupt in the VintrCtrl cannot get "recognized". That's the only way I can express it because I don't have anything more concrete in the traces - it is just that VMPL2 runs 3 times and that's it. And after that KVM does not run the VMPL2 guest anymore due to a lack of pending events as I explained in the previous email. Thanks, Melody On 8/17/25 9:52 PM, Jon Lange wrote: > I'm skeptical that you can ever make any of this work without the planes implementation in KVM, which is still under development. > > Your example scenario is not clear about what vectors 33 and 236 mean. Are they both interrupts targeted at VMPL 2? Or are they interrupts targeted at the SVSM itself? Or is one interrupt for each VMPL? > > Targeting interrupts at multiple VMPLs is exactly what planes is supposed to enable, and without planes, this is impossible. > > If the interrupts in your example are targeted to VMPL 2, then I would expect this to work because all of the injection required is performed by the SVSM up front, and thus the VMPL 2 state is fully configured in the emulated APIC. When VMPL 2 executes EOI for the first interrupt, then this should cause the SVSM to execute (since EOI is an SVSM call) and SVSM should trigger the second interrupt as part of that processing. > > If the concern is that a second interrupt arrives while VMPL 2 is executing, and that KVM doesn't know that it's supposed to invoke the SVSM for processing, then this is something that requires planes. > > -Jon > > -----Original Message----- > From: Melody Wang <[email protected]> > Sent: Sunday, August 17, 2025 12:50 PM > To: Jon Lange <[email protected]>; Kaplan, David <[email protected]>; Lendacky, Thomas <[email protected]>; Rödel, Jörg <[email protected]> > Cc: [email protected]; Fontenot, Nathan <[email protected]> > Subject: [EXTERNAL] The problem of KVM checking Alternate Injection guest events > > I found one issue when multiple interrupts are being handled in the SVSM but I think it can happen also with a single one. > > The gist of the observation is, that SVSM queues the interrupt into the > VMPL2 guest's VMSA but if the hypervisor doesn't run the VMPL2 guest due to a lack of pending events - it cannot know that - then that interrupt won't get injected, leading to a stop. > > Below are the details: > > Interrupt 33 and 236 are in the doorbell page as multiple interrupts, > > 12796.893994: sev_snp_ai_update_doorbell: vector: 236, no_further: 1, > ai_vector: 80, si_vector: 33 > 12796.893994: sev_snp_ai_update_doorbell: doorbell after: > 12796.893994: dump_hvdb: pending_events: > 12796.893995: dump_hvdb: vector: 80, nmi: 0, mce: 0, no_further_signal: 1 > 12796.893995: dump_hvdb: second_word: 0x200 > 12796.893995: dump_hvdb: VMPL IRQs: 1: 0 2: 1 3: 0 > 12796.893997: dump_hvdb: irq_info: 00 00 00 00 00 00 00 00 00 00 00 00 > 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > 00 00 00 > 12796.893997: print_ext_irq_desc.constprop.0: VMPL2 > 12796.893997: print_ext_irq_desc.constprop.0: ext_word0: 0x4000, > si_vec: 0x0, mult: 1, ext_word1: 0x0, counter: 1226 > 12796.893998: print_ext_irq_desc.constprop.0: irq_vec: 0002 0000 0000 > 0000 0000 0000 0000 0000 0000 0000 0000 0000 1000 0000 > > These two interrupts will be delivered to the SVSM, SVSM consumes these two interrupts, and marks them in the emulated IRR in the SVSM APIC: > > 12796.894031: __kvm_set_msr: guest: post_interrupt(33) > 12796.894036: __kvm_set_msr: guest: post_interrupt(236) > > Then the SVSM injects 236 which is the highest priority interrupt, which will be cleared in the IRR and moved to the ISR until the eoi is sent back from the guest, i.e. the interrupt has been serviced: > > 12796.894046: __kvm_set_msr: guest: deliver_immed: shadow: 0, > irqs_enabled: 0, irq: 236 > 12796.894051: __kvm_set_msr: guest: queue_interrupt(236) into VintrCtrl: > v_irq: 1 > 12796.894055: __kvm_set_msr: guest: Mark ISR, queued: 1, ISR idx: 1, > delivered: 0 > > After 236 is written into the VintrCtrl, the SVSM will switch to VMPL2: > > 12796.894067: sev_handle_vmgexit: vmpl: 0, ghcb_info: 0x16 > 12796.894067: __sev_run_vmpl_vmsa: parent: 0xff445aee23690ac0, current: > 0xff445aee2cb83940, current_vmpl: 0 > 12796.894068: __sev_run_vmpl_vmsa: new_vmpl: 2 > > And VMPL2 runs: > > 12796.894069: svm_vcpu_run: VMPL switch: 0 -> 2, immed_ex: 0 > 12796.894071: svm_vcpu_run: parent: 0xff445aee23690ac0, clear switch_pending > 12796.894071: kvm_exit: vcpu 0 reason npf rip 0x0 info1 > 0x0000000500000014 info2 0x0000000001881000 intr_info 0x00000000 error_code 0x00000000 > 12796.894071: kvm_page_fault: vcpu 0 rip 0x0 address 0x0000000001881000 error_code 0x2000500000014 > 12796.894071: apic_has_pending_timer: lapic_timer.pending: 0 > 12796.894072: kvm_entry: vcpu 0, rip 0x0, vcpu_vmpl 2, current_vmpl 2, target_vmpl 2 > 12796.894073: kvm_exit: vcpu 0 reason npf rip 0x0 info1 > 0x0000000500000006 info2 0x0000000277c1f000 intr_info 0x00000000 error_code 0x00000000 > 12796.894073: kvm_page_fault: vcpu 0 rip 0x0 address 0x0000000277c1f000 error_code 0x2000500000006 > 12796.894074: apic_has_pending_timer: lapic_timer.pending: 0 > 12796.894074: kvm_entry: vcpu 0, rip 0x0, vcpu_vmpl 2, current_vmpl 2, target_vmpl 2 > 12796.894076: kvm_exit: vcpu 0 reason npf rip 0x0 info1 > 0x0000000500000014 info2 0x0000000002297000 intr_info 0x00000000 error_code 0x00000000 > 12796.894076: kvm_page_fault: vcpu 0 rip 0x0 address 0x0000000002297000 error_code 0x2000500000014 > 12796.894077: apic_has_pending_timer: lapic_timer.pending: 0 > 12796.894077: kvm_entry: vcpu 0, rip 0x0, vcpu_vmpl 2, current_vmpl 2, target_vmpl 2 > 12796.894079: kvm_exit: vcpu 0 reason hlt rip 0x0 info1 > 0x0000000000000000 info2 0x0000000000000000 intr_info 0x00000000 error_code 0x00000000 > 12796.894079: apic_has_pending_timer: lapic_timer.pending: 0 > > kvm_vcpu_has_events() is KVM's way to ask whether the guest needs to be run. It did not find there is any event in IRR (encrypted in the SVSM), so KVM does not run VMPL2 anymore even the interrupt is not handled. But in fact 33 is in SVSM's irr now which KVM does not know now, otherwise it will be able to trigger VMPL2 to run. > > 12796.894086: kvm_vcpu_has_events: none > > So KVM needs a way to know whether to run the guests again - SVSM or VMPL2. I don't think we have such a provision in the spec so maybe we need something there. > > Right? > > -- > Thanks, > Melody > -- Thanks, Melody