summaryrefslogtreecommitdiff
path: root/arch/i386/kernel/paging.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/paging.c')
-rw-r--r--arch/i386/kernel/paging.c141
1 files changed, 87 insertions, 54 deletions
diff --git a/arch/i386/kernel/paging.c b/arch/i386/kernel/paging.c
index d8f72a3..54539ac 100644
--- a/arch/i386/kernel/paging.c
+++ b/arch/i386/kernel/paging.c
@@ -2,87 +2,120 @@
#include <kernel/io.h>
#include <kernel/syscall.h>
#include <kernel/string.h>
-#include <kernel/alloc.h>
-#include <stddef.h>
-extern int halt_catch_fire();
-extern uint32_t _kernel_start;
-extern uint32_t _kernel_end;
-static uint32_t *kstart = &_kernel_start;
-static uint32_t *kend = (uint32_t)(&_kernel_end) - 0xC0000000;
+extern uintptr_t _kernel_start;
+extern uintptr_t _kernel_end;
+static uintptr_t kstart = (uintptr_t)&_kernel_start;
+static uintptr_t kend = (uintptr_t)&_kernel_end - 0xC0000000;
-static uint32_t page_directory[1024] __attribute__((aligned(PAGE_SIZE)));
-static uint32_t first_page_table[1024] __attribute__((aligned(PAGE_SIZE)));
+static uintptr_t page_directory[1024] __attribute__((aligned(PAGE_SIZE)));
+static uintptr_t first_page_table[1024] __attribute__((aligned(PAGE_SIZE)));
static int paging_enabled = 0;
+static uint32_t dma_zone_bitmap[DMA_BITMAP_SZ];
+static uint32_t buddy_bitmap[BDY_BITMAP_SZ];
+static struct pfa_buddy first_buddy;
+
+static void _pfa_init(void) {
+ first_buddy.start = 0x01000000;
+ first_buddy.bitmap = buddy_bitmap;
+}
+
+static void _pfa_alloc(uintptr_t paddr) {
+ uintptr_t index = (paddr & 0xFFFFF000) / 4096 / 32;
+ uintptr_t bit = (paddr & 0xFFFFF000) / 4096 % 32;
+ uint32_t *bitmap;
+ if (paddr < 0x01000000)
+ bitmap = dma_zone_bitmap;
+ else
+ bitmap = first_buddy.bitmap;
+
+ bitmap[index] |= (1 << bit);
+}
+
+static void _pfa_free(uintptr_t paddr) {
+ uintptr_t index = (paddr & 0xFFFFF000) / 4096 / 32;
+ uintptr_t bit = (paddr & 0xFFFFF000) / 4096 % 32;
+ uint32_t *bitmap;
+ if (paddr < 0x01000000)
+ bitmap = dma_zone_bitmap;
+ else
+ bitmap = first_buddy.bitmap;
+
+ bitmap[index] &= ~(1 << bit);
+}
+
void paging_init(void) {
+ _pfa_init();
for (int i = 0; i < 1024; i++)
page_directory[i] = 0x00000002;
- page_directory[1023] = ((uint32_t)&page_directory - 0xC0000000) | 3;
- page_directory[0] = ((uint32_t)&first_page_table - 0xC0000000) | 3;
- page_directory[768] = ((uint32_t)&first_page_table - 0xC0000000) | 3;
- for (uint32_t i = kstart; i < kend; i += 4096) {
- map_page(i, get_vaddr(i), 0x003);
- mark_bitmap(i, 1);
+ page_directory[1023] = ((uintptr_t)&page_directory - 0xC0000000) | 3;
+ page_directory[0] = ((uintptr_t)&first_page_table - 0xC0000000) | 3;
+ page_directory[768] = ((uintptr_t)&first_page_table - 0xC0000000) | 3;
+ for (uintptr_t i = kstart; i < kend; i += 4096) {
+ _pfa_alloc(get_vaddr(i));
+ map_page(page_directory, i, get_vaddr(i), 0x003);
}
- map_page(0xB8000, 0xC03FF000, 0x003);
- mark_bitmap(0xB8000, 1);
-
- load_page_dir(((uint32_t)&page_directory) - 0xC0000000);
+ load_page_dir(((uintptr_t)&page_directory) - 0xC0000000);
enable_paging();
paging_enabled = 1;
return;
}
void page_fault_handler(struct isr_frame *frame) {
- kprintf("Page fault detected\n");
- uint32_t errno = frame->errno;
+ uintptr_t errno = frame->errno;
- uint32_t fault_addr;
+ uintptr_t fault_addr;
__asm__ volatile("movl %%cr2, %0" : "=r"(fault_addr));
- kprintf("Fault occured at address %x\n", fault_addr);
- uint32_t present = errno & ERR_PRESENT;
- uint32_t rw = errno & ERR_RW;
- uint32_t user = errno & ERR_USER;
- uint32_t reserved = errno & ERR_RESERVED;
- uint32_t ifetch = errno & ERR_INST;
- kprintf("Possible causes:\n");
- if (!present) kprintf("\tPage not present\n");
- if (rw || user) kprintf("\tPage is read only\n");
- if (reserved) kprintf("\tOverwrote reserved bits\n");
- if (ifetch) kprintf("\tInstruction fetch\n");
- halt_catch_fire(frame);
-}
-
-uint32_t get_paddr(uint32_t vaddr) {
- uint32_t pdindex = vaddr >> 22;
- uint32_t ptindex = vaddr >> 12 & 0x03FF;
-
- uint32_t *page_table = (page_directory[pdindex] + 0xC0000000 & 0xFFFFF000);
- return (page_table[ptindex] & 0xFFFFF000) | (vaddr & 0x00000FFF);
+ int present = errno & ERR_PRESENT;
+ int rw = errno & ERR_RW;
+ int user = errno & ERR_USER;
+ int reserved = errno & ERR_RESERVED;
+ int ifetch = errno & ERR_INST;
+
+ if (!present)
+ _pfa_alloc(fault_addr);
+ map_page(NULL, fault_addr, fault_addr, 0x003);
+ if (user)
+ panic("Usermode attempted to read supervisor page");
+ if (rw)
+ panic("Task wrote to read only page");
+ if (reserved)
+ panic("Task overwrote reserved page bits");
+ if (ifetch)
+ panic("Task paging instruction fetch failure");
}
-uint32_t get_vaddr(uint32_t paddr) {
+uintptr_t get_vaddr(uintptr_t paddr) {
return paddr + 0xC0000000;
}
-void map_page(uint32_t paddr, uint32_t vaddr, uint32_t flags) {
- uint32_t pdindex = vaddr >> 22;
- uint32_t ptindex = vaddr >> 12 & 0x03FF;
+void map_page(uint32_t *pd, uintptr_t paddr, uintptr_t vaddr, uint32_t flags) {
+ if (pd == NULL)
+ pd = page_directory;
+
+ uintptr_t paddr_aligned = paddr & 0xFFFFF000;
+ uintptr_t vaddr_aligned = vaddr & 0xFFFFF000;
- uint32_t *page_table = (page_directory[pdindex] + 0xC0000000 & 0xFFFFF000);
- uint32_t *pte = (uint32_t*)(&page_table[ptindex]);
- *pte |= paddr | (flags & 0xFFF) | 0x01;
+ uintptr_t pdindex = vaddr_aligned >> 22;
+ uintptr_t ptindex = vaddr_aligned >> 12 & 0x03FF;
+
+ uintptr_t *pt = (pd[pdindex] + 0xC0000000 & 0xFFFFF000);
+ uintptr_t *pte = (uintptr_t*)(&pt[ptindex]);
+ *pte |= paddr_aligned | (flags & 0xFFF) | 0x01;
}
-void unmap_page(uint32_t vaddr) {
- uint32_t pdindex = vaddr >> 22;
- uint32_t ptindex = vaddr >> 12 & 0x03FF;
+void unmap_page(uint32_t *pd, uintptr_t vaddr) {
+ if (pd == NULL)
+ pd = page_directory;
+
+ uintptr_t pdindex = vaddr >> 22;
+ uintptr_t ptindex = vaddr >> 12 & 0x03FF;
- uint32_t *page_table = (page_directory[pdindex] + 0xC0000000 & 0xFFFFF000);
- uint32_t *pte = (uint32_t*)(&page_table[ptindex]);
+ uintptr_t *pt = (pd[pdindex] + 0xC0000000 & 0xFFFFF000);
+ uintptr_t *pte = (uintptr_t*)(&pt[ptindex]);
*pte &= 0;
}