2022-05-31 06:04:11 -04:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
|
|
|
*/
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/threads.h>
|
|
|
|
|
|
|
|
#include <asm/addrspace.h>
|
|
|
|
#include <asm/asm.h>
|
|
|
|
#include <asm/asmmacro.h>
|
2022-10-12 04:36:19 -04:00
|
|
|
#include <asm/bug.h>
|
2022-05-31 06:04:11 -04:00
|
|
|
#include <asm/regdef.h>
|
|
|
|
#include <asm/loongarch.h>
|
|
|
|
#include <asm/stackframe.h>
|
|
|
|
|
efi/loongarch: Add efistub booting support
This patch adds efistub booting support, which is the standard UEFI boot
protocol for LoongArch to use.
We use generic efistub, which means we can pass boot information (i.e.,
system table, memory map, kernel command line, initrd) via a light FDT
and drop a lot of non-standard code.
We use a flat mapping to map the efi runtime in the kernel's address
space. In efi, VA = PA; in kernel, VA = PA + PAGE_OFFSET. As a result,
flat mapping is not identity mapping, SetVirtualAddressMap() is still
needed for the efi runtime.
Tested-by: Xi Ruoyao <xry111@xry111.site>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
[ardb: change fpic to fpie as suggested by Xi Ruoyao]
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2022-08-19 06:20:37 -04:00
|
|
|
#ifdef CONFIG_EFI_STUB
|
|
|
|
|
|
|
|
#include "efi-header.S"
|
|
|
|
|
|
|
|
__HEAD
|
|
|
|
|
|
|
|
_head:
|
|
|
|
.word MZ_MAGIC /* "MZ", MS-DOS header */
|
2022-10-12 04:36:19 -04:00
|
|
|
.org 0x8
|
|
|
|
.dword kernel_entry /* Kernel entry point */
|
2023-06-29 08:58:42 -04:00
|
|
|
.dword _kernel_asize /* Kernel image effective size */
|
2023-02-25 02:52:56 -05:00
|
|
|
.quad PHYS_LINK_KADDR /* Kernel image load offset from start of RAM */
|
efi: Put Linux specific magic number in the DOS header
GRUB currently relies on the magic number in the image header of ARM and
arm64 EFI kernel images to decide whether or not the image in question
is a bootable kernel.
However, the purpose of the magic number is to identify the image as one
that implements the bare metal boot protocol, and so GRUB, which only
does EFI boot, is limited unnecessarily to booting images that could
potentially be booted in a non-EFI manner as well.
This is problematic for the new zboot decompressor image format, as it
can only boot in EFI mode, and must therefore not use the bare metal
boot magic number in its header.
For this reason, the strict magic number was dropped from GRUB, to
permit essentially any kind of EFI executable to be booted via the
'linux' command, blurring the line between the linux loader and the
chainloader.
So let's use the same field in the DOS header that RISC-V and arm64
already use for their 'bare metal' magic numbers to store a 'generic
Linux kernel' magic number, which can be used to identify bootable
kernel images in PE format which don't necessarily implement a bare
metal boot protocol in the same binary. Note that, in the context of
EFI, the MS-DOS header is only described in terms of the fields that it
shares with the hybrid PE/COFF image format, (i.e., the MS-DOS EXE magic
number at offset #0 and the PE header offset at byte offset #0x3c).
Since we aim for compatibility with EFI only, and not with MS-DOS or
MS-Windows, we can use the remaining space in the MS-DOS header however
we want.
Let's set the generic magic number for x86 images as well: existing
bootloaders already have their own methods to identify x86 Linux images
that can be booted in a non-EFI manner, and having the magic number in
place there will ease any future transitions in loader implementations
to merge the x86 and non-x86 EFI boot paths.
Note that 32-bit ARM already uses the same location in the header for a
different purpose, but the ARM support is already widely implemented and
the EFI zboot decompressor is not available on ARM anyway, so we just
disregard it here.
Acked-by: Leif Lindholm <quic_llindhol@quicinc.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2022-11-09 09:16:11 -05:00
|
|
|
.org 0x38 /* 0x20 ~ 0x37 reserved */
|
|
|
|
.long LINUX_PE_MAGIC
|
efi/loongarch: Add efistub booting support
This patch adds efistub booting support, which is the standard UEFI boot
protocol for LoongArch to use.
We use generic efistub, which means we can pass boot information (i.e.,
system table, memory map, kernel command line, initrd) via a light FDT
and drop a lot of non-standard code.
We use a flat mapping to map the efi runtime in the kernel's address
space. In efi, VA = PA; in kernel, VA = PA + PAGE_OFFSET. As a result,
flat mapping is not identity mapping, SetVirtualAddressMap() is still
needed for the efi runtime.
Tested-by: Xi Ruoyao <xry111@xry111.site>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
[ardb: change fpic to fpie as suggested by Xi Ruoyao]
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2022-08-19 06:20:37 -04:00
|
|
|
.long pe_header - _head /* Offset to the PE header */
|
|
|
|
|
|
|
|
pe_header:
|
|
|
|
__EFI_PE_HEADER
|
|
|
|
|
2023-06-29 08:58:42 -04:00
|
|
|
SYM_DATA(kernel_asize, .long _kernel_asize);
|
|
|
|
SYM_DATA(kernel_fsize, .long _kernel_fsize);
|
efi/loongarch: Add efistub booting support
This patch adds efistub booting support, which is the standard UEFI boot
protocol for LoongArch to use.
We use generic efistub, which means we can pass boot information (i.e.,
system table, memory map, kernel command line, initrd) via a light FDT
and drop a lot of non-standard code.
We use a flat mapping to map the efi runtime in the kernel's address
space. In efi, VA = PA; in kernel, VA = PA + PAGE_OFFSET. As a result,
flat mapping is not identity mapping, SetVirtualAddressMap() is still
needed for the efi runtime.
Tested-by: Xi Ruoyao <xry111@xry111.site>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
[ardb: change fpic to fpie as suggested by Xi Ruoyao]
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2022-08-19 06:20:37 -04:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2022-05-31 06:04:11 -04:00
|
|
|
__REF
|
|
|
|
|
2022-09-26 10:25:29 -04:00
|
|
|
.align 12
|
|
|
|
|
2022-05-31 06:04:11 -04:00
|
|
|
SYM_CODE_START(kernel_entry) # kernel entry point
|
|
|
|
|
|
|
|
/* Config direct window and set PG */
|
|
|
|
li.d t0, CSR_DMW0_INIT # UC, PLV0, 0x8000 xxxx xxxx xxxx
|
|
|
|
csrwr t0, LOONGARCH_CSR_DMWIN0
|
|
|
|
li.d t0, CSR_DMW1_INIT # CA, PLV0, 0x9000 xxxx xxxx xxxx
|
|
|
|
csrwr t0, LOONGARCH_CSR_DMWIN1
|
2022-08-11 08:52:12 -04:00
|
|
|
|
2023-02-25 02:52:56 -05:00
|
|
|
JUMP_VIRT_ADDR t0, t1
|
|
|
|
|
2022-05-31 06:04:11 -04:00
|
|
|
/* Enable PG */
|
|
|
|
li.w t0, 0xb0 # PLV=0, IE=0, PG=1
|
|
|
|
csrwr t0, LOONGARCH_CSR_CRMD
|
|
|
|
li.w t0, 0x04 # PLV=0, PIE=1, PWE=0
|
|
|
|
csrwr t0, LOONGARCH_CSR_PRMD
|
|
|
|
li.w t0, 0x00 # FPE=0, SXE=0, ASXE=0, BTE=0
|
|
|
|
csrwr t0, LOONGARCH_CSR_EUEN
|
|
|
|
|
2022-10-12 04:36:08 -04:00
|
|
|
la.pcrel t0, __bss_start # clear .bss
|
2022-05-31 06:04:11 -04:00
|
|
|
st.d zero, t0, 0
|
2022-10-12 04:36:08 -04:00
|
|
|
la.pcrel t1, __bss_stop - LONGSIZE
|
2022-05-31 06:04:11 -04:00
|
|
|
1:
|
|
|
|
addi.d t0, t0, LONGSIZE
|
|
|
|
st.d zero, t0, 0
|
|
|
|
bne t0, t1, 1b
|
|
|
|
|
2022-10-12 04:36:08 -04:00
|
|
|
la.pcrel t0, fw_arg0
|
2022-05-31 06:04:11 -04:00
|
|
|
st.d a0, t0, 0 # firmware arguments
|
2022-10-12 04:36:08 -04:00
|
|
|
la.pcrel t0, fw_arg1
|
2022-05-31 06:04:11 -04:00
|
|
|
st.d a1, t0, 0
|
2022-10-12 04:36:08 -04:00
|
|
|
la.pcrel t0, fw_arg2
|
efi/loongarch: libstub: remove dependency on flattened DT
LoongArch does not use FDT or DT natively [yet], and the only reason it
currently uses it is so that it can reuse the existing EFI stub code.
Overloading the DT with data passed between the EFI stub and the core
kernel has been a source of problems: there is the overlap between
information provided by EFI which DT can also provide (initrd base/size,
command line, memory descriptions), requiring us to reason about which
is which and what to prioritize. It has also resulted in ABI leaks,
i.e., internal ABI being promoted to external ABI inadvertently because
the bootloader can set the EFI stub's DT properties as well (e.g.,
"kaslr-seed"). This has become especially problematic with boot
environments that want to pretend that EFI boot is being done (to access
ACPI and SMBIOS tables, for instance) but have no ability to execute the
EFI stub, and so the environment that the EFI stub creates is emulated
[poorly, in some cases].
Another downside of treating DT like this is that the DT binary that the
kernel receives is different from the one created by the firmware, which
is undesirable in the context of secure and measured boot.
Given that LoongArch support in Linux is brand new, we can avoid these
pitfalls, and treat the DT strictly as a hardware description, and use a
separate handover method between the EFI stub and the kernel. Now that
initrd loading and passing the EFI memory map have been refactored into
pure EFI routines that use EFI configuration tables, the only thing we
need to pass directly is the kernel command line (even if we could pass
this via a config table as well, it is used extremely early, so passing
it directly is preferred in this case.)
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Acked-by: Huacai Chen <chenhuacai@loongson.cn>
2022-09-16 13:48:53 -04:00
|
|
|
st.d a2, t0, 0
|
2022-05-31 06:04:11 -04:00
|
|
|
|
2024-01-16 23:43:08 -05:00
|
|
|
#ifdef CONFIG_PAGE_SIZE_4KB
|
|
|
|
li.d t0, 0
|
|
|
|
li.d t1, CSR_STFILL
|
|
|
|
csrxchg t0, t1, LOONGARCH_CSR_IMPCTL1
|
|
|
|
#endif
|
2022-05-31 06:04:11 -04:00
|
|
|
/* KSave3 used for percpu base, initialized as 0 */
|
|
|
|
csrwr zero, PERCPU_BASE_KS
|
|
|
|
/* GPR21 used for percpu base (runtime), initialized as 0 */
|
2022-07-26 11:57:18 -04:00
|
|
|
move u0, zero
|
2022-05-31 06:04:11 -04:00
|
|
|
|
2022-10-12 04:36:08 -04:00
|
|
|
la.pcrel tp, init_thread_union
|
2022-05-31 06:04:11 -04:00
|
|
|
/* Set the SP after an empty pt_regs. */
|
2022-10-29 04:29:31 -04:00
|
|
|
PTR_LI sp, (_THREAD_SIZE - PT_SIZE)
|
2022-05-31 06:04:11 -04:00
|
|
|
PTR_ADD sp, sp, tp
|
|
|
|
set_saved_sp sp, t0, t1
|
|
|
|
|
2023-02-25 02:52:56 -05:00
|
|
|
#ifdef CONFIG_RELOCATABLE
|
2023-02-25 02:52:56 -05:00
|
|
|
|
2023-02-25 02:52:56 -05:00
|
|
|
bl relocate_kernel
|
2023-02-25 02:52:56 -05:00
|
|
|
|
|
|
|
#ifdef CONFIG_RANDOMIZE_BASE
|
|
|
|
/* Repoint the sp into the new kernel */
|
|
|
|
PTR_LI sp, (_THREAD_SIZE - PT_SIZE)
|
|
|
|
PTR_ADD sp, sp, tp
|
|
|
|
set_saved_sp sp, t0, t1
|
|
|
|
|
2023-09-06 10:54:16 -04:00
|
|
|
/* Jump to the new kernel: new_pc = current_pc + random_offset */
|
|
|
|
pcaddi t0, 0
|
|
|
|
add.d t0, t0, a0
|
|
|
|
jirl zero, t0, 0xc
|
|
|
|
#endif /* CONFIG_RANDOMIZE_BASE */
|
2023-02-25 02:52:56 -05:00
|
|
|
|
2023-09-06 10:54:16 -04:00
|
|
|
#endif /* CONFIG_RELOCATABLE */
|
2023-02-25 02:52:56 -05:00
|
|
|
|
2023-09-06 10:54:16 -04:00
|
|
|
#ifdef CONFIG_KASAN
|
|
|
|
bl kasan_early_init
|
|
|
|
#endif
|
|
|
|
|
2022-05-31 06:04:11 -04:00
|
|
|
bl start_kernel
|
2022-10-12 04:36:19 -04:00
|
|
|
ASM_BUG()
|
2022-05-31 06:04:11 -04:00
|
|
|
|
|
|
|
SYM_CODE_END(kernel_entry)
|
|
|
|
|
2022-05-31 06:04:12 -04:00
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SMP slave cpus entry point. Board specific code for bootstrap calls this
|
|
|
|
* function after setting up the stack and tp registers.
|
|
|
|
*/
|
|
|
|
SYM_CODE_START(smpboot_entry)
|
|
|
|
li.d t0, CSR_DMW0_INIT # UC, PLV0
|
|
|
|
csrwr t0, LOONGARCH_CSR_DMWIN0
|
|
|
|
li.d t0, CSR_DMW1_INIT # CA, PLV0
|
|
|
|
csrwr t0, LOONGARCH_CSR_DMWIN1
|
2022-08-11 08:52:12 -04:00
|
|
|
|
2023-02-25 02:52:56 -05:00
|
|
|
JUMP_VIRT_ADDR t0, t1
|
|
|
|
|
2024-01-16 23:43:08 -05:00
|
|
|
#ifdef CONFIG_PAGE_SIZE_4KB
|
|
|
|
li.d t0, 0
|
|
|
|
li.d t1, CSR_STFILL
|
|
|
|
csrxchg t0, t1, LOONGARCH_CSR_IMPCTL1
|
|
|
|
#endif
|
2022-08-11 08:52:12 -04:00
|
|
|
/* Enable PG */
|
2022-05-31 06:04:12 -04:00
|
|
|
li.w t0, 0xb0 # PLV=0, IE=0, PG=1
|
|
|
|
csrwr t0, LOONGARCH_CSR_CRMD
|
|
|
|
li.w t0, 0x04 # PLV=0, PIE=1, PWE=0
|
|
|
|
csrwr t0, LOONGARCH_CSR_PRMD
|
|
|
|
li.w t0, 0x00 # FPE=0, SXE=0, ASXE=0, BTE=0
|
|
|
|
csrwr t0, LOONGARCH_CSR_EUEN
|
|
|
|
|
2023-02-25 02:52:56 -05:00
|
|
|
la.pcrel t0, cpuboot_data
|
2022-05-31 06:04:12 -04:00
|
|
|
ld.d sp, t0, CPU_BOOT_STACK
|
|
|
|
ld.d tp, t0, CPU_BOOT_TINFO
|
|
|
|
|
|
|
|
bl start_secondary
|
2022-10-12 04:36:19 -04:00
|
|
|
ASM_BUG()
|
|
|
|
|
2022-05-31 06:04:12 -04:00
|
|
|
SYM_CODE_END(smpboot_entry)
|
|
|
|
|
|
|
|
#endif /* CONFIG_SMP */
|
|
|
|
|
2022-05-31 06:04:11 -04:00
|
|
|
SYM_ENTRY(kernel_entry_end, SYM_L_GLOBAL, SYM_A_NONE)
|