thread_context_impl.hh revision 8761:20322354b80b
1/* 2 * Copyright (c) 2010 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2004-2006 The Regents of The University of Michigan 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Kevin Lim 41 * Korey Sewell 42 */ 43 44#include "arch/registers.hh" 45#include "config/the_isa.hh" 46#include "cpu/o3/thread_context.hh" 47#include "cpu/quiesce_event.hh" 48#include "debug/O3CPU.hh" 49 50template <class Impl> 51VirtualPort * 52O3ThreadContext<Impl>::getVirtPort() 53{ 54 return thread->getVirtPort(); 55} 56 57#if FULL_SYSTEM 58template <class Impl> 59void 60O3ThreadContext<Impl>::dumpFuncProfile() 61{ 62 thread->dumpFuncProfile(); 63} 64#endif 65 66template <class Impl> 67void 68O3ThreadContext<Impl>::takeOverFrom(ThreadContext *old_context) 69{ 70 // some things should already be set up 71#if FULL_SYSTEM 72 assert(getSystemPtr() == old_context->getSystemPtr()); 73#else 74 assert(getProcessPtr() == old_context->getProcessPtr()); 75#endif 76 77 // copy over functional state 78 setStatus(old_context->status()); 79 copyArchRegs(old_context); 80 setContextId(old_context->contextId()); 81 setThreadId(old_context->threadId()); 82 83#if !FULL_SYSTEM 84 thread->funcExeInst = old_context->readFuncExeInst(); 85#else 86 EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent(); 87 if (other_quiesce) { 88 // Point the quiesce event's TC at this TC so that it wakes up 89 // the proper CPU. 90 other_quiesce->tc = this; 91 } 92 if (thread->quiesceEvent) { 93 thread->quiesceEvent->tc = this; 94 } 95 96 // Transfer kernel stats from one CPU to the other. 97 thread->kernelStats = old_context->getKernelStats(); 98// storeCondFailures = 0; 99 cpu->lockFlag = false; 100#endif 101 102 old_context->setStatus(ThreadContext::Halted); 103 104 thread->inSyscall = false; 105 thread->trapPending = false; 106} 107 108template <class Impl> 109void 110O3ThreadContext<Impl>::activate(int delay) 111{ 112 DPRINTF(O3CPU, "Calling activate on Thread Context %d\n", 113 threadId()); 114 115 if (thread->status() == ThreadContext::Active) 116 return; 117 118#if FULL_SYSTEM 119 thread->lastActivate = curTick(); 120#endif 121 122 thread->setStatus(ThreadContext::Active); 123 124 // status() == Suspended 125 cpu->activateContext(thread->threadId(), delay); 126} 127 128template <class Impl> 129void 130O3ThreadContext<Impl>::suspend(int delay) 131{ 132 DPRINTF(O3CPU, "Calling suspend on Thread Context %d\n", 133 threadId()); 134 135 if (thread->status() == ThreadContext::Suspended) 136 return; 137 138#if FULL_SYSTEM 139 thread->lastActivate = curTick(); 140 thread->lastSuspend = curTick(); 141#endif 142/* 143#if FULL_SYSTEM 144 // Don't change the status from active if there are pending interrupts 145 if (cpu->checkInterrupts()) { 146 assert(status() == ThreadContext::Active); 147 return; 148 } 149#endif 150*/ 151 thread->setStatus(ThreadContext::Suspended); 152 cpu->suspendContext(thread->threadId()); 153} 154 155template <class Impl> 156void 157O3ThreadContext<Impl>::halt(int delay) 158{ 159 DPRINTF(O3CPU, "Calling halt on Thread Context %d\n", 160 threadId()); 161 162 if (thread->status() == ThreadContext::Halted) 163 return; 164 165 thread->setStatus(ThreadContext::Halted); 166 cpu->haltContext(thread->threadId()); 167} 168 169template <class Impl> 170void 171O3ThreadContext<Impl>::regStats(const std::string &name) 172{ 173#if FULL_SYSTEM 174 thread->kernelStats = new TheISA::Kernel::Statistics(cpu->system); 175 thread->kernelStats->regStats(name + ".kern"); 176#endif 177} 178 179template <class Impl> 180void 181O3ThreadContext<Impl>::serialize(std::ostream &os) 182{ 183#if FULL_SYSTEM 184 if (thread->kernelStats) 185 thread->kernelStats->serialize(os); 186#endif 187 188} 189 190template <class Impl> 191void 192O3ThreadContext<Impl>::unserialize(Checkpoint *cp, const std::string §ion) 193{ 194#if FULL_SYSTEM 195 if (thread->kernelStats) 196 thread->kernelStats->unserialize(cp, section); 197#endif 198 199} 200 201#if FULL_SYSTEM 202template <class Impl> 203Tick 204O3ThreadContext<Impl>::readLastActivate() 205{ 206 return thread->lastActivate; 207} 208 209template <class Impl> 210Tick 211O3ThreadContext<Impl>::readLastSuspend() 212{ 213 return thread->lastSuspend; 214} 215 216template <class Impl> 217void 218O3ThreadContext<Impl>::profileClear() 219{ 220 thread->profileClear(); 221} 222 223template <class Impl> 224void 225O3ThreadContext<Impl>::profileSample() 226{ 227 thread->profileSample(); 228} 229#endif 230 231template <class Impl> 232void 233O3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc) 234{ 235 // Prevent squashing 236 thread->inSyscall = true; 237 TheISA::copyRegs(tc, this); 238 thread->inSyscall = false; 239 240#if !FULL_SYSTEM 241 this->thread->funcExeInst = tc->readFuncExeInst(); 242#endif 243} 244 245template <class Impl> 246void 247O3ThreadContext<Impl>::clearArchRegs() 248{ 249 cpu->isa[thread->threadId()].clear(); 250} 251 252template <class Impl> 253uint64_t 254O3ThreadContext<Impl>::readIntReg(int reg_idx) 255{ 256 reg_idx = cpu->isa[thread->threadId()].flattenIntIndex(reg_idx); 257 return cpu->readArchIntReg(reg_idx, thread->threadId()); 258} 259 260template <class Impl> 261TheISA::FloatReg 262O3ThreadContext<Impl>::readFloatReg(int reg_idx) 263{ 264 reg_idx = cpu->isa[thread->threadId()].flattenFloatIndex(reg_idx); 265 return cpu->readArchFloatReg(reg_idx, thread->threadId()); 266} 267 268template <class Impl> 269TheISA::FloatRegBits 270O3ThreadContext<Impl>::readFloatRegBits(int reg_idx) 271{ 272 reg_idx = cpu->isa[thread->threadId()].flattenFloatIndex(reg_idx); 273 return cpu->readArchFloatRegInt(reg_idx, thread->threadId()); 274} 275 276template <class Impl> 277void 278O3ThreadContext<Impl>::setIntReg(int reg_idx, uint64_t val) 279{ 280 reg_idx = cpu->isa[thread->threadId()].flattenIntIndex(reg_idx); 281 cpu->setArchIntReg(reg_idx, val, thread->threadId()); 282 283 // Squash if we're not already in a state update mode. 284 if (!thread->trapPending && !thread->inSyscall) { 285 cpu->squashFromTC(thread->threadId()); 286 } 287} 288 289template <class Impl> 290void 291O3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val) 292{ 293 reg_idx = cpu->isa[thread->threadId()].flattenFloatIndex(reg_idx); 294 cpu->setArchFloatReg(reg_idx, val, thread->threadId()); 295 296 if (!thread->trapPending && !thread->inSyscall) { 297 cpu->squashFromTC(thread->threadId()); 298 } 299} 300 301template <class Impl> 302void 303O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 304{ 305 reg_idx = cpu->isa[thread->threadId()].flattenFloatIndex(reg_idx); 306 cpu->setArchFloatRegInt(reg_idx, val, thread->threadId()); 307 308 // Squash if we're not already in a state update mode. 309 if (!thread->trapPending && !thread->inSyscall) { 310 cpu->squashFromTC(thread->threadId()); 311 } 312} 313 314template <class Impl> 315void 316O3ThreadContext<Impl>::pcState(const TheISA::PCState &val) 317{ 318 cpu->pcState(val, thread->threadId()); 319 320 // Squash if we're not already in a state update mode. 321 if (!thread->trapPending && !thread->inSyscall) { 322 cpu->squashFromTC(thread->threadId()); 323 } 324} 325 326template <class Impl> 327int 328O3ThreadContext<Impl>::flattenIntIndex(int reg) 329{ 330 return cpu->isa[thread->threadId()].flattenIntIndex(reg); 331} 332 333template <class Impl> 334int 335O3ThreadContext<Impl>::flattenFloatIndex(int reg) 336{ 337 return cpu->isa[thread->threadId()].flattenFloatIndex(reg); 338} 339 340template <class Impl> 341void 342O3ThreadContext<Impl>::setMiscRegNoEffect(int misc_reg, const MiscReg &val) 343{ 344 cpu->setMiscRegNoEffect(misc_reg, val, thread->threadId()); 345 346 // Squash if we're not already in a state update mode. 347 if (!thread->trapPending && !thread->inSyscall) { 348 cpu->squashFromTC(thread->threadId()); 349 } 350} 351 352template <class Impl> 353void 354O3ThreadContext<Impl>::setMiscReg(int misc_reg, const MiscReg &val) 355{ 356 cpu->setMiscReg(misc_reg, val, thread->threadId()); 357 358 // Squash if we're not already in a state update mode. 359 if (!thread->trapPending && !thread->inSyscall) { 360 cpu->squashFromTC(thread->threadId()); 361 } 362} 363 364