aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/memory/paging.c
diff options
context:
space:
mode:
authorMarvin Borner2020-02-16 17:29:19 +0100
committerMarvin Borner2020-02-16 17:29:50 +0100
commit45184af20936cb889b658e69e00a0bb3d522757f (patch)
tree4b6c3408e526fe733ccfa960726c37e70dc6f989 /src/kernel/memory/paging.c
parentf5b995586e28f7db426f4707a4348dc067df41c0 (diff)
Revert to good ol' paging
Diffstat (limited to 'src/kernel/memory/paging.c')
-rw-r--r--src/kernel/memory/paging.c283
1 files changed, 136 insertions, 147 deletions
diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c
index bca5ed3..e4169ba 100644
--- a/src/kernel/memory/paging.c
+++ b/src/kernel/memory/paging.c
@@ -1,203 +1,192 @@
+#include <stdint.h>
#include <kernel/memory/paging.h>
-#include <kernel/memory/kheap.h>
-#include <kernel/lib/lib.h>
#include <kernel/system.h>
+#include <kernel/lib/lib.h>
int paging_enabled = 0;
-page_directory_t *kernel_directory = 0;
-page_directory_t *current_directory = 0;
-
-uint32_t *frames;
-uint32_t nframes;
+uint32_t *current_page_directory;
+uint32_t (*current_page_tables)[1024];
+uint32_t kernel_page_directory[1024] __attribute__((aligned(4096)));
+uint32_t kernel_page_tables[1024][1024] __attribute__((aligned(4096)));
+uint32_t user_page_directory[1024] __attribute__((aligned(4096)));
+uint32_t user_page_tables[1024][1024] __attribute__((aligned(4096)));
-extern uint32_t placement_address;
-extern heap_t *kheap;
-
-extern void copy_page_physical();
+void paging_init()
+{
+ for (uint32_t i = 0; i < 1024; i++) {
+ for (uint32_t j = 0; j < 1024; j++) {
+ current_page_tables[i][j] = ((j * 0x1000) + (i * 0x400000)) | PT_RW;
+ }
+ }
-#define INDEX_FROM_BIT(a) (a/(8*4))
-#define OFFSET_FROM_BIT(a) (a%(8*4))
+ for (uint32_t i = 0; i < 1024; i++) {
+ current_page_directory[i] = ((uint32_t) current_page_tables[i]) | PD_RW | PD_PRESENT;
+ }
-void paging_set_frame(uint32_t frame_addr)
-{
- uint32_t frame = frame_addr / 0x1000;
- uint32_t idx = INDEX_FROM_BIT(frame);
- uint32_t off = OFFSET_FROM_BIT(frame);
- frames[idx] |= (0x1 << off);
+ paging_set_present(0, memory_get_all() >> 3); // /4
}
-void paging_clear_frame(uint32_t frame_addr)
+void paging_install()
{
- uint32_t frame = frame_addr / 0x1000;
- uint32_t idx = INDEX_FROM_BIT(frame);
- uint32_t off = OFFSET_FROM_BIT(frame);
- frames[idx] &= ~(0x1 << off);
+ // User paging
+ paging_switch_directory(1);
+ paging_init();
+ paging_set_user(0, memory_get_all() >> 3);
+
+ // Kernel paging
+ paging_switch_directory(0);
+ paging_init();
+ paging_set_used(0, ((uint32_t) ASM_KERNEL_END >> 12) + 1); // /4096
+
+ paging_enable();
+
+ vga_log("Installed paging");
}
-uint32_t paging_first_frame()
+void paging_disable()
{
- uint32_t i, j;
- for (i = 0; i < INDEX_FROM_BIT(nframes); i++) {
- if (frames[i] != 0xFFFFFFFF) {
- for (j = 0; j < 32; j++) {
- uint32_t toTest = (0x1 << j);
- if (!(frames[i] & toTest)) {
- return i * 4 * 8 + j;
- }
- }
- }
- }
- return 0;
+ uint32_t cr0;
+ asm ("mov %%cr0, %0": "=r"(cr0));
+ cr0 &= 0x7fffffff;
+ asm ("mov %0, %%cr0"::"r"(cr0));
+ paging_enabled = 0;
}
-void paging_alloc_frame(page_t *page, int is_kernel, int is_writeable)
+void paging_switch_directory(int user)
{
- if (page->frame != 0) {
- return;
+ if (user == 1) {
+ current_page_tables = user_page_tables;
+ current_page_directory = user_page_directory;
} else {
- uint32_t idx = paging_first_frame();
- if (idx == (uint32_t) -1)
- panic("No free frames!");
- paging_set_frame(idx * 0x1000);
- page->present = 1;
- page->rw = (is_writeable == 1) ? 1 : 0;
- page->user = (is_kernel == 1) ? 0 : 1;
- page->frame = idx;
+ current_page_tables = kernel_page_tables;
+ current_page_directory = kernel_page_directory;
}
+ asm ("mov %0, %%cr3"::"r"(current_page_directory));
}
-void paging_free_frame(page_t *page)
+void paging_enable()
{
- uint32_t frame;
- if (!(frame = page->frame)) {
- return;
- } else {
- paging_clear_frame(frame);
- page->frame = 0x0;
- }
+ asm ("mov %0, %%cr3"::"r"(current_page_directory));
+ uint32_t cr0;
+ asm ("mov %%cr0, %0": "=r"(cr0));
+ cr0 |= 0x80000000;
+ asm ("mov %0, %%cr0"::"r"(cr0));
+ paging_enabled = 1;
}
-void paging_install()
+inline void invlpg(uint32_t addr)
{
- uint32_t mem_end_page = memory_get_all() << 10;
-
- nframes = mem_end_page / 0x1000;
- frames = (uint32_t *) kmalloc(INDEX_FROM_BIT(nframes));
- memset(frames, 0, INDEX_FROM_BIT(nframes));
-
- kernel_directory = (page_directory_t *) kmalloc_a(sizeof(page_directory_t));
- memset(kernel_directory, 0, sizeof(page_directory_t));
- kernel_directory->physical_address = (uint32_t) kernel_directory->tables_physical;
-
- for (uint32_t i = KHEAP_START; i < KHEAP_START + KHEAP_INITIAL_SIZE; i += 0x1000)
- paging_get_page((uint32_t) i, 1, kernel_directory);
-
- int i = 0;
- while (i < 0x400000) {
- paging_alloc_frame(paging_get_page((uint32_t) i, 1, kernel_directory), 0, 0);
- i += 0x1000;
- }
-
- for (i = KHEAP_START; i < (int) (KHEAP_START + KHEAP_INITIAL_SIZE); i += 0x1000)
- paging_alloc_frame(paging_get_page((uint32_t) i, 1, kernel_directory), 0, 0);
-
- paging_switch_directory(kernel_directory);
-
- kheap = create_heap(KHEAP_START, KHEAP_START + KHEAP_INITIAL_SIZE, 0xCFFFF000, 0, 0);
-
- current_directory = paging_clone_directory(kernel_directory);
- paging_switch_directory(current_directory);
- vga_log("Installed Paging");
+ asm ("invlpg (%0)"::"r" (addr) : "memory");
}
-void paging_switch_directory(page_directory_t *dir)
+void paging_map(uint32_t phy, uint32_t virt, uint16_t flags)
{
- current_directory = dir;
- asm volatile("mov %0, %%cr3"::"r"(dir->physical_address));
- uint32_t cr0;
- asm volatile("mov %%cr0, %0": "=r"(cr0));
- cr0 |= 0x80000000; // Enable paging!
- asm volatile("mov %0, %%cr0"::"r"(cr0));
+ uint32_t pdi = virt >> 22;
+ uint32_t pti = virt >> 12 & 0x03FF;
+ current_page_tables[pdi][pti] = phy | flags;
+ invlpg(virt);
}
-void paging_enable()
+uint32_t paging_get_phys(uint32_t virt)
{
- paging_switch_directory(kernel_directory);
- paging_enabled = 1;
+ uint32_t pdi = virt >> 22;
+ uint32_t pti = (virt >> 12) & 0x03FF;
+ return current_page_tables[pdi][pti] & 0xFFFFF000;
}
-void paging_disable()
+uint16_t paging_get_flags(uint32_t virt)
{
- uint32_t cr0;
- asm ("mov %%cr0, %0": "=r"(cr0));
- cr0 &= 0x7fffffff;
- asm ("mov %0, %%cr0"::"r"(cr0));
- paging_enabled = 0;
+ uint32_t pdi = virt >> 22;
+ uint32_t pti = (virt >> 12) & 0x03FF;
+ return current_page_tables[pdi][pti] & 0xFFF;
}
-page_t *paging_get_page(uint32_t address, int make, page_directory_t *dir)
+void paging_set_flag_up(uint32_t virt, uint32_t count, uint32_t flag)
{
- address /= 0x1000;
- uint32_t table_idx = address / 1024;
+ uint32_t page_n = virt / 4096;
+ for (uint32_t i = page_n; i < page_n + count; i++) {
+ current_page_tables[i / 1024][i % 1024] |= flag;
+ invlpg(i * 4096);
+ }
+}
- if (dir->tables[table_idx]) {
- return &dir->tables[table_idx]->pages[address % 1024];
- } else if (make) {
- uint32_t tmp;
- dir->tables[table_idx] = (page_table_t *) kmalloc_ap(sizeof(page_table_t), &tmp);
- memset(dir->tables[table_idx], 0, 0x1000);
- dir->tables_physical[table_idx] = tmp | 0x7; // PRESENT, RW, US
- return &dir->tables[table_idx]->pages[address % 1024];
- } else {
- return 0;
+void paging_set_flag_down(uint32_t virt, uint32_t count, uint32_t flag)
+{
+ uint32_t page_n = virt / 4096;
+ for (uint32_t i = page_n; i < page_n + count; i++) {
+ current_page_tables[i / 1024][i % 1024] &= ~flag;
+ invlpg(i * 4096);
}
}
-static page_table_t *paging_clone_table(page_table_t *src, uint32_t *physAddr)
+void paging_set_present(uint32_t virt, uint32_t count)
{
- page_table_t *table = (page_table_t *) kmalloc_ap(sizeof(page_table_t), physAddr);
- memset(table, 0, sizeof(page_directory_t));
+ paging_set_flag_up(virt, count, PT_PRESENT);
+}
- for (int i = 0; i < 1024; i++) {
- if (!src->pages[i].frame)
- continue;
+void paging_set_absent(uint32_t virt, uint32_t count)
+{
+ paging_set_flag_down(virt, count, PT_PRESENT);
+}
- paging_alloc_frame(&table->pages[i], 0, 0);
+void paging_set_used(uint32_t virt, uint32_t count)
+{
+ paging_set_flag_up(virt, count, PT_USED);
+}
- if (src->pages[i].present) table->pages[i].present = 1;
- if (src->pages[i].rw) table->pages[i].rw = 1;
- if (src->pages[i].user) table->pages[i].user = 1;
- if (src->pages[i].accessed)table->pages[i].accessed = 1;
- if (src->pages[i].dirty) table->pages[i].dirty = 1;
+void paging_set_free(uint32_t virt, uint32_t count)
+{
+ paging_set_flag_down(virt, count, PT_USED);
+}
- copy_page_physical(src->pages[i].frame * 0x1000, table->pages[i].frame * 0x1000);
+void paging_set_user(uint32_t virt, uint32_t count)
+{
+ uint32_t page_n = virt / 4096;
+ for (uint32_t i = page_n; i < page_n + count; i += 1024) {
+ current_page_directory[i / 1024] |= PD_ALL_PRIV;
}
- return table;
+ paging_set_flag_up(virt, count, PT_ALL_PRIV);
}
-page_directory_t *paging_clone_directory(page_directory_t *src)
+uint32_t paging_find_pages(uint32_t count)
{
- uint32_t phys;
- page_directory_t *dir = (page_directory_t *) kmalloc_ap(sizeof(page_directory_t), &phys);
- memset(dir, 0, sizeof(page_directory_t));
-
- uint32_t offset = (uint32_t) dir->tables_physical - (uint32_t) dir;
+ uint32_t continuous = 0;
+ uint32_t startDir = 0;
+ uint32_t startPage = 0;
+ for (uint32_t i = 0; i < 1024; i++) {
+ for (uint32_t j = 0; j < 1024; j++) {
+ if (!(current_page_tables[i][j] & PT_PRESENT) || (current_page_tables[i][j] & PT_USED)) {
+ continuous = 0;
+ startDir = i;
+ startPage = j + 1;
+ } else {
+ if (++continuous == count)
+ return (startDir * 0x400000) + (startPage * 0x1000);
+ }
+ }
+ }
- dir->physical_address = phys + offset;
+ panic("Out of memory!");
+ return 0;
+}
- for (int i = 0; i < 1024; i++) {
- if (!src->tables[i])
- continue;
+uint32_t paging_alloc_pages(uint32_t count)
+{
+ uint32_t ptr = paging_find_pages(count);
+ paging_set_used(ptr, count);
+ paging_set_user(ptr, count);
+ return ptr;
+}
- if (kernel_directory->tables[i] == src->tables[i]) {
- dir->tables[i] = src->tables[i];
- dir->tables_physical[i] = src->tables_physical[i];
- } else {
- uint32_t phys;
- dir->tables[i] = paging_clone_table(src->tables[i], &phys);
- dir->tables_physical[i] = phys | 0x07;
+uint32_t paging_get_used_pages()
+{
+ uint32_t n = 0;
+ for (uint32_t i = 0; i < 1024; i++) {
+ for (uint32_t j = 0; j < 1024; j++) {
+ uint8_t flags = current_page_tables[i][j] & PT_USED;
+ if (flags == 1) n++;
}
}
- return dir;
+ return n;
} \ No newline at end of file