add basic paging functionality

This commit is contained in:
2025-03-23 13:39:29 +03:00
parent 1ce599cee1
commit 2f2c824c98
5 changed files with 108 additions and 1 deletions
+3
View File
@@ -6,6 +6,7 @@
#include "../include/string.h"
#include "../include/pic.h"
#include "../include/pit.h"
#include "../include/paging.h"
#include <stdint.h>
@@ -25,6 +26,8 @@ void kmain()
pit_init(100);
apply_pic_masks();
paging_init();
__asm__ __volatile__ ("sti");
printf("Kernel init sequence completed\n");
+24
View File
@@ -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
+68
View File
@@ -0,0 +1,68 @@
#include "../include/paging.h"
#include <stdint.h>
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.
}