diff options
author | Patrick Williams <iawillia@us.ibm.com> | 2010-06-02 17:45:11 -0500 |
---|---|---|
committer | Patrick Williams <iawillia@us.ibm.com> | 2010-06-02 17:45:11 -0500 |
commit | 2cc0de1f136026f13ca6de363d9e57831c6ba10b (patch) | |
tree | 5653bf1244af8c97e63745536bf5ca887d06ea36 | |
parent | 5235cd52014205f358f1a295c5228091e1847efb (diff) | |
download | talos-hostboot-2cc0de1f136026f13ca6de363d9e57831c6ba10b.tar.gz talos-hostboot-2cc0de1f136026f13ca6de363d9e57831c6ba10b.zip |
Initial cpu / task structs.
-rw-r--r-- | src/include/kernel/cpu.H | 16 | ||||
-rw-r--r-- | src/include/kernel/cpumgr.H | 32 | ||||
-rw-r--r-- | src/include/kernel/scheduler.H | 26 | ||||
-rw-r--r-- | src/include/kernel/task.H | 25 | ||||
-rw-r--r-- | src/include/kernel/taskmgr.H | 31 | ||||
-rw-r--r-- | src/include/kernel/types.h | 12 | ||||
-rw-r--r-- | src/kernel/cpumgr.C | 72 | ||||
-rw-r--r-- | src/kernel/kernel.C | 8 | ||||
-rw-r--r-- | src/kernel/makefile | 2 | ||||
-rw-r--r-- | src/kernel/start.S | 8 | ||||
-rw-r--r-- | src/kernel/taskmgr.C | 66 |
11 files changed, 289 insertions, 9 deletions
diff --git a/src/include/kernel/cpu.H b/src/include/kernel/cpu.H new file mode 100644 index 000000000..6dd513b2c --- /dev/null +++ b/src/include/kernel/cpu.H @@ -0,0 +1,16 @@ +#ifndef __KERNEL_CPU_H +#define __KERNEL_CPU_H + +#include <kernel/types.h> + +class Scheduler; + +struct cpu_t +{ + cpuid_t cpu; + + Scheduler* scheduler; + void* kernel_stack; +}; + +#endif diff --git a/src/include/kernel/cpumgr.H b/src/include/kernel/cpumgr.H new file mode 100644 index 000000000..06ca8dbc1 --- /dev/null +++ b/src/include/kernel/cpumgr.H @@ -0,0 +1,32 @@ +#ifndef __KERNEL_CPUMGR_H +#define __KERNEL_CPUMGR_H + +#include <kernel/types.h> + +class CpuManager +{ + public: + enum { MAXCPUS = 8 }; + + /** @fn getCurrentCPU + * Returns a pointer to the current CPU structure by using the + * task structure in SPRG3. + */ + cpu_t* getCurrentCPU(); + + static void init(); + + protected: + CpuManager(); + ~CpuManager() {}; + + /** @fn startCPU + * Starts the requested CPU. Default of -1 implies current CPU. + */ + void startCPU(ssize_t i = -1); + + private: + cpu_t* iv_cpus[MAXCPUS]; +}; + +#endif diff --git a/src/include/kernel/scheduler.H b/src/include/kernel/scheduler.H new file mode 100644 index 000000000..06c3adcee --- /dev/null +++ b/src/include/kernel/scheduler.H @@ -0,0 +1,26 @@ +#ifndef __KERNEL_SCHEDULER_H +#define __KERNEL_SCHEDULER_H + +#include <kernel/types.h> +#include <util/lockfree/stack.H> + +class Scheduler +{ + public: + friend class CpuManager; + + protected: + Scheduler() : iv_direction(false) {}; + ~Scheduler() {}; + + void setIdleTask(task_t* t) { iv_idleTask = t; }; + task_t* getIdleTask() { return iv_idleTask; }; + + private: + bool iv_direction; + Util::Lockfree::Stack<task_t> iv_taskList[2]; + + task_t* iv_idleTask; +}; + +#endif diff --git a/src/include/kernel/task.H b/src/include/kernel/task.H new file mode 100644 index 000000000..c2ae51de1 --- /dev/null +++ b/src/include/kernel/task.H @@ -0,0 +1,25 @@ +#ifndef __KERNEL_TASK_H +#define __KERNEL_TASK_H + +#include <kernel/types.h> + +struct context_t +{ + void* stack_ptr; + void* nip; + uint64_t gprs[32]; + uint64_t lr; + uint64_t ctr; + uint64_t xer; +}; + +struct task_t +{ + cpu_t* cpu; + context_t context; + + tid_t tid; + task_t* next; +}; + +#endif diff --git a/src/include/kernel/taskmgr.H b/src/include/kernel/taskmgr.H new file mode 100644 index 000000000..7f23c8821 --- /dev/null +++ b/src/include/kernel/taskmgr.H @@ -0,0 +1,31 @@ +#ifndef __KERNEL_TASKMGR_H +#define __KENREL_TASKMGR_H + +#include <kernel/types.h> + +class TaskManager +{ + public: + static task_t* getCurrentTask(); + + typedef void(*task_fn_t)(); + + friend class CpuManager; + protected: + TaskManager(); + ~TaskManager() {}; + + static task_t* createIdleTask(); + static task_t* createTask(task_fn_t); + + private: + tid_t getNextTid(); + + tid_t iv_nextTid; + + static void idleTaskLoop(); + task_t* _createIdleTask(); + task_t* _createTask(task_fn_t, bool); +}; + +#endif diff --git a/src/include/kernel/types.h b/src/include/kernel/types.h new file mode 100644 index 000000000..c994308c2 --- /dev/null +++ b/src/include/kernel/types.h @@ -0,0 +1,12 @@ +#ifndef __KERNEL_TYPES_H +#define __KNERLE_TYPES_H + +#include <stdint.h> + +typedef uint64_t tid_t; +struct task_t; + +typedef uint64_t cpuid_t; +struct cpu_t; + +#endif diff --git a/src/kernel/cpumgr.C b/src/kernel/cpumgr.C new file mode 100644 index 000000000..3c2c3b907 --- /dev/null +++ b/src/kernel/cpumgr.C @@ -0,0 +1,72 @@ +#include <kernel/cpumgr.H> +#include <kernel/task.H> +#include <kernel/cpu.H> +#include <kernel/scheduler.H> +#include <kernel/taskmgr.H> +#include <kernel/pagemgr.H> +#include <kernel/console.H> +#include <util/singleton.H> + +CpuManager::CpuManager() +{ + for (int i = 0; i < MAXCPUS; i++) + iv_cpus[i] = NULL; +} + +cpu_t* CpuManager::getCurrentCPU() +{ + register task_t* current_task = NULL; + asm volatile("mfsprg3 %0" : "=r" (current_task) ); + return current_task->cpu; +} + +void CpuManager::init() +{ + Singleton<CpuManager>::instance().startCPU(); +} + +void CpuManager::startCPU(ssize_t i) +{ + bool currentCPU = false; + if (i < 0) + { + // TODO: Determine position of this CPU, somehow. + i = 0; + + currentCPU = true; + } + + printk("Starting CPU %d...", i); + + // Initialize CPU structure. + if (NULL == iv_cpus[i]) + { + cpu_t* cpu = iv_cpus[i] = new cpu_t; + + // Initialize CPU. + cpu->cpu = i; + cpu->scheduler = new Scheduler(); + cpu->kernel_stack = PageManager::allocatePage(4); + + // Create idle task. + task_t * idle_task = TaskManager::createIdleTask(); + idle_task->cpu = cpu; + + // Add to scheduler. + cpu->scheduler->setIdleTask(idle_task); + } + + if (currentCPU) + { + register task_t* idle_task = iv_cpus[i]->scheduler->getIdleTask(); + asm volatile("mtsprg3 %0" :: "r" (idle_task)); + } + else + { + // TODO once we get to SMP. + } + + printk("done\n"); + + return; +} diff --git a/src/kernel/kernel.C b/src/kernel/kernel.C index c7379e75d..ed2794dd7 100644 --- a/src/kernel/kernel.C +++ b/src/kernel/kernel.C @@ -2,6 +2,7 @@ #include <kernel/console.H> #include <kernel/pagemgr.H> #include <kernel/heapmgr.H> +#include <kernel/cpumgr.H> #include <util/singleton.H> #include <stdlib.h> @@ -11,6 +12,7 @@ class Kernel public: void cppBootstrap(); void memBootstrap(); + void cpuBootstrap(); protected: Kernel() {}; @@ -23,6 +25,7 @@ int main() Kernel& kernel = Singleton<Kernel>::instance(); kernel.cppBootstrap(); kernel.memBootstrap(); + kernel.cpuBootstrap(); while(1); return 0; @@ -47,3 +50,8 @@ void Kernel::memBootstrap() HeapManager::init(); } +void Kernel::cpuBootstrap() +{ + CpuManager::init(); +} + diff --git a/src/kernel/makefile b/src/kernel/makefile index 41d9f706c..3ff471de2 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 pagemgr.o heapmgr.o +OBJS = start.o kernel.o console.o pagemgr.o heapmgr.o taskmgr.o cpumgr.o OBJECTS = $(addprefix ${OBJDIR}/, ${OBJS}) all: ${OBJECTS} diff --git a/src/kernel/start.S b/src/kernel/start.S index 6906c2c33..9e8a560ba 100644 --- a/src/kernel/start.S +++ b/src/kernel/start.S @@ -77,12 +77,6 @@ _main: ori 1, 1, kernel_stack@l addi 1, 1, 16320 - ;// Set up exception stack, space for 8 double-words - lis 3, exception_stack@h - ori 3, 3, exception_stack@l - addi 3, 3, 16320 - mtsprg0 3 - ;// Call main. bl main _main_loop: @@ -93,8 +87,6 @@ _main_loop: .balign 1024 kernel_stack: .space 16*1024 -exception_stack: - .space 16*1024 .section .text.hreset hreset: diff --git a/src/kernel/taskmgr.C b/src/kernel/taskmgr.C new file mode 100644 index 000000000..0cbdda2d3 --- /dev/null +++ b/src/kernel/taskmgr.C @@ -0,0 +1,66 @@ +#include <util/singleton.H> +#include <kernel/taskmgr.H> +#include <kernel/task.H> +#include <kernel/pagemgr.H> + +void TaskManager::idleTaskLoop() +{ + while(1); +} + +task_t* TaskManager::getCurrentTask() +{ + register task_t* current_task = NULL; + asm volatile("mfsprg3 %0" : "=r" (current_task) ); + return current_task; +} + +TaskManager::TaskManager() : iv_nextTid(0) +{ +} + +task_t* TaskManager::createIdleTask() +{ + return Singleton<TaskManager>::instance()._createIdleTask(); +} + +task_t* TaskManager::createTask(TaskManager::task_fn_t t) +{ + return Singleton<TaskManager>::instance()._createTask(t, true); +} + +tid_t TaskManager::getNextTid() +{ + return __sync_fetch_and_add(&iv_nextTid, 1); +} + +task_t* TaskManager::_createIdleTask() +{ + return this->_createTask(&TaskManager::idleTaskLoop, false); +} + +task_t* TaskManager::_createTask(TaskManager::task_fn_t t, bool withStack) +{ + task_t* task = new task_t; + task->tid = this->getNextTid(); + + // Function pointer 't' is actually a TOC entry. + // TOC[0] = function address + // TOC[1] = TOC base -> r2 + task->context.nip = (void*) ((uint64_t*) t)[0]; + task->context.gprs[2] = ((uint64_t*)t)[1]; + + // Setup stack. + if (withStack) + { + task->context.stack_ptr = PageManager::allocatePage(4); + task->context.gprs[1] = ((uint64_t)task->context.stack_ptr) + 16320; + } + else + { + task->context.stack_ptr = NULL; + } + + return task; +} + |