2011-08-25 17:56:32 +00:00
|
|
|
// Yet another shot at a frame manager... This time, instead of focusing on
|
|
|
|
// something unnecessarily complex, I'll try something simpler: an alloc-only
|
|
|
|
// frame manager. I wasn't even freeing them anyway, and I don't think I'll ever
|
|
|
|
// need that. All the hardcore memory allocation will be done on the kernel heap
|
|
|
|
// anyway.
|
|
|
|
//
|
|
|
|
// tl;dr - want to free a frame? memory leaks ahoy.
|
|
|
|
//
|
|
|
|
// I want this to be as simple as a 'top' pointer, pointing to the next address
|
|
|
|
// of the physical memory that is free. There are two things to watch out for,
|
|
|
|
// though:
|
|
|
|
// o unusable memory regions
|
|
|
|
// o max memory size
|
|
|
|
// We'll solve the first problem by asking system.c whether we can use a provided
|
|
|
|
// region. It used to work the previosu way around, but I'm not going to keep a
|
|
|
|
// list of unusable regions both here and in system.c...
|
|
|
|
// The second problem is solved by also keeping a max memory size, and throwing
|
|
|
|
// a kernel panic when we reach it. It could use an exception system, but since
|
|
|
|
// this code will only be called from low-level system routines, if it actually
|
|
|
|
// happens that we run out of memory... We're probably badly screwed, anyway.
|
|
|
|
|
2011-08-25 18:06:16 +00:00
|
|
|
#include "Tier0/physmem.h"
|
2011-08-25 21:26:24 +00:00
|
|
|
#include "Tier0/system.h"
|
2011-08-25 17:56:32 +00:00
|
|
|
#include "Tier0/kstdio.h"
|
|
|
|
#include "Tier0/panic.h"
|
2011-08-27 17:43:37 +00:00
|
|
|
#include "Tier0/paging.h"
|
2011-08-25 17:56:32 +00:00
|
|
|
|
|
|
|
// The amount of memory in the system, or the top usable pointer.
|
|
|
|
u64 g_MemorySize;
|
|
|
|
// The current pointer to the top of the frame stack.
|
|
|
|
u64 g_TopFrame;
|
|
|
|
|
|
|
|
void physmem_init(u64 MemorySize)
|
|
|
|
{
|
|
|
|
g_TopFrame = 0;
|
|
|
|
g_MemorySize = MemorySize;
|
|
|
|
}
|
|
|
|
|
|
|
|
u64 physmem_allocate_page(void)
|
|
|
|
{
|
2011-08-25 21:26:24 +00:00
|
|
|
u64 NextPageStart = g_TopFrame;
|
|
|
|
|
|
|
|
while (!system_memory_available(NextPageStart, PHYSMEM_PAGE_SIZE))
|
|
|
|
{
|
|
|
|
NextPageStart += PHYSMEM_PAGE_SIZE;
|
|
|
|
|
|
|
|
if (NextPageStart > g_MemorySize)
|
|
|
|
PANIC("Out of memory!");
|
|
|
|
}
|
|
|
|
|
|
|
|
return NextPageStart / PHYSMEM_PAGE_SIZE;
|
2011-08-25 17:56:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
u64 physmem_page_to_physical(u64 Page)
|
|
|
|
{
|
2011-08-25 21:26:24 +00:00
|
|
|
return Page * PHYSMEM_PAGE_SIZE;
|
2011-08-25 17:56:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
u64 physmem_physical_to_page(u64 Physical)
|
|
|
|
{
|
2011-08-25 21:26:24 +00:00
|
|
|
return Physical / PHYSMEM_PAGE_SIZE;
|
2011-08-25 17:56:32 +00:00
|
|
|
}
|
2011-08-27 17:43:37 +00:00
|
|
|
|
|
|
|
void physmem_read(u64 Base, u64 Size, void *Destination)
|
|
|
|
{
|
|
|
|
u8 *DataSource = (u8 *)paging_temp_page_get_virtual();
|
|
|
|
u64 OffsetInSource = Base & 0xFFF;
|
|
|
|
|
|
|
|
u64 PreviousPageBase = Base & ~((u64)0xFFF);
|
|
|
|
paging_temp_page_set_physical(PreviousPageBase);
|
|
|
|
for (u64 i = 0; i < Size; i++)
|
|
|
|
{
|
|
|
|
u64 PageBase = (Base + i) & ~((u64)0xFFF);
|
|
|
|
|
|
|
|
if (PageBase != PreviousPageBase)
|
|
|
|
paging_temp_page_set_physical(PageBase);
|
|
|
|
|
|
|
|
PreviousPageBase = PageBase;
|
|
|
|
|
|
|
|
*((u8 *)Destination + i) = DataSource[OffsetInSource % 4096];
|
|
|
|
OffsetInSource++;
|
|
|
|
}
|
|
|
|
}
|