mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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:76fc776392master date: 2026-06-25 11:08:02 +0100
This commit is contained in:
1 parent
5597c9c564
commit
bc13e99ec6
2 files changed
+36
-19
No files matched your search
@@ -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
@@ -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
|
||||
|
||||