:: limine / common / protos / limine_32.asm_x86 2.2 KB raw

1
bits 32
2
3
section .text
4
5
global limine_spinup_32
6
limine_spinup_32:
7
    ; If available, set PAT as:
8
    ; PAT0 -> WB  (06)
9
    ; PAT1 -> WT  (04)
10
    ; PAT2 -> UC- (07)
11
    ; PAT3 -> UC  (00)
12
    ; PAT4 -> WP  (05)
13
    ; PAT5 -> WC  (01)
14
    mov eax, 1
15
    xor ecx, ecx
16
    cpuid
17
    test edx, 1 << 16
18
    jz .no_pat
19
    mov eax, 0x00070406
20
    mov edx, 0x00000105
21
    mov ecx, 0x277
22
    wrmsr
23
  .no_pat:
24
25
    ; Enable CR4.LA57
26
    cmp dword [esp+4], 0 ; level5pg
27
    je .no_la57
28
    mov eax, cr4
29
    bts eax, 12
30
    mov cr4, eax
31
  .no_la57:
32
33
    ; Enable CR0.WP
34
    mov eax, cr0
35
    bts eax, 16
36
    mov cr0, eax
37
38
    cld
39
40
    mov eax, [esp+8] ; pagemap_top_lv
41
    mov cr3, eax
42
43
    ; Enable CR4.PAE
44
    mov eax, cr4
45
    bts eax, 5
46
    mov cr4, eax
47
48
    ; Set EFER (LME + NX if available), all other bits cleared
49
    mov ecx, 0xc0000080
50
    xor edx, edx
51
    mov eax, 1 << 8
52
    cmp dword [esp+32], 0 ; nx_available
53
    je .no_nx
54
    or eax, 1 << 11
55
  .no_nx:
56
    wrmsr
57
58
    ; Enable CR0.PG
59
    mov eax, cr0
60
    bts eax, 31
61
    mov cr0, eax
62
63
    ; Go 64
64
    push 0x28
65
    call .p1
66
  .p1:
67
    add dword [esp], .mode64 - .p1
68
    retfd
69
70
bits 64
71
  .mode64:
72
    mov eax, 0x30
73
    mov ds, eax
74
    mov es, eax
75
    mov fs, eax
76
    mov gs, eax
77
    mov ss, eax
78
79
    ; Load 64-bit GDT
80
    mov eax, [rsp+28] ; local_gdt
81
    lgdt [rax]
82
83
    ; Jump to higher half
84
    mov rax, qword [rsp+36]
85
    add rsp, rax
86
    call .p2
87
  .p2:
88
    add qword [rsp], .hh - .p2
89
    add qword [rsp], rax
90
    retq
91
  .hh:
92
93
    cmp dword [rsp+44], 1
94
    jb .no_unmap_lower_half
95
96
    ; Unmap lower half entirely
97
    mov rsi, cr3
98
    lea rdi, [rsi + rax]
99
    mov rcx, 256
100
    xor rax, rax
101
    rep stosq
102
    mov cr3, rsi
103
104
  .no_unmap_lower_half:
105
106
    ; Push fake return address
107
    mov rsi, [rsp+20] ; stack
108
    sub rsi, 8
109
    mov qword [rsi], 0
110
111
    ; Prepare iretq frame
112
    mov rax, qword [rsp+12] ; entry_point
113
    push 0x30
114
    push rsi
115
    push 0x2
116
    push 0x28
117
    push rax
118
119
    ; Zero out all GPRs
120
    xor eax, eax
121
    xor ebx, ebx
122
    xor ecx, ecx
123
    xor edx, edx
124
    xor esi, esi
125
    xor edi, edi
126
    xor ebp, ebp
127
    xor r8d, r8d
128
    xor r9d, r9d
129
    xor r10d, r10d
130
    xor r11d, r11d
131
    xor r12d, r12d
132
    xor r13d, r13d
133
    xor r14d, r14d
134
    xor r15d, r15d
135
136
    iretq
137
138
section .note.GNU-stack noalloc noexec nowrite progbits
tab: 248 wrap: offon