.. | .. |
---|
1 | | -// SPDX-License-Identifier: GPL-2.0 |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0 */ |
---|
2 | 2 | |
---|
3 | 3 | #ifndef _ASM_X86_CPU_ENTRY_AREA_H |
---|
4 | 4 | #define _ASM_X86_CPU_ENTRY_AREA_H |
---|
.. | .. |
---|
6 | 6 | #include <linux/percpu-defs.h> |
---|
7 | 7 | #include <asm/processor.h> |
---|
8 | 8 | #include <asm/intel_ds.h> |
---|
| 9 | +#include <asm/pgtable_areas.h> |
---|
| 10 | + |
---|
| 11 | +#ifdef CONFIG_X86_64 |
---|
| 12 | + |
---|
| 13 | +#ifdef CONFIG_AMD_MEM_ENCRYPT |
---|
| 14 | +#define VC_EXCEPTION_STKSZ EXCEPTION_STKSZ |
---|
| 15 | +#else |
---|
| 16 | +#define VC_EXCEPTION_STKSZ 0 |
---|
| 17 | +#endif |
---|
| 18 | + |
---|
| 19 | +/* Macro to enforce the same ordering and stack sizes */ |
---|
| 20 | +#define ESTACKS_MEMBERS(guardsize, optional_stack_size) \ |
---|
| 21 | + char DF_stack_guard[guardsize]; \ |
---|
| 22 | + char DF_stack[EXCEPTION_STKSZ]; \ |
---|
| 23 | + char NMI_stack_guard[guardsize]; \ |
---|
| 24 | + char NMI_stack[EXCEPTION_STKSZ]; \ |
---|
| 25 | + char DB_stack_guard[guardsize]; \ |
---|
| 26 | + char DB_stack[EXCEPTION_STKSZ]; \ |
---|
| 27 | + char MCE_stack_guard[guardsize]; \ |
---|
| 28 | + char MCE_stack[EXCEPTION_STKSZ]; \ |
---|
| 29 | + char VC_stack_guard[guardsize]; \ |
---|
| 30 | + char VC_stack[optional_stack_size]; \ |
---|
| 31 | + char VC2_stack_guard[guardsize]; \ |
---|
| 32 | + char VC2_stack[optional_stack_size]; \ |
---|
| 33 | + char IST_top_guard[guardsize]; \ |
---|
| 34 | + |
---|
| 35 | +/* The exception stacks' physical storage. No guard pages required */ |
---|
| 36 | +struct exception_stacks { |
---|
| 37 | + ESTACKS_MEMBERS(0, VC_EXCEPTION_STKSZ) |
---|
| 38 | +}; |
---|
| 39 | + |
---|
| 40 | +/* The effective cpu entry area mapping with guard pages. */ |
---|
| 41 | +struct cea_exception_stacks { |
---|
| 42 | + ESTACKS_MEMBERS(PAGE_SIZE, EXCEPTION_STKSZ) |
---|
| 43 | +}; |
---|
| 44 | + |
---|
| 45 | +/* |
---|
| 46 | + * The exception stack ordering in [cea_]exception_stacks |
---|
| 47 | + */ |
---|
| 48 | +enum exception_stack_ordering { |
---|
| 49 | + ESTACK_DF, |
---|
| 50 | + ESTACK_NMI, |
---|
| 51 | + ESTACK_DB, |
---|
| 52 | + ESTACK_MCE, |
---|
| 53 | + ESTACK_VC, |
---|
| 54 | + ESTACK_VC2, |
---|
| 55 | + N_EXCEPTION_STACKS |
---|
| 56 | +}; |
---|
| 57 | + |
---|
| 58 | +#define CEA_ESTACK_SIZE(st) \ |
---|
| 59 | + sizeof(((struct cea_exception_stacks *)0)->st## _stack) |
---|
| 60 | + |
---|
| 61 | +#define CEA_ESTACK_BOT(ceastp, st) \ |
---|
| 62 | + ((unsigned long)&(ceastp)->st## _stack) |
---|
| 63 | + |
---|
| 64 | +#define CEA_ESTACK_TOP(ceastp, st) \ |
---|
| 65 | + (CEA_ESTACK_BOT(ceastp, st) + CEA_ESTACK_SIZE(st)) |
---|
| 66 | + |
---|
| 67 | +#define CEA_ESTACK_OFFS(st) \ |
---|
| 68 | + offsetof(struct cea_exception_stacks, st## _stack) |
---|
| 69 | + |
---|
| 70 | +#define CEA_ESTACK_PAGES \ |
---|
| 71 | + (sizeof(struct cea_exception_stacks) / PAGE_SIZE) |
---|
| 72 | + |
---|
| 73 | +#endif |
---|
| 74 | + |
---|
| 75 | +#ifdef CONFIG_X86_32 |
---|
| 76 | +struct doublefault_stack { |
---|
| 77 | + unsigned long stack[(PAGE_SIZE - sizeof(struct x86_hw_tss)) / sizeof(unsigned long)]; |
---|
| 78 | + struct x86_hw_tss tss; |
---|
| 79 | +} __aligned(PAGE_SIZE); |
---|
| 80 | +#endif |
---|
9 | 81 | |
---|
10 | 82 | /* |
---|
11 | 83 | * cpu_entry_area is a percpu region that contains things needed by the CPU |
---|
.. | .. |
---|
20 | 92 | |
---|
21 | 93 | /* |
---|
22 | 94 | * The GDT is just below entry_stack and thus serves (on x86_64) as |
---|
23 | | - * a a read-only guard page. |
---|
| 95 | + * a read-only guard page. On 32-bit the GDT must be writeable, so |
---|
| 96 | + * it needs an extra guard page. |
---|
24 | 97 | */ |
---|
| 98 | +#ifdef CONFIG_X86_32 |
---|
| 99 | + char guard_entry_stack[PAGE_SIZE]; |
---|
| 100 | +#endif |
---|
25 | 101 | struct entry_stack_page entry_stack_page; |
---|
| 102 | + |
---|
| 103 | +#ifdef CONFIG_X86_32 |
---|
| 104 | + char guard_doublefault_stack[PAGE_SIZE]; |
---|
| 105 | + struct doublefault_stack doublefault_stack; |
---|
| 106 | +#endif |
---|
26 | 107 | |
---|
27 | 108 | /* |
---|
28 | 109 | * On x86_64, the TSS is mapped RO. On x86_32, it's mapped RW because |
---|
.. | .. |
---|
30 | 111 | */ |
---|
31 | 112 | struct tss_struct tss; |
---|
32 | 113 | |
---|
33 | | - char entry_trampoline[PAGE_SIZE]; |
---|
34 | | - |
---|
35 | 114 | #ifdef CONFIG_X86_64 |
---|
36 | 115 | /* |
---|
37 | | - * Exception stacks used for IST entries. |
---|
38 | | - * |
---|
39 | | - * In the future, this should have a separate slot for each stack |
---|
40 | | - * with guard pages between them. |
---|
| 116 | + * Exception stacks used for IST entries with guard pages. |
---|
41 | 117 | */ |
---|
42 | | - char exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ]; |
---|
| 118 | + struct cea_exception_stacks estacks; |
---|
43 | 119 | #endif |
---|
44 | | -#ifdef CONFIG_CPU_SUP_INTEL |
---|
45 | 120 | /* |
---|
46 | 121 | * Per CPU debug store for Intel performance monitoring. Wastes a |
---|
47 | 122 | * full page at the moment. |
---|
.. | .. |
---|
52 | 127 | * Reserve enough fixmap PTEs. |
---|
53 | 128 | */ |
---|
54 | 129 | struct debug_store_buffers cpu_debug_buffers; |
---|
55 | | -#endif |
---|
56 | 130 | }; |
---|
57 | 131 | |
---|
58 | | -#define CPU_ENTRY_AREA_SIZE (sizeof(struct cpu_entry_area)) |
---|
59 | | -#define CPU_ENTRY_AREA_TOT_SIZE (CPU_ENTRY_AREA_SIZE * NR_CPUS) |
---|
| 132 | +#define CPU_ENTRY_AREA_SIZE (sizeof(struct cpu_entry_area)) |
---|
| 133 | +#define CPU_ENTRY_AREA_ARRAY_SIZE (CPU_ENTRY_AREA_SIZE * NR_CPUS) |
---|
| 134 | + |
---|
| 135 | +/* Total size includes the readonly IDT mapping page as well: */ |
---|
| 136 | +#define CPU_ENTRY_AREA_TOTAL_SIZE (CPU_ENTRY_AREA_ARRAY_SIZE + PAGE_SIZE) |
---|
60 | 137 | |
---|
61 | 138 | DECLARE_PER_CPU(struct cpu_entry_area *, cpu_entry_area); |
---|
| 139 | +DECLARE_PER_CPU(struct cea_exception_stacks *, cea_exception_stacks); |
---|
62 | 140 | |
---|
63 | 141 | extern void setup_cpu_entry_areas(void); |
---|
64 | 142 | extern void cea_set_pte(void *cea_vaddr, phys_addr_t pa, pgprot_t flags); |
---|
65 | | - |
---|
66 | | -#define CPU_ENTRY_AREA_RO_IDT CPU_ENTRY_AREA_BASE |
---|
67 | | -#define CPU_ENTRY_AREA_PER_CPU (CPU_ENTRY_AREA_RO_IDT + PAGE_SIZE) |
---|
68 | | - |
---|
69 | | -#define CPU_ENTRY_AREA_RO_IDT_VADDR ((void *)CPU_ENTRY_AREA_RO_IDT) |
---|
70 | | - |
---|
71 | | -#define CPU_ENTRY_AREA_MAP_SIZE \ |
---|
72 | | - (CPU_ENTRY_AREA_PER_CPU + CPU_ENTRY_AREA_TOT_SIZE - CPU_ENTRY_AREA_BASE) |
---|
73 | 143 | |
---|
74 | 144 | extern struct cpu_entry_area *get_cpu_entry_area(int cpu); |
---|
75 | 145 | |
---|
.. | .. |
---|
78 | 148 | return &get_cpu_entry_area(cpu)->entry_stack_page.stack; |
---|
79 | 149 | } |
---|
80 | 150 | |
---|
| 151 | +#define __this_cpu_ist_top_va(name) \ |
---|
| 152 | + CEA_ESTACK_TOP(__this_cpu_read(cea_exception_stacks), name) |
---|
| 153 | + |
---|
| 154 | +#define __this_cpu_ist_bottom_va(name) \ |
---|
| 155 | + CEA_ESTACK_BOT(__this_cpu_read(cea_exception_stacks), name) |
---|
| 156 | + |
---|
81 | 157 | #endif |
---|