* [PATCH v2 0/9] x86/entry/head: standardize the end of the stack
@ 2016-09-21 21:03 Josh Poimboeuf
2016-09-21 21:03 ` [PATCH v2 1/9] x86/entry/head/32: use local labels Josh Poimboeuf
` (9 more replies)
0 siblings, 10 replies; 21+ messages in thread
From: Josh Poimboeuf @ 2016-09-21 21:03 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H . Peter Anvin
Cc: x86, linux-kernel, Andy Lutomirski, Linus Torvalds, Brian Gerst,
Peter Zijlstra, Nilay Vaish
v2:
- keep 'restore_all' label in "x86/entry/head/32: use local labels"
---
Thanks to all the recent x86 entry code refactoring, most tasks' kernel
stacks start at the same offset right below their saved pt_regs,
regardless of which syscall was used to enter the kernel. That creates
a nice convention which makes it straightforward to identify the end of
the stack, which can be useful [*] for the unwinder.
But there a few places where tasks don't yet follow the convention.
This patch set finishes the job.
[*] This will be useful for three upcoming proposed features:
- Detecting corrupt stacks in the unwinder (which will also be a force
for ensuring this end of stack convention continues to be followed in
the future).
- Printing all saved pt_regs on the stack during an oops/warning.
- Validating stacks in the livepatch consistency model.
Josh Poimboeuf (9):
x86/entry/head/32: use local labels
x86/entry/32: rename 'error_code' to 'common_exception'
x86/entry/32: fix the end of the stack for newly forked tasks
x86/head/32: fix the end of the stack for idle tasks
x86/smp: fix initial idle stack location on 32-bit
x86/asm/head: use a common function for starting CPUs
x86/head: put real return address on idle task stack
x86/head: fix the end of the stack for idle tasks
x86: move _stext marker to before head code
arch/x86/entry/entry_32.S | 108 +++++++++++++++++++++++++-----------------
arch/x86/kernel/head_32.S | 49 +++++++++++--------
arch/x86/kernel/head_64.S | 42 ++++++++--------
arch/x86/kernel/smpboot.c | 4 +-
arch/x86/kernel/vmlinux.lds.S | 2 +-
5 files changed, 116 insertions(+), 89 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v2 1/9] x86/entry/head/32: use local labels
2016-09-21 21:03 [PATCH v2 0/9] x86/entry/head: standardize the end of the stack Josh Poimboeuf
@ 2016-09-21 21:03 ` Josh Poimboeuf
2016-10-20 11:08 ` [tip:x86/asm] x86/entry/32, x86/boot/32: Use " tip-bot for Josh Poimboeuf
2016-09-21 21:04 ` [PATCH v2 2/9] x86/entry/32: rename 'error_code' to 'common_exception' Josh Poimboeuf
` (8 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Josh Poimboeuf @ 2016-09-21 21:03 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H . Peter Anvin
Cc: x86, linux-kernel, Andy Lutomirski, Linus Torvalds, Brian Gerst,
Peter Zijlstra, Nilay Vaish
Add the local label prefix to all non-function named labels in head_32.S
and entry_32.S. In addition to decluttering the symbol table, it also
will help stack traces to be more sensible. For example, the last
reported function in the idle task stack trace will be startup_32_smp()
instead of is486().
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
---
arch/x86/entry/entry_32.S | 43 ++++++++++++++++++++++---------------------
arch/x86/kernel/head_32.S | 32 ++++++++++++++++----------------
2 files changed, 38 insertions(+), 37 deletions(-)
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index b75a8bc..7ff0462 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -306,13 +306,13 @@ END(ret_from_exception)
#ifdef CONFIG_PREEMPT
ENTRY(resume_kernel)
DISABLE_INTERRUPTS(CLBR_ANY)
-need_resched:
+.Lneed_resched:
cmpl $0, PER_CPU_VAR(__preempt_count)
jnz restore_all
testl $X86_EFLAGS_IF, PT_EFLAGS(%esp) # interrupts off (exception path) ?
jz restore_all
call preempt_schedule_irq
- jmp need_resched
+ jmp .Lneed_resched
END(resume_kernel)
#endif
@@ -333,7 +333,7 @@ GLOBAL(__begin_SYSENTER_singlestep_region)
*/
ENTRY(xen_sysenter_target)
addl $5*4, %esp /* remove xen-provided frame */
- jmp sysenter_past_esp
+ jmp .Lsysenter_past_esp
#endif
/*
@@ -370,7 +370,7 @@ ENTRY(xen_sysenter_target)
*/
ENTRY(entry_SYSENTER_32)
movl TSS_sysenter_sp0(%esp), %esp
-sysenter_past_esp:
+.Lsysenter_past_esp:
pushl $__USER_DS /* pt_regs->ss */
pushl %ebp /* pt_regs->sp (stashed in bp) */
pushfl /* pt_regs->flags (except IF = 0) */
@@ -503,9 +503,9 @@ ENTRY(entry_INT80_32)
restore_all:
TRACE_IRQS_IRET
-restore_all_notrace:
+.Lrestore_all_notrace:
#ifdef CONFIG_X86_ESPFIX32
- ALTERNATIVE "jmp restore_nocheck", "", X86_BUG_ESPFIX
+ ALTERNATIVE "jmp .Lrestore_nocheck", "", X86_BUG_ESPFIX
movl PT_EFLAGS(%esp), %eax # mix EFLAGS, SS and CS
/*
@@ -517,22 +517,23 @@ restore_all_notrace:
movb PT_CS(%esp), %al
andl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
- je ldt_ss # returning to user-space with LDT SS
+ je .Lldt_ss # returning to user-space with LDT SS
#endif
-restore_nocheck:
+.Lrestore_nocheck:
RESTORE_REGS 4 # skip orig_eax/error_code
-irq_return:
+.Lirq_return:
INTERRUPT_RETURN
+
.section .fixup, "ax"
ENTRY(iret_exc )
pushl $0 # no error code
pushl $do_iret_error
jmp error_code
.previous
- _ASM_EXTABLE(irq_return, iret_exc)
+ _ASM_EXTABLE(.Lirq_return, iret_exc)
#ifdef CONFIG_X86_ESPFIX32
-ldt_ss:
+.Lldt_ss:
/*
* Setup and switch to ESPFIX stack
*
@@ -561,7 +562,7 @@ ldt_ss:
*/
DISABLE_INTERRUPTS(CLBR_EAX)
lss (%esp), %esp /* switch to espfix segment */
- jmp restore_nocheck
+ jmp .Lrestore_nocheck
#endif
ENDPROC(entry_INT80_32)
@@ -881,7 +882,7 @@ ftrace_call:
popl %edx
popl %ecx
popl %eax
-ftrace_ret:
+.Lftrace_ret:
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
.globl ftrace_graph_call
ftrace_graph_call:
@@ -951,7 +952,7 @@ GLOBAL(ftrace_regs_call)
popl %gs
addl $8, %esp /* Skip orig_ax and ip */
popf /* Pop flags at end (no addl to corrupt flags) */
- jmp ftrace_ret
+ jmp .Lftrace_ret
popf
jmp ftrace_stub
@@ -962,7 +963,7 @@ ENTRY(mcount)
jb ftrace_stub /* Paging not enabled yet? */
cmpl $ftrace_stub, ftrace_trace_function
- jnz trace
+ jnz .Ltrace
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
cmpl $ftrace_stub, ftrace_graph_return
jnz ftrace_graph_caller
@@ -975,7 +976,7 @@ ftrace_stub:
ret
/* taken from glibc */
-trace:
+.Ltrace:
pushl %eax
pushl %ecx
pushl %edx
@@ -1114,7 +1115,7 @@ ENTRY(nmi)
movl %ss, %eax
cmpw $__ESPFIX_SS, %ax
popl %eax
- je nmi_espfix_stack
+ je .Lnmi_espfix_stack
#endif
pushl %eax # pt_regs->orig_ax
@@ -1130,7 +1131,7 @@ ENTRY(nmi)
/* Not on SYSENTER stack. */
call do_nmi
- jmp restore_all_notrace
+ jmp .Lrestore_all_notrace
.Lnmi_from_sysenter_stack:
/*
@@ -1141,10 +1142,10 @@ ENTRY(nmi)
movl PER_CPU_VAR(cpu_current_top_of_stack), %esp
call do_nmi
movl %ebp, %esp
- jmp restore_all_notrace
+ jmp .Lrestore_all_notrace
#ifdef CONFIG_X86_ESPFIX32
-nmi_espfix_stack:
+.Lnmi_espfix_stack:
/*
* create the pointer to lss back
*/
@@ -1162,7 +1163,7 @@ nmi_espfix_stack:
call do_nmi
RESTORE_REGS
lss 12+4(%esp), %esp # back to espfix stack
- jmp irq_return
+ jmp .Lirq_return
#endif
END(nmi)
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 5f40126..617fba2 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -247,19 +247,19 @@ page_pde_offset = (__PAGE_OFFSET >> 20);
#ifdef CONFIG_PARAVIRT
/* This is can only trip for a broken bootloader... */
cmpw $0x207, pa(boot_params + BP_version)
- jb default_entry
+ jb .Ldefault_entry
/* Paravirt-compatible boot parameters. Look to see what architecture
we're booting under. */
movl pa(boot_params + BP_hardware_subarch), %eax
cmpl $num_subarch_entries, %eax
- jae bad_subarch
+ jae .Lbad_subarch
movl pa(subarch_entries)(,%eax,4), %eax
subl $__PAGE_OFFSET, %eax
jmp *%eax
-bad_subarch:
+.Lbad_subarch:
WEAK(lguest_entry)
WEAK(xen_entry)
/* Unknown implementation; there's really
@@ -269,14 +269,14 @@ WEAK(xen_entry)
__INITDATA
subarch_entries:
- .long default_entry /* normal x86/PC */
+ .long .Ldefault_entry /* normal x86/PC */
.long lguest_entry /* lguest hypervisor */
.long xen_entry /* Xen hypervisor */
- .long default_entry /* Moorestown MID */
+ .long .Ldefault_entry /* Moorestown MID */
num_subarch_entries = (. - subarch_entries) / 4
.previous
#else
- jmp default_entry
+ jmp .Ldefault_entry
#endif /* CONFIG_PARAVIRT */
#ifdef CONFIG_HOTPLUG_CPU
@@ -316,7 +316,7 @@ ENTRY(startup_32_smp)
call load_ucode_ap
#endif
-default_entry:
+.Ldefault_entry:
#define CR0_STATE (X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | \
X86_CR0_NE | X86_CR0_WP | X86_CR0_AM | \
X86_CR0_PG)
@@ -346,7 +346,7 @@ default_entry:
pushfl
popl %eax # get EFLAGS
testl $X86_EFLAGS_ID,%eax # did EFLAGS.ID remained set?
- jz enable_paging # hw disallowed setting of ID bit
+ jz .Lenable_paging # hw disallowed setting of ID bit
# which means no CPUID and no CR4
xorl %eax,%eax
@@ -356,13 +356,13 @@ default_entry:
movl $1,%eax
cpuid
andl $~1,%edx # Ignore CPUID.FPU
- jz enable_paging # No flags or only CPUID.FPU = no CR4
+ jz .Lenable_paging # No flags or only CPUID.FPU = no CR4
movl pa(mmu_cr4_features),%eax
movl %eax,%cr4
testb $X86_CR4_PAE, %al # check if PAE is enabled
- jz enable_paging
+ jz .Lenable_paging
/* Check if extended functions are implemented */
movl $0x80000000, %eax
@@ -370,7 +370,7 @@ default_entry:
/* Value must be in the range 0x80000001 to 0x8000ffff */
subl $0x80000001, %eax
cmpl $(0x8000ffff-0x80000001), %eax
- ja enable_paging
+ ja .Lenable_paging
/* Clear bogus XD_DISABLE bits */
call verify_cpu
@@ -379,7 +379,7 @@ default_entry:
cpuid
/* Execute Disable bit supported? */
btl $(X86_FEATURE_NX & 31), %edx
- jnc enable_paging
+ jnc .Lenable_paging
/* Setup EFER (Extended Feature Enable Register) */
movl $MSR_EFER, %ecx
@@ -389,7 +389,7 @@ default_entry:
/* Make changes effective */
wrmsr
-enable_paging:
+.Lenable_paging:
/*
* Enable paging
@@ -418,7 +418,7 @@ enable_paging:
*/
movb $4,X86 # at least 486
cmpl $-1,X86_CPUID
- je is486
+ je .Lis486
/* get vendor info */
xorl %eax,%eax # call CPUID with 0 -> return vendor ID
@@ -429,7 +429,7 @@ enable_paging:
movl %ecx,X86_VENDOR_ID+8 # last 4 chars
orl %eax,%eax # do we have processor info as well?
- je is486
+ je .Lis486
movl $1,%eax # Use the CPUID instruction to get CPU type
cpuid
@@ -443,7 +443,7 @@ enable_paging:
movb %cl,X86_MASK
movl %edx,X86_CAPABILITY
-is486:
+.Lis486:
movl $0x50022,%ecx # set AM, WP, NE and MP
movl %cr0,%eax
andl $0x80000011,%eax # Save PG,PE,ET
--
2.7.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 2/9] x86/entry/32: rename 'error_code' to 'common_exception'
2016-09-21 21:03 [PATCH v2 0/9] x86/entry/head: standardize the end of the stack Josh Poimboeuf
2016-09-21 21:03 ` [PATCH v2 1/9] x86/entry/head/32: use local labels Josh Poimboeuf
@ 2016-09-21 21:04 ` Josh Poimboeuf
2016-10-20 11:08 ` [tip:x86/asm] x86/entry/32: Rename " tip-bot for Josh Poimboeuf
2016-09-21 21:04 ` [PATCH v2 3/9] x86/entry/32: fix the end of the stack for newly forked tasks Josh Poimboeuf
` (7 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Josh Poimboeuf @ 2016-09-21 21:04 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H . Peter Anvin
Cc: x86, linux-kernel, Andy Lutomirski, Linus Torvalds, Brian Gerst,
Peter Zijlstra, Nilay Vaish
The 'error_code' label is awkwardly named, especially when it shows up
in a stack trace. Move it to its own local function and rename it to
'common_exception', analagous to the existing 'common_interrupt'.
This also makes related stack traces more sensible.
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
---
arch/x86/entry/entry_32.S | 43 +++++++++++++++++++++++--------------------
1 file changed, 23 insertions(+), 20 deletions(-)
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index 7ff0462..dae8684 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -528,7 +528,7 @@ restore_all:
ENTRY(iret_exc )
pushl $0 # no error code
pushl $do_iret_error
- jmp error_code
+ jmp common_exception
.previous
_ASM_EXTABLE(.Lirq_return, iret_exc)
@@ -659,7 +659,7 @@ ENTRY(coprocessor_error)
ASM_CLAC
pushl $0
pushl $do_coprocessor_error
- jmp error_code
+ jmp common_exception
END(coprocessor_error)
ENTRY(simd_coprocessor_error)
@@ -673,14 +673,14 @@ ENTRY(simd_coprocessor_error)
#else
pushl $do_simd_coprocessor_error
#endif
- jmp error_code
+ jmp common_exception
END(simd_coprocessor_error)
ENTRY(device_not_available)
ASM_CLAC
pushl $-1 # mark this as an int
pushl $do_device_not_available
- jmp error_code
+ jmp common_exception
END(device_not_available)
#ifdef CONFIG_PARAVIRT
@@ -694,59 +694,59 @@ ENTRY(overflow)
ASM_CLAC
pushl $0
pushl $do_overflow
- jmp error_code
+ jmp common_exception
END(overflow)
ENTRY(bounds)
ASM_CLAC
pushl $0
pushl $do_bounds
- jmp error_code
+ jmp common_exception
END(bounds)
ENTRY(invalid_op)
ASM_CLAC
pushl $0
pushl $do_invalid_op
- jmp error_code
+ jmp common_exception
END(invalid_op)
ENTRY(coprocessor_segment_overrun)
ASM_CLAC
pushl $0
pushl $do_coprocessor_segment_overrun
- jmp error_code
+ jmp common_exception
END(coprocessor_segment_overrun)
ENTRY(invalid_TSS)
ASM_CLAC
pushl $do_invalid_TSS
- jmp error_code
+ jmp common_exception
END(invalid_TSS)
ENTRY(segment_not_present)
ASM_CLAC
pushl $do_segment_not_present
- jmp error_code
+ jmp common_exception
END(segment_not_present)
ENTRY(stack_segment)
ASM_CLAC
pushl $do_stack_segment
- jmp error_code
+ jmp common_exception
END(stack_segment)
ENTRY(alignment_check)
ASM_CLAC
pushl $do_alignment_check
- jmp error_code
+ jmp common_exception
END(alignment_check)
ENTRY(divide_error)
ASM_CLAC
pushl $0 # no error code
pushl $do_divide_error
- jmp error_code
+ jmp common_exception
END(divide_error)
#ifdef CONFIG_X86_MCE
@@ -754,7 +754,7 @@ ENTRY(machine_check)
ASM_CLAC
pushl $0
pushl machine_check_vector
- jmp error_code
+ jmp common_exception
END(machine_check)
#endif
@@ -762,7 +762,7 @@ ENTRY(spurious_interrupt_bug)
ASM_CLAC
pushl $0
pushl $do_spurious_interrupt_bug
- jmp error_code
+ jmp common_exception
END(spurious_interrupt_bug)
#ifdef CONFIG_XEN
@@ -1026,7 +1026,7 @@ return_to_handler:
ENTRY(trace_page_fault)
ASM_CLAC
pushl $trace_do_page_fault
- jmp error_code
+ jmp common_exception
END(trace_page_fault)
#endif
@@ -1034,7 +1034,10 @@ ENTRY(page_fault)
ASM_CLAC
pushl $do_page_fault
ALIGN
-error_code:
+ jmp common_exception
+END(page_fault)
+
+common_exception:
/* the function address is in %gs's slot on the stack */
pushl %fs
pushl %es
@@ -1063,7 +1066,7 @@ error_code:
movl %esp, %eax # pt_regs pointer
call *%edi
jmp ret_from_exception
-END(page_fault)
+END(common_exception)
ENTRY(debug)
/*
@@ -1180,14 +1183,14 @@ END(int3)
ENTRY(general_protection)
pushl $do_general_protection
- jmp error_code
+ jmp common_exception
END(general_protection)
#ifdef CONFIG_KVM_GUEST
ENTRY(async_page_fault)
ASM_CLAC
pushl $do_async_page_fault
- jmp error_code
+ jmp common_exception
END(async_page_fault)
#endif
--
2.7.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 3/9] x86/entry/32: fix the end of the stack for newly forked tasks
2016-09-21 21:03 [PATCH v2 0/9] x86/entry/head: standardize the end of the stack Josh Poimboeuf
2016-09-21 21:03 ` [PATCH v2 1/9] x86/entry/head/32: use local labels Josh Poimboeuf
2016-09-21 21:04 ` [PATCH v2 2/9] x86/entry/32: rename 'error_code' to 'common_exception' Josh Poimboeuf
@ 2016-09-21 21:04 ` Josh Poimboeuf
2016-10-20 11:09 ` [tip:x86/asm] x86/entry/32: Fix " tip-bot for Josh Poimboeuf
2016-09-21 21:04 ` [PATCH v2 4/9] x86/head/32: fix the end of the stack for idle tasks Josh Poimboeuf
` (6 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Josh Poimboeuf @ 2016-09-21 21:04 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H . Peter Anvin
Cc: x86, linux-kernel, Andy Lutomirski, Linus Torvalds, Brian Gerst,
Peter Zijlstra, Nilay Vaish
Thanks to all the recent x86 entry code refactoring, most tasks' kernel
stacks start at the same offset right below their saved pt_regs,
regardless of which syscall was used to enter the kernel. That creates
a nice convention which makes it straightforward to identify the end of
the stack, which can be useful for the unwinder to verify the stack is
sane.
Calling schedule_tail() directly breaks that convention because its an
asmlinkage function so its argument has to be pushed on the stack. Add
a wrapper which creates a proper "end of stack" frame header before the
call.
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
---
arch/x86/entry/entry_32.S | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index dae8684..82b55ef 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -44,6 +44,7 @@
#include <asm/alternative-asm.h>
#include <asm/asm.h>
#include <asm/smap.h>
+#include <asm/frame.h>
.section .entry.text, "ax"
@@ -237,6 +238,23 @@ ENTRY(__switch_to_asm)
END(__switch_to_asm)
/*
+ * The unwinder expects the last frame on the stack to always be at the same
+ * offset from the end of the page, which allows it to validate the stack.
+ * Calling schedule_tail() directly would break that convention because its an
+ * asmlinkage function so its argument has to be pushed on the stack. This
+ * wrapper creates a proper "end of stack" frame header before the call.
+ */
+ENTRY(schedule_tail_wrapper)
+ FRAME_BEGIN
+
+ pushl %eax
+ call schedule_tail
+ popl %eax
+
+ FRAME_END
+ ret
+ENDPROC(schedule_tail_wrapper)
+/*
* A newly forked process directly context switches into this address.
*
* eax: prev task we switched from
@@ -244,9 +262,7 @@ END(__switch_to_asm)
* edi: kernel thread arg
*/
ENTRY(ret_from_fork)
- pushl %eax
- call schedule_tail
- popl %eax
+ call schedule_tail_wrapper
testl %ebx, %ebx
jnz 1f /* kernel threads are uncommon */
--
2.7.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 4/9] x86/head/32: fix the end of the stack for idle tasks
2016-09-21 21:03 [PATCH v2 0/9] x86/entry/head: standardize the end of the stack Josh Poimboeuf
` (2 preceding siblings ...)
2016-09-21 21:04 ` [PATCH v2 3/9] x86/entry/32: fix the end of the stack for newly forked tasks Josh Poimboeuf
@ 2016-09-21 21:04 ` Josh Poimboeuf
2016-10-20 11:10 ` [tip:x86/asm] x86/boot/32: Fix " tip-bot for Josh Poimboeuf
2016-09-21 21:04 ` [PATCH v2 5/9] x86/smp: fix initial idle stack location on 32-bit Josh Poimboeuf
` (5 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Josh Poimboeuf @ 2016-09-21 21:04 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H . Peter Anvin
Cc: x86, linux-kernel, Andy Lutomirski, Linus Torvalds, Brian Gerst,
Peter Zijlstra, Nilay Vaish
The frame at the end of each idle task stack is inconsistent with real
task stacks, which have a stack frame header and a real return address
before the pt_regs area. This inconsistency can be confusing for stack
unwinders. It also hides useful information about what asm code was
involved in calling into C.
Fix that by changing the initial code jumps to calls. Also add infinite
loops after the calls to make it clear that the calls don't return, and
to hang if they do.
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
---
arch/x86/kernel/head_32.S | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 617fba2..7aac1b9 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -288,7 +288,8 @@ num_subarch_entries = (. - subarch_entries) / 4
ENTRY(start_cpu0)
movl initial_stack, %ecx
movl %ecx, %esp
- jmp *(initial_code)
+ call *(initial_code)
+1: jmp 1b
ENDPROC(start_cpu0)
#endif
@@ -469,8 +470,9 @@ ENTRY(startup_32_smp)
xorl %eax,%eax # Clear LDT
lldt %ax
- pushl $0 # fake return address for unwinder
- jmp *(initial_code)
+ call *(initial_code)
+1: jmp 1b
+ENDPROC(startup_32_smp)
#include "verify_cpu.S"
--
2.7.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 5/9] x86/smp: fix initial idle stack location on 32-bit
2016-09-21 21:03 [PATCH v2 0/9] x86/entry/head: standardize the end of the stack Josh Poimboeuf
` (3 preceding siblings ...)
2016-09-21 21:04 ` [PATCH v2 4/9] x86/head/32: fix the end of the stack for idle tasks Josh Poimboeuf
@ 2016-09-21 21:04 ` Josh Poimboeuf
2016-10-20 11:10 ` [tip:x86/asm] x86/boot/smp/32: Fix initial idle stack location on 32-bit kernels tip-bot for Josh Poimboeuf
2016-09-21 21:04 ` [PATCH v2 6/9] x86/asm/head: use a common function for starting CPUs Josh Poimboeuf
` (4 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Josh Poimboeuf @ 2016-09-21 21:04 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H . Peter Anvin
Cc: x86, linux-kernel, Andy Lutomirski, Linus Torvalds, Brian Gerst,
Peter Zijlstra, Nilay Vaish
On 32-bit, the initial idle stack calculation doesn't take into account
the TOP_OF_KERNEL_STACK_PADDING, making the stack end address
inconsistent with other tasks on 32-bit.
Reviewed-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
---
arch/x86/kernel/smpboot.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 039790b..9345072 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -963,9 +963,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
int cpu0_nmi_registered = 0;
unsigned long timeout;
- idle->thread.sp = (unsigned long) (((struct pt_regs *)
- (THREAD_SIZE + task_stack_page(idle))) - 1);
-
+ idle->thread.sp = (unsigned long)task_pt_regs(idle);
early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
initial_code = (unsigned long)start_secondary;
initial_stack = idle->thread.sp;
--
2.7.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 6/9] x86/asm/head: use a common function for starting CPUs
2016-09-21 21:03 [PATCH v2 0/9] x86/entry/head: standardize the end of the stack Josh Poimboeuf
` (4 preceding siblings ...)
2016-09-21 21:04 ` [PATCH v2 5/9] x86/smp: fix initial idle stack location on 32-bit Josh Poimboeuf
@ 2016-09-21 21:04 ` Josh Poimboeuf
2016-10-20 11:11 ` [tip:x86/asm] x86/boot/64: Use " tip-bot for Josh Poimboeuf
2016-09-21 21:04 ` [PATCH v2 7/9] x86/head: put real return address on idle task stack Josh Poimboeuf
` (3 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Josh Poimboeuf @ 2016-09-21 21:04 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H . Peter Anvin
Cc: x86, linux-kernel, Andy Lutomirski, Linus Torvalds, Brian Gerst,
Peter Zijlstra, Nilay Vaish
There are two different pieces of code for starting a CPU: start_cpu0()
and the end of secondary_startup_64(). They're identical except for the
stack setup. Combine the common parts into a shared start_cpu()
function.
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
---
arch/x86/kernel/head_64.S | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index c98a559..3621ad2 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -264,13 +264,17 @@ ENTRY(secondary_startup_64)
movl $MSR_GS_BASE,%ecx
movl initial_gs(%rip),%eax
movl initial_gs+4(%rip),%edx
- wrmsr
+ wrmsr
/* rsi is pointer to real mode structure with interesting info.
pass it to C */
movq %rsi, %rdi
-
- /* Finally jump to run C code and to be on real kernel address
+ jmp start_cpu
+ENDPROC(secondary_startup_64)
+
+ENTRY(start_cpu)
+ /*
+ * Jump to run C code and to be on a real kernel address.
* Since we are running on identity-mapped space we have to jump
* to the full 64bit address, this is only possible as indirect
* jump. In addition we need to ensure %cs is set so we make this
@@ -299,7 +303,7 @@ ENTRY(secondary_startup_64)
pushq $__KERNEL_CS # set correct cs
pushq %rax # target address in negative space
lretq
-ENDPROC(secondary_startup_64)
+ENDPROC(start_cpu)
#include "verify_cpu.S"
@@ -307,15 +311,11 @@ ENDPROC(secondary_startup_64)
/*
* Boot CPU0 entry point. It's called from play_dead(). Everything has been set
* up already except stack. We just set up stack here. Then call
- * start_secondary().
+ * start_secondary() via start_cpu().
*/
ENTRY(start_cpu0)
- movq initial_stack(%rip),%rsp
- movq initial_code(%rip),%rax
- pushq $0 # fake return address to stop unwinder
- pushq $__KERNEL_CS # set correct cs
- pushq %rax # target address in negative space
- lretq
+ movq initial_stack(%rip), %rsp
+ jmp start_cpu
ENDPROC(start_cpu0)
#endif
--
2.7.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 7/9] x86/head: put real return address on idle task stack
2016-09-21 21:03 [PATCH v2 0/9] x86/entry/head: standardize the end of the stack Josh Poimboeuf
` (5 preceding siblings ...)
2016-09-21 21:04 ` [PATCH v2 6/9] x86/asm/head: use a common function for starting CPUs Josh Poimboeuf
@ 2016-09-21 21:04 ` Josh Poimboeuf
2016-10-20 11:11 ` [tip:x86/asm] x86/boot/64: Put a real return address on the " tip-bot for Josh Poimboeuf
2016-09-21 21:04 ` [PATCH v2 8/9] x86/head: fix the end of the stack for idle tasks Josh Poimboeuf
` (2 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Josh Poimboeuf @ 2016-09-21 21:04 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H . Peter Anvin
Cc: x86, linux-kernel, Andy Lutomirski, Linus Torvalds, Brian Gerst,
Peter Zijlstra, Nilay Vaish
The frame at the end of each idle task stack has a zeroed return
address. This is inconsistent with real task stacks, which have a real
return address at that spot. This inconsistency can be confusing for
stack unwinders. It also hides useful information about what asm code
was involved in calling into C.
Make it a real address by using the side effect of a call instruction to
push the instruction pointer on the stack.
Reviewed-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
---
arch/x86/kernel/head_64.S | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index 3621ad2..c90f481 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -298,8 +298,9 @@ ENTRY(start_cpu)
* REX.W + FF /5 JMP m16:64 Jump far, absolute indirect,
* address given in m16:64.
*/
- movq initial_code(%rip),%rax
- pushq $0 # fake return address to stop unwinder
+ call 1f # put return address on stack for unwinder
+1: xorq %rbp, %rbp # clear frame pointer
+ movq initial_code(%rip), %rax
pushq $__KERNEL_CS # set correct cs
pushq %rax # target address in negative space
lretq
--
2.7.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 8/9] x86/head: fix the end of the stack for idle tasks
2016-09-21 21:03 [PATCH v2 0/9] x86/entry/head: standardize the end of the stack Josh Poimboeuf
` (6 preceding siblings ...)
2016-09-21 21:04 ` [PATCH v2 7/9] x86/head: put real return address on idle task stack Josh Poimboeuf
@ 2016-09-21 21:04 ` Josh Poimboeuf
2016-10-20 11:12 ` [tip:x86/asm] x86/boot: Fix " tip-bot for Josh Poimboeuf
2016-09-21 21:04 ` [PATCH v2 9/9] x86: move _stext marker to before head code Josh Poimboeuf
2016-10-18 17:17 ` [PATCH v2 0/9] x86/entry/head: standardize the end of the stack Josh Poimboeuf
9 siblings, 1 reply; 21+ messages in thread
From: Josh Poimboeuf @ 2016-09-21 21:04 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H . Peter Anvin
Cc: x86, linux-kernel, Andy Lutomirski, Linus Torvalds, Brian Gerst,
Peter Zijlstra, Nilay Vaish
Thanks to all the recent x86 entry code refactoring, most tasks' kernel
stacks start at the same offset right below their saved pt_regs,
regardless of which syscall was used to enter the kernel. That creates
a nice convention which makes it straightforward to identify the end of
the stack, which can be useful for the unwinder to verify the stack is
sane.
However, the boot CPU's idle "swapper" task doesn't follow that
convention. Fix that by starting its stack at a sizeof(pt_regs) offset
from the end of the stack page.
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
---
arch/x86/kernel/head_32.S | 9 ++++++++-
arch/x86/kernel/head_64.S | 15 +++++++--------
2 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 7aac1b9..d87bec4 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -62,6 +62,8 @@
#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
#endif
+#define SIZEOF_PTREGS 17*4
+
/*
* Number of possible pages in the lowmem region.
*
@@ -706,7 +708,12 @@ ENTRY(initial_page_table)
.data
.balign 4
ENTRY(initial_stack)
- .long init_thread_union+THREAD_SIZE
+ /*
+ * The SIZEOF_PTREGS gap is a convention which helps the in-kernel
+ * unwinder reliably detect the end of the stack.
+ */
+ .long init_thread_union + THREAD_SIZE - SIZEOF_PTREGS - \
+ TOP_OF_KERNEL_STACK_PADDING;
__INITRODATA
int_msg:
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index c90f481..ec332e9 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -65,13 +65,8 @@ startup_64:
* tables and then reload them.
*/
- /*
- * Setup stack for verify_cpu(). "-8" because initial_stack is defined
- * this way, see below. Our best guess is a NULL ptr for stack
- * termination heuristics and we don't want to break anything which
- * might depend on it (kgdb, ...).
- */
- leaq (__end_init_task - 8)(%rip), %rsp
+ /* Set up the stack for verify_cpu(), similar to initial_stack below */
+ leaq (__end_init_task - SIZEOF_PTREGS)(%rip), %rsp
/* Sanitize CPU configuration */
call verify_cpu
@@ -328,7 +323,11 @@ ENDPROC(start_cpu0)
GLOBAL(initial_gs)
.quad INIT_PER_CPU_VAR(irq_stack_union)
GLOBAL(initial_stack)
- .quad init_thread_union+THREAD_SIZE-8
+ /*
+ * The SIZEOF_PTREGS gap is a convention which helps the in-kernel
+ * unwinder reliably detect the end of the stack.
+ */
+ .quad init_thread_union + THREAD_SIZE - SIZEOF_PTREGS
__FINITDATA
bad_address:
--
2.7.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 9/9] x86: move _stext marker to before head code
2016-09-21 21:03 [PATCH v2 0/9] x86/entry/head: standardize the end of the stack Josh Poimboeuf
` (7 preceding siblings ...)
2016-09-21 21:04 ` [PATCH v2 8/9] x86/head: fix the end of the stack for idle tasks Josh Poimboeuf
@ 2016-09-21 21:04 ` Josh Poimboeuf
2016-10-20 11:12 ` [tip:x86/asm] x86/boot: Move the _stext marker to before the boot code tip-bot for Josh Poimboeuf
2016-10-18 17:17 ` [PATCH v2 0/9] x86/entry/head: standardize the end of the stack Josh Poimboeuf
9 siblings, 1 reply; 21+ messages in thread
From: Josh Poimboeuf @ 2016-09-21 21:04 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H . Peter Anvin
Cc: x86, linux-kernel, Andy Lutomirski, Linus Torvalds, Brian Gerst,
Peter Zijlstra, Nilay Vaish
When core_kernel_text() is used to determine whether an address on a
task's stack trace is a kernel text address, it incorrectly returns
false for early text addresses for the head code between the _text and
_stext markers. Among other things, this can cause the unwinder to
behave incorrectly when unwinding to x86 head code.
Head code is text code too, so mark it as such. This seems to match the
intent of other users of the _stext symbol, and it also seems consistent
with what other architectures are already doing.
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
---
arch/x86/kernel/vmlinux.lds.S | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 9297a00..1d9b636 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -91,10 +91,10 @@ SECTIONS
/* Text and read-only data */
.text : AT(ADDR(.text) - LOAD_OFFSET) {
_text = .;
+ _stext = .;
/* bootstrapping code */
HEAD_TEXT
. = ALIGN(8);
- _stext = .;
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
--
2.7.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v2 0/9] x86/entry/head: standardize the end of the stack
2016-09-21 21:03 [PATCH v2 0/9] x86/entry/head: standardize the end of the stack Josh Poimboeuf
` (8 preceding siblings ...)
2016-09-21 21:04 ` [PATCH v2 9/9] x86: move _stext marker to before head code Josh Poimboeuf
@ 2016-10-18 17:17 ` Josh Poimboeuf
2016-10-19 13:20 ` Ingo Molnar
9 siblings, 1 reply; 21+ messages in thread
From: Josh Poimboeuf @ 2016-10-18 17:17 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H . Peter Anvin
Cc: x86, linux-kernel, Andy Lutomirski, Linus Torvalds, Brian Gerst,
Peter Zijlstra, Nilay Vaish
On Wed, Sep 21, 2016 at 04:03:58PM -0500, Josh Poimboeuf wrote:
> v2:
> - keep 'restore_all' label in "x86/entry/head/32: use local labels"
>
> ---
>
> Thanks to all the recent x86 entry code refactoring, most tasks' kernel
> stacks start at the same offset right below their saved pt_regs,
> regardless of which syscall was used to enter the kernel. That creates
> a nice convention which makes it straightforward to identify the end of
> the stack, which can be useful [*] for the unwinder.
>
> But there a few places where tasks don't yet follow the convention.
> This patch set finishes the job.
>
> [*] This will be useful for three upcoming proposed features:
>
> - Detecting corrupt stacks in the unwinder (which will also be a force
> for ensuring this end of stack convention continues to be followed in
> the future).
>
> - Printing all saved pt_regs on the stack during an oops/warning.
>
> - Validating stacks in the livepatch consistency model.
Ping?
--
Josh
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 0/9] x86/entry/head: standardize the end of the stack
2016-10-18 17:17 ` [PATCH v2 0/9] x86/entry/head: standardize the end of the stack Josh Poimboeuf
@ 2016-10-19 13:20 ` Ingo Molnar
0 siblings, 0 replies; 21+ messages in thread
From: Ingo Molnar @ 2016-10-19 13:20 UTC (permalink / raw)
To: Josh Poimboeuf
Cc: Thomas Gleixner, H . Peter Anvin, x86, linux-kernel,
Andy Lutomirski, Linus Torvalds, Brian Gerst, Peter Zijlstra,
Nilay Vaish
* Josh Poimboeuf <jpoimboe@redhat.com> wrote:
> On Wed, Sep 21, 2016 at 04:03:58PM -0500, Josh Poimboeuf wrote:
> > v2:
> > - keep 'restore_all' label in "x86/entry/head/32: use local labels"
> >
> > ---
> >
> > Thanks to all the recent x86 entry code refactoring, most tasks' kernel
> > stacks start at the same offset right below their saved pt_regs,
> > regardless of which syscall was used to enter the kernel. That creates
> > a nice convention which makes it straightforward to identify the end of
> > the stack, which can be useful [*] for the unwinder.
> >
> > But there a few places where tasks don't yet follow the convention.
> > This patch set finishes the job.
> >
> > [*] This will be useful for three upcoming proposed features:
> >
> > - Detecting corrupt stacks in the unwinder (which will also be a force
> > for ensuring this end of stack convention continues to be followed in
> > the future).
> >
> > - Printing all saved pt_regs on the stack during an oops/warning.
> >
> > - Validating stacks in the livepatch consistency model.
>
> Ping?
Missed this one: I expected more discussion but nobody replied so it went missing.
Will have a look later this week!
Thanks,
Ingo
^ permalink raw reply [flat|nested] 21+ messages in thread
* [tip:x86/asm] x86/entry/32, x86/boot/32: Use local labels
2016-09-21 21:03 ` [PATCH v2 1/9] x86/entry/head/32: use local labels Josh Poimboeuf
@ 2016-10-20 11:08 ` tip-bot for Josh Poimboeuf
0 siblings, 0 replies; 21+ messages in thread
From: tip-bot for Josh Poimboeuf @ 2016-10-20 11:08 UTC (permalink / raw)
To: linux-tip-commits
Cc: dvlasenk, mingo, brgerst, hpa, jpoimboe, peterz, torvalds,
linux-kernel, bp, nilayvaish, tglx, luto
Commit-ID: 1b00255f32b94b61897c83a22c05ed7d33229957
Gitweb: http://git.kernel.org/tip/1b00255f32b94b61897c83a22c05ed7d33229957
Author: Josh Poimboeuf <jpoimboe@redhat.com>
AuthorDate: Wed, 21 Sep 2016 16:03:59 -0500
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Thu, 20 Oct 2016 09:15:22 +0200
x86/entry/32, x86/boot/32: Use local labels
Add the local label prefix to all non-function named labels in head_32.S
and entry_32.S. In addition to decluttering the symbol table, it also
will help stack traces to be more sensible. For example, the last
reported function in the idle task stack trace will be startup_32_smp()
instead of is486().
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Nilay Vaish <nilayvaish@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/14f9f7afd478b23a762f40734da1a57c0c273f6e.1474480779.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
arch/x86/entry/entry_32.S | 43 ++++++++++++++++++++++---------------------
arch/x86/kernel/head_32.S | 32 ++++++++++++++++----------------
2 files changed, 38 insertions(+), 37 deletions(-)
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index 21b352a..b03c1cb 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -307,13 +307,13 @@ END(ret_from_exception)
#ifdef CONFIG_PREEMPT
ENTRY(resume_kernel)
DISABLE_INTERRUPTS(CLBR_ANY)
-need_resched:
+.Lneed_resched:
cmpl $0, PER_CPU_VAR(__preempt_count)
jnz restore_all
testl $X86_EFLAGS_IF, PT_EFLAGS(%esp) # interrupts off (exception path) ?
jz restore_all
call preempt_schedule_irq
- jmp need_resched
+ jmp .Lneed_resched
END(resume_kernel)
#endif
@@ -334,7 +334,7 @@ GLOBAL(__begin_SYSENTER_singlestep_region)
*/
ENTRY(xen_sysenter_target)
addl $5*4, %esp /* remove xen-provided frame */
- jmp sysenter_past_esp
+ jmp .Lsysenter_past_esp
#endif
/*
@@ -371,7 +371,7 @@ ENTRY(xen_sysenter_target)
*/
ENTRY(entry_SYSENTER_32)
movl TSS_sysenter_sp0(%esp), %esp
-sysenter_past_esp:
+.Lsysenter_past_esp:
pushl $__USER_DS /* pt_regs->ss */
pushl %ebp /* pt_regs->sp (stashed in bp) */
pushfl /* pt_regs->flags (except IF = 0) */
@@ -504,9 +504,9 @@ ENTRY(entry_INT80_32)
restore_all:
TRACE_IRQS_IRET
-restore_all_notrace:
+.Lrestore_all_notrace:
#ifdef CONFIG_X86_ESPFIX32
- ALTERNATIVE "jmp restore_nocheck", "", X86_BUG_ESPFIX
+ ALTERNATIVE "jmp .Lrestore_nocheck", "", X86_BUG_ESPFIX
movl PT_EFLAGS(%esp), %eax # mix EFLAGS, SS and CS
/*
@@ -518,22 +518,23 @@ restore_all_notrace:
movb PT_CS(%esp), %al
andl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
- je ldt_ss # returning to user-space with LDT SS
+ je .Lldt_ss # returning to user-space with LDT SS
#endif
-restore_nocheck:
+.Lrestore_nocheck:
RESTORE_REGS 4 # skip orig_eax/error_code
-irq_return:
+.Lirq_return:
INTERRUPT_RETURN
+
.section .fixup, "ax"
ENTRY(iret_exc )
pushl $0 # no error code
pushl $do_iret_error
jmp error_code
.previous
- _ASM_EXTABLE(irq_return, iret_exc)
+ _ASM_EXTABLE(.Lirq_return, iret_exc)
#ifdef CONFIG_X86_ESPFIX32
-ldt_ss:
+.Lldt_ss:
/*
* Setup and switch to ESPFIX stack
*
@@ -562,7 +563,7 @@ ldt_ss:
*/
DISABLE_INTERRUPTS(CLBR_EAX)
lss (%esp), %esp /* switch to espfix segment */
- jmp restore_nocheck
+ jmp .Lrestore_nocheck
#endif
ENDPROC(entry_INT80_32)
@@ -882,7 +883,7 @@ ftrace_call:
popl %edx
popl %ecx
popl %eax
-ftrace_ret:
+.Lftrace_ret:
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
.globl ftrace_graph_call
ftrace_graph_call:
@@ -952,7 +953,7 @@ GLOBAL(ftrace_regs_call)
popl %gs
addl $8, %esp /* Skip orig_ax and ip */
popf /* Pop flags at end (no addl to corrupt flags) */
- jmp ftrace_ret
+ jmp .Lftrace_ret
popf
jmp ftrace_stub
@@ -963,7 +964,7 @@ ENTRY(mcount)
jb ftrace_stub /* Paging not enabled yet? */
cmpl $ftrace_stub, ftrace_trace_function
- jnz trace
+ jnz .Ltrace
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
cmpl $ftrace_stub, ftrace_graph_return
jnz ftrace_graph_caller
@@ -976,7 +977,7 @@ ftrace_stub:
ret
/* taken from glibc */
-trace:
+.Ltrace:
pushl %eax
pushl %ecx
pushl %edx
@@ -1116,7 +1117,7 @@ ENTRY(nmi)
movl %ss, %eax
cmpw $__ESPFIX_SS, %ax
popl %eax
- je nmi_espfix_stack
+ je .Lnmi_espfix_stack
#endif
pushl %eax # pt_regs->orig_ax
@@ -1132,7 +1133,7 @@ ENTRY(nmi)
/* Not on SYSENTER stack. */
call do_nmi
- jmp restore_all_notrace
+ jmp .Lrestore_all_notrace
.Lnmi_from_sysenter_stack:
/*
@@ -1143,10 +1144,10 @@ ENTRY(nmi)
movl PER_CPU_VAR(cpu_current_top_of_stack), %esp
call do_nmi
movl %ebp, %esp
- jmp restore_all_notrace
+ jmp .Lrestore_all_notrace
#ifdef CONFIG_X86_ESPFIX32
-nmi_espfix_stack:
+.Lnmi_espfix_stack:
/*
* create the pointer to lss back
*/
@@ -1164,7 +1165,7 @@ nmi_espfix_stack:
call do_nmi
RESTORE_REGS
lss 12+4(%esp), %esp # back to espfix stack
- jmp irq_return
+ jmp .Lirq_return
#endif
END(nmi)
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index b6b2f02..65e6225 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -248,19 +248,19 @@ page_pde_offset = (__PAGE_OFFSET >> 20);
#ifdef CONFIG_PARAVIRT
/* This is can only trip for a broken bootloader... */
cmpw $0x207, pa(boot_params + BP_version)
- jb default_entry
+ jb .Ldefault_entry
/* Paravirt-compatible boot parameters. Look to see what architecture
we're booting under. */
movl pa(boot_params + BP_hardware_subarch), %eax
cmpl $num_subarch_entries, %eax
- jae bad_subarch
+ jae .Lbad_subarch
movl pa(subarch_entries)(,%eax,4), %eax
subl $__PAGE_OFFSET, %eax
jmp *%eax
-bad_subarch:
+.Lbad_subarch:
WEAK(lguest_entry)
WEAK(xen_entry)
/* Unknown implementation; there's really
@@ -270,14 +270,14 @@ WEAK(xen_entry)
__INITDATA
subarch_entries:
- .long default_entry /* normal x86/PC */
+ .long .Ldefault_entry /* normal x86/PC */
.long lguest_entry /* lguest hypervisor */
.long xen_entry /* Xen hypervisor */
- .long default_entry /* Moorestown MID */
+ .long .Ldefault_entry /* Moorestown MID */
num_subarch_entries = (. - subarch_entries) / 4
.previous
#else
- jmp default_entry
+ jmp .Ldefault_entry
#endif /* CONFIG_PARAVIRT */
#ifdef CONFIG_HOTPLUG_CPU
@@ -317,7 +317,7 @@ ENTRY(startup_32_smp)
call load_ucode_ap
#endif
-default_entry:
+.Ldefault_entry:
#define CR0_STATE (X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | \
X86_CR0_NE | X86_CR0_WP | X86_CR0_AM | \
X86_CR0_PG)
@@ -347,7 +347,7 @@ default_entry:
pushfl
popl %eax # get EFLAGS
testl $X86_EFLAGS_ID,%eax # did EFLAGS.ID remained set?
- jz enable_paging # hw disallowed setting of ID bit
+ jz .Lenable_paging # hw disallowed setting of ID bit
# which means no CPUID and no CR4
xorl %eax,%eax
@@ -357,13 +357,13 @@ default_entry:
movl $1,%eax
cpuid
andl $~1,%edx # Ignore CPUID.FPU
- jz enable_paging # No flags or only CPUID.FPU = no CR4
+ jz .Lenable_paging # No flags or only CPUID.FPU = no CR4
movl pa(mmu_cr4_features),%eax
movl %eax,%cr4
testb $X86_CR4_PAE, %al # check if PAE is enabled
- jz enable_paging
+ jz .Lenable_paging
/* Check if extended functions are implemented */
movl $0x80000000, %eax
@@ -371,7 +371,7 @@ default_entry:
/* Value must be in the range 0x80000001 to 0x8000ffff */
subl $0x80000001, %eax
cmpl $(0x8000ffff-0x80000001), %eax
- ja enable_paging
+ ja .Lenable_paging
/* Clear bogus XD_DISABLE bits */
call verify_cpu
@@ -380,7 +380,7 @@ default_entry:
cpuid
/* Execute Disable bit supported? */
btl $(X86_FEATURE_NX & 31), %edx
- jnc enable_paging
+ jnc .Lenable_paging
/* Setup EFER (Extended Feature Enable Register) */
movl $MSR_EFER, %ecx
@@ -390,7 +390,7 @@ default_entry:
/* Make changes effective */
wrmsr
-enable_paging:
+.Lenable_paging:
/*
* Enable paging
@@ -419,7 +419,7 @@ enable_paging:
*/
movb $4,X86 # at least 486
cmpl $-1,X86_CPUID
- je is486
+ je .Lis486
/* get vendor info */
xorl %eax,%eax # call CPUID with 0 -> return vendor ID
@@ -430,7 +430,7 @@ enable_paging:
movl %ecx,X86_VENDOR_ID+8 # last 4 chars
orl %eax,%eax # do we have processor info as well?
- je is486
+ je .Lis486
movl $1,%eax # Use the CPUID instruction to get CPU type
cpuid
@@ -444,7 +444,7 @@ enable_paging:
movb %cl,X86_MASK
movl %edx,X86_CAPABILITY
-is486:
+.Lis486:
movl $0x50022,%ecx # set AM, WP, NE and MP
movl %cr0,%eax
andl $0x80000011,%eax # Save PG,PE,ET
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [tip:x86/asm] x86/entry/32: Rename 'error_code' to 'common_exception'
2016-09-21 21:04 ` [PATCH v2 2/9] x86/entry/32: rename 'error_code' to 'common_exception' Josh Poimboeuf
@ 2016-10-20 11:08 ` tip-bot for Josh Poimboeuf
0 siblings, 0 replies; 21+ messages in thread
From: tip-bot for Josh Poimboeuf @ 2016-10-20 11:08 UTC (permalink / raw)
To: linux-tip-commits
Cc: brgerst, bp, peterz, luto, linux-kernel, jpoimboe, mingo, tglx,
hpa, dvlasenk, torvalds, nilayvaish
Commit-ID: 7252c4c35e94863bc13f37b4faad3087250a1588
Gitweb: http://git.kernel.org/tip/7252c4c35e94863bc13f37b4faad3087250a1588
Author: Josh Poimboeuf <jpoimboe@redhat.com>
AuthorDate: Wed, 21 Sep 2016 16:04:00 -0500
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Thu, 20 Oct 2016 09:15:22 +0200
x86/entry/32: Rename 'error_code' to 'common_exception'
The 'error_code' label is awkwardly named, especially when it shows up
in a stack trace. Move it to its own local function and rename it to
'common_exception', analagous to the existing 'common_interrupt'.
This also makes related stack traces more sensible.
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Nilay Vaish <nilayvaish@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/cca1734a93e52799556d946281b32468f9b93950.1474480779.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
arch/x86/entry/entry_32.S | 43 +++++++++++++++++++++++--------------------
1 file changed, 23 insertions(+), 20 deletions(-)
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index b03c1cb..9bd0087 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -529,7 +529,7 @@ restore_all:
ENTRY(iret_exc )
pushl $0 # no error code
pushl $do_iret_error
- jmp error_code
+ jmp common_exception
.previous
_ASM_EXTABLE(.Lirq_return, iret_exc)
@@ -660,7 +660,7 @@ ENTRY(coprocessor_error)
ASM_CLAC
pushl $0
pushl $do_coprocessor_error
- jmp error_code
+ jmp common_exception
END(coprocessor_error)
ENTRY(simd_coprocessor_error)
@@ -674,14 +674,14 @@ ENTRY(simd_coprocessor_error)
#else
pushl $do_simd_coprocessor_error
#endif
- jmp error_code
+ jmp common_exception
END(simd_coprocessor_error)
ENTRY(device_not_available)
ASM_CLAC
pushl $-1 # mark this as an int
pushl $do_device_not_available
- jmp error_code
+ jmp common_exception
END(device_not_available)
#ifdef CONFIG_PARAVIRT
@@ -695,59 +695,59 @@ ENTRY(overflow)
ASM_CLAC
pushl $0
pushl $do_overflow
- jmp error_code
+ jmp common_exception
END(overflow)
ENTRY(bounds)
ASM_CLAC
pushl $0
pushl $do_bounds
- jmp error_code
+ jmp common_exception
END(bounds)
ENTRY(invalid_op)
ASM_CLAC
pushl $0
pushl $do_invalid_op
- jmp error_code
+ jmp common_exception
END(invalid_op)
ENTRY(coprocessor_segment_overrun)
ASM_CLAC
pushl $0
pushl $do_coprocessor_segment_overrun
- jmp error_code
+ jmp common_exception
END(coprocessor_segment_overrun)
ENTRY(invalid_TSS)
ASM_CLAC
pushl $do_invalid_TSS
- jmp error_code
+ jmp common_exception
END(invalid_TSS)
ENTRY(segment_not_present)
ASM_CLAC
pushl $do_segment_not_present
- jmp error_code
+ jmp common_exception
END(segment_not_present)
ENTRY(stack_segment)
ASM_CLAC
pushl $do_stack_segment
- jmp error_code
+ jmp common_exception
END(stack_segment)
ENTRY(alignment_check)
ASM_CLAC
pushl $do_alignment_check
- jmp error_code
+ jmp common_exception
END(alignment_check)
ENTRY(divide_error)
ASM_CLAC
pushl $0 # no error code
pushl $do_divide_error
- jmp error_code
+ jmp common_exception
END(divide_error)
#ifdef CONFIG_X86_MCE
@@ -755,7 +755,7 @@ ENTRY(machine_check)
ASM_CLAC
pushl $0
pushl machine_check_vector
- jmp error_code
+ jmp common_exception
END(machine_check)
#endif
@@ -763,7 +763,7 @@ ENTRY(spurious_interrupt_bug)
ASM_CLAC
pushl $0
pushl $do_spurious_interrupt_bug
- jmp error_code
+ jmp common_exception
END(spurious_interrupt_bug)
#ifdef CONFIG_XEN
@@ -1028,7 +1028,7 @@ return_to_handler:
ENTRY(trace_page_fault)
ASM_CLAC
pushl $trace_do_page_fault
- jmp error_code
+ jmp common_exception
END(trace_page_fault)
#endif
@@ -1036,7 +1036,10 @@ ENTRY(page_fault)
ASM_CLAC
pushl $do_page_fault
ALIGN
-error_code:
+ jmp common_exception
+END(page_fault)
+
+common_exception:
/* the function address is in %gs's slot on the stack */
pushl %fs
pushl %es
@@ -1065,7 +1068,7 @@ error_code:
movl %esp, %eax # pt_regs pointer
call *%edi
jmp ret_from_exception
-END(page_fault)
+END(common_exception)
ENTRY(debug)
/*
@@ -1182,14 +1185,14 @@ END(int3)
ENTRY(general_protection)
pushl $do_general_protection
- jmp error_code
+ jmp common_exception
END(general_protection)
#ifdef CONFIG_KVM_GUEST
ENTRY(async_page_fault)
ASM_CLAC
pushl $do_async_page_fault
- jmp error_code
+ jmp common_exception
END(async_page_fault)
#endif
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [tip:x86/asm] x86/entry/32: Fix the end of the stack for newly forked tasks
2016-09-21 21:04 ` [PATCH v2 3/9] x86/entry/32: fix the end of the stack for newly forked tasks Josh Poimboeuf
@ 2016-10-20 11:09 ` tip-bot for Josh Poimboeuf
0 siblings, 0 replies; 21+ messages in thread
From: tip-bot for Josh Poimboeuf @ 2016-10-20 11:09 UTC (permalink / raw)
To: linux-tip-commits
Cc: brgerst, jpoimboe, nilayvaish, mingo, luto, peterz, bp, dvlasenk,
torvalds, hpa, linux-kernel, tglx
Commit-ID: 4d516f41704055710da872b62ddc4b6d23248984
Gitweb: http://git.kernel.org/tip/4d516f41704055710da872b62ddc4b6d23248984
Author: Josh Poimboeuf <jpoimboe@redhat.com>
AuthorDate: Wed, 21 Sep 2016 16:04:01 -0500
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Thu, 20 Oct 2016 09:15:22 +0200
x86/entry/32: Fix the end of the stack for newly forked tasks
Thanks to all the recent x86 entry code refactoring, most tasks' kernel
stacks start at the same offset right below their saved pt_regs,
regardless of which syscall was used to enter the kernel. That creates
a nice convention which makes it straightforward to identify the end of
the stack, which can be useful for the unwinder to verify the stack is
sane.
Calling schedule_tail() directly breaks that convention because its an
asmlinkage function so its argument has to be pushed on the stack. Add
a wrapper which creates a proper "end of stack" frame header before the
call.
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Nilay Vaish <nilayvaish@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/ecafcd882676bf48ceaf50483782552bb98476e5.1474480779.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
arch/x86/entry/entry_32.S | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index 9bd0087..2225105 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -45,6 +45,7 @@
#include <asm/asm.h>
#include <asm/smap.h>
#include <asm/export.h>
+#include <asm/frame.h>
.section .entry.text, "ax"
@@ -238,6 +239,23 @@ ENTRY(__switch_to_asm)
END(__switch_to_asm)
/*
+ * The unwinder expects the last frame on the stack to always be at the same
+ * offset from the end of the page, which allows it to validate the stack.
+ * Calling schedule_tail() directly would break that convention because its an
+ * asmlinkage function so its argument has to be pushed on the stack. This
+ * wrapper creates a proper "end of stack" frame header before the call.
+ */
+ENTRY(schedule_tail_wrapper)
+ FRAME_BEGIN
+
+ pushl %eax
+ call schedule_tail
+ popl %eax
+
+ FRAME_END
+ ret
+ENDPROC(schedule_tail_wrapper)
+/*
* A newly forked process directly context switches into this address.
*
* eax: prev task we switched from
@@ -245,9 +263,7 @@ END(__switch_to_asm)
* edi: kernel thread arg
*/
ENTRY(ret_from_fork)
- pushl %eax
- call schedule_tail
- popl %eax
+ call schedule_tail_wrapper
testl %ebx, %ebx
jnz 1f /* kernel threads are uncommon */
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [tip:x86/asm] x86/boot/32: Fix the end of the stack for idle tasks
2016-09-21 21:04 ` [PATCH v2 4/9] x86/head/32: fix the end of the stack for idle tasks Josh Poimboeuf
@ 2016-10-20 11:10 ` tip-bot for Josh Poimboeuf
0 siblings, 0 replies; 21+ messages in thread
From: tip-bot for Josh Poimboeuf @ 2016-10-20 11:10 UTC (permalink / raw)
To: linux-tip-commits
Cc: jpoimboe, peterz, brgerst, tglx, hpa, luto, torvalds, mingo,
linux-kernel, dvlasenk, bp, nilayvaish
Commit-ID: 6616a147a79c6fc280572f5a993e9e5ebd200d24
Gitweb: http://git.kernel.org/tip/6616a147a79c6fc280572f5a993e9e5ebd200d24
Author: Josh Poimboeuf <jpoimboe@redhat.com>
AuthorDate: Wed, 21 Sep 2016 16:04:02 -0500
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Thu, 20 Oct 2016 09:15:23 +0200
x86/boot/32: Fix the end of the stack for idle tasks
The frame at the end of each idle task stack is inconsistent with real
task stacks, which have a stack frame header and a real return address
before the pt_regs area. This inconsistency can be confusing for stack
unwinders. It also hides useful information about what asm code was
involved in calling into C.
Fix that by changing the initial code jumps to calls. Also add infinite
loops after the calls to make it clear that the calls don't return, and
to hang if they do.
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Nilay Vaish <nilayvaish@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/2588f34b6fbac4ae6f6f9ead2a78d7f8d58a6341.1474480779.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
arch/x86/kernel/head_32.S | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 65e6225..9a6f8e8 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -289,7 +289,8 @@ num_subarch_entries = (. - subarch_entries) / 4
ENTRY(start_cpu0)
movl initial_stack, %ecx
movl %ecx, %esp
- jmp *(initial_code)
+ call *(initial_code)
+1: jmp 1b
ENDPROC(start_cpu0)
#endif
@@ -470,8 +471,9 @@ ENTRY(startup_32_smp)
xorl %eax,%eax # Clear LDT
lldt %ax
- pushl $0 # fake return address for unwinder
- jmp *(initial_code)
+ call *(initial_code)
+1: jmp 1b
+ENDPROC(startup_32_smp)
#include "verify_cpu.S"
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [tip:x86/asm] x86/boot/smp/32: Fix initial idle stack location on 32-bit kernels
2016-09-21 21:04 ` [PATCH v2 5/9] x86/smp: fix initial idle stack location on 32-bit Josh Poimboeuf
@ 2016-10-20 11:10 ` tip-bot for Josh Poimboeuf
0 siblings, 0 replies; 21+ messages in thread
From: tip-bot for Josh Poimboeuf @ 2016-10-20 11:10 UTC (permalink / raw)
To: linux-tip-commits
Cc: hpa, mingo, peterz, tglx, luto, dvlasenk, nilayvaish,
linux-kernel, bp, jpoimboe, torvalds, brgerst
Commit-ID: b9b1a9c363ff7b17b2a35e20e28e86a449cfde1f
Gitweb: http://git.kernel.org/tip/b9b1a9c363ff7b17b2a35e20e28e86a449cfde1f
Author: Josh Poimboeuf <jpoimboe@redhat.com>
AuthorDate: Wed, 21 Sep 2016 16:04:03 -0500
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Thu, 20 Oct 2016 09:15:23 +0200
x86/boot/smp/32: Fix initial idle stack location on 32-bit kernels
On 32-bit kernels, the initial idle stack calculation doesn't take into
account the TOP_OF_KERNEL_STACK_PADDING, making the stack end address
inconsistent with other tasks on 32-bit.
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Reviewed-by: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Nilay Vaish <nilayvaish@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/6cf569410bfa84cf923902fc4d628444cace94be.1474480779.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
arch/x86/kernel/smpboot.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 951f093..dcbd45a 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -964,9 +964,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
int cpu0_nmi_registered = 0;
unsigned long timeout;
- idle->thread.sp = (unsigned long) (((struct pt_regs *)
- (THREAD_SIZE + task_stack_page(idle))) - 1);
-
+ idle->thread.sp = (unsigned long)task_pt_regs(idle);
early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
initial_code = (unsigned long)start_secondary;
initial_stack = idle->thread.sp;
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [tip:x86/asm] x86/boot/64: Use a common function for starting CPUs
2016-09-21 21:04 ` [PATCH v2 6/9] x86/asm/head: use a common function for starting CPUs Josh Poimboeuf
@ 2016-10-20 11:11 ` tip-bot for Josh Poimboeuf
0 siblings, 0 replies; 21+ messages in thread
From: tip-bot for Josh Poimboeuf @ 2016-10-20 11:11 UTC (permalink / raw)
To: linux-tip-commits
Cc: brgerst, nilayvaish, bp, linux-kernel, mingo, torvalds, dvlasenk,
jpoimboe, luto, hpa, tglx, peterz
Commit-ID: a9468df5ad48d06e5237fc2b56fb04c52f79c8c4
Gitweb: http://git.kernel.org/tip/a9468df5ad48d06e5237fc2b56fb04c52f79c8c4
Author: Josh Poimboeuf <jpoimboe@redhat.com>
AuthorDate: Wed, 21 Sep 2016 16:04:04 -0500
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Thu, 20 Oct 2016 09:15:23 +0200
x86/boot/64: Use a common function for starting CPUs
There are two different pieces of code for starting a CPU: start_cpu0()
and the end of secondary_startup_64(). They're identical except for the
stack setup. Combine the common parts into a shared start_cpu()
function.
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Nilay Vaish <nilayvaish@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1d692ffa62fcb3cc835a5b254e953f2d9bab3549.1474480779.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
arch/x86/kernel/head_64.S | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index b4421cc..3631777 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -265,13 +265,17 @@ ENTRY(secondary_startup_64)
movl $MSR_GS_BASE,%ecx
movl initial_gs(%rip),%eax
movl initial_gs+4(%rip),%edx
- wrmsr
+ wrmsr
/* rsi is pointer to real mode structure with interesting info.
pass it to C */
movq %rsi, %rdi
-
- /* Finally jump to run C code and to be on real kernel address
+ jmp start_cpu
+ENDPROC(secondary_startup_64)
+
+ENTRY(start_cpu)
+ /*
+ * Jump to run C code and to be on a real kernel address.
* Since we are running on identity-mapped space we have to jump
* to the full 64bit address, this is only possible as indirect
* jump. In addition we need to ensure %cs is set so we make this
@@ -300,7 +304,7 @@ ENTRY(secondary_startup_64)
pushq $__KERNEL_CS # set correct cs
pushq %rax # target address in negative space
lretq
-ENDPROC(secondary_startup_64)
+ENDPROC(start_cpu)
#include "verify_cpu.S"
@@ -308,15 +312,11 @@ ENDPROC(secondary_startup_64)
/*
* Boot CPU0 entry point. It's called from play_dead(). Everything has been set
* up already except stack. We just set up stack here. Then call
- * start_secondary().
+ * start_secondary() via start_cpu().
*/
ENTRY(start_cpu0)
- movq initial_stack(%rip),%rsp
- movq initial_code(%rip),%rax
- pushq $0 # fake return address to stop unwinder
- pushq $__KERNEL_CS # set correct cs
- pushq %rax # target address in negative space
- lretq
+ movq initial_stack(%rip), %rsp
+ jmp start_cpu
ENDPROC(start_cpu0)
#endif
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [tip:x86/asm] x86/boot/64: Put a real return address on the idle task stack
2016-09-21 21:04 ` [PATCH v2 7/9] x86/head: put real return address on idle task stack Josh Poimboeuf
@ 2016-10-20 11:11 ` tip-bot for Josh Poimboeuf
0 siblings, 0 replies; 21+ messages in thread
From: tip-bot for Josh Poimboeuf @ 2016-10-20 11:11 UTC (permalink / raw)
To: linux-tip-commits
Cc: nilayvaish, luto, hpa, linux-kernel, bp, torvalds, brgerst, tglx,
jpoimboe, dvlasenk, peterz, mingo
Commit-ID: 595c1e645d9fd8561104b5680931f68a429aaa1c
Gitweb: http://git.kernel.org/tip/595c1e645d9fd8561104b5680931f68a429aaa1c
Author: Josh Poimboeuf <jpoimboe@redhat.com>
AuthorDate: Wed, 21 Sep 2016 16:04:05 -0500
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Thu, 20 Oct 2016 09:15:23 +0200
x86/boot/64: Put a real return address on the idle task stack
The frame at the end of each idle task stack has a zeroed return
address. This is inconsistent with real task stacks, which have a real
return address at that spot. This inconsistency can be confusing for
stack unwinders. It also hides useful information about what asm code
was involved in calling into C.
Make it a real address by using the side effect of a call instruction to
push the instruction pointer on the stack.
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Reviewed-by: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Nilay Vaish <nilayvaish@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/f59593ae7b15d5126f872b0a23143173d28aa32d.1474480779.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
arch/x86/kernel/head_64.S | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index 3631777..1c5e5db 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -299,8 +299,9 @@ ENTRY(start_cpu)
* REX.W + FF /5 JMP m16:64 Jump far, absolute indirect,
* address given in m16:64.
*/
- movq initial_code(%rip),%rax
- pushq $0 # fake return address to stop unwinder
+ call 1f # put return address on stack for unwinder
+1: xorq %rbp, %rbp # clear frame pointer
+ movq initial_code(%rip), %rax
pushq $__KERNEL_CS # set correct cs
pushq %rax # target address in negative space
lretq
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [tip:x86/asm] x86/boot: Fix the end of the stack for idle tasks
2016-09-21 21:04 ` [PATCH v2 8/9] x86/head: fix the end of the stack for idle tasks Josh Poimboeuf
@ 2016-10-20 11:12 ` tip-bot for Josh Poimboeuf
0 siblings, 0 replies; 21+ messages in thread
From: tip-bot for Josh Poimboeuf @ 2016-10-20 11:12 UTC (permalink / raw)
To: linux-tip-commits
Cc: bp, tglx, peterz, dvlasenk, brgerst, linux-kernel, nilayvaish,
jpoimboe, hpa, torvalds, mingo, luto
Commit-ID: 22dc391865af29a1332bd1d17152f2ca7188bc4a
Gitweb: http://git.kernel.org/tip/22dc391865af29a1332bd1d17152f2ca7188bc4a
Author: Josh Poimboeuf <jpoimboe@redhat.com>
AuthorDate: Wed, 21 Sep 2016 16:04:06 -0500
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Thu, 20 Oct 2016 09:15:23 +0200
x86/boot: Fix the end of the stack for idle tasks
Thanks to all the recent x86 entry code refactoring, most tasks' kernel
stacks start at the same offset right below their saved pt_regs,
regardless of which syscall was used to enter the kernel. That creates
a nice convention which makes it straightforward to identify the end of
the stack, which can be useful for the unwinder to verify the stack is
sane.
However, the boot CPU's idle "swapper" task doesn't follow that
convention. Fix that by starting its stack at a sizeof(pt_regs) offset
from the end of the stack page.
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Nilay Vaish <nilayvaish@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/81aee3beb6ed88e44f1bea6986bb7b65c368f77a.1474480779.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
arch/x86/kernel/head_32.S | 9 ++++++++-
arch/x86/kernel/head_64.S | 15 +++++++--------
2 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 9a6f8e8..df541ac 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -63,6 +63,8 @@
#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
#endif
+#define SIZEOF_PTREGS 17*4
+
/*
* Number of possible pages in the lowmem region.
*
@@ -708,7 +710,12 @@ ENTRY(initial_page_table)
.data
.balign 4
ENTRY(initial_stack)
- .long init_thread_union+THREAD_SIZE
+ /*
+ * The SIZEOF_PTREGS gap is a convention which helps the in-kernel
+ * unwinder reliably detect the end of the stack.
+ */
+ .long init_thread_union + THREAD_SIZE - SIZEOF_PTREGS - \
+ TOP_OF_KERNEL_STACK_PADDING;
__INITRODATA
int_msg:
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index 1c5e5db..b07cd27 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -66,13 +66,8 @@ startup_64:
* tables and then reload them.
*/
- /*
- * Setup stack for verify_cpu(). "-8" because initial_stack is defined
- * this way, see below. Our best guess is a NULL ptr for stack
- * termination heuristics and we don't want to break anything which
- * might depend on it (kgdb, ...).
- */
- leaq (__end_init_task - 8)(%rip), %rsp
+ /* Set up the stack for verify_cpu(), similar to initial_stack below */
+ leaq (__end_init_task - SIZEOF_PTREGS)(%rip), %rsp
/* Sanitize CPU configuration */
call verify_cpu
@@ -329,7 +324,11 @@ ENDPROC(start_cpu0)
GLOBAL(initial_gs)
.quad INIT_PER_CPU_VAR(irq_stack_union)
GLOBAL(initial_stack)
- .quad init_thread_union+THREAD_SIZE-8
+ /*
+ * The SIZEOF_PTREGS gap is a convention which helps the in-kernel
+ * unwinder reliably detect the end of the stack.
+ */
+ .quad init_thread_union + THREAD_SIZE - SIZEOF_PTREGS
__FINITDATA
bad_address:
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [tip:x86/asm] x86/boot: Move the _stext marker to before the boot code
2016-09-21 21:04 ` [PATCH v2 9/9] x86: move _stext marker to before head code Josh Poimboeuf
@ 2016-10-20 11:12 ` tip-bot for Josh Poimboeuf
0 siblings, 0 replies; 21+ messages in thread
From: tip-bot for Josh Poimboeuf @ 2016-10-20 11:12 UTC (permalink / raw)
To: linux-tip-commits
Cc: hpa, bp, peterz, mingo, torvalds, linux-kernel, dvlasenk,
brgerst, luto, jpoimboe, nilayvaish, tglx
Commit-ID: e728f61ce05404a26447e6bbc1885ca5956d6a44
Gitweb: http://git.kernel.org/tip/e728f61ce05404a26447e6bbc1885ca5956d6a44
Author: Josh Poimboeuf <jpoimboe@redhat.com>
AuthorDate: Wed, 21 Sep 2016 16:04:07 -0500
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Thu, 20 Oct 2016 09:15:24 +0200
x86/boot: Move the _stext marker to before the boot code
When core_kernel_text() is used to determine whether an address on a
task's stack trace is a kernel text address, it incorrectly returns
false for early text addresses for the head code between the _text and
_stext markers. Among other things, this can cause the unwinder to
behave incorrectly when unwinding to x86 head code.
Head code is text code too, so mark it as such. This seems to match the
intent of other users of the _stext symbol, and it also seems consistent
with what other architectures are already doing.
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Nilay Vaish <nilayvaish@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/789cf978866420e72fa89df44aa2849426ac378d.1474480779.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
arch/x86/kernel/vmlinux.lds.S | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index dbf67f6..e79f15f 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -91,10 +91,10 @@ SECTIONS
/* Text and read-only data */
.text : AT(ADDR(.text) - LOAD_OFFSET) {
_text = .;
+ _stext = .;
/* bootstrapping code */
HEAD_TEXT
. = ALIGN(8);
- _stext = .;
TEXT_TEXT
SCHED_TEXT
CPUIDLE_TEXT
^ permalink raw reply related [flat|nested] 21+ messages in thread
end of thread, other threads:[~2016-10-20 11:13 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-21 21:03 [PATCH v2 0/9] x86/entry/head: standardize the end of the stack Josh Poimboeuf
2016-09-21 21:03 ` [PATCH v2 1/9] x86/entry/head/32: use local labels Josh Poimboeuf
2016-10-20 11:08 ` [tip:x86/asm] x86/entry/32, x86/boot/32: Use " tip-bot for Josh Poimboeuf
2016-09-21 21:04 ` [PATCH v2 2/9] x86/entry/32: rename 'error_code' to 'common_exception' Josh Poimboeuf
2016-10-20 11:08 ` [tip:x86/asm] x86/entry/32: Rename " tip-bot for Josh Poimboeuf
2016-09-21 21:04 ` [PATCH v2 3/9] x86/entry/32: fix the end of the stack for newly forked tasks Josh Poimboeuf
2016-10-20 11:09 ` [tip:x86/asm] x86/entry/32: Fix " tip-bot for Josh Poimboeuf
2016-09-21 21:04 ` [PATCH v2 4/9] x86/head/32: fix the end of the stack for idle tasks Josh Poimboeuf
2016-10-20 11:10 ` [tip:x86/asm] x86/boot/32: Fix " tip-bot for Josh Poimboeuf
2016-09-21 21:04 ` [PATCH v2 5/9] x86/smp: fix initial idle stack location on 32-bit Josh Poimboeuf
2016-10-20 11:10 ` [tip:x86/asm] x86/boot/smp/32: Fix initial idle stack location on 32-bit kernels tip-bot for Josh Poimboeuf
2016-09-21 21:04 ` [PATCH v2 6/9] x86/asm/head: use a common function for starting CPUs Josh Poimboeuf
2016-10-20 11:11 ` [tip:x86/asm] x86/boot/64: Use " tip-bot for Josh Poimboeuf
2016-09-21 21:04 ` [PATCH v2 7/9] x86/head: put real return address on idle task stack Josh Poimboeuf
2016-10-20 11:11 ` [tip:x86/asm] x86/boot/64: Put a real return address on the " tip-bot for Josh Poimboeuf
2016-09-21 21:04 ` [PATCH v2 8/9] x86/head: fix the end of the stack for idle tasks Josh Poimboeuf
2016-10-20 11:12 ` [tip:x86/asm] x86/boot: Fix " tip-bot for Josh Poimboeuf
2016-09-21 21:04 ` [PATCH v2 9/9] x86: move _stext marker to before head code Josh Poimboeuf
2016-10-20 11:12 ` [tip:x86/asm] x86/boot: Move the _stext marker to before the boot code tip-bot for Josh Poimboeuf
2016-10-18 17:17 ` [PATCH v2 0/9] x86/entry/head: standardize the end of the stack Josh Poimboeuf
2016-10-19 13:20 ` Ingo Molnar
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.