[????] BUILD 0.1.1.??? DATE 9/0?/2011 AT ?:?? ??
==================================================== Mainly changed: Tasking + Implemented multitasking
This commit is contained in:
		@@ -6,9 +6,6 @@
 | 
			
		||||
#define MEMHEAP_INDEX_SIZE 0x20000
 | 
			
		||||
#define MEMHEAP_MINIM_SIZE 0x70000
 | 
			
		||||
 | 
			
		||||
#define FlagsKernel 1
 | 
			
		||||
#define FlagsWriteable 2
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
	uint32 Magic;
 | 
			
		||||
@@ -98,30 +95,31 @@ MemHeap* MemHeapCreate(uint32 start, uint32 end, uint32 max, uint8 flags)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void MemHeapExpand(uint32 newsz, MemHeap* heap, PageDirectory* pd)
 | 
			
		||||
uint32 MemHeapExpand(uint32 newsz, MemHeap* heap, PageDirectory* pd)
 | 
			
		||||
{
 | 
			
		||||
	if (newsz <= heap->EndAddress - heap->StartAddress) return;
 | 
			
		||||
	if (newsz <= heap->EndAddress - heap->StartAddress) return heap->EndAddress - heap->StartAddress;
 | 
			
		||||
 | 
			
		||||
	if (newsz & 0xfff) newsz = (newsz & 0xfffff000) + 0x1000;
 | 
			
		||||
	if (newsz + heap->StartAddress >= heap->MaxAddress) return;
 | 
			
		||||
	if (newsz + heap->StartAddress >= heap->MaxAddress) return heap->EndAddress - heap->StartAddress;
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
	for (i = heap->EndAddress; i < heap->StartAddress + newsz; i+=0x1000)
 | 
			
		||||
		PagingMapPage(MemPhAllocateBlock(), i, heap->Flags, pd);
 | 
			
		||||
 | 
			
		||||
	heap->EndAddress = heap->StartAddress + newsz;
 | 
			
		||||
	return newsz;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32 MemHeapContract(uint32 newsz, MemHeap* heap, PageDirectory* pd)
 | 
			
		||||
{
 | 
			
		||||
	if (newsz >= heap->EndAddress - heap->StartAddress) return 0;
 | 
			
		||||
	if (newsz >= heap->EndAddress - heap->StartAddress) return heap->EndAddress - heap->StartAddress;
 | 
			
		||||
 | 
			
		||||
	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));
 | 
			
		||||
	for (i = heap->EndAddress - 0x1000; i > heap->StartAddress + newsz; i-=0x1000)
 | 
			
		||||
		PagingUnmapPage(i, pd);
 | 
			
		||||
 | 
			
		||||
	heap->EndAddress = heap->StartAddress + newsz;
 | 
			
		||||
	return newsz;
 | 
			
		||||
 
 | 
			
		||||
@@ -6,69 +6,123 @@
 | 
			
		||||
 */
 | 
			
		||||
#include <memory-add.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
/*******************************
 | 
			
		||||
 * Data						   *
 | 
			
		||||
 *******************************/
 | 
			
		||||
PageDirectory* CurrentDirectory;
 | 
			
		||||
PageDirectory* KernelDirectory;
 | 
			
		||||
 | 
			
		||||
/*******************************
 | 
			
		||||
 * Useful routines			   *
 | 
			
		||||
 *******************************/
 | 
			
		||||
void PagingInitialize(uint32 kernel_used)
 | 
			
		||||
void PagingEnable()
 | 
			
		||||
{
 | 
			
		||||
	Log("Mem", "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);
 | 
			
		||||
 | 
			
		||||
	Log("Mem", "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);
 | 
			
		||||
 | 
			
		||||
	Log("Mem", "Mapped kernel space.\n");
 | 
			
		||||
 | 
			
		||||
	PagingSwitchPageDirectory (kernelPd);
 | 
			
		||||
	uint32 tmp;
 | 
			
		||||
	asm volatile ("mov %%cr0, %0" : "=r"(tmp));
 | 
			
		||||
	tmp |= 0x80000000;
 | 
			
		||||
	asm volatile ("mov %0, %%cr0" : : "r"(tmp));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PagingSwitchPageDirectory (PageDirectory* dir)
 | 
			
		||||
void PagingDisable()
 | 
			
		||||
{
 | 
			
		||||
	uint32 tmp;
 | 
			
		||||
	asm volatile ("mov %%cr0, %0" : "=r"(tmp));
 | 
			
		||||
	tmp &= 0x7FFFFFFF;
 | 
			
		||||
	asm volatile ("mov %0, %%cr0" : : "r"(tmp));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PagingSwitchDirectory(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));
 | 
			
		||||
 | 
			
		||||
	Log("Mem", "Enabled paging.\n");
 | 
			
		||||
	asm volatile ("mov %0, %%cr3" : : "r"(dir->PhysicalAddr));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Page* PagingGetPage(uint32 addr, uint8 make, PageDirectory* dir)
 | 
			
		||||
void PagingFlushTlb ()
 | 
			
		||||
{
 | 
			
		||||
	addr >>= 12;
 | 
			
		||||
	uint32 tmp;
 | 
			
		||||
	asm volatile ("mov %%cr3, %0" : "=r"(tmp));
 | 
			
		||||
	asm volatile ("mov %0, %%cr3" : : "r" (tmp));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	uint32 tableIndex = addr >> 10;
 | 
			
		||||
void PagingInitialize(uint32* kernelEnd)
 | 
			
		||||
{
 | 
			
		||||
	// Create the kernel page directory
 | 
			
		||||
	PageDirectory* kdir = kmalloc_a(sizeof(PageDirectory));
 | 
			
		||||
	memset(kdir, 0, sizeof(PageDirectory));
 | 
			
		||||
 | 
			
		||||
	if (dir->Tables[tableIndex])
 | 
			
		||||
		return &dir->Tables[tableIndex]->Pages[addr&0x3ff];
 | 
			
		||||
	KernelDirectory = kdir;
 | 
			
		||||
 | 
			
		||||
	else if (make)
 | 
			
		||||
	// Set up physical address of PDEs.
 | 
			
		||||
	kdir->PhysicalAddr = (uint32) kdir->TablesPhysical;
 | 
			
		||||
 | 
			
		||||
	// Identity map the kernel
 | 
			
		||||
	uint32 i = 0;
 | 
			
		||||
	while (i <= *kernelEnd + 1024)
 | 
			
		||||
	{
 | 
			
		||||
		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];
 | 
			
		||||
		PagingMapPage(i, i, PageWriteable, kdir);
 | 
			
		||||
		i += 0x1000;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	else return 0;
 | 
			
		||||
	// Reserve the identity mapped blocks
 | 
			
		||||
	MemPhReserveBlocks(0x0, *kernelEnd);
 | 
			
		||||
 | 
			
		||||
	PagingSwitchDirectory(kdir);
 | 
			
		||||
	PagingEnable();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PagingMapPage (uint32 phys, uint32 virt, uint32 flags, PageDirectory* pd)
 | 
			
		||||
{
 | 
			
		||||
	// Calculate pde and pte
 | 
			
		||||
	uint32 pde = virt >> 22;
 | 
			
		||||
	uint32 pte = (virt >> 12) & 0x3ff;
 | 
			
		||||
 | 
			
		||||
	phys &= 0xFFFFF000;	// Make sure address is page aligned
 | 
			
		||||
	flags &= 0xFFF;		// Make sure flags don't overflow
 | 
			
		||||
 | 
			
		||||
	// See if page table exists
 | 
			
		||||
	if (!pd->Tables[pde])
 | 
			
		||||
	{
 | 
			
		||||
		// No? allocate it
 | 
			
		||||
		uint32 ph;
 | 
			
		||||
		PageTable* pt = kmalloc_ap(sizeof(PageTable), &ph);
 | 
			
		||||
		memset(pt, 0, sizeof(PageTable));
 | 
			
		||||
 | 
			
		||||
		pd->Tables[pde] = pt;
 | 
			
		||||
		pd->TablesPhysical[pde] = ph | 0x7;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Set up the page
 | 
			
		||||
	pd->Tables[pde]->Pages[pte] = phys | flags | 0x1; // Present, and flags
 | 
			
		||||
 | 
			
		||||
	// If it is the current directory, flush the tlb to notice the change
 | 
			
		||||
	if (pd == CurrentDirectory) PagingFlushTlb();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PagingUnmapPage (uint32 virt, PageDirectory* pd)
 | 
			
		||||
{
 | 
			
		||||
	// Calculate pde and pte
 | 
			
		||||
	uint32 pde = virt >> 22;
 | 
			
		||||
	uint32 pte = (virt >> 12) & 0x3ff;
 | 
			
		||||
 | 
			
		||||
	if (!pd->Tables[pde] || !pd->Tables[pde]->Pages[pte]) return;
 | 
			
		||||
 | 
			
		||||
	// Get physical address
 | 
			
		||||
	uint32 phys = pd->Tables[pde]->Pages[pte] & PageFrame;
 | 
			
		||||
 | 
			
		||||
	// Free page
 | 
			
		||||
	pd->Tables[pde]->Pages[pte] = 0;
 | 
			
		||||
	MemPhFreeBlock(phys);
 | 
			
		||||
 | 
			
		||||
	// If it is the current directory, flush the tlb to notice the change
 | 
			
		||||
	if (pd == CurrentDirectory) PagingFlushTlb();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32 PagingGetPhysical (uint32 virt, PageDirectory* pd)
 | 
			
		||||
{
 | 
			
		||||
	// Calculate pde and pte
 | 
			
		||||
	uint32 pde = virt >> 22;
 | 
			
		||||
	uint32 pte = (virt >> 12) & 0x3ff;
 | 
			
		||||
 | 
			
		||||
	// Not mapped
 | 
			
		||||
	if (!pd->Tables[pde] || !pd->Tables[pde]->Pages[pte]) return NULL;
 | 
			
		||||
 | 
			
		||||
	return (pd->Tables[pde]->Pages[pte] & PageFrame);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,103 +6,89 @@
 | 
			
		||||
 */
 | 
			
		||||
#include <memory-add.h>
 | 
			
		||||
 | 
			
		||||
uint32* FrameMap;
 | 
			
		||||
uint32 TotalFrames;
 | 
			
		||||
uint32* BlockMap;
 | 
			
		||||
uint32 TotalBlocks;
 | 
			
		||||
uint32 TotalMemory;
 | 
			
		||||
uint32 UsedFrames;
 | 
			
		||||
uint32 UsedBlocks;
 | 
			
		||||
 | 
			
		||||
inline void ConvertIndexToFrame (uint32 index, uint32* address, uint32* offset)
 | 
			
		||||
inline void ConvertIndexToBlock (uint32 index, uint32* address, uint32* offset)
 | 
			
		||||
{
 | 
			
		||||
	*address = (index >> 5);
 | 
			
		||||
	*offset = index & 0x1f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline uint32 ConvertFrameToIndex (uint32 address, uint32 offset)
 | 
			
		||||
inline uint32 ConvertBlockToIndex (uint32 address, uint32 offset)
 | 
			
		||||
{
 | 
			
		||||
	return (address<<5) | offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MemPhSetFrame (uint32 frame, uint8 value)
 | 
			
		||||
void MemPhSetBlock (uint32 Block, uint8 value)
 | 
			
		||||
{
 | 
			
		||||
	uint32 addr, off;
 | 
			
		||||
	ConvertIndexToFrame(frame, &addr, &off);
 | 
			
		||||
	ConvertIndexToBlock(Block, &addr, &off);
 | 
			
		||||
 | 
			
		||||
	if (value) {
 | 
			
		||||
		if ((FrameMap[addr] & (1<<off)) == 0) UsedFrames++;
 | 
			
		||||
		FrameMap[addr] |= 1<<off;
 | 
			
		||||
		if ((BlockMap[addr] & (1<<off)) == 0) UsedBlocks++;
 | 
			
		||||
		BlockMap[addr] |= 1<<off;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	else {
 | 
			
		||||
		if (FrameMap[addr] & (1<<off)) UsedFrames--;
 | 
			
		||||
		FrameMap[addr] &= ~(1<<off);	
 | 
			
		||||
		if (BlockMap[addr] & (1<<off)) UsedBlocks--;
 | 
			
		||||
		BlockMap[addr] &= ~(1<<off);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32 MemPhGetFrame (uint32 frame)
 | 
			
		||||
uint32 MemPhGetBlock (uint32 Block)
 | 
			
		||||
{
 | 
			
		||||
	uint32 addr, off;
 | 
			
		||||
	ConvertIndexToFrame(frame, &addr, &off);
 | 
			
		||||
	ConvertIndexToBlock(Block, &addr, &off);
 | 
			
		||||
 | 
			
		||||
	return FrameMap[addr] & (1<<off);
 | 
			
		||||
	return BlockMap[addr] & (1<<off);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32 MemPhFindFreeFrame()
 | 
			
		||||
uint32 MemPhAllocateBlock()
 | 
			
		||||
{
 | 
			
		||||
	uint32 addr, pos;
 | 
			
		||||
 | 
			
		||||
	for (addr = 0; addr < TotalFrames >> 5; addr++)
 | 
			
		||||
		if (FrameMap[addr] != 0xffffffff)
 | 
			
		||||
	for (addr = 0; addr < TotalBlocks >> 5; addr++)
 | 
			
		||||
		if (BlockMap[addr] != 0xffffffff)
 | 
			
		||||
		{
 | 
			
		||||
			for (pos = 0; (FrameMap[addr] & (1<<pos)) != 0; pos++) ;
 | 
			
		||||
			for (pos = 0; (BlockMap[addr] & (1<<pos)) != 0; pos++) ;
 | 
			
		||||
 | 
			
		||||
			return ConvertFrameToIndex(addr, pos);
 | 
			
		||||
			uint32 index = ConvertBlockToIndex(addr, pos);
 | 
			
		||||
			MemPhSetBlock(index, 1);
 | 
			
		||||
 | 
			
		||||
			// Return address
 | 
			
		||||
			return (index<<12);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	return 0xffffffff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MemPhAllocFrame(Page* page, uint8 isKernel, uint8 isWriteable)
 | 
			
		||||
void MemPhFreeBlock(uint32 addr)
 | 
			
		||||
{
 | 
			
		||||
	if ((*page & PageFrame) != 0) return;
 | 
			
		||||
	uint32 Block = addr >> 12;
 | 
			
		||||
	if (!Block) return;
 | 
			
		||||
 | 
			
		||||
	uint32 free = MemPhFindFreeFrame();
 | 
			
		||||
	if (free == 0xffffffff) {
 | 
			
		||||
		Panic("Mem", "%#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;
 | 
			
		||||
	MemPhSetBlock(Block, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MemPhInitialize(uint32 SystemMemoryKb)
 | 
			
		||||
{
 | 
			
		||||
	TotalFrames = SystemMemoryKb >> 2;
 | 
			
		||||
	TotalBlocks = SystemMemoryKb >> 2;
 | 
			
		||||
	TotalMemory = SystemMemoryKb;
 | 
			
		||||
 | 
			
		||||
	FrameMap = (uint32*) kmalloc(sizeof(uint32) * (1 + (TotalFrames>>5)));
 | 
			
		||||
	memset(FrameMap, 0,  sizeof(uint32) * (1 + (TotalFrames>>5)));
 | 
			
		||||
	BlockMap = (uint32*) kmalloc(sizeof(uint32) * (1 + (TotalBlocks>>5)));
 | 
			
		||||
	memset(BlockMap, 0,  sizeof(uint32) * (1 + (TotalBlocks>>5)));
 | 
			
		||||
	Log("Mem", "%#Started physical memory manager ok!, found %ukb\n", ColorLightGreen, SystemMemoryKb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MemPhReserveFrames (uint32 address, uint32 length)
 | 
			
		||||
void MemPhReserveBlocks (uint32 address, uint32 length)
 | 
			
		||||
{
 | 
			
		||||
	address >>= 12;
 | 
			
		||||
	length = (length>>12) + ((length & 0xfff) > 0);
 | 
			
		||||
	uint32 end = address + length;
 | 
			
		||||
 | 
			
		||||
	for (; address < end ; address++)
 | 
			
		||||
		MemPhSetFrame(address, 1);
 | 
			
		||||
		MemPhSetBlock(address, 1);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user