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