add basic paging functionality
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
# Define the object files
|
# 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
|
# Define the compiler and assembler
|
||||||
CC = gcc -D__is_katauos
|
CC = gcc -D__is_katauos
|
||||||
@@ -67,6 +67,12 @@ bin/pit.o: src/pit.c
|
|||||||
bin/keyboard.o: src/keyboard.c
|
bin/keyboard.o: src/keyboard.c
|
||||||
$(CC) $(CFLAGS) -c $< -o $@
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
bin/paging.o: src/paging.c
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
bin/page.o: src/page.asm
|
||||||
|
$(AS) $(ASFLAGS) $< -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf bin/
|
rm -rf bin/
|
||||||
rm -f $(OUTPUT)
|
rm -f $(OUTPUT)
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef PAGING_H
|
||||||
|
#define PAGING_H
|
||||||
|
|
||||||
|
void paging_init();
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "../include/string.h"
|
#include "../include/string.h"
|
||||||
#include "../include/pic.h"
|
#include "../include/pic.h"
|
||||||
#include "../include/pit.h"
|
#include "../include/pit.h"
|
||||||
|
#include "../include/paging.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@@ -25,6 +26,8 @@ void kmain()
|
|||||||
pit_init(100);
|
pit_init(100);
|
||||||
|
|
||||||
apply_pic_masks();
|
apply_pic_masks();
|
||||||
|
|
||||||
|
paging_init();
|
||||||
__asm__ __volatile__ ("sti");
|
__asm__ __volatile__ ("sti");
|
||||||
printf("Kernel init sequence completed\n");
|
printf("Kernel init sequence completed\n");
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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.
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user