diff options
author | Marvin Borner | 2020-02-16 17:29:19 +0100 |
---|---|---|
committer | Marvin Borner | 2020-02-16 17:29:50 +0100 |
commit | 45184af20936cb889b658e69e00a0bb3d522757f (patch) | |
tree | 4b6c3408e526fe733ccfa960726c37e70dc6f989 /src/kernel/memory/paging.c | |
parent | f5b995586e28f7db426f4707a4348dc067df41c0 (diff) |
Revert to good ol' paging
Diffstat (limited to 'src/kernel/memory/paging.c')
-rw-r--r-- | src/kernel/memory/paging.c | 283 |
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 |