feat: setup paging and map kernel to higher half

Kernel is now at 0xC0100000, but still we use 4MiB pages, instruction like 'invlpg' which are invalid for cpu prior to 486, and we don't ensure multiboot structures are mapped. Still lot of work
This commit is contained in:
d0p1 🏳️‍⚧️ 2023-07-12 13:24:17 +02:00
parent fd991daeed
commit a9fec6e18c
9 changed files with 86 additions and 91 deletions

View file

@ -1,5 +1,6 @@
KERNEL = vmstupid KERNEL = vmstupid
SRCS = boot/head.s boot/feat.s kernel.s gdt.s pic.s isr.s idt.s pmm.s paging.s \ SRCS = boot/head.s \
kernel.s gdt.s pic.s isr.s idt.s \
lib/log.s drivers/serial.s lib/log.s drivers/serial.s
INCS = sys/multiboot.inc \ INCS = sys/multiboot.inc \
sys/i386/cpuid.inc \ sys/i386/cpuid.inc \

View file

@ -1,55 +0,0 @@
;; File: feat.s
%include "machdep.inc"
%include "sys/i386/registers.inc"
%include "sys/i386/cpuid.inc"
%include "sys/i386/mmu.inc"
section multiboot.text
extern machdep
;; Function: cpuid_detect
;; check if cpuid is avaible.
;;
;; ripped from <osdev wiki at https://wiki.osdev.org/CPUID#Checking_CPUID_availability>
cpuid_detect:
pushfd
pushfd
xor dword [esp], EFLAGS_ID
popfd
pushfd
pop eax
xor eax, [esp]
popfd
and eax, EFLAGS_ID
ret
;; Function: feat_detect
global feat_detect
feat_detect:
push ebp
mov ebp, esp
call cpuid_detect
test eax, eax
jz .has_cpuid
jmp .end
.has_cpuid:
mov byte [V2P(machdep) + machinfo.has_cpuid], 1
mov eax, CPUID_GETFEATURES
cpuid
;; test if PSE is available
mov eax, edx
and eax, CPUID_FEAT_EDX_PSE
jz .end
mov byte [V2P(machdep) + machinfo.has_pse], 1
;; test if PAE is available (we won't support PAE for now)
mov eax, edx
and eax, CPUID_FEAT_EDX_PAE
jz .end
mov byte [V2P(machdep) + machinfo.has_pae], 1
.end:
leave
ret

View file

@ -1,8 +1,11 @@
;; File: head.s ;; File: head.s
;;
;; About: CPU compatibility
;; /!\ Only work on *486+* for now.
;; - `invlpg` which is not part of 386 ISA.
;;
[BITS 32] [BITS 32]
%include "machdep.inc"
%include "sys/multiboot.inc" %include "sys/multiboot.inc"
%include "sys/i386/registers.inc" %include "sys/i386/registers.inc"
%include "sys/i386/mmu.inc" %include "sys/i386/mmu.inc"
@ -38,24 +41,35 @@ section .multiboot.text
;; ;;
global entry global entry
entry: entry:
extern stack_top ;; disable interrupt
mov esp, V2P(stack_top) cli
;; save boot params ;; save boot params
mov edi, eax mov edi, eax
mov esi, ebx mov esi, ebx
extern feat_detect
call feat_detect
;; setup 4MB paging ;; setup 4MB paging
;; TODO: check if 4MB paging is available ;; TODO: check if 4MB paging is available
mov eax, cr4 mov eax, cr4
or eax, CR4_PSE or eax, CR4_PSE
mov cr4, eax mov cr4, eax
cmp edi, MB_MAGIC
jne .skip_map_multiboot
;; check if multiboot struct is in first 4Mib
;; otherwith add entry in page dir
mov eax, 400000
cmp ebx, eax
jg .map_multiboot
jmp .skip_map_multiboot
.map_multiboot:
;; TODO: for now let's assume data are bellow 4Mib
jmp .end
.skip_map_multiboot:
add esi, KERNBASE
.end:
extern page_directory extern page_directory
mov eax, V2P(page_directory) mov eax, V2P(boot_page_dir)
mov cr3, eax mov cr3, eax
;; enable paging ;; enable paging
@ -63,7 +77,34 @@ entry:
or eax, CR0_PG | CR0_PE | CR0_WP or eax, CR0_PG | CR0_PE | CR0_WP
mov cr0, eax mov cr0, eax
extern page_directory ;; Jump to higher half
mov eax, page_directory - KERNBASE lea eax, entry_high
extern kernel_start jmp eax ; near jump, indirect
mov ebx, kernel_start
section .text
entry_high:
mov dword [boot_page_dir], 0
invlpg [0]
extern stack_top
mov esp, stack_top
xor ebp, ebp
push edi
push esi
extern kmain
call kmain
cli
hang:
hlt
jmp hang
section .data
align 0x1000
boot_page_dir:
dd 0 | PDE_P | PDE_W | PDE_PS
times (P2PDE(KERNBASE) - 1) dd 0
dd 0 | PDE_P | PDE_W | PDE_PS
times 0x400 - (boot_page_dir - $$) dd 0

View file

@ -1,7 +1,7 @@
; File: kernel.s ; File: kernel.s
[BITS 32] [BITS 32]
%include "machdep.inc" %include "base.inc"
section .bss section .bss
align 16 align 16
@ -17,14 +17,16 @@ kmain:
push ebp push ebp
mov ebp, esp mov ebp, esp
extern serial_init
call serial_init
LOG msg_hello_world
leave leave
ret ret
section .data section .rodata
global machdep
machdep: msg_hello_world db "StupidOS v", STUPID_VERSION, " (built with ", __NASM_VER__, " on ", __DATE__, " ", __TIME__, ")", 0
istruc machinfo
at machinfo.has_cpuid, db 0 file db __FILE__, 0
at machinfo.has_pse, db 0
at machinfo.has_pae, db 0
iend

View file

@ -7,7 +7,7 @@ SECTIONS
kernel_start = .; kernel_start = .;
.multiboot : { .multiboot ALIGN(0x1000): {
KEEP(*(.multiboot.data)) KEEP(*(.multiboot.data))
KEEP(*(.multiboot.text)) KEEP(*(.multiboot.text))
} }

View file

@ -1,5 +0,0 @@
struc machinfo
.has_cpuid: resb 1
.has_pse: resb 1
.has_pae: resb 1
endstruc

View file

@ -45,8 +45,12 @@
%define PDE2P(addr) (addr << 22) %define PDE2P(addr) (addr << 22)
%define P2PTE(addr) ((addr >> 12) & 0x3FF) %define P2PTE(addr) ((addr >> 12) & 0x3FF)
;; Defines: PDE ;; Defines: Page Directory Flags
;; PTE_P - Present ;; PDE_P - Present
;; PDE_W - Writable
;; PDE_U - User
;; PDE_PWT - Write-Through
;; PDE_PS - 4MiB page
PDE_P equ 1 << 0 PDE_P equ 1 << 0
PDE_W equ 1 << 1 PDE_W equ 1 << 1
PDE_U equ 1 << 2 PDE_U equ 1 << 2
@ -57,7 +61,7 @@ PDE_D equ 1 << 6
PDE_PS equ 1 << 7 PDE_PS equ 1 << 7
PDE_G equ 1 << 8 PDE_G equ 1 << 8
;; Defines: PTE ;; Defines: Page Table Flags
;; PTE_P - Present ;; PTE_P - Present
;; PTE_W - Writable ;; PTE_W - Writable
;; PTE_U - User ;; PTE_U - User

View file

@ -110,6 +110,13 @@ endstruc
; MB_INFO_BOOTDEV - todo ; MB_INFO_BOOTDEV - todo
MB_INFO_MEM equ 1 << 0 MB_INFO_MEM equ 1 << 0
MB_INFO_BOOTDEV equ 1 << 1 MB_INFO_BOOTDEV equ 1 << 1
MB_INFO_CMDLINE equ 1 << 2
MB_INFO_MODULES equ 1 << 3
MB_INFO_MMAP equ 1 << 6
MB_INFO_DRIVES equ 1 << 7
MB_INFO_BOOTLOADER_NAME equ 1 << 9
MB_INFO_VBE equ 1 << 11
MB_INFO_FRAMEBUFFER equ 1 << 12
; Structure: mb_mmap ; Structure: mb_mmap
struc mb_mmap struc mb_mmap

View file

@ -3,4 +3,4 @@ SRCS = log.s
INCS = base.inc INCS = base.inc
include $(TOPDIR)/share/mk/stupid.lib.mk include $(TOPDIR)/share/mk/stupid.lib.mk
include $(TOPDIR)/share/mk/stupid.inc.mk #include $(TOPDIR)/share/mk/stupid.inc.mk