Last active
May 1, 2021 21:22
-
-
Save hibariya/9dc9b836e39a04300a410e92368dec7d to your computer and use it in GitHub Desktop.
Trying to get 4KB paging in long-mode...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ; http://davidad.github.io/blog/2014/02/18/kernel-from-scratch/ | |
| ; http://wiki.osdev.org/Setting_Up_Long_Mode#Setting_up_the_Paging | |
| bits 16 | |
| org 0x7c00 | |
| k16bits: | |
| ; The cli instruction disables maskable external interrupts. | |
| cli | |
| ; Set CR0.PE to 1 to enable 32-bit mode (al == eax) | |
| ; (Control register: https://en.wikipedia.org/wiki/Control_register) | |
| mov eax, cr0 | |
| or al, 1 | |
| mov cr0, eax | |
| jmp 0x08:k32bits | |
| bits 32 | |
| k32bits: | |
| ; Set up paging for 64-bit mode | |
| %define PML4E_ADDR 0x8000 | |
| %define PDPTE_ADDR 0x9000 | |
| %define PDE_ADDR 0xa000 | |
| %define PTE_ADDR 0xb000 | |
| %define PT_ADDR 0xc000 | |
| ; Disable paging in advance | |
| mov eax, cr0 | |
| and eax, 01111111111111111111111111111111b | |
| mov cr0, eax | |
| ; Set up PML4E | |
| mov dword eax, PDPTE_ADDR ; PDPTE_ADDR is the 1st entry of PML4E | |
| or dword eax, 011b ; user-mode / R/W / PML4E present | |
| mov dword [PML4E_ADDR], eax ; PML4E[0] = eax | |
| mov dword [PML4E_ADDR + 4], 0 ; Although we're in 32-bit mode, the table entry is 64 bits. We can just zero out the upper bits in this case. | |
| ; Set up PDPTE | |
| mov dword eax, PDE_ADDR | |
| or dword eax, 011b | |
| mov dword [PDPTE_ADDR], eax | |
| mov dword [PDPTE_ADDR + 4], 0 | |
| ; Set up PDE | |
| mov dword eax, PTE_ADDR | |
| or dword eax, 011b | |
| mov dword [PDE_ADDR], eax | |
| mov dword [PDE_ADDR + 4], 0 | |
| ; Set up PTE | |
| mov dword [PTE_ADDR], 011b | |
| mov dword [PTE_ADDR + 4], 0 | |
| ; Set up pages | |
| mov edi, PT_ADDR | |
| mov ebx, 011b | |
| mov ecx, 512 | |
| create_pages: | |
| mov dword [edi], ebx | |
| add ebx, 0x1000 | |
| add edi, 8 | |
| loop create_pages | |
| ; Set each CR4.PGE and CR4.PAE to 1 to enable 64-bit paging and global pages | |
| mov eax, 10100000b | |
| mov cr4, eax | |
| ; CR3 = PML4E_ADDR | |
| mov eax, PML4E_ADDR | |
| mov cr3, eax | |
| ; Enable 64-bit mode | |
| ; A logical processor uses IA-32e paging if CR0.PG = 1, CR4.PAE = 1, and IA32_EFER.LME = 1. (intel manual: Vol.3A 4.5 IA-32E PAGING) | |
| mov ecx, 0xc0000080 ; It's the argument for rdmsr following / MSR number of EFER is this constant | |
| rdmsr ; Read EFER into eax | |
| or eax, 100000000b ; Set EFER.LME (Long Mode Enable) to 1 | |
| wrmsr | |
| ; Set CR0.PG to 1 to enable paging | |
| mov eax, cr0 | |
| or eax, 0x80000000 | |
| mov cr0, eax | |
| ; Load Global Descriptor Table | |
| lgdt [gdt_hdr] | |
| jmp 0x08:k64bits | |
| bits 64 | |
| k64bits: | |
| mov rax, 0xdeadbeef | |
| hlt | |
| ; Grobal descriptor table entry | |
| ; https://en.wikipedia.org/wiki/Global_Descriptor_Table | |
| ; http://wiki.osdev.org/Global_Descriptor_Table | |
| %macro GDT_ENTRY 4 ; GDT_ENTRY(Base, Limit, Ring, Access) | |
| dw %2 & 0xffff ; Limit 0:15 | |
| dw %1 & 0xffff ; Base 0:15 | |
| db (%1 >> 16) & 0xff ; Base 16:23 | |
| db %4 | ((%3 << 4) & 0xf0) ; Access | (Ring << 4 & 0xf0) | |
| db (%3 & 0xf0) | ((%2 >> 16) & 0x0f) ; Flags (Ring & 0xf0) | Limit 16:19 | |
| db %1 >> 24 ; Base 24:31 | |
| %endmacro | |
| ; (Executable, Direction/Conforming, RW, Accessed) | |
| %define EXECUTE_READ 1010b | |
| %define READ_WRITE 0010b | |
| ; (Granularity, Size, ?, 0), (Present, Privilege(2), 1) | |
| %define RING0 10101001b | |
| gdt_hdr: | |
| dw gdt_end - gdt - 1 | |
| dd gdt | |
| gdt: | |
| GDT_ENTRY 0, 0, 0, 0 | |
| GDT_ENTRY 0, 0xffffff, RING0, EXECUTE_READ | |
| GDT_ENTRY 0, 0xffffff, RING0, READ_WRITE | |
| gdt_end: | |
| times 512 - 2 - ($ - $$) db 0 ; zero-pad the 512-byte sector to the last 2 bytes | |
| dw 0xaa55 ; Magic "boot signature" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| all: bootable.bin | |
| bootable.bin: | |
| nasm boot.s -o $@ | |
| clean: | |
| rm -rf *.bin | |
| run: bootable.bin | |
| qemu-system-x86_64 -monitor stdio bootable.bin |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment