summaryrefslogtreecommitdiffstats
path: root/src/kernel
diff options
context:
space:
mode:
authorPatrick Williams <iawillia@us.ibm.com>2012-05-16 12:51:22 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2012-07-16 19:05:48 -0500
commit3bba9a3ff18b6991bba4247898f4c26fa944a676 (patch)
treeda3462c53eaf0670670b37f094c17444f1ce5c4c /src/kernel
parent2aa5e0afac73384aaabe1fe1529898601be1155f (diff)
downloadtalos-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.C109
-rw-r--r--src/kernel/intmsghandler.C13
-rw-r--r--src/kernel/msghandler.C11
-rw-r--r--src/kernel/start.S1
-rw-r--r--src/kernel/syscall.C9
-rw-r--r--src/kernel/timemgr.C26
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);
+}
OpenPOWER on IntegriCloud