Added basic long mode setup

This commit is contained in:
Simon 2024-01-27 02:18:08 -05:00
parent 05cf015382
commit df2c0ee981
4 changed files with 138 additions and 64 deletions

View file

@ -5,10 +5,10 @@ BUILD_DIR=build
K_BIN_NAME=kernel.bin K_BIN_NAME=kernel.bin
ISO_NAME=os_image.iso ISO_NAME=os_image.iso
CC=cc CC=gcc
LD=ld LD=ld
CFLAGS=-ffreestanding -g -Wall -Wextra -pedantic -lgcc -isystem $(INCLUDE_DIR) CFLAGS= -std=c2x -ffreestanding -g -Wall -Wextra -pedantic -lgcc -isystem $(INCLUDE_DIR)
C_SRC=$(shell find $(SRC_DIR) -type f -name "*.c") C_SRC=$(shell find $(SRC_DIR) -type f -name "*.c")
@ -31,6 +31,10 @@ $(A_OBJ): $(BUILD_DIR)/%.S.o : %.S
@mkdir -p $(@D) @mkdir -p $(@D)
nasm $< -f elf64 -o $@ nasm $< -f elf64 -o $@
$(BUILD_DIR)/$(SRC_DIR)/arch/amd64/shim.o: $(SRC_DIR)/arch/amd64/shim.c
@mkdir -p $(@D)
$(CC) -c $(CFLAGS) -o $@ $< -m32
$(C_OBJ): $(BUILD_DIR)/%.o : %.c $(C_OBJ): $(BUILD_DIR)/%.o : %.c
@mkdir -p $(@D) @mkdir -p $(@D)
$(CC) -c $(CFLAGS) -o $@ $< $(CC) -c $(CFLAGS) -o $@ $<

View file

@ -3,18 +3,6 @@ extern kmain
extern amd64_shim extern amd64_shim
bits 32 bits 32
; base, limit, access, flags
%macro gdt_entry 4
db %2 & 0xff
db (%2 >> 8) & 0xff
db %1 & 0xff
db (%1 >> 8) & 0xff
db (%1 >> 16) & 0xff
db %3
db ((%2 >> 16) & 0x0f) | (%4 << 4)
db (%1 >> 24) & 0xff
%endmacro
section .multiboot section .multiboot
align 8 align 8
mb_start: mb_start:
@ -38,33 +26,97 @@ stack_end:
section .rodata section .rodata
align 16 align 16
gdt_start: ; Access bits
gdt_entry 0, 0, 0, 0 PRESENT equ 1 << 7
gdt_entry 0, 0xFFFFF, 0x9A, 0xC NOT_SYS equ 1 << 4
gdt_entry 0, 0xFFFFF, 0x92, 0xC EXEC equ 1 << 3
gdt_end: DC equ 1 << 2
gdt_descriptor: RW equ 1 << 1
dw gdt_end - gdt_start - 1 ACCESSED equ 1 << 0
dd gdt_start
; Flags bits
GRAN_4K equ 1 << 7
SZ_32 equ 1 << 6
LONG_MODE equ 1 << 5
GDT:
.Null: equ $ - GDT
dq 0
.Code: equ $ - GDT
dd 0xFFFF ; Limit & Base (low, bits 0-15)
db 0 ; Base (mid, bits 16-23)
db PRESENT | NOT_SYS | EXEC | RW ; Access
db GRAN_4K | LONG_MODE | 0xF ; Flags & Limit (high, bits 16-19)
db 0 ; Base (high, bits 24-31)
.Data: equ $ - GDT
dd 0xFFFF ; Limit & Base (low, bits 0-15)
db 0 ; Base (mid, bits 16-23)
db PRESENT | NOT_SYS | RW ; Access
db GRAN_4K | SZ_32 | 0xF ; Flags & Limit (high, bits 16-19)
db 0 ; Base (high, bits 24-31)
.TSS: equ $ - GDT
dd 0x00000068
dd 0x00CF8900
.Pointer:
dw $ - GDT - 1
dq GDT
section .text section .text
align 8 align 8
start: start:
cli cli
lgdt [gdt_descriptor]
jmp 0x08:after_lgdt
after_lgdt:
mov ax, 0x10
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov esp, stack_end mov esp, stack_end
mov ebp, stack_end mov ebp, stack_end
push ebx push ebx
mov edi, 0x1000
mov cr3, edi
xor eax, eax
mov ecx, 4096
rep stosd
mov edi, cr3
mov DWORD [edi], 0x2003 ; Set the uint32_t at the destination index to 0x2003.
add edi, 0x1000 ; Add 0x1000 to the destination index.
mov DWORD [edi], 0x3003 ; Set the uint32_t at the destination index to 0x3003.
add edi, 0x1000 ; Add 0x1000 to the destination index.
mov DWORD [edi], 0x4003 ; Set the uint32_t at the destination index to 0x4003.
add edi, 0x1000 ; Add 0x1000 to the destination index.
mov ebx, 0x00000003 ; Set the B-register to 0x00000003.
mov ecx, 512 ; Set the C-register to 512.
.SetEntry:
mov DWORD [edi], ebx ; Set the uint32_t at the destination index to the B-register.
add ebx, 0x1000 ; Add 0x1000 to the B-register.
add edi, 8 ; Add eight to the destination index.
loop .SetEntry ; Set the next entry.
;push ebx ; Call our function to set up basic paging
;call amd64_shim
mov eax, cr4 ; Enable the PAE bit
or eax, 1 << 5
mov cr4, eax
mov ecx, 0xC0000080 ; Enable long mode
rdmsr
or eax, 1 << 8
wrmsr
mov eax, cr0 ; Enable paging
or eax, 1 << 31
mov cr0, eax
lgdt [GDT.Pointer]
jmp GDT.Code:code64
bits 64
code64:
call amd64_shim call amd64_shim
push rax
call kmain call kmain
cli cli
halt: halt:

View file

@ -1,4 +1,5 @@
#include <stdint.h> #include <stdint.h>
#include <cpuid.h>
#define PG_PRESENT 0x0000'0000'0000'0001 #define PG_PRESENT 0x0000'0000'0000'0001
#define PG_READ_WRITE 0x0000'0000'0000'0002 #define PG_READ_WRITE 0x0000'0000'0000'0002
@ -8,14 +9,19 @@
#define PG_ACCESSED 0x0000'0000'0000'0020 #define PG_ACCESSED 0x0000'0000'0000'0020
#define PG_EXECUTE_DISABLE 0x8000'0000'0000'0000 #define PG_EXECUTE_DISABLE 0x8000'0000'0000'0000
#define F_PRESENT 0b1
#define F_WRITEABLE 0b10
#define F_UNPRIVILEGED 0b100
#define F_WRITETHROUGH 0b1000
#define F_CACHEDISABLE 0b10000
#define F_ACCESSED 0b100000
#define F_DIRTY 0b1000000
#define F_MEGABYTE 0b10000000
#define F_GLOBAL 0b100000000
// PAGE MAP LEVEL 4 ENTRY // PAGE MAP LEVEL 4 ENTRY
struct pml4 { struct pml4e {
uint64_t present : 1; uint64_t flags : 6;
uint64_t rw : 1;
uint64_t user_supervisor : 1;
uint64_t write_through : 1;
uint64_t cache_disable : 1;
uint64_t accessed : 1;
uint64_t _reserved : 6; uint64_t _reserved : 6;
uint64_t address : 40; uint64_t address : 40;
uint64_t _reserved_2 : 11; uint64_t _reserved_2 : 11;
@ -24,12 +30,7 @@ struct pml4 {
// PAGE DIRECTORY POINTER TABLE ENTRY // PAGE DIRECTORY POINTER TABLE ENTRY
struct pdpte { struct pdpte {
uint64_t present : 1; uint64_t flags : 6;
uint64_t rw : 1;
uint64_t user_supervisor : 1;
uint64_t write_through : 1;
uint64_t cache_disable : 1;
uint64_t accessed : 1;
uint64_t _reserved : 1; uint64_t _reserved : 1;
uint64_t page_size : 1; uint64_t page_size : 1;
uint64_t _reserved_2 : 2; uint64_t _reserved_2 : 2;
@ -40,12 +41,7 @@ struct pdpte {
// PAGE DIRECTORY ENTRY // PAGE DIRECTORY ENTRY
struct pde { struct pde {
uint64_t present : 1; uint64_t flags : 6;
uint64_t rw : 1;
uint64_t user_supervisor : 1;
uint64_t write_through : 1;
uint64_t cache_disable : 1;
uint64_t accessed : 1;
uint64_t _reserved : 1; uint64_t _reserved : 1;
uint64_t page_size : 1; uint64_t page_size : 1;
uint64_t _reserved_2 : 2; uint64_t _reserved_2 : 2;
@ -56,15 +52,7 @@ struct pde {
// PAGE TABLE ENTRY // PAGE TABLE ENTRY
struct pte { struct pte {
uint64_t present : 1; uint64_t flags : 9;
uint64_t rw : 1;
uint64_t user_supervisor : 1;
uint64_t write_through : 1;
uint64_t cache_disable : 1;
uint64_t accessed : 1;
uint64_t dirty : 1;
uint64_t mem_type : 1;
uint64_t global : 1;
uint64_t _reserved : 3; uint64_t _reserved : 3;
uint64_t address : 40; uint64_t address : 40;
uint64_t _reserved_2 : 7; uint64_t _reserved_2 : 7;
@ -72,7 +60,36 @@ struct pte {
uint64_t execute_disable : 1; uint64_t execute_disable : 1;
}; };
// entry point for amd64 struct pml4e pml4[512];
void amd64_shim(void *boot_info) { struct pdpte pdpt[512];
struct pde pd[512];
struct pte pt[512];
static int get_maxphysaddr() {
uint32_t eax, ebx, ecx, edx;
__cpuid(0x80000008, eax, ebx, ecx, edx);
return eax & 0xFF;
}
// entry point for amd64
void* amd64_shim(void *boot_info) {
for (int i = 0; i < 512; i++) {
pml4[i].flags = 0;
}
for (int i = 0; i < 512; i++) {
pdpt[i].flags = 0;
}
for (int i = 0; i < 512; i++) {
pd[i].flags = 0;
}
pml4[0].flags = F_PRESENT | F_WRITEABLE;
pml4[0].address = (uint64_t)&pdpt;
pdpt[0].flags = F_PRESENT | F_WRITEABLE;
pdpt[0].address = (uint64_t)&pd;
pd[0].flags = F_PRESENT | F_WRITEABLE;
pd[0].address = (uint64_t)&pt;
for (int i = 0; i < 512; i++) {
pt[i].flags = F_PRESENT | F_WRITEABLE;
pt[i].address = i * 4096;
}
} }

View file

@ -1,5 +1,6 @@
void kmain() { void kmain() {
*(char*)0xB8000 = 'c';
while(1) { while(1) {
asm("cli; hlt"); __asm("cli; hlt");
} }
} }