diff options
Diffstat (limited to 'src/cpu/minor/cpu.cc')
-rw-r--r-- | src/cpu/minor/cpu.cc | 46 |
1 files changed, 35 insertions, 11 deletions
diff --git a/src/cpu/minor/cpu.cc b/src/cpu/minor/cpu.cc index 63efde2dc..484457bd4 100644 --- a/src/cpu/minor/cpu.cc +++ b/src/cpu/minor/cpu.cc @@ -49,6 +49,7 @@ MinorCPU::MinorCPU(MinorCPUParams *params) : BaseCPU(params), + pipelineStartupEvent([this]{ wakeupPipeline(); }, name()), threadPolicy(params->threadPolicy) { /* This is only written for one thread at the moment */ @@ -279,20 +280,43 @@ MinorCPU::takeOverFrom(BaseCPU *old_cpu) void MinorCPU::activateContext(ThreadID thread_id) { - DPRINTF(MinorCPU, "ActivateContext thread: %d\n", thread_id); + /* Remember to wake up this thread_id by scheduling the + * pipelineStartup event. + * We can't wakeupFetch the thread right away because its context may + * not have been fully initialized. For example, in the case of clone + * syscall, this activateContext function is called in the middle of + * the syscall and before the new thread context is initialized. + * If we start fetching right away, the new thread will fetch from an + * invalid address (i.e., pc is not initialized yet), which could lead + * to a page fault. Instead, we remember which threads to wake up and + * schedule an event to wake all them up after their contexts are + * fully initialized */ + readyThreads.push_back(thread_id); + if (!pipelineStartupEvent.scheduled()) + schedule(pipelineStartupEvent, clockEdge(Cycles(0))); +} - /* Do some cycle accounting. lastStopped is reset to stop the - * wakeup call on the pipeline from adding the quiesce period - * to BaseCPU::numCycles */ - stats.quiesceCycles += pipeline->cyclesSinceLastStopped(); - pipeline->resetLastStopped(); +void +MinorCPU::wakeupPipeline() +{ + for (auto thread_id : readyThreads) { + DPRINTF(MinorCPU, "ActivateContext thread: %d\n", thread_id); - /* Wake up the thread, wakeup the pipeline tick */ - threads[thread_id]->activate(); - wakeupOnEvent(Minor::Pipeline::CPUStageId); - pipeline->wakeupFetch(thread_id); + /* Do some cycle accounting. lastStopped is reset to stop the + * wakeup call on the pipeline from adding the quiesce period + * to BaseCPU::numCycles */ + stats.quiesceCycles += pipeline->cyclesSinceLastStopped(); + pipeline->resetLastStopped(); + + /* Wake up the thread, wakeup the pipeline tick */ + threads[thread_id]->activate(); + wakeupOnEvent(Minor::Pipeline::CPUStageId); + + pipeline->wakeupFetch(thread_id); + BaseCPU::activateContext(thread_id); + } - BaseCPU::activateContext(thread_id); + readyThreads.clear(); } void |