Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch Add reloc keyworkd to let EFI bootstrap load amd64 ...
details: https://anonhg.NetBSD.org/src/rev/a69f36040458
branches: trunk
changeset: 374343:a69f36040458
user: manu <manu%NetBSD.org@localhost>
date: Thu Apr 20 00:42:23 2023 +0000
description:
Add reloc keyworkd to let EFI bootstrap load amd64 kernel at any address
EFI bootstrap assumes it can copy the amd64 kernel to its ELF load
address (that is KERNTEXTOFF - KERNBASE = 0x200000), but it can
clash with previous UEFI memory allocation, as described here:
http://mail-index.netbsd.org/tech-kern/2023/04/07/msg028833.html
This change adds a reloc keyword for controling where the EFI
boostrap will copy the kernel image. Possible values are:
default - the default and prior behavior, copy at 0x200000.
none - do not copy and use the kernel image where it was loaded.
address - specify an explicit address where to copy the kernel.
This comes with an amd64 kernel patch that makes it self-relocatable.
It first discover where it was loaded in memory, and if this is
different than the expected 0x200000, hhe the kernel relocates
itself and start over at the right address.
diffstat:
sys/arch/amd64/amd64/locore.S | 145 ++++++++++++++++++++-
sys/arch/i386/stand/efiboot/boot.c | 47 ++++++-
sys/arch/i386/stand/efiboot/bootia32/efibootia32.c | 4 +-
sys/arch/i386/stand/efiboot/bootia32/startprog32.S | 7 +-
sys/arch/i386/stand/efiboot/bootx64/efibootx64.c | 4 +-
sys/arch/i386/stand/efiboot/bootx64/startprog64.S | 6 +-
sys/arch/i386/stand/efiboot/efiboot.c | 6 +-
sys/arch/i386/stand/efiboot/efiboot.h | 10 +-
sys/arch/i386/stand/lib/exec.c | 23 +++-
9 files changed, 238 insertions(+), 14 deletions(-)
diffs (truncated from 425 to 300 lines):
diff -r ea4caf1943d4 -r a69f36040458 sys/arch/amd64/amd64/locore.S
--- a/sys/arch/amd64/amd64/locore.S Wed Apr 19 22:00:18 2023 +0000
+++ b/sys/arch/amd64/amd64/locore.S Thu Apr 20 00:42:23 2023 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: locore.S,v 1.218 2023/03/03 14:32:48 riastradh Exp $ */
+/* $NetBSD: locore.S,v 1.219 2023/04/20 00:42:23 manu Exp $ */
/*
* Copyright-o-rama!
@@ -456,6 +456,14 @@ ENTRY(start)
#ifndef XENPV
.code32
+ call next
+next: pop %edi
+ sub $(next - kernel_text), %edi
+
+ /* If not KERNBASE, reloc ourselves to KERNBASE */
+ cmpl $(KERNTEXTOFF_LO - KERNBASE_LO), %edi
+ jne selfreloc_start
+
/* Warm boot */
movw $0x1234,0x472
@@ -1757,3 +1765,138 @@ LABEL(mds_leave_end)
LABEL(nomds_leave)
NOMDS_LEAVE
LABEL(nomds_leave_end)
+
+/*
+ * selfreloc(loadddr edi)
+ * This is adapted from sys/arch/i386/i386/locore.S
+ */
+ .code32
+ENTRY(selfreloc_start)
+ movl %edi, %ebx /* loadaddr saved in ebx */
+ movl %edi, %esi /* src */
+ movl $_RELOC(kernel_text), %edi /* dest */
+ movl 16(%esp),%ecx /* esym */
+ subl $_RELOC(kernel_text), %ecx /* size */
+
+#if defined(NO_OVERLAP)
+ movl %ecx, %eax
+#else
+ movl %edi, %eax
+ subl %esi, %eax
+ cmpl %ecx, %eax /* overlapping? */
+ movl %ecx, %eax
+ jb .Lbackwards
+#endif
+ /* nope, copy forwards. */
+ shrl $2, %ecx /* copy by words */
+ rep
+ movsl
+ and $3, %eax /* any bytes left? */
+ jnz .Ltrailing
+ jmp .Lcopy_done
+
+.Ltrailing:
+ cmp $2, %eax
+ jb 11f
+ movw (%esi), %ax
+ movw %ax, (%edi)
+ je .Lcopy_done
+ movb 2(%esi), %al
+ movb %al, 2(%edi)
+ jmp .Lcopy_done
+11: movb (%esi), %al
+ movb %al, (%edi)
+ jmp .Lcopy_done
+
+#if !defined(NO_OVERLAP)
+.Lbackwards:
+ addl %ecx, %edi /* copy backwards. */
+ addl %ecx, %esi
+ and $3, %eax /* any fractional bytes? */
+ jnz .Lback_align
+.Lback_aligned:
+ shrl $2, %ecx
+ subl $4, %esi
+ subl $4, %edi
+ std
+ rep
+ movsl
+ cld
+ jmp .Lcopy_done
+
+.Lback_align:
+ sub %eax, %esi
+ sub %eax, %edi
+ cmp $2, %eax
+ jb 11f
+ je 12f
+ movb 2(%esi), %al
+ movb %al, 2(%edi)
+12: movw (%esi), %ax
+ movw %ax, (%edi)
+ jmp .Lback_aligned
+11: movb (%esi), %al
+ movb %al, (%edi)
+ jmp .Lback_aligned
+#endif
+ /* End of copy kernel */
+.Lcopy_done:
+ cld /* LynxOS depends on it */
+
+ /* load current selfreloc_start addesss in $edi */
+ movl %ebx, %edi /* loadaddr was saved in ebx */
+ addl $(selfreloc_start - kernel_text), %edi
+
+ /* Prepare jump address */
+ lea (selfreloc_start32a - selfreloc_start)(%edi), %eax
+ movl %eax, (selfreloc_start32r - selfreloc_start)(%edi)
+
+ /* Setup GDT */
+ lea (gdt - selfreloc_start)(%edi), %eax
+ mov %eax, (gdtrr - selfreloc_start)(%edi)
+ lgdt (gdtr - selfreloc_start)(%edi)
+
+ /* Jump to set %cs */
+ ljmp *(selfreloc_start32r - selfreloc_start)(%edi)
+
+ .align 4
+selfreloc_start32a:
+ movl $0x10, %eax /* #define DATA_SEGMENT 0x10 */
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+
+ /* Disable Paging in CR0 */
+ movl %cr0, %eax
+ andl $(~CR0_PG), %eax
+ movl %eax, %cr0
+
+ /* Disable PAE in CR4 */
+ movl %cr4, %eax
+ andl $(~CR4_PAE), %eax
+ movl %eax, %cr4
+
+ jmp selfreloc_start32b
+
+ .align 4
+selfreloc_start32b:
+ xor %eax, %eax
+ movl $_RELOC(start), %esi
+ jmp *%esi
+
+ .align 16
+selfreloc_start32r:
+ .long 0
+ .long 0x08 /* #define CODE_SEGMENT 0x08 */
+ .align 16
+gdt:
+ .long 0, 0
+ .byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9f, 0xcf, 0x00
+ .byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x93, 0xcf, 0x00
+gdtr:
+ .word gdtr - gdt
+gdtrr:
+ .quad
+END(selfreloc_start)
diff -r ea4caf1943d4 -r a69f36040458 sys/arch/i386/stand/efiboot/boot.c
--- a/sys/arch/i386/stand/efiboot/boot.c Wed Apr 19 22:00:18 2023 +0000
+++ b/sys/arch/i386/stand/efiboot/boot.c Thu Apr 20 00:42:23 2023 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: boot.c,v 1.21 2022/06/08 21:43:45 wiz Exp $ */
+/* $NetBSD: boot.c,v 1.22 2023/04/20 00:42:24 manu Exp $ */
/*-
* Copyright (c) 2016 Kimihiro Nonaka <nonaka%netbsd.org@localhost>
@@ -83,6 +83,7 @@ void command_menu(char *);
#endif
void command_modules(char *);
void command_multiboot(char *);
+void command_reloc(char *);
void command_text(char *);
void command_version(char *);
@@ -109,6 +110,7 @@ const struct bootblk_command commands[]
#endif
{ "modules", command_modules },
{ "multiboot", command_multiboot },
+ { "reloc", command_reloc },
{ "rndseed", rnd_add },
{ "splash", splash_add },
{ "text", command_text },
@@ -406,6 +408,7 @@ command_help(char *arg)
#endif
"modules {on|off|enabled|disabled}\n"
"multiboot [dev:][filename] [<args>]\n"
+ "reloc {address|none|default}\n"
"rndseed {path_to_rndseed_file}\n"
"splash {path_to_image_file}\n"
"text [{modenum|list}]\n"
@@ -641,6 +644,48 @@ command_multiboot(char *arg)
}
void
+command_reloc(char *arg)
+{
+ char *ep;
+
+ if (*arg == '\0') {
+ switch (efi_reloc_type) {
+ case RELOC_NONE:
+ printf("reloc: none\n");
+ break;
+ case RELOC_ADDR:
+ printf("reloc: %p\n", (void *)efi_kernel_reloc);
+ break;
+ case RELOC_DEFAULT:
+ default:
+ printf("reloc: default\n");
+ break;
+ }
+ goto out;
+ }
+
+ if (strcmp(arg, "default") == 0) {
+ efi_reloc_type = RELOC_DEFAULT;
+ goto out;
+ }
+
+ if (strcmp(arg, "none") == 0) {
+ efi_reloc_type = RELOC_NONE;
+ goto out;
+ }
+
+ errno = 0;
+ efi_kernel_reloc = strtoul(arg, &ep, 0);
+ if (ep == arg || *ep != '\0' || errno)
+ printf("could not parse address \"%s\"\n", arg);
+ else
+ efi_reloc_type = RELOC_ADDR;
+out:
+ return;
+
+}
+
+void
command_version(char *arg)
{
CHAR16 *path;
diff -r ea4caf1943d4 -r a69f36040458 sys/arch/i386/stand/efiboot/bootia32/efibootia32.c
--- a/sys/arch/i386/stand/efiboot/bootia32/efibootia32.c Wed Apr 19 22:00:18 2023 +0000
+++ b/sys/arch/i386/stand/efiboot/bootia32/efibootia32.c Thu Apr 20 00:42:23 2023 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: efibootia32.c,v 1.5 2019/09/13 02:19:45 manu Exp $ */
+/* $NetBSD: efibootia32.c,v 1.6 2023/04/20 00:42:24 manu Exp $ */
/*-
* Copyright (c) 2016 Kimihiro Nonaka <nonaka%netbsd.org@localhost>
@@ -76,7 +76,7 @@ startprog(physaddr_t entry, uint32_t arg
(*startprog32)(entry, argc, argv,
(physaddr_t)startprog32 + startprog32_size,
- efi_kernel_start, efi_kernel_start + efi_loadaddr,
+ efi_kernel_start, efi_load_start,
efi_kernel_size, startprog32);
}
diff -r ea4caf1943d4 -r a69f36040458 sys/arch/i386/stand/efiboot/bootia32/startprog32.S
--- a/sys/arch/i386/stand/efiboot/bootia32/startprog32.S Wed Apr 19 22:00:18 2023 +0000
+++ b/sys/arch/i386/stand/efiboot/bootia32/startprog32.S Thu Apr 20 00:42:23 2023 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: startprog32.S,v 1.2 2017/02/24 12:24:25 nonaka Exp $ */
+/* $NetBSD: startprog32.S,v 1.3 2023/04/20 00:42:24 manu Exp $ */
/* NetBSD: startprog.S,v 1.4 2016/12/04 08:21:08 maxv Exp */
/*
@@ -117,6 +117,11 @@ start:
movl 24(%ebp), %edi /* dest */
movl 28(%ebp), %esi /* src */
movl 32(%ebp), %ecx /* size */
+
+ /* skip copy if same source and destination */
+ cmpl %edi,%esi
+ jz .Lcopy_done
+
#if defined(NO_OVERLAP)
movl %ecx, %eax
#else
diff -r ea4caf1943d4 -r a69f36040458 sys/arch/i386/stand/efiboot/bootx64/efibootx64.c
--- a/sys/arch/i386/stand/efiboot/bootx64/efibootx64.c Wed Apr 19 22:00:18 2023 +0000
+++ b/sys/arch/i386/stand/efiboot/bootx64/efibootx64.c Thu Apr 20 00:42:23 2023 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: efibootx64.c,v 1.5 2019/09/13 02:19:46 manu Exp $ */
+/* $NetBSD: efibootx64.c,v 1.6 2023/04/20 00:42:24 manu Exp $ */
/*-
* Copyright (c) 2016 Kimihiro Nonaka <nonaka%netbsd.org@localhost>
@@ -80,7 +80,7 @@ startprog(physaddr_t entry, uint32_t arg
memcpy(newsp, argv, sizeof(*argv) * argc);
}
- (*startprog64)(efi_kernel_start, efi_kernel_start + efi_loadaddr,
+ (*startprog64)(efi_kernel_start, efi_load_start,
(physaddr_t)newsp, efi_kernel_size, startprog64, entry);
Home |
Main Index |
Thread Index |
Old Index