thread_context_impl.hh revision 2986
1/* 2 * Copyright (c) 2004-2006 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Kevin Lim 29 * Korey Sewell 30 */ 31 32#include "cpu/o3/thread_context.hh" 33#include "cpu/quiesce_event.hh" 34 35#if FULL_SYSTEM 36template <class Impl> 37VirtualPort * 38O3ThreadContext<Impl>::getVirtPort(ThreadContext *src_tc) 39{ 40 if (!src_tc) 41 return thread->getVirtPort(); 42 43 VirtualPort *vp; 44 Port *mem_port; 45 46 vp = new VirtualPort("tc-vport", src_tc); 47 mem_port = cpu->system->physmem->getPort("functional"); 48 mem_port->setPeer(vp); 49 vp->setPeer(mem_port); 50 return vp; 51} 52 53template <class Impl> 54void 55O3ThreadContext<Impl>::dumpFuncProfile() 56{ 57 // Currently not supported 58} 59#endif 60 61template <class Impl> 62void 63O3ThreadContext<Impl>::takeOverFrom(ThreadContext *old_context) 64{ 65 // some things should already be set up 66#if FULL_SYSTEM 67 assert(getSystemPtr() == old_context->getSystemPtr()); 68#else 69 assert(getProcessPtr() == old_context->getProcessPtr()); 70#endif 71 72 // copy over functional state 73 setStatus(old_context->status()); 74 copyArchRegs(old_context); 75 setCpuId(old_context->readCpuId()); 76 77#if !FULL_SYSTEM 78 thread->funcExeInst = old_context->readFuncExeInst(); 79#else 80 EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent(); 81 if (other_quiesce) { 82 // Point the quiesce event's TC at this TC so that it wakes up 83 // the proper CPU. 84 other_quiesce->tc = this; 85 } 86 if (thread->quiesceEvent) { 87 thread->quiesceEvent->tc = this; 88 } 89 90 // Transfer kernel stats from one CPU to the other. 91 thread->kernelStats = old_context->getKernelStats(); 92// storeCondFailures = 0; 93 cpu->lockFlag = false; 94#endif 95 96 old_context->setStatus(ThreadContext::Unallocated); 97 98 thread->inSyscall = false; 99 thread->trapPending = false; 100} 101 102#if FULL_SYSTEM 103template <class Impl> 104void 105O3ThreadContext<Impl>::delVirtPort(VirtualPort *vp) 106{ 107 delete vp->getPeer(); 108 delete vp; 109} 110#endif 111 112template <class Impl> 113void 114O3ThreadContext<Impl>::activate(int delay) 115{ 116 DPRINTF(O3CPU, "Calling activate on Thread Context %d\n", 117 getThreadNum()); 118 119 if (thread->status() == ThreadContext::Active) 120 return; 121 122#if FULL_SYSTEM 123 thread->lastActivate = curTick; 124#endif 125 126 if (thread->status() == ThreadContext::Unallocated) { 127 cpu->activateWhenReady(thread->readTid()); 128 return; 129 } 130 131 thread->setStatus(ThreadContext::Active); 132 133 // status() == Suspended 134 cpu->activateContext(thread->readTid(), delay); 135} 136 137template <class Impl> 138void 139O3ThreadContext<Impl>::suspend() 140{ 141 DPRINTF(O3CPU, "Calling suspend on Thread Context %d\n", 142 getThreadNum()); 143 144 if (thread->status() == ThreadContext::Suspended) 145 return; 146 147#if FULL_SYSTEM 148 thread->lastActivate = curTick; 149 thread->lastSuspend = curTick; 150#endif 151/* 152#if FULL_SYSTEM 153 // Don't change the status from active if there are pending interrupts 154 if (cpu->check_interrupts()) { 155 assert(status() == ThreadContext::Active); 156 return; 157 } 158#endif 159*/ 160 thread->setStatus(ThreadContext::Suspended); 161 cpu->suspendContext(thread->readTid()); 162} 163 164template <class Impl> 165void 166O3ThreadContext<Impl>::deallocate(int delay) 167{ 168 DPRINTF(O3CPU, "Calling deallocate on Thread Context %d\n", 169 getThreadNum()); 170 171 if (thread->status() == ThreadContext::Unallocated) 172 return; 173 174 thread->setStatus(ThreadContext::Unallocated); 175 cpu->deallocateContext(thread->readTid(), delay); 176} 177 178template <class Impl> 179void 180O3ThreadContext<Impl>::halt() 181{ 182 DPRINTF(O3CPU, "Calling halt on Thread Context %d\n", 183 getThreadNum()); 184 185 if (thread->status() == ThreadContext::Halted) 186 return; 187 188 thread->setStatus(ThreadContext::Halted); 189 cpu->haltContext(thread->readTid()); 190} 191 192template <class Impl> 193void 194O3ThreadContext<Impl>::regStats(const std::string &name) 195{ 196#if FULL_SYSTEM 197 thread->kernelStats = new Kernel::Statistics(cpu->system); 198 thread->kernelStats->regStats(name + ".kern"); 199#endif 200} 201 202template <class Impl> 203void 204O3ThreadContext<Impl>::serialize(std::ostream &os) 205{ 206#if FULL_SYSTEM 207 if (thread->kernelStats) 208 thread->kernelStats->serialize(os); 209#endif 210 211} 212 213template <class Impl> 214void 215O3ThreadContext<Impl>::unserialize(Checkpoint *cp, const std::string §ion) 216{ 217#if FULL_SYSTEM 218 if (thread->kernelStats) 219 thread->kernelStats->unserialize(cp, section); 220#endif 221 222} 223 224#if FULL_SYSTEM 225template <class Impl> 226Tick 227O3ThreadContext<Impl>::readLastActivate() 228{ 229 return thread->lastActivate; 230} 231 232template <class Impl> 233Tick 234O3ThreadContext<Impl>::readLastSuspend() 235{ 236 return thread->lastSuspend; 237} 238 239template <class Impl> 240void 241O3ThreadContext<Impl>::profileClear() 242{} 243 244template <class Impl> 245void 246O3ThreadContext<Impl>::profileSample() 247{} 248#endif 249 250template <class Impl> 251TheISA::MachInst 252O3ThreadContext<Impl>:: getInst() 253{ 254 return thread->getInst(); 255} 256 257template <class Impl> 258void 259O3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc) 260{ 261 // This function will mess things up unless the ROB is empty and 262 // there are no instructions in the pipeline. 263 unsigned tid = thread->readTid(); 264 PhysRegIndex renamed_reg; 265 266 // First loop through the integer registers. 267 for (int i = 0; i < TheISA::NumIntRegs; ++i) { 268 renamed_reg = cpu->renameMap[tid].lookup(i); 269 270 DPRINTF(O3CPU, "Copying over register %i, had data %lli, " 271 "now has data %lli.\n", 272 renamed_reg, cpu->readIntReg(renamed_reg), 273 tc->readIntReg(i)); 274 275 cpu->setIntReg(renamed_reg, tc->readIntReg(i)); 276 } 277 278 // Then loop through the floating point registers. 279 for (int i = 0; i < TheISA::NumFloatRegs; ++i) { 280 renamed_reg = cpu->renameMap[tid].lookup(i + TheISA::FP_Base_DepTag); 281 cpu->setFloatRegBits(renamed_reg, 282 tc->readFloatRegBits(i)); 283 } 284 285 // Copy the misc regs. 286 TheISA::copyMiscRegs(tc, this); 287 288 // Then finally set the PC and the next PC. 289 cpu->setPC(tc->readPC(), tid); 290 cpu->setNextPC(tc->readNextPC(), tid); 291#if !FULL_SYSTEM 292 this->thread->funcExeInst = tc->readFuncExeInst(); 293#endif 294} 295 296template <class Impl> 297void 298O3ThreadContext<Impl>::clearArchRegs() 299{} 300 301template <class Impl> 302uint64_t 303O3ThreadContext<Impl>::readIntReg(int reg_idx) 304{ 305 return cpu->readArchIntReg(reg_idx, thread->readTid()); 306} 307 308template <class Impl> 309TheISA::FloatReg 310O3ThreadContext<Impl>::readFloatReg(int reg_idx, int width) 311{ 312 switch(width) { 313 case 32: 314 return cpu->readArchFloatRegSingle(reg_idx, thread->readTid()); 315 case 64: 316 return cpu->readArchFloatRegDouble(reg_idx, thread->readTid()); 317 default: 318 panic("Unsupported width!"); 319 return 0; 320 } 321} 322 323template <class Impl> 324TheISA::FloatReg 325O3ThreadContext<Impl>::readFloatReg(int reg_idx) 326{ 327 return cpu->readArchFloatRegSingle(reg_idx, thread->readTid()); 328} 329 330template <class Impl> 331TheISA::FloatRegBits 332O3ThreadContext<Impl>::readFloatRegBits(int reg_idx, int width) 333{ 334 DPRINTF(Fault, "Reading floatint register through the TC!\n"); 335 return cpu->readArchFloatRegInt(reg_idx, thread->readTid()); 336} 337 338template <class Impl> 339TheISA::FloatRegBits 340O3ThreadContext<Impl>::readFloatRegBits(int reg_idx) 341{ 342 return cpu->readArchFloatRegInt(reg_idx, thread->readTid()); 343} 344 345template <class Impl> 346void 347O3ThreadContext<Impl>::setIntReg(int reg_idx, uint64_t val) 348{ 349 cpu->setArchIntReg(reg_idx, val, thread->readTid()); 350 351 // Squash if we're not already in a state update mode. 352 if (!thread->trapPending && !thread->inSyscall) { 353 cpu->squashFromTC(thread->readTid()); 354 } 355} 356 357template <class Impl> 358void 359O3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val, int width) 360{ 361 switch(width) { 362 case 32: 363 cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid()); 364 break; 365 case 64: 366 cpu->setArchFloatRegDouble(reg_idx, val, thread->readTid()); 367 break; 368 } 369 370 // Squash if we're not already in a state update mode. 371 if (!thread->trapPending && !thread->inSyscall) { 372 cpu->squashFromTC(thread->readTid()); 373 } 374} 375 376template <class Impl> 377void 378O3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val) 379{ 380 cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid()); 381 382 if (!thread->trapPending && !thread->inSyscall) { 383 cpu->squashFromTC(thread->readTid()); 384 } 385} 386 387template <class Impl> 388void 389O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, 390 int width) 391{ 392 DPRINTF(Fault, "Setting floatint register through the TC!\n"); 393 cpu->setArchFloatRegInt(reg_idx, val, thread->readTid()); 394 395 // Squash if we're not already in a state update mode. 396 if (!thread->trapPending && !thread->inSyscall) { 397 cpu->squashFromTC(thread->readTid()); 398 } 399} 400 401template <class Impl> 402void 403O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 404{ 405 cpu->setArchFloatRegInt(reg_idx, val, thread->readTid()); 406 407 // Squash if we're not already in a state update mode. 408 if (!thread->trapPending && !thread->inSyscall) { 409 cpu->squashFromTC(thread->readTid()); 410 } 411} 412 413template <class Impl> 414void 415O3ThreadContext<Impl>::setPC(uint64_t val) 416{ 417 cpu->setPC(val, thread->readTid()); 418 419 // Squash if we're not already in a state update mode. 420 if (!thread->trapPending && !thread->inSyscall) { 421 cpu->squashFromTC(thread->readTid()); 422 } 423} 424 425template <class Impl> 426void 427O3ThreadContext<Impl>::setNextPC(uint64_t val) 428{ 429 cpu->setNextPC(val, thread->readTid()); 430 431 // Squash if we're not already in a state update mode. 432 if (!thread->trapPending && !thread->inSyscall) { 433 cpu->squashFromTC(thread->readTid()); 434 } 435} 436 437template <class Impl> 438Fault 439O3ThreadContext<Impl>::setMiscReg(int misc_reg, const MiscReg &val) 440{ 441 Fault ret_fault = cpu->setMiscReg(misc_reg, val, thread->readTid()); 442 443 // Squash if we're not already in a state update mode. 444 if (!thread->trapPending && !thread->inSyscall) { 445 cpu->squashFromTC(thread->readTid()); 446 } 447 448 return ret_fault; 449} 450 451template <class Impl> 452Fault 453O3ThreadContext<Impl>::setMiscRegWithEffect(int misc_reg, 454 const MiscReg &val) 455{ 456 Fault ret_fault = cpu->setMiscRegWithEffect(misc_reg, val, 457 thread->readTid()); 458 459 // Squash if we're not already in a state update mode. 460 if (!thread->trapPending && !thread->inSyscall) { 461 cpu->squashFromTC(thread->readTid()); 462 } 463 464 return ret_fault; 465} 466 467#if !FULL_SYSTEM 468 469template <class Impl> 470TheISA::IntReg 471O3ThreadContext<Impl>::getSyscallArg(int i) 472{ 473 return cpu->getSyscallArg(i, thread->readTid()); 474} 475 476template <class Impl> 477void 478O3ThreadContext<Impl>::setSyscallArg(int i, IntReg val) 479{ 480 cpu->setSyscallArg(i, val, thread->readTid()); 481} 482 483template <class Impl> 484void 485O3ThreadContext<Impl>::setSyscallReturn(SyscallReturn return_value) 486{ 487 cpu->setSyscallReturn(return_value, thread->readTid()); 488} 489 490#endif // FULL_SYSTEM 491 492