| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | 
|---|
| 2 |  | 
|---|
| 3 | #ifndef _ASM_X86_CPU_ENTRY_AREA_H | 
|---|
| 4 | #define _ASM_X86_CPU_ENTRY_AREA_H | 
|---|
| 5 |  | 
|---|
| 6 | #include <linux/percpu-defs.h> | 
|---|
| 7 | #include <asm/processor.h> | 
|---|
| 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 | 
|---|
| 81 |  | 
|---|
| 82 | /* | 
|---|
| 83 | * cpu_entry_area is a percpu region that contains things needed by the CPU | 
|---|
| 84 | * and early entry/exit code.  Real types aren't used for all fields here | 
|---|
| 85 | * to avoid circular header dependencies. | 
|---|
| 86 | * | 
|---|
| 87 | * Every field is a virtual alias of some other allocated backing store. | 
|---|
| 88 | * There is no direct allocation of a struct cpu_entry_area. | 
|---|
| 89 | */ | 
|---|
| 90 | struct cpu_entry_area { | 
|---|
| 91 | char gdt[PAGE_SIZE]; | 
|---|
| 92 |  | 
|---|
| 93 | /* | 
|---|
| 94 | * The GDT is just below entry_stack and thus serves (on x86_64) as | 
|---|
| 95 | * a read-only guard page. On 32-bit the GDT must be writeable, so | 
|---|
| 96 | * it needs an extra guard page. | 
|---|
| 97 | */ | 
|---|
| 98 | #ifdef CONFIG_X86_32 | 
|---|
| 99 | char guard_entry_stack[PAGE_SIZE]; | 
|---|
| 100 | #endif | 
|---|
| 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 | 
|---|
| 107 |  | 
|---|
| 108 | /* | 
|---|
| 109 | * On x86_64, the TSS is mapped RO.  On x86_32, it's mapped RW because | 
|---|
| 110 | * we need task switches to work, and task switches write to the TSS. | 
|---|
| 111 | */ | 
|---|
| 112 | struct tss_struct tss; | 
|---|
| 113 |  | 
|---|
| 114 | #ifdef CONFIG_X86_64 | 
|---|
| 115 | /* | 
|---|
| 116 | * Exception stacks used for IST entries with guard pages. | 
|---|
| 117 | */ | 
|---|
| 118 | struct cea_exception_stacks estacks; | 
|---|
| 119 | #endif | 
|---|
| 120 | /* | 
|---|
| 121 | * Per CPU debug store for Intel performance monitoring. Wastes a | 
|---|
| 122 | * full page at the moment. | 
|---|
| 123 | */ | 
|---|
| 124 | struct debug_store cpu_debug_store; | 
|---|
| 125 | /* | 
|---|
| 126 | * The actual PEBS/BTS buffers must be mapped to user space | 
|---|
| 127 | * Reserve enough fixmap PTEs. | 
|---|
| 128 | */ | 
|---|
| 129 | struct debug_store_buffers cpu_debug_buffers; | 
|---|
| 130 | }; | 
|---|
| 131 |  | 
|---|
| 132 | #define CPU_ENTRY_AREA_SIZE		(sizeof(struct cpu_entry_area)) | 
|---|
| 133 |  | 
|---|
| 134 | DECLARE_PER_CPU(struct cpu_entry_area *, cpu_entry_area); | 
|---|
| 135 | DECLARE_PER_CPU(struct cea_exception_stacks *, cea_exception_stacks); | 
|---|
| 136 |  | 
|---|
| 137 | extern void setup_cpu_entry_areas(void); | 
|---|
| 138 | extern void cea_set_pte(void *cea_vaddr, phys_addr_t pa, pgprot_t flags); | 
|---|
| 139 |  | 
|---|
| 140 | extern struct cpu_entry_area *get_cpu_entry_area(int cpu); | 
|---|
| 141 |  | 
|---|
| 142 | static __always_inline struct entry_stack *cpu_entry_stack(int cpu) | 
|---|
| 143 | { | 
|---|
| 144 | return &get_cpu_entry_area(cpu)->entry_stack_page.stack; | 
|---|
| 145 | } | 
|---|
| 146 |  | 
|---|
| 147 | #define __this_cpu_ist_top_va(name)					\ | 
|---|
| 148 | CEA_ESTACK_TOP(__this_cpu_read(cea_exception_stacks), name) | 
|---|
| 149 |  | 
|---|
| 150 | #define __this_cpu_ist_bottom_va(name)					\ | 
|---|
| 151 | CEA_ESTACK_BOT(__this_cpu_read(cea_exception_stacks), name) | 
|---|
| 152 |  | 
|---|
| 153 | #endif | 
|---|
| 154 |  | 
|---|