x86/fred: Send an EVENT_CHECK IPI on exit from NMI

Returning from an NMI which hits guest context needs special casing in FRED
mode just like it does in IDT mode.

Break nmi_exit_to_guest() out of handle_ist_exception(), and use it in
entry_FRED_R3() also.

Expand the comment a little, and invert the conditional jump to
compat_restore_all_guest() to avoid needing an #else clause for CONFIG_PV32.

Fixes: 87cfcbe9f0 ("x86/pv: Guest exception handling in FRED mode")
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
master commit: 76fc776392
master date: 2026-06-25 11:08:02 +0100
This commit is contained in:
Andrew Cooper authored and Jan Beulich committed 2026-06-30 14:55:45 +02:00
1 parent 5597c9c564
commit bc13e99ec6
2 files changed
+36 -19

No files matched your search

+6
View File
@@ -20,6 +20,12 @@ FUNC(entry_FRED_R3, 4096)
GET_STACK_END(14)
movq STACK_CPUINFO_FIELD(current_vcpu)(%r14), %rbx
/* NMIs need special handling on return to guest. */
movzbl UREGS_ss + 6(%rsp), %eax
and $0xf, %eax
cmp $X86_ET_NMI, %al
je nmi_exit_to_guest
jmp test_all_events
#else
BUG /* Not Reached */
+30 -19
View File
@@ -147,6 +147,35 @@ process_trap:
jmp test_all_events
END(switch_to_kernel)
/*
* When returning to guest from an NMI, we must execute an IRET/ERETU to
* re-enable NMIs, and must not process softirqs which can e.g. schedule
* rather than returning to guest context.
*
* If a softirq is pending, send ourselves an EVENT_CHECK IPI to compensate.
* This will cause softirq processing to occur upon leaving NMI context.
*
* %rbx: struct vcpu, %r14 stack_end
*/
FUNC(nmi_exit_to_guest)
mov STACK_CPUINFO_FIELD(processor_id)(%r14), %eax
shl $IRQSTAT_shift, %eax
lea irq_stat + IRQSTAT_softirq_pending(%rip), %rcx
cmpl $0, (%rcx, %rax, 1)
je 1f
mov $EVENT_CHECK_VECTOR, %edi
call send_IPI_self
1:
/* For restore_all_guest. */
mov STACK_CPUINFO_FIELD(current_vcpu)(%r14), %rbx
#ifdef CONFIG_PV32
mov VCPU_domain(%rbx), %rax
cmpb $0, DOMAIN_is_32bit_pv(%rax)
jne compat_restore_all_guest
#endif
jmp restore_all_guest
END(nmi_exit_to_guest)
.section .text.entry, "ax", @progbits
/* %rbx: struct vcpu, interrupts disabled */
@@ -1193,25 +1222,7 @@ FUNC(handle_ist_exception)
#ifdef CONFIG_PV
testb $3,UREGS_cs(%rsp)
jz restore_all_xen
/* Send an IPI to ourselves to cover for the lack of event checking. */
mov STACK_CPUINFO_FIELD(processor_id)(%r14), %eax
shll $IRQSTAT_shift,%eax
leaq irq_stat+IRQSTAT_softirq_pending(%rip),%rcx
cmpl $0,(%rcx,%rax,1)
je 1f
movl $EVENT_CHECK_VECTOR,%edi
call send_IPI_self
1:
/* For restore_all_guest. */
mov STACK_CPUINFO_FIELD(current_vcpu)(%r14), %rbx
#ifdef CONFIG_PV32
movq VCPU_domain(%rbx),%rax
cmpb $0,DOMAIN_is_32bit_pv(%rax)
je restore_all_guest
jmp compat_restore_all_guest
#else
jmp restore_all_guest
#endif
jmp nmi_exit_to_guest
#else
ASSERT_CONTEXT_IS_XEN
jmp restore_all_xen
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.