Skip to content

Commit 9aaefe7

Browse files
amlutoIngo Molnar
authored andcommitted
x86/entry/64: Separate cpu_current_top_of_stack from TSS.sp0
On 64-bit kernels, we used to assume that TSS.sp0 was the current top of stack. With the addition of an entry trampoline, this will no longer be the case. Store the current top of stack in TSS.sp1, which is otherwise unused but shares the same cacheline. Signed-off-by: Andy Lutomirski <luto@kernel.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Borislav Petkov <bp@suse.de> Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Borislav Petkov <bpetkov@suse.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: David Laight <David.Laight@aculab.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: Eduardo Valentin <eduval@amazon.com> Cc: Greg KH <gregkh@linuxfoundation.org> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Juergen Gross <jgross@suse.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Rik van Riel <riel@redhat.com> Cc: Will Deacon <will.deacon@arm.com> Cc: aliguori@amazon.com Cc: daniel.gruss@iaik.tugraz.at Cc: hughd@google.com Cc: keescook@google.com Link: https://lkml.kernel.org/r/20171204150606.050864668@linutronix.de Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent 72f5e08 commit 9aaefe7

File tree

5 files changed

+26
-6
lines changed

5 files changed

+26
-6
lines changed

arch/x86/include/asm/processor.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,13 @@ struct x86_hw_tss {
309309
struct x86_hw_tss {
310310
u32 reserved1;
311311
u64 sp0;
312+
313+
/*
314+
* We store cpu_current_top_of_stack in sp1 so it's always accessible.
315+
* Linux does not use ring 1, so sp1 is not otherwise needed.
316+
*/
312317
u64 sp1;
318+
313319
u64 sp2;
314320
u64 reserved2;
315321
u64 ist[7];
@@ -368,6 +374,8 @@ DECLARE_PER_CPU_PAGE_ALIGNED(struct tss_struct, cpu_tss);
368374

369375
#ifdef CONFIG_X86_32
370376
DECLARE_PER_CPU(unsigned long, cpu_current_top_of_stack);
377+
#else
378+
#define cpu_current_top_of_stack cpu_tss.x86_tss.sp1
371379
#endif
372380

373381
/*
@@ -539,12 +547,12 @@ static inline void native_swapgs(void)
539547

540548
static inline unsigned long current_top_of_stack(void)
541549
{
542-
#ifdef CONFIG_X86_64
543-
return this_cpu_read_stable(cpu_tss.x86_tss.sp0);
544-
#else
545-
/* sp0 on x86_32 is special in and around vm86 mode. */
550+
/*
551+
* We can't read directly from tss.sp0: sp0 on x86_32 is special in
552+
* and around vm86 mode and sp0 on x86_64 is special because of the
553+
* entry trampoline.
554+
*/
546555
return this_cpu_read_stable(cpu_current_top_of_stack);
547-
#endif
548556
}
549557

550558
static inline bool on_thread_stack(void)

arch/x86/include/asm/thread_info.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ static inline int arch_within_stack_frames(const void * const stack,
207207
#else /* !__ASSEMBLY__ */
208208

209209
#ifdef CONFIG_X86_64
210-
# define cpu_current_top_of_stack (cpu_tss + TSS_sp0)
210+
# define cpu_current_top_of_stack (cpu_tss + TSS_sp1)
211211
#endif
212212

213213
#endif

arch/x86/kernel/asm-offsets_64.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ int main(void)
6666

6767
OFFSET(TSS_ist, tss_struct, x86_tss.ist);
6868
OFFSET(TSS_sp0, tss_struct, x86_tss.sp0);
69+
OFFSET(TSS_sp1, tss_struct, x86_tss.sp1);
6970
BLANK();
7071

7172
#ifdef CONFIG_CC_STACKPROTECTOR

arch/x86/kernel/process.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@ __visible DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, cpu_tss) = {
5656
* Poison it.
5757
*/
5858
.sp0 = (1UL << (BITS_PER_LONG-1)) + 1,
59+
60+
#ifdef CONFIG_X86_64
61+
/*
62+
* .sp1 is cpu_current_top_of_stack. The init task never
63+
* runs user code, but cpu_current_top_of_stack should still
64+
* be well defined before the first context switch.
65+
*/
66+
.sp1 = TOP_OF_INIT_STACK,
67+
#endif
68+
5969
#ifdef CONFIG_X86_32
6070
.ss0 = __KERNEL_DS,
6171
.ss1 = __KERNEL_CS,

arch/x86/kernel/process_64.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
461461
* Switch the PDA and FPU contexts.
462462
*/
463463
this_cpu_write(current_task, next_p);
464+
this_cpu_write(cpu_current_top_of_stack, task_top_of_stack(next_p));
464465

465466
/* Reload sp0. */
466467
update_sp0(next_p);

0 commit comments

Comments
 (0)