mt.hh revision 10474:799c8ee4ecba
110916Sandreas.sandberg@arm.com/* 211349Sandreas.sandberg@arm.com * Copyright (c) 2007 MIPS Technologies, Inc. 310916Sandreas.sandberg@arm.com * All rights reserved. 410916Sandreas.sandberg@arm.com * 510916Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without 610916Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are 710916Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright 810916Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer; 910916Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright 1010916Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the 1110916Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution; 1210916Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its 1310916Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from 1410916Sandreas.sandberg@arm.com * this software without specific prior written permission. 1510916Sandreas.sandberg@arm.com * 1610916Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1710916Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1810916Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1910916Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2010916Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2110916Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2210916Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2310916Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2410916Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2510916Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2610916Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2710916Sandreas.sandberg@arm.com * 2810916Sandreas.sandberg@arm.com * Authors: Korey Sewell 2910916Sandreas.sandberg@arm.com */ 3010916Sandreas.sandberg@arm.com 3110916Sandreas.sandberg@arm.com#ifndef __ARCH_MIPS_MT_HH__ 3210916Sandreas.sandberg@arm.com#define __ARCH_MIPS_MT_HH__ 3310916Sandreas.sandberg@arm.com 3410916Sandreas.sandberg@arm.com/** 3510916Sandreas.sandberg@arm.com * @file 3610916Sandreas.sandberg@arm.com * 3710916Sandreas.sandberg@arm.com * ISA-specific helper functions for multithreaded execution. 3810916Sandreas.sandberg@arm.com */ 3910916Sandreas.sandberg@arm.com 4010916Sandreas.sandberg@arm.com#include <iostream> 4110916Sandreas.sandberg@arm.com 4210916Sandreas.sandberg@arm.com#include "arch/mips/faults.hh" 4310916Sandreas.sandberg@arm.com#include "arch/mips/isa_traits.hh" 4410916Sandreas.sandberg@arm.com#include "arch/mips/mt_constants.hh" 4510916Sandreas.sandberg@arm.com#include "arch/mips/pra_constants.hh" 4610916Sandreas.sandberg@arm.com#include "arch/mips/registers.hh" 4710916Sandreas.sandberg@arm.com#include "base/bitfield.hh" 4810916Sandreas.sandberg@arm.com#include "base/misc.hh" 4911619Sandreas.sandberg@arm.com#include "base/trace.hh" 5010916Sandreas.sandberg@arm.com 5110916Sandreas.sandberg@arm.comnamespace MipsISA 5210916Sandreas.sandberg@arm.com{ 5310916Sandreas.sandberg@arm.com 5410916Sandreas.sandberg@arm.comtemplate <class TC> 5510916Sandreas.sandberg@arm.cominline unsigned 5610916Sandreas.sandberg@arm.comgetVirtProcNum(TC *tc) 5710916Sandreas.sandberg@arm.com{ 5811350Sandreas.sandberg@arm.com TCBindReg tcbind = tc->readMiscRegNoEffect(MISCREG_TC_BIND); 5911350Sandreas.sandberg@arm.com return tcbind.curVPE; 6010916Sandreas.sandberg@arm.com} 6111168Sandreas.hansson@arm.com 6211168Sandreas.hansson@arm.comtemplate <class TC> 6310916Sandreas.sandberg@arm.cominline unsigned 6410916Sandreas.sandberg@arm.comgetTargetThread(TC *tc) 6511168Sandreas.hansson@arm.com{ 6611168Sandreas.hansson@arm.com VPEControlReg vpeCtrl = tc->readMiscRegNoEffect(MISCREG_VPE_CONTROL); 6711168Sandreas.hansson@arm.com return vpeCtrl.targTC; 6810916Sandreas.sandberg@arm.com} 6911349Sandreas.sandberg@arm.com 7010916Sandreas.sandberg@arm.comtemplate <class TC> 7111349Sandreas.sandberg@arm.cominline void 7211349Sandreas.sandberg@arm.comhaltThread(TC *tc) 7310916Sandreas.sandberg@arm.com{ 7410916Sandreas.sandberg@arm.com if (tc->status() == TC::Active) { 7511349Sandreas.sandberg@arm.com tc->halt(); 7611349Sandreas.sandberg@arm.com 7710916Sandreas.sandberg@arm.com // Save last known PC in TCRestart 7810916Sandreas.sandberg@arm.com // @TODO: Needs to check if this is a branch and if so, 7910916Sandreas.sandberg@arm.com // take previous instruction 8010916Sandreas.sandberg@arm.com PCState pc = tc->pcState(); 8110916Sandreas.sandberg@arm.com tc->setMiscReg(MISCREG_TC_RESTART, pc.npc()); 8210916Sandreas.sandberg@arm.com 8310916Sandreas.sandberg@arm.com warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", 8410916Sandreas.sandberg@arm.com curTick(), tc->threadId(), tc->getCpuPtr()->name(), 8510916Sandreas.sandberg@arm.com pc.pc(), pc.npc()); 8610916Sandreas.sandberg@arm.com } 8710916Sandreas.sandberg@arm.com} 8810916Sandreas.sandberg@arm.com 8911349Sandreas.sandberg@arm.comtemplate <class TC> 9011349Sandreas.sandberg@arm.cominline void 9111349Sandreas.sandberg@arm.comrestoreThread(TC *tc) 9211349Sandreas.sandberg@arm.com{ 9311349Sandreas.sandberg@arm.com if (tc->status() != TC::Active) { 9411349Sandreas.sandberg@arm.com // Restore PC from TCRestart 9511349Sandreas.sandberg@arm.com Addr restartPC = tc->readMiscRegNoEffect(MISCREG_TC_RESTART); 9611349Sandreas.sandberg@arm.com 9711349Sandreas.sandberg@arm.com // TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY 9811349Sandreas.sandberg@arm.com tc->pcState(restartPC); 9910916Sandreas.sandberg@arm.com tc->activate(); 10010916Sandreas.sandberg@arm.com 10110916Sandreas.sandberg@arm.com warn("%i: Restoring thread %i in %s @ PC %x", 10210916Sandreas.sandberg@arm.com curTick(), tc->threadId(), tc->getCpuPtr()->name(), restartPC); 10310916Sandreas.sandberg@arm.com } 10410916Sandreas.sandberg@arm.com} 10510916Sandreas.sandberg@arm.com 10610916Sandreas.sandberg@arm.comtemplate <class TC> 10710916Sandreas.sandberg@arm.comvoid 10810916Sandreas.sandberg@arm.comforkThread(TC *tc, Fault &fault, int Rd_bits, int Rs, int Rt) 10910916Sandreas.sandberg@arm.com{ 11010916Sandreas.sandberg@arm.com MVPConf0Reg mvpConf = tc->readMiscRegNoEffect(MISCREG_MVP_CONF0); 11110916Sandreas.sandberg@arm.com int num_threads = mvpConf.ptc + 1; 11210916Sandreas.sandberg@arm.com 11310916Sandreas.sandberg@arm.com int success = 0; 11410916Sandreas.sandberg@arm.com for (ThreadID tid = 0; tid < num_threads && success == 0; tid++) { 11510916Sandreas.sandberg@arm.com TCBindReg tidTCBind = 11611349Sandreas.sandberg@arm.com tc->readRegOtherThread(MISCREG_TC_BIND + Misc_Reg_Base, tid); 11711349Sandreas.sandberg@arm.com TCBindReg tcBind = tc->readMiscRegNoEffect(MISCREG_TC_BIND); 11811349Sandreas.sandberg@arm.com 11911349Sandreas.sandberg@arm.com if (tidTCBind.curVPE == tcBind.curVPE) { 12011349Sandreas.sandberg@arm.com 12111349Sandreas.sandberg@arm.com TCStatusReg tidTCStatus = 12211349Sandreas.sandberg@arm.com tc->readRegOtherThread(MISCREG_TC_STATUS + 12311349Sandreas.sandberg@arm.com Misc_Reg_Base,tid); 12411349Sandreas.sandberg@arm.com 12511349Sandreas.sandberg@arm.com TCHaltReg tidTCHalt = 12611349Sandreas.sandberg@arm.com tc->readRegOtherThread(MISCREG_TC_HALT + Misc_Reg_Base,tid); 12711349Sandreas.sandberg@arm.com 12811349Sandreas.sandberg@arm.com if (tidTCStatus.da == 1 && tidTCHalt.h == 0 && 12911349Sandreas.sandberg@arm.com tidTCStatus.a == 0 && success == 0) { 13011349Sandreas.sandberg@arm.com 13111349Sandreas.sandberg@arm.com tc->setRegOtherThread(MISCREG_TC_RESTART + 13211350Sandreas.sandberg@arm.com Misc_Reg_Base, Rs, tid); 13311350Sandreas.sandberg@arm.com tc->setRegOtherThread(Rd_bits, Rt, tid); 13411350Sandreas.sandberg@arm.com 13511350Sandreas.sandberg@arm.com StatusReg status = tc->readMiscReg(MISCREG_STATUS); 13611350Sandreas.sandberg@arm.com TCStatusReg tcStatus = tc->readMiscReg(MISCREG_TC_STATUS); 13711350Sandreas.sandberg@arm.com 13811350Sandreas.sandberg@arm.com // Set Run-State to Running 13911350Sandreas.sandberg@arm.com tidTCStatus.rnst = 0; 14011349Sandreas.sandberg@arm.com // Set Delay-Slot to 0 14111349Sandreas.sandberg@arm.com tidTCStatus.tds = 0; 14211349Sandreas.sandberg@arm.com // Set Dirty TC to 1 14311349Sandreas.sandberg@arm.com tidTCStatus.dt = 1; 14411349Sandreas.sandberg@arm.com // Set Activated to 1 14511349Sandreas.sandberg@arm.com tidTCStatus.a = 1; 14611349Sandreas.sandberg@arm.com // Set status to previous thread's status 14711349Sandreas.sandberg@arm.com tidTCStatus.tksu = status.ksu; 14811349Sandreas.sandberg@arm.com // Set ASID to previous thread's state 14911349Sandreas.sandberg@arm.com tidTCStatus.asid = tcStatus.asid; 15011349Sandreas.sandberg@arm.com 15111349Sandreas.sandberg@arm.com // Write Status Register 15211349Sandreas.sandberg@arm.com tc->setRegOtherThread(MISCREG_TC_STATUS + Misc_Reg_Base, 15311349Sandreas.sandberg@arm.com tidTCStatus, tid); 15411349Sandreas.sandberg@arm.com 15511349Sandreas.sandberg@arm.com // Mark As Successful Fork 15611349Sandreas.sandberg@arm.com success = 1; 15711349Sandreas.sandberg@arm.com } 15811349Sandreas.sandberg@arm.com } else { 15911350Sandreas.sandberg@arm.com std::cerr << "Bad VPEs" << std::endl; 16011350Sandreas.sandberg@arm.com } 16111350Sandreas.sandberg@arm.com } 16211350Sandreas.sandberg@arm.com 16311350Sandreas.sandberg@arm.com if (success == 0) { 16411350Sandreas.sandberg@arm.com VPEControlReg vpeControl = 16511350Sandreas.sandberg@arm.com tc->readMiscRegNoEffect(MISCREG_VPE_CONTROL); 16611350Sandreas.sandberg@arm.com vpeControl.excpt = 1; 16711350Sandreas.sandberg@arm.com tc->setMiscReg(MISCREG_VPE_CONTROL, vpeControl); 16811350Sandreas.sandberg@arm.com fault = std::make_shared<ThreadFault>(); 16911350Sandreas.sandberg@arm.com } 17011350Sandreas.sandberg@arm.com} 17111349Sandreas.sandberg@arm.com 17210916Sandreas.sandberg@arm.com 17310916Sandreas.sandberg@arm.comtemplate <class TC> 17410916Sandreas.sandberg@arm.comint 17510916Sandreas.sandberg@arm.comyieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask) 17610916Sandreas.sandberg@arm.com{ 17710916Sandreas.sandberg@arm.com if (src_reg == 0) { 17810916Sandreas.sandberg@arm.com MVPConf0Reg mvpConf0 = tc->readMiscRegNoEffect(MISCREG_MVP_CONF0); 17910916Sandreas.sandberg@arm.com ThreadID num_threads = mvpConf0.ptc + 1; 18010916Sandreas.sandberg@arm.com 18110916Sandreas.sandberg@arm.com int ok = 0; 18210916Sandreas.sandberg@arm.com 18310916Sandreas.sandberg@arm.com // Get Current VPE & TC numbers from calling thread 18410916Sandreas.sandberg@arm.com TCBindReg tcBind = tc->readMiscRegNoEffect(MISCREG_TC_BIND); 18510916Sandreas.sandberg@arm.com 18610916Sandreas.sandberg@arm.com for (ThreadID tid = 0; tid < num_threads; tid++) { 18710916Sandreas.sandberg@arm.com TCStatusReg tidTCStatus = 18810916Sandreas.sandberg@arm.com tc->readRegOtherThread(MISCREG_TC_STATUS + Misc_Reg_Base, 18910916Sandreas.sandberg@arm.com tid); 19011619Sandreas.sandberg@arm.com TCHaltReg tidTCHalt = 19111619Sandreas.sandberg@arm.com tc->readRegOtherThread(MISCREG_TC_HALT + Misc_Reg_Base, 19211619Sandreas.sandberg@arm.com tid); 19311619Sandreas.sandberg@arm.com TCBindReg tidTCBind = 19411619Sandreas.sandberg@arm.com tc->readRegOtherThread(MISCREG_TC_BIND + Misc_Reg_Base, 19511619Sandreas.sandberg@arm.com tid); 19611619Sandreas.sandberg@arm.com 19711619Sandreas.sandberg@arm.com if (tidTCBind.curVPE == tcBind.curVPE && 19811619Sandreas.sandberg@arm.com tidTCBind.curTC == tcBind.curTC && 19911619Sandreas.sandberg@arm.com tidTCStatus.da == 1 && 20011619Sandreas.sandberg@arm.com tidTCHalt.h == 0 && 20111619Sandreas.sandberg@arm.com tidTCStatus.a == 1) { 20211619Sandreas.sandberg@arm.com ok = 1; 20311619Sandreas.sandberg@arm.com } 20410916Sandreas.sandberg@arm.com } 205 206 if (ok == 1) { 207 TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 208 tcStatus.a = 0; 209 tc->setMiscReg(MISCREG_TC_STATUS, tcStatus); 210 warn("%i: Deactivating Hardware Thread Context #%i", 211 curTick(), tc->threadId()); 212 } 213 } else if (src_reg > 0) { 214 if (src_reg && !yield_mask != 0) { 215 VPEControlReg vpeControl = tc->readMiscReg(MISCREG_VPE_CONTROL); 216 vpeControl.excpt = 2; 217 tc->setMiscReg(MISCREG_VPE_CONTROL, vpeControl); 218 fault = std::make_shared<ThreadFault>(); 219 } else { 220 } 221 } else if (src_reg != -2) { 222 TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 223 VPEControlReg vpeControl = 224 tc->readMiscRegNoEffect(MISCREG_VPE_CONTROL); 225 226 if (vpeControl.ysi == 1 && tcStatus.dt == 1 ) { 227 vpeControl.excpt = 4; 228 fault = std::make_shared<ThreadFault>(); 229 } else { 230 } 231 } 232 233 return src_reg & yield_mask; 234} 235 236 237// TC will usually be a object derived from ThreadContext 238// (src/cpu/thread_context.hh) 239template <class TC> 240inline void 241updateStatusView(TC *tc) 242{ 243 // TCStatus' register view must be the same as 244 // Status register view for CU, MX, KSU bits 245 TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 246 StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS); 247 248 status.cu = tcStatus.tcu; 249 status.mx = tcStatus.tmx; 250 status.ksu = tcStatus.tksu; 251 252 tc->setMiscRegNoEffect(MISCREG_STATUS, status); 253} 254 255// TC will usually be a object derived from ThreadContext 256// (src/cpu/thread_context.hh) 257template <class TC> 258inline void 259updateTCStatusView(TC *tc) 260{ 261 // TCStatus' register view must be the same as 262 // Status register view for CU, MX, KSU bits 263 TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 264 StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS); 265 266 tcStatus.tcu = status.cu; 267 tcStatus.tmx = status.mx; 268 tcStatus.tksu = status.ksu; 269 270 tc->setMiscRegNoEffect(MISCREG_TC_STATUS, tcStatus); 271} 272 273} // namespace MipsISA 274 275 276#endif 277