2008-01-30 15:32:49 +03:00
/*
2009-02-03 20:02:36 +03:00
x86 function call convention , 64 - bit :
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
arguments | callee - saved | extra caller - saved | return
[ callee - clobbered ] | | [ callee - clobbered ] |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
rdi rsi rdx rcx r8 - 9 | rbx rbp [ * ] r12 - 15 | r10 - 11 | rax , rdx [ * * ]
( rsp is obviously invariant across normal function calls . ( gcc can ' merge '
functions when it sees tail - call optimization possibilities ) rflags is
clobbered . Leftover arguments are passed over the stack frame . )
[ * ] In the frame - pointers case rbp is fixed to the stack frame .
[ * * ] for struct return values wider than 64 bits the return convention is a
bit more complex : up to 128 bits width we return small structures
straight in rax , rdx . For structures larger than that ( 3 words or
larger ) the caller puts a pointer to an on - stack return struct
[ allocated in the caller ' s stack frame ] into the first argument - i . e .
into rdi . All other arguments shift up by one in this case .
Fortunately this case is rare in the kernel .
For 32 - bit we have the following conventions - kernel is built with
- mregparm = 3 and - freg - struct - return :
x86 function calling convention , 32 - bit :
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
arguments | callee - saved | extra caller - saved | return
[ callee - clobbered ] | | [ callee - clobbered ] |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
eax edx ecx | ebx edi esi ebp [ * ] | < none > | eax , edx [ * * ]
( here too esp is obviously invariant across normal function calls . eflags
is clobbered . Leftover arguments are passed over the stack frame . )
[ * ] In the frame - pointers case ebp is fixed to the stack frame .
[ * * ] We build with - freg - struct - return , which on 32 - bit means similar
semantics as on 64 - bit : edx can be used for a second return value
( i . e . covering integer and structure sizes up to 64 bits ) - after that
it gets more complex and more expensive : 3 - word or larger struct returns
get done in the caller ' s frame and the pointer to the return struct goes
into regparm0 , i . e . eax - the other arguments shift up and the
function ' s register parameters degenerate to regparm = 2 in essence .
*/
/*
2010-10-19 17:52:26 +04:00
* 64 - bit system call stack frame layout defines and helpers , for
* assembly code ( note that the seemingly unnecessary parentheses
* are to prevent cpp from inserting spaces in expressions that get
* passed to macros ) :
2008-01-30 15:32:49 +03:00
*/
2005-04-17 02:20:36 +04:00
2010-10-19 17:52:26 +04:00
# define R15 (0)
# define R14 (8)
# define R13 (16)
# define R12 (24)
# define RBP (32)
# define RBX (40)
2005-04-17 02:20:36 +04:00
2009-02-03 20:02:36 +03:00
/* arguments: interrupts/non tracing syscalls only save up to here: */
2010-10-19 17:52:26 +04:00
# define R11 (48)
# define R10 (56)
# define R9 (64)
# define R8 (72)
# define RAX (80)
# define RCX (88)
# define RDX (96)
# define RSI (104)
# define RDI (112)
# define ORIG_RAX (120) /* + error_code */
2008-01-30 15:32:49 +03:00
/* end of arguments */
2009-02-03 20:02:36 +03:00
/* cpu exception frame or undefined in case of fast syscall: */
2010-10-19 17:52:26 +04:00
# define RIP (128)
# define CS (136)
# define EFLAGS (144)
# define RSP (152)
# define SS (160)
2008-01-30 15:32:49 +03:00
# define ARGOFFSET R11
# define SWFRAME ORIG_RAX
2005-04-17 02:20:36 +04:00
2008-01-30 15:32:49 +03:00
. macro SAVE_ARGS addskip = 0 , norcx = 0 , nor891011 = 0
subq $ 9 * 8 + \ addskip , % rsp
2005-04-17 02:20:36 +04:00
CFI_ADJUST_CFA_OFFSET 9 * 8 + \ addskip
2008-01-30 15:32:49 +03:00
movq % rdi , 8 * 8 ( % rsp )
CFI_REL_OFFSET rdi , 8 * 8
movq % rsi , 7 * 8 ( % rsp )
CFI_REL_OFFSET rsi , 7 * 8
movq % rdx , 6 * 8 ( % rsp )
CFI_REL_OFFSET rdx , 6 * 8
2005-04-17 02:20:36 +04:00
. if \ norcx
. else
2008-01-30 15:32:49 +03:00
movq % rcx , 5 * 8 ( % rsp )
CFI_REL_OFFSET rcx , 5 * 8
2005-04-17 02:20:36 +04:00
. endif
2008-01-30 15:32:49 +03:00
movq % rax , 4 * 8 ( % rsp )
CFI_REL_OFFSET rax , 4 * 8
2005-04-17 02:20:36 +04:00
. if \ nor891011
. else
2008-01-30 15:32:49 +03:00
movq % r8 , 3 * 8 ( % rsp )
CFI_REL_OFFSET r8 , 3 * 8
movq % r9 , 2 * 8 ( % rsp )
CFI_REL_OFFSET r9 , 2 * 8
movq % r10 , 1 * 8 ( % rsp )
CFI_REL_OFFSET r10 , 1 * 8
movq % r11 , ( % rsp )
CFI_REL_OFFSET r11 , 0 * 8
2005-04-17 02:20:36 +04:00
. endif
. endm
2010-10-19 17:52:26 +04:00
# define ARG_SKIP (9*8)
2008-01-30 15:32:49 +03:00
. macro RESTORE_ARGS skiprax = 0 , addskip = 0 , skiprcx = 0 , skipr11 = 0 , \
skipr8910 = 0 , skiprdx = 0
2005-04-17 02:20:36 +04:00
. if \ skipr11
. else
2008-01-30 15:32:49 +03:00
movq ( % rsp ) , % r11
2005-09-12 20:49:24 +04:00
CFI_RESTORE r11
2005-04-17 02:20:36 +04:00
. endif
. if \ skipr8910
. else
2008-01-30 15:32:49 +03:00
movq 1 * 8 ( % rsp ) , % r10
2005-09-12 20:49:24 +04:00
CFI_RESTORE r10
2008-01-30 15:32:49 +03:00
movq 2 * 8 ( % rsp ) , % r9
2005-09-12 20:49:24 +04:00
CFI_RESTORE r9
2008-01-30 15:32:49 +03:00
movq 3 * 8 ( % rsp ) , % r8
2005-09-12 20:49:24 +04:00
CFI_RESTORE r8
2005-04-17 02:20:36 +04:00
. endif
. if \ skiprax
. else
2008-01-30 15:32:49 +03:00
movq 4 * 8 ( % rsp ) , % rax
2005-09-12 20:49:24 +04:00
CFI_RESTORE rax
2005-04-17 02:20:36 +04:00
. endif
. if \ skiprcx
. else
2008-01-30 15:32:49 +03:00
movq 5 * 8 ( % rsp ) , % rcx
2005-09-12 20:49:24 +04:00
CFI_RESTORE rcx
2005-04-17 02:20:36 +04:00
. endif
. if \ skiprdx
. else
2008-01-30 15:32:49 +03:00
movq 6 * 8 ( % rsp ) , % rdx
2005-09-12 20:49:24 +04:00
CFI_RESTORE rdx
2005-04-17 02:20:36 +04:00
. endif
2008-01-30 15:32:49 +03:00
movq 7 * 8 ( % rsp ) , % rsi
2005-09-12 20:49:24 +04:00
CFI_RESTORE rsi
2008-01-30 15:32:49 +03:00
movq 8 * 8 ( % rsp ) , % rdi
2005-09-12 20:49:24 +04:00
CFI_RESTORE rdi
2005-04-17 02:20:36 +04:00
. if ARG_SKIP + \ addskip > 0
2008-01-30 15:32:49 +03:00
addq $ ARG_SKIP + \ addskip , % rsp
2005-04-17 02:20:36 +04:00
CFI_ADJUST_CFA_OFFSET - ( ARG_SKIP + \ addskip )
. endif
2008-01-30 15:32:49 +03:00
. endm
2005-04-17 02:20:36 +04:00
2008-07-09 13:38:07 +04:00
. macro LOAD_ARGS offset , skiprax = 0
2008-01-30 15:32:49 +03:00
movq \ offset ( % rsp ) , % r11
movq \ offset + 8 ( % rsp ) , % r10
movq \ offset + 16 ( % rsp ) , % r9
movq \ offset + 24 ( % rsp ) , % r8
movq \ offset + 40 ( % rsp ) , % rcx
movq \ offset + 48 ( % rsp ) , % rdx
movq \ offset + 56 ( % rsp ) , % rsi
movq \ offset + 64 ( % rsp ) , % rdi
2008-07-09 13:38:07 +04:00
. if \ skiprax
. else
2008-01-30 15:32:49 +03:00
movq \ offset + 72 ( % rsp ) , % rax
2008-07-09 13:38:07 +04:00
. endif
2005-04-17 02:20:36 +04:00
. endm
2008-01-30 15:32:49 +03:00
2010-10-19 17:52:26 +04:00
# define REST_SKIP (6*8)
2008-01-30 15:32:49 +03:00
2005-04-17 02:20:36 +04:00
. macro SAVE_REST
2008-01-30 15:32:49 +03:00
subq $ REST_SKIP , % rsp
2005-04-17 02:20:36 +04:00
CFI_ADJUST_CFA_OFFSET REST_SKIP
2008-01-30 15:32:49 +03:00
movq % rbx , 5 * 8 ( % rsp )
CFI_REL_OFFSET rbx , 5 * 8
movq % rbp , 4 * 8 ( % rsp )
CFI_REL_OFFSET rbp , 4 * 8
movq % r12 , 3 * 8 ( % rsp )
CFI_REL_OFFSET r12 , 3 * 8
movq % r13 , 2 * 8 ( % rsp )
CFI_REL_OFFSET r13 , 2 * 8
movq % r14 , 1 * 8 ( % rsp )
CFI_REL_OFFSET r14 , 1 * 8
movq % r15 , ( % rsp )
CFI_REL_OFFSET r15 , 0 * 8
. endm
2005-04-17 02:20:36 +04:00
. macro RESTORE_REST
2008-01-30 15:32:49 +03:00
movq ( % rsp ) , % r15
2005-09-12 20:49:24 +04:00
CFI_RESTORE r15
2008-01-30 15:32:49 +03:00
movq 1 * 8 ( % rsp ) , % r14
2005-09-12 20:49:24 +04:00
CFI_RESTORE r14
2008-01-30 15:32:49 +03:00
movq 2 * 8 ( % rsp ) , % r13
2005-09-12 20:49:24 +04:00
CFI_RESTORE r13
2008-01-30 15:32:49 +03:00
movq 3 * 8 ( % rsp ) , % r12
2005-09-12 20:49:24 +04:00
CFI_RESTORE r12
2008-01-30 15:32:49 +03:00
movq 4 * 8 ( % rsp ) , % rbp
2005-09-12 20:49:24 +04:00
CFI_RESTORE rbp
2008-01-30 15:32:49 +03:00
movq 5 * 8 ( % rsp ) , % rbx
2005-09-12 20:49:24 +04:00
CFI_RESTORE rbx
2008-01-30 15:32:49 +03:00
addq $ REST_SKIP , % rsp
2005-04-17 02:20:36 +04:00
CFI_ADJUST_CFA_OFFSET - ( REST_SKIP )
. endm
2008-01-30 15:32:49 +03:00
2005-04-17 02:20:36 +04:00
. macro SAVE_ALL
SAVE_ARGS
SAVE_REST
. endm
2008-01-30 15:32:49 +03:00
2005-04-17 02:20:36 +04:00
. macro RESTORE_ALL addskip = 0
RESTORE_REST
2008-01-30 15:32:49 +03:00
RESTORE_ARGS 0 , \ addskip
2005-04-17 02:20:36 +04:00
. endm
. macro icebp
. byte 0xf1
. endm