summaryrefslogtreecommitdiff
path: root/Source/Kernel/MemoryManager
diff options
context:
space:
mode:
authorAlexis211 <alexis211@gmail.com>2009-08-29 13:39:06 +0200
committerAlexis211 <alexis211@gmail.com>2009-08-29 13:39:06 +0200
commitc92beeedda51487696ce476ee30604f22e7b2270 (patch)
tree29b89d31b0b35792e1ed2bc5861be0439e7e40d9 /Source/Kernel/MemoryManager
parent5deab22107fc38bd2bea19f07889b14c376754e0 (diff)
downloadMelon-c92beeedda51487696ce476ee30604f22e7b2270.tar.gz
Melon-c92beeedda51487696ce476ee30604f22e7b2270.zip
The Melon kernel now has support for simple multitasking
Diffstat (limited to 'Source/Kernel/MemoryManager')
-rw-r--r--Source/Kernel/MemoryManager/PageDirectory.class.cpp43
-rw-r--r--Source/Kernel/MemoryManager/PageDirectory.class.h1
2 files changed, 42 insertions, 2 deletions
diff --git a/Source/Kernel/MemoryManager/PageDirectory.class.cpp b/Source/Kernel/MemoryManager/PageDirectory.class.cpp
index f48b0be..2c8507f 100644
--- a/Source/Kernel/MemoryManager/PageDirectory.class.cpp
+++ b/Source/Kernel/MemoryManager/PageDirectory.class.cpp
@@ -1,6 +1,9 @@
#include "PageDirectory.class.h"
#include <MemoryManager/PhysMem.ns.h>
#include <MemoryManager/PageAlloc.ns.h>
+#include <TaskManager/Task.ns.h>
+
+extern "C" void copy_page_physical(u32int src, u32int dest);
PageDirectory::PageDirectory() {
tablesPhysical = (u32int*)PageAlloc::alloc(&physicalAddr);
@@ -10,10 +13,44 @@ PageDirectory::PageDirectory() {
}
}
+PageDirectory::PageDirectory(PageDirectory* other) {
+ tablesPhysical = (u32int*)PageAlloc::alloc(&physicalAddr);
+ for (u32int i = 0; i < 768; i++) {
+ if (other->tablesPhysical[i] != 0) {
+ u32int tmp;
+ tables[i] = (page_table_t*)PageAlloc::alloc(&tmp);
+ tablesPhysical[i] = tmp | 0x07;
+ for (u32int j = 0; j < 1024; j++) {
+ if (!(other->tables[i]->pages[j].frame))
+ continue;
+ PhysMem::allocFrame(&tables[i]->pages[j], true, true);
+ tables[i]->pages[j].present = other->tables[i]->pages[j].present;
+ tables[i]->pages[j].rw = other->tables[i]->pages[j].rw;
+ tables[i]->pages[j].user = other->tables[i]->pages[j].user;
+ tables[i]->pages[j].accessed = other->tables[i]->pages[j].accessed;
+ tables[i]->pages[j].dirty = other->tables[i]->pages[j].dirty;
+ copy_page_physical(other->tables[i]->pages[j].frame * 0x1000, tables[i]->pages[j].frame * 0x1000);
+ }
+ } else {
+ tables[i] = 0;
+ tablesPhysical[i] = 0;
+ }
+ }
+ for (u32int i = 768; i < 1024; i++) { //Link kernel page tables
+ tablesPhysical[i] = other->tablesPhysical[i];
+ tables[i] = other->tables[i];
+ }
+}
+
PageDirectory::~PageDirectory() {
PageAlloc::free((void*)tablesPhysical);
- for (int i = 0; i < 1024; i++) {
- if (tables[i] != 0) PageAlloc::free((void*)tables[i]);
+ for (int i = 0; i < 768; i++) { //Only free addresses below 0xC0000000, upper is kernel space
+ if (tables[i] != 0) {
+ for (int j = 0; j < 1024; j++) {
+ PhysMem::freeFrame(&(tables[i]->pages[j]));
+ }
+ PageAlloc::free((void*)tables[i]);
+ }
}
}
@@ -27,6 +64,8 @@ page_t *PageDirectory::getPage(u32int address, bool make) {
tables[tableIdx] = (page_table_t*)PageAlloc::alloc(&tmp);
CMem::memset((u8int*)tables[tableIdx], 0, 0x1000);
tablesPhysical[tableIdx] = tmp | 0x07;
+ if (tableIdx >= 768)
+ Task::allocKernelPageTable(tableIdx, tables[tableIdx], tablesPhysical[tableIdx]);
return &(tables[tableIdx]->pages[address % 1024]);
} else {
return 0;
diff --git a/Source/Kernel/MemoryManager/PageDirectory.class.h b/Source/Kernel/MemoryManager/PageDirectory.class.h
index 4591324..8dac7ce 100644
--- a/Source/Kernel/MemoryManager/PageDirectory.class.h
+++ b/Source/Kernel/MemoryManager/PageDirectory.class.h
@@ -23,6 +23,7 @@ struct PageDirectory {
u32int physicalAddr;
PageDirectory();
+ PageDirectory(PageDirectory* other); //Clones the other pagedir
~PageDirectory();
page_t *getPage(u32int address, bool make);
void allocFrame(u32int address, bool is_user, bool is_writable);