thread_context_impl.hh revision 2834
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 35using namespace TheISA; 36 37#if FULL_SYSTEM 38template <class Impl> 39VirtualPort * 40O3ThreadContext<Impl>::getVirtPort(ThreadContext *src_tc) 41{ 42 if (!src_tc) 43 return thread->getVirtPort(); 44 45 VirtualPort *vp; 46 Port *mem_port; 47 48 vp = new VirtualPort("tc-vport", src_tc); 49 mem_port = cpu->system->physmem->getPort("functional"); 50 mem_port->setPeer(vp); 51 vp->setPeer(mem_port); 52 return vp; 53} 54 55template <class Impl> 56void 57O3ThreadContext<Impl>::dumpFuncProfile() 58{ 59 // Currently not supported 60} 61#endif 62 63template <class Impl> 64void 65O3ThreadContext<Impl>::takeOverFrom(ThreadContext *old_context) 66{ 67 // some things should already be set up 68#if FULL_SYSTEM 69 assert(getSystemPtr() == old_context->getSystemPtr()); 70#else 71 assert(getProcessPtr() == old_context->getProcessPtr()); 72#endif 73 74 // copy over functional state 75 setStatus(old_context->status()); 76 copyArchRegs(old_context); 77 setCpuId(old_context->readCpuId()); 78 79#if !FULL_SYSTEM 80 thread->funcExeInst = old_context->readFuncExeInst(); 81#else 82 EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent(); 83 if (other_quiesce) { 84 // Point the quiesce event's TC at this TC so that it wakes up 85 // the proper CPU. 86 other_quiesce->tc = this; 87 } 88 if (thread->quiesceEvent) { 89 thread->quiesceEvent->tc = this; 90 } 91 92 // Transfer kernel stats from one CPU to the other. 93 thread->kernelStats = old_context->getKernelStats(); 94// storeCondFailures = 0; 95 cpu->lockFlag = false; 96#endif 97 98 old_context->setStatus(ThreadContext::Unallocated); 99 100 thread->inSyscall = false; 101 thread->trapPending = false; 102} 103 104#if FULL_SYSTEM 105template <class Impl> 106void 107O3ThreadContext<Impl>::delVirtPort(VirtualPort *vp) 108{ 109 delete vp->getPeer(); 110 delete vp; 111} 112#endif 113 114template <class Impl> 115void 116O3ThreadContext<Impl>::activate(int delay) 117{ 118 DPRINTF(O3CPU, "Calling activate on AlphaTC\n"); 119 120 if (thread->status() == ThreadContext::Active) 121 return; 122 123#if FULL_SYSTEM 124 thread->lastActivate = curTick; 125#endif 126 127 if (thread->status() == ThreadContext::Unallocated) { 128 cpu->activateWhenReady(thread->readTid()); 129 return; 130 } 131 132 thread->setStatus(ThreadContext::Active); 133 134 // status() == Suspended 135 cpu->activateContext(thread->readTid(), delay); 136} 137 138template <class Impl> 139void 140O3ThreadContext<Impl>::suspend() 141{ 142 DPRINTF(O3CPU, "Calling suspend on AlphaTC\n"); 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() 167{ 168 DPRINTF(O3CPU, "Calling deallocate on AlphaTC\n"); 169 170 if (thread->status() == ThreadContext::Unallocated) 171 return; 172 173 thread->setStatus(ThreadContext::Unallocated); 174 cpu->deallocateContext(thread->readTid()); 175} 176 177template <class Impl> 178void 179O3ThreadContext<Impl>::halt() 180{ 181 DPRINTF(O3CPU, "Calling halt on AlphaTC\n"); 182 183 if (thread->status() == ThreadContext::Halted) 184 return; 185 186 thread->setStatus(ThreadContext::Halted); 187 cpu->haltContext(thread->readTid()); 188} 189 190template <class Impl> 191void 192O3ThreadContext<Impl>::regStats(const std::string &name) 193{ 194#if FULL_SYSTEM 195 thread->kernelStats = new Kernel::Statistics(cpu->system); 196 thread->kernelStats->regStats(name + ".kern"); 197#endif 198} 199 200template <class Impl> 201void 202O3ThreadContext<Impl>::serialize(std::ostream &os) 203{ 204#if FULL_SYSTEM 205 if (thread->kernelStats) 206 thread->kernelStats->serialize(os); 207#endif 208 209} 210 211template <class Impl> 212void 213O3ThreadContext<Impl>::unserialize(Checkpoint *cp, const std::string §ion) 214{ 215#if FULL_SYSTEM 216 if (thread->kernelStats) 217 thread->kernelStats->unserialize(cp, section); 218#endif 219 220} 221 222#if FULL_SYSTEM 223template <class Impl> 224Tick 225O3ThreadContext<Impl>::readLastActivate() 226{ 227 return thread->lastActivate; 228} 229 230template <class Impl> 231Tick 232O3ThreadContext<Impl>::readLastSuspend() 233{ 234 return thread->lastSuspend; 235} 236 237template <class Impl> 238void 239O3ThreadContext<Impl>::profileClear() 240{} 241 242template <class Impl> 243void 244O3ThreadContext<Impl>::profileSample() 245{} 246#endif 247 248template <class Impl> 249TheISA::MachInst 250O3ThreadContext<Impl>:: getInst() 251{ 252 return thread->getInst(); 253} 254 255template <class Impl> 256void 257O3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc) 258{ 259 // This function will mess things up unless the ROB is empty and 260 // there are no instructions in the pipeline. 261 unsigned tid = thread->readTid(); 262 PhysRegIndex renamed_reg; 263 264 // First loop through the integer registers. 265 for (int i = 0; i < TheISA::NumIntRegs; ++i) { 266 renamed_reg = cpu->renameMap[tid].lookup(i); 267 268 DPRINTF(O3CPU, "Copying over register %i, had data %lli, " 269 "now has data %lli.\n", 270 renamed_reg, cpu->readIntReg(renamed_reg), 271 tc->readIntReg(i)); 272 273 cpu->setIntReg(renamed_reg, tc->readIntReg(i)); 274 } 275 276 // Then loop through the floating point registers. 277 for (int i = 0; i < TheISA::NumFloatRegs; ++i) { 278 renamed_reg = cpu->renameMap[tid].lookup(i + TheISA::FP_Base_DepTag); 279 cpu->setFloatRegBits(renamed_reg, 280 tc->readFloatRegBits(i)); 281 } 282 283 // Copy the misc regs. 284 copyMiscRegs(tc, this); 285 286 // Then finally set the PC and the next PC. 287 cpu->setPC(tc->readPC(), tid); 288 cpu->setNextPC(tc->readNextPC(), tid); 289#if !FULL_SYSTEM 290 this->thread->funcExeInst = tc->readFuncExeInst(); 291#endif 292} 293 294template <class Impl> 295void 296O3ThreadContext<Impl>::clearArchRegs() 297{} 298 299template <class Impl> 300uint64_t 301O3ThreadContext<Impl>::readIntReg(int reg_idx) 302{ 303 return cpu->readArchIntReg(reg_idx, thread->readTid()); 304} 305 306template <class Impl> 307FloatReg 308O3ThreadContext<Impl>::readFloatReg(int reg_idx, int width) 309{ 310 switch(width) { 311 case 32: 312 return cpu->readArchFloatRegSingle(reg_idx, thread->readTid()); 313 case 64: 314 return cpu->readArchFloatRegDouble(reg_idx, thread->readTid()); 315 default: 316 panic("Unsupported width!"); 317 return 0; 318 } 319} 320 321template <class Impl> 322FloatReg 323O3ThreadContext<Impl>::readFloatReg(int reg_idx) 324{ 325 return cpu->readArchFloatRegSingle(reg_idx, thread->readTid()); 326} 327 328template <class Impl> 329FloatRegBits 330O3ThreadContext<Impl>::readFloatRegBits(int reg_idx, int width) 331{ 332 DPRINTF(Fault, "Reading floatint register through the TC!\n"); 333 return cpu->readArchFloatRegInt(reg_idx, thread->readTid()); 334} 335 336template <class Impl> 337FloatRegBits 338O3ThreadContext<Impl>::readFloatRegBits(int reg_idx) 339{ 340 return cpu->readArchFloatRegInt(reg_idx, thread->readTid()); 341} 342 343template <class Impl> 344void 345O3ThreadContext<Impl>::setIntReg(int reg_idx, uint64_t val) 346{ 347 cpu->setArchIntReg(reg_idx, val, thread->readTid()); 348 349 // Squash if we're not already in a state update mode. 350 if (!thread->trapPending && !thread->inSyscall) { 351 cpu->squashFromTC(thread->readTid()); 352 } 353} 354 355template <class Impl> 356void 357O3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val, int width) 358{ 359 switch(width) { 360 case 32: 361 cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid()); 362 break; 363 case 64: 364 cpu->setArchFloatRegDouble(reg_idx, val, thread->readTid()); 365 break; 366 } 367 368 // Squash if we're not already in a state update mode. 369 if (!thread->trapPending && !thread->inSyscall) { 370 cpu->squashFromTC(thread->readTid()); 371 } 372} 373 374template <class Impl> 375void 376O3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val) 377{ 378 cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid()); 379 380 if (!thread->trapPending && !thread->inSyscall) { 381 cpu->squashFromTC(thread->readTid()); 382 } 383} 384 385template <class Impl> 386void 387O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, 388 int width) 389{ 390 DPRINTF(Fault, "Setting floatint register through the TC!\n"); 391 cpu->setArchFloatRegInt(reg_idx, val, thread->readTid()); 392 393 // Squash if we're not already in a state update mode. 394 if (!thread->trapPending && !thread->inSyscall) { 395 cpu->squashFromTC(thread->readTid()); 396 } 397} 398 399template <class Impl> 400void 401O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 402{ 403 cpu->setArchFloatRegInt(reg_idx, val, thread->readTid()); 404 405 // Squash if we're not already in a state update mode. 406 if (!thread->trapPending && !thread->inSyscall) { 407 cpu->squashFromTC(thread->readTid()); 408 } 409} 410 411template <class Impl> 412void 413O3ThreadContext<Impl>::setPC(uint64_t val) 414{ 415 cpu->setPC(val, thread->readTid()); 416 417 // Squash if we're not already in a state update mode. 418 if (!thread->trapPending && !thread->inSyscall) { 419 cpu->squashFromTC(thread->readTid()); 420 } 421} 422 423template <class Impl> 424void 425O3ThreadContext<Impl>::setNextPC(uint64_t val) 426{ 427 cpu->setNextPC(val, thread->readTid()); 428 429 // Squash if we're not already in a state update mode. 430 if (!thread->trapPending && !thread->inSyscall) { 431 cpu->squashFromTC(thread->readTid()); 432 } 433} 434 435template <class Impl> 436Fault 437O3ThreadContext<Impl>::setMiscReg(int misc_reg, const MiscReg &val) 438{ 439 Fault ret_fault = cpu->setMiscReg(misc_reg, val, thread->readTid()); 440 441 // Squash if we're not already in a state update mode. 442 if (!thread->trapPending && !thread->inSyscall) { 443 cpu->squashFromTC(thread->readTid()); 444 } 445 446 return ret_fault; 447} 448 449template <class Impl> 450Fault 451O3ThreadContext<Impl>::setMiscRegWithEffect(int misc_reg, 452 const MiscReg &val) 453{ 454 Fault ret_fault = cpu->setMiscRegWithEffect(misc_reg, val, 455 thread->readTid()); 456 457 // Squash if we're not already in a state update mode. 458 if (!thread->trapPending && !thread->inSyscall) { 459 cpu->squashFromTC(thread->readTid()); 460 } 461 462 return ret_fault; 463} 464 465#if !FULL_SYSTEM 466 467template <class Impl> 468TheISA::IntReg 469O3ThreadContext<Impl>::getSyscallArg(int i) 470{ 471 return cpu->getSyscallArg(i, thread->readTid()); 472} 473 474template <class Impl> 475void 476O3ThreadContext<Impl>::setSyscallArg(int i, IntReg val) 477{ 478 cpu->setSyscallArg(i, val, thread->readTid()); 479} 480 481template <class Impl> 482void 483O3ThreadContext<Impl>::setSyscallReturn(SyscallReturn return_value) 484{ 485 cpu->setSyscallReturn(return_value, thread->readTid()); 486} 487 488#endif // FULL_SYSTEM 489 490