Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch Add multiboot 2 support to amd64 kernel



details:   https://anonhg.NetBSD.org/src/rev/7f5242191b9f
branches:  trunk
changeset: 466054:7f5242191b9f
user:      manu <manu%NetBSD.org@localhost>
date:      Tue Dec 10 02:06:07 2019 +0000

description:
Add multiboot 2 support to amd64 kernel

diffstat:

 sys/arch/amd64/amd64/locore.S     |  759 +++++++++++++++++++++++++++++++++++++-
 sys/arch/amd64/amd64/machdep.c    |   16 +-
 sys/arch/amd64/conf/GENERIC       |    6 +-
 sys/arch/amd64/conf/files.amd64   |    6 +-
 sys/arch/amd64/conf/kern.ldscript |    8 +-
 sys/arch/x86/x86/efi.c            |   18 +-
 sys/arch/x86/x86/multiboot2.c     |  203 ++++++---
 7 files changed, 915 insertions(+), 101 deletions(-)

diffs (truncated from 1295 to 300 lines):

diff -r 13514f82a31c -r 7f5242191b9f sys/arch/amd64/amd64/locore.S
--- a/sys/arch/amd64/amd64/locore.S     Tue Dec 10 02:02:47 2019 +0000
+++ b/sys/arch/amd64/amd64/locore.S     Tue Dec 10 02:06:07 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: locore.S,v 1.192 2019/11/22 23:36:25 ad Exp $  */
+/*     $NetBSD: locore.S,v 1.193 2019/12/10 02:06:07 manu Exp $        */
 
 /*
  * Copyright-o-rama!
@@ -158,6 +158,7 @@
 
 #include "opt_compat_netbsd.h"
 #include "opt_compat_netbsd32.h"
+#include "opt_multiboot.h"
 #include "opt_xen.h"
 #include "opt_svs.h"
 
@@ -177,6 +178,13 @@
 #include <machine/frameasm.h>
 #include <machine/cputypes.h>
 
+#ifndef XENPV
+#include <arch/i386/include/multiboot.h>
+#endif 
+
+#define CODE_SEGMENT   0x08
+#define DATA_SEGMENT   0x10
+
 #if NLAPIC > 0
 #include <machine/i82489reg.h>
 #endif
@@ -424,6 +432,50 @@
        .space  512
 tmpstk:
 
+.section multiboot,"ax",@progbits
+#if defined(MULTIBOOT)
+       .align  8
+       .globl  Multiboot2_Header
+_C_LABEL(Multiboot2_Header):
+       .int    MULTIBOOT2_HEADER_MAGIC
+       .int    MULTIBOOT2_ARCHITECTURE_I386
+       .int    Multiboot2_Header_end - Multiboot2_Header
+       .int    -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT2_ARCHITECTURE_I386 \
+               + (Multiboot2_Header_end - Multiboot2_Header))
+
+       .int    1       /* MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST */
+       .int    12      /* sizeof(multiboot_header_tag_information_request) */
+                       /* + sizeof(uint32_t) * requests */
+       .int    4       /* MULTIBOOT_TAG_TYPE_BASIC_MEMINFO */
+       .align  8
+
+       .int    3       /* MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS */
+       .int    16      /* sizeof(struct multiboot_tag_efi64) */
+       .quad   (multiboot2_entry - KERNBASE)
+       .align  8
+
+       .int    9       /* MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 */
+       .int    16      /* sizeof(struct multiboot_tag_efi64) */
+       .quad   (multiboot2_entry - KERNBASE)
+       .align  8
+
+#if notyet
+       /*
+        * Could be used to get an early console for debug,
+        * but this is broken.
+        */
+       .int    7       /* MULTIBOOT_HEADER_TAG_EFI_BS */
+       .int    8       /* sizeof(struct multiboot_tag) */
+       .align  8
+#endif
+
+       .int    0       /* MULTIBOOT_HEADER_TAG_END */
+       .int    8       /* sizeof(struct multiboot_tag) */
+       .align  8
+       .globl  Multiboot2_Header_end
+_C_LABEL(Multiboot2_Header_end):
+#endif /* MULTIBOOT */
+
 /*
  * Some hackage to deal with 64bit symbols in 32 bit mode.
  * This may not be needed if things are cleaned up a little.
@@ -440,6 +492,700 @@
        /* Warm boot */
        movw    $0x1234,0x472
 
+#if defined(MULTIBOOT)
+       jmp     .Lnative_loader
+
+
+multiboot2_entry:
+       .code64
+       /*
+        * multiboot2 entry point. We are left here without
+        * stack and with no idea of where we were loaded in memory.
+        * The only inputs are
+        * %eax MULTIBOOT2_BOOTLOADER_MAGIC
+        * %ebx pointer to multiboot_info
+        *
+        * Here we will:
+        * - copy the kernel to 0x200000 (KERNTEXTOFF - KERNBASE)
+        *      as almost all the code in locore.S assume it is there. 
+        *      This is derived from 
+        *      src/sys/arch/i386/stand/efiboot/bootx64/startprog64.S
+        * - copy multiboot_info, as done in multiboot_pre_reloc() from
+        *      src/sys/arch/x86/x86/multiboot2.c
+        *      Unfortunately we cannot call that function as there is 
+        *      no simple way to build it as 32 bit code in a 64 bit kernel.
+        * - Copy ELF symbols, also as in multiboot_pre_reloc()
+        */
+
+       cli
+
+       /*
+        * Discover our load address and use it to get start address
+        */
+       mov     $_RELOC(tmpstk),%rsp
+       call    next
+next:  pop     %r8
+       sub     $(next - start), %r8
+
+       /*
+        * Save multiboot_info for later. We cannot use 
+        * temporary stack for that since we are going to
+        * overwrite it.
+        */
+       movl    %ebx, (multiboot2_info_ptr - start)(%r8)
+
+       /*
+        * Get relocated multiboot2_loader entry point in %r9
+        */
+       mov     $(KERNTEXTOFF - KERNBASE), %r9
+       add     $(multiboot2_loader - kernel_text), %r9
+
+       /* Copy kernel */
+       mov     $(KERNTEXTOFF - KERNBASE), %rdi                 /* dest */
+       mov     %r8, %rsi               
+       sub     $(start - kernel_text), %rsi                    /* src */
+       mov     $(__kernel_end - kernel_text), %rcx             /* size *.
+       mov     %rcx, %r12              
+       movq    %rdi, %r11              /* for misaligned check */
+
+#if !defined(NO_OVERLAP)
+       movq    %rdi, %r13
+       subq    %rsi, %r13
+#endif
+
+       shrq    $3, %rcx                /* count for copy by words */
+       jz      8f                      /* j if less than 8 bytes */
+
+       lea     -8(%rdi, %r12), %r14    /* target address of last 8 */
+       mov     -8(%rsi, %r12), %r15    /* get last word */
+#if !defined(NO_OVERLAP)
+       cmpq    %r12, %r13              /* overlapping? */
+       jb      10f
+#endif
+
+/*
+ * Non-overlaping, copy forwards.
+ * Newer Intel cpus (Nehalem) will do 16byte read/write transfers
+ * if %ecx is more than 76.
+ * AMD might do something similar some day.
+ */
+       and     $7, %r11                /* destination misaligned ? */
+       jnz     12f
+       rep
+       movsq
+       mov     %r15, (%r14)            /* write last word */
+       jmp     .Lcopy_done
+
+/*
+ * Destination misaligned
+ * AMD say it is better to align the destination (not the source).
+ * This will also re-align copies if the source and dest are both
+ * misaligned by the same amount)
+ * (I think Nehalem will use its accelerated copy if the source
+ * and destination have the same alignment.)
+ */
+12:
+       lea     -9(%r11, %r12), %rcx    /* post re-alignment count */
+       neg     %r11                    /* now -1 .. -7 */
+       mov     (%rsi), %r12            /* get first word */
+       mov     %rdi, %r13              /* target for first word */
+       lea     8(%rsi, %r11), %rsi
+       lea     8(%rdi, %r11), %rdi
+       shr     $3, %rcx
+       rep
+       movsq
+       mov     %r12, (%r13)            /* write first word */
+       mov     %r15, (%r14)            /* write last word */
+       jmp     .Lcopy_done
+
+#if !defined(NO_OVERLAP)
+/* Must copy backwards.
+ * Reverse copy is probably easy to code faster than 'rep movds'
+ * since that requires (IIRC) an extra clock every 3 iterations (AMD).
+ * However I don't suppose anything cares that much!
+ * The big cost is the std/cld pair - reputedly 50+ cycles on Netburst P4.
+ * The copy is aligned with the buffer start (more likely to
+ * be a multiple of 8 than the end).
+ */
+10:
+       lea     -8(%rsi, %rcx, 8), %rsi
+       lea     -8(%rdi, %rcx, 8), %rdi
+       std
+       rep
+       movsq
+       cld
+       mov     %r15, (%r14)    /* write last bytes */
+       jmp     .Lcopy_done
+#endif
+
+/* Less than 8 bytes to copy, copy by bytes */
+/* Intel Nehalem optimise 'rep movsb' for <= 7 bytes (9-15 clocks).
+ * For longer transfers it is 50+ !
+ */
+8:     mov     %r12, %rcx
+
+#if !defined(NO_OVERLAP)
+       cmpq    %r12, %r13      /* overlapping? */
+       jb      81f
+#endif
+
+       /* nope, copy forwards. */
+       rep
+       movsb
+       jmp     .Lcopy_done
+
+#if !defined(NO_OVERLAP)
+/* Must copy backwards */
+81:
+       lea     -1(%rsi, %rcx), %rsi
+       lea     -1(%rdi, %rcx), %rdi
+       std
+       rep
+       movsb
+       cld
+#endif
+       /* End of copy kernel */
+.Lcopy_done:
+
+       mov     %r8, %rdi       /* %rdi: loaded start address */
+       mov     %r9, %rsi       /* %rsi: kernel entry address */
+
+       /* Prepare jump address */
+       lea     (multiboot2_loader32a - start)(%rdi), %rax
+       movl    %eax, (multiboot2_loader32r - start)(%rdi)
+
+       /* Setup GDT */
+       lea     (gdt - start)(%rdi), %rax
+       mov     %rax, (gdtrr - start)(%rdi)
+       lgdt    (gdtr - start)(%rdi)
+
+       /* Jump to set %cs */
+       ljmp    *(multiboot2_loader32r - start)(%rdi)
+
+       .align  4
+       .code32
+multiboot2_loader32a:
+       movl    $DATA_SEGMENT, %eax
+       movw    %ax, %ds
+       movw    %ax, %es
+       movw    %ax, %fs
+       movw    %ax, %gs
+       movw    %ax, %ss
+
+       /* Already set new stack pointer */
+       movl    %esp, %ebp
+
+       /* 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     multiboot2_loader32b
+
+       .align  4
+multiboot2_loader32b:
+       xor     %eax, %eax
+
+       /* 
+       * Reload multiboot info from target location
+       */      
+       movl    _RELOC(multiboot2_info_ptr), %ebx
+       call    *%esi
+
+       .align  16
+multiboot2_loader32r:
+       .long   0
+       .long   CODE_SEGMENT
+       .align  16
+gdt:
+       .long   0, 0
+       .byte   0xff, 0xff, 0x00, 0x00, 0x00, 0x9f, 0xcf, 0x00
+       .byte   0xff, 0xff, 0x00, 0x00, 0x00, 0x93, 0xcf, 0x00



Home | Main Index | Thread Index | Old Index