x86: entry_64.S: always allocate complete "struct pt_regs"
Subsystems (2)
v2 cover x86: entry_64.S: always allocate complete "struct pt_regs"
Version 2 of the patchset.
Changes since v1 (mainly in patch 4/6):
= Reverted changes to "partial pt_regs saving" on interrupt path. = Folded PARTIAL_FRAME macro into DEFAULT_FRAME. Patch v1
had a bug (incorrect dwarf debug info generation).
= Corrected more comments.
= Added use of SAVE_* macros to error_entry and save_paranoid. = Added another cleanup rename patch.
TODO:
= error_entry and save_paranoid have different CFI decorations.
At least one of them is likely to be wrong...
= Move save_paranoid closer to the callers.
= "idtentry" macro uses a subroutine to factor out a largish
common code block. "interrupt" macro inlines a similar block every time (~20 instances). Maybe factor it out?
Denys Vlasenko (6):
x86: entry_64.S: delete unused code
x86: open-code register save/restore in trace_hardirqs thunks
x86: entry_64.S: fold SAVE_ARGS_IRQ macro into its sole user
x86: entry_64.S: always allocate complete "struct pt_regs"
x86: mass removal of ARGOFFSET
x86: rename some macros and labels, no code changes
arch/x86/ia32/ia32entry.S | 175 +++++++++-------- arch/x86/include/asm/calling.h | 216 ++++++++++---------- arch/x86/include/asm/irqflags.h | 4 +- arch/x86/include/asm/ptrace.h | 13 +- arch/x86/include/uapi/asm/ptrace-abi.h | 16 +- arch/x86/include/uapi/asm/ptrace.h | 13 +- arch/x86/kernel/entry_64.S | 349 +++++++++++++-------------------- arch/x86/kernel/preempt.S | 16 +- arch/x86/lib/thunk_64.S | 29 ++- 9 files changed, 395 insertions(+), 436 deletions(-)
Signature · 1 line
1.8.1.4
PATCH v2 1/6 x86: entry_64.S: delete unused code
A define, two macros and an unreferenced bit of assembly are gone.
--- arch/x86/include/asm/calling.h | 1 - arch/x86/kernel/entry_64.S | 34 ---------------------------------- 2 files changed, 35 deletions(-)
arch/x86/include/asm/calling.h +0 -1
@@ -83,7 +83,6 @@ For 32-bit we have the following conventions - kernel is built with#define SS 160#define ARGOFFSET R11 -#define SWFRAME ORIG_RAX .macro SAVE_ARGS addskip=0, save_rcx=1, save_r891011=1 subq $9*8+\addskip, %rsp
arch/x86/kernel/entry_64.S +0 -34
@@ -155,27 +155,6 @@ ENDPROC(native_usergs_sysret64) movq \tmp,R11+\offset(%rsp) .endm - .macro FAKE_STACK_FRAME child_rip - /* push in order ss, rsp, eflags, cs, rip */ - xorl %eax, %eax - pushq_cfi $__KERNEL_DS /* ss */ - /*CFI_REL_OFFSET ss,0*/ - pushq_cfi %rax /* rsp */ - CFI_REL_OFFSET rsp,0 - pushq_cfi $(X86_EFLAGS_IF|X86_EFLAGS_FIXED) /* eflags - interrupts on */ - /*CFI_REL_OFFSET rflags,0*/ - pushq_cfi $__KERNEL_CS /* cs */ - /*CFI_REL_OFFSET cs,0*/ - pushq_cfi \child_rip /* rip */ - CFI_REL_OFFSET rip,0 - pushq_cfi %rax /* orig rax */ - .endm - - .macro UNFAKE_STACK_FRAME - addq $8*6, %rsp - CFI_ADJUST_CFA_OFFSET -(6*8) - .endm - /* * initial frame state for interrupts (and exceptions without error code) */
@@ -640,19 +619,6 @@ END(\label) FORK_LIKE vfork FIXED_FRAME stub_iopl, sys_iopl -ENTRY(ptregscall_common) - DEFAULT_FRAME 1 8 /* offset 8: return address */ - RESTORE_TOP_OF_STACK %r11, 8 - movq_cfi_restore R15+8, r15 - movq_cfi_restore R14+8, r14 - movq_cfi_restore R13+8, r13 - movq_cfi_restore R12+8, r12 - movq_cfi_restore RBP+8, rbp - movq_cfi_restore RBX+8, rbx - ret $REST_SKIP /* pop extended registers */ - CFI_ENDPROC -END(ptregscall_common) - ENTRY(stub_execve) CFI_STARTPROC addq $8, %rsp
Signature · 1 line
1.8.1.4
PATCH v2 2/6 x86: open-code register save/restore in trace_hardirqs thunks
In reply to Denys VlasenkoThis is a preparatory patch for change in "struct pt_regs" handling in entry_64.S.
trace_hardirqs thunks were (ab)using a part of pt_regs handling code, namely SAVE_ARGS/RESTORE_ARGS macros, to save/restore registers across C function calls.
Since SAVE_ARGS is going to be changed, open-code
register saving/restoring here.
Incidentally, this removes a bit of dead code:
one SAVE_ARGS was just to emit a CFI annotation,
but it also generated unreachable assembly insns.
--- arch/x86/lib/thunk_64.S | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-)
arch/x86/lib/thunk_64.S +24 -5
@@ -16,10 +16,20 @@ \name: CFI_STARTPROC - /* this one pushes 9 elems, the next one would be %rIP */ - SAVE_ARGS + subq $9*8, %rsp + CFI_ADJUST_CFA_OFFSET 9*8 + movq_cfi rdi, 8*8 + movq_cfi rsi, 7*8 + movq_cfi rdx, 6*8 + movq_cfi rcx, 5*8 + movq_cfi rax, 4*8 + movq_cfi r8, 3*8 + movq_cfi r9, 2*8 + movq_cfi r10, 1*8 + movq_cfi r11, 0*8 .if \put_ret_addr_in_rdi + /* 9*8(%rsp) is return addr on stack */ movq_cfi_restore 9*8, rdi .endif
@@ -38,11 +48,20 @@ THUNK lockdep_sys_exit_thunk,lockdep_sys_exit #endif - /* SAVE_ARGS below is used only for the .cfi directives it contains. */ CFI_STARTPROC - SAVE_ARGS + CFI_ADJUST_CFA_OFFSET 9*8 restore: - RESTORE_ARGS + movq_cfi_restore 0*8, r11 + movq_cfi_restore 1*8, r10 + movq_cfi_restore 2*8, r9 + movq_cfi_restore 3*8, r8 + movq_cfi_restore 4*8, rax + movq_cfi_restore 5*8, rcx + movq_cfi_restore 6*8, rdx + movq_cfi_restore 7*8, rsi + movq_cfi_restore 8*8, rdi + addq 9*8, %rsp + CFI_ADJUST_CFA_OFFSET -9*8 ret CFI_ENDPROC _ASM_NOKPROBE(restore)
Signature · 1 line
1.8.1.4
PATCH v2 3/6 x86: entry_64.S: fold SAVE_ARGS_IRQ macro into its sole user
In reply to Denys VlasenkoNo code changes.
This is a preparatory patch for change in "struct pt_regs" handling.
--- arch/x86/kernel/entry_64.S | 88 ++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 46 deletions(-)
arch/x86/kernel/entry_64.S +42 -46
@@ -218,51 +218,6 @@ ENDPROC(native_usergs_sysret64) CFI_REL_OFFSET r15, R15+\offset .endm -/* save partial stack frame */ - .macro SAVE_ARGS_IRQ - cld - /* start from rbp in pt_regs and jump over */ - movq_cfi rdi, (RDI-RBP) - movq_cfi rsi, (RSI-RBP) - movq_cfi rdx, (RDX-RBP) - movq_cfi rcx, (RCX-RBP) - movq_cfi rax, (RAX-RBP) - movq_cfi r8, (R8-RBP) - movq_cfi r9, (R9-RBP) - movq_cfi r10, (R10-RBP) - movq_cfi r11, (R11-RBP) - - /* Save rbp so that we can unwind from get_irq_regs() */ - movq_cfi rbp, 0 - - /* Save previous stack value */ - movq %rsp, %rsi - - leaq -RBP(%rsp),%rdi /* arg1 for handler */ - testl $3, CS-RBP(%rsi) - je 1f - SWAPGS - /* - * irq_count is used to check if a CPU is already on an interrupt stack - * or not. While this is essentially redundant with preempt_count it is - * a little cheaper to use a separate counter in the PDA (short of - * moving irq_enter into assembly, which would be too much work) - */ -1: incl PER_CPU_VAR(irq_count) - cmovzq PER_CPU_VAR(irq_stack_ptr),%rsp - CFI_DEF_CFA_REGISTER rsi - - /* Store previous stack value */ - pushq %rsi - CFI_ESCAPE 0x0f /* DW_CFA_def_cfa_expression */, 6, \ - 0x77 /* DW_OP_breg7 */, 0, \ - 0x06 /* DW_OP_deref */, \ - 0x08 /* DW_OP_const1u */, SS+8-RBP, \ - 0x22 /* DW_OP_plus */ - /* We entered an interrupt context - irqs are off: */ - TRACE_IRQS_OFF - .endm - ENTRY(save_paranoid) XCPT_FRAME 1 RDI+8 cld
@@ -731,7 +686,48 @@ END(interrupt) /* reserve pt_regs for scratch regs and rbp */ subq $ORIG_RAX-RBP, %rsp CFI_ADJUST_CFA_OFFSET ORIG_RAX-RBP - SAVE_ARGS_IRQ + cld + /* start from rbp in pt_regs and jump over */ + movq_cfi rdi, (RDI-RBP) + movq_cfi rsi, (RSI-RBP) + movq_cfi rdx, (RDX-RBP) + movq_cfi rcx, (RCX-RBP) + movq_cfi rax, (RAX-RBP) + movq_cfi r8, (R8-RBP) + movq_cfi r9, (R9-RBP) + movq_cfi r10, (R10-RBP) + movq_cfi r11, (R11-RBP) + + /* Save rbp so that we can unwind from get_irq_regs() */ + movq_cfi rbp, 0 + + /* Save previous stack value */ + movq %rsp, %rsi + + leaq -RBP(%rsp),%rdi /* arg1 for handler */ + testl $3, CS-RBP(%rsi) + je 1f + SWAPGS + /* + * irq_count is used to check if a CPU is already on an interrupt stack + * or not. While this is essentially redundant with preempt_count it is + * a little cheaper to use a separate counter in the PDA (short of + * moving irq_enter into assembly, which would be too much work) + */ +1: incl PER_CPU_VAR(irq_count) + cmovzq PER_CPU_VAR(irq_stack_ptr),%rsp + CFI_DEF_CFA_REGISTER rsi + + /* Store previous stack value */ + pushq %rsi + CFI_ESCAPE 0x0f /* DW_CFA_def_cfa_expression */, 6, \ + 0x77 /* DW_OP_breg7 */, 0, \ + 0x06 /* DW_OP_deref */, \ + 0x08 /* DW_OP_const1u */, SS+8-RBP, \ + 0x22 /* DW_OP_plus */ + /* We entered an interrupt context - irqs are off: */ + TRACE_IRQS_OFF + call \func .endm
Signature · 1 line
1.8.1.4
PATCH v2 4/6 x86: entry_64.S: always allocate complete "struct pt_regs"
In reply to Denys Vlasenko64-bit code was using six stack slots fewer by not saving/restoring registers which a callee-preserved according to C ABI,
and not allocating space for them.
Only when syscall needed a complete "struct pt_regs",
the complete area was allocated and filled in.
As an additional twist, on interrupt entry a "slightly less truncated pt_regs" trick is used, to make nested interrupt stacks easier to unwind.
This proved to be a source of significant obfuscation and subtle bugs. For example, stub_fork had to pop the return address, extend the struct, save registers, and push return address back. Ugly. ia32_ptregs_common pops return address and "returns" via jmp insn, throwing a wrench into CPU return stack cache.
This patch changes code to always allocate a complete "struct pt_regs". The saving of registers is still done lazily.
"Partial pt_regs" trick on interrupt stack is retained, but with added comments which explain what we are doing, and why. Existing comments are improved.
Macros which manipulate "struct pt_regs" on stack are reworked:ALLOC_PTREGS_ON_STACK allocates the structure.SAVE_C_REGS saves to it those registers which are clobbered by C code. SAVE_EXTRA_REGS saves to it all other registers. Corresponding RESTORE_* and REMOVE_PTREGS_FROM_STACK macros reverse it.
ia32_ptregs_common, stub_fork and friends lost their ugly dance with return pointer.
LOAD_ARGS32 in ia32entry.S now uses symbolic stack offsets instead of magic numbers.
error_entry and save_paranoid now use SAVE_C_REGS + SAVE_EXTRA_REGS instead of having it open-coded yet again.
Misleading and slightly wrong comments in "struct pt_regs" are fixed (four instances).
Patch was run-tested: 64-bit executables, 32-bit executables, strace works.
Timing tests did not show measurable difference in 32-bit and 64-bit syscalls.
--- arch/x86/ia32/ia32entry.S | 47 +++---- arch/x86/include/asm/calling.h | 217 ++++++++++++++++----------------- arch/x86/include/asm/irqflags.h | 4 +- arch/x86/include/asm/ptrace.h | 13 +- arch/x86/include/uapi/asm/ptrace-abi.h | 16 ++- arch/x86/include/uapi/asm/ptrace.h | 13 +- arch/x86/kernel/entry_64.S | 191 +++++++++++------------------ arch/x86/kernel/preempt.S | 16 ++- 8 files changed, 249 insertions(+), 268 deletions(-)
arch/x86/ia32/ia32entry.S +25 -22
@@ -62,12 +62,12 @@ */ .macro LOAD_ARGS32 offset, _r9=0 .if \_r9 - movl \offset+16(%rsp),%r9d + movl \offset+R9(%rsp),%r9d .endif - movl \offset+40(%rsp),%ecx - movl \offset+48(%rsp),%edx - movl \offset+56(%rsp),%esi - movl \offset+64(%rsp),%edi + movl \offset+RCX(%rsp),%ecx + movl \offset+RDX(%rsp),%edx + movl \offset+RSI(%rsp),%esi + movl \offset+RDI(%rsp),%edi movl %eax,%eax /* zero extension */ .endm
@@ -144,7 +144,8 @@ ENTRY(ia32_sysenter_target) CFI_REL_OFFSET rip,0 pushq_cfi %rax cld - SAVE_ARGS 0,1,0 + ALLOC_PTREGS_ON_STACK + SAVE_C_REGS_EXCEPT_R891011 /* no need to do an access_ok check here because rbp has been 32bit zero extended */ ASM_STAC
@@ -172,7 +173,8 @@ sysexit_from_sys_call: andl $~0x200,EFLAGS-R11(%rsp) movl RIP-R11(%rsp),%edx /* User %eip */ CFI_REGISTER rip,rdx - RESTORE_ARGS 0,24,0,0,0,0 + RESTORE_RSI_RDI + REMOVE_PTREGS_FROM_STACK 8*3 xorq %r8,%r8 xorq %r9,%r9 xorq %r10,%r10
@@ -240,13 +242,13 @@ sysenter_tracesys: testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) jz sysenter_auditsys #endif - SAVE_REST + SAVE_EXTRA_REGS CLEAR_RREGS movq $-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ - RESTORE_REST + RESTORE_EXTRA_REGS cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */ jmp sysenter_do_call
@@ -288,7 +290,8 @@ ENTRY(ia32_cstar_target) * disabled irqs and here we enable it straight after entry: */ ENABLE_INTERRUPTS(CLBR_NONE) - SAVE_ARGS 8,0,0 + ALLOC_PTREGS_ON_STACK 8 + SAVE_C_REGS_EXCEPT_RCX_R891011 movl %eax,%eax /* zero extension */ movq %rax,ORIG_RAX-ARGOFFSET(%rsp) movq %rcx,RIP-ARGOFFSET(%rsp)
@@ -325,7 +328,7 @@ cstar_dispatch: jnz sysretl_audit sysretl_from_sys_call: andl $~TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) - RESTORE_ARGS 0,-ARG_SKIP,0,0,0 + RESTORE_RSI_RDI_RDX movl RIP-ARGOFFSET(%rsp),%ecx CFI_REGISTER rip,rcx movl EFLAGS-ARGOFFSET(%rsp),%r11d
@@ -356,13 +359,13 @@ cstar_tracesys: jz cstar_auditsys #endif xchgl %r9d,%ebp - SAVE_REST + SAVE_EXTRA_REGS CLEAR_RREGS 0, r9 movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */ - RESTORE_REST + RESTORE_EXTRA_REGS xchgl %ebp,%r9d cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
@@ -417,7 +420,8 @@ ENTRY(ia32_syscall) cld /* note the registers are not zero extended to the sf. this could be a problem. */ - SAVE_ARGS 0,1,0 + ALLOC_PTREGS_ON_STACK + SAVE_C_REGS_EXCEPT_R891011 orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) jnz ia32_tracesys
@@ -430,16 +434,16 @@ ia32_sysret: movq %rax,RAX-ARGOFFSET(%rsp) ia32_ret_from_sys_call: CLEAR_RREGS -ARGOFFSET - jmp int_ret_from_sys_call + jmp int_ret_from_sys_call -ia32_tracesys: - SAVE_REST +ia32_tracesys: + SAVE_EXTRA_REGS CLEAR_RREGS movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ - RESTORE_REST + RESTORE_EXTRA_REGS cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */ jmp ia32_do_call
@@ -475,7 +479,6 @@ GLOBAL(stub32_clone) ALIGN ia32_ptregs_common: - popq %r11 CFI_ENDPROC CFI_STARTPROC32 simple CFI_SIGNAL_FRAME
@@ -490,9 +493,9 @@ ia32_ptregs_common: /* CFI_REL_OFFSET rflags,EFLAGS-ARGOFFSET*/ CFI_REL_OFFSET rsp,RSP-ARGOFFSET /* CFI_REL_OFFSET ss,SS-ARGOFFSET*/ - SAVE_REST + SAVE_EXTRA_REGS 8 call *%rax - RESTORE_REST - jmp ia32_sysret /* misbalances the return cache */ + RESTORE_EXTRA_REGS 8 + ret CFI_ENDPROC END(ia32_ptregs_common)
arch/x86/include/asm/calling.h +105 -112
247 lines not on this page · raw message
arch/x86/include/asm/irqflags.h +2 -2
@@ -171,9 +171,9 @@ static inline int arch_irqs_disabled(void)#define ARCH_LOCKDEP_SYS_EXIT_IRQ \ TRACE_IRQS_ON; \ sti; \ - SAVE_REST; \ + SAVE_EXTRA_REGS; \ LOCKDEP_SYS_EXIT; \ - RESTORE_REST; \ + RESTORE_EXTRA_REGS; \ cli; \ TRACE_IRQS_OFF;
arch/x86/include/asm/ptrace.h +10 -3
@@ -31,13 +31,17 @@ struct pt_regs { #else /* __i386__ */ struct pt_regs { +/* + * C ABI says these regs are callee-preserved. They aren't saved on kernel entry + * unless syscall needs a complete, fully filled "struct pt_regs". + */ unsigned long r15; unsigned long r14; unsigned long r13; unsigned long r12; unsigned long bp; unsigned long bx; -/* arguments: non interrupts/non tracing syscalls only save up to here*/ +/* These regs are callee-clobbered. Always saved on kernel entry. */ unsigned long r11; unsigned long r10; unsigned long r9;
@@ -47,9 +51,12 @@ struct pt_regs {unsigned long dx;unsigned long si;unsigned long di; +/* +* On syscall entry, this is syscall#. On CPU exception, this is error code. +* On hw interrupt, it's IRQ number: +*/ unsigned long orig_ax; -/* end of arguments */ -/* cpu exception frame or undefined */ +/* Return frame for iretq */ unsigned long ip;unsigned long cs;unsigned long flags;
arch/x86/include/uapi/asm/ptrace-abi.h +11 -5
@@ -25,13 +25,17 @@#else /* __i386__ */ #if defined(__ASSEMBLY__) || defined(__FRAME_OFFSETS) +/* +* C ABI says these regs are callee-preserved. They aren't saved on kernel entry +* unless syscall needs a complete, fully filled "struct pt_regs". +*/ #define R15 0#define R14 8#define R13 16#define R12 24#define RBP 32#define RBX 40 -/* arguments: interrupts/non tracing syscalls only save up to here*/ +/* These regs are callee-clobbered. Always saved on kernel entry. */ #define R11 48#define R10 56#define R9 64
@@ -41,15 +45,17 @@#define RDX 96#define RSI 104#define RDI 112 -#define ORIG_RAX 120/* = ERROR */ -/* end of arguments */ -/* cpu exception frame or undefined in case of fast syscall. */ +/* +* On syscall entry, this is syscall#. On CPU exception, this is error code. +* On hw interrupt, it's IRQ number: +*/ +#define ORIG_RAX 120 +/* Return frame for iretq */ #define RIP 128#define CS 136#define EFLAGS 144#define RSP 152#define SS 160 -#define ARGOFFSET R11#endif /* __ASSEMBLY__ */ /* top of stack page */
arch/x86/include/uapi/asm/ptrace.h +10 -3
@@ -41,13 +41,17 @@ struct pt_regs { #ifndef __KERNEL__ struct pt_regs { +/* + * C ABI says these regs are callee-preserved. They aren't saved on kernel entry + * unless syscall needs a complete, fully filled "struct pt_regs". + */ unsigned long r15; unsigned long r14; unsigned long r13; unsigned long r12; unsigned long rbp; unsigned long rbx; -/* arguments: non interrupts/non tracing syscalls only save up to here*/ +/* These regs are callee-clobbered. Always saved on kernel entry. */ unsigned long r11; unsigned long r10; unsigned long r9;
@@ -57,9 +61,12 @@ struct pt_regs {unsigned long rdx;unsigned long rsi;unsigned long rdi; +/* +* On syscall entry, this is syscall#. On CPU exception, this is error code. +* On hw interrupt, it's IRQ number: +*/ unsigned long orig_rax; -/* end of arguments */ -/* cpu exception frame or undefined */ +/* Return frame for iretq */ unsigned long rip;unsigned long cs;unsigned long eflags;
arch/x86/kernel/entry_64.S +74 -117
431 lines not on this page · raw message
arch/x86/kernel/preempt.S +12 -4
@@ -6,9 +6,13 @@ ENTRY(___preempt_schedule) CFI_STARTPROC - SAVE_ALL + ALLOC_PTREGS_ON_STACK + SAVE_C_REGS + SAVE_EXTRA_REGS call preempt_schedule - RESTORE_ALL + RESTORE_EXTRA_REGS + RESTORE_C_REGS + REMOVE_PTREGS_FROM_STACK ret CFI_ENDPROC
@@ -16,9 +20,13 @@ ENTRY(___preempt_schedule) ENTRY(___preempt_schedule_context) CFI_STARTPROC - SAVE_ALL + ALLOC_PTREGS_ON_STACK + SAVE_C_REGS + SAVE_EXTRA_REGS call preempt_schedule_context - RESTORE_ALL + RESTORE_EXTRA_REGS + RESTORE_C_REGS + REMOVE_PTREGS_FROM_STACK ret CFI_ENDPROC
Signature · 1 line
1.8.1.4
Oleg Nesterov
maintainer[PATCH?] x86: reimplement ___preempt_schedule*() using THUNK helpers
Quoted 24 lines · Denys Vlasenko
arch/x86/kernel/preempt.S +6
-3@@ -6,9 +6,13 @@ ENTRY(___preempt_schedule) CFI_STARTPROC - SAVE_ALL + ALLOC_PTREGS_ON_STACK + SAVE_C_REGS + SAVE_EXTRA_REGS call preempt_schedule - RESTORE_ALL + RESTORE_EXTRA_REGS + RESTORE_C_REGS + REMOVE_PTREGS_FROM_STACK ret CFI_ENDPROC@@ -16,9 +20,13 @@ ENTRY(___preempt_schedule) ENTRY(___preempt_schedule_context) CFI_STARTPROC - SAVE_ALL
arch/x86/kernel/preempt.S ENTRY(___preempt_schedule) · line 31
Quoted 10 lines
arch/x86/kernel/preempt.S +6
-1+ ALLOC_PTREGS_ON_STACK + SAVE_C_REGS + SAVE_EXTRA_REGS call preempt_schedule_context - RESTORE_ALL + RESTORE_EXTRA_REGS + RESTORE_C_REGS + REMOVE_PTREGS_FROM_STACK ret CFI_ENDPROC
Hmm. This part looks fine, but with or without this patch this all is suboptimal, we do not need SAVE_ALL unless I missed something. Can't we simply kill preempt.S ?
Peter, what do you think?
Oleg.
----------------------------------------------------------------------------
Subject: [PATCH] x86: reimplement ___preempt_schedule*() using THUNK helpers
arch/x86/kernel/Makefile +0 -2
@@ -39,8 +39,6 @@ obj-y += tsc.o tsc_msr.o io_delay.o rtc.o obj-y += pci-iommu_table.o obj-y += resource.o -obj-$(CONFIG_PREEMPT) += preempt.o - obj-y += process.o obj-y += i387.o xsave.o obj-y += ptrace.o
arch/x86/kernel/preempt.S deleted +0 -25
@@ -1,25 +0,0 @@ - -#include <linux/linkage.h> -#include <asm/dwarf2.h> -#include <asm/asm.h> -#include <asm/calling.h> - -ENTRY(___preempt_schedule) - CFI_STARTPROC - SAVE_ALL - call preempt_schedule - RESTORE_ALL - ret - CFI_ENDPROC - -#ifdef CONFIG_CONTEXT_TRACKING - -ENTRY(___preempt_schedule_context) - CFI_STARTPROC - SAVE_ALL - call preempt_schedule_context - RESTORE_ALL - ret - CFI_ENDPROC - -#endif
arch/x86/lib/thunk_32.S +9 -1
@@ -7,7 +7,6 @@ #include <linux/linkage.h> #include <asm/asm.h> -#ifdef CONFIG_TRACE_IRQFLAGS /* put return address in eax (arg1) */ .macro thunk_ra name,func .globl \name
@@ -25,6 +24,15 @@ _ASM_NOKPROBE(\name) .endm +#ifdef CONFIG_TRACE_IRQFLAGS thunk_ra trace_hardirqs_on_thunk,trace_hardirqs_on_caller thunk_ra trace_hardirqs_off_thunk,trace_hardirqs_off_caller #endif + +#ifdef CONFIG_PREEMPT + THUNK ___preempt_schedule, preempt_schedule +#ifdef CONFIG_CONTEXT_TRACKING + THUNK ___preempt_schedule_context, preempt_schedule_context +#endif +#endif +
arch/x86/lib/thunk_64.S +7 -0
@@ -38,6 +38,13 @@ THUNK lockdep_sys_exit_thunk,lockdep_sys_exit #endif +#ifdef CONFIG_PREEMPT + THUNK ___preempt_schedule, preempt_schedule +#ifdef CONFIG_CONTEXT_TRACKING + THUNK ___preempt_schedule_context, preempt_schedule_context +#endif +#endif + /* SAVE_ARGS below is used only for the .cfi directives it contains. */ CFI_STARTPROC SAVE_ARGS
Re: [PATCH?] x86: reimplement ___preempt_schedule*() using THUNK helpers
Quoted 5 lines · Oleg Nesterov
Hmm. This part looks fine, but with or without this patch this all is suboptimal, we do not need
SAVE_ALLunless I missed something. Can't we simply killpreempt.S?Peter, what do you think?
HPA right, not me? I'm never sure on these details, if hpa thinks its fine, I'm good.
Oleg Nesterov
maintainerPATCH v2 1/1 x86: reimplement ___preempt_schedule*() using THUNK helpers
Quoted 9 lines · Peter Zijlstra
Quoted 5 lines · Oleg Nesterov
Hmm. This part looks fine, but with or without this patch this all is suboptimal, we do not need
SAVE_ALLunless I missed something. Can't we simply killpreempt.S?Peter, what do you think?
HPA right, not me?
You too ;)
Quoted 2 lines
I'm never sure on these details, if hpa thinks its fine, I'm good.
OK, please see v2 below, I missed the unconditional "Place EIP in the arg1" in thunk_32.S.
Seems to work at least on x86_64, but I do not know how to test, lets see what HPA thinks.
_If_ this is correct, I should probably rebase it on top of Denys's changes... Or, given that this patch is simple, perhaps Denys can take this patch as 1/X. If correct ;)
Oleg.
----------------------------------------------------------------------------
Subject: [PATCH] x86: reimplement ___preempt_schedule*() using THUNK helpers
--- arch/x86/kernel/Makefile | 2 -- arch/x86/kernel/preempt.S | 25 ------------------------- arch/x86/lib/thunk_32.S | 20 ++++++++++++++++---- arch/x86/lib/thunk_64.S | 7 +++++++ 4 files changed, 23 insertions(+), 31 deletions(-) delete mode 100644 arch/x86/kernel/preempt.S
arch/x86/kernel/Makefile +0 -2
@@ -39,8 +39,6 @@ obj-y += tsc.o tsc_msr.o io_delay.o rtc.o obj-y += pci-iommu_table.o obj-y += resource.o -obj-$(CONFIG_PREEMPT) += preempt.o - obj-y += process.o obj-y += i387.o xsave.o obj-y += ptrace.o
arch/x86/kernel/preempt.S deleted +0 -25
@@ -1,25 +0,0 @@ - -#include <linux/linkage.h> -#include <asm/dwarf2.h> -#include <asm/asm.h> -#include <asm/calling.h> - -ENTRY(___preempt_schedule) - CFI_STARTPROC - SAVE_ALL - call preempt_schedule - RESTORE_ALL - ret - CFI_ENDPROC - -#ifdef CONFIG_CONTEXT_TRACKING - -ENTRY(___preempt_schedule_context) - CFI_STARTPROC - SAVE_ALL - call preempt_schedule_context - RESTORE_ALL - ret - CFI_ENDPROC - -#endif
arch/x86/lib/thunk_32.S +16 -4
@@ -7,16 +7,19 @@ #include <linux/linkage.h> #include <asm/asm.h> -#ifdef CONFIG_TRACE_IRQFLAGS /* put return address in eax (arg1) */ - .macro thunk_ra name,func + .macro thunk_ra name, func, put_ret_addr_in_eax=0 .globl \name \name: pushl %eax pushl %ecx pushl %edx + + .if \put_ret_addr_in_eax /* Place EIP in the arg1 */ movl 3*4(%esp), %eax + .endif + call \func popl %edx popl %ecx
@@ -25,6 +28,15 @@ _ASM_NOKPROBE(\name) .endm - thunk_ra trace_hardirqs_on_thunk,trace_hardirqs_on_caller - thunk_ra trace_hardirqs_off_thunk,trace_hardirqs_off_caller +#ifdef CONFIG_TRACE_IRQFLAGS + thunk_ra trace_hardirqs_on_thunk,trace_hardirqs_on_caller,1 + thunk_ra trace_hardirqs_off_thunk,trace_hardirqs_off_caller,1 +#endif + +#ifdef CONFIG_PREEMPT + THUNK ___preempt_schedule, preempt_schedule +#ifdef CONFIG_CONTEXT_TRACKING + THUNK ___preempt_schedule_context, preempt_schedule_context #endif +#endif +
arch/x86/lib/thunk_64.S +7 -0
@@ -38,6 +38,13 @@ THUNK lockdep_sys_exit_thunk,lockdep_sys_exit #endif +#ifdef CONFIG_PREEMPT + THUNK ___preempt_schedule, preempt_schedule +#ifdef CONFIG_CONTEXT_TRACKING + THUNK ___preempt_schedule_context, preempt_schedule_context +#endif +#endif + /* SAVE_ARGS below is used only for the .cfi directives it contains. */ CFI_STARTPROC SAVE_ARGS
Signature · 1 line
1.5.5.1
Re: [PATCH? v2] x86: reimplement ___preempt_schedule*() using THUNK helpers
Quoted 2 lines · Oleg Nesterov
Seems to work at least on
x86_64, but I do not know how to test, lets see what HPA thinks.
Seeing the words "preempt" and "test", blindly feeding it to -rt seemed like a reasonable thing to do over morning java (la la la;)... it hasn't spat it out yet.
-Mike
PATCH v2 5/6 x86: mass removal of ARGOFFSET
In reply to Denys VlasenkoARGOFFSET is zero now, removing it changes no code.
A few macros lost "offset" parameter, since it is always zero now too.
--- arch/x86/ia32/ia32entry.S | 136 ++++++++++++++++++++--------------------- arch/x86/include/asm/calling.h | 2 - arch/x86/kernel/entry_64.S | 66 ++++++++++---------- 3 files changed, 101 insertions(+), 103 deletions(-)
arch/x86/ia32/ia32entry.S +68 -68
@@ -41,13 +41,13 @@ movl %edx,%edx /* zero extension */ .endm - /* clobbers %eax */ - .macro CLEAR_RREGS offset=0, _r9=rax + /* clobbers %rax */ + .macro CLEAR_RREGS _r9=rax xorl %eax,%eax - movq %rax,\offset+R11(%rsp) - movq %rax,\offset+R10(%rsp) - movq %\_r9,\offset+R9(%rsp) - movq %rax,\offset+R8(%rsp) + movq %rax,R11(%rsp) + movq %rax,R10(%rsp) + movq %\_r9,R9(%rsp) + movq %rax,R8(%rsp) .endm /*
@@ -60,14 +60,14 @@ * If it's -1 to make us punt the syscall, then (u32)-1 is still * an appropriately invalid value. */ - .macro LOAD_ARGS32 offset, _r9=0 + .macro LOAD_ARGS32 _r9=0 .if \_r9 - movl \offset+R9(%rsp),%r9d + movl R9(%rsp),%r9d .endif - movl \offset+RCX(%rsp),%ecx - movl \offset+RDX(%rsp),%edx - movl \offset+RSI(%rsp),%esi - movl \offset+RDI(%rsp),%edi + movl RCX(%rsp),%ecx + movl RDX(%rsp),%edx + movl RSI(%rsp),%esi + movl RDI(%rsp),%edi movl %eax,%eax /* zero extension */ .endm
@@ -152,8 +152,8 @@ ENTRY(ia32_sysenter_target) 1: movl (%rbp),%ebp _ASM_EXTABLE(1b,ia32_badarg) ASM_CLAC - orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) - testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP) + testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP) CFI_REMEMBER_STATE jnz sysenter_tracesys cmpq $(IA32_NR_syscalls-1),%rax
@@ -162,13 +162,13 @@ sysenter_do_call: IA32_ARG_FIXUP sysenter_dispatch: call *ia32_sys_call_table(,%rax,8) - movq %rax,RAX-ARGOFFSET(%rsp) + movq %rax,RAX(%rsp) DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF - testl $_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + testl $_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,RIP) jnz sysexit_audit sysexit_from_sys_call: - andl $~TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) + andl $~TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP) /* clear IF, that popfq doesn't enable interrupts early */ andl $~0x200,EFLAGS-R11(%rsp) movl RIP-R11(%rsp),%edx /* User %eip */
@@ -195,18 +195,18 @@ sysexit_from_sys_call: movl %eax,%esi /* 2nd arg: syscall number */ movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */ call __audit_syscall_entry - movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */ + movl RAX(%rsp),%eax /* reload syscall number */ cmpq $(IA32_NR_syscalls-1),%rax ja ia32_badsys movl %ebx,%edi /* reload 1st syscall arg */ - movl RCX-ARGOFFSET(%rsp),%esi /* reload 2nd syscall arg */ - movl RDX-ARGOFFSET(%rsp),%edx /* reload 3rd syscall arg */ - movl RSI-ARGOFFSET(%rsp),%ecx /* reload 4th syscall arg */ - movl RDI-ARGOFFSET(%rsp),%r8d /* reload 5th syscall arg */ + movl RCX(%rsp),%esi /* reload 2nd syscall arg */ + movl RDX(%rsp),%edx /* reload 3rd syscall arg */ + movl RSI(%rsp),%ecx /* reload 4th syscall arg */ + movl RDI(%rsp),%r8d /* reload 5th syscall arg */ .endm .macro auditsys_exit exit - testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP) jnz ia32_ret_from_sys_call TRACE_IRQS_ON ENABLE_INTERRUPTS(CLBR_NONE)
@@ -217,13 +217,13 @@ sysexit_from_sys_call: 1: setbe %al /* 1 if error, 0 if not */ movzbl %al,%edi /* zero-extend that into %edi */ call __audit_syscall_exit - movq RAX-ARGOFFSET(%rsp),%rax /* reload syscall return value */ + movq RAX(%rsp),%rax /* reload syscall return value */ movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF - testl %edi,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + testl %edi,TI_flags+THREAD_INFO(%rsp,RIP) jz \exit - CLEAR_RREGS -ARGOFFSET + CLEAR_RREGS jmp int_with_check .endm
@@ -239,7 +239,7 @@ sysexit_audit: sysenter_tracesys: #ifdef CONFIG_AUDITSYSCALL - testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP) jz sysenter_auditsys #endif SAVE_EXTRA_REGS
@@ -247,7 +247,7 @@ sysenter_tracesys: movq $-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter - LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ + LOAD_ARGS32 /* reload args from stack in case ptrace changed it */ RESTORE_EXTRA_REGS cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
@@ -293,17 +293,17 @@ ENTRY(ia32_cstar_target) ALLOC_PTREGS_ON_STACK 8 SAVE_C_REGS_EXCEPT_RCX_R891011 movl %eax,%eax /* zero extension */ - movq %rax,ORIG_RAX-ARGOFFSET(%rsp) - movq %rcx,RIP-ARGOFFSET(%rsp) - CFI_REL_OFFSET rip,RIP-ARGOFFSET - movq %rbp,RCX-ARGOFFSET(%rsp) /* this lies slightly to ptrace */ + movq %rax,ORIG_RAX(%rsp) + movq %rcx,RIP(%rsp) + CFI_REL_OFFSET rip,RIP + movq %rbp,RCX(%rsp) /* this lies slightly to ptrace */ movl %ebp,%ecx - movq $__USER32_CS,CS-ARGOFFSET(%rsp) - movq $__USER32_DS,SS-ARGOFFSET(%rsp) - movq %r11,EFLAGS-ARGOFFSET(%rsp) - /*CFI_REL_OFFSET rflags,EFLAGS-ARGOFFSET*/ - movq %r8,RSP-ARGOFFSET(%rsp) - CFI_REL_OFFSET rsp,RSP-ARGOFFSET + movq $__USER32_CS,CS(%rsp) + movq $__USER32_DS,SS(%rsp) + movq %r11,EFLAGS(%rsp) + /*CFI_REL_OFFSET rflags,EFLAGS*/ + movq %r8,RSP(%rsp) + CFI_REL_OFFSET rsp,RSP /* no need to do an access_ok check here because r8 has been 32bit zero extended */ /* hardware stack frame is complete now */
@@ -311,8 +311,8 @@ ENTRY(ia32_cstar_target) 1: movl (%r8),%r9d _ASM_EXTABLE(1b,ia32_badarg) ASM_CLAC - orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) - testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP) + testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP) CFI_REMEMBER_STATE jnz cstar_tracesys cmpq $IA32_NR_syscalls-1,%rax
@@ -321,32 +321,32 @@ cstar_do_call: IA32_ARG_FIXUP 1 cstar_dispatch: call *ia32_sys_call_table(,%rax,8) - movq %rax,RAX-ARGOFFSET(%rsp) + movq %rax,RAX(%rsp) DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF - testl $_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + testl $_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,RIP) jnz sysretl_audit sysretl_from_sys_call: - andl $~TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) + andl $~TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP) RESTORE_RSI_RDI_RDX - movl RIP-ARGOFFSET(%rsp),%ecx + movl RIP(%rsp),%ecx CFI_REGISTER rip,rcx - movl EFLAGS-ARGOFFSET(%rsp),%r11d + movl EFLAGS(%rsp),%r11d /*CFI_REGISTER rflags,r11*/ xorq %r10,%r10 xorq %r9,%r9 xorq %r8,%r8 TRACE_IRQS_ON - movl RSP-ARGOFFSET(%rsp),%esp + movl RSP(%rsp),%esp CFI_RESTORE rsp USERGS_SYSRET32 #ifdef CONFIG_AUDITSYSCALL cstar_auditsys: CFI_RESTORE_STATE - movl %r9d,R9-ARGOFFSET(%rsp) /* register to be clobbered by call */ + movl %r9d,R9(%rsp) /* register to be clobbered by call */ auditsys_entry_common - movl R9-ARGOFFSET(%rsp),%r9d /* reload 6th syscall arg */ + movl R9(%rsp),%r9d /* reload 6th syscall arg */ jmp cstar_dispatch sysretl_audit:
@@ -355,16 +355,16 @@ sysretl_audit: cstar_tracesys: #ifdef CONFIG_AUDITSYSCALL - testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP) jz cstar_auditsys #endif xchgl %r9d,%ebp SAVE_EXTRA_REGS - CLEAR_RREGS 0, r9 + CLEAR_RREGS r9 movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter - LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */ + LOAD_ARGS32 1 /* reload args from stack in case ptrace changed it */ RESTORE_EXTRA_REGS xchgl %ebp,%r9d cmpq $(IA32_NR_syscalls-1),%rax
@@ -422,8 +422,8 @@ ENTRY(ia32_syscall) this could be a problem. */ ALLOC_PTREGS_ON_STACK SAVE_C_REGS_EXCEPT_R891011 - orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) - testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP) + testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP) jnz ia32_tracesys cmpq $(IA32_NR_syscalls-1),%rax ja ia32_badsys
@@ -431,9 +431,9 @@ ia32_do_call: IA32_ARG_FIXUP call *ia32_sys_call_table(,%rax,8) # xxx: rip relative ia32_sysret: - movq %rax,RAX-ARGOFFSET(%rsp) + movq %rax,RAX(%rsp) ia32_ret_from_sys_call: - CLEAR_RREGS -ARGOFFSET + CLEAR_RREGS jmp int_ret_from_sys_call ia32_tracesys:
@@ -442,7 +442,7 @@ ia32_tracesys: movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter - LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ + LOAD_ARGS32 /* reload args from stack in case ptrace changed it */ RESTORE_EXTRA_REGS cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */
@@ -450,7 +450,7 @@ ia32_tracesys: END(ia32_syscall) ia32_badsys: - movq $0,ORIG_RAX-ARGOFFSET(%rsp) + movq $0,ORIG_RAX(%rsp) movq $-ENOSYS,%rax jmp ia32_sysret
@@ -482,17 +482,17 @@ ia32_ptregs_common: CFI_ENDPROC CFI_STARTPROC32 simple CFI_SIGNAL_FRAME - CFI_DEF_CFA rsp,SS+8-ARGOFFSET - CFI_REL_OFFSET rax,RAX-ARGOFFSET - CFI_REL_OFFSET rcx,RCX-ARGOFFSET - CFI_REL_OFFSET rdx,RDX-ARGOFFSET - CFI_REL_OFFSET rsi,RSI-ARGOFFSET - CFI_REL_OFFSET rdi,RDI-ARGOFFSET - CFI_REL_OFFSET rip,RIP-ARGOFFSET -/* CFI_REL_OFFSET cs,CS-ARGOFFSET*/ -/* CFI_REL_OFFSET rflags,EFLAGS-ARGOFFSET*/ - CFI_REL_OFFSET rsp,RSP-ARGOFFSET -/* CFI_REL_OFFSET ss,SS-ARGOFFSET*/ + CFI_DEF_CFA rsp,SS+8 + CFI_REL_OFFSET rax,RAX + CFI_REL_OFFSET rcx,RCX + CFI_REL_OFFSET rdx,RDX + CFI_REL_OFFSET rsi,RSI + CFI_REL_OFFSET rdi,RDI + CFI_REL_OFFSET rip,RIP +/* CFI_REL_OFFSET cs,CS*/ +/* CFI_REL_OFFSET rflags,EFLAGS*/ + CFI_REL_OFFSET rsp,RSP +/* CFI_REL_OFFSET ss,SS*/ SAVE_EXTRA_REGS 8 call *%rax RESTORE_EXTRA_REGS 8
arch/x86/include/asm/calling.h +0 -2
@@ -88,8 +88,6 @@ For 32-bit we have the following conventions - kernel is built with#define RSP 19*8#define SS 20*8 -#define ARGOFFSET 0 - .macro ALLOC_PTREGS_ON_STACK addskip=0 subq $15*8+\addskip, %rsp CFI_ADJUST_CFA_OFFSET 15*8+\addskip
arch/x86/kernel/entry_64.S +33 -33
175 lines not on this page · raw message
Signature · 1 line
1.8.1.4
Re: [PATCH 5/6] x86: mass removal of ARGOFFSET
FYI: the patch is incomplete. arch/x86/ia32/ia32entry.S has a bug, fix is:
sysexit_from_sys_call:
andl $~TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
/* clear IF, that popfq doesn't enable interrupts early */
- andl $~0x200,EFLAGS-R11(%rsp).
- movl RIP-R11(%rsp),%edx /* User %eip */
+ andl $~0x200,EFLAGS-ARGOFFSET(%rsp)
+ movl RIP-ARGOFFSET(%rsp),%edx /* User %eip */
CFI_REGISTER rip,rdx
RESTORE_ARGS 0,24,0,0,0,0
xorq %r8,%r8It went unnoticed for so long because
these two constants are the same.
Patch #4 changes ARGOFFSET to 0, but of course R11 stays the same, breaking this code.
PATCH v2 6/6 x86: rename some macros and labels, no code changes
In reply to Denys VlasenkoRename LOAD_ARGS32 to RESTORE_REGS32 to match other RESTORE_* macros. The "ARGS" part was misleading anyway - we are restoring registers, not arguments.
Similarly, rename [retint_]restore_args to [retint_]restore_c_regs:
at these labels, we restore registers clobbered by C ABI; rename int_restore_rest to int_restore_extra_regs.
--- arch/x86/ia32/ia32entry.S | 10 +++++----- arch/x86/kernel/entry_64.S | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-)
arch/x86/ia32/ia32entry.S +5 -5
@@ -51,7 +51,7 @@ .endm /* - * Reload arg registers from stack in case ptrace changed them. + * Reload registers from stack in case ptrace changed them. * We don't reload %eax because syscall_trace_enter() returned * the %rax value we should see. Instead, we just truncate that * value to 32 bits again as we did on entry from user mode.
@@ -60,7 +60,7 @@ * If it's -1 to make us punt the syscall, then (u32)-1 is still * an appropriately invalid value. */ - .macro LOAD_ARGS32 _r9=0 + .macro RESTORE_REGS32 _r9=0 .if \_r9 movl R9(%rsp),%r9d .endif
@@ -247,7 +247,7 @@ sysenter_tracesys: movq $-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter - LOAD_ARGS32 /* reload args from stack in case ptrace changed it */ + RESTORE_REGS32 /* reload regs from stack in case ptrace changed it */ RESTORE_EXTRA_REGS cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
@@ -364,7 +364,7 @@ cstar_tracesys: movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter - LOAD_ARGS32 1 /* reload args from stack in case ptrace changed it */ + RESTORE_REGS32 1 /* reload regs from stack in case ptrace changed it */ RESTORE_EXTRA_REGS xchgl %ebp,%r9d cmpq $(IA32_NR_syscalls-1),%rax
@@ -442,7 +442,7 @@ ia32_tracesys: movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter - LOAD_ARGS32 /* reload args from stack in case ptrace changed it */ + RESTORE_REGS32 /* reload args from stack in case ptrace changed it */ RESTORE_EXTRA_REGS cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */
arch/x86/kernel/entry_64.S +8 -8
@@ -62,7 +62,7 @@ #ifndef CONFIG_PREEMPT -#define retint_kernel retint_restore_args +#define retint_kernel retint_restore_c_regs #endif #ifdef CONFIG_PARAVIRT
@@ -494,7 +494,7 @@ int_check_syscall_exit_work: call syscall_trace_leave popq_cfi %rdi andl $~(_TIF_WORK_SYSCALL_EXIT|_TIF_SYSCALL_EMU),%edi - jmp int_restore_rest + jmp int_restore_extra_regs int_signal: testl $_TIF_DO_NOTIFY_MASK,%edx
@@ -503,7 +503,7 @@ int_signal: xorl %esi,%esi # oldset -> arg2 call do_notify_resume 1: movl $_TIF_WORK_MASK,%edi -int_restore_rest: +int_restore_extra_regs: RESTORE_EXTRA_REGS DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF
@@ -742,15 +742,15 @@ retint_swapgs: /* return to user-space */ DISABLE_INTERRUPTS(CLBR_ANY) TRACE_IRQS_IRETQ SWAPGS - jmp restore_args + jmp restore_c_regs -retint_restore_args: /* return to kernel space */ +retint_restore_c_regs: /* return to kernel space */ DISABLE_INTERRUPTS(CLBR_ANY) /* * The iretq could re-enable interrupts: */ TRACE_IRQS_IRETQ -restore_args: +restore_c_regs: RESTORE_C_REGS REMOVE_PTREGS_FROM_STACK 8
@@ -855,9 +855,9 @@ retint_signal: /* rcx: threadinfo. interrupts off. */ ENTRY(retint_kernel) cmpl $0,PER_CPU_VAR(__preempt_count) - jnz retint_restore_args + jnz retint_restore_c_regs bt $9,EFLAGS(%rsp) /* interrupts off? */ - jnc retint_restore_args + jnc retint_restore_c_regs call preempt_schedule_irq jmp exit_intr #endif
Signature · 1 line
1.8.1.4