aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/memory/paging.c
diff options
context:
space:
mode:
authorMarvin Borner2020-04-26 20:12:05 +0200
committerMarvin Borner2020-04-26 20:12:05 +0200
commit31f671f2137bc09e62de09142bea232c1975c76b (patch)
tree60729693e4a70d2b3d449ed396ba860d3fa33071 /src/kernel/memory/paging.c
parentd3047efc1085d3e2f5524f629e55dc456a2f5065 (diff)
Complete rewrite of paging and allocation libs
-> This was REALLY needed.
Diffstat (limited to 'src/kernel/memory/paging.c')
-rw-r--r--src/kernel/memory/paging.c225
1 files changed, 85 insertions, 140 deletions
diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c
index e237a90..910b569 100644
--- a/src/kernel/memory/paging.c
+++ b/src/kernel/memory/paging.c
@@ -1,198 +1,143 @@
#include <stdint.h>
#include <kernel/memory/paging.h>
+#include <kernel/memory/alloc.h>
#include <kernel/system.h>
#include <kernel/lib/lib.h>
#include <kernel/io/io.h>
#include <kernel/acpi/acpi.h>
-int paging_enabled = 0;
+struct page_directory *paging_current_directory = NULL;
+struct page_directory *paging_root_directory = NULL;
-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)));
+/* void paging_install(uint32_t multiboot_address) */
+/* { */
+/* if (!memory_init(multiboot_address)) */
+/* paging_set_present(0, memory_get_all() >> 3); // /4 */
+/* paging_set_used(0, ((uint32_t)ASM_KERNEL_END >> 12) + 1); // /4096 */
+/* } */
-void paging_init()
+struct page_table *get_cr3()
{
- 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;
- }
- }
-
- for (uint32_t i = 0; i < 1024; i++) {
- current_page_directory[i] = ((uint32_t)current_page_tables[i]) | PD_RW | PD_PRESENT;
- }
-}
-
-void paging_install(uint32_t multiboot_address)
-{
- // User paging
- paging_switch_directory(1);
- paging_init();
- paging_set_user(0, memory_get_all() >> 3);
-
- // Kernel paging
- paging_switch_directory(0);
- paging_init();
-
- // if mmap approach didn't work
- if (!memory_init(multiboot_address))
- paging_set_present(0, memory_get_all() >> 3); // /4
- paging_set_used(0, ((uint32_t)ASM_KERNEL_END >> 12) + 1); // /4096
- // paging_set_user(0, memory_get_all() >> 3); // HMM
-
- paging_enable();
- log("Installed paging");
+ uint32_t cr3;
+ asm volatile("movl %%cr3, %%eax" : "=a"(cr3));
+ return (struct page_table *)cr3;
}
-void paging_disable()
+uint32_t get_cr0()
{
uint32_t cr0;
- asm("mov %%cr0, %0" : "=r"(cr0));
- cr0 &= 0x7fffffff;
- asm("mov %0, %%cr0" ::"r"(cr0));
- paging_enabled = 0;
+ asm volatile("movl %%cr0, %%eax" : "=a"(cr0));
+ return cr0;
}
-void paging_enable()
+void set_cr3(struct page_directory *dir)
{
- 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;
+ uint32_t addr = (uint32_t)&dir->tables[0];
+ asm volatile("movl %%eax, %%cr3" ::"a"(addr));
}
-void paging_switch_directory(int user)
+void set_cr0(uint32_t cr0)
{
- if (user == 1) {
- current_page_tables = user_page_tables;
- current_page_directory = user_page_directory;
- } else {
- current_page_tables = kernel_page_tables;
- current_page_directory = kernel_page_directory;
- }
- asm("mov %0, %%cr3" ::"r"(current_page_directory));
+ asm volatile("movl %%eax, %%cr0" ::"a"(cr0));
}
-void invlpg(uint32_t addr)
+void paging_switch_directory(struct page_directory *dir)
{
- asm("invlpg (%0)" ::"r"(addr) : "memory");
+ set_cr3(dir);
+ set_cr0(get_cr0() | 0x80000000);
}
-void paging_map(uint32_t phy, uint32_t virt, uint16_t flags)
+struct page_directory *paging_make_directory()
{
- uint32_t pdi = virt >> 22;
- uint32_t pti = virt >> 12 & 0x03FF;
- current_page_tables[pdi][pti] = phy | flags;
- invlpg(virt);
-}
+ struct page_directory *dir =
+ (struct page_directory *)kmalloc_a(sizeof(struct page_directory));
-uint32_t paging_get_phys(uint32_t virt)
-{
- uint32_t pdi = virt >> 22;
- uint32_t pti = (virt >> 12) & 0x03FF;
- return current_page_tables[pdi][pti] & 0xFFFFF000;
-}
+ for (int i = 0; i < 1024; i++)
+ dir->tables[i] = EMPTY_TAB;
-uint16_t paging_get_flags(uint32_t virt)
-{
- uint32_t pdi = virt >> 22;
- uint32_t pti = (virt >> 12) & 0x03FF;
- return current_page_tables[pdi][pti] & 0xFFF;
+ return dir;
}
-void paging_set_flag_up(uint32_t virt, uint32_t count, uint32_t flag)
+struct page_table *paging_make_table()
{
- uint32_t page_n = virt / 0x1000;
- for (uint32_t i = page_n; i < page_n + count; i++) {
- current_page_tables[i / 1024][i % 1024] |= flag;
- invlpg(i * 0x1000);
+ struct page_table *tab = (struct page_table *)kmalloc_a(sizeof(struct page_table));
+
+ for (int i = 0; i < 1024; i++) {
+ tab->pages[i].present = 0;
+ tab->pages[i].rw = 1;
}
+
+ return tab;
}
-void paging_set_flag_down(uint32_t virt, uint32_t count, uint32_t flag)
+void paging_map(struct page_directory *dir, uint32_t phys, uint32_t virt)
{
- uint32_t page_n = virt / 0x1000;
- for (uint32_t i = page_n; i < page_n + count; i++) {
- current_page_tables[i / 1024][i % 1024] &= ~flag;
- invlpg(i * 0x1000);
+ short id = virt >> 22;
+ struct page_table *tab = paging_make_table();
+
+ dir->tables[id] = ((struct page_table *)((uint32_t)tab | 3)); // RW
+
+ for (int i = 0; i < 1024; i++) {
+ tab->pages[i].frame = phys >> 12;
+ tab->pages[i].present = 1;
+ phys += 4096;
}
}
-void paging_set_present(uint32_t virt, uint32_t count)
+void paging_map_user(struct page_directory *dir, uint32_t phys, uint32_t virt)
{
- paging_set_flag_up(virt, count, PT_PRESENT);
-}
+ short id = virt >> 22;
+ struct page_table *tab = paging_make_table();
-void paging_set_absent(uint32_t virt, uint32_t count)
-{
- paging_set_flag_down(virt, count, PT_PRESENT);
-}
+ dir->tables[id] = ((struct page_table *)((uint32_t)tab | 3 | 4)); // RW + usermode
-void paging_set_used(uint32_t virt, uint32_t count)
-{
- paging_set_flag_up(virt, count, PT_USED);
+ int i;
+ for (i = 0; i < 1024; i++) {
+ tab->pages[i].frame = phys >> 12;
+ tab->pages[i].present = 1;
+ tab->pages[i].user = 1;
+ phys += 4096;
+ }
}
-void paging_set_free(uint32_t virt, uint32_t count)
+void paging_install()
{
- paging_set_flag_down(virt, count, PT_USED);
-}
+ kheap_init();
-void paging_set_user(uint32_t virt, uint32_t count)
-{
- uint32_t page_n = virt / 0x1000;
- for (uint32_t i = page_n; i < page_n + count; i += 1024) {
- current_page_directory[i / 1024] |= PD_ALL_PRIV;
- }
- paging_set_flag_up(virt, count, PT_ALL_PRIV);
+ paging_current_directory = paging_make_directory();
+ paging_root_directory = paging_current_directory;
+
+ for (uint32_t i = 0; i < 0xF0000000; i += PAGE_S)
+ paging_map(paging_root_directory, i, i);
}
-uint32_t paging_find_pages(uint32_t count)
+void paging_convert_page(struct page_directory *kdir)
{
- 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);
- }
+ for (int i = 0; i < 1024; i++) {
+ kdir->tables[i] = (struct page_table *)((uint32_t)kdir->tables[i] | 4); // Usermode
+
+ if (((uint32_t)kdir->tables[i]) & 1) { // Is present
+ for (int j = 0; j < 1024; j++)
+ kdir->tables[i]->pages[j].user = 1; // Usermode
}
}
-
- panic("Out of memory!");
- return 0;
}
-uint32_t paging_alloc_pages(uint32_t count)
+struct page_directory *paging_copy_user_directory(struct page_directory *dir)
{
- uint32_t ptr = paging_find_pages(count);
- paging_set_used(ptr, count);
- paging_set_user(ptr, count);
- return ptr;
-}
+ struct page_directory *copy = paging_make_directory();
+ memcpy(copy, paging_root_directory, sizeof(struct page_directory));
-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++;
+ if (((uint32_t)dir->tables[i]) & 4) {
+ struct page_table *tab =
+ (struct page_table *)((uint32_t)dir->tables[i] & 0xFFFFF000);
+
+ void *buffer = kmalloc_a(PAGE_S);
+ memcpy(buffer, (void *)(tab->pages[0].frame << 12), PAGE_S);
+ paging_map_user(copy, (uint32_t)buffer, (uint32_t)i << 22);
}
}
- return n;
+
+ return copy;
}