mt.hh revision 13899
14661Sksewell@umich.edu/* 25268Sksewell@umich.edu * Copyright (c) 2007 MIPS Technologies, Inc. 35268Sksewell@umich.edu * All rights reserved. 44661Sksewell@umich.edu * 55268Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without 65268Sksewell@umich.edu * modification, are permitted provided that the following conditions are 75268Sksewell@umich.edu * met: redistributions of source code must retain the above copyright 85268Sksewell@umich.edu * notice, this list of conditions and the following disclaimer; 95268Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright 105268Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the 115268Sksewell@umich.edu * documentation and/or other materials provided with the distribution; 125268Sksewell@umich.edu * neither the name of the copyright holders nor the names of its 135268Sksewell@umich.edu * contributors may be used to endorse or promote products derived from 145268Sksewell@umich.edu * this software without specific prior written permission. 154661Sksewell@umich.edu * 165268Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 175268Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 185268Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 195268Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 205268Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 215268Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225268Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 235268Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245268Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255268Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265268Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275222Sksewell@umich.edu * 285254Sksewell@umich.edu * Authors: Korey Sewell 294661Sksewell@umich.edu */ 304661Sksewell@umich.edu 314661Sksewell@umich.edu#ifndef __ARCH_MIPS_MT_HH__ 324661Sksewell@umich.edu#define __ARCH_MIPS_MT_HH__ 334661Sksewell@umich.edu 344661Sksewell@umich.edu/** 354661Sksewell@umich.edu * @file 364661Sksewell@umich.edu * 374661Sksewell@umich.edu * ISA-specific helper functions for multithreaded execution. 384661Sksewell@umich.edu */ 394661Sksewell@umich.edu 408229Snate@binkert.org#include <iostream> 418229Snate@binkert.org 424661Sksewell@umich.edu#include "arch/mips/faults.hh" 436329Sgblack@eecs.umich.edu#include "arch/mips/isa_traits.hh" 444661Sksewell@umich.edu#include "arch/mips/mt_constants.hh" 456376Sgblack@eecs.umich.edu#include "arch/mips/pra_constants.hh" 466329Sgblack@eecs.umich.edu#include "arch/mips/registers.hh" 474661Sksewell@umich.edu#include "base/bitfield.hh" 4812334Sgabeblack@google.com#include "base/logging.hh" 494661Sksewell@umich.edu#include "base/trace.hh" 5013899Sgabeblack@google.com#include "cpu/exec_context.hh" 514661Sksewell@umich.edu 524661Sksewell@umich.edunamespace MipsISA 534661Sksewell@umich.edu{ 544661Sksewell@umich.edu 5513899Sgabeblack@google.comstatic inline RegVal 5613899Sgabeblack@google.comreadRegOtherThread(ThreadContext *tc, const RegId ®, 5713899Sgabeblack@google.com ThreadID tid=InvalidThreadID) 5813899Sgabeblack@google.com{ 5913899Sgabeblack@google.com ThreadContext *otc = nullptr; 6013899Sgabeblack@google.com if (tid != InvalidThreadID) 6113899Sgabeblack@google.com otc = tc->getCpuPtr()->getContext(tid); 6213899Sgabeblack@google.com else 6313899Sgabeblack@google.com otc = tc; 6413899Sgabeblack@google.com 6513899Sgabeblack@google.com switch (reg.classValue()) { 6613899Sgabeblack@google.com case IntRegClass: 6713899Sgabeblack@google.com return otc->readIntReg(reg.index()); 6813899Sgabeblack@google.com break; 6913899Sgabeblack@google.com case FloatRegClass: 7013899Sgabeblack@google.com return otc->readFloatReg(reg.index()); 7113899Sgabeblack@google.com break; 7213899Sgabeblack@google.com case MiscRegClass: 7313899Sgabeblack@google.com return otc->readMiscReg(reg.index()); 7413899Sgabeblack@google.com default: 7513899Sgabeblack@google.com panic("Unexpected reg class! (%s)", reg.className()); 7613899Sgabeblack@google.com } 7713899Sgabeblack@google.com} 7813899Sgabeblack@google.com 7913899Sgabeblack@google.comstatic inline void 8013899Sgabeblack@google.comsetRegOtherThread(ThreadContext *tc, const RegId& reg, RegVal val, 8113899Sgabeblack@google.com ThreadID tid=InvalidThreadID) 8213899Sgabeblack@google.com{ 8313899Sgabeblack@google.com ThreadContext *otc = nullptr; 8413899Sgabeblack@google.com if (tid != InvalidThreadID) 8513899Sgabeblack@google.com otc = tc->getCpuPtr()->getContext(tid); 8613899Sgabeblack@google.com else 8713899Sgabeblack@google.com otc = tc; 8813899Sgabeblack@google.com 8913899Sgabeblack@google.com switch (reg.classValue()) { 9013899Sgabeblack@google.com case IntRegClass: 9113899Sgabeblack@google.com return otc->setIntReg(reg.index(), val); 9213899Sgabeblack@google.com break; 9313899Sgabeblack@google.com case FloatRegClass: 9413899Sgabeblack@google.com return otc->setFloatReg(reg.index(), val); 9513899Sgabeblack@google.com break; 9613899Sgabeblack@google.com case MiscRegClass: 9713899Sgabeblack@google.com return otc->setMiscReg(reg.index(), val); 9813899Sgabeblack@google.com default: 9913899Sgabeblack@google.com panic("Unexpected reg class! (%s)", reg.className()); 10013899Sgabeblack@google.com } 10113899Sgabeblack@google.com} 10213899Sgabeblack@google.com 10313899Sgabeblack@google.comstatic inline RegVal 10413899Sgabeblack@google.comreadRegOtherThread(ExecContext *xc, const RegId ®, 10513899Sgabeblack@google.com ThreadID tid=InvalidThreadID) 10613899Sgabeblack@google.com{ 10713899Sgabeblack@google.com return readRegOtherThread(xc->tcBase(), reg, tid); 10813899Sgabeblack@google.com} 10913899Sgabeblack@google.com 11013899Sgabeblack@google.comstatic inline void 11113899Sgabeblack@google.comsetRegOtherThread(ExecContext *xc, const RegId& reg, RegVal val, 11213899Sgabeblack@google.com ThreadID tid=InvalidThreadID) 11313899Sgabeblack@google.com{ 11413899Sgabeblack@google.com setRegOtherThread(xc->tcBase(), reg, val, tid); 11513899Sgabeblack@google.com} 11613899Sgabeblack@google.com 1174661Sksewell@umich.edutemplate <class TC> 1184661Sksewell@umich.eduinline unsigned 1194661Sksewell@umich.edugetVirtProcNum(TC *tc) 1204661Sksewell@umich.edu{ 1216383Sgblack@eecs.umich.edu TCBindReg tcbind = tc->readMiscRegNoEffect(MISCREG_TC_BIND); 1226376Sgblack@eecs.umich.edu return tcbind.curVPE; 1234661Sksewell@umich.edu} 1244661Sksewell@umich.edu 1254661Sksewell@umich.edutemplate <class TC> 1264661Sksewell@umich.eduinline unsigned 1274661Sksewell@umich.edugetTargetThread(TC *tc) 1284661Sksewell@umich.edu{ 1296383Sgblack@eecs.umich.edu VPEControlReg vpeCtrl = tc->readMiscRegNoEffect(MISCREG_VPE_CONTROL); 1306376Sgblack@eecs.umich.edu return vpeCtrl.targTC; 1314661Sksewell@umich.edu} 1324661Sksewell@umich.edu 1334661Sksewell@umich.edutemplate <class TC> 1344661Sksewell@umich.eduinline void 1354661Sksewell@umich.eduhaltThread(TC *tc) 1364661Sksewell@umich.edu{ 1374661Sksewell@umich.edu if (tc->status() == TC::Active) { 1384661Sksewell@umich.edu tc->halt(); 1394661Sksewell@umich.edu 1404661Sksewell@umich.edu // Save last known PC in TCRestart 1416378Sgblack@eecs.umich.edu // @TODO: Needs to check if this is a branch and if so, 1426378Sgblack@eecs.umich.edu // take previous instruction 1437720Sgblack@eecs.umich.edu PCState pc = tc->pcState(); 1447720Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_TC_RESTART, pc.npc()); 1454661Sksewell@umich.edu 1466378Sgblack@eecs.umich.edu warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", 1477823Ssteve.reinhardt@amd.com curTick(), tc->threadId(), tc->getCpuPtr()->name(), 1487720Sgblack@eecs.umich.edu pc.pc(), pc.npc()); 1494661Sksewell@umich.edu } 1504661Sksewell@umich.edu} 1514661Sksewell@umich.edu 1524661Sksewell@umich.edutemplate <class TC> 1534661Sksewell@umich.eduinline void 1544661Sksewell@umich.edurestoreThread(TC *tc) 1554661Sksewell@umich.edu{ 1564661Sksewell@umich.edu if (tc->status() != TC::Active) { 1574661Sksewell@umich.edu // Restore PC from TCRestart 1587720Sgblack@eecs.umich.edu Addr restartPC = tc->readMiscRegNoEffect(MISCREG_TC_RESTART); 1594661Sksewell@umich.edu 1604661Sksewell@umich.edu // TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY 1617720Sgblack@eecs.umich.edu tc->pcState(restartPC); 16210407Smitch.hayenga@arm.com tc->activate(); 1634661Sksewell@umich.edu 1646378Sgblack@eecs.umich.edu warn("%i: Restoring thread %i in %s @ PC %x", 1657823Ssteve.reinhardt@amd.com curTick(), tc->threadId(), tc->getCpuPtr()->name(), restartPC); 1664661Sksewell@umich.edu } 1674661Sksewell@umich.edu} 1684661Sksewell@umich.edu 1694661Sksewell@umich.edutemplate <class TC> 1704661Sksewell@umich.eduvoid 1714661Sksewell@umich.eduforkThread(TC *tc, Fault &fault, int Rd_bits, int Rs, int Rt) 1724661Sksewell@umich.edu{ 1736383Sgblack@eecs.umich.edu MVPConf0Reg mvpConf = tc->readMiscRegNoEffect(MISCREG_MVP_CONF0); 1746376Sgblack@eecs.umich.edu int num_threads = mvpConf.ptc + 1; 1754661Sksewell@umich.edu 1764661Sksewell@umich.edu int success = 0; 1776221Snate@binkert.org for (ThreadID tid = 0; tid < num_threads && success == 0; tid++) { 1786376Sgblack@eecs.umich.edu TCBindReg tidTCBind = 17913899Sgabeblack@google.com readRegOtherThread(tc, RegId(MiscRegClass, MISCREG_TC_BIND), tid); 1806383Sgblack@eecs.umich.edu TCBindReg tcBind = tc->readMiscRegNoEffect(MISCREG_TC_BIND); 1814661Sksewell@umich.edu 1826424Snate@binkert.org if (tidTCBind.curVPE == tcBind.curVPE) { 1834661Sksewell@umich.edu 1846376Sgblack@eecs.umich.edu TCStatusReg tidTCStatus = 18513899Sgabeblack@google.com readRegOtherThread(tc, RegId(MiscRegClass, MISCREG_TC_STATUS), 18612104Snathanael.premillieu@arm.com tid); 1874661Sksewell@umich.edu 1886376Sgblack@eecs.umich.edu TCHaltReg tidTCHalt = 18913899Sgabeblack@google.com readRegOtherThread(tc, RegId(MiscRegClass, MISCREG_TC_HALT), 19012104Snathanael.premillieu@arm.com tid); 1914661Sksewell@umich.edu 1926376Sgblack@eecs.umich.edu if (tidTCStatus.da == 1 && tidTCHalt.h == 0 && 1936376Sgblack@eecs.umich.edu tidTCStatus.a == 0 && success == 0) { 1944661Sksewell@umich.edu 19513899Sgabeblack@google.com setRegOtherThread(tc, RegId(MiscRegClass, MISCREG_TC_RESTART), 19612104Snathanael.premillieu@arm.com Rs, tid); 19713899Sgabeblack@google.com setRegOtherThread(tc, RegId(IntRegClass, Rd_bits), Rt, tid); 1984661Sksewell@umich.edu 1996383Sgblack@eecs.umich.edu StatusReg status = tc->readMiscReg(MISCREG_STATUS); 2006383Sgblack@eecs.umich.edu TCStatusReg tcStatus = tc->readMiscReg(MISCREG_TC_STATUS); 2014661Sksewell@umich.edu 2024661Sksewell@umich.edu // Set Run-State to Running 2036376Sgblack@eecs.umich.edu tidTCStatus.rnst = 0; 2044661Sksewell@umich.edu // Set Delay-Slot to 0 2056376Sgblack@eecs.umich.edu tidTCStatus.tds = 0; 2064661Sksewell@umich.edu // Set Dirty TC to 1 2076376Sgblack@eecs.umich.edu tidTCStatus.dt = 1; 2084661Sksewell@umich.edu // Set Activated to 1 2096376Sgblack@eecs.umich.edu tidTCStatus.a = 1; 2104661Sksewell@umich.edu // Set status to previous thread's status 2116376Sgblack@eecs.umich.edu tidTCStatus.tksu = status.ksu; 2124661Sksewell@umich.edu // Set ASID to previous thread's state 2136376Sgblack@eecs.umich.edu tidTCStatus.asid = tcStatus.asid; 2144661Sksewell@umich.edu 2154661Sksewell@umich.edu // Write Status Register 21613899Sgabeblack@google.com setRegOtherThread(tc, RegId(MiscRegClass, MISCREG_TC_STATUS), 2176376Sgblack@eecs.umich.edu tidTCStatus, tid); 2184661Sksewell@umich.edu 2194661Sksewell@umich.edu // Mark As Successful Fork 2204661Sksewell@umich.edu success = 1; 2214661Sksewell@umich.edu } 2224661Sksewell@umich.edu } else { 2235991Ssteve.reinhardt@amd.com std::cerr << "Bad VPEs" << std::endl; 2244661Sksewell@umich.edu } 2254661Sksewell@umich.edu } 2264661Sksewell@umich.edu 2274661Sksewell@umich.edu if (success == 0) { 2286383Sgblack@eecs.umich.edu VPEControlReg vpeControl = 2296383Sgblack@eecs.umich.edu tc->readMiscRegNoEffect(MISCREG_VPE_CONTROL); 2306376Sgblack@eecs.umich.edu vpeControl.excpt = 1; 2316383Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_VPE_CONTROL, vpeControl); 23210474Sandreas.hansson@arm.com fault = std::make_shared<ThreadFault>(); 2334661Sksewell@umich.edu } 2344661Sksewell@umich.edu} 2354661Sksewell@umich.edu 2364661Sksewell@umich.edu 2374661Sksewell@umich.edutemplate <class TC> 2384661Sksewell@umich.eduint 2394661Sksewell@umich.eduyieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask) 2404661Sksewell@umich.edu{ 2414661Sksewell@umich.edu if (src_reg == 0) { 2426383Sgblack@eecs.umich.edu MVPConf0Reg mvpConf0 = tc->readMiscRegNoEffect(MISCREG_MVP_CONF0); 2436376Sgblack@eecs.umich.edu ThreadID num_threads = mvpConf0.ptc + 1; 2444661Sksewell@umich.edu 2454661Sksewell@umich.edu int ok = 0; 2464661Sksewell@umich.edu 2474661Sksewell@umich.edu // Get Current VPE & TC numbers from calling thread 2486383Sgblack@eecs.umich.edu TCBindReg tcBind = tc->readMiscRegNoEffect(MISCREG_TC_BIND); 2494661Sksewell@umich.edu 2506221Snate@binkert.org for (ThreadID tid = 0; tid < num_threads; tid++) { 2516376Sgblack@eecs.umich.edu TCStatusReg tidTCStatus = 25213899Sgabeblack@google.com readRegOtherThread(tc, RegId(MiscRegClass, MISCREG_TC_STATUS), 2536383Sgblack@eecs.umich.edu tid); 2546376Sgblack@eecs.umich.edu TCHaltReg tidTCHalt = 25513899Sgabeblack@google.com readRegOtherThread(tc, RegId(MiscRegClass, MISCREG_TC_HALT), 2566383Sgblack@eecs.umich.edu tid); 2576376Sgblack@eecs.umich.edu TCBindReg tidTCBind = 25813899Sgabeblack@google.com readRegOtherThread(tc, RegId(MiscRegClass, MISCREG_TC_BIND), 2596383Sgblack@eecs.umich.edu tid); 2604661Sksewell@umich.edu 2616376Sgblack@eecs.umich.edu if (tidTCBind.curVPE == tcBind.curVPE && 2626376Sgblack@eecs.umich.edu tidTCBind.curTC == tcBind.curTC && 2636376Sgblack@eecs.umich.edu tidTCStatus.da == 1 && 2646376Sgblack@eecs.umich.edu tidTCHalt.h == 0 && 2656376Sgblack@eecs.umich.edu tidTCStatus.a == 1) { 2664661Sksewell@umich.edu ok = 1; 2674661Sksewell@umich.edu } 2684661Sksewell@umich.edu } 2694661Sksewell@umich.edu 2704661Sksewell@umich.edu if (ok == 1) { 2716383Sgblack@eecs.umich.edu TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 2726376Sgblack@eecs.umich.edu tcStatus.a = 0; 2736383Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_TC_STATUS, tcStatus); 2746376Sgblack@eecs.umich.edu warn("%i: Deactivating Hardware Thread Context #%i", 2757823Ssteve.reinhardt@amd.com curTick(), tc->threadId()); 2764661Sksewell@umich.edu } 2774661Sksewell@umich.edu } else if (src_reg > 0) { 2785561Snate@binkert.org if (src_reg && !yield_mask != 0) { 2796383Sgblack@eecs.umich.edu VPEControlReg vpeControl = tc->readMiscReg(MISCREG_VPE_CONTROL); 2806376Sgblack@eecs.umich.edu vpeControl.excpt = 2; 2816383Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_VPE_CONTROL, vpeControl); 28210474Sandreas.hansson@arm.com fault = std::make_shared<ThreadFault>(); 2834661Sksewell@umich.edu } else { 2844661Sksewell@umich.edu } 2854661Sksewell@umich.edu } else if (src_reg != -2) { 2866383Sgblack@eecs.umich.edu TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 2876383Sgblack@eecs.umich.edu VPEControlReg vpeControl = 2886383Sgblack@eecs.umich.edu tc->readMiscRegNoEffect(MISCREG_VPE_CONTROL); 2894661Sksewell@umich.edu 2906376Sgblack@eecs.umich.edu if (vpeControl.ysi == 1 && tcStatus.dt == 1 ) { 2916376Sgblack@eecs.umich.edu vpeControl.excpt = 4; 29210474Sandreas.hansson@arm.com fault = std::make_shared<ThreadFault>(); 2934661Sksewell@umich.edu } else { 2944661Sksewell@umich.edu } 2954661Sksewell@umich.edu } 2964661Sksewell@umich.edu 2974661Sksewell@umich.edu return src_reg & yield_mask; 2984661Sksewell@umich.edu} 2994661Sksewell@umich.edu 3004661Sksewell@umich.edu 3014661Sksewell@umich.edu// TC will usually be a object derived from ThreadContext 3024661Sksewell@umich.edu// (src/cpu/thread_context.hh) 3034661Sksewell@umich.edutemplate <class TC> 3044661Sksewell@umich.eduinline void 3054661Sksewell@umich.eduupdateStatusView(TC *tc) 3064661Sksewell@umich.edu{ 3074661Sksewell@umich.edu // TCStatus' register view must be the same as 3084661Sksewell@umich.edu // Status register view for CU, MX, KSU bits 3096383Sgblack@eecs.umich.edu TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 3106383Sgblack@eecs.umich.edu StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS); 3114661Sksewell@umich.edu 3126376Sgblack@eecs.umich.edu status.cu = tcStatus.tcu; 3136376Sgblack@eecs.umich.edu status.mx = tcStatus.tmx; 3146376Sgblack@eecs.umich.edu status.ksu = tcStatus.tksu; 3154661Sksewell@umich.edu 3166383Sgblack@eecs.umich.edu tc->setMiscRegNoEffect(MISCREG_STATUS, status); 3174661Sksewell@umich.edu} 3184661Sksewell@umich.edu 3194661Sksewell@umich.edu// TC will usually be a object derived from ThreadContext 3204661Sksewell@umich.edu// (src/cpu/thread_context.hh) 3214661Sksewell@umich.edutemplate <class TC> 3224661Sksewell@umich.eduinline void 3234661Sksewell@umich.eduupdateTCStatusView(TC *tc) 3244661Sksewell@umich.edu{ 3254661Sksewell@umich.edu // TCStatus' register view must be the same as 3264661Sksewell@umich.edu // Status register view for CU, MX, KSU bits 3276383Sgblack@eecs.umich.edu TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 3286383Sgblack@eecs.umich.edu StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS); 3294661Sksewell@umich.edu 3306376Sgblack@eecs.umich.edu tcStatus.tcu = status.cu; 3316376Sgblack@eecs.umich.edu tcStatus.tmx = status.mx; 3326376Sgblack@eecs.umich.edu tcStatus.tksu = status.ksu; 3334661Sksewell@umich.edu 3346383Sgblack@eecs.umich.edu tc->setMiscRegNoEffect(MISCREG_TC_STATUS, tcStatus); 3354661Sksewell@umich.edu} 3364661Sksewell@umich.edu 3374661Sksewell@umich.edu} // namespace MipsISA 3384661Sksewell@umich.edu 3394661Sksewell@umich.edu 3404661Sksewell@umich.edu#endif 341