summaryrefslogtreecommitdiff
path: root/arch/i386/kernel/paging.c
blob: d8f72a376f28ef8df5b63f921a670bfa726eaf69 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <kernel/paging.h>
#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;

static uint32_t page_directory[1024] __attribute__((aligned(PAGE_SIZE)));
static uint32_t first_page_table[1024] __attribute__((aligned(PAGE_SIZE)));

static int paging_enabled = 0;

void paging_init(void) {
        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);
        }

        map_page(0xB8000, 0xC03FF000, 0x003);
        mark_bitmap(0xB8000, 1);

        load_page_dir(((uint32_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;

        uint32_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);
}

uint32_t get_vaddr(uint32_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;

        uint32_t *page_table = (page_directory[pdindex] + 0xC0000000 & 0xFFFFF000);
        uint32_t *pte = (uint32_t*)(&page_table[ptindex]);
        *pte |= paddr | (flags & 0xFFF) | 0x01;
}

void unmap_page(uint32_t vaddr) {
        uint32_t pdindex = vaddr >> 22;
        uint32_t ptindex = vaddr >> 12 & 0x03FF;

        uint32_t *page_table = (page_directory[pdindex] + 0xC0000000 & 0xFFFFF000);
        uint32_t *pte = (uint32_t*)(&page_table[ptindex]);
        *pte &= 0;
}