1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #ifndef _ASM_X86_KEXEC_H |
3 | #define _ASM_X86_KEXEC_H |
4 | |
5 | #ifdef CONFIG_X86_32 |
6 | # define PA_CONTROL_PAGE 0 |
7 | # define VA_CONTROL_PAGE 1 |
8 | # define PA_PGD 2 |
9 | # define PA_SWAP_PAGE 3 |
10 | # define PAGES_NR 4 |
11 | #else |
12 | # define PA_CONTROL_PAGE 0 |
13 | # define VA_CONTROL_PAGE 1 |
14 | # define PA_TABLE_PAGE 2 |
15 | # define PA_SWAP_PAGE 3 |
16 | # define PAGES_NR 4 |
17 | #endif |
18 | |
19 | # define KEXEC_CONTROL_CODE_MAX_SIZE 2048 |
20 | |
21 | #ifndef __ASSEMBLY__ |
22 | |
23 | #include <linux/string.h> |
24 | #include <linux/kernel.h> |
25 | |
26 | #include <asm/page.h> |
27 | #include <asm/ptrace.h> |
28 | #include <asm/bootparam.h> |
29 | |
30 | struct kimage; |
31 | |
32 | /* |
33 | * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return. |
34 | * I.e. Maximum page that is mapped directly into kernel memory, |
35 | * and kmap is not required. |
36 | * |
37 | * So far x86_64 is limited to 40 physical address bits. |
38 | */ |
39 | #ifdef CONFIG_X86_32 |
40 | /* Maximum physical address we can use pages from */ |
41 | # define KEXEC_SOURCE_MEMORY_LIMIT (-1UL) |
42 | /* Maximum address we can reach in physical address mode */ |
43 | # define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL) |
44 | /* Maximum address we can use for the control code buffer */ |
45 | # define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE |
46 | |
47 | # define KEXEC_CONTROL_PAGE_SIZE 4096 |
48 | |
49 | /* The native architecture */ |
50 | # define KEXEC_ARCH KEXEC_ARCH_386 |
51 | |
52 | /* We can also handle crash dumps from 64 bit kernel. */ |
53 | # define vmcore_elf_check_arch_cross(x) ((x)->e_machine == EM_X86_64) |
54 | #else |
55 | /* Maximum physical address we can use pages from */ |
56 | # define KEXEC_SOURCE_MEMORY_LIMIT (MAXMEM-1) |
57 | /* Maximum address we can reach in physical address mode */ |
58 | # define KEXEC_DESTINATION_MEMORY_LIMIT (MAXMEM-1) |
59 | /* Maximum address we can use for the control pages */ |
60 | # define KEXEC_CONTROL_MEMORY_LIMIT (MAXMEM-1) |
61 | |
62 | /* Allocate one page for the pdp and the second for the code */ |
63 | # define KEXEC_CONTROL_PAGE_SIZE (4096UL + 4096UL) |
64 | |
65 | /* The native architecture */ |
66 | # define KEXEC_ARCH KEXEC_ARCH_X86_64 |
67 | #endif |
68 | |
69 | /* |
70 | * This function is responsible for capturing register states if coming |
71 | * via panic otherwise just fix up the ss and sp if coming via kernel |
72 | * mode exception. |
73 | */ |
74 | static inline void crash_setup_regs(struct pt_regs *newregs, |
75 | struct pt_regs *oldregs) |
76 | { |
77 | if (oldregs) { |
78 | memcpy(newregs, oldregs, sizeof(*newregs)); |
79 | } else { |
80 | #ifdef CONFIG_X86_32 |
81 | asm volatile("movl %%ebx,%0" : "=m" (newregs->bx)); |
82 | asm volatile("movl %%ecx,%0" : "=m" (newregs->cx)); |
83 | asm volatile("movl %%edx,%0" : "=m" (newregs->dx)); |
84 | asm volatile("movl %%esi,%0" : "=m" (newregs->si)); |
85 | asm volatile("movl %%edi,%0" : "=m" (newregs->di)); |
86 | asm volatile("movl %%ebp,%0" : "=m" (newregs->bp)); |
87 | asm volatile("movl %%eax,%0" : "=m" (newregs->ax)); |
88 | asm volatile("movl %%esp,%0" : "=m" (newregs->sp)); |
89 | asm volatile("movl %%ss, %%eax;" :"=a" (newregs->ss)); |
90 | asm volatile("movl %%cs, %%eax;" :"=a" (newregs->cs)); |
91 | asm volatile("movl %%ds, %%eax;" :"=a" (newregs->ds)); |
92 | asm volatile("movl %%es, %%eax;" :"=a" (newregs->es)); |
93 | asm volatile("pushfl; popl %0" :"=m" (newregs->flags)); |
94 | #else |
95 | asm volatile("movq %%rbx,%0" : "=m" (newregs->bx)); |
96 | asm volatile("movq %%rcx,%0" : "=m" (newregs->cx)); |
97 | asm volatile("movq %%rdx,%0" : "=m" (newregs->dx)); |
98 | asm volatile("movq %%rsi,%0" : "=m" (newregs->si)); |
99 | asm volatile("movq %%rdi,%0" : "=m" (newregs->di)); |
100 | asm volatile("movq %%rbp,%0" : "=m" (newregs->bp)); |
101 | asm volatile("movq %%rax,%0" : "=m" (newregs->ax)); |
102 | asm volatile("movq %%rsp,%0" : "=m" (newregs->sp)); |
103 | asm volatile("movq %%r8,%0" : "=m" (newregs->r8)); |
104 | asm volatile("movq %%r9,%0" : "=m" (newregs->r9)); |
105 | asm volatile("movq %%r10,%0" : "=m" (newregs->r10)); |
106 | asm volatile("movq %%r11,%0" : "=m" (newregs->r11)); |
107 | asm volatile("movq %%r12,%0" : "=m" (newregs->r12)); |
108 | asm volatile("movq %%r13,%0" : "=m" (newregs->r13)); |
109 | asm volatile("movq %%r14,%0" : "=m" (newregs->r14)); |
110 | asm volatile("movq %%r15,%0" : "=m" (newregs->r15)); |
111 | asm volatile("movl %%ss, %%eax;" :"=a" (newregs->ss)); |
112 | asm volatile("movl %%cs, %%eax;" :"=a" (newregs->cs)); |
113 | asm volatile("pushfq; popq %0" :"=m" (newregs->flags)); |
114 | #endif |
115 | newregs->ip = _THIS_IP_; |
116 | } |
117 | } |
118 | |
119 | #ifdef CONFIG_X86_32 |
120 | asmlinkage unsigned long |
121 | relocate_kernel(unsigned long indirection_page, |
122 | unsigned long control_page, |
123 | unsigned long start_address, |
124 | unsigned int has_pae, |
125 | unsigned int preserve_context); |
126 | #else |
127 | unsigned long |
128 | relocate_kernel(unsigned long indirection_page, |
129 | unsigned long page_list, |
130 | unsigned long start_address, |
131 | unsigned int preserve_context, |
132 | unsigned int host_mem_enc_active); |
133 | #endif |
134 | |
135 | #define ARCH_HAS_KIMAGE_ARCH |
136 | |
137 | #ifdef CONFIG_X86_32 |
138 | struct kimage_arch { |
139 | pgd_t *pgd; |
140 | #ifdef CONFIG_X86_PAE |
141 | pmd_t *pmd0; |
142 | pmd_t *pmd1; |
143 | #endif |
144 | pte_t *pte0; |
145 | pte_t *pte1; |
146 | }; |
147 | #else |
148 | struct kimage_arch { |
149 | p4d_t *p4d; |
150 | pud_t *pud; |
151 | pmd_t *pmd; |
152 | pte_t *pte; |
153 | }; |
154 | #endif /* CONFIG_X86_32 */ |
155 | |
156 | #ifdef CONFIG_X86_64 |
157 | /* |
158 | * Number of elements and order of elements in this structure should match |
159 | * with the ones in arch/x86/purgatory/entry64.S. If you make a change here |
160 | * make an appropriate change in purgatory too. |
161 | */ |
162 | struct kexec_entry64_regs { |
163 | uint64_t rax; |
164 | uint64_t rcx; |
165 | uint64_t rdx; |
166 | uint64_t rbx; |
167 | uint64_t rsp; |
168 | uint64_t rbp; |
169 | uint64_t rsi; |
170 | uint64_t rdi; |
171 | uint64_t r8; |
172 | uint64_t r9; |
173 | uint64_t r10; |
174 | uint64_t r11; |
175 | uint64_t r12; |
176 | uint64_t r13; |
177 | uint64_t r14; |
178 | uint64_t r15; |
179 | uint64_t rip; |
180 | }; |
181 | |
182 | extern int arch_kexec_post_alloc_pages(void *vaddr, unsigned int pages, |
183 | gfp_t gfp); |
184 | #define arch_kexec_post_alloc_pages arch_kexec_post_alloc_pages |
185 | |
186 | extern void arch_kexec_pre_free_pages(void *vaddr, unsigned int pages); |
187 | #define arch_kexec_pre_free_pages arch_kexec_pre_free_pages |
188 | |
189 | void arch_kexec_protect_crashkres(void); |
190 | #define arch_kexec_protect_crashkres arch_kexec_protect_crashkres |
191 | |
192 | void arch_kexec_unprotect_crashkres(void); |
193 | #define arch_kexec_unprotect_crashkres arch_kexec_unprotect_crashkres |
194 | |
195 | #ifdef CONFIG_KEXEC_FILE |
196 | struct purgatory_info; |
197 | int arch_kexec_apply_relocations_add(struct purgatory_info *pi, |
198 | Elf_Shdr *section, |
199 | const Elf_Shdr *relsec, |
200 | const Elf_Shdr *symtab); |
201 | #define arch_kexec_apply_relocations_add arch_kexec_apply_relocations_add |
202 | |
203 | int arch_kimage_file_post_load_cleanup(struct kimage *image); |
204 | #define arch_kimage_file_post_load_cleanup arch_kimage_file_post_load_cleanup |
205 | #endif |
206 | #endif |
207 | |
208 | extern void kdump_nmi_shootdown_cpus(void); |
209 | |
210 | #ifdef CONFIG_CRASH_HOTPLUG |
211 | void arch_crash_handle_hotplug_event(struct kimage *image); |
212 | #define arch_crash_handle_hotplug_event arch_crash_handle_hotplug_event |
213 | |
214 | #ifdef CONFIG_HOTPLUG_CPU |
215 | int arch_crash_hotplug_cpu_support(void); |
216 | #define crash_hotplug_cpu_support arch_crash_hotplug_cpu_support |
217 | #endif |
218 | |
219 | #ifdef CONFIG_MEMORY_HOTPLUG |
220 | int arch_crash_hotplug_memory_support(void); |
221 | #define crash_hotplug_memory_support arch_crash_hotplug_memory_support |
222 | #endif |
223 | |
224 | unsigned int arch_crash_get_elfcorehdr_size(void); |
225 | #define crash_get_elfcorehdr_size arch_crash_get_elfcorehdr_size |
226 | #endif |
227 | |
228 | #endif /* __ASSEMBLY__ */ |
229 | |
230 | #endif /* _ASM_X86_KEXEC_H */ |
231 | |