summaryrefslogtreecommitdiffstats
path: root/src/kernel
diff options
context:
space:
mode:
authorBrian Stegmiller <bjs@us.ibm.com>2015-11-15 10:52:28 -0600
committerPatrick Williams <iawillia@us.ibm.com>2015-12-11 15:30:29 -0600
commitcb1f5614326054b025774dae1a37ad5bdf07902d (patch)
tree4b5ef74fd7aac1b7bba91da711da867ccb870920 /src/kernel
parentbedb0a1a1818ebe6d683028926ccaec14fdb9f8d (diff)
downloadblackbird-hostboot-cb1f5614326054b025774dae1a37ad5bdf07902d.tar.gz
blackbird-hostboot-cb1f5614326054b025774dae1a37ad5bdf07902d.zip
HOSTBOOT: Support fused cores
Change-Id: I2ad133be733ee9e41590b3b8bd60bd6abe69d1a9 RTC: 126786 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/22054 Tested-by: Jenkins Server Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/misc.C71
-rw-r--r--src/kernel/start.S17
-rw-r--r--src/kernel/syscall.C3
3 files changed, 79 insertions, 12 deletions
diff --git a/src/kernel/misc.C b/src/kernel/misc.C
index a4b438ceb..080c0adf3 100644
--- a/src/kernel/misc.C
+++ b/src/kernel/misc.C
@@ -40,6 +40,7 @@
#include <kernel/hbdescriptor.H>
#include <kernel/ipc.H>
#include <kernel/timemgr.H>
+#include <util/singleton.H>
extern "C"
@@ -249,14 +250,35 @@ namespace KernelMisc
// Save away the current timebase. All threads are in this object
// now so they're not going to be using the time for anything else.
iv_timebase = getTB() + TimeManager::convertSecToTicks(1,0);
+
+ if (true == iv_fusedCores)
+ {
+ uint64_t l_numThreads = CpuManager::getThreadCount();
+ cpu_t * l_cput = CpuManager::getCurrentCPU();
+
+ // creates cpu_t structure in advance for new threads
+ // (should be next set of cpuIds past master core)
+ for ( uint64_t l_threadNum = l_numThreads;
+ (l_threadNum < (l_numThreads *2));
+ l_threadNum++ )
+ {
+ Singleton<CpuManager>::instance().startCPU(l_cput->cpu +
+ l_threadNum);
+ }
+
+ // Tell SIMICS we expect more threads (one more core)
+ // to appear after doing the 'stop' instruction.
+ MAGIC_INSTRUCTION(MAGIC_SIMICS_FUSEDCOREWAKE);
+ } // end if fused core mode
}
- extern "C" void kernel_execute_winkle(task_t* t);
+ extern "C" void kernel_execute_stop(task_t* t);
void WinkleCore::activeMainWork()
{
cpu_t* cpu = CpuManager::getCurrentCPU();
- printk("%d", static_cast<int>(cpu->cpu & 0x7));
+ ssize_t l_numThreads = CpuManager::getThreadCount();
+ printk("%d", static_cast<int>(cpu->cpu & (l_numThreads-1)));
// Return current task to run-queue so it isn't lost.
cpu->scheduler->returnRunnable();
@@ -276,10 +298,14 @@ namespace KernelMisc
saveArea->context.msr_mask = 0xD030; // EE, ME, PR, IR, DR.
*(reinterpret_cast<task_t**>(cpu->kernel_stack_bottom)) = saveArea;
+ // Set register to indicate we want a 'stop 15' to occur (state loss)
+ uint64_t l_psscr_saved = getPSSCR();
+ setPSSCR( 0x00000000003F00FF );
// Execute winkle.
- kernel_execute_winkle(saveArea);
+ kernel_execute_stop(saveArea);
// Re-activate CPU in kernel and re-init VMM SPRs.
+ setPSSCR(l_psscr_saved);
delete saveArea;
cpu->winkled = false;
CpuManager::activateCPU(cpu);
@@ -314,6 +340,39 @@ namespace KernelMisc
//Issue sbe master workaround
InterruptMsgHdlr::issueSbeMboxWA();
+ // NOTE: The cpu_t structures for theads 1:3 were created
+ // during init (CpuManager::init).
+
+ #ifdef HOSTBOOT_REAL_WINKLE
+ // @todo- RTC 141924 Start the other threads 1:3 in a new manner
+ // SBE won't start them and we can't use normal instruction start.
+ // Maybe something like: sendIPI(..) or addCpuCore(..)
+ // Need interrupt code in place for this.
+
+ #else
+ // get other 3 threads going in SIMICs for now
+ MAGIC_INSTRUCTION(MAGIC_WAKE_OTHER_THREADS);
+ #endif
+
+ if (true == iv_fusedCores)
+ {
+ // If using FUSED cores, we need to essentially
+ // treat this as a new core appearing.
+
+ #ifdef HOSTBOOT_REAL_WINKLE
+ ssize_t l_numThreads = CpuManager::getThreadCount();
+ cpu_t* l_cpuPtr = CpuManager::getCurrentCPU();
+ cpuid_t l_startPir = l_cpuPtr->cpu & (~(l_numThreads - 1));
+
+ // New core should have threads just past current ones
+ CpuManager::startCore(l_startPir + l_numThreads,
+ 0xF000000000000000); // all 4 threads
+ #else
+ // get new core going in SIMICS
+ MAGIC_INSTRUCTION(MAGIC_WAKE_FUSED_THREADS);
+ #endif
+ } // end if fused core mode
+
}
void WinkleCore::nonactiveMainWork()
@@ -356,10 +415,14 @@ namespace KernelMisc
saveArea->context.msr_mask = 0xD030; // EE, ME, PR, IR, DR.
*(reinterpret_cast<task_t**>(cpu->kernel_stack_bottom)) = saveArea;
+ // Set register to indicate we want a 'stop 15' to ocur (state loss)
+ uint64_t l_psscr_saved = getPSSCR();
+ setPSSCR( 0x00000000003F00FF );
// Execute winkle.
- kernel_execute_winkle(saveArea);
+ kernel_execute_stop(saveArea);
// Re-activate CPU in kernel and re-init VMM SPRs.
+ setPSSCR(l_psscr_saved);
delete saveArea;
cpu->winkled = false;
CpuManager::activateCPU(cpu);
diff --git a/src/kernel/start.S b/src/kernel/start.S
index 13351b893..dbb499751 100644
--- a/src/kernel/start.S
+++ b/src/kernel/start.S
@@ -867,15 +867,15 @@ UNIMPL_INTERRUPT_NOADDR(vector_unavail, 0xF20)
UNIMPL_INTERRUPT_NOADDR(vsx_unavail, 0xF40)
UNIMPL_INTERRUPT_NOADDR(fac_unavail, 0xF60)
- ;// @fn kernel_execute_winkle
+ ;// @fn kernel_execute_stop
;//
;// Saves kernel state into a specified task structure and then executes
- ;// the winkle instruction.
+ ;// the stop instruction.
;//
;// @param r3 - task_t* to save kernel state into.
;//
-.global kernel_execute_winkle
-kernel_execute_winkle:
+.global kernel_execute_stop
+kernel_execute_stop:
;// Move save area to SPRG3 for kernel_save_task.
mtsprg3 r3
@@ -883,7 +883,7 @@ kernel_execute_winkle:
mflr r3
mtsrr0 r3
- ;// Load winkle instruction address into the "return to" address (SPRG0).
+ ;// Load stop instruction address into the "return to" address (SPRG0).
lis r3, 1f@h
ori r3, r3, 1f@l
mtsprg0 r3
@@ -891,9 +891,12 @@ kernel_execute_winkle:
;// Save kernel state.
b kernel_save_task
- ;// Execute winkle.
+ ;// Execute stop.
1:
- rvwinkle
+ ;// Magic instruction(7015) to allow simics to trigger thread wakeup
+ rlwimi r27,r27,0,6,23
+ ;// When GCC supports 'stop', you can use it
+ .long 0x4C0002E4
.section .data
.balign 1024
diff --git a/src/kernel/syscall.C b/src/kernel/syscall.C
index 1b1bd7f57..92907c3df 100644
--- a/src/kernel/syscall.C
+++ b/src/kernel/syscall.C
@@ -751,7 +751,8 @@ namespace Systemcalls
DeferredWork* deferred = NULL;
if (WINKLE_SCOPE_MASTER == TASK_GETARG0(t))
{
- deferred = new KernelMisc::WinkleCore(t);
+ bool l_fusedCores = (bool)TASK_GETARG1(t);
+ deferred = new KernelMisc::WinkleCore(t, l_fusedCores);
}
else
{
OpenPOWER on IntegriCloud