Print this page
Rearrange multiboot2_entry.S so all data is first, code64 is second, code32 is third. (No more dual code64 sections.)
Use `iretq` method of jumping to 32-bit so VirtualBox (and maybe QEMU/KVM too?)
can cope and not get its `ljmp <mem48>` emulation bug(s) tickled.

Split Close
Expand all
Collapse all
          --- old/src/arch/x86/image/multiboot2_entry.S
          +++ new/src/arch/x86/image/multiboot2_entry.S
   1    1  /*
   2    2   * Parts copyright Michael Brown <mbrown@fensystems.co.uk>
   3    3   *
   4      - * Copyright (c) 2019, Joyent, Inc.
        4 + * Copyright 2020 Joyent, Inc.
   5    5   */
   6    6  
   7    7  FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
   8    8  
   9    9  /* CR0: protection enabled */
  10   10  #define CR0_PE ( 1 << 0 )
  11   11  
  12   12  /* CR0: paging */
  13   13  #define CR0_PG ( 1 << 31 )
  14   14  
↓ open down ↓ 8 lines elided ↑ open up ↑
  23   23  /* EFER: long mode enable */
  24   24  #define EFER_LME ( 1 << 8 )
  25   25  
  26   26  #define GDTSEL_CODE 0x8
  27   27  #define GDTSEL_DATA 0x10
  28   28  
  29   29  #if defined(PXE_EFI) && defined(__x86_64__)
  30   30  
  31   31          .section ".text", "ax", @progbits
  32   32  
       33 +        .data
       34 +
       35 +entry_gdt:
       36 +        /* null entry */
       37 +        .word   0x0, 0x0
       38 +        .byte   0x0, 0x0, 0x0, 0x0
       39 +
       40 +        /* 32 bit protected mode code segment */
       41 +        .word   0xffff, 0x0
       42 +        .byte   0x0, 0x9f, 0xcf, 0x0
       43 +
       44 +        /* 32 bit protected mode data segment */
       45 +        .word   0xffff, 0x0
       46 +        .byte   0x0, 0x93, 0xcf, 0x0
       47 +
       48 +entry_gdt_end:
       49 +        .equ    entry_gdt_length, entry_gdt_end - entry_gdt
       50 +
       51 +entry_gdtr:
       52 +        .word entry_gdt_length - 1
       53 +entry_gdt_base:
       54 +        .quad 0
       55 +
  33   56          /*
       57 +         * %rdi -> struct mb2 *
       58 +         * %rsi -> stack pointer to switch to
       59 +         * %rdx -> &multiboot2_enter_kernel
       60 +         */
       61 +        .code64
       62 +        .globl multiboot2_bounce
       63 +
       64 +multiboot2_bounce:
       65 +        movq    %rsi, %rsp
       66 +        jmp     *%rdx
       67 +
       68 +        /*
  34   69           * %rdi -> multiboot2 magic
  35   70           * %rsi -> multiboot info pointer
  36   71           * %rdx -> entry address (32 bits)
  37   72           *
  38   73           *
  39   74           * We need to transition from our 64-bit environment into the one
  40   75           * defined by the multiboot2 spec, section 3.3. Namely, drop down to
  41   76           * 32-bit protected mode with a basic GDT, paging disabled, interrupts
  42   77           * off, and
  43   78           *
  44   79           * %eax -> multiboot2 magic
  45   80           * %ebx -> multiboot info pointer (physical)
  46   81           */
  47      -        .align 16
  48   82          .globl multiboot2_entry
  49   83  
  50   84  multiboot2_entry:
  51   85          cli
  52   86  
  53   87          movq    %rsi, %rbx /* mb2 infop */
  54   88          movq    %rdx, %rsi /* entry address */
  55   89  
  56   90          /* Load the mb2-mandated code and data segments.  */
  57   91          leaq    entry_gdt_base(%rip), %rcx
  58   92          leaq    entry_gdt(%rip), %rax
  59   93          movq    %rax, (%rcx)
  60   94  
  61   95          leaq    entry_gdtr(%rip), %rax
  62   96          lgdt    (%rax)
  63   97  
  64   98          /* Load our new %cs. */
  65      -        ljmp    *newcs_vector
       99 +        movq    %rsp, %rax
      100 +        pushq   $GDTSEL_DATA
      101 +        pushq   %rax
      102 +        pushf
      103 +        pushq   $GDTSEL_CODE
      104 +        lea     newcs(%rip), %rax
      105 +        pushq   %rax
      106 +        iretq
  66  107  
      108 +
  67  109          .code32
  68  110  newcs:
  69  111  
  70  112          movw    $GDTSEL_DATA, %ax
  71  113          movw    %ax, %ds
  72  114          movw    %ax, %es
  73  115          movw    %ax, %fs
  74  116          movw    %ax, %gs
  75  117          movw    %ax, %ss
  76  118  
↓ open down ↓ 9 lines elided ↑ open up ↑
  86  128          /* Disable long mode (clobbers %eax, %edx) */
  87  129          movl    $MSR_EFER, %ecx
  88  130          rdmsr
  89  131          andw    $~EFER_LME, %ax
  90  132          wrmsr
  91  133  
  92  134          /* %ebx still has our infop */
  93  135          movl    %edi, %eax
  94  136          jmp     *%esi
  95  137  
  96      -        /*
  97      -         * %rdi -> struct mb2 *
  98      -         * %rsi -> stack pointer to switch to
  99      -         * %rdx -> &multiboot2_enter_kernel
 100      -         */
 101      -        .align 16
 102      -        .code64
 103      -        .globl multiboot2_bounce
 104      -
 105      -multiboot2_bounce:
 106      -        movq    %rsi, %rsp
 107      -        jmp     *%rdx
 108      -
 109      -        .data
 110      -
 111      -newcs_vector:
 112      -        .long   newcs, GDTSEL_CODE
 113      -
 114      -        .align 16
 115      -entry_gdt:
 116      -        /* null entry */
 117      -        .word   0x0, 0x0
 118      -        .byte   0x0, 0x0, 0x0, 0x0
 119      -
 120      -        /* 32 bit protected mode code segment */
 121      -        .word   0xffff, 0x0
 122      -        .byte   0x0, 0x9f, 0xcf, 0x0
 123      -
 124      -        /* 32 bit protected mode data segment */
 125      -        .word   0xffff, 0x0
 126      -        .byte   0x0, 0x93, 0xcf, 0x0
 127      -
 128      -entry_gdt_end:
 129      -        .equ    entry_gdt_length, entry_gdt_end - entry_gdt
 130      -
 131      -        .align 16
 132      -entry_gdtr:
 133      -        .word entry_gdt_length - 1
 134      -entry_gdt_base:
 135      -        .quad 0
 136      -
 137  138  #endif /* PXE_EFI && __x86_64__ */
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX