[GOOD] BUILD 0.1.0.450 DATE 8/29/2011 AT 10:30 AM

====================================================
+ Changed 'align 0x4' line above multiboot header in loader.asm to
'align 4'
+ Removed -e option for echo in build.sh
+ Modified build.sh for linux
+ Fixed triple fault when enabling paging
+ Fixed page faults at memory manager initialization
+ Fixed 'mem' console function
+ Added more info about page fault at crash screen
+ Added Panic() macro
+ Added verbose mode for memory manager

[ BAD] BUILD 0.1.0.390 DATE 8/27/2011 AT 10:54 PM
====================================================
+ Added stdlib routines, separated in different files
+ Rewritten physical memory manager
+ Added virtual mem manager
+ Added memory allocation/freeing
+ Added memory library
+ Added temporary allocation (at end of kernel), until paging is started
- Removed functionality from debug console function 'mem'
- Removed system.h, the one remaining function now in stdio.h
This commit is contained in:
2021-09-14 18:48:57 +03:00
parent b6ddeca1c3
commit 913e65b856
326 changed files with 6990 additions and 12229 deletions

304
Kernel/memory/mem-heap.c Normal file
View File

@ -0,0 +1,304 @@
#include <memory-add.h>
#include <debugio.h>
#include <stdlib.h>
#define MEMHEAP_MAGIC 0x50DBE514
#define MEMHEAP_INDEX_SIZE 0x20000
#define MEMHEAP_MINIM_SIZE 0x70000
#define FlagsKernel 1
#define FlagsWriteable 2
typedef struct
{
uint32 Magic;
// bit 0: used bit 1: reserved
uint8 Used;
uint32 Size;
} MemHeapHeader;
typedef struct
{
uint32 Magic;
MemHeapHeader* Header;
} MemHeapFooter;
MemHeap* KernelHeap;
uint32 MemHeapFindSmallestHole (uint32 size, uint8 page_align, MemHeap* heap)
{
uint32 i;
for (i = 0; i < heap->Index.Size; i++)
{
MemHeapHeader* head = (MemHeapHeader*) OrderedArrayLookup(i, &heap->Index);
if (page_align)
{
uint32 location = (uint32)(head) + sizeof(MemHeapHeader);
// page align it
uint32 offset = 0x1000 - (location & 0xfff);
offset &= 0xfff;
if (head->Size - offset >= size) return i;
}
else if (head->Size >= size) return i;
}
return 0xffffffff;
}
int32 MemHeapCompare (uint32 a, uint32 b)
{
MemHeapHeader *ha = (MemHeapHeader*)a, *hb = (MemHeapHeader*)b;
if (ha->Size > hb->Size) return 1;
else if (ha->Size == hb->Size) return 0;
return -1;
}
inline void MemHeapHeaderSetup (uint32 size, uint8 used, MemHeapHeader* head)
{
head->Magic = MEMHEAP_MAGIC;
head->Used = used;
head->Size = size;
}
inline void MemHeapFooterSetup (MemHeapHeader* head, MemHeapFooter* foot)
{
foot->Magic = MEMHEAP_MAGIC;
foot->Header = head;
}
MemHeap* MemHeapCreate(uint32 start, uint32 end, uint32 max, uint8 flags)
{
if ((start & 0xfff) || (end & 0xfff)) return NULL;
MemHeap* heap = (MemHeap*) kmalloc(sizeof(MemHeap));
heap->Index = OrderedArrayPlace(start, MEMHEAP_INDEX_SIZE, MemHeapCompare);
start += sizeof(uint32) * MEMHEAP_INDEX_SIZE;
if (start & 0xfff) start = (start & 0xFFFFF000) + 0x1000;
heap->StartAddress = start;
heap->EndAddress = end;
heap->Flags = flags;
heap->MaxAddress = max;
// One large hole
MemHeapHeader* hole = (MemHeapHeader*)start;
MemHeapHeaderSetup(end-start, 0, hole);
OrderedArrayInsert(start, &heap->Index);
return heap;
}
void MemHeapExpand(uint32 newsz, MemHeap* heap, PageDirectory* pd)
{
if (newsz <= heap->EndAddress - heap->StartAddress) return;
if (newsz & 0xfff) newsz = (newsz & 0xfffff000) + 0x1000;
if (newsz + heap->StartAddress >= heap->MaxAddress) return;
uint32 i;
for (i = heap->EndAddress - heap->StartAddress; i < heap->StartAddress + newsz; i+=0x1000)
MemPhAllocFrame(PagingGetPage(i, 1, pd), heap->Flags & FlagsKernel, heap->Flags & FlagsWriteable);
heap->EndAddress = heap->StartAddress + newsz;
}
uint32 MemHeapContract(uint32 newsz, MemHeap* heap, PageDirectory* pd)
{
if (newsz >= heap->EndAddress - heap->StartAddress) return 0;
if (newsz & 0xfff) newsz = (newsz & 0xfffff000) + 0x1000; // page align
newsz = Max(newsz, MEMHEAP_MINIM_SIZE);
uint32 i;
for (i = heap->EndAddress - heap->StartAddress - 0x1000; i > newsz; i-=0x1000)
MemPhFreeFrame(PagingGetPage(i, 0, pd));
heap->EndAddress = heap->StartAddress + newsz;
return newsz;
}
uint32 MemHeapAlloc (uint32 size, uint8 isPageAligned, MemHeap* heap, PageDirectory* pd)
{
// Sanity check
if (!size || !heap) return 0;
// Find a good hole
uint32 newsize = size + sizeof(MemHeapHeader) + sizeof(MemHeapFooter);
uint32 i = MemHeapFindSmallestHole(newsize, isPageAligned, heap);
// Didn't find? Expand heap
if (i == 0xffffffff)
{
uint32 oldLen = heap->EndAddress - heap->StartAddress;
uint32 oldEnd = heap->EndAddress;
MemHeapExpand(oldLen + newsize, heap, pd);
uint32 newLen = heap->EndAddress - heap->StartAddress;
// Find the last header
uint32 i = 0, index = 0, addr = 0;
for (; i < heap->Index.Size; i++)
{
uint32 tmp = OrderedArrayLookup(i, &heap->Index);
if (tmp > addr) {
addr = tmp; index = i;
}
}
MemHeapHeader* head; MemHeapFooter* foot;
if (heap->Index.Size == 0) // No headers? Add one
{
head = (MemHeapHeader*)oldEnd;
MemHeapHeaderSetup(newLen - oldLen, 0, head);
OrderedArrayInsert(oldEnd, &heap->Index);
}
else { // Modify last header
head = (MemHeapHeader*) OrderedArrayLookup(index, &heap->Index);
head->Size = newLen - oldLen;
}
foot = (MemHeapFooter*)((uint32)head + head->Size - sizeof(MemHeapFooter));
MemHeapFooterSetup(head, foot);
// Try again
return MemHeapAlloc(size, isPageAligned, heap, pd);
}
// Get info about hole
uint32 origAddr = OrderedArrayLookup(i, &heap->Index);
MemHeapHeader* origHead =(MemHeapHeader*) origAddr;
uint32 origSize = origHead->Size;
// Should split in two?
if (origSize - newsize <= sizeof(MemHeapHeader) + sizeof(MemHeapFooter))
{
size += origSize - newsize;
newsize = origSize;
}
// Should be page aligned
if (isPageAligned && (origAddr&0xfffff000))
{
uint32 newAddr = origAddr + 0x1000 - (origAddr&0xfff) - sizeof(MemHeapHeader);
MemHeapHeaderSetup(0x1000 - (origAddr&0xfff) - sizeof(MemHeapHeader), 0, origHead);
MemHeapFooter* holeFooter = (MemHeapFooter*)(newAddr - sizeof(MemHeapFooter));
MemHeapFooterSetup(origHead, holeFooter);
origAddr = newAddr;
origSize -= origHead->Size;
}
else OrderedArrayDeleteIndex(i, &heap->Index);
// Create the new block
MemHeapHeader* bHead = (MemHeapHeader*)origAddr;
MemHeapFooter* bFoot = (MemHeapFooter*)(origAddr + sizeof(MemHeapHeader) + size);
MemHeapHeaderSetup(newsize, 1, bHead);
MemHeapFooterSetup(bHead, bFoot);
// Create a new hole at the end of current block if necessary
if (origSize - newsize > 0)
{
// header
MemHeapHeader* hHead = (MemHeapHeader*)(origAddr + sizeof(MemHeapHeader) +
sizeof(MemHeapFooter) + size);
MemHeapHeaderSetup(origSize - newsize, 0, hHead);
// footer
MemHeapFooter* hFoot = (MemHeapFooter*)((uint32)hHead + hHead->Size - sizeof(MemHeapFooter));
if ((uint32)hFoot < heap->EndAddress) MemHeapFooterSetup(hHead, hFoot);
// add it to index
OrderedArrayInsert((uint32)hHead, &heap->Index);
}
return (uint32)bHead + sizeof(MemHeapHeader);
}
void MemHeapFree (uint32 address, MemHeap* heap, PageDirectory* pd)
{
// Sanity check
if (!address || !heap) return;
MemHeapHeader* head = (MemHeapHeader*) (address - sizeof(MemHeapHeader));
MemHeapFooter* foot = (MemHeapFooter*) ((uint32)head + head->Size - sizeof(MemHeapFooter));
if (head->Magic != MEMHEAP_MAGIC) return;
if (foot->Magic != MEMHEAP_MAGIC) return;
// Clear used flag
head->Used = 0;
uint8 AddToIndex = 1;
// Unify left (if possible)
MemHeapFooter* testFoot = (MemHeapFooter*) ((uint32)head - sizeof(MemHeapFooter));
if (testFoot->Magic == MEMHEAP_MAGIC && testFoot->Header->Used == 0)
{
uint32 temp = head->Size;
head = testFoot->Header;
foot->Header = head;
head->Size += temp;
AddToIndex = 0;
}
// Unify right (if possible)
MemHeapHeader* testHead = (MemHeapHeader*) ((uint32)foot + sizeof(MemHeapFooter));
if ((uint32)testHead < heap->EndAddress && testHead->Magic == MEMHEAP_MAGIC && testHead->Used == 0)
{
head->Size += testHead->Size;
testFoot = (MemHeapFooter*) ((uint32)testHead + testHead->Size - sizeof(MemHeapFooter));
foot = testFoot;
uint32 i;
for (i = 0; i < heap->Index.Size &&
(uint32)testHead != OrderedArrayLookup(i, &heap->Index); i++) ;
if (i < heap->Index.Size) OrderedArrayDeleteIndex(i, &heap->Index);
}
// Contract heap (if possible)
if ((uint32)foot + sizeof(MemHeapFooter) == heap->EndAddress)
{
uint32 old = heap->EndAddress - heap->StartAddress;
uint32 new = MemHeapContract((uint32)head + head->Size - sizeof(MemHeapFooter), heap,pd);
// Last block still existent
if (head->Size > (old - new))
{
head->Size -= old - new;
foot = (MemHeapFooter*) ((uint32)head + head->Size - sizeof(MemHeapFooter));
MemHeapFooterSetup(head, foot);
}
// Nope, not existent
else
{
uint32 i;
for (i=0; i<heap->Index.Size && (uint32)testHead != OrderedArrayLookup(i,&heap->Index); i++) ;
if (i < heap->Index.Size) OrderedArrayDeleteIndex(i,&heap->Index);
}
}
// Lastly, insert hole in array
if (AddToIndex) OrderedArrayInsert((uint32)head, &heap->Index);
}

View File

@ -0,0 +1,74 @@
/*
* memory-vi.c
*
* Created on: Aug 23, 2011
* Author: Tiberiu
*/
#include <memory-add.h>
#include <stdio.h>
/*******************************
* Data *
*******************************/
PageDirectory* CurrentDirectory;
PageDirectory* KernelDirectory;
/*******************************
* Useful routines *
*******************************/
void PagingInitialize(uint32 kernel_used)
{
LogMem("Virtual memory manager initialization started. End of kernel = 0x%x\n", kernel_used);
PageDirectory* kernelPd = (PageDirectory*) kmalloc_a(sizeof(PageDirectory));
memset(kernelPd, 0, sizeof(PageDirectory));
CurrentDirectory = kernelPd;
KernelDirectory = kernelPd;
uint32 i;
for (i = 0; i < kernel_used; i+=0x1000)
MemPhAllocFrame(PagingGetPage(i, 1, kernelPd), 0, 0);
LogMem("Identity mapped first 0x%x bytes.\n", kernel_used);
for (i = KERNEL_HEAP_START; i < KERNEL_HEAP_END; i+=0x1000)
MemPhAllocFrame(PagingGetPage(i, 1, kernelPd), 1, 1);
LogMem("Mapped kernel space.\n");
PagingSwitchPageDirectory (kernelPd);
}
void PagingSwitchPageDirectory (PageDirectory* dir)
{
CurrentDirectory = dir;
asm volatile ("mov %0, %%cr3":: "r"(&dir->TablesPhysical));
uint32 cr0;
asm volatile ("mov %%cr0, %0": "=r"(cr0));
cr0 |= 0x80000000;
asm volatile ("mov %0, %%cr0":: "r"(cr0));
LogMem("Enabled paging.\n");
}
Page* PagingGetPage(uint32 addr, uint8 make, PageDirectory* dir)
{
addr >>= 12;
uint32 tableIndex = addr >> 10;
if (dir->Tables[tableIndex])
return &dir->Tables[tableIndex]->Pages[addr&0x3ff];
else if (make)
{
uint32 temp;
dir->Tables[tableIndex] = (PageTable*)kmalloc_ap(sizeof(PageTable), &temp);
memset (dir->Tables[tableIndex], 0, 0x1000);
dir->TablesPhysical[tableIndex] = temp | 0x7;
return &dir->Tables[tableIndex]->Pages[addr&0x3ff];
}
else return 0;
}

View File

@ -0,0 +1,75 @@
/*
* memory-vi.c
*
* Created on: Aug 23, 2011
* Author: Tiberiu
*/
#include <memory-add.h>
#include <stdio.h>
/*******************************
* Data *
*******************************/
PageDirectory* CurrentDirectory;
PageDirectory* KernelDirectory;
/*******************************
* Useful routines *
*******************************/
void PagingInitialize(uint32 kernel_used)
{
LogMem("Virtual memory manager initialization started. End of kernel = 0x%x\n", kernel_used);
PageDirectory* kernelPd = (PageDirectory*) kmalloc_a(sizeof(PageDirectory));
memset(kernelPd, 0, sizeof(PageDirectory));
CurrentDirectory = kernelPd;
KernelDirectory = kernelPd;
uint32 i;
for (i = 0; i < kernel_used; i+=0x1000)
MemPhAllocFrame(PagingGetPage(i, 1, kernelPd), 0, 0);
LogMem("Identity mapped first 0x%x bytes.\n", kernel_used);
for (i = KERNEL_HEAP_START; i < KERNEL_HEAP_END; i+=0x1000)
MemPhAllocFrame(PagingGetPage(i, 1, kernelPd), 1, 1);
LogMem("Mapped kernel space.\n");
PagingSwitchPageDirectory (kernelPd);
}
void PagingSwitchPageDirectory (PageDirectory* dir)
{
CurrentDirectory = dir;
asm volatile ("mov %0, %%cr3":: "r"(&dir->TablesPhysical));
LogMem("Switched page directory to 0x%x.\n", (uint32)(&dir->TablesPhysical));
uint32 cr0;
asm volatile ("mov %%cr0, %0": "=r"(cr0));
cr0 |= 0x80000000;
asm volatile ("mov %0, %%cr0":: "r"(cr0));
LogMem("Enabled paging.\n");
}
Page* PagingGetPage(uint32 addr, uint8 make, PageDirectory* dir)
{
addr >>= 12;
uint32 tableIndex = addr >> 10;
if (dir->Tables[tableIndex])
return &dir->Tables[tableIndex]->Pages[addr&0x3ff];
else if (make)
{
uint32 temp;
dir->Tables[tableIndex] = (PageTable*)kmalloc_ap(sizeof(PageTable), &temp);
memset (dir->Tables[tableIndex], 0, 0x1000);
dir->TablesPhysical[tableIndex] = temp | 0x7;
return &dir->Tables[tableIndex]->Pages[addr&0x3ff];
}
else return 0;
}

108
Kernel/memory/mem-phys.c Normal file
View File

@ -0,0 +1,108 @@
/*
* mem-phys.c
*
* Created on: Aug 27, 2011
* Author: Tiberiu
*/
#include <memory-add.h>
uint32* FrameMap;
uint32 TotalFrames;
uint32 TotalMemory;
uint32 UsedFrames;
inline void ConvertIndexToFrame (uint32 index, uint32* address, uint32* offset)
{
*address = (index >> 5);
*offset = index & 0x1f;
}
inline uint32 ConvertFrameToIndex (uint32 address, uint32 offset)
{
return (address<<5) | offset;
}
void MemPhSetFrame (uint32 frame, uint8 value)
{
uint32 addr, off;
ConvertIndexToFrame(frame, &addr, &off);
if (value) {
if ((FrameMap[addr] & (1<<off)) == 0) UsedFrames++;
FrameMap[addr] |= 1<<off;
}
else {
if (FrameMap[addr] & (1<<off)) UsedFrames--;
FrameMap[addr] &= ~(1<<off);
}
}
uint32 MemPhGetFrame (uint32 frame)
{
uint32 addr, off;
ConvertIndexToFrame(frame, &addr, &off);
return FrameMap[addr] & (1<<off);
}
uint32 MemPhFindFreeFrame()
{
uint32 addr, pos;
for (addr = 0; addr < TotalFrames >> 5; addr++)
if (FrameMap[addr] != 0xffffffff)
{
for (pos = 0; (FrameMap[addr] & (1<<pos)) != 0; pos++) ;
return ConvertFrameToIndex(addr, pos);
}
return 0xffffffff;
}
void MemPhAllocFrame(Page* page, uint8 isKernel, uint8 isWriteable)
{
if ((*page & PageFrame) != 0) return;
uint32 free = MemPhFindFreeFrame();
if (free == 0xffffffff) {
Panic("%#Failed allocation free=0x%x page=0x%x\n", ColorRed, free, *page);
return;
}
MemPhSetFrame(free, 1);
*page |= PagePresent;
*page |= (isKernel) ? 0 : PageUser;
*page |= (isWriteable) ? PageWriteable : 0;
*page |= (free<<12) & PageFrame;
}
void MemPhFreeFrame(Page* page)
{
uint32 frame = *page & PageFrame;
if (!frame) return;
MemPhSetFrame(frame, 0);
*page &= ~PageFrame;
}
void MemPhInitialize(uint32 SystemMemoryKb)
{
TotalFrames = SystemMemoryKb >> 2;
TotalMemory = SystemMemoryKb;
FrameMap = (uint32*) kmalloc(sizeof(uint32) * (1 + (TotalFrames>>5)));
memset(FrameMap, 0, sizeof(uint32) * (1 + (TotalFrames>>5)));
LogMem("%#Started physical memory manager ok!, found %ukb\n", ColorLightGreen, SystemMemoryKb);
}
void MemPhReserveFrames (uint32 address, uint32 length)
{
address >>= 12;
length = (length>>12) + ((length & 0xfff) > 0);
uint32 end = address + length;
for (; address < end ; address++)
MemPhSetFrame(address, 1);
}

109
Kernel/memory/mem-phys.c~ Normal file
View File

@ -0,0 +1,109 @@
/*
* mem-phys.c
*
* Created on: Aug 27, 2011
* Author: Tiberiu
*/
#include <memory-add.h>
uint32* FrameMap;
uint32 TotalFrames;
uint32 TotalMemory;
uint32 UsedFrames;
inline void ConvertIndexToFrame (uint32 index, uint32* address, uint32* offset)
{
*address = (index >> 5);
*offset = index & 0x1f;
}
inline uint32 ConvertFrameToIndex (uint32 address, uint32 offset)
{
return (address<<5) | offset;
}
void MemPhSetFrame (uint32 frame, uint8 value)
{
uint32 addr, off;
ConvertIndexToFrame(frame, &addr, &off);
if (value) {
if ((FrameMap[addr] & (1<<off)) == 0) UsedFrames++;
FrameMap[addr] |= 1<<off;
}
else {
if (FrameMap[addr] & (1<<off)) UsedFrames--;
FrameMap[addr] &= ~(1<<off);
}
}
uint32 MemPhGetFrame (uint32 frame)
{
uint32 addr, off;
ConvertIndexToFrame(frame, &addr, &off);
return FrameMap[addr] & (1<<off);
}
uint32 MemPhFindFreeFrame()
{
uint32 addr, pos;
for (addr = 0; addr < TotalFrames >> 5; addr++)
if (FrameMap[addr] != 0xffffffff)
{
for (pos = 0; (FrameMap[addr] & (1<<pos)) != 0; pos++) ;
return ConvertFrameToIndex(addr, pos);
}
return 0xffffffff;
}
void MemPhAllocFrame(Page* page, uint8 isKernel, uint8 isWriteable)
{
if ((*page & PageFrame) != 0) return;
uint32 free = MemPhFindFreeFrame();
if (free == 0xffffffff) {
Panic("%#Failed allocation free=0x%x page=0x%x\n", ColorRed, free, *page);
return;
}
MemPhSetFrame(free, 1);
*page |= PagePresent;
*page |= (isKernel) ? 0 : PageUser;
*page |= (isWriteable) ? PageWriteable : 0;
*page |= (free<<12) & PageFrame;
}
void MemPhFreeFrame(Page* page)
{
uint32 frame = *page & PageFrame;
if (!frame) return;
MemPhSetFrame(frame, 0);
*page &= ~PageFrame;
}
void MemPhInitialize(uint32 SystemMemoryKb)
{
LogMem("Starting physical memory manager...\n");
TotalFrames = SystemMemoryKb >> 2;
TotalMemory = SystemMemoryKb;
FrameMap = (uint32*) kmalloc(sizeof(uint32) * (1 + (TotalFrames>>5)));
memset(FrameMap, 0, sizeof(uint32) * (1 + (TotalFrames>>5)));
LogMem("%#Started physical memory manager ok!, found %ukb\n", ColorLightGreen, SystemMemoryKb);
}
void MemPhReserveFrames (uint32 address, uint32 length)
{
address >>= 12;
length = (length>>12) + ((length & 0xfff) > 0);
uint32 end = address + length;
for (; address < end ; address++)
MemPhSetFrame(address, 1);
}