diff options
-rw-r--r-- | src/include/kernel/cpu.H | 3 | ||||
-rw-r--r-- | src/include/kernel/doorbell.H | 7 | ||||
-rw-r--r-- | src/include/kernel/workitem.H | 12 | ||||
-rw-r--r-- | src/kernel/cpumgr.C | 1 | ||||
-rw-r--r-- | src/kernel/doorbell.C | 14 | ||||
-rw-r--r-- | src/kernel/misc.C | 4 | ||||
-rw-r--r-- | src/kernel/workitem.C | 15 |
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; +} |