128 lines
3.5 KiB
C
128 lines
3.5 KiB
C
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <stdbool.h>
|
|
#include <mm/vmm.h>
|
|
|
|
__attribute__((noreturn)) void stivale_spinup_32(
|
|
int bits, bool level5pg, uint32_t pagemap_top_lv,
|
|
uint32_t entry_point_lo, uint32_t entry_point_hi,
|
|
void *stivale_struct, uint32_t stack_lo, uint32_t stack_hi) {
|
|
uint64_t entry_point =
|
|
(uint64_t)entry_point_lo | ((uint64_t)entry_point_hi << 32);
|
|
uint64_t stack =
|
|
(uint64_t)stack_lo | ((uint64_t)stack_hi << 32);
|
|
|
|
if (bits == 64) {
|
|
if (level5pg) {
|
|
// Enable CR4.LA57
|
|
asm volatile (
|
|
"mov eax, cr4\n\t"
|
|
"bts eax, 12\n\t"
|
|
"mov cr4, eax\n\t" ::: "eax", "memory"
|
|
);
|
|
}
|
|
|
|
asm volatile (
|
|
"cli\n\t"
|
|
"cld\n\t"
|
|
"mov cr3, eax\n\t"
|
|
"mov eax, cr4\n\t"
|
|
"or eax, 1 << 5\n\t"
|
|
"mov cr4, eax\n\t"
|
|
"mov ecx, 0xc0000080\n\t"
|
|
"rdmsr\n\t"
|
|
"or eax, 1 << 8\n\t"
|
|
"wrmsr\n\t"
|
|
"mov eax, cr0\n\t"
|
|
"or eax, 1 << 31\n\t"
|
|
"mov cr0, eax\n\t"
|
|
"call 1f\n\t"
|
|
"1: pop eax\n\t"
|
|
"add eax, 8\n\t"
|
|
"push 0x28\n\t"
|
|
"push eax\n\t"
|
|
"retf\n\t"
|
|
".code64\n\t"
|
|
"mov ax, 0x30\n\t"
|
|
"mov ds, ax\n\t"
|
|
"mov es, ax\n\t"
|
|
"mov fs, ax\n\t"
|
|
"mov gs, ax\n\t"
|
|
"mov ss, ax\n\t"
|
|
|
|
// Since we don't really know what is now present in the upper
|
|
// 32 bits of the 64 bit registers, clear up the upper bits
|
|
// of the registers we use to store stack pointer and instruction
|
|
// pointer
|
|
"mov esi, esi\n\t"
|
|
"mov ebx, ebx\n\t"
|
|
"mov edi, edi\n\t"
|
|
|
|
// Let's pretend we push a return address
|
|
"mov rsi, qword ptr [rsi]\n\t"
|
|
"test rsi, rsi\n\t"
|
|
"jz 1f\n\t"
|
|
|
|
"sub rsi, 8\n\t"
|
|
"mov qword ptr [rsi], 0\n\t"
|
|
|
|
"1:\n\t"
|
|
"push 0x30\n\t"
|
|
"push rsi\n\t"
|
|
"pushfq\n\t"
|
|
"push 0x28\n\t"
|
|
"push [rbx]\n\t"
|
|
|
|
"xor rax, rax\n\t"
|
|
"xor rbx, rbx\n\t"
|
|
"xor rcx, rcx\n\t"
|
|
"xor rdx, rdx\n\t"
|
|
"xor rsi, rsi\n\t"
|
|
"xor rbp, rbp\n\t"
|
|
"xor r8, r8\n\t"
|
|
"xor r9, r9\n\t"
|
|
"xor r10, r10\n\t"
|
|
"xor r11, r11\n\t"
|
|
"xor r12, r12\n\t"
|
|
"xor r13, r13\n\t"
|
|
"xor r14, r14\n\t"
|
|
"xor r15, r15\n\t"
|
|
|
|
"iretq\n\t"
|
|
".code32\n\t"
|
|
:
|
|
: "a" (pagemap_top_lv), "b" (&entry_point),
|
|
"D" (stivale_struct), "S" (&stack)
|
|
: "memory"
|
|
);
|
|
} else if (bits == 32) {
|
|
asm volatile (
|
|
"cli\n\t"
|
|
"cld\n\t"
|
|
|
|
"mov esp, dword ptr [esi]\n\t"
|
|
"push edi\n\t"
|
|
"push 0\n\t"
|
|
|
|
"pushfd\n\t"
|
|
"push 0x18\n\t"
|
|
"push [ebx]\n\t"
|
|
|
|
"xor eax, eax\n\t"
|
|
"xor ebx, ebx\n\t"
|
|
"xor ecx, ecx\n\t"
|
|
"xor edx, edx\n\t"
|
|
"xor esi, esi\n\t"
|
|
"xor edi, edi\n\t"
|
|
"xor ebp, ebp\n\t"
|
|
|
|
"iret\n\t"
|
|
:
|
|
: "b"(&entry_point), "D"(stivale_struct), "S"(&stack)
|
|
: "memory"
|
|
);
|
|
}
|
|
|
|
__builtin_unreachable();
|
|
}
|