Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

x86_64 align stack and recover without saving registers

I'm writing interrupt handling routines for x86_64. The ABI specifies that before calling a C function I must align the stack to 16 bytes. The x86_64 ISA specifies that on entry to an ISR, my stack is 8 byte aligned. I need to align my stack pointer to 16 bytes therefore. The issue is that on return from my C function, I must recover the (potentially) unaligned stack pointer so that I can return from my interrupt correctly.

I wonder if there is a way to do this without using a general purpose register?

like image 903
dschatz Avatar asked Mar 06 '12 21:03

dschatz


1 Answers

Here's my solution to the question as put:

pushq %rsp
pushq (%rsp)
andq $-0x10, %rsp
    call function
movq 8(%rsp), %rsp

The two pushes leave the stack with the same alignment it had originally, and a copy of the original %rsp at (%rsp) and 8(%rsp). The andq then aligns the stack - if it was already 16 byte aligned nothing changes, if it was 8 byte aligned then it subtracts 8 from %rsp, meaning that the original %rsp is now at 8(%rsp) and 16(%rsp). So we can unconditionally restore it from 8(%rsp).

like image 81
caf Avatar answered Oct 06 '22 00:10

caf