summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/include/kernel/cpu.H3
-rw-r--r--src/include/kernel/doorbell.H7
-rw-r--r--src/include/kernel/workitem.H12
-rw-r--r--src/kernel/cpumgr.C1
-rw-r--r--src/kernel/doorbell.C14
-rw-r--r--src/kernel/misc.C4
-rw-r--r--src/kernel/workitem.C15
7 files changed, 53 insertions, 3 deletions
diff --git a/src/include/kernel/cpu.H b/src/include/kernel/cpu.H
index f218e3e45..e6dc4a1fa 100644
--- a/src/include/kernel/cpu.H
+++ b/src/include/kernel/cpu.H
@@ -104,6 +104,9 @@ struct cpu_t
/** Sequence ID of CPU initialization. */
uint64_t cpu_start_seqid;
+ /** Timebase Restore Value (used during core wakeup) */
+ uint64_t cpu_restore_tb;
+
/** Stack of WorkItems to be executed during doorbell wakeup */
Util::Lockfree::Stack<KernelWorkItem> doorbell_actions;
};
diff --git a/src/include/kernel/doorbell.H b/src/include/kernel/doorbell.H
index 1d01ce119..d9a613672 100644
--- a/src/include/kernel/doorbell.H
+++ b/src/include/kernel/doorbell.H
@@ -56,6 +56,13 @@ void send_doorbell_wakeup(uint64_t i_pir);
*/
void send_doorbell_ipc(uint64_t i_pir);
+/** Send a doorbell and also restore the thread's timebase
+ *
+ * @param i_pir - PIR to send doorbell to wakeup
+ * @param i_tb - Timebase value to restore during wakeup
+ */
+void send_doorbell_restore_tb(uint64_t i_pir, uint64_t i_tb);
+
enum
{
_DOORBELL_MSG_TYPE = 0x0000000028000000, /// Comes from the ISA.
diff --git a/src/include/kernel/workitem.H b/src/include/kernel/workitem.H
index 856f5b365..027f3626f 100644
--- a/src/include/kernel/workitem.H
+++ b/src/include/kernel/workitem.H
@@ -53,6 +53,18 @@ class CpuWakeupDoorbellWorkItem : public KernelWorkItem
~CpuWakeupDoorbellWorkItem() = default;
};
+//A work item to be created/executed during a Master CPU
+// wakeup scenario, it will also restore the timebase
+// on the threads being woken up
+class CpuTbRestoreDoorbellWorkItem : public KernelWorkItem
+{
+ public:
+ //Implement operator() function
+ void operator() (void);
+
+ //No data to clean up, use default destructor
+ ~CpuTbRestoreDoorbellWorkItem() = default;
+};
#endif
diff --git a/src/kernel/cpumgr.C b/src/kernel/cpumgr.C
index 095b0a946..6ef08051c 100644
--- a/src/kernel/cpumgr.C
+++ b/src/kernel/cpumgr.C
@@ -253,6 +253,7 @@ void CpuManager::startCPU(ssize_t i)
cpu->idle_task = TaskManager::createIdleTask();
cpu->idle_task->cpu = cpu;
cpu->periodic_count = 0;
+ cpu->cpu_restore_tb = 0;
// Call TimeManager setup for a CPU.
TimeManager::init_cpu(cpu);
diff --git a/src/kernel/doorbell.C b/src/kernel/doorbell.C
index e746ab8cb..c24ee1384 100644
--- a/src/kernel/doorbell.C
+++ b/src/kernel/doorbell.C
@@ -79,6 +79,20 @@ void send_doorbell_wakeup(uint64_t i_pir)
doorbell_send(i_pir);
}
+void send_doorbell_restore_tb(uint64_t i_pir, uint64_t i_tb)
+{
+ cpu_t *l_cpu = CpuManager::getCpu(i_pir);
+ l_cpu->cpu_restore_tb = i_tb;
+
+ printkd("send_doorbell_restore_tb to pir: %lx\n", i_pir);
+ //Create WorkItem and put on the stack to be executed during doorbell
+ // execution
+ KernelWorkItem* l_work = new CpuTbRestoreDoorbellWorkItem();
+ l_cpu->doorbell_actions.push(l_work);
+ //Send doorbell to wakeup core/thread
+ doorbell_send(i_pir);
+}
+
void send_doorbell_ipc(uint64_t i_pir)
{
printk("send_doorbell_ipc to pir: %lx\n", i_pir);
diff --git a/src/kernel/misc.C b/src/kernel/misc.C
index 9f21fe75b..c770fc49f 100644
--- a/src/kernel/misc.C
+++ b/src/kernel/misc.C
@@ -348,7 +348,7 @@ namespace KernelMisc
// NOTE: The deferred work container verifies master core
// threads 1-3 wake up so a direct doorbell can be sent. For
// threads on other cores send_doorbell_wakeup() is used.
- doorbell_send(l_pir + i);
+ send_doorbell_restore_tb(l_pir + i, iv_timebase);
}
}
@@ -358,7 +358,6 @@ namespace KernelMisc
{
cpu->scheduler->setNextRunnable();
}
-
}
void WinkleCore::masterPostWork()
@@ -465,7 +464,6 @@ namespace KernelMisc
{
cpu->scheduler->setNextRunnable();
}
-
}
void WinkleAll::masterPostWork()
diff --git a/src/kernel/workitem.C b/src/kernel/workitem.C
index 0edf83083..53f91cb3b 100644
--- a/src/kernel/workitem.C
+++ b/src/kernel/workitem.C
@@ -27,6 +27,7 @@
#include <kernel/workitem.H>
#include <kernel/console.H>
#include <kernel/intmsghandler.H>
+#include <kernel/cpumgr.H>
//Define the desired behavior for a CPU core/thread
// wakeup scenario
@@ -40,3 +41,17 @@ void CpuWakeupDoorbellWorkItem::operator() (void)
InterruptMsgHdlr::sendThreadWakeupMsg(pir);
return;
}
+
+void CpuTbRestoreDoorbellWorkItem::operator() (void)
+{
+ size_t pir = getPIR();
+ cpu_t *l_cpu = CpuManager::getCpu(pir);
+
+ uint64_t l_restore_tb = l_cpu->cpu_restore_tb;
+ printkd("pir:%ld tb:0x%0x\n", pir, l_restore_tb);
+ if (l_restore_tb > getTB())
+ {
+ setTB(l_restore_tb);
+ }
+ return;
+}
OpenPOWER on IntegriCloud