#include <l4/thread.h>
#include <l4io.h>
#include <l4/sigma0.h>
#include <idl4glue.h>
#include <if/ifsyscall.h>
#include <sdi/panic.h>
#include <sdi/util.h>
#include <string.h>
#include "pager-server.h"
#include "RangeClassifier.h"
#include "BuddySystem.h"
#include "PageMappingList.h"
#include "TaskList.h"
#include "pdebug.h"
static L4_KernelInterfacePage_t *KIP;
static const L4_Word_t kipmin_pagesize = 10;
static inline L4_Word_t page_start(L4_Word_t page)
{
return page & ~((1UL << kipmin_pagesize) - 1);
}
static inline L4_Word_t page_end(L4_Word_t page)
{
return (page + ((1UL << kipmin_pagesize) - 1)) & ~((1UL << kipmin_pagesize) - 1);
}
enum { MT_INVALID=0, MT_CONVENTIONAL, MT_SPECIAL, MT_RESERVED };
static class RangeClassifier rangeclassifier(MT_INVALID);
static void rangeclassifier_init()
{
L4_MemoryDesc_t *md;
for (L4_Word_t n = 0; (md = L4_MemoryDesc(KIP, n)); n++)
{
if (L4_IsVirtual(md)) continue;
L4_Word_t low = page_start(L4_MemoryDescLow(md));
L4_Word_t high = page_end(L4_MemoryDescHigh(md)) - 1;
if ((L4_MemoryDescType(md) &0xf) == L4_BootLoaderSpecificMemoryType ||
(L4_MemoryDescType(md) &0xf) == L4_ArchitectureSpecificMemoryType)
{
rangeclassifier.set(low, high, MT_SPECIAL);
}
else
{
switch (L4_MemoryDescType(md))
{
case L4_UndefinedMemoryType:
break;
case L4_ConventionalMemoryType:
rangeclassifier.set(low, high, MT_CONVENTIONAL);
break;
case L4_ReservedMemoryType:
rangeclassifier.set(low, high, MT_RESERVED);
break;
case L4_DedicatedMemoryType:
rangeclassifier.set(low, high, MT_SPECIAL);
break;
case L4_SharedMemoryType:
rangeclassifier.set(low, high, MT_SPECIAL);
break;
default:
printf("pager: unknown memory type 0x%x\n", (int)L4_MemoryDescType(md));
break;
}
}
}
}
enum { VMA_SEGFAULT=0, VMA_ANONYMOUS, VMA_PROGRAM };
static class RangeClassifier vmaddressclass(VMA_SEGFAULT);
static void vmaddressclass_init()
{
vmaddressclass.set(0x02010000, 0x0202ffff, VMA_ANONYMOUS);
vmaddressclass.set(0x08408000, 0x90000000, VMA_PROGRAM);
vmaddressclass.set(0xb8000000, 0xbfffffff, VMA_ANONYMOUS);
}
typedef SlabAllocator<PageFreeEntry> PageFreeAllocator;
static PageFreeAllocator::Page pagefreeslabpages[32];
static PageFreeAllocator::Pool pagefreeslaballoc (pagefreeslabpages, 32);
static class BuddySystem buddysystem (pagefreeslaballoc);
typedef SlabAllocator<PageMappingEntry> PageMappingAllocator;
static PageMappingAllocator::Page pagemappingslabpages[8];
static PageMappingAllocator::Pool pagemappingslaballoc (pagemappingslabpages, 8);
typedef SlabAllocator<TaskEntry> TaskAllocator;
static TaskAllocator::Page tasklistslabpages[4];
static TaskAllocator::Pool tasklistslaballoc (tasklistslabpages, 4);
static class TaskList tasklist (&tasklistslaballoc);
static L4_ThreadId_t sigma0id;
static L4_ThreadId_t getSigma0Id()
{
return L4_GlobalId(KIP->ThreadInfo.X.UserBase, 1);
}
extern L4_ThreadId_t syscallServerId;
#include "pager-ia32.h"
static inline void zeroFpage(L4_Fpage_t fp)
{
pager_memset_long((void*)L4_Address(fp), 0, L4_Size(fp));
}
static void* slaballocator_callback(unsigned int pagesize)
{
L4_Fpage_t fp = buddysystem.allocate(pagesize);
if (L4_IsNilFpage(fp)) return NULL;
zeroFpage(fp);
return (void*)L4_Address(fp);
}
#define KB(x) (x*1024)
#define MB(x) (x*1024*1024)
#define GB(x) (x*1024*1024*1024)
int memgrab()
{
printf ("Hello world, I will now allocate all available memory.\n\n");
L4_Word_t tsize = 0;
for (L4_Word_t s = sizeof (L4_Word_t) * 8 - 1; s >= 10; s--)
{
L4_Fpage_t f;
int n = -1;
do {
f = L4_Sigma0_GetAny (L4_nilthread, s, L4_CompleteAddressSpace);
n++;
} while (! L4_IsNilFpage (f));
L4_Word_t size = n * (1UL << s);
tsize += size;
if (n)
printf ("Allocated %d pages of %3ld%cB (log2size %2ld) [%ld%cB]\n",
n,
s >= 30 ? 1UL << (s-30) :
s >= 20 ? 1UL << (s-20) : 1UL << (s-10),
s >= 30 ? 'G' : s >= 20 ? 'M' : 'K',
s,
size >= GB(1) ? size/GB(1) :
size >= MB(1) ? size/MB(1) : size/KB(1),
size >= GB(1) ? 'G' : size >= MB(1) ? 'M' : 'K');
}
printf ("\nTotal memory: %ld.%ldGB | %ld.%ldMB | %ldKB\n",
tsize / GB(1), ((tsize * 100) / GB(1)) % 100,
tsize / MB(1), ((tsize * 100) / MB(1)) % 100,
tsize / KB(1));
for (;;);
return 0;
}
#include "pager-impl.h"
void pager_main()
{
printf("Pager startup. Allocating all available memory from sigma0.\n");
KIP = (L4_KernelInterfacePage_t*)L4_GetKernelInterface();
rangeclassifier_init();
vmaddressclass_init();
pagefreeslaballoc.setAllocCallback(slaballocator_callback);
pagemappingslaballoc.setAllocCallback(slaballocator_callback);
tasklistslaballoc.setAllocCallback(slaballocator_callback);
sigma0id = getSigma0Id();
for (unsigned int pagelog2 = 22; pagelog2 >= 12; pagelog2--)
{
L4_Fpage_t fp;
while(1)
{
fp = L4_Sigma0_GetAny(sigma0id, pagelog2, L4_CompleteAddressSpace);
int mt = rangeclassifier.get(L4_Address(fp));
if (mt != 1) {
printf("Got special page: 0x%08lx - size %ld - type %d\n",
L4_Address(fp), L4_Size(fp), mt);
}
if (L4_IsNilFpage(fp)) break;
buddysystem.insert(fp);
}
}
buddysystem.test();
printf("pager: available anonymous memory %lu bytes\n", buddysystem.available());
printf("pager: entering idl4 loop\n");
pager_server();
panic("pager: idl4 loop terminated!");
while(1) ;
}