Merge remote-tracking branch 'asoc/topic/pcm512x' into asoc-next
[sfrench/cifs-2.6.git] / arch / x86 / boot / compressed / head_64.S
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  *  linux/boot/head.S
4  *
5  *  Copyright (C) 1991, 1992, 1993  Linus Torvalds
6  */
7
8 /*
9  *  head.S contains the 32-bit startup code.
10  *
11  * NOTE!!! Startup happens at absolute address 0x00001000, which is also where
12  * the page directory will exist. The startup code will be overwritten by
13  * the page directory. [According to comments etc elsewhere on a compressed
14  * kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC]
15  *
16  * Page 0 is deliberately kept safe, since System Management Mode code in 
17  * laptops may need to access the BIOS data stored there.  This is also
18  * useful for future device drivers that either access the BIOS via VM86 
19  * mode.
20  */
21
22 /*
23  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
24  */
25         .code32
26         .text
27
28 #include <linux/init.h>
29 #include <linux/linkage.h>
30 #include <asm/segment.h>
31 #include <asm/boot.h>
32 #include <asm/msr.h>
33 #include <asm/processor-flags.h>
34 #include <asm/asm-offsets.h>
35 #include <asm/bootparam.h>
36
37 /*
38  * Locally defined symbols should be marked hidden:
39  */
40         .hidden _bss
41         .hidden _ebss
42         .hidden _got
43         .hidden _egot
44
45         __HEAD
46         .code32
47 ENTRY(startup_32)
48         /*
49          * 32bit entry is 0 and it is ABI so immutable!
50          * If we come here directly from a bootloader,
51          * kernel(text+data+bss+brk) ramdisk, zero_page, command line
52          * all need to be under the 4G limit.
53          */
54         cld
55         /*
56          * Test KEEP_SEGMENTS flag to see if the bootloader is asking
57          * us to not reload segments
58          */
59         testb $KEEP_SEGMENTS, BP_loadflags(%esi)
60         jnz 1f
61
62         cli
63         movl    $(__BOOT_DS), %eax
64         movl    %eax, %ds
65         movl    %eax, %es
66         movl    %eax, %ss
67 1:
68
69 /*
70  * Calculate the delta between where we were compiled to run
71  * at and where we were actually loaded at.  This can only be done
72  * with a short local call on x86.  Nothing  else will tell us what
73  * address we are running at.  The reserved chunk of the real-mode
74  * data at 0x1e4 (defined as a scratch field) are used as the stack
75  * for this calculation. Only 4 bytes are needed.
76  */
77         leal    (BP_scratch+4)(%esi), %esp
78         call    1f
79 1:      popl    %ebp
80         subl    $1b, %ebp
81
82 /* setup a stack and make sure cpu supports long mode. */
83         movl    $boot_stack_end, %eax
84         addl    %ebp, %eax
85         movl    %eax, %esp
86
87         call    verify_cpu
88         testl   %eax, %eax
89         jnz     no_longmode
90
91 /*
92  * Compute the delta between where we were compiled to run at
93  * and where the code will actually run at.
94  *
95  * %ebp contains the address we are loaded at by the boot loader and %ebx
96  * contains the address where we should move the kernel image temporarily
97  * for safe in-place decompression.
98  */
99
100 #ifdef CONFIG_RELOCATABLE
101         movl    %ebp, %ebx
102         movl    BP_kernel_alignment(%esi), %eax
103         decl    %eax
104         addl    %eax, %ebx
105         notl    %eax
106         andl    %eax, %ebx
107         cmpl    $LOAD_PHYSICAL_ADDR, %ebx
108         jge     1f
109 #endif
110         movl    $LOAD_PHYSICAL_ADDR, %ebx
111 1:
112
113         /* Target address to relocate to for decompression */
114         movl    BP_init_size(%esi), %eax
115         subl    $_end, %eax
116         addl    %eax, %ebx
117
118 /*
119  * Prepare for entering 64 bit mode
120  */
121
122         /* Load new GDT with the 64bit segments using 32bit descriptor */
123         addl    %ebp, gdt+2(%ebp)
124         lgdt    gdt(%ebp)
125
126         /* Enable PAE mode */
127         movl    %cr4, %eax
128         orl     $X86_CR4_PAE, %eax
129         movl    %eax, %cr4
130
131  /*
132   * Build early 4G boot pagetable
133   */
134         /* Initialize Page tables to 0 */
135         leal    pgtable(%ebx), %edi
136         xorl    %eax, %eax
137         movl    $(BOOT_INIT_PGT_SIZE/4), %ecx
138         rep     stosl
139
140         /* Build Level 4 */
141         leal    pgtable + 0(%ebx), %edi
142         leal    0x1007 (%edi), %eax
143         movl    %eax, 0(%edi)
144
145         /* Build Level 3 */
146         leal    pgtable + 0x1000(%ebx), %edi
147         leal    0x1007(%edi), %eax
148         movl    $4, %ecx
149 1:      movl    %eax, 0x00(%edi)
150         addl    $0x00001000, %eax
151         addl    $8, %edi
152         decl    %ecx
153         jnz     1b
154
155         /* Build Level 2 */
156         leal    pgtable + 0x2000(%ebx), %edi
157         movl    $0x00000183, %eax
158         movl    $2048, %ecx
159 1:      movl    %eax, 0(%edi)
160         addl    $0x00200000, %eax
161         addl    $8, %edi
162         decl    %ecx
163         jnz     1b
164
165         /* Enable the boot page tables */
166         leal    pgtable(%ebx), %eax
167         movl    %eax, %cr3
168
169         /* Enable Long mode in EFER (Extended Feature Enable Register) */
170         movl    $MSR_EFER, %ecx
171         rdmsr
172         btsl    $_EFER_LME, %eax
173         wrmsr
174
175         /* After gdt is loaded */
176         xorl    %eax, %eax
177         lldt    %ax
178         movl    $__BOOT_TSS, %eax
179         ltr     %ax
180
181         /*
182          * Setup for the jump to 64bit mode
183          *
184          * When the jump is performend we will be in long mode but
185          * in 32bit compatibility mode with EFER.LME = 1, CS.L = 0, CS.D = 1
186          * (and in turn EFER.LMA = 1).  To jump into 64bit mode we use
187          * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
188          * We place all of the values on our mini stack so lret can
189          * used to perform that far jump.
190          */
191         pushl   $__KERNEL_CS
192         leal    startup_64(%ebp), %eax
193 #ifdef CONFIG_EFI_MIXED
194         movl    efi32_config(%ebp), %ebx
195         cmp     $0, %ebx
196         jz      1f
197         leal    handover_entry(%ebp), %eax
198 1:
199 #endif
200         pushl   %eax
201
202         /* Enter paged protected Mode, activating Long Mode */
203         movl    $(X86_CR0_PG | X86_CR0_PE), %eax /* Enable Paging and Protected mode */
204         movl    %eax, %cr0
205
206         /* Jump from 32bit compatibility mode into 64bit mode. */
207         lret
208 ENDPROC(startup_32)
209
210 #ifdef CONFIG_EFI_MIXED
211         .org 0x190
212 ENTRY(efi32_stub_entry)
213         add     $0x4, %esp              /* Discard return address */
214         popl    %ecx
215         popl    %edx
216         popl    %esi
217
218         leal    (BP_scratch+4)(%esi), %esp
219         call    1f
220 1:      pop     %ebp
221         subl    $1b, %ebp
222
223         movl    %ecx, efi32_config(%ebp)
224         movl    %edx, efi32_config+8(%ebp)
225         sgdtl   efi32_boot_gdt(%ebp)
226
227         leal    efi32_config(%ebp), %eax
228         movl    %eax, efi_config(%ebp)
229
230         jmp     startup_32
231 ENDPROC(efi32_stub_entry)
232 #endif
233
234         .code64
235         .org 0x200
236 ENTRY(startup_64)
237         /*
238          * 64bit entry is 0x200 and it is ABI so immutable!
239          * We come here either from startup_32 or directly from a
240          * 64bit bootloader.
241          * If we come here from a bootloader, kernel(text+data+bss+brk),
242          * ramdisk, zero_page, command line could be above 4G.
243          * We depend on an identity mapped page table being provided
244          * that maps our entire kernel(text+data+bss+brk), zero page
245          * and command line.
246          */
247
248         /* Setup data segments. */
249         xorl    %eax, %eax
250         movl    %eax, %ds
251         movl    %eax, %es
252         movl    %eax, %ss
253         movl    %eax, %fs
254         movl    %eax, %gs
255
256         /*
257          * Compute the decompressed kernel start address.  It is where
258          * we were loaded at aligned to a 2M boundary. %rbp contains the
259          * decompressed kernel start address.
260          *
261          * If it is a relocatable kernel then decompress and run the kernel
262          * from load address aligned to 2MB addr, otherwise decompress and
263          * run the kernel from LOAD_PHYSICAL_ADDR
264          *
265          * We cannot rely on the calculation done in 32-bit mode, since we
266          * may have been invoked via the 64-bit entry point.
267          */
268
269         /* Start with the delta to where the kernel will run at. */
270 #ifdef CONFIG_RELOCATABLE
271         leaq    startup_32(%rip) /* - $startup_32 */, %rbp
272         movl    BP_kernel_alignment(%rsi), %eax
273         decl    %eax
274         addq    %rax, %rbp
275         notq    %rax
276         andq    %rax, %rbp
277         cmpq    $LOAD_PHYSICAL_ADDR, %rbp
278         jge     1f
279 #endif
280         movq    $LOAD_PHYSICAL_ADDR, %rbp
281 1:
282
283         /* Target address to relocate to for decompression */
284         movl    BP_init_size(%rsi), %ebx
285         subl    $_end, %ebx
286         addq    %rbp, %rbx
287
288         /* Set up the stack */
289         leaq    boot_stack_end(%rbx), %rsp
290
291 #ifdef CONFIG_X86_5LEVEL
292         /* Check if 5-level paging has already enabled */
293         movq    %cr4, %rax
294         testl   $X86_CR4_LA57, %eax
295         jnz     lvl5
296
297         /*
298          * At this point we are in long mode with 4-level paging enabled,
299          * but we want to enable 5-level paging.
300          *
301          * The problem is that we cannot do it directly. Setting LA57 in
302          * long mode would trigger #GP. So we need to switch off long mode
303          * first.
304          *
305          * NOTE: This is not going to work if bootloader put us above 4G
306          * limit.
307          *
308          * The first step is go into compatibility mode.
309          */
310
311         /* Clear additional page table */
312         leaq    lvl5_pgtable(%rbx), %rdi
313         xorq    %rax, %rax
314         movq    $(PAGE_SIZE/8), %rcx
315         rep     stosq
316
317         /*
318          * Setup current CR3 as the first and only entry in a new top level
319          * page table.
320          */
321         movq    %cr3, %rdi
322         leaq    0x7 (%rdi), %rax
323         movq    %rax, lvl5_pgtable(%rbx)
324
325         /* Switch to compatibility mode (CS.L = 0 CS.D = 1) via far return */
326         pushq   $__KERNEL32_CS
327         leaq    compatible_mode(%rip), %rax
328         pushq   %rax
329         lretq
330 lvl5:
331 #endif
332
333         /* Zero EFLAGS */
334         pushq   $0
335         popfq
336
337 /*
338  * Copy the compressed kernel to the end of our buffer
339  * where decompression in place becomes safe.
340  */
341         pushq   %rsi
342         leaq    (_bss-8)(%rip), %rsi
343         leaq    (_bss-8)(%rbx), %rdi
344         movq    $_bss /* - $startup_32 */, %rcx
345         shrq    $3, %rcx
346         std
347         rep     movsq
348         cld
349         popq    %rsi
350
351 /*
352  * Jump to the relocated address.
353  */
354         leaq    relocated(%rbx), %rax
355         jmp     *%rax
356
357 #ifdef CONFIG_EFI_STUB
358
359 /* The entry point for the PE/COFF executable is efi_pe_entry. */
360 ENTRY(efi_pe_entry)
361         movq    %rcx, efi64_config(%rip)        /* Handle */
362         movq    %rdx, efi64_config+8(%rip) /* EFI System table pointer */
363
364         leaq    efi64_config(%rip), %rax
365         movq    %rax, efi_config(%rip)
366
367         call    1f
368 1:      popq    %rbp
369         subq    $1b, %rbp
370
371         /*
372          * Relocate efi_config->call().
373          */
374         addq    %rbp, efi64_config+40(%rip)
375
376         movq    %rax, %rdi
377         call    make_boot_params
378         cmpq    $0,%rax
379         je      fail
380         mov     %rax, %rsi
381         leaq    startup_32(%rip), %rax
382         movl    %eax, BP_code32_start(%rsi)
383         jmp     2f              /* Skip the relocation */
384
385 handover_entry:
386         call    1f
387 1:      popq    %rbp
388         subq    $1b, %rbp
389
390         /*
391          * Relocate efi_config->call().
392          */
393         movq    efi_config(%rip), %rax
394         addq    %rbp, 40(%rax)
395 2:
396         movq    efi_config(%rip), %rdi
397         call    efi_main
398         movq    %rax,%rsi
399         cmpq    $0,%rax
400         jne     2f
401 fail:
402         /* EFI init failed, so hang. */
403         hlt
404         jmp     fail
405 2:
406         movl    BP_code32_start(%esi), %eax
407         leaq    startup_64(%rax), %rax
408         jmp     *%rax
409 ENDPROC(efi_pe_entry)
410
411         .org 0x390
412 ENTRY(efi64_stub_entry)
413         movq    %rdi, efi64_config(%rip)        /* Handle */
414         movq    %rsi, efi64_config+8(%rip) /* EFI System table pointer */
415
416         leaq    efi64_config(%rip), %rax
417         movq    %rax, efi_config(%rip)
418
419         movq    %rdx, %rsi
420         jmp     handover_entry
421 ENDPROC(efi64_stub_entry)
422 #endif
423
424         .text
425 relocated:
426
427 /*
428  * Clear BSS (stack is currently empty)
429  */
430         xorl    %eax, %eax
431         leaq    _bss(%rip), %rdi
432         leaq    _ebss(%rip), %rcx
433         subq    %rdi, %rcx
434         shrq    $3, %rcx
435         rep     stosq
436
437 /*
438  * Adjust our own GOT
439  */
440         leaq    _got(%rip), %rdx
441         leaq    _egot(%rip), %rcx
442 1:
443         cmpq    %rcx, %rdx
444         jae     2f
445         addq    %rbx, (%rdx)
446         addq    $8, %rdx
447         jmp     1b
448 2:
449         
450 /*
451  * Do the extraction, and jump to the new kernel..
452  */
453         pushq   %rsi                    /* Save the real mode argument */
454         movq    %rsi, %rdi              /* real mode address */
455         leaq    boot_heap(%rip), %rsi   /* malloc area for uncompression */
456         leaq    input_data(%rip), %rdx  /* input_data */
457         movl    $z_input_len, %ecx      /* input_len */
458         movq    %rbp, %r8               /* output target address */
459         movq    $z_output_len, %r9      /* decompressed length, end of relocs */
460         call    extract_kernel          /* returns kernel location in %rax */
461         popq    %rsi
462
463 /*
464  * Jump to the decompressed kernel.
465  */
466         jmp     *%rax
467
468         .code32
469 #ifdef CONFIG_X86_5LEVEL
470 compatible_mode:
471         /* Setup data and stack segments */
472         movl    $__KERNEL_DS, %eax
473         movl    %eax, %ds
474         movl    %eax, %ss
475
476         /* Disable paging */
477         movl    %cr0, %eax
478         btrl    $X86_CR0_PG_BIT, %eax
479         movl    %eax, %cr0
480
481         /* Point CR3 to 5-level paging */
482         leal    lvl5_pgtable(%ebx), %eax
483         movl    %eax, %cr3
484
485         /* Enable PAE and LA57 mode */
486         movl    %cr4, %eax
487         orl     $(X86_CR4_PAE | X86_CR4_LA57), %eax
488         movl    %eax, %cr4
489
490         /* Calculate address we are running at */
491         call    1f
492 1:      popl    %edi
493         subl    $1b, %edi
494
495         /* Prepare stack for far return to Long Mode */
496         pushl   $__KERNEL_CS
497         leal    lvl5(%edi), %eax
498         push    %eax
499
500         /* Enable paging back */
501         movl    $(X86_CR0_PG | X86_CR0_PE), %eax
502         movl    %eax, %cr0
503
504         lret
505 #endif
506
507 no_longmode:
508         /* This isn't an x86-64 CPU so hang */
509 1:
510         hlt
511         jmp     1b
512
513 #include "../../kernel/verify_cpu.S"
514
515         .data
516 gdt:
517         .word   gdt_end - gdt
518         .long   gdt
519         .word   0
520         .quad   0x00cf9a000000ffff      /* __KERNEL32_CS */
521         .quad   0x00af9a000000ffff      /* __KERNEL_CS */
522         .quad   0x00cf92000000ffff      /* __KERNEL_DS */
523         .quad   0x0080890000000000      /* TS descriptor */
524         .quad   0x0000000000000000      /* TS continued */
525 gdt_end:
526
527 #ifdef CONFIG_EFI_STUB
528 efi_config:
529         .quad   0
530
531 #ifdef CONFIG_EFI_MIXED
532         .global efi32_config
533 efi32_config:
534         .fill   5,8,0
535         .quad   efi64_thunk
536         .byte   0
537 #endif
538
539         .global efi64_config
540 efi64_config:
541         .fill   5,8,0
542         .quad   efi_call
543         .byte   1
544 #endif /* CONFIG_EFI_STUB */
545
546 /*
547  * Stack and heap for uncompression
548  */
549         .bss
550         .balign 4
551 boot_heap:
552         .fill BOOT_HEAP_SIZE, 1, 0
553 boot_stack:
554         .fill BOOT_STACK_SIZE, 1, 0
555 boot_stack_end:
556
557 /*
558  * Space for page tables (not in .bss so not zeroed)
559  */
560         .section ".pgtable","a",@nobits
561         .balign 4096
562 pgtable:
563         .fill BOOT_PGT_SIZE, 1, 0
564 #ifdef CONFIG_X86_5LEVEL
565 lvl5_pgtable:
566         .fill PAGE_SIZE, 1, 0
567 #endif