| 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 |