thread_context_impl.hh revision 2875:9b6f6b75b187
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 Thread Context %d\n", 119 getThreadNum()); 120 121 if (thread->status() == ThreadContext::Active) 122 return; 123 124#if FULL_SYSTEM 125 thread->lastActivate = curTick; 126#endif 127 128 if (thread->status() == ThreadContext::Unallocated) { 129 cpu->activateWhenReady(thread->readTid()); 130 return; 131 } 132 133 thread->setStatus(ThreadContext::Active); 134 135 // status() == Suspended 136 cpu->activateContext(thread->readTid(), delay); 137} 138 139template <class Impl> 140void 141O3ThreadContext<Impl>::suspend() 142{ 143 DPRINTF(O3CPU, "Calling suspend on Thread Context %d\n", 144 getThreadNum()); 145 146 if (thread->status() == ThreadContext::Suspended) 147 return; 148 149#if FULL_SYSTEM 150 thread->lastActivate = curTick; 151 thread->lastSuspend = curTick; 152#endif 153/* 154#if FULL_SYSTEM 155 // Don't change the status from active if there are pending interrupts 156 if (cpu->check_interrupts()) { 157 assert(status() == ThreadContext::Active); 158 return; 159 } 160#endif 161*/ 162 thread->setStatus(ThreadContext::Suspended); 163 cpu->suspendContext(thread->readTid()); 164} 165 166template <class Impl> 167void 168O3ThreadContext<Impl>::deallocate(int delay) 169{ 170 DPRINTF(O3CPU, "Calling deallocate on Thread Context %d\n", 171 getThreadNum()); 172 173 if (thread->status() == ThreadContext::Unallocated) 174 return; 175 176 thread->setStatus(ThreadContext::Unallocated); 177 cpu->deallocateContext(thread->readTid(), delay); 178} 179 180template <class Impl> 181void 182O3ThreadContext<Impl>::halt() 183{ 184 DPRINTF(O3CPU, "Calling halt on Thread Context %d\n", 185 getThreadNum()); 186 187 if (thread->status() == ThreadContext::Halted) 188 return; 189 190 thread->setStatus(ThreadContext::Halted); 191 cpu->haltContext(thread->readTid()); 192} 193 194template <class Impl> 195void 196O3ThreadContext<Impl>::regStats(const std::string &name) 197{ 198#if FULL_SYSTEM 199 thread->kernelStats = new Kernel::Statistics(cpu->system); 200 thread->kernelStats->regStats(name + ".kern"); 201#endif 202} 203 204template <class Impl> 205void 206O3ThreadContext<Impl>::serialize(std::ostream &os) 207{ 208#if FULL_SYSTEM 209 if (thread->kernelStats) 210 thread->kernelStats->serialize(os); 211#endif 212 213} 214 215template <class Impl> 216void 217O3ThreadContext<Impl>::unserialize(Checkpoint *cp, const std::string §ion) 218{ 219#if FULL_SYSTEM 220 if (thread->kernelStats) 221 thread->kernelStats->unserialize(cp, section); 222#endif 223 224} 225 226#if FULL_SYSTEM 227template <class Impl> 228Tick 229O3ThreadContext<Impl>::readLastActivate() 230{ 231 return thread->lastActivate; 232} 233 234template <class Impl> 235Tick 236O3ThreadContext<Impl>::readLastSuspend() 237{ 238 return thread->lastSuspend; 239} 240 241template <class Impl> 242void 243O3ThreadContext<Impl>::profileClear() 244{} 245 246template <class Impl> 247void 248O3ThreadContext<Impl>::profileSample() 249{} 250#endif 251 252template <class Impl> 253TheISA::MachInst 254O3ThreadContext<Impl>:: getInst() 255{ 256 return thread->getInst(); 257} 258 259template <class Impl> 260void 261O3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc) 262{ 263 // This function will mess things up unless the ROB is empty and 264 // there are no instructions in the pipeline. 265 unsigned tid = thread->readTid(); 266 PhysRegIndex renamed_reg; 267 268 // First loop through the integer registers. 269 for (int i = 0; i < TheISA::NumIntRegs; ++i) { 270 renamed_reg = cpu->renameMap[tid].lookup(i); 271 272 DPRINTF(O3CPU, "Copying over register %i, had data %lli, " 273 "now has data %lli.\n", 274 renamed_reg, cpu->readIntReg(renamed_reg), 275 tc->readIntReg(i)); 276 277 cpu->setIntReg(renamed_reg, tc->readIntReg(i)); 278 } 279 280 // Then loop through the floating point registers. 281 for (int i = 0; i < TheISA::NumFloatRegs; ++i) { 282 renamed_reg = cpu->renameMap[tid].lookup(i + TheISA::FP_Base_DepTag); 283 cpu->setFloatRegBits(renamed_reg, 284 tc->readFloatRegBits(i)); 285 } 286 287 // Copy the misc regs. 288 copyMiscRegs(tc, this); 289 290 // Then finally set the PC and the next PC. 291 cpu->setPC(tc->readPC(), tid); 292 cpu->setNextPC(tc->readNextPC(), tid); 293#if !FULL_SYSTEM 294 this->thread->funcExeInst = tc->readFuncExeInst(); 295#endif 296} 297 298template <class Impl> 299void 300O3ThreadContext<Impl>::clearArchRegs() 301{} 302 303template <class Impl> 304uint64_t 305O3ThreadContext<Impl>::readIntReg(int reg_idx) 306{ 307 return cpu->readArchIntReg(reg_idx, thread->readTid()); 308} 309 310template <class Impl> 311FloatReg 312O3ThreadContext<Impl>::readFloatReg(int reg_idx, int width) 313{ 314 switch(width) { 315 case 32: 316 return cpu->readArchFloatRegSingle(reg_idx, thread->readTid()); 317 case 64: 318 return cpu->readArchFloatRegDouble(reg_idx, thread->readTid()); 319 default: 320 panic("Unsupported width!"); 321 return 0; 322 } 323} 324 325template <class Impl> 326FloatReg 327O3ThreadContext<Impl>::readFloatReg(int reg_idx) 328{ 329 return cpu->readArchFloatRegSingle(reg_idx, thread->readTid()); 330} 331 332template <class Impl> 333FloatRegBits 334O3ThreadContext<Impl>::readFloatRegBits(int reg_idx, int width) 335{ 336 DPRINTF(Fault, "Reading floatint register through the TC!\n"); 337 return cpu->readArchFloatRegInt(reg_idx, thread->readTid()); 338} 339 340template <class Impl> 341FloatRegBits 342O3ThreadContext<Impl>::readFloatRegBits(int reg_idx) 343{ 344 return cpu->readArchFloatRegInt(reg_idx, thread->readTid()); 345} 346 347template <class Impl> 348void 349O3ThreadContext<Impl>::setIntReg(int reg_idx, uint64_t val) 350{ 351 cpu->setArchIntReg(reg_idx, val, thread->readTid()); 352 353 // Squash if we're not already in a state update mode. 354 if (!thread->trapPending && !thread->inSyscall) { 355 cpu->squashFromTC(thread->readTid()); 356 } 357} 358 359template <class Impl> 360void 361O3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val, int width) 362{ 363 switch(width) { 364 case 32: 365 cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid()); 366 break; 367 case 64: 368 cpu->setArchFloatRegDouble(reg_idx, val, thread->readTid()); 369 break; 370 } 371 372 // Squash if we're not already in a state update mode. 373 if (!thread->trapPending && !thread->inSyscall) { 374 cpu->squashFromTC(thread->readTid()); 375 } 376} 377 378template <class Impl> 379void 380O3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val) 381{ 382 cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid()); 383 384 if (!thread->trapPending && !thread->inSyscall) { 385 cpu->squashFromTC(thread->readTid()); 386 } 387} 388 389template <class Impl> 390void 391O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, 392 int width) 393{ 394 DPRINTF(Fault, "Setting floatint register through the TC!\n"); 395 cpu->setArchFloatRegInt(reg_idx, val, thread->readTid()); 396 397 // Squash if we're not already in a state update mode. 398 if (!thread->trapPending && !thread->inSyscall) { 399 cpu->squashFromTC(thread->readTid()); 400 } 401} 402 403template <class Impl> 404void 405O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 406{ 407 cpu->setArchFloatRegInt(reg_idx, val, thread->readTid()); 408 409 // Squash if we're not already in a state update mode. 410 if (!thread->trapPending && !thread->inSyscall) { 411 cpu->squashFromTC(thread->readTid()); 412 } 413} 414 415template <class Impl> 416void 417O3ThreadContext<Impl>::setPC(uint64_t val) 418{ 419 cpu->setPC(val, thread->readTid()); 420 421 // Squash if we're not already in a state update mode. 422 if (!thread->trapPending && !thread->inSyscall) { 423 cpu->squashFromTC(thread->readTid()); 424 } 425} 426 427template <class Impl> 428void 429O3ThreadContext<Impl>::setNextPC(uint64_t val) 430{ 431 cpu->setNextPC(val, thread->readTid()); 432 433 // Squash if we're not already in a state update mode. 434 if (!thread->trapPending && !thread->inSyscall) { 435 cpu->squashFromTC(thread->readTid()); 436 } 437} 438 439template <class Impl> 440Fault 441O3ThreadContext<Impl>::setMiscReg(int misc_reg, const MiscReg &val) 442{ 443 Fault ret_fault = cpu->setMiscReg(misc_reg, val, thread->readTid()); 444 445 // Squash if we're not already in a state update mode. 446 if (!thread->trapPending && !thread->inSyscall) { 447 cpu->squashFromTC(thread->readTid()); 448 } 449 450 return ret_fault; 451} 452 453template <class Impl> 454Fault 455O3ThreadContext<Impl>::setMiscRegWithEffect(int misc_reg, 456 const MiscReg &val) 457{ 458 Fault ret_fault = cpu->setMiscRegWithEffect(misc_reg, val, 459 thread->readTid()); 460 461 // Squash if we're not already in a state update mode. 462 if (!thread->trapPending && !thread->inSyscall) { 463 cpu->squashFromTC(thread->readTid()); 464 } 465 466 return ret_fault; 467} 468 469#if !FULL_SYSTEM 470 471template <class Impl> 472TheISA::IntReg 473O3ThreadContext<Impl>::getSyscallArg(int i) 474{ 475 return cpu->getSyscallArg(i, thread->readTid()); 476} 477 478template <class Impl> 479void 480O3ThreadContext<Impl>::setSyscallArg(int i, IntReg val) 481{ 482 cpu->setSyscallArg(i, val, thread->readTid()); 483} 484 485template <class Impl> 486void 487O3ThreadContext<Impl>::setSyscallReturn(SyscallReturn return_value) 488{ 489 cpu->setSyscallReturn(return_value, thread->readTid()); 490} 491 492#endif // FULL_SYSTEM 493 494