* [PATCH 0/3] x86_64, entry: some cleanup and simplification...
@ 2015-01-18 1:17 Alexander van Heukelum
2015-01-18 1:17 ` [PATCH 1/3] x86_64: remove KERNEL_STACK_OFFSET from THREAD_INFO macro Alexander van Heukelum
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Alexander van Heukelum @ 2015-01-18 1:17 UTC (permalink / raw)
To: Andy Lutomirski, x86, linux-kernel
Cc: Frederic Weisbecker, Oleg Nesterov, Borislav Petkov, Rik van Riel
Hi Andy,
Seems you are the person to talk now :). Good to see some activity in
the "entry" area of the kernel. I found some (very) old patches in this
area lying around and some time to dust them off.
Any chance you can review them?
They were redone on top of 22f2aa4a0361707a5cfb1de9d45260b39965dead
(x86/entry-devel in your tree) and this kernel is now running happily
on my laptop. I didn't try any benchmarking, though.
Greetings,
Alexander
Alexander van Heukelum (3):
x86_64: remove KERNEL_STACK_OFFSET from THREAD_INFO macro
x86_64: don't use KERNEL_STACK_OFFSET for syscall and sysenter
x86_64, entry: Create IRET-compatible stack frame at syscall entry
arch/x86/ia32/ia32entry.S | 34 ++++++++--------
arch/x86/include/asm/calling.h | 1 +
arch/x86/include/asm/thread_info.h | 8 ++--
arch/x86/kernel/cpu/common.c | 2 +-
arch/x86/kernel/entry_64.S | 82 ++++++++++++--------------------------
arch/x86/kernel/process_64.c | 3 +-
arch/x86/kernel/smpboot.c | 3 +-
arch/x86/xen/smp.c | 3 +-
8 files changed, 50 insertions(+), 86 deletions(-)
--
2.1.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/3] x86_64: remove KERNEL_STACK_OFFSET from THREAD_INFO macro
2015-01-18 1:17 [PATCH 0/3] x86_64, entry: some cleanup and simplification Alexander van Heukelum
@ 2015-01-18 1:17 ` Alexander van Heukelum
2015-01-18 1:17 ` [PATCH 2/3] x86_64: don't use KERNEL_STACK_OFFSET for syscall and sysenter Alexander van Heukelum
2015-01-18 1:17 ` [PATCH 3/3] x86_64, entry: Create IRET-compatible stack frame at syscall entry Alexander van Heukelum
2 siblings, 0 replies; 4+ messages in thread
From: Alexander van Heukelum @ 2015-01-18 1:17 UTC (permalink / raw)
To: Andy Lutomirski, x86, linux-kernel
Cc: Frederic Weisbecker, Oleg Nesterov, Borislav Petkov, Rik van Riel
In the macro THREAD_INFO(reg,offset), the offset is relative to
KERNEL_STACK_OFFSET. Change the macro and all its uses so that
offset is given as the current top of stack in the pt_regs frame.
The generated code is identical.
Signed-off-by: Alexander van Heukelum <heukelum@fastmail.fm>
---
arch/x86/ia32/ia32entry.S | 30 +++++++++++++++---------------
arch/x86/include/asm/calling.h | 1 +
arch/x86/include/asm/thread_info.h | 2 +-
arch/x86/kernel/entry_64.S | 4 ++--
4 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 156ebca..1c74f39 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -135,7 +135,7 @@ ENTRY(ia32_sysenter_target)
CFI_REL_OFFSET rsp,0
pushfq_cfi
/*CFI_REL_OFFSET rflags,0*/
- movl TI_sysenter_return+THREAD_INFO(%rsp,3*8-KERNEL_STACK_OFFSET),%r10d
+ movl TI_sysenter_return+THREAD_INFO(%rsp,EFLAGS),%r10d
CFI_REGISTER rip,r10
pushq_cfi $__USER32_CS
/*CFI_REL_OFFSET cs,0*/
@@ -161,8 +161,8 @@ ENTRY(ia32_sysenter_target)
jnz sysenter_fix_flags
sysenter_flags_fixed:
- 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,ARGOFFSET)
+ testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,ARGOFFSET)
CFI_REMEMBER_STATE
jnz sysenter_tracesys
cmpq $(IA32_NR_syscalls-1),%rax
@@ -174,10 +174,10 @@ sysenter_dispatch:
movq %rax,RAX-ARGOFFSET(%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,ARGOFFSET)
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,ARGOFFSET)
/* clear IF, that popfq doesn't enable interrupts early */
andl $~0x200,EFLAGS-ARGOFFSET(%rsp)
movl RIP-ARGOFFSET(%rsp),%edx /* User %eip */
@@ -216,7 +216,7 @@ sysexit_from_sys_call:
.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,ARGOFFSET)
jnz ia32_ret_from_sys_call
TRACE_IRQS_ON
ENABLE_INTERRUPTS(CLBR_NONE)
@@ -231,7 +231,7 @@ sysexit_from_sys_call:
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,ARGOFFSET)
jz \exit
CLEAR_RREGS -ARGOFFSET
jmp int_with_check
@@ -253,7 +253,7 @@ sysenter_fix_flags:
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,ARGOFFSET)
jz sysenter_auditsys
#endif
SAVE_REST
@@ -324,8 +324,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,ARGOFFSET)
+ testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,ARGOFFSET)
CFI_REMEMBER_STATE
jnz cstar_tracesys
cmpq $IA32_NR_syscalls-1,%rax
@@ -337,10 +337,10 @@ cstar_dispatch:
movq %rax,RAX-ARGOFFSET(%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,ARGOFFSET)
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,ARGOFFSET)
RESTORE_ARGS 0,-ARG_SKIP,0,0,0
movl RIP-ARGOFFSET(%rsp),%ecx
CFI_REGISTER rip,rcx
@@ -368,7 +368,7 @@ 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,ARGOFFSET)
jz cstar_auditsys
#endif
xchgl %r9d,%ebp
@@ -434,8 +434,8 @@ ENTRY(ia32_syscall)
/* note the registers are not zero extended to the sf.
this could be a problem. */
SAVE_ARGS 0,1,0
- 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,ARGOFFSET)
+ testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,ARGOFFSET)
jnz ia32_tracesys
cmpq $(IA32_NR_syscalls-1),%rax
ja ia32_badsys
diff --git a/arch/x86/include/asm/calling.h b/arch/x86/include/asm/calling.h
index 1f1297b..16ab13d 100644
--- a/arch/x86/include/asm/calling.h
+++ b/arch/x86/include/asm/calling.h
@@ -81,6 +81,7 @@ For 32-bit we have the following conventions - kernel is built with
#define EFLAGS 144
#define RSP 152
#define SS 160
+#define PTREGS_SIZE 168
#define ARGOFFSET R11
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index e82e95a..471037d 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -190,7 +190,7 @@ static inline unsigned long current_stack_pointer(void)
* Same if PER_CPU_VAR(kernel_stack) is, perhaps with some offset, already in
* a certain register (to be used in assembler memory operands).
*/
-#define THREAD_INFO(reg, off) KERNEL_STACK_OFFSET+(off)-THREAD_SIZE(reg)
+#define THREAD_INFO(reg, off) PTREGS_SIZE-(off)-THREAD_SIZE(reg)
#endif
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index db13655..9f9ca20 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -343,7 +343,7 @@ GLOBAL(system_call_after_swapgs)
movq_cfi rax,(ORIG_RAX-ARGOFFSET)
movq %rcx,RIP-ARGOFFSET(%rsp)
CFI_REL_OFFSET rip,RIP-ARGOFFSET
- testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+ testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,ARGOFFSET)
jnz tracesys
system_call_fastpath:
#if __SYSCALL_MASK == ~0
@@ -361,7 +361,7 @@ system_call_fastpath:
* Has incomplete stack frame and undefined top of stack.
*/
ret_from_sys_call:
- testl $_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+ testl $_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,ARGOFFSET)
jnz int_ret_from_sys_call_fixup /* Go the the slow path */
LOCKDEP_SYS_EXIT
--
2.1.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 2/3] x86_64: don't use KERNEL_STACK_OFFSET for syscall and sysenter
2015-01-18 1:17 [PATCH 0/3] x86_64, entry: some cleanup and simplification Alexander van Heukelum
2015-01-18 1:17 ` [PATCH 1/3] x86_64: remove KERNEL_STACK_OFFSET from THREAD_INFO macro Alexander van Heukelum
@ 2015-01-18 1:17 ` Alexander van Heukelum
2015-01-18 1:17 ` [PATCH 3/3] x86_64, entry: Create IRET-compatible stack frame at syscall entry Alexander van Heukelum
2 siblings, 0 replies; 4+ messages in thread
From: Alexander van Heukelum @ 2015-01-18 1:17 UTC (permalink / raw)
To: Andy Lutomirski, x86, linux-kernel
Cc: Frederic Weisbecker, Oleg Nesterov, Borislav Petkov, Rik van Riel
The syscall and sysenter code use KERNEL_STACK_OFFSET to set the
initial stack pointer a bit below the top of the kernel stack page.
Stop doing that.
Signed-off-by: Alexander van Heukelum <heukelum@fastmail.fm>
---
arch/x86/ia32/ia32entry.S | 4 ++--
arch/x86/include/asm/thread_info.h | 6 ++----
arch/x86/kernel/cpu/common.c | 2 +-
arch/x86/kernel/entry_64.S | 3 ++-
arch/x86/kernel/process_64.c | 3 +--
arch/x86/kernel/smpboot.c | 3 +--
arch/x86/xen/smp.c | 3 +--
7 files changed, 10 insertions(+), 14 deletions(-)
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 1c74f39..93b30a1 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -122,7 +122,6 @@ ENTRY(ia32_sysenter_target)
CFI_REGISTER rsp,rbp
SWAPGS_UNSAFE_STACK
movq PER_CPU_VAR(kernel_stack), %rsp
- addq $(KERNEL_STACK_OFFSET),%rsp
/*
* No need to follow this irqs on/off section: the syscall
* disabled irqs, here we enable it straight after entry:
@@ -292,13 +291,14 @@ ENDPROC(ia32_sysenter_target)
ENTRY(ia32_cstar_target)
CFI_STARTPROC32 simple
CFI_SIGNAL_FRAME
- CFI_DEF_CFA rsp,KERNEL_STACK_OFFSET
+ CFI_DEF_CFA rsp,0
CFI_REGISTER rip,rcx
/*CFI_REGISTER rflags,r11*/
SWAPGS_UNSAFE_STACK
movl %esp,%r8d
CFI_REGISTER rsp,r8
movq PER_CPU_VAR(kernel_stack),%rsp
+ sub $(PTREGS_SIZE-RIP),%rsp
/*
* No need to follow this irqs on/off section: the syscall
* disabled irqs and here we enable it straight after entry:
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index 471037d..2caaaf2 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -149,7 +149,6 @@ struct thread_info {
#define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW)
#define STACK_WARN (THREAD_SIZE/8)
-#define KERNEL_STACK_OFFSET (5*(BITS_PER_LONG/8))
/*
* macros/functions for gaining access to the thread information structure
@@ -163,8 +162,7 @@ DECLARE_PER_CPU(unsigned long, kernel_stack);
static inline struct thread_info *current_thread_info(void)
{
struct thread_info *ti;
- ti = (void *)(this_cpu_read_stable(kernel_stack) +
- KERNEL_STACK_OFFSET - THREAD_SIZE);
+ ti = (void *)(this_cpu_read_stable(kernel_stack) - THREAD_SIZE);
return ti;
}
@@ -184,7 +182,7 @@ static inline unsigned long current_stack_pointer(void)
/* how to get the thread information struct from ASM */
#define GET_THREAD_INFO(reg) \
_ASM_MOV PER_CPU_VAR(kernel_stack),reg ; \
- _ASM_SUB $(THREAD_SIZE-KERNEL_STACK_OFFSET),reg ;
+ _ASM_SUB $THREAD_SIZE,reg ;
/*
* Same if PER_CPU_VAR(kernel_stack) is, perhaps with some offset, already in
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index c604965..aa76c69 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1116,7 +1116,7 @@ static __init int setup_disablecpuid(char *arg)
__setup("clearcpuid=", setup_disablecpuid);
DEFINE_PER_CPU(unsigned long, kernel_stack) =
- (unsigned long)&init_thread_union - KERNEL_STACK_OFFSET + THREAD_SIZE;
+ (unsigned long)&init_thread_union + THREAD_SIZE;
EXPORT_PER_CPU_SYMBOL(kernel_stack);
#ifdef CONFIG_X86_64
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 9f9ca20..7adff94 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -321,7 +321,7 @@ END(ret_from_fork)
ENTRY(system_call)
CFI_STARTPROC simple
CFI_SIGNAL_FRAME
- CFI_DEF_CFA rsp,KERNEL_STACK_OFFSET
+ CFI_DEF_CFA rsp,0
CFI_REGISTER rip,rcx
/*CFI_REGISTER rflags,r11*/
SWAPGS_UNSAFE_STACK
@@ -334,6 +334,7 @@ GLOBAL(system_call_after_swapgs)
movq %rsp,PER_CPU_VAR(old_rsp)
movq PER_CPU_VAR(kernel_stack),%rsp
+ sub $(PTREGS_SIZE-RIP),%rsp
/*
* No need to follow this irqs off/on section - it's straight
* and short:
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 5a2c029..0747dbf 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -414,8 +414,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
this_cpu_write(__preempt_count, task_thread_info(next_p)->saved_preempt_count);
this_cpu_write(kernel_stack,
- (unsigned long)task_stack_page(next_p) +
- THREAD_SIZE - KERNEL_STACK_OFFSET);
+ (unsigned long)task_stack_page(next_p) + THREAD_SIZE);
/*
* Now maybe reload the debug registers and handle I/O bitmaps
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 6d7022c..66fd449 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -776,8 +776,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
initial_gs = per_cpu_offset(cpu);
#endif
per_cpu(kernel_stack, cpu) =
- (unsigned long)task_stack_page(idle) -
- KERNEL_STACK_OFFSET + THREAD_SIZE;
+ (unsigned long)task_stack_page(idle) + THREAD_SIZE;
early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
initial_code = (unsigned long)start_secondary;
stack_start = idle->thread.sp;
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 4c071ae..4e71a3b 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -452,8 +452,7 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle)
clear_tsk_thread_flag(idle, TIF_FORK);
#endif
per_cpu(kernel_stack, cpu) =
- (unsigned long)task_stack_page(idle) -
- KERNEL_STACK_OFFSET + THREAD_SIZE;
+ (unsigned long)task_stack_page(idle) + THREAD_SIZE;
xen_setup_runstate_info(cpu);
xen_setup_timer(cpu);
--
2.1.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 3/3] x86_64, entry: Create IRET-compatible stack frame at syscall entry
2015-01-18 1:17 [PATCH 0/3] x86_64, entry: some cleanup and simplification Alexander van Heukelum
2015-01-18 1:17 ` [PATCH 1/3] x86_64: remove KERNEL_STACK_OFFSET from THREAD_INFO macro Alexander van Heukelum
2015-01-18 1:17 ` [PATCH 2/3] x86_64: don't use KERNEL_STACK_OFFSET for syscall and sysenter Alexander van Heukelum
@ 2015-01-18 1:17 ` Alexander van Heukelum
2 siblings, 0 replies; 4+ messages in thread
From: Alexander van Heukelum @ 2015-01-18 1:17 UTC (permalink / raw)
To: Andy Lutomirski, x86, linux-kernel
Cc: Frederic Weisbecker, Oleg Nesterov, Borislav Petkov, Rik van Riel
Create an IRET-compatible top of stack at syscall entry and use this
information to return to user mode in the sysret path. This removes
the need for the FIXUP_TOP_OF_STACK and RESTORE_TOP_OF_STACK macros.
Signed-off-by: Alexander van Heukelum <heukelum@fastmail.fm>
---
arch/x86/kernel/entry_64.S | 77 +++++++++++++---------------------------------
1 file changed, 22 insertions(+), 55 deletions(-)
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 7adff94..e952839 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -33,8 +33,6 @@
* - SAVE_REST/RESTORE_REST - Handle the registers not saved by SAVE_ARGS.
* Gives a full stack frame.
* - ENTRY/END Define functions in the symbol table.
- * - FIXUP_TOP_OF_STACK/RESTORE_TOP_OF_STACK - Fix up the hardware stack
- * frame that is otherwise undefined after a SYSCALL
* - TRACE_IRQ_* - Trace hard interrupt state for lock debugging.
* - idtentry - Define exception entry points.
*/
@@ -130,33 +128,6 @@ ENDPROC(native_usergs_sysret64)
#endif
/*
- * C code is not supposed to know about undefined top of stack. Every time
- * a C function with an pt_regs argument is called from the SYSCALL based
- * fast path FIXUP_TOP_OF_STACK is needed.
- * RESTORE_TOP_OF_STACK syncs the syscall state after any possible ptregs
- * manipulation.
- */
-
- /* %rsp:at FRAMEEND */
- .macro FIXUP_TOP_OF_STACK tmp offset=0
- movq PER_CPU_VAR(old_rsp),\tmp
- movq \tmp,RSP+\offset(%rsp)
- movq $__USER_DS,SS+\offset(%rsp)
- movq $__USER_CS,CS+\offset(%rsp)
- movq RIP+\offset(%rsp),\tmp /* get rip */
- movq \tmp,RCX+\offset(%rsp) /* copy it to rcx as sysret would do */
- movq R11+\offset(%rsp),\tmp /* get eflags */
- movq \tmp,EFLAGS+\offset(%rsp)
- .endm
-
- .macro RESTORE_TOP_OF_STACK tmp offset=0
- movq RSP+\offset(%rsp),\tmp
- movq \tmp,PER_CPU_VAR(old_rsp)
- movq EFLAGS+\offset(%rsp),\tmp
- movq \tmp,R11+\offset(%rsp)
- .endm
-
-/*
* initial frame state for interrupts (and exceptions without error code)
*/
.macro EMPTY_FRAME start=1 offset=0
@@ -272,7 +243,6 @@ ENTRY(ret_from_fork)
testl $_TIF_IA32, TI_flags(%rcx) # 32-bit compat task needs IRET
jnz int_ret_from_sys_call
- RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET
jmp ret_from_sys_call # go to the SYSRET fastpath
1:
@@ -334,16 +304,30 @@ GLOBAL(system_call_after_swapgs)
movq %rsp,PER_CPU_VAR(old_rsp)
movq PER_CPU_VAR(kernel_stack),%rsp
- sub $(PTREGS_SIZE-RIP),%rsp
/*
* No need to follow this irqs off/on section - it's straight
* and short:
*/
ENABLE_INTERRUPTS(CLBR_NONE)
- SAVE_ARGS 8, 0, rax_enosys=1
+
+ /*
+ * Save user mode rsp (temporarily saved above in old_rsp),
+ * rflags (%r11), rip (%rcx) and segments (fixed values) on
+ * the stack as a regular interrupt frame.
+ */
+ pushq_cfi $__USER_DS
+ /* CFI_REL_OFFSET ss, 0 */
+ pushq_cfi PER_CPU_VAR(old_rsp)
+ CFI_REL_OFFSET rsp, 0
+ pushq_cfi %r11 /* %r11 clobbered (userspace %rflags) */
+ /* CFI_REL_OFFSET rflags, 0 */
+ pushq_cfi $__USER_CS
+ /* CFI_REL_OFFSET cs, 0 */
+ pushq_cfi %rcx /* %rcx clobbered (userspace %rip) */
+ CFI_REL_OFFSET rip, 0
+
+ SAVE_ARGS 8, rax_enosys=1
movq_cfi rax,(ORIG_RAX-ARGOFFSET)
- movq %rcx,RIP-ARGOFFSET(%rsp)
- CFI_REL_OFFSET rip,RIP-ARGOFFSET
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,ARGOFFSET)
jnz tracesys
system_call_fastpath:
@@ -363,7 +347,7 @@ system_call_fastpath:
*/
ret_from_sys_call:
testl $_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,ARGOFFSET)
- jnz int_ret_from_sys_call_fixup /* Go the the slow path */
+ jnz int_ret_from_sys_call /* Go the the slow path */
LOCKDEP_SYS_EXIT
DISABLE_INTERRUPTS(CLBR_NONE)
@@ -373,19 +357,16 @@ ret_from_sys_call:
* sysretq will re-enable interrupts:
*/
TRACE_IRQS_ON
+ RESTORE_ARGS addskip=-ARG_SKIP, rstor_rcx=0, rstor_r11=0
movq RIP-ARGOFFSET(%rsp),%rcx
CFI_REGISTER rip,rcx
- RESTORE_ARGS 1,-ARG_SKIP,0
+ mov EFLAGS-ARGOFFSET(%rsp), %r11
/*CFI_REGISTER rflags,r11*/
- movq PER_CPU_VAR(old_rsp), %rsp
+ mov RSP-ARGOFFSET(%rsp), %rsp
USERGS_SYSRET64
CFI_RESTORE_STATE
-int_ret_from_sys_call_fixup:
- FIXUP_TOP_OF_STACK %r11, -ARGOFFSET
- jmp int_ret_from_sys_call
-
/* Do syscall tracing */
tracesys:
leaq -REST_SKIP(%rsp), %rdi
@@ -398,7 +379,6 @@ tracesys:
tracesys_phase2:
SAVE_REST
- FIXUP_TOP_OF_STACK %rdi
movq %rsp, %rdi
movq $AUDIT_ARCH_X86_64, %rsi
movq %rax,%rdx
@@ -494,10 +474,8 @@ ENTRY(stub_\func)
PARTIAL_FRAME 0
SAVE_REST
pushq %r11 /* put it back on stack */
- FIXUP_TOP_OF_STACK %r11, 8
DEFAULT_FRAME 0 8 /* offset 8: return address */
call sys_\func
- RESTORE_TOP_OF_STACK %r11, 8
ret $REST_SKIP /* pop extended registers */
CFI_ENDPROC
END(stub_\func)
@@ -507,9 +485,7 @@ END(stub_\func)
ENTRY(\label)
CFI_STARTPROC
PARTIAL_FRAME 0 8 /* offset 8: return address */
- FIXUP_TOP_OF_STACK %r11, 8-ARGOFFSET
call \func
- RESTORE_TOP_OF_STACK %r11, 8-ARGOFFSET
ret
CFI_ENDPROC
END(\label)
@@ -525,7 +501,6 @@ ENTRY(stub_execve)
addq $8, %rsp
PARTIAL_FRAME 0
SAVE_REST
- FIXUP_TOP_OF_STACK %r11
call sys_execve
movq %rax,RAX(%rsp)
RESTORE_REST
@@ -538,9 +513,7 @@ ENTRY(stub_execveat)
addq $8, %rsp
PARTIAL_FRAME 0
SAVE_REST
- FIXUP_TOP_OF_STACK %r11
call sys_execveat
- RESTORE_TOP_OF_STACK %r11
movq %rax,RAX(%rsp)
RESTORE_REST
jmp int_ret_from_sys_call
@@ -556,7 +529,6 @@ ENTRY(stub_rt_sigreturn)
addq $8, %rsp
PARTIAL_FRAME 0
SAVE_REST
- FIXUP_TOP_OF_STACK %r11
call sys_rt_sigreturn
movq %rax,RAX(%rsp) # fixme, this could be done at the higher layer
RESTORE_REST
@@ -570,7 +542,6 @@ ENTRY(stub_x32_rt_sigreturn)
addq $8, %rsp
PARTIAL_FRAME 0
SAVE_REST
- FIXUP_TOP_OF_STACK %r11
call sys32_x32_rt_sigreturn
movq %rax,RAX(%rsp) # fixme, this could be done at the higher layer
RESTORE_REST
@@ -583,9 +554,7 @@ ENTRY(stub_x32_execve)
addq $8, %rsp
PARTIAL_FRAME 0
SAVE_REST
- FIXUP_TOP_OF_STACK %r11
call compat_sys_execve
- RESTORE_TOP_OF_STACK %r11
movq %rax,RAX(%rsp)
RESTORE_REST
jmp int_ret_from_sys_call
@@ -597,9 +566,7 @@ ENTRY(stub_x32_execveat)
addq $8, %rsp
PARTIAL_FRAME 0
SAVE_REST
- FIXUP_TOP_OF_STACK %r11
call compat_sys_execveat
- RESTORE_TOP_OF_STACK %r11
movq %rax,RAX(%rsp)
RESTORE_REST
jmp int_ret_from_sys_call
--
2.1.0
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2015-01-18 1:18 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-18 1:17 [PATCH 0/3] x86_64, entry: some cleanup and simplification Alexander van Heukelum
2015-01-18 1:17 ` [PATCH 1/3] x86_64: remove KERNEL_STACK_OFFSET from THREAD_INFO macro Alexander van Heukelum
2015-01-18 1:17 ` [PATCH 2/3] x86_64: don't use KERNEL_STACK_OFFSET for syscall and sysenter Alexander van Heukelum
2015-01-18 1:17 ` [PATCH 3/3] x86_64, entry: Create IRET-compatible stack frame at syscall entry Alexander van Heukelum
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®