Rust: Tracking issue for the `x86-interrupt` calling convention

Created on 1 Mar 2017  路  9Comments  路  Source: rust-lang/rust

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

  • LLVM doesn't preserve MMX and x87 floating point registers across interrupts. This issue was reported in bug 26411.
  • ~x86-interrupt calling convention leads to wrong error code in debug mode (#57270)~

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 the xmm registers. This issue is tracked as bug 26413.~ A fix for this problem is 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 rust-lang/llvm#63.

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 bug 26477.
B-unstable C-tracking-issue T-lang

Most helpful comment

If we're going to have an x86-interrupt abi, would it also make sense to have an x86-syscall? Or x86-sysenter?

All 9 comments

If we're going to have an x86-interrupt abi, would it also make sense to have an x86-syscall? Or x86-sysenter?

(D30049 was merged to LLVM trunk on the 3rd of April, for the record.)

@kyrias Thanks for the hint, I updated the issue text. I'll try to create a backport PR in the next few days.

Triage: not aware of any movement stabilizing this.

Personal note: this is one of my favorite rust features :)

Both of the 64-bit issues have long since been fixed, and Rust's minimum LLVM is newer than the fix, so it's just the MMX/x87 floating point and 32-bit issues remaining, which appear to have been untouched since 2017.

@kyrias I updated the issue description. I also added https://github.com/rust-lang/rust/issues/57270, which will be hopefully fixed soon with the LLVM 9 upgrade.

@phil-opp I think this issue can be updated to cross off #57270

On the x87/MMX issue, we should just mandate that to use the interrupt ABI, you have to build the code with target-features of -x87 and -mmx (-mmx could be a default now that MMX support is gone from Rust). It looks like LLVM and GCC just never intend to support saving/restoring the MMX/x87 registers, so it's probably not worth trying to make it work (as nobody should be using those features anyway.

We may also want to similarly disallow all SSE code in interrupt handlers (GCC bans SSE code, Clang allows it), as that might make it easier to make sure we are doing the right thing.

@phil-opp I think this issue can be updated to cross off #57270

Done!

Just came across the following from a conference paper, and thought I would quote here as a data point:

We implement the low-level interrupt entry and exit code in assembly. While Rust provides support for the x86-interrupt function ABI (a way to write a Rust function that takes the x86 interrupt stack frame as an argument), in practice, it is not useful as we need the ability to interpose on the entry and exit from the interrupt, for example, to save all CPU registers.

(section 4.1 of https://www.usenix.org/system/files/osdi20-narayanan_vikram.pdf)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pedrohjordao picture pedrohjordao  路  3Comments

behnam picture behnam  路  3Comments

modsec picture modsec  路  3Comments

Robbepop picture Robbepop  路  3Comments

nikomatsakis picture nikomatsakis  路  3Comments