Print this page
    
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  
  15   15  /* CR4: physical address extensions */
  16   16  #define CR4_PSE ( 1 << 4 )
  17   17  #define CR4_PAE ( 1 << 5 )
  18   18  #define CR4_PGE ( 1 << 7 )
  19   19  
  20   20  /* Extended feature enable MSR (EFER) */
  21   21  #define MSR_EFER 0xc0000080
  22   22  
  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   33          /*
  34   34           * %rdi -> multiboot2 magic
  35   35           * %rsi -> multiboot info pointer
  36   36           * %rdx -> entry address (32 bits)
  37   37           *
  38   38           *
  39   39           * We need to transition from our 64-bit environment into the one
  40   40           * defined by the multiboot2 spec, section 3.3. Namely, drop down to
  41   41           * 32-bit protected mode with a basic GDT, paging disabled, interrupts
  42   42           * off, and
  43   43           *
  44   44           * %eax -> multiboot2 magic
  45   45           * %ebx -> multiboot info pointer (physical)
  46   46           */
  47   47          .align 16
  48   48          .globl multiboot2_entry
  49   49  
  50   50  multiboot2_entry:
  51   51          cli
  52   52  
  53   53          movq    %rsi, %rbx /* mb2 infop */
  54   54          movq    %rdx, %rsi /* entry address */
  
    | 
      ↓ open down ↓ | 
    40 lines elided | 
    
      ↑ open up ↑ | 
  
  55   55  
  56   56          /* Load the mb2-mandated code and data segments.  */
  57   57          leaq    entry_gdt_base(%rip), %rcx
  58   58          leaq    entry_gdt(%rip), %rax
  59   59          movq    %rax, (%rcx)
  60   60  
  61   61          leaq    entry_gdtr(%rip), %rax
  62   62          lgdt    (%rax)
  63   63  
  64   64          /* Load our new %cs. */
  65      -        ljmp    *newcs_vector
       65 +        movq    %rsp, %rax
       66 +        pushq   $GDTSEL_DATA
       67 +        pushq   %rax
       68 +        pushf
       69 +        pushq   $GDTSEL_CODE
       70 +        lea     newcs(%rip), %rax
       71 +        pushq   %rax
       72 +        iretq
  66   73  
  67   74          .code32
  68   75  newcs:
  69   76  
  70   77          movw    $GDTSEL_DATA, %ax
  71   78          movw    %ax, %ds
  72   79          movw    %ax, %es
  73   80          movw    %ax, %fs
  74   81          movw    %ax, %gs
  75   82          movw    %ax, %ss
  76   83  
  77   84          /* Disable paging */
  78   85          movl    %cr0, %eax
  79   86          andl    $~CR0_PG, %eax
  80   87          movl    %eax, %cr0
  81   88  
  82   89          movl    %cr4, %eax
  83   90          andb    $~(CR4_PAE | CR4_PGE | CR4_PSE), %al
  84   91          movl    %eax, %cr4
  85   92  
  86   93          /* Disable long mode (clobbers %eax, %edx) */
  87   94          movl    $MSR_EFER, %ecx
  88   95          rdmsr
  89   96          andw    $~EFER_LME, %ax
  90   97          wrmsr
  91   98  
  92   99          /* %ebx still has our infop */
  93  100          movl    %edi, %eax
  94  101          jmp     *%esi
  95  102  
  96  103          /*
  97  104           * %rdi -> struct mb2 *
  98  105           * %rsi -> stack pointer to switch to
  99  106           * %rdx -> &multiboot2_enter_kernel
 100  107           */
  
    | 
      ↓ open down ↓ | 
    25 lines elided | 
    
      ↑ open up ↑ | 
  
 101  108          .align 16
 102  109          .code64
 103  110          .globl multiboot2_bounce
 104  111  
 105  112  multiboot2_bounce:
 106  113          movq    %rsi, %rsp
 107  114          jmp     *%rdx
 108  115  
 109  116          .data
 110  117  
 111      -newcs_vector:
 112      -        .long   newcs, GDTSEL_CODE
 113      -
 114  118          .align 16
 115  119  entry_gdt:
 116  120          /* null entry */
 117  121          .word   0x0, 0x0
 118  122          .byte   0x0, 0x0, 0x0, 0x0
 119  123  
 120  124          /* 32 bit protected mode code segment */
 121  125          .word   0xffff, 0x0
 122  126          .byte   0x0, 0x9f, 0xcf, 0x0
 123  127  
 124  128          /* 32 bit protected mode data segment */
 125  129          .word   0xffff, 0x0
 126  130          .byte   0x0, 0x93, 0xcf, 0x0
 127  131  
 128  132  entry_gdt_end:
 129  133          .equ    entry_gdt_length, entry_gdt_end - entry_gdt
 130  134  
 131  135          .align 16
 132  136  entry_gdtr:
 133  137          .word entry_gdt_length - 1
 134  138  entry_gdt_base:
 135  139          .quad 0
 136  140  
 137  141  #endif /* PXE_EFI && __x86_64__ */
  
    | 
      ↓ open down ↓ | 
    14 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX