1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * relocate_kernel.S - put the kernel image in place to boot 4 * Copyright (C) 2002-2005 Eric Biederman <ebiederm@xmission.com> 5 */ 6 7#include <linux/linkage.h> 8#include <asm/page_types.h> 9#include <asm/kexec.h> 10#include <asm/processor-flags.h> 11#include <asm/pgtable_types.h> 12#include <asm/nospec-branch.h> 13#include <asm/unwind_hints.h> 14#include <asm/asm-offsets.h> 15 16/* 17 * Must be relocatable PIC code callable as a C function, in particular 18 * there must be a plain RET and not jump to return thunk. 19 */ 20 21#define PTR(x) (x << 3) 22#define PAGE_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) 23 24/* 25 * control_page + KEXEC_CONTROL_CODE_MAX_SIZE 26 * ~ control_page + PAGE_SIZE are used as data storage and stack for 27 * jumping back 28 */ 29#define DATA(offset) (KEXEC_CONTROL_CODE_MAX_SIZE+(offset)) 30 31/* Minimal CPU state */ 32#define RSP DATA(0x0) 33#define CR0 DATA(0x8) 34#define CR3 DATA(0x10) 35#define CR4 DATA(0x18) 36 37/* other data */ 38#define CP_PA_TABLE_PAGE DATA(0x20) 39#define CP_PA_SWAP_PAGE DATA(0x28) 40#define CP_PA_BACKUP_PAGES_MAP DATA(0x30) 41 42 .text 43 .align PAGE_SIZE 44 .code64 45SYM_CODE_START_NOALIGN(relocate_range) 46SYM_CODE_START_NOALIGN(relocate_kernel) 47 UNWIND_HINT_END_OF_STACK 48 ANNOTATE_NOENDBR 49 /* 50 * %rdi indirection_page 51 * %rsi page_list 52 * %rdx start address 53 * %rcx preserve_context 54 * %r8 host_mem_enc_active 55 */ 56 57 /* Save the CPU context, used for jumping back */ 58 pushq %rbx 59 pushq %rbp 60 pushq %r12 61 pushq %r13 62 pushq %r14 63 pushq %r15 64 pushf 65 66 movq PTR(VA_CONTROL_PAGE)(%rsi), %r11 67 movq %rsp, RSP(%r11) 68 movq %cr0, %rax 69 movq %rax, CR0(%r11) 70 movq %cr3, %rax 71 movq %rax, CR3(%r11) 72 movq %cr4, %rax 73 movq %rax, CR4(%r11) 74 75 /* Save CR4. Required to enable the right paging mode later. */ 76 movq %rax, %r13 77 78 /* zero out flags, and disable interrupts */ 79 pushq $0 80 popfq 81 82 /* Save SME active flag */ 83 movq %r8, %r12 84 85 /* 86 * get physical address of control page now 87 * this is impossible after page table switch 88 */ 89 movq PTR(PA_CONTROL_PAGE)(%rsi), %r8 90 91 /* get physical address of page table now too */ 92 movq PTR(PA_TABLE_PAGE)(%rsi), %r9 93 94 /* get physical address of swap page now */ 95 movq PTR(PA_SWAP_PAGE)(%rsi), %r10 96 97 /* save some information for jumping back */ 98 movq %r9, CP_PA_TABLE_PAGE(%r11) 99 movq %r10, CP_PA_SWAP_PAGE(%r11) 100 movq %rdi, CP_PA_BACKUP_PAGES_MAP(%r11) 101 102 /* Switch to the identity mapped page tables */ 103 movq %r9, %cr3 104 105 /* setup a new stack at the end of the physical control page */ 106 lea PAGE_SIZE(%r8), %rsp 107 108 /* jump to identity mapped page */ 109 addq $(identity_mapped - relocate_kernel), %r8 110 pushq %r8 111 ANNOTATE_UNRET_SAFE 112 ret 113 int3 114SYM_CODE_END(relocate_kernel) 115 116SYM_CODE_START_LOCAL_NOALIGN(identity_mapped) 117 UNWIND_HINT_END_OF_STACK 118 /* set return address to 0 if not preserving context */ 119 pushq $0 120 /* store the start address on the stack */ 121 pushq %rdx 122 123 /* 124 * Clear X86_CR4_CET (if it was set) such that we can clear CR0_WP 125 * below. 126 */ 127 movq %cr4, %rax 128 andq $~(X86_CR4_CET), %rax 129 movq %rax, %cr4 130 131 /* 132 * Set cr0 to a known state: 133 * - Paging enabled 134 * - Alignment check disabled 135 * - Write protect disabled 136 * - No task switch 137 * - Don't do FP software emulation. 138 * - Protected mode enabled 139 */ 140 movq %cr0, %rax 141 andq $~(X86_CR0_AM | X86_CR0_WP | X86_CR0_TS | X86_CR0_EM), %rax 142 orl $(X86_CR0_PG | X86_CR0_PE), %eax 143 movq %rax, %cr0 144 145 /* 146 * Set cr4 to a known state: 147 * - physical address extension enabled 148 * - 5-level paging, if it was enabled before 149 */ 150 movl $X86_CR4_PAE, %eax 151 testq $X86_CR4_LA57, %r13 152 jz 1f 153 orl $X86_CR4_LA57, %eax 1541: 155 movq %rax, %cr4 156 157 jmp 1f 1581: 159 160 /* Flush the TLB (needed?) */ 161 movq %r9, %cr3 162 163 /* 164 * If SME is active, there could be old encrypted cache line 165 * entries that will conflict with the now unencrypted memory 166 * used by kexec. Flush the caches before copying the kernel. 167 */ 168 testq %r12, %r12 169 jz 1f 170 wbinvd 1711: 172 173 movq %rcx, %r11 174 call swap_pages 175 176 /* 177 * To be certain of avoiding problems with self-modifying code 178 * I need to execute a serializing instruction here. 179 * So I flush the TLB by reloading %cr3 here, it's handy, 180 * and not processor dependent. 181 */ 182 movq %cr3, %rax 183 movq %rax, %cr3 184 185 /* 186 * set all of the registers to known values 187 * leave %rsp alone 188 */ 189 190 testq %r11, %r11 191 jnz 1f 192 xorl %eax, %eax 193 xorl %ebx, %ebx 194 xorl %ecx, %ecx 195 xorl %edx, %edx 196 xorl %esi, %esi 197 xorl %edi, %edi 198 xorl %ebp, %ebp 199 xorl %r8d, %r8d 200 xorl %r9d, %r9d 201 xorl %r10d, %r10d 202 xorl %r11d, %r11d 203 xorl %r12d, %r12d 204 xorl %r13d, %r13d 205 xorl %r14d, %r14d 206 xorl %r15d, %r15d 207 208 ANNOTATE_UNRET_SAFE 209 ret 210 int3 211 2121: 213 popq %rdx 214 leaq PAGE_SIZE(%r10), %rsp 215 ANNOTATE_RETPOLINE_SAFE 216 call *%rdx 217 218 /* get the re-entry point of the peer system */ 219 movq 0(%rsp), %rbp 220 leaq relocate_kernel(%rip), %r8 221 movq CP_PA_SWAP_PAGE(%r8), %r10 222 movq CP_PA_BACKUP_PAGES_MAP(%r8), %rdi 223 movq CP_PA_TABLE_PAGE(%r8), %rax 224 movq %rax, %cr3 225 lea PAGE_SIZE(%r8), %rsp 226 call swap_pages 227 movq $virtual_mapped, %rax 228 pushq %rax 229 ANNOTATE_UNRET_SAFE 230 ret 231 int3 232SYM_CODE_END(identity_mapped) 233 234SYM_CODE_START_LOCAL_NOALIGN(virtual_mapped) 235 UNWIND_HINT_END_OF_STACK 236 ANNOTATE_NOENDBR // RET target, above 237 movq RSP(%r8), %rsp 238 movq CR4(%r8), %rax 239 movq %rax, %cr4 240 movq CR3(%r8), %rax 241 movq CR0(%r8), %r8 242 movq %rax, %cr3 243 movq %r8, %cr0 244 245#ifdef CONFIG_KEXEC_JUMP 246 /* Saved in save_processor_state. */ 247 movq $saved_context, %rax 248 lgdt saved_context_gdt_desc(%rax) 249#endif 250 251 movq %rbp, %rax 252 253 popf 254 popq %r15 255 popq %r14 256 popq %r13 257 popq %r12 258 popq %rbp 259 popq %rbx 260 ANNOTATE_UNRET_SAFE 261 ret 262 int3 263SYM_CODE_END(virtual_mapped) 264 265 /* Do the copies */ 266SYM_CODE_START_LOCAL_NOALIGN(swap_pages) 267 UNWIND_HINT_END_OF_STACK 268 movq %rdi, %rcx /* Put the page_list in %rcx */ 269 xorl %edi, %edi 270 xorl %esi, %esi 271 jmp 1f 272 2730: /* top, read another word for the indirection page */ 274 275 movq (%rbx), %rcx 276 addq $8, %rbx 2771: 278 testb $0x1, %cl /* is it a destination page? */ 279 jz 2f 280 movq %rcx, %rdi 281 andq $0xfffffffffffff000, %rdi 282 jmp 0b 2832: 284 testb $0x2, %cl /* is it an indirection page? */ 285 jz 2f 286 movq %rcx, %rbx 287 andq $0xfffffffffffff000, %rbx 288 jmp 0b 2892: 290 testb $0x4, %cl /* is it the done indicator? */ 291 jz 2f 292 jmp 3f 2932: 294 testb $0x8, %cl /* is it the source indicator? */ 295 jz 0b /* Ignore it otherwise */ 296 movq %rcx, %rsi /* For ever source page do a copy */ 297 andq $0xfffffffffffff000, %rsi 298 299 movq %rdi, %rdx 300 movq %rsi, %rax 301 302 movq %r10, %rdi 303 movl $512, %ecx 304 rep ; movsq 305 306 movq %rax, %rdi 307 movq %rdx, %rsi 308 movl $512, %ecx 309 rep ; movsq 310 311 movq %rdx, %rdi 312 movq %r10, %rsi 313 movl $512, %ecx 314 rep ; movsq 315 316 lea PAGE_SIZE(%rax), %rsi 317 jmp 0b 3183: 319 ANNOTATE_UNRET_SAFE 320 ret 321 int3 322SYM_CODE_END(swap_pages) 323 324 .skip KEXEC_CONTROL_CODE_MAX_SIZE - (. - relocate_kernel), 0xcc 325SYM_CODE_END(relocate_range); 326