Tracking issue for the x86-interrupt
calling convention #40180
Description
Overview
Tracking issue for the x86-interrupt
calling convention, which was added in PR #39832. The feature gate name is abi_x86_interrupt
. This feature will not be considered for stabilization without an RFC.
The x86-interrupt
calling convention can be used for defining interrupt handlers on 32-bit and 64-bit x86 targets. The compiler then uses iret
instead of ret
for returning and ensures that all registers are restored to their original values.
Usage
extern "x86-interrupt" fn handler(stack_frame: ExceptionStackFrame) {…}
for interrupts and exceptions without error code and
extern "x86-interrupt" fn handler_with_err_code(stack_frame: ExceptionStackFrame,
error_code: u64) {…}
for exceptions that push an error code (e.g., page faults or general protection faults). The programmer must ensure that the correct version is used for each interrupt.
For more details see the LLVM PR, and the corresponding proposal.
Known issues
- An earlier version of this description stated that the
ExceptionStackFrame
is passed by reference (instead of by value). This used to work on older LLVM version, but no longer works on LLVM 12. See Tracking issue for thex86-interrupt
calling convention #40180 (comment) for more details. - LLVM doesn't preserve MMX and x87 floating point registers across interrupts. This issue was reported in __attribute__((interrupt)) trashes MMX registers llvm/llvm-project#26785.
- (fixed) x86-interrupt calling convention leads to wrong error code in debug mode (x86-interrupt calling convention leads to wrong error code in debug mode #57270)
-
F-abi_x86_interrupt
currently shows:
- SIGSEGV during compilation of extern x86-interrupt fn with u128 param #63018
- ICE:
used byval ABI for unsized layout
#124806 - ICE:
Tried to make Ignore indirect
#126418 - Directly calling
"x86-interrupt" fn
should be invalid #132834 -
extern "x86-interrupt" fn
allows absurd signatures #132835 - All interrupt ABIs should enforce either
()
or!
as return types #132841
64-bit
-
The x86_64 automatically aligns the stack on a 16-byte boundary when an interrupts occurs in 64-bit mode. However, the CPU pushes an 8-byte error code for some exceptions, which destroys the 16-byte alignment. At the moment, LLVM doesn't handle this case correctly and always assumes a 16-byte alignment. This leads to alignment issues on targets with SSE support, since LLVM uses misaligned
movaps
instructions for saving thexmm
registers. This issue is tracked as bug 26413.A fix for this problem was submitted in D30049 and merged in rL299383.
-
LLVM always tries to backup the
xmm
registers on 64-bit platforms even if the target doesn't support SSE. This leads to invalid opcode exceptions whenever an interrupt handler is invoked.The fix was merged to LLVM trunk in rL295347. Backported in x86 interrupt calling convention: only save xmm registers if the target supports SSE llvm#63.
-
__attribute__((interrupt)) Handlers Dangerously Out of Spec on x86-64 llvm/llvm-project#41189
32-bit
- In 32-bit mode, the CPU performs no stack alignment on interrupts. Thus, the interrupt handler should perform a dynamic stack alignment (i.e.
and esp, 16
). However, LLVM doesn't do that at the moment, which might lead to alignment errors, especially for targets with SSE support. This issue is tracked in interrupt handler calls functions with misaligned stack llvm/llvm-project#26851.
Activity