aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@kernel.org>2017-12-04 09:07:26 -0500
committerIngo Molnar <mingo@kernel.org>2017-12-17 08:27:51 -0500
commit40e7f949e0d9a33968ebde5d67f7e3a47c97742a (patch)
tree1e6b3fa11c7a8bd23a3e9d955181a8cb1c20f7dd
parent3386bc8aed825e9f1f65ce38df4b109b2019b71a (diff)
x86/entry/64: Move the IST stacks into struct cpu_entry_area
The IST stacks are needed when an IST exception occurs and are accessed before any kernel code at all runs. Move them into struct cpu_entry_area. The IST stacks are unlike the rest of cpu_entry_area: they're used even for entries from kernel mode. This means that they should be set up before we load the final IDT. Move cpu_entry_area setup to trap_init() for the boot CPU and set it up for all possible CPUs at once in native_smp_prepare_cpus(). 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.480598743@linutronix.de Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/include/asm/fixmap.h12
-rw-r--r--arch/x86/kernel/cpu/common.c74
-rw-r--r--arch/x86/kernel/traps.c3
3 files changed, 57 insertions, 32 deletions
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index 6a699474c2c7..451da7d9a502 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -63,10 +63,22 @@ struct cpu_entry_area {
63 struct tss_struct tss; 63 struct tss_struct tss;
64 64
65 char entry_trampoline[PAGE_SIZE]; 65 char entry_trampoline[PAGE_SIZE];
66
67#ifdef CONFIG_X86_64
68 /*
69 * Exception stacks used for IST entries.
70 *
71 * In the future, this should have a separate slot for each stack
72 * with guard pages between them.
73 */
74 char exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ];
75#endif
66}; 76};
67 77
68#define CPU_ENTRY_AREA_PAGES (sizeof(struct cpu_entry_area) / PAGE_SIZE) 78#define CPU_ENTRY_AREA_PAGES (sizeof(struct cpu_entry_area) / PAGE_SIZE)
69 79
80extern void setup_cpu_entry_areas(void);
81
70/* 82/*
71 * Here we define all the compile-time 'special' virtual 83 * Here we define all the compile-time 'special' virtual
72 * addresses. The point is to have a constant address at 84 * addresses. The point is to have a constant address at
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 430f950b0b7f..fb01a8e5e9b7 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -466,24 +466,36 @@ void load_percpu_segment(int cpu)
466 load_stack_canary_segment(); 466 load_stack_canary_segment();
467} 467}
468 468
469static void set_percpu_fixmap_pages(int fixmap_index, void *ptr,
470 int pages, pgprot_t prot)
471{
472 int i;
473
474 for (i = 0; i < pages; i++) {
475 __set_fixmap(fixmap_index - i,
476 per_cpu_ptr_to_phys(ptr + i * PAGE_SIZE), prot);
477 }
478}
479
480#ifdef CONFIG_X86_32 469#ifdef CONFIG_X86_32
481/* The 32-bit entry code needs to find cpu_entry_area. */ 470/* The 32-bit entry code needs to find cpu_entry_area. */
482DEFINE_PER_CPU(struct cpu_entry_area *, cpu_entry_area); 471DEFINE_PER_CPU(struct cpu_entry_area *, cpu_entry_area);
483#endif 472#endif
484 473
474#ifdef CONFIG_X86_64
475/*
476 * Special IST stacks which the CPU switches to when it calls
477 * an IST-marked descriptor entry. Up to 7 stacks (hardware
478 * limit), all of them are 4K, except the debug stack which
479 * is 8K.
480 */
481static const unsigned int exception_stack_sizes[N_EXCEPTION_STACKS] = {
482 [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STKSZ,
483 [DEBUG_STACK - 1] = DEBUG_STKSZ
484};
485
486static DEFINE_PER_CPU_PAGE_ALIGNED(char, exception_stacks
487 [(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ]);
488#endif
489
490static void __init
491set_percpu_fixmap_pages(int idx, void *ptr, int pages, pgprot_t prot)
492{
493 for ( ; pages; pages--, idx--, ptr += PAGE_SIZE)
494 __set_fixmap(idx, per_cpu_ptr_to_phys(ptr), prot);
495}
496
485/* Setup the fixmap mappings only once per-processor */ 497/* Setup the fixmap mappings only once per-processor */
486static inline void setup_cpu_entry_area(int cpu) 498static void __init setup_cpu_entry_area(int cpu)
487{ 499{
488#ifdef CONFIG_X86_64 500#ifdef CONFIG_X86_64
489 extern char _entry_trampoline[]; 501 extern char _entry_trampoline[];
@@ -532,15 +544,31 @@ static inline void setup_cpu_entry_area(int cpu)
532 PAGE_KERNEL); 544 PAGE_KERNEL);
533 545
534#ifdef CONFIG_X86_32 546#ifdef CONFIG_X86_32
535 this_cpu_write(cpu_entry_area, get_cpu_entry_area(cpu)); 547 per_cpu(cpu_entry_area, cpu) = get_cpu_entry_area(cpu);
536#endif 548#endif
537 549
538#ifdef CONFIG_X86_64 550#ifdef CONFIG_X86_64
551 BUILD_BUG_ON(sizeof(exception_stacks) % PAGE_SIZE != 0);
552 BUILD_BUG_ON(sizeof(exception_stacks) !=
553 sizeof(((struct cpu_entry_area *)0)->exception_stacks));
554 set_percpu_fixmap_pages(get_cpu_entry_area_index(cpu, exception_stacks),
555 &per_cpu(exception_stacks, cpu),
556 sizeof(exception_stacks) / PAGE_SIZE,
557 PAGE_KERNEL);
558
539 __set_fixmap(get_cpu_entry_area_index(cpu, entry_trampoline), 559 __set_fixmap(get_cpu_entry_area_index(cpu, entry_trampoline),
540 __pa_symbol(_entry_trampoline), PAGE_KERNEL_RX); 560 __pa_symbol(_entry_trampoline), PAGE_KERNEL_RX);
541#endif 561#endif
542} 562}
543 563
564void __init setup_cpu_entry_areas(void)
565{
566 unsigned int cpu;
567
568 for_each_possible_cpu(cpu)
569 setup_cpu_entry_area(cpu);
570}
571
544/* Load the original GDT from the per-cpu structure */ 572/* Load the original GDT from the per-cpu structure */
545void load_direct_gdt(int cpu) 573void load_direct_gdt(int cpu)
546{ 574{
@@ -1385,20 +1413,6 @@ DEFINE_PER_CPU(unsigned int, irq_count) __visible = -1;
1385DEFINE_PER_CPU(int, __preempt_count) = INIT_PREEMPT_COUNT; 1413DEFINE_PER_CPU(int, __preempt_count) = INIT_PREEMPT_COUNT;
1386EXPORT_PER_CPU_SYMBOL(__preempt_count); 1414EXPORT_PER_CPU_SYMBOL(__preempt_count);
1387 1415
1388/*
1389 * Special IST stacks which the CPU switches to when it calls
1390 * an IST-marked descriptor entry. Up to 7 stacks (hardware
1391 * limit), all of them are 4K, except the debug stack which
1392 * is 8K.
1393 */
1394static const unsigned int exception_stack_sizes[N_EXCEPTION_STACKS] = {
1395 [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STKSZ,
1396 [DEBUG_STACK - 1] = DEBUG_STKSZ
1397};
1398
1399static DEFINE_PER_CPU_PAGE_ALIGNED(char, exception_stacks
1400 [(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ]);
1401
1402/* May not be marked __init: used by software suspend */ 1416/* May not be marked __init: used by software suspend */
1403void syscall_init(void) 1417void syscall_init(void)
1404{ 1418{
@@ -1607,7 +1621,7 @@ void cpu_init(void)
1607 * set up and load the per-CPU TSS 1621 * set up and load the per-CPU TSS
1608 */ 1622 */
1609 if (!oist->ist[0]) { 1623 if (!oist->ist[0]) {
1610 char *estacks = per_cpu(exception_stacks, cpu); 1624 char *estacks = get_cpu_entry_area(cpu)->exception_stacks;
1611 1625
1612 for (v = 0; v < N_EXCEPTION_STACKS; v++) { 1626 for (v = 0; v < N_EXCEPTION_STACKS; v++) {
1613 estacks += exception_stack_sizes[v]; 1627 estacks += exception_stack_sizes[v];
@@ -1633,8 +1647,6 @@ void cpu_init(void)
1633 initialize_tlbstate_and_flush(); 1647 initialize_tlbstate_and_flush();
1634 enter_lazy_tlb(&init_mm, me); 1648 enter_lazy_tlb(&init_mm, me);
1635 1649
1636 setup_cpu_entry_area(cpu);
1637
1638 /* 1650 /*
1639 * Initialize the TSS. sp0 points to the entry trampoline stack 1651 * Initialize the TSS. sp0 points to the entry trampoline stack
1640 * regardless of what task is running. 1652 * regardless of what task is running.
@@ -1694,8 +1706,6 @@ void cpu_init(void)
1694 initialize_tlbstate_and_flush(); 1706 initialize_tlbstate_and_flush();
1695 enter_lazy_tlb(&init_mm, curr); 1707 enter_lazy_tlb(&init_mm, curr);
1696 1708
1697 setup_cpu_entry_area(cpu);
1698
1699 /* 1709 /*
1700 * Initialize the TSS. Don't bother initializing sp0, as the initial 1710 * Initialize the TSS. Don't bother initializing sp0, as the initial
1701 * task never enters user mode. 1711 * task never enters user mode.
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index ee9ca0ad4388..3e29aad5c7cc 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -947,6 +947,9 @@ dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
947 947
948void __init trap_init(void) 948void __init trap_init(void)
949{ 949{
950 /* Init cpu_entry_area before IST entries are set up */
951 setup_cpu_entry_areas();
952
950 idt_setup_traps(); 953 idt_setup_traps();
951 954
952 /* 955 /*