1 /*
2 * Parts copyright Michael Brown <mbrown@fensystems.co.uk>
3 *
4 * Copyright (c) 2019, Joyent, Inc.
5 */
6
7 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
8
9 /* CR0: protection enabled */
10 #define CR0_PE ( 1 << 0 )
11
12 /* CR0: paging */
13 #define CR0_PG ( 1 << 31 )
14
15 /* CR4: physical address extensions */
16 #define CR4_PSE ( 1 << 4 )
17 #define CR4_PAE ( 1 << 5 )
18 #define CR4_PGE ( 1 << 7 )
19
20 /* Extended feature enable MSR (EFER) */
21 #define MSR_EFER 0xc0000080
22
23 /* EFER: long mode enable */
24 #define EFER_LME ( 1 << 8 )
25
26 #define GDTSEL_CODE 0x8
27 #define GDTSEL_DATA 0x10
28
29 #if defined(PXE_EFI) && defined(__x86_64__)
30
31 .section ".text", "ax", @progbits
32
33 /*
34 * %rdi -> multiboot2 magic
35 * %rsi -> multiboot info pointer
36 * %rdx -> entry address (32 bits)
37 *
38 *
39 * We need to transition from our 64-bit environment into the one
40 * defined by the multiboot2 spec, section 3.3. Namely, drop down to
41 * 32-bit protected mode with a basic GDT, paging disabled, interrupts
42 * off, and
43 *
44 * %eax -> multiboot2 magic
45 * %ebx -> multiboot info pointer (physical)
46 */
47 .align 16
48 .globl multiboot2_entry
49
50 multiboot2_entry:
51 cli
52
53 movq %rsi, %rbx /* mb2 infop */
54 movq %rdx, %rsi /* entry address */
55
56 /* Load the mb2-mandated code and data segments. */
57 leaq entry_gdt_base(%rip), %rcx
58 leaq entry_gdt(%rip), %rax
59 movq %rax, (%rcx)
60
61 leaq entry_gdtr(%rip), %rax
62 lgdt (%rax)
63
64 /* Load our new %cs. */
65 ljmp *newcs_vector
66
67 .code32
68 newcs:
69
70 movw $GDTSEL_DATA, %ax
71 movw %ax, %ds
72 movw %ax, %es
73 movw %ax, %fs
74 movw %ax, %gs
75 movw %ax, %ss
76
77 /* Disable paging */
78 movl %cr0, %eax
79 andl $~CR0_PG, %eax
80 movl %eax, %cr0
81
82 movl %cr4, %eax
83 andb $~(CR4_PAE | CR4_PGE | CR4_PSE), %al
84 movl %eax, %cr4
85
86 /* Disable long mode (clobbers %eax, %edx) */
87 movl $MSR_EFER, %ecx
88 rdmsr
89 andw $~EFER_LME, %ax
90 wrmsr
91
92 /* %ebx still has our infop */
93 movl %edi, %eax
94 jmp *%esi
95
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 #endif /* PXE_EFI && __x86_64__ */
|
1 /*
2 * Parts copyright Michael Brown <mbrown@fensystems.co.uk>
3 *
4 * Copyright 2020 Joyent, Inc.
5 */
6
7 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
8
9 /* CR0: protection enabled */
10 #define CR0_PE ( 1 << 0 )
11
12 /* CR0: paging */
13 #define CR0_PG ( 1 << 31 )
14
15 /* CR4: physical address extensions */
16 #define CR4_PSE ( 1 << 4 )
17 #define CR4_PAE ( 1 << 5 )
18 #define CR4_PGE ( 1 << 7 )
19
20 /* Extended feature enable MSR (EFER) */
21 #define MSR_EFER 0xc0000080
22
23 /* EFER: long mode enable */
24 #define EFER_LME ( 1 << 8 )
25
26 #define GDTSEL_CODE 0x8
27 #define GDTSEL_DATA 0x10
28
29 #if defined(PXE_EFI) && defined(__x86_64__)
30
31 .section ".text", "ax", @progbits
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
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 /*
69 * %rdi -> multiboot2 magic
70 * %rsi -> multiboot info pointer
71 * %rdx -> entry address (32 bits)
72 *
73 *
74 * We need to transition from our 64-bit environment into the one
75 * defined by the multiboot2 spec, section 3.3. Namely, drop down to
76 * 32-bit protected mode with a basic GDT, paging disabled, interrupts
77 * off, and
78 *
79 * %eax -> multiboot2 magic
80 * %ebx -> multiboot info pointer (physical)
81 */
82 .globl multiboot2_entry
83
84 multiboot2_entry:
85 cli
86
87 movq %rsi, %rbx /* mb2 infop */
88 movq %rdx, %rsi /* entry address */
89
90 /* Load the mb2-mandated code and data segments. */
91 leaq entry_gdt_base(%rip), %rcx
92 leaq entry_gdt(%rip), %rax
93 movq %rax, (%rcx)
94
95 leaq entry_gdtr(%rip), %rax
96 lgdt (%rax)
97
98 /* Load our new %cs. */
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
107
108
109 .code32
110 newcs:
111
112 movw $GDTSEL_DATA, %ax
113 movw %ax, %ds
114 movw %ax, %es
115 movw %ax, %fs
116 movw %ax, %gs
117 movw %ax, %ss
118
119 /* Disable paging */
120 movl %cr0, %eax
121 andl $~CR0_PG, %eax
122 movl %eax, %cr0
123
124 movl %cr4, %eax
125 andb $~(CR4_PAE | CR4_PGE | CR4_PSE), %al
126 movl %eax, %cr4
127
128 /* Disable long mode (clobbers %eax, %edx) */
129 movl $MSR_EFER, %ecx
130 rdmsr
131 andw $~EFER_LME, %ax
132 wrmsr
133
134 /* %ebx still has our infop */
135 movl %edi, %eax
136 jmp *%esi
137
138 #endif /* PXE_EFI && __x86_64__ */
|