mirror of
https://github.com/Tom-on64/kern.git
synced 2026-11-03 18:22:22 +00:00
Finished Virtual Memory Manager!!! Paging etc. now works perfectly*
*i have no idea if it works right, but it doesn't seem to be broken
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
#ifndef ADDRESSES_H
|
||||
#define ADDRESSES_H
|
||||
|
||||
#define MEMMAP_AREA 0x30000
|
||||
#define KERNEL_LOC 0x50000
|
||||
|
||||
#endif
|
||||
@@ -47,14 +47,20 @@ int32_t findFreeBlocks(uint32_t blockCount) {
|
||||
uint32_t block = 1 << j;
|
||||
|
||||
if (!(memoryMap[i] & block)) {
|
||||
uint32_t startBlock = i * 32 + block;
|
||||
uint32_t freeBlocks = 0;
|
||||
// uint32_t startBlock = i * 32 + block;
|
||||
// uint32_t freeBlocks = 0;
|
||||
|
||||
for (uint32_t count = 0; count <= blockCount; count++) {
|
||||
if (!testBlock(startBlock + count)) {
|
||||
freeBlocks++;
|
||||
for (uint32_t count = i, freeBlocks = 0; count < blockCount; count++) {
|
||||
if (j + count > 31 && i + 1 <= maxBlocks / 32) {
|
||||
if (!(memoryMap[i+1] & (1 << (j + count)))) {
|
||||
freeBlocks++;
|
||||
}
|
||||
} else {
|
||||
if (!(memoryMap[i] & (1 << (j + count)))) {
|
||||
freeBlocks++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (freeBlocks == blockCount) {
|
||||
return i * 32 + j;
|
||||
}
|
||||
@@ -67,7 +73,7 @@ int32_t findFreeBlocks(uint32_t blockCount) {
|
||||
return -1; // No free memory found :/
|
||||
}
|
||||
|
||||
void setupMemoryManager(uint32_t startAddress, uint32_t size) {
|
||||
void setupPhysicalMemoryManager(uint32_t startAddress, uint32_t size) {
|
||||
memoryMap = (uint32_t*)startAddress;
|
||||
maxBlocks = size / BLOCK_SIZE;
|
||||
usedBlocks = maxBlocks;
|
||||
|
||||
+153
-1
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <memory/physical.h>
|
||||
#include <string.h>
|
||||
#include <memory/addresses.h>
|
||||
|
||||
#define PAGES_PER_TABLE 1024
|
||||
#define TABLES_PER_DIRECTORY 1024
|
||||
@@ -10,6 +12,11 @@
|
||||
|
||||
#define PD_INDEX(_vAddress) ((_vAddress) >> 22)
|
||||
#define PT_INDEX(_vAddress) (((_vAddress) >> 12) & 0x3ff)
|
||||
#define PAGE_PHYS_ADDRESS(_dirEntry) (*(_dirEntry) & ~ 0xfff)
|
||||
#define SET_ATTR(_entry, _attr) (*(_entry) |= (_attr))
|
||||
#define CLEAR_ATTR(_entry, _attr) (*(_entry) &= ~(_attr))
|
||||
#define TEST_ATTR(_entry, _attr) (*(_entry) & (_attr))
|
||||
#define SET_FRAME(_entry, _address) (*(_entry) = (*(_entry) & ~0x7ffff000) | (_address))
|
||||
|
||||
typedef uint32_t ptEntry_t;
|
||||
typedef uint32_t pdEntry_t;
|
||||
@@ -49,6 +56,151 @@ typedef struct {
|
||||
pdEntry_t entries[TABLES_PER_DIRECTORY];
|
||||
} pageDirectory_t;
|
||||
|
||||
pageDirectory_t* currentPd = 0;
|
||||
pageDirectory_t* currentPd = NULL;
|
||||
|
||||
ptEntry_t* getPtEntry(pageTable_t* pt, uint32_t virtualAddress) {
|
||||
if (pt) return &pt->entries[PT_INDEX(virtualAddress)];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pdEntry_t* getPdEntry(pageDirectory_t* pd, uint32_t virtualAddress) {
|
||||
if (pd) return &pd->entries[PT_INDEX(virtualAddress)]; // It it supposed to be PT_INDEX, don't worry
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptEntry_t* getPage(uint32_t virtualAddress) {
|
||||
pageDirectory_t* pd = currentPd;
|
||||
pdEntry_t* entry = &pd->entries[PD_INDEX(virtualAddress)];
|
||||
pageTable_t* table = (pageTable_t*)PAGE_PHYS_ADDRESS(entry);
|
||||
ptEntry_t* page = &table->entries[PT_INDEX(virtualAddress)];
|
||||
return page;
|
||||
}
|
||||
|
||||
void* allocPage(ptEntry_t* page) {
|
||||
void* block = allocBlocks(1);
|
||||
if (block) {
|
||||
SET_FRAME(page, (uint32_t)block);
|
||||
SET_ATTR(page, PTE_PRESENT);
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
void freePage(ptEntry_t* page) {
|
||||
void* address = (void*)PAGE_PHYS_ADDRESS(page);
|
||||
if (address) {
|
||||
freeBlocks(address, 1);
|
||||
}
|
||||
|
||||
CLEAR_ATTR(page, PTE_PRESENT);
|
||||
}
|
||||
|
||||
uint8_t setPageDirectory(pageDirectory_t* pd) {
|
||||
if (!pd) { return 0; } // Nuh uh
|
||||
currentPd = pd;
|
||||
|
||||
// cr3 (Control register 3) - current page dir address
|
||||
__asm__ volatile("movl %%eax, %%cr3" : : "a"(currentPd));
|
||||
|
||||
return 1; // Success
|
||||
}
|
||||
|
||||
void flushTlbEntry(uint32_t virtualAddress) {
|
||||
__asm__ volatile("cli; invlpg (%0); sti" : : "r"(virtualAddress));
|
||||
}
|
||||
|
||||
uint8_t mapPage(void* physicalAddr, void* virtualAddr) {
|
||||
pageDirectory_t* pd = currentPd;
|
||||
pdEntry_t* entry = &pd->entries[PD_INDEX((uint32_t)virtualAddr)];
|
||||
|
||||
if (!TEST_ATTR(entry, PTE_PRESENT)) {
|
||||
// Assuming that the page is not allocated since it's not present
|
||||
pageTable_t* table = (pageTable_t*)allocBlocks(1);
|
||||
if (!table) return 0; // Out of memory!!
|
||||
|
||||
// Clear page table (may be slow?)
|
||||
memset(table, 0, sizeof(pageTable_t));
|
||||
|
||||
pdEntry_t* entry = &pd->entries[PD_INDEX((uint32_t)virtualAddr)];
|
||||
// Enable attributes and map in table
|
||||
SET_ATTR(entry, PDE_PRESENT);
|
||||
SET_ATTR(entry, PDE_READ_WRITE);
|
||||
SET_FRAME(entry, (uint32_t)table);
|
||||
}
|
||||
|
||||
pageTable_t* table = (pageTable_t*)PAGE_PHYS_ADDRESS(entry);
|
||||
ptEntry_t* page = &table->entries[PT_INDEX((uint32_t)virtualAddr)];
|
||||
|
||||
SET_ATTR(page, PTE_PRESENT);
|
||||
SET_FRAME(page, (uint32_t)physicalAddr);
|
||||
|
||||
return 1; // Success
|
||||
}
|
||||
|
||||
void unmapPage(void* virtualAddress) {
|
||||
ptEntry_t* page = getPage((uint32_t)virtualAddress);
|
||||
|
||||
SET_FRAME(page, 0);
|
||||
CLEAR_ATTR(page, PDE_PRESENT);
|
||||
}
|
||||
|
||||
uint8_t setupVirtualMemoryManager() {
|
||||
// Create a default page dir
|
||||
pageDirectory_t* dir = (pageDirectory_t*)allocBlocks(3);
|
||||
|
||||
if (!dir) { return 0; } // Out of memory
|
||||
|
||||
memset(dir, 0, sizeof(pageDirectory_t));
|
||||
for (uint32_t i = 0; i < 1024; i++) {
|
||||
dir->entries[i] = 0x02; // Supervisor, r/w, not present
|
||||
}
|
||||
|
||||
// Alloc default page table
|
||||
pageTable_t* table = (pageTable_t*)allocBlocks(1);
|
||||
if (!table) { return 0; } // Out of memory
|
||||
|
||||
// Alloc a 3GB page
|
||||
pageTable_t* table3gb = (pageTable_t*)allocBlocks(1);
|
||||
if (!table) { return 0; } // Out of memory
|
||||
|
||||
memset(table, 0, sizeof(pageTable_t));
|
||||
memset(table3gb, 0, sizeof(pageTable_t));
|
||||
|
||||
// Identity map first 4MB
|
||||
for (uint32_t i = 0, frame = 0, virt = 0; i < 1024; i++, frame += PAGE_SIZE, virt += PAGE_SIZE) {
|
||||
ptEntry_t page = 0;
|
||||
SET_ATTR(&page, PTE_PRESENT);
|
||||
SET_ATTR(&page, PTE_READ_WRITE);
|
||||
SET_FRAME(&page, frame);
|
||||
|
||||
table3gb->entries[PT_INDEX(virt)] = page;
|
||||
}
|
||||
|
||||
// Map kernel to 3GB+
|
||||
for (uint32_t i = 0, frame = KERNEL_LOC, virt = 0xc0000000; i < 1024; i++, frame += PAGE_SIZE, virt += PAGE_SIZE) {
|
||||
ptEntry_t page = 0;
|
||||
SET_ATTR(&page, PTE_PRESENT);
|
||||
SET_ATTR(&page, PTE_READ_WRITE);
|
||||
SET_FRAME(&page, frame);
|
||||
|
||||
table->entries[PT_INDEX(virt)] = page;
|
||||
}
|
||||
|
||||
pdEntry_t* entry = &dir->entries[PD_INDEX(0xc0000000)];
|
||||
SET_ATTR(entry, PDE_PRESENT);
|
||||
SET_ATTR(entry, PDE_READ_WRITE);
|
||||
SET_FRAME(entry, (uint32_t)table);
|
||||
|
||||
pdEntry_t* entry2 = &dir->entries[PD_INDEX(0x00000000)];
|
||||
SET_ATTR(entry2, PDE_PRESENT);
|
||||
SET_ATTR(entry2, PDE_READ_WRITE);
|
||||
SET_FRAME(entry2, (uint32_t)table3gb);
|
||||
|
||||
setPageDirectory(dir);
|
||||
|
||||
// ENABLE PAGING!!! Set PG bit 31 and PE bit 0 in cr0
|
||||
__asm__ volatile("movl %cr0, %eax; orl $0x80000001, %eax; movl %eax, %cr0");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user