mt.hh revision 6378
112854Sgabeblack@google.com/* 212854Sgabeblack@google.com * Copyright (c) 2007 MIPS Technologies, Inc. 312854Sgabeblack@google.com * All rights reserved. 412854Sgabeblack@google.com * 512854Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 612854Sgabeblack@google.com * modification, are permitted provided that the following conditions are 712854Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 812854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 912854Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 1012854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1112854Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1212854Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1312854Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1412854Sgabeblack@google.com * this software without specific prior written permission. 1512854Sgabeblack@google.com * 1612854Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712854Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812854Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912854Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012854Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112854Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212854Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312854Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412854Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512854Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612854Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712854Sgabeblack@google.com * 2812854Sgabeblack@google.com * Authors: Korey Sewell 2912854Sgabeblack@google.com */ 3012854Sgabeblack@google.com 3112854Sgabeblack@google.com#ifndef __ARCH_MIPS_MT_HH__ 3212854Sgabeblack@google.com#define __ARCH_MIPS_MT_HH__ 3312854Sgabeblack@google.com 3412854Sgabeblack@google.com/** 3512854Sgabeblack@google.com * @file 3612854Sgabeblack@google.com * 3712854Sgabeblack@google.com * ISA-specific helper functions for multithreaded execution. 3812854Sgabeblack@google.com */ 3912854Sgabeblack@google.com 4012854Sgabeblack@google.com#include "arch/mips/faults.hh" 4112854Sgabeblack@google.com#include "arch/mips/isa_traits.hh" 4212854Sgabeblack@google.com#include "arch/mips/mt_constants.hh" 4312854Sgabeblack@google.com#include "arch/mips/pra_constants.hh" 4412854Sgabeblack@google.com#include "arch/mips/registers.hh" 4512854Sgabeblack@google.com#include "base/bitfield.hh" 4612854Sgabeblack@google.com#include "base/trace.hh" 4712854Sgabeblack@google.com#include "base/misc.hh" 4812854Sgabeblack@google.com 4912854Sgabeblack@google.com#include <iostream> 5012854Sgabeblack@google.com 5112854Sgabeblack@google.comnamespace MipsISA 5212854Sgabeblack@google.com{ 5312854Sgabeblack@google.com 5412854Sgabeblack@google.comtemplate <class TC> 5512854Sgabeblack@google.cominline unsigned 5612854Sgabeblack@google.comgetVirtProcNum(TC *tc) 5712854Sgabeblack@google.com{ 5812854Sgabeblack@google.com TCBindReg tcbind = tc->readMiscRegNoEffect(TCBind); 5912854Sgabeblack@google.com return tcbind.curVPE; 6012854Sgabeblack@google.com} 6112854Sgabeblack@google.com 6212854Sgabeblack@google.comtemplate <class TC> 6312854Sgabeblack@google.cominline unsigned 6412854Sgabeblack@google.comgetTargetThread(TC *tc) 6512854Sgabeblack@google.com{ 6612854Sgabeblack@google.com VPEControlReg vpeCtrl = tc->readMiscRegNoEffect(VPEControl); 6712854Sgabeblack@google.com return vpeCtrl.targTC; 6812854Sgabeblack@google.com} 6912854Sgabeblack@google.com 7012854Sgabeblack@google.comtemplate <class TC> 7112854Sgabeblack@google.cominline void 7212854Sgabeblack@google.comhaltThread(TC *tc) 7312854Sgabeblack@google.com{ 7412854Sgabeblack@google.com if (tc->status() == TC::Active) { 7512854Sgabeblack@google.com tc->halt(); 7612854Sgabeblack@google.com 7712854Sgabeblack@google.com // Save last known PC in TCRestart 7812854Sgabeblack@google.com // @TODO: Needs to check if this is a branch and if so, 7912854Sgabeblack@google.com // take previous instruction 8012854Sgabeblack@google.com tc->setMiscReg(TCRestart, tc->readNextPC()); 8112854Sgabeblack@google.com 8212854Sgabeblack@google.com warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", 8312854Sgabeblack@google.com curTick, tc->threadId(), tc->getCpuPtr()->name(), 8412854Sgabeblack@google.com tc->readPC(), tc->readNextPC()); 8512854Sgabeblack@google.com } 8612854Sgabeblack@google.com} 8712854Sgabeblack@google.com 8812854Sgabeblack@google.comtemplate <class TC> 8912854Sgabeblack@google.cominline void 9012854Sgabeblack@google.comrestoreThread(TC *tc) 9112854Sgabeblack@google.com{ 9212854Sgabeblack@google.com if (tc->status() != TC::Active) { 9312854Sgabeblack@google.com // Restore PC from TCRestart 9412854Sgabeblack@google.com IntReg pc = tc->readMiscRegNoEffect(TCRestart); 9512854Sgabeblack@google.com 9612854Sgabeblack@google.com // TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY 9712854Sgabeblack@google.com tc->setPC(pc); 9812854Sgabeblack@google.com tc->setNextPC(pc + 4); 9912854Sgabeblack@google.com tc->setNextNPC(pc + 8); 10012854Sgabeblack@google.com tc->activate(0); 10112854Sgabeblack@google.com 10212854Sgabeblack@google.com warn("%i: Restoring thread %i in %s @ PC %x", 10312854Sgabeblack@google.com curTick, tc->threadId(), tc->getCpuPtr()->name(), 10412854Sgabeblack@google.com tc->readPC()); 10512854Sgabeblack@google.com } 10612854Sgabeblack@google.com} 10712854Sgabeblack@google.com 10812854Sgabeblack@google.comtemplate <class TC> 10912854Sgabeblack@google.comvoid 11012854Sgabeblack@google.comforkThread(TC *tc, Fault &fault, int Rd_bits, int Rs, int Rt) 11112854Sgabeblack@google.com{ 11212854Sgabeblack@google.com MVPConf0Reg mvpConf = tc->readMiscRegNoEffect(MVPConf0); 11312854Sgabeblack@google.com int num_threads = mvpConf.ptc + 1; 11412854Sgabeblack@google.com 11512854Sgabeblack@google.com int success = 0; 11612854Sgabeblack@google.com for (ThreadID tid = 0; tid < num_threads && success == 0; tid++) { 11712854Sgabeblack@google.com TCBindReg tidTCBind = 11812854Sgabeblack@google.com tc->readRegOtherThread(TCBind + Ctrl_Base_DepTag, tid); 11912854Sgabeblack@google.com TCBindReg tcBind = tc->readMiscRegNoEffect(TCBind); 12012854Sgabeblack@google.com 12112854Sgabeblack@google.com if (tidTCBind.curVPE = tcBind.curVPE) { 12212854Sgabeblack@google.com 12312854Sgabeblack@google.com TCStatusReg tidTCStatus = 12412854Sgabeblack@google.com tc->readRegOtherThread(TCStatus + Ctrl_Base_DepTag,tid); 12512854Sgabeblack@google.com 12612854Sgabeblack@google.com TCHaltReg tidTCHalt = 12712854Sgabeblack@google.com tc->readRegOtherThread(TCHalt + Ctrl_Base_DepTag,tid); 12812854Sgabeblack@google.com 12912854Sgabeblack@google.com if (tidTCStatus.da == 1 && tidTCHalt.h == 0 && 13012854Sgabeblack@google.com tidTCStatus.a == 0 && success == 0) { 13112854Sgabeblack@google.com 13212854Sgabeblack@google.com tc->setRegOtherThread(TCRestart + Ctrl_Base_DepTag, Rs, tid); 13312854Sgabeblack@google.com tc->setRegOtherThread(Rd_bits, Rt, tid); 13412854Sgabeblack@google.com 13512854Sgabeblack@google.com StatusReg status = tc->readMiscReg(Status); 13612854Sgabeblack@google.com TCStatusReg tcStatus = tc->readMiscReg(TCStatus); 13712854Sgabeblack@google.com 13812854Sgabeblack@google.com // Set Run-State to Running 13912854Sgabeblack@google.com tidTCStatus.rnst = 0; 14012854Sgabeblack@google.com // Set Delay-Slot to 0 14112854Sgabeblack@google.com tidTCStatus.tds = 0; 14212854Sgabeblack@google.com // Set Dirty TC to 1 14312854Sgabeblack@google.com tidTCStatus.dt = 1; 14412854Sgabeblack@google.com // Set Activated to 1 14512854Sgabeblack@google.com tidTCStatus.a = 1; 14612854Sgabeblack@google.com // Set status to previous thread's status 14712854Sgabeblack@google.com tidTCStatus.tksu = status.ksu; 14812854Sgabeblack@google.com // Set ASID to previous thread's state 14912854Sgabeblack@google.com tidTCStatus.asid = tcStatus.asid; 15012854Sgabeblack@google.com 15112854Sgabeblack@google.com // Write Status Register 15212854Sgabeblack@google.com tc->setRegOtherThread(TCStatus + Ctrl_Base_DepTag, 15312854Sgabeblack@google.com tidTCStatus, tid); 15412854Sgabeblack@google.com 15512854Sgabeblack@google.com // Mark As Successful Fork 15612854Sgabeblack@google.com success = 1; 15712854Sgabeblack@google.com } 15812854Sgabeblack@google.com } else { 15912854Sgabeblack@google.com std::cerr << "Bad VPEs" << std::endl; 16012854Sgabeblack@google.com } 16112854Sgabeblack@google.com } 16212854Sgabeblack@google.com 16312854Sgabeblack@google.com if (success == 0) { 16412854Sgabeblack@google.com VPEControlReg vpeControl = tc->readMiscRegNoEffect(VPEControl); 16512854Sgabeblack@google.com vpeControl.excpt = 1; 16612854Sgabeblack@google.com tc->setMiscReg(VPEControl, vpeControl); 16712854Sgabeblack@google.com fault = new ThreadFault(); 16812854Sgabeblack@google.com } 16912854Sgabeblack@google.com} 17012854Sgabeblack@google.com 17112854Sgabeblack@google.com 17212854Sgabeblack@google.comtemplate <class TC> 17312854Sgabeblack@google.comint 17412854Sgabeblack@google.comyieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask) 17512854Sgabeblack@google.com{ 17612854Sgabeblack@google.com if (src_reg == 0) { 17712854Sgabeblack@google.com MVPConf0Reg mvpConf0 = tc->readMiscRegNoEffect(MVPConf0); 17812854Sgabeblack@google.com ThreadID num_threads = mvpConf0.ptc + 1; 17912854Sgabeblack@google.com 18012854Sgabeblack@google.com int ok = 0; 18112854Sgabeblack@google.com 18212854Sgabeblack@google.com // Get Current VPE & TC numbers from calling thread 18312854Sgabeblack@google.com TCBindReg tcBind = tc->readMiscRegNoEffect(TCBind); 18412854Sgabeblack@google.com 18512854Sgabeblack@google.com for (ThreadID tid = 0; tid < num_threads; tid++) { 18612854Sgabeblack@google.com TCStatusReg tidTCStatus = 18712854Sgabeblack@google.com tc->readRegOtherThread(TCStatus + Ctrl_Base_DepTag, tid); 18812854Sgabeblack@google.com TCHaltReg tidTCHalt = 18912854Sgabeblack@google.com tc->readRegOtherThread(TCHalt + Ctrl_Base_DepTag, tid); 19012854Sgabeblack@google.com TCBindReg tidTCBind = 19112854Sgabeblack@google.com tc->readRegOtherThread(TCBind + Ctrl_Base_DepTag, tid); 19212854Sgabeblack@google.com 19312854Sgabeblack@google.com if (tidTCBind.curVPE == tcBind.curVPE && 19412854Sgabeblack@google.com tidTCBind.curTC == tcBind.curTC && 19512854Sgabeblack@google.com tidTCStatus.da == 1 && 19612854Sgabeblack@google.com tidTCHalt.h == 0 && 19712854Sgabeblack@google.com tidTCStatus.a == 1) { 19812854Sgabeblack@google.com ok = 1; 19912854Sgabeblack@google.com } 20012854Sgabeblack@google.com } 20112854Sgabeblack@google.com 20212854Sgabeblack@google.com if (ok == 1) { 20312854Sgabeblack@google.com TCStatusReg tcStatus = tc->readMiscRegNoEffect(TCStatus); 20412854Sgabeblack@google.com tcStatus.a = 0; 20512854Sgabeblack@google.com tc->setMiscReg(TCStatus, tcStatus); 20612854Sgabeblack@google.com warn("%i: Deactivating Hardware Thread Context #%i", 20712854Sgabeblack@google.com curTick, tc->threadId()); 20812854Sgabeblack@google.com } 20912854Sgabeblack@google.com } else if (src_reg > 0) { 21012854Sgabeblack@google.com if (src_reg && !yield_mask != 0) { 21112854Sgabeblack@google.com VPEControlReg vpeControl = tc->readMiscReg(VPEControl); 21212854Sgabeblack@google.com vpeControl.excpt = 2; 21312854Sgabeblack@google.com tc->setMiscReg(VPEControl, vpeControl); 21412854Sgabeblack@google.com fault = new ThreadFault(); 21512854Sgabeblack@google.com } else { 21612854Sgabeblack@google.com } 21712854Sgabeblack@google.com } else if (src_reg != -2) { 21812854Sgabeblack@google.com TCStatusReg tcStatus = tc->readMiscRegNoEffect(TCStatus); 21912854Sgabeblack@google.com VPEControlReg vpeControl = tc->readMiscRegNoEffect(VPEControl); 22012854Sgabeblack@google.com 22112854Sgabeblack@google.com if (vpeControl.ysi == 1 && tcStatus.dt == 1 ) { 22212854Sgabeblack@google.com vpeControl.excpt = 4; 22312854Sgabeblack@google.com fault = new ThreadFault(); 22412854Sgabeblack@google.com } else { 22512854Sgabeblack@google.com } 22612854Sgabeblack@google.com } 22712854Sgabeblack@google.com 22812854Sgabeblack@google.com return src_reg & yield_mask; 22912854Sgabeblack@google.com} 23012854Sgabeblack@google.com 23112854Sgabeblack@google.com 23212854Sgabeblack@google.com// TC will usually be a object derived from ThreadContext 23312854Sgabeblack@google.com// (src/cpu/thread_context.hh) 23412854Sgabeblack@google.comtemplate <class TC> 23512854Sgabeblack@google.cominline void 23612854Sgabeblack@google.comupdateStatusView(TC *tc) 23712854Sgabeblack@google.com{ 23812854Sgabeblack@google.com // TCStatus' register view must be the same as 23912854Sgabeblack@google.com // Status register view for CU, MX, KSU bits 24012854Sgabeblack@google.com TCStatusReg tcStatus = tc->readMiscRegNoEffect(TCStatus); 24112854Sgabeblack@google.com StatusReg status = tc->readMiscRegNoEffect(Status); 24212854Sgabeblack@google.com 24312854Sgabeblack@google.com status.cu = tcStatus.tcu; 24412854Sgabeblack@google.com status.mx = tcStatus.tmx; 24512854Sgabeblack@google.com status.ksu = tcStatus.tksu; 24612854Sgabeblack@google.com 24712854Sgabeblack@google.com tc->setMiscRegNoEffect(Status, status); 24812854Sgabeblack@google.com} 24912854Sgabeblack@google.com 25012854Sgabeblack@google.com// TC will usually be a object derived from ThreadContext 25112854Sgabeblack@google.com// (src/cpu/thread_context.hh) 25212854Sgabeblack@google.comtemplate <class TC> 25312854Sgabeblack@google.cominline void 25412854Sgabeblack@google.comupdateTCStatusView(TC *tc) 25512854Sgabeblack@google.com{ 25612854Sgabeblack@google.com // TCStatus' register view must be the same as 25712854Sgabeblack@google.com // Status register view for CU, MX, KSU bits 25812854Sgabeblack@google.com TCStatusReg tcStatus = tc->readMiscRegNoEffect(TCStatus); 25912854Sgabeblack@google.com StatusReg status = tc->readMiscRegNoEffect(Status); 26012854Sgabeblack@google.com 26112854Sgabeblack@google.com tcStatus.tcu = status.cu; 26212854Sgabeblack@google.com tcStatus.tmx = status.mx; 26312854Sgabeblack@google.com tcStatus.tksu = status.ksu; 26412854Sgabeblack@google.com 26512854Sgabeblack@google.com tc->setMiscRegNoEffect(TCStatus, tcStatus); 26612854Sgabeblack@google.com} 26712854Sgabeblack@google.com 26812854Sgabeblack@google.com} // namespace MipsISA 26912854Sgabeblack@google.com 27012854Sgabeblack@google.com 27112854Sgabeblack@google.com#endif 27212854Sgabeblack@google.com