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