summaryrefslogtreecommitdiffstats
path: root/src/kernel
diff options
context:
space:
mode:
authorPatrick Williams <iawillia@us.ibm.com>2010-05-20 19:16:30 -0500
committerPatrick Williams <iawillia@us.ibm.com>2010-05-20 19:16:30 -0500
commitd9d7e6c7247aaf5d2721d08a365e9c51ec18c870 (patch)
tree16f882f7d77eb293ac0417b43bb5680ee149efbd /src/kernel
parentd5a43e2fa43f8178aaa7ca67a9615d3ab4e68dbb (diff)
downloadtalos-hostboot-d9d7e6c7247aaf5d2721d08a365e9c51ec18c870.tar.gz
talos-hostboot-d9d7e6c7247aaf5d2721d08a365e9c51ec18c870.zip
Create page manager.
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/kernel.C18
-rw-r--r--src/kernel/makefile2
-rw-r--r--src/kernel/pagemgr.C124
3 files changed, 138 insertions, 6 deletions
diff --git a/src/kernel/kernel.C b/src/kernel/kernel.C
index d44095719..2ce5f3e43 100644
--- a/src/kernel/kernel.C
+++ b/src/kernel/kernel.C
@@ -1,11 +1,13 @@
#include <stdint.h>
#include <kernel/console.H>
+#include <kernel/pagemgr.H>
#include <util/singleton.H>
class Kernel
{
public:
void cppBootstrap();
+ void memBootstrap();
protected:
Kernel() {};
@@ -13,10 +15,11 @@ class Kernel
int main()
{
- printk("Booting Chenoo kernel...\n");
+ printk("Booting %s kernel...\n\n", "Chenoo");
Kernel& kernel = Singleton<Kernel>::instance();
kernel.cppBootstrap();
+ kernel.memBootstrap();
while(1);
return 0;
@@ -25,13 +28,18 @@ int main()
void Kernel::cppBootstrap()
{
// Call default constructors for any static objects.
- extern void (*ctor_start)();
- extern void (*ctor_end)();
- void(**ctors)() = &ctor_start;
- while(ctors != &ctor_end)
+ extern void (*ctor_start_address)();
+ extern void (*ctor_end_address)();
+ void(**ctors)() = &ctor_start_address;
+ while(ctors != &ctor_end_address)
{
(*ctors)();
ctors++;
}
}
+void Kernel::memBootstrap()
+{
+ PageManager::freePage(PageManager::allocatePage());
+}
+
diff --git a/src/kernel/makefile b/src/kernel/makefile
index 1047de456..c4cf3c421 100644
--- a/src/kernel/makefile
+++ b/src/kernel/makefile
@@ -1,7 +1,7 @@
OBJDIR = ../../obj
include ../../config.mk
-OBJS = start.o kernel.o console.o
+OBJS = start.o kernel.o console.o pagemgr.o
OBJECTS = $(addprefix ${OBJDIR}/, ${OBJS})
all: ${OBJECTS}
diff --git a/src/kernel/pagemgr.C b/src/kernel/pagemgr.C
new file mode 100644
index 000000000..e5d9ec321
--- /dev/null
+++ b/src/kernel/pagemgr.C
@@ -0,0 +1,124 @@
+#include <kernel/pagemgr.H>
+#include <util/singleton.H>
+#include <kernel/console.H>
+
+void* PageManager::allocatePage(size_t n)
+{
+ PageManager& pmgr = Singleton<PageManager>::instance();
+ return pmgr._allocatePage(n);
+}
+
+void PageManager::freePage(void* p, size_t n)
+{
+ PageManager& pmgr = Singleton<PageManager>::instance();
+ return pmgr._freePage(p, n);
+}
+
+PageManager::PageManager()
+{
+ // NOTE: This will need to change once we support loading modules.
+
+ // Determine first page of un-allocated memory.
+ extern void* end_load_address;
+ uint64_t addr = (uint64_t)&end_load_address;
+ if (0 != (addr % PAGESIZE))
+ addr = (addr - (addr % PAGESIZE)) + PAGESIZE;
+
+ // Determine number of pages available.
+ page_t* page = (page_t*)((void*) addr);
+ size_t length = (MEMLEN - addr) / PAGESIZE;
+
+ // Display.
+ printk("Initializing PageManager with %zd pages starting at %llx...",
+ length,
+ (uint64_t)page);
+
+ // Clear page buckets.
+ for(int i = 0; i < BUCKETS; i++)
+ first_page[i] = NULL;
+
+ // Allocate pages to buckets.
+ size_t page_length = BUCKETS-1;
+ while(length > 0)
+ {
+ while (length < (1 << page_length))
+ page_length--;
+
+ page->next_page = first_page[page_length];
+ first_page[page_length] = page;
+ page = (page_t*)((uint64_t)page + (1 << page_length)*PAGESIZE);
+ length -= (1 << page_length);
+ }
+
+ printk("done\n");
+}
+
+void* PageManager::_allocatePage(size_t n)
+{
+ int which_bucket = 0;
+ while (n > (1 << which_bucket)) which_bucket++;
+
+ int retries = 0;
+ page_t* page = (page_t*)NULL;
+ while ((page == NULL) && (retries < 3))
+ {
+ page = pop_bucket(which_bucket);
+ retries++;
+ }
+
+ if (NULL == page)
+ {
+ // TODO: Add abort instead.
+ printk("Insufficient memory for allocation of size %zd!\n", n);
+ while(1);
+ }
+
+ return page;
+}
+
+void PageManager::_freePage(void* p, size_t n)
+{
+ if ((NULL == p) || (0 == n)) return;
+
+ int which_bucket = 0;
+ while (n > (1 << which_bucket)) which_bucket++;
+
+ push_bucket((page_t*)p, which_bucket);
+ return;
+}
+
+PageManager::page_t* PageManager::pop_bucket(size_t n)
+{
+ if (n >= BUCKETS) return NULL;
+
+ page_t* p = first_page[n];
+
+ if (NULL == p)
+ {
+ // Couldn't allocate from the correct size bucket, so split up an
+ // item from the next sized bucket.
+ p = pop_bucket(n+1);
+ push_bucket((page_t*) (((uint64_t)p) + (PAGESIZE * (1 << n))),
+ n);
+ }
+ else
+ {
+ // This bucket appears to have items in it, allocate one.
+ if (!__sync_bool_compare_and_swap(&first_page[n],
+ p,
+ p->next_page))
+ return pop_bucket(n);
+ }
+ return p;
+}
+
+void PageManager::push_bucket(page_t* p, size_t n)
+{
+ if (n >= BUCKETS) return;
+
+ p->next_page = first_page[n];
+ if (!__sync_bool_compare_and_swap(&first_page[n],
+ p->next_page,
+ p))
+ push_bucket(p, n);
+}
OpenPOWER on IntegriCloud