Repository: rust
Issue: Tracking issue for the `x86-interrupt` calling convention
Labels: T-lang,B-unstable,C-tracking-issue,S-tracking-needs-summary,F-abi_x86_interrupt,A-hardware-interrupts

## 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

```rust
extern "x86-interrupt" fn handler(stack_frame: ExceptionStackFrame) {…}
```

for interrupts and exceptions without error code and

```rust
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][1], and the corresponding [proposal][2].

[1]: https://reviews.llvm.org/D15567
[2]: http://lists.llvm.org/pipermail/cfe-dev/2015-September/045171.html

## Known issues

- [x] 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 https://github.com/rust-lang/rust/issues/40180#issuecomment-814270159 for more details.
- [ ] LLVM **doesn't preserve MMX and x87 floating point registers** across interrupts. This issue was reported in https://github.com/llvm/llvm-project/issues/26785.
- [x] _(fixed)_ x86-interrupt calling convention leads to **wrong error code** in debug mode (#57270)
- https://github.com/rust-lang/rust/labels/F-abi_x86_interrupt currently shows:
    - [ ] https://github.com/rust-lang/rust/issues/63018
    - [ ] https://github.com/rust-lang/rust/issues/124806
    - [ ] https://github.com/rust-lang/rust/issues/126418
    - [ ] https://github.com/rust-lang/rust/issues/132834
    - [ ] https://github.com/rust-lang/rust/issues/132835
    - [ ] https://github.com/rust-lang/rust/issues/132841

### 64-bit

- [x] 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`](http://x86.renejeschke.de/html/file_module_x86_id_180.html) instructions for saving the `xmm` registers. This issue is tracked as [bug 26413](https://bugs.llvm.org//show_bug.cgi?id=26413).

  _A fix for this problem was submitted in [D30049](https://reviews.llvm.org/D30049) and merged in [rL299383](https://reviews.llvm.org/rL299383)._

- [x] 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](https://reviews.llvm.org/rL295347). Backported in rust-lang/llvm#63._

- [ ] https://github.com/llvm/llvm-project/issues/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 https://github.com/llvm/llvm-project/issues/26851.