diff options
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/cpumgr.C | 8 | ||||
-rw-r--r-- | src/kernel/exception.C | 4 | ||||
-rw-r--r-- | src/kernel/idebug.C | 89 | ||||
-rw-r--r-- | src/kernel/kernel.C | 2 | ||||
-rw-r--r-- | src/kernel/makefile | 2 | ||||
-rw-r--r-- | src/kernel/taskmgr.C | 12 |
6 files changed, 108 insertions, 9 deletions
diff --git a/src/kernel/cpumgr.C b/src/kernel/cpumgr.C index 6ec3b9f6d..626ad7f84 100644 --- a/src/kernel/cpumgr.C +++ b/src/kernel/cpumgr.C @@ -42,11 +42,14 @@ uint64_t CpuManager::cv_shutdown_status = 0; Barrier CpuManager::cv_barrier; bool CpuManager::cv_defrag = false; size_t CpuManager::cv_cpuCount = 0; +InteractiveDebug CpuManager::cv_interactive_debug; CpuManager::CpuManager() { for (int i = 0; i < MAXCPUS; i++) cv_cpus[i] = NULL; + + memset(&cv_interactive_debug, '\0', sizeof(cv_interactive_debug)); } cpu_t* CpuManager::getCurrentCPU() @@ -178,6 +181,11 @@ void CpuManager::executePeriodics(cpu_t * i_cpu) { if(i_cpu->master) { + if (cv_interactive_debug.isReady()) + { + cv_interactive_debug.startDebugTask(); + } + ++(i_cpu->periodic_count); if(0 == (i_cpu->periodic_count % CPU_PERIODIC_CHECK_MEMORY)) { diff --git a/src/kernel/exception.C b/src/kernel/exception.C index cbe97b220..863743f06 100644 --- a/src/kernel/exception.C +++ b/src/kernel/exception.C @@ -75,8 +75,8 @@ void kernel_execute_data_storage() } if (!handled) { - printk("Data Storage exception on %d: %lx, %lx\n", - t->tid, getDAR(), getDSISR()); + printk("Data Storage exception on %d: %lx, %lx @ %p\n", + t->tid, getDAR(), getDSISR(), t->context.nip); TaskManager::endTask(t, NULL, TASK_STATUS_CRASHED); } } diff --git a/src/kernel/idebug.C b/src/kernel/idebug.C new file mode 100644 index 000000000..673ecb149 --- /dev/null +++ b/src/kernel/idebug.C @@ -0,0 +1,89 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/kernel/idebug.C $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +#include <kernel/idebug.H> +#include <kernel/console.H> +#include <kernel/cpumgr.H> +#include <kernel/scheduler.H> +#include <sys/task.h> + + // Set Ready = 0, Running = 1, Complete = 0. +static const uint64_t IDEBUG_RUNNING_STATE = 0x0001000000000000ull; + // Set Ready = 0, Running = 0, Complete = 1. +static const uint64_t IDEBUG_COMPLETE_STATE = 0x0000010000000000ull; + +void InteractiveDebug::startDebugTask() +{ + // Atomically set state to 'running'. + // Set Ready = 0, Running = 1, Complete = 0. + __sync_lock_test_and_set(&state_value, IDEBUG_RUNNING_STATE); + + // Create userspace task to execute function. + task_t* t = TaskManager::createTask(&debugEntryPoint, this, true); + CpuManager::getCurrentCPU()->scheduler->addTask(t); + + return; +} + +void InteractiveDebug::debugEntryPoint(void* i_idObject) +{ + // Detach task so it is cleaned up properly once it exits. + task_detach(); + + // Get interactive debug structure from cast of input paramater. + InteractiveDebug* interactiveDebug = + static_cast<InteractiveDebug*>(i_idObject); + + // Get function pointer from 'entry_point_toc'. + typedef uint64_t(*func)(uint64_t,uint64_t,uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t); + func entry_point = + reinterpret_cast<func>(interactiveDebug->entry_point_toc); + + // Call function with parameters. + // Due to the PowerABI, parameters get passed in r3-r10 and any + // unused parameters are ignored by the called function. You can + // therefore treat every function as if it has 8 parameters, even + // if it has fewer, and the calling conventions are the same from + // an assembly perspective. + interactiveDebug->return_value = + entry_point(interactiveDebug->parms[0], + interactiveDebug->parms[1], + interactiveDebug->parms[2], + interactiveDebug->parms[3], + interactiveDebug->parms[4], + interactiveDebug->parms[5], + interactiveDebug->parms[6], + interactiveDebug->parms[7]); + + // Atomically set state to 'complete'. + // This must be proceeded by a sync to ensure all memory operations + // and instructions have fully completed prior to setting the complete + // state (due to weak consistency). + // Set Ready = 0, Running = 0, Complete = 1. + __sync_synchronize(); + __sync_lock_test_and_set(&interactiveDebug->state_value, + IDEBUG_COMPLETE_STATE); + + task_end(); +} + diff --git a/src/kernel/kernel.C b/src/kernel/kernel.C index 557a1c81c..cbac9a20f 100644 --- a/src/kernel/kernel.C +++ b/src/kernel/kernel.C @@ -117,7 +117,7 @@ void Kernel::cpuBootstrap() void Kernel::inittaskBootstrap() { - task_t * t = TaskManager::createTask(&init_main, NULL); + task_t * t = TaskManager::createTask(&init_main, NULL, true); t->cpu = CpuManager::getCurrentCPU(); TaskManager::setCurrentTask(t); } diff --git a/src/kernel/makefile b/src/kernel/makefile index 2ec3db0d9..05c15115a 100644 --- a/src/kernel/makefile +++ b/src/kernel/makefile @@ -26,7 +26,7 @@ OBJS = start.o kernel.o console.o pagemgr.o heapmgr.o taskmgr.o cpumgr.o OBJS += syscall.o scheduler.o spinlock.o exception.o vmmmgr.o timemgr.o OBJS += futexmgr.o ptmgr.o segmentmgr.o devicesegment.o basesegment.o OBJS += block.o cpuid.o misc.o msghandler.o blockmsghdlr.o stacksegment.o -OBJS += softpatch_p7.o barrier.o +OBJS += softpatch_p7.o barrier.o idebug.o include ${ROOTPATH}/config.mk diff --git a/src/kernel/taskmgr.C b/src/kernel/taskmgr.C index ad2aa3af5..b71bd2f25 100644 --- a/src/kernel/taskmgr.C +++ b/src/kernel/taskmgr.C @@ -68,9 +68,11 @@ task_t* TaskManager::createIdleTask() return Singleton<TaskManager>::instance()._createIdleTask(); } -task_t* TaskManager::createTask(TaskManager::task_fn_t t, void* p) +task_t* TaskManager::createTask(TaskManager::task_fn_t t, void* p, + bool kernelParent) { - return Singleton<TaskManager>::instance()._createTask(t, p, true); + return Singleton<TaskManager>::instance()._createTask(t, p, true, + kernelParent); } void TaskManager::endTask(task_t* t, void* retval, int status) @@ -85,11 +87,11 @@ void TaskManager::waitTask(task_t* t, int64_t tid, int* status, void** retval) task_t* TaskManager::_createIdleTask() { - return this->_createTask(&TaskManager::idleTaskLoop, NULL, false); + return this->_createTask(&TaskManager::idleTaskLoop, NULL, false, true); } task_t* TaskManager::_createTask(TaskManager::task_fn_t t, - void* p, bool withStack) + void* p, bool withStack, bool kernelParent) { task_t* task = new task_t; memset(task, '\0', sizeof(task_t)); @@ -144,7 +146,7 @@ task_t* TaskManager::_createTask(TaskManager::task_fn_t t, // Assign parent for tracker instance, add to task tree. iv_spinlock.lock(); - task_t* parent = getCurrentTask(); + task_t* parent = kernelParent ? NULL : getCurrentTask(); if (NULL == parent) { tracker->parent = NULL; |