From 0a157437c294f2f3a244e0125e673b3791529052 Mon Sep 17 00:00:00 2001 From: Patrick Williams Date: Fri, 2 Jul 2010 13:25:57 -0500 Subject: Start virtual memory management. --- src/include/kernel/pagemgr.H | 5 +- src/include/kernel/taskmgr.H | 4 +- src/include/kernel/types.h | 3 +- src/include/kernel/vmmmgr.H | 124 +++++++++++++++++++++++++++++++++++++++++++ src/include/sys/task.h | 3 +- src/kernel/kernel.C | 2 + src/kernel/makefile | 2 +- src/kernel/vmmmgr.C | 65 +++++++++++++++++++++++ src/lib/syscall_task.C | 2 +- 9 files changed, 202 insertions(+), 8 deletions(-) create mode 100644 src/include/kernel/vmmmgr.H create mode 100644 src/kernel/vmmmgr.C (limited to 'src') diff --git a/src/include/kernel/pagemgr.H b/src/include/kernel/pagemgr.H index fded2c6c1..95d7bf21c 100644 --- a/src/include/kernel/pagemgr.H +++ b/src/include/kernel/pagemgr.H @@ -3,6 +3,7 @@ #include #include +#include /** @class PageManager * @brief Manages the allocation of memory pages. @@ -18,8 +19,8 @@ class PageManager enum { - PAGESIZE = 4096, - MEMLEN = 8 * 1024 * 1024, + PAGESIZE = VmmManager::PAGESIZE, + MEMLEN = VmmManager::HTABORG, BUCKETS = 16, }; diff --git a/src/include/kernel/taskmgr.H b/src/include/kernel/taskmgr.H index 3cf036f37..b34a1d3b1 100644 --- a/src/include/kernel/taskmgr.H +++ b/src/include/kernel/taskmgr.H @@ -3,6 +3,7 @@ #include #include +#include class TaskManager { @@ -21,7 +22,8 @@ class TaskManager static task_t* createIdleTask(); private: - tid_t getNextTid() { return iv_nextTid.next(); }; + tid_t getNextTid() + { return iv_nextTid.next() + VmmManager::FirstPid; }; Util::Lockfree::Counter iv_nextTid; static void idleTaskLoop(void*); diff --git a/src/include/kernel/types.h b/src/include/kernel/types.h index c994308c2..056486b4a 100644 --- a/src/include/kernel/types.h +++ b/src/include/kernel/types.h @@ -3,7 +3,8 @@ #include -typedef uint64_t tid_t; +typedef uint16_t tid_t; // This is 16-bit for the VMM mapping of + // stacks. See VmmManager. struct task_t; typedef uint64_t cpuid_t; diff --git a/src/include/kernel/vmmmgr.H b/src/include/kernel/vmmmgr.H new file mode 100644 index 000000000..18d1f0862 --- /dev/null +++ b/src/include/kernel/vmmmgr.H @@ -0,0 +1,124 @@ +#ifndef __KERNEL_VMMMGR_H +#define __KERNEL_VMMMGR_H + +#include + +class VmmManager +{ + public: + struct pte_t + { + uint64_t a,b; + }; + + enum VMM_CONSTS + { + FULL_MEM_SIZE = 8 * 1024 * 1024, + PAGESIZE = 4096, + + PTSIZE = (1 << 18), + PTEG_SIZE = 8, + PTEG_COUNT = (PTSIZE / sizeof(pte_t)) / PTEG_SIZE, + + HTABORG = (FULL_MEM_SIZE - PTSIZE), + }; + + enum ACCESS_TYPES + { + NO_USER_ACCESS, + NORMAL_ACCESS, + CI_ACCESS, + }; + + enum PID_ALLOCATIONS + { + LinearSpace = 0, + MMIOSpace = 1, + FirstPid, + }; + + static void init(); + + protected: + VmmManager(); + ~VmmManager() {}; + + private: + void initSLB(); + void initPTEs(); + void initSDR1(); + + static pte_t* page_table; + + inline pte_t& getPte(uint64_t pteg, uint64_t idx) + { + return page_table[pteg * PTEG_SIZE + idx]; + } + + inline void defaultPte(pte_t& pte) + { + pte.a = 0x4000000000000000; // B = 01 (1TB). + pte.b = 0x0; + } + + inline void setValid(bool valid, pte_t& pte) + { + // Adding a page requires EIEIO to ensure update of PTE prior + // to making valid and PTESYNC afterwards. + // Removing a page just requires PTESYNC afterwards. + if (valid) + { + asm volatile("eieio" ::: "memory"); + } + + pte.a &= ~0x01; + pte.a |= (valid ? 0x1 : 0x0); + + asm volatile("ptesync" ::: "memory"); + } + + inline bool isValid(pte_t& pte) + { + return ((pte.a & 0x01) == 0x01); + } + + inline void setTid(tid_t tid, pte_t& pte) + { + pte.a &= 0xC00000000000007F; + pte.a |= ((uint64_t) tid) << 7; + } + + inline tid_t getTid(pte_t& pte) + { + return (tid_t) ((pte.a & 0xC00000000000007F) >> 7); + } + + inline void setAccess(ACCESS_TYPES t, pte_t& pte) + { + uint64_t pteMask = ~0x800000000000007B; + pte.b &= pteMask; + pte.b |= (NO_USER_ACCESS == t ? 0x0000000000000010 : + (NORMAL_ACCESS == t ? 0x0000000000000012 : + (CI_ACCESS == t ? 0x000000000000002A : + 0x0))); + } + + inline void setPage(uint64_t page, pte_t& pte) + { + pte.b &= ~0x0FFFFFFFFFFFF000; + pte.b |= page << 12; + } + + inline uint64_t getPage(pte_t& pte) + { + return (pte.b & 0x0FFFFFFFFFFFF000) >> 12; + } + + inline void pteSync() + { + asm volatile("ptesync" ::: "memory"); + } + +}; + +#endif diff --git a/src/include/sys/task.h b/src/include/sys/task.h index fa9838723..e50c6daee 100644 --- a/src/include/sys/task.h +++ b/src/include/sys/task.h @@ -2,14 +2,13 @@ #define __SYS_TASK_H #include +#include #ifdef __cplusplus extern "C" { #endif -typedef uint64_t tid_t; - void task_yield(); tid_t task_create(void(*)(void*), void*); void task_end(); diff --git a/src/kernel/kernel.C b/src/kernel/kernel.C index b071d9999..00f3002e5 100644 --- a/src/kernel/kernel.C +++ b/src/kernel/kernel.C @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -59,6 +60,7 @@ void Kernel::memBootstrap() { PageManager::init(); HeapManager::init(); + VmmManager::init(); } void Kernel::cpuBootstrap() diff --git a/src/kernel/makefile b/src/kernel/makefile index 4bdc0d02d..7d33a056e 100644 --- a/src/kernel/makefile +++ b/src/kernel/makefile @@ -2,7 +2,7 @@ OBJDIR = ../../obj include ../../config.mk OBJS = start.o kernel.o console.o pagemgr.o heapmgr.o taskmgr.o cpumgr.o -OBJS += syscall.o scheduler.o spinlock.o exception.o +OBJS += syscall.o scheduler.o spinlock.o exception.o vmmmgr.o OBJECTS = $(addprefix ${OBJDIR}/, ${OBJS}) all: ${OBJECTS} diff --git a/src/kernel/vmmmgr.C b/src/kernel/vmmmgr.C new file mode 100644 index 000000000..db19d36a3 --- /dev/null +++ b/src/kernel/vmmmgr.C @@ -0,0 +1,65 @@ +#include +#include +#include + +VmmManager::VmmManager() +{ +} + +void VmmManager::init() +{ + printk("Starting VMM..."); + + VmmManager& v = Singleton::instance(); + + //v.initSLB(); + v.initPTEs(); + v.initSDR1(); + + printk("done.\n"); +}; + +void VmmManager::initSLB() +{ + register uint64_t slbRS, slbRB; + + // ESID = 0, V = 1, Index = 0. + slbRB = 0x0000000008000000; + + // B = 01 (1TB), VSID = 0, Ks = 0, Kp = 1, NLCLP = 0 + slbRS = 0x4000000000000400; + + asm volatile("slbmte %0, %1" :: "r"(slbRS), "r"(slbRB) : "memory"); +} + +void VmmManager::initPTEs() +{ + // Invalidate all. + for(int i = 0; i < PTEG_COUNT; i++) + for (int j = 0; j < PTEG_SIZE; j++) + setValid(false, getPte(i,j)); + + // Set up linear map. + for(int i = 0; i < (FULL_MEM_SIZE / PAGESIZE); i++) + { + pte_t& pte = getPte(i, 0); + defaultPte(pte); + setTid(LinearSpace, pte); + setAccess( (0 == i) ? NO_USER_ACCESS : NORMAL_ACCESS, pte); + setPage(i, pte); + setValid(true, pte); + } + + // PTE sync. + pteSync(); +} + +void VmmManager::initSDR1() +{ + // HTABORG << 17, HTABSIZE = 0 (11 bits, 256k table) + register uint64_t sdr1 = (((uint64_t)HTABORG) << 17); + asm volatile("mtsdr1 %0" :: "r"(sdr1) : "memory"); +} + + +VmmManager::pte_t* VmmManager::page_table = (VmmManager::pte_t*) HTABORG; diff --git a/src/lib/syscall_task.C b/src/lib/syscall_task.C index 405e4f202..a29a9a94c 100644 --- a/src/lib/syscall_task.C +++ b/src/lib/syscall_task.C @@ -13,7 +13,7 @@ void task_yield() tid_t task_create(void(*fn)(void*), void* ptr) { - return (tid_t) _syscall2(TASK_START, (void*)fn, ptr); + return (tid_t)(uint64_t) _syscall2(TASK_START, (void*)fn, ptr); } void task_end() -- cgit v1.2.1