From 2f2c824c987ec16ddc28a2f4784e6b9d3f7d99d8 Mon Sep 17 00:00:00 2001 From: Ruslan Isaev Date: Sun, 23 Mar 2025 13:39:29 +0300 Subject: [PATCH] add basic paging functionality --- Makefile | 8 +++++- include/paging.h | 6 +++++ src/kernel.c | 3 +++ src/page.asm | 24 +++++++++++++++++ src/paging.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 include/paging.h create mode 100644 src/page.asm create mode 100644 src/paging.c diff --git a/Makefile b/Makefile index 8cfd563..a597331 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # Define the object files -OBJS = bin/boot.o bin/kernel.o bin/idt.o bin/isr.o bin/screen.o bin/utils.o bin/string.o bin/stdio.o bin/disk.o bin/pic.o bin/pit.o bin/keyboard.o +OBJS = bin/boot.o bin/kernel.o bin/idt.o bin/isr.o bin/screen.o bin/utils.o bin/string.o bin/stdio.o bin/disk.o bin/pic.o bin/pit.o bin/keyboard.o bin/paging.o bin/page.o # Define the compiler and assembler CC = gcc -D__is_katauos @@ -67,6 +67,12 @@ bin/pit.o: src/pit.c bin/keyboard.o: src/keyboard.c $(CC) $(CFLAGS) -c $< -o $@ +bin/paging.o: src/paging.c + $(CC) $(CFLAGS) -c $< -o $@ + +bin/page.o: src/page.asm + $(AS) $(ASFLAGS) $< -o $@ + clean: rm -rf bin/ rm -f $(OUTPUT) diff --git a/include/paging.h b/include/paging.h new file mode 100644 index 0000000..2c0583e --- /dev/null +++ b/include/paging.h @@ -0,0 +1,6 @@ +#ifndef PAGING_H +#define PAGING_H + +void paging_init(); + +#endif diff --git a/src/kernel.c b/src/kernel.c index 71b57e8..1ace5ef 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -6,6 +6,7 @@ #include "../include/string.h" #include "../include/pic.h" #include "../include/pit.h" +#include "../include/paging.h" #include @@ -25,6 +26,8 @@ void kmain() pit_init(100); apply_pic_masks(); + + paging_init(); __asm__ __volatile__ ("sti"); printf("Kernel init sequence completed\n"); diff --git a/src/page.asm b/src/page.asm new file mode 100644 index 0000000..6ca81b9 --- /dev/null +++ b/src/page.asm @@ -0,0 +1,24 @@ + + +global loadPageDirectory +loadPageDirectory: + push ebp + mov ebp, esp + mov eax, [esp+8] + mov cr3, eax + mov esp, ebp + pop ebp + ret + +global enablePaging +enablePaging: + push ebp + mov ebp, esp + + mov eax, cr0 + or eax, 0x80000000 + mov cr0, eax + + mov esp, ebp + pop ebp + ret diff --git a/src/paging.c b/src/paging.c new file mode 100644 index 0000000..cb2cee4 --- /dev/null +++ b/src/paging.c @@ -0,0 +1,68 @@ +#include "../include/paging.h" +#include + +extern void loadPageDirectory(unsigned int*); +extern void enablePaging(); + +uint32_t page_directory[1024] __attribute__((aligned(4096))); +uint32_t first_page_table[1024] __attribute__((aligned(4096))); + +void paging_init() +{ + //set each entry to not present + int i; + for(i = 0; i < 1024; i++) + { + // This sets the following flags to the pages: + // Supervisor: Only kernel-mode can access them + // Write Enabled: It can be both read from and written to + // Not Present: The page table is not present + page_directory[i] = 0x00000002; + } + + //we will fill all 1024 entries in the table, mapping 4 megabytes + for(i = 0; i < 1024; i++) + { + // As the address is page aligned, it will always leave 12 bits zeroed. + // Those bits are used by the attributes ;) + first_page_table[i] = (i * 0x1000) | 3; // attributes: supervisor level, read/write, present. + } + page_directory[0] = ((unsigned int)first_page_table) | 3; + + loadPageDirectory(page_directory); + enablePaging(); +} + +void *get_physaddr(void *virtualaddr) { + unsigned long pdindex = (unsigned long)virtualaddr >> 22; + unsigned long ptindex = (unsigned long)virtualaddr >> 12 & 0x03FF; + + unsigned long *pd = (unsigned long *)0xFFFFF000; + // Here you need to check whether the PD entry is present. + + unsigned long *pt = ((unsigned long *)0xFFC00000) + (0x400 * pdindex); + // Here you need to check whether the PT entry is present. + + return (void *)((pt[ptindex] & ~0xFFF) + ((unsigned long)virtualaddr & 0xFFF)); +} + +void map_page(void *physaddr, void *virtualaddr, unsigned int flags) { + // Make sure that both addresses are page-aligned. + + unsigned long pdindex = (unsigned long)virtualaddr >> 22; + unsigned long ptindex = (unsigned long)virtualaddr >> 12 & 0x03FF; + + unsigned long *pd = (unsigned long *)0xFFFFF000; + // Here you need to check whether the PD entry is present. + // When it is not present, you need to create a new empty PT and + // adjust the PDE accordingly. + + unsigned long *pt = ((unsigned long *)0xFFC00000) + (0x400 * pdindex); + // Here you need to check whether the PT entry is present. + // When it is, then there is already a mapping present. What do you do now? + + pt[ptindex] = ((unsigned long)physaddr) | (flags & 0xFFF) | 0x01; // Present + + // Now you need to flush the entry in the TLB + // or you might not notice the change. +}