diff options
| author | Patrick Williams <iawillia@us.ibm.com> | 2012-05-16 12:51:22 -0500 |
|---|---|---|
| committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2012-07-16 19:05:48 -0500 |
| commit | 3bba9a3ff18b6991bba4247898f4c26fa944a676 (patch) | |
| tree | da3462c53eaf0670670b37f094c17444f1ce5c4c /src/kernel | |
| parent | 2aa5e0afac73384aaabe1fe1529898601be1155f (diff) | |
| download | talos-hostboot-3bba9a3ff18b6991bba4247898f4c26fa944a676.tar.gz talos-hostboot-3bba9a3ff18b6991bba4247898f4c26fa944a676.zip | |
Support for core_activate via IPI.
RTC: 37009
Change-Id: I56669805c86d9659a20ad7c26e5e9860c7a248c7
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/1087
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/kernel')
| -rw-r--r-- | src/kernel/cpumgr.C | 109 | ||||
| -rw-r--r-- | src/kernel/intmsghandler.C | 13 | ||||
| -rw-r--r-- | src/kernel/msghandler.C | 11 | ||||
| -rw-r--r-- | src/kernel/start.S | 1 | ||||
| -rw-r--r-- | src/kernel/syscall.C | 9 | ||||
| -rw-r--r-- | src/kernel/timemgr.C | 26 |
6 files changed, 116 insertions, 53 deletions
diff --git a/src/kernel/cpumgr.C b/src/kernel/cpumgr.C index 4fdc8fde9..48bf4a5e8 100644 --- a/src/kernel/cpumgr.C +++ b/src/kernel/cpumgr.C @@ -36,8 +36,10 @@ #include <kernel/cpuid.H> #include <kernel/ptmgr.H> #include <kernel/heapmgr.H> +#include <kernel/intmsghandler.H> +#include <errno.h> -cpu_t* CpuManager::cv_cpus[CpuManager::MAXCPUS] = { NULL }; +cpu_t** CpuManager::cv_cpus = NULL; bool CpuManager::cv_shutdown_requested = false; uint64_t CpuManager::cv_shutdown_status = 0; Barrier CpuManager::cv_barrier; @@ -49,16 +51,11 @@ InteractiveDebug CpuManager::cv_interactive_debug; CpuManager::CpuManager() { for (int i = 0; i < MAXCPUS; i++) - cv_cpus[i] = NULL; + cv_cpus[i] = NULL; memset(&cv_interactive_debug, '\0', sizeof(cv_interactive_debug)); } -cpu_t* CpuManager::getCurrentCPU() -{ - return cv_cpus[getPIR()]; -} - cpu_t* CpuManager::getMasterCPU() { for (int i = 0; i < MAXCPUS; i++) @@ -77,27 +74,13 @@ void CpuManager::init() // enter the kernel, so we skip initializing all the other CPUs for now. // Determine number of threads on this core. - size_t threads = -1; - switch (CpuID::getCpuType()) - { - case CORE_POWER7: - case CORE_POWER7_PLUS: - threads = 4; - break; - - case CORE_POWER8_VENICE: - case CORE_POWER8_MURANO: - threads = 8; - break; + size_t threads = getThreadCount(); - case CORE_UNKNOWN: - default: - kassert(false); - break; - } + // Set up CPU structure. + cv_cpus = new cpu_t*[MAXCPUS]; // Create CPU objects starting at the thread-0 for this core. - size_t baseCpu = getPIR() & ~(threads-1); + size_t baseCpu = getCpuId() & ~(threads-1); for (size_t i = 0; i < threads; i++) Singleton<CpuManager>::instance().startCPU(i + baseCpu); } @@ -119,22 +102,22 @@ void CpuManager::startCPU(ssize_t i) bool currentCPU = false; if (i < 0) { - i = getCpuId(); - currentCPU = true; + i = getCpuId(); + currentCPU = true; } else if (getCpuId() == (uint64_t)i) { - currentCPU = true; + currentCPU = true; } // Initialize CPU structure. if (NULL == cv_cpus[i]) { - printk("Starting CPU %ld...", i); - cpu_t* cpu = cv_cpus[i] = new cpu_t; + printk("Starting CPU %ld...", i); + cpu_t* cpu = cv_cpus[i] = new cpu_t; - // Initialize CPU. - cpu->cpu = i; + // Initialize CPU. + cpu->cpu = i; if (currentCPU) { cpu->master = true; @@ -143,18 +126,21 @@ void CpuManager::startCPU(ssize_t i) { cpu->master = false; } - cpu->scheduler = &Singleton<Scheduler>::instance(); + cpu->scheduler = &Singleton<Scheduler>::instance(); cpu->scheduler_extra = NULL; - cpu->kernel_stack = - (void*) (((uint64_t)PageManager::allocatePage(4)) + 16320); + cpu->kernel_stack = + (void*) (((uint64_t)PageManager::allocatePage(4)) + 16320); cpu->xscom_mutex = (mutex_t)MUTEX_INITIALIZER; - // Create idle task. - cpu->idle_task = TaskManager::createIdleTask(); - cpu->idle_task->cpu = cpu; + // Create idle task. + cpu->idle_task = TaskManager::createIdleTask(); + cpu->idle_task->cpu = cpu; cpu->periodic_count = 0; - printk("done\n"); + // Call TimeManager setup for a CPU. + TimeManager::init_cpu(cpu); + + printk("done\n"); } if (currentCPU) @@ -176,7 +162,7 @@ void CpuManager::startSlaveCPU(cpu_t* cpu) void CpuManager::activateCPU(cpu_t * i_cpu) { i_cpu->active = true; - __sync_fetch_and_add(&cv_cpuCount, 1); + __sync_add_and_fetch(&cv_cpuCount, 1); lwsync(); } @@ -247,6 +233,49 @@ void CpuManager::executePeriodics(cpu_t * i_cpu) } } +int CpuManager::startCore(uint64_t pir) +{ + size_t threads = getThreadCount(); + pir = pir & ~(threads-1); + + + if (pir >= MAXCPUS) { return -ENXIO; } + + for(size_t i = 0; i < threads; i++) + { + Singleton<CpuManager>::instance().startCPU(pir + i); + } + __sync_synchronize(); + + InterruptMsgHdlr::addCpuCore(pir); + + return 0; +}; + +size_t CpuManager::getThreadCount() +{ + size_t threads = 0; + switch (CpuID::getCpuType()) + { + case CORE_POWER7: + case CORE_POWER7_PLUS: + threads = 4; + break; + + case CORE_POWER8_VENICE: + case CORE_POWER8_MURANO: + threads = 8; + break; + + case CORE_UNKNOWN: + default: + kassert(false); + break; + } + + return threads; +} + void CpuManager::forceMemoryPeriodic() { cv_forcedMemPeriodic = true; diff --git a/src/kernel/intmsghandler.C b/src/kernel/intmsghandler.C index 98f941f4c..73d14e787 100644 --- a/src/kernel/intmsghandler.C +++ b/src/kernel/intmsghandler.C @@ -99,8 +99,8 @@ void InterruptMsgHdlr::handleInterrupt() if(cv_instance) { cv_instance->sendMessage(MSG_INTR_EXTERN, - (void *)xirr, (void *)pir, + (void *)xirr, NULL); } @@ -114,13 +114,18 @@ void InterruptMsgHdlr::handleInterrupt() } - -// TODO where does this get called from? (story 39878) void InterruptMsgHdlr::addCpuCore(uint64_t i_pir) { + task_t* t = TaskManager::getCurrentTask(); + if(cv_instance) { - cv_instance->sendMessage(MSG_INTR_ADD_CPU,(void *)i_pir,NULL,NULL); + // To avoid conflict with interrupts on thread i_pir, change the key + // for the message to be an invalid PIR. + uint64_t pir_key = i_pir | 0x8000000000000000ul; + + cv_instance->sendMessage(MSG_INTR_ADD_CPU, + (void*)pir_key,(void *)i_pir,t); } } diff --git a/src/kernel/msghandler.C b/src/kernel/msghandler.C index 71a9d84d1..7761d36ae 100644 --- a/src/kernel/msghandler.C +++ b/src/kernel/msghandler.C @@ -42,6 +42,13 @@ void MessageHandler::sendMessage(msg_sys_types_t i_type, void* i_key, mhp->key = i_key; mhp->task = i_task; + // Update block status for task. + if (NULL != i_task) + { + i_task->state = TASK_STATE_BLOCK_USRSPACE; + i_task->state_info = i_key; + } + // Send userspace message if one hasn't been sent for this key. if (!iv_pending.find(i_key)) { @@ -76,10 +83,6 @@ void MessageHandler::sendMessage(msg_sys_types_t i_type, void* i_key, // Defer task while waiting for message response. if (NULL != i_task) { - // Set block status. - i_task->state = TASK_STATE_BLOCK_USRSPACE; - i_task->state_info = i_key; - if (i_task == TaskManager::getCurrentTask()) { // Switch to ready waiter, or pick a new task off the scheduler. diff --git a/src/kernel/start.S b/src/kernel/start.S index 6d0eab195..a8166b980 100644 --- a/src/kernel/start.S +++ b/src/kernel/start.S @@ -272,6 +272,7 @@ _other_thread_spinlock_complete: mfspr r1, PIR lis r2, _ZN10CpuManager7cv_cpusE@h ori r2, r2, _ZN10CpuManager7cv_cpusE@l + ld r2, 0(r2) ;// Dereference cv_cpus to get array. muli r3, r1, 8 add r2, r3, r2 ld r3, 0(r2) ;// Load CPU object. diff --git a/src/kernel/syscall.C b/src/kernel/syscall.C index b061a4877..26a72cd35 100644 --- a/src/kernel/syscall.C +++ b/src/kernel/syscall.C @@ -96,6 +96,7 @@ namespace Systemcalls void Shutdown(task_t *t); void CpuCoreType(task_t *t); void CpuDDLevel(task_t *t); + void CpuStartCore(task_t *t); void MmAllocBlock(task_t *t); void MmRemovePages(task_t *t); void MmSetPermission(task_t *t); @@ -129,6 +130,7 @@ namespace Systemcalls &Shutdown, // MISC_SHUTDOWN &CpuCoreType, // MISC_CPUCORETYPE &CpuDDLevel, // MISC_CPUDDLEVEL + &CpuStartCore, // MISC_CPUSTARTCORE &MmAllocBlock, // MM_ALLOC_BLOCK &MmRemovePages, // MM_REMOVE_PAGES @@ -631,6 +633,13 @@ namespace Systemcalls TASK_SETRTN(t, CpuID::getCpuDD()); } + /** Prep core for activation. */ + void CpuStartCore(task_t *t) + { + TASK_SETRTN(t, + CpuManager::startCore(static_cast<uint64_t>(TASK_GETARG0(t)))); + }; + /** * Allocate a block of virtual memory within the base segment * @param[in] t: The task used to allocate a block in the base segment diff --git a/src/kernel/timemgr.C b/src/kernel/timemgr.C index b6be8cb90..36d89ee30 100644 --- a/src/kernel/timemgr.C +++ b/src/kernel/timemgr.C @@ -24,6 +24,7 @@ #include <kernel/scheduler.H> #include <util/singleton.H> #include <kernel/task.H> +#include <kernel/cpumgr.H> uint64_t TimeManager::iv_timebaseFreq = 0xFFFFFFFF; @@ -37,6 +38,16 @@ void TimeManager::_init() iv_timebaseFreq = 512000000ULL; } +void TimeManager::init_cpu(cpu_t* cpu) +{ + Singleton<TimeManager>::instance()._init_cpu(cpu); +} + +void TimeManager::_init_cpu(cpu_t* cpu) +{ + cpu->delay_list = new delaylist_t; +} + uint64_t TimeManager::convertSecToTicks(uint64_t i_sec, uint64_t i_nsec) { // This code will handle times almost up to a year without overflowing a @@ -68,13 +79,13 @@ void TimeManager::_delayTask(task_t* t, uint64_t i_sec, uint64_t i_nsec) _TimeManager_Delay_t* node = new _TimeManager_Delay_t(); node->key = this->getCurrentTimeBase() + - this->convertSecToTicks(i_sec, i_nsec); + this->convertSecToTicks(i_sec, i_nsec); node->task = t; t->state = TASK_STATE_BLOCK_SLEEP; t->state_info = (void*)node->key; - iv_taskList[getPIR()].insert(node); + _get_delaylist()->insert(node); } void TimeManager::checkReleaseTasks(Scheduler* s) @@ -87,9 +98,14 @@ void TimeManager::_checkReleaseTasks(Scheduler* s) uint64_t l_currentTime = getCurrentTimeBase(); _TimeManager_Delay_t* node = NULL; - while(NULL != (node = iv_taskList[getPIR()].remove_if(l_currentTime))) + while(NULL != (node = _get_delaylist()->remove_if(l_currentTime))) { - s->addTask(node->task); - delete node; + s->addTask(node->task); + delete node; } } + +inline TimeManager::delaylist_t* TimeManager::_get_delaylist() +{ + return static_cast<delaylist_t*>(CpuManager::getCurrentCPU()->delay_list); +} |

