Files
gem5/src/arch/riscv/isa.cc
Gabe Black ede1ad4b8c arch,cpu,mem,sim: Fold arch/locked_mem.hh into the BaseISA class.
Turn the functions within it into virtual methods on the ISA classes.
Eliminate the implementation in MIPS, which was just copy pasted from
Alpha long ago. Fix some minor style issues in ARM. Remove templating.
Switch from using an "XC" type parameter to using the ThreadContext *
installed in all ISA classes.

The ARM version of these functions actually depend on the ExecContext
delaying writes to MiscRegs to work correctly. More insiduously than
that, they also depend on the conicidental ThreadContext like
availability of certain functions like contextId and getCpuPtr which
come from the class which happened to implement the type passed into XC.

To accomodate that, those functions need both a real ThreadContext, and
another object which is either an ExecContext or a ThreadContext
depending on how the method is called.

Jira Issue: https://gem5.atlassian.net/browse/GEM5-1053

Change-Id: I68f95f7283f831776ba76bc5481bfffd18211bc4
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/50087
Maintainer: Gabe Black <gabe.black@gmail.com>
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
2021-09-28 19:56:01 +00:00

565 lines
20 KiB
C++

/*
* Copyright (c) 2016 RISC-V Foundation
* Copyright (c) 2016 The University of Virginia
* Copyright (c) 2020 Barkhausen Institut
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "arch/riscv/isa.hh"
#include <ctime>
#include <set>
#include <sstream>
#include "arch/riscv/interrupts.hh"
#include "arch/riscv/mmu.hh"
#include "arch/riscv/pagetable.hh"
#include "arch/riscv/pmp.hh"
#include "arch/riscv/regs/float.hh"
#include "arch/riscv/regs/int.hh"
#include "arch/riscv/regs/misc.hh"
#include "base/bitfield.hh"
#include "base/compiler.hh"
#include "base/logging.hh"
#include "base/trace.hh"
#include "cpu/base.hh"
#include "debug/Checkpoint.hh"
#include "debug/LLSC.hh"
#include "debug/RiscvMisc.hh"
#include "mem/packet.hh"
#include "mem/request.hh"
#include "params/RiscvISA.hh"
#include "sim/pseudo_inst.hh"
namespace gem5
{
namespace RiscvISA
{
[[maybe_unused]] const std::array<const char *, NUM_MISCREGS> MiscRegNames = {{
[MISCREG_PRV] = "PRV",
[MISCREG_ISA] = "ISA",
[MISCREG_VENDORID] = "VENDORID",
[MISCREG_ARCHID] = "ARCHID",
[MISCREG_IMPID] = "IMPID",
[MISCREG_HARTID] = "HARTID",
[MISCREG_STATUS] = "STATUS",
[MISCREG_IP] = "IP",
[MISCREG_IE] = "IE",
[MISCREG_CYCLE] = "CYCLE",
[MISCREG_TIME] = "TIME",
[MISCREG_INSTRET] = "INSTRET",
[MISCREG_HPMCOUNTER03] = "HPMCOUNTER03",
[MISCREG_HPMCOUNTER04] = "HPMCOUNTER04",
[MISCREG_HPMCOUNTER05] = "HPMCOUNTER05",
[MISCREG_HPMCOUNTER06] = "HPMCOUNTER06",
[MISCREG_HPMCOUNTER07] = "HPMCOUNTER07",
[MISCREG_HPMCOUNTER08] = "HPMCOUNTER08",
[MISCREG_HPMCOUNTER09] = "HPMCOUNTER09",
[MISCREG_HPMCOUNTER10] = "HPMCOUNTER10",
[MISCREG_HPMCOUNTER11] = "HPMCOUNTER11",
[MISCREG_HPMCOUNTER12] = "HPMCOUNTER12",
[MISCREG_HPMCOUNTER13] = "HPMCOUNTER13",
[MISCREG_HPMCOUNTER14] = "HPMCOUNTER14",
[MISCREG_HPMCOUNTER15] = "HPMCOUNTER15",
[MISCREG_HPMCOUNTER16] = "HPMCOUNTER16",
[MISCREG_HPMCOUNTER17] = "HPMCOUNTER17",
[MISCREG_HPMCOUNTER18] = "HPMCOUNTER18",
[MISCREG_HPMCOUNTER19] = "HPMCOUNTER19",
[MISCREG_HPMCOUNTER20] = "HPMCOUNTER20",
[MISCREG_HPMCOUNTER21] = "HPMCOUNTER21",
[MISCREG_HPMCOUNTER22] = "HPMCOUNTER22",
[MISCREG_HPMCOUNTER23] = "HPMCOUNTER23",
[MISCREG_HPMCOUNTER24] = "HPMCOUNTER24",
[MISCREG_HPMCOUNTER25] = "HPMCOUNTER25",
[MISCREG_HPMCOUNTER26] = "HPMCOUNTER26",
[MISCREG_HPMCOUNTER27] = "HPMCOUNTER27",
[MISCREG_HPMCOUNTER28] = "HPMCOUNTER28",
[MISCREG_HPMCOUNTER29] = "HPMCOUNTER29",
[MISCREG_HPMCOUNTER30] = "HPMCOUNTER30",
[MISCREG_HPMCOUNTER31] = "HPMCOUNTER31",
[MISCREG_HPMEVENT03] = "HPMEVENT03",
[MISCREG_HPMEVENT04] = "HPMEVENT04",
[MISCREG_HPMEVENT05] = "HPMEVENT05",
[MISCREG_HPMEVENT06] = "HPMEVENT06",
[MISCREG_HPMEVENT07] = "HPMEVENT07",
[MISCREG_HPMEVENT08] = "HPMEVENT08",
[MISCREG_HPMEVENT09] = "HPMEVENT09",
[MISCREG_HPMEVENT10] = "HPMEVENT10",
[MISCREG_HPMEVENT11] = "HPMEVENT11",
[MISCREG_HPMEVENT12] = "HPMEVENT12",
[MISCREG_HPMEVENT13] = "HPMEVENT13",
[MISCREG_HPMEVENT14] = "HPMEVENT14",
[MISCREG_HPMEVENT15] = "HPMEVENT15",
[MISCREG_HPMEVENT16] = "HPMEVENT16",
[MISCREG_HPMEVENT17] = "HPMEVENT17",
[MISCREG_HPMEVENT18] = "HPMEVENT18",
[MISCREG_HPMEVENT19] = "HPMEVENT19",
[MISCREG_HPMEVENT20] = "HPMEVENT20",
[MISCREG_HPMEVENT21] = "HPMEVENT21",
[MISCREG_HPMEVENT22] = "HPMEVENT22",
[MISCREG_HPMEVENT23] = "HPMEVENT23",
[MISCREG_HPMEVENT24] = "HPMEVENT24",
[MISCREG_HPMEVENT25] = "HPMEVENT25",
[MISCREG_HPMEVENT26] = "HPMEVENT26",
[MISCREG_HPMEVENT27] = "HPMEVENT27",
[MISCREG_HPMEVENT28] = "HPMEVENT28",
[MISCREG_HPMEVENT29] = "HPMEVENT29",
[MISCREG_HPMEVENT30] = "HPMEVENT30",
[MISCREG_HPMEVENT31] = "HPMEVENT31",
[MISCREG_TSELECT] = "TSELECT",
[MISCREG_TDATA1] = "TDATA1",
[MISCREG_TDATA2] = "TDATA2",
[MISCREG_TDATA3] = "TDATA3",
[MISCREG_DCSR] = "DCSR",
[MISCREG_DPC] = "DPC",
[MISCREG_DSCRATCH] = "DSCRATCH",
[MISCREG_MEDELEG] = "MEDELEG",
[MISCREG_MIDELEG] = "MIDELEG",
[MISCREG_MTVEC] = "MTVEC",
[MISCREG_MCOUNTEREN] = "MCOUNTEREN",
[MISCREG_MSCRATCH] = "MSCRATCH",
[MISCREG_MEPC] = "MEPC",
[MISCREG_MCAUSE] = "MCAUSE",
[MISCREG_MTVAL] = "MTVAL",
[MISCREG_PMPCFG0] = "PMPCFG0",
// pmpcfg1 rv32 only
[MISCREG_PMPCFG2] = "PMPCFG2",
// pmpcfg3 rv32 only
[MISCREG_PMPADDR00] = "PMPADDR00",
[MISCREG_PMPADDR01] = "PMPADDR01",
[MISCREG_PMPADDR02] = "PMPADDR02",
[MISCREG_PMPADDR03] = "PMPADDR03",
[MISCREG_PMPADDR04] = "PMPADDR04",
[MISCREG_PMPADDR05] = "PMPADDR05",
[MISCREG_PMPADDR06] = "PMPADDR06",
[MISCREG_PMPADDR07] = "PMPADDR07",
[MISCREG_PMPADDR08] = "PMPADDR08",
[MISCREG_PMPADDR09] = "PMPADDR09",
[MISCREG_PMPADDR10] = "PMPADDR10",
[MISCREG_PMPADDR11] = "PMPADDR11",
[MISCREG_PMPADDR12] = "PMPADDR12",
[MISCREG_PMPADDR13] = "PMPADDR13",
[MISCREG_PMPADDR14] = "PMPADDR14",
[MISCREG_PMPADDR15] = "PMPADDR15",
[MISCREG_SEDELEG] = "SEDELEG",
[MISCREG_SIDELEG] = "SIDELEG",
[MISCREG_STVEC] = "STVEC",
[MISCREG_SCOUNTEREN] = "SCOUNTEREN",
[MISCREG_SSCRATCH] = "SSCRATCH",
[MISCREG_SEPC] = "SEPC",
[MISCREG_SCAUSE] = "SCAUSE",
[MISCREG_STVAL] = "STVAL",
[MISCREG_SATP] = "SATP",
[MISCREG_UTVEC] = "UTVEC",
[MISCREG_USCRATCH] = "USCRATCH",
[MISCREG_UEPC] = "UEPC",
[MISCREG_UCAUSE] = "UCAUSE",
[MISCREG_UTVAL] = "UTVAL",
[MISCREG_FFLAGS] = "FFLAGS",
[MISCREG_FRM] = "FRM",
}};
ISA::ISA(const Params &p) : BaseISA(p)
{
_regClasses.emplace_back(NumIntRegs, 0);
_regClasses.emplace_back(NumFloatRegs);
_regClasses.emplace_back(1); // Not applicable to RISCV
_regClasses.emplace_back(2); // Not applicable to RISCV
_regClasses.emplace_back(1); // Not applicable to RISCV
_regClasses.emplace_back(0); // Not applicable to RISCV
_regClasses.emplace_back(NUM_MISCREGS);
miscRegFile.resize(NUM_MISCREGS);
clear();
}
void
ISA::copyRegsFrom(ThreadContext *src)
{
// First loop through the integer registers.
for (int i = 0; i < NumIntRegs; ++i)
tc->setIntReg(i, src->readIntReg(i));
// Second loop through the float registers.
for (int i = 0; i < NumFloatRegs; ++i)
tc->setFloatReg(i, src->readFloatReg(i));
// Lastly copy PC/NPC
tc->pcState(src->pcState());
}
void ISA::clear()
{
std::fill(miscRegFile.begin(), miscRegFile.end(), 0);
miscRegFile[MISCREG_PRV] = PRV_M;
miscRegFile[MISCREG_ISA] = (2ULL << MXL_OFFSET) | 0x14112D;
miscRegFile[MISCREG_VENDORID] = 0;
miscRegFile[MISCREG_ARCHID] = 0;
miscRegFile[MISCREG_IMPID] = 0;
miscRegFile[MISCREG_STATUS] = (2ULL << UXL_OFFSET) | (2ULL << SXL_OFFSET) |
(1ULL << FS_OFFSET);
miscRegFile[MISCREG_MCOUNTEREN] = 0x7;
miscRegFile[MISCREG_SCOUNTEREN] = 0x7;
// don't set it to zero; software may try to determine the supported
// triggers, starting at zero. simply set a different value here.
miscRegFile[MISCREG_TSELECT] = 1;
}
bool
ISA::hpmCounterEnabled(int misc_reg) const
{
int hpmcounter = misc_reg - MISCREG_CYCLE;
if (hpmcounter < 0 || hpmcounter > 31)
panic("Illegal HPM counter %d\n", hpmcounter);
int counteren;
switch (readMiscRegNoEffect(MISCREG_PRV)) {
case PRV_M:
return true;
case PRV_S:
counteren = MISCREG_MCOUNTEREN;
break;
case PRV_U:
counteren = MISCREG_SCOUNTEREN;
break;
default:
panic("Unknown privilege level %d\n", miscRegFile[MISCREG_PRV]);
return false;
}
return (miscRegFile[counteren] & (1ULL << (hpmcounter))) > 0;
}
RegVal
ISA::readMiscRegNoEffect(int misc_reg) const
{
if (misc_reg > NUM_MISCREGS || misc_reg < 0) {
// Illegal CSR
panic("Illegal CSR index %#x\n", misc_reg);
return -1;
}
DPRINTF(RiscvMisc, "Reading MiscReg %s (%d): %#x.\n",
MiscRegNames[misc_reg], misc_reg, miscRegFile[misc_reg]);
return miscRegFile[misc_reg];
}
RegVal
ISA::readMiscReg(int misc_reg)
{
switch (misc_reg) {
case MISCREG_HARTID:
return tc->contextId();
case MISCREG_CYCLE:
if (hpmCounterEnabled(MISCREG_CYCLE)) {
DPRINTF(RiscvMisc, "Cycle counter at: %llu.\n",
tc->getCpuPtr()->curCycle());
return tc->getCpuPtr()->curCycle();
} else {
warn("Cycle counter disabled.\n");
return 0;
}
case MISCREG_TIME:
if (hpmCounterEnabled(MISCREG_TIME)) {
DPRINTF(RiscvMisc, "Wall-clock counter at: %llu.\n",
std::time(nullptr));
return readMiscRegNoEffect(MISCREG_TIME);
} else {
warn("Wall clock disabled.\n");
return 0;
}
case MISCREG_INSTRET:
if (hpmCounterEnabled(MISCREG_INSTRET)) {
DPRINTF(RiscvMisc, "Instruction counter at: %llu.\n",
tc->getCpuPtr()->totalInsts());
return tc->getCpuPtr()->totalInsts();
} else {
warn("Instruction counter disabled.\n");
return 0;
}
case MISCREG_IP:
{
auto ic = dynamic_cast<RiscvISA::Interrupts *>(
tc->getCpuPtr()->getInterruptController(tc->threadId()));
return ic->readIP();
}
case MISCREG_IE:
{
auto ic = dynamic_cast<RiscvISA::Interrupts *>(
tc->getCpuPtr()->getInterruptController(tc->threadId()));
return ic->readIE();
}
case MISCREG_SEPC:
case MISCREG_MEPC:
{
auto misa = readMiscRegNoEffect(MISCREG_ISA);
auto val = readMiscRegNoEffect(misc_reg);
// if compressed instructions are disabled, epc[1] is set to 0
if ((misa & ISA_EXT_C_MASK) == 0)
return mbits(val, 63, 2);
// epc[0] is always 0
else
return mbits(val, 63, 1);
}
default:
// Try reading HPM counters
// As a placeholder, all HPM counters are just cycle counters
if (misc_reg >= MISCREG_HPMCOUNTER03 &&
misc_reg <= MISCREG_HPMCOUNTER31) {
if (hpmCounterEnabled(misc_reg)) {
DPRINTF(RiscvMisc, "HPM counter %d: %llu.\n",
misc_reg - MISCREG_CYCLE, tc->getCpuPtr()->curCycle());
return tc->getCpuPtr()->curCycle();
} else {
warn("HPM counter %d disabled.\n", misc_reg - MISCREG_CYCLE);
return 0;
}
}
return readMiscRegNoEffect(misc_reg);
}
}
void
ISA::setMiscRegNoEffect(int misc_reg, RegVal val)
{
if (misc_reg > NUM_MISCREGS || misc_reg < 0) {
// Illegal CSR
panic("Illegal CSR index %#x\n", misc_reg);
}
DPRINTF(RiscvMisc, "Setting MiscReg %s (%d) to %#x.\n",
MiscRegNames[misc_reg], misc_reg, val);
miscRegFile[misc_reg] = val;
}
void
ISA::setMiscReg(int misc_reg, RegVal val)
{
if (misc_reg >= MISCREG_CYCLE && misc_reg <= MISCREG_HPMCOUNTER31) {
// Ignore writes to HPM counters for now
warn("Ignoring write to %s.\n", CSRData.at(misc_reg).name);
} else {
switch (misc_reg) {
// From section 3.7.1 of RISCV priv. specs
// V1.12, the odd-numbered configuration
// registers are illegal for RV64 and
// each 64 bit CFG register hold configurations
// for 8 PMP entries.
case MISCREG_PMPCFG0:
case MISCREG_PMPCFG2:
{
// PMP registers should only be modified in M mode
assert(readMiscRegNoEffect(MISCREG_PRV) == PRV_M);
// Specs do not seem to mention what should be
// configured first, cfg or address regs!
// qemu seems to update the tables when
// pmp addr regs are written (with the assumption
// that cfg regs are already written)
for (int i=0; i < sizeof(val); i++) {
uint8_t cfg_val = (val >> (8*i)) & 0xff;
auto mmu = dynamic_cast<RiscvISA::MMU *>
(tc->getMMUPtr());
// Form pmp_index using the index i and
// PMPCFG register number
// Note: MISCREG_PMPCFG2 - MISCREG_PMPCFG0 = 1
// 8*(misc_reg-MISCREG_PMPCFG0) will be useful
// if a system contains more than 16 PMP entries
uint32_t pmp_index = i+(8*(misc_reg-MISCREG_PMPCFG0));
mmu->getPMP()->pmpUpdateCfg(pmp_index,cfg_val);
}
setMiscRegNoEffect(misc_reg, val);
}
break;
case MISCREG_PMPADDR00 ... MISCREG_PMPADDR15:
{
// PMP registers should only be modified in M mode
assert(readMiscRegNoEffect(MISCREG_PRV) == PRV_M);
auto mmu = dynamic_cast<RiscvISA::MMU *>
(tc->getMMUPtr());
uint32_t pmp_index = misc_reg-MISCREG_PMPADDR00;
mmu->getPMP()->pmpUpdateAddr(pmp_index, val);
setMiscRegNoEffect(misc_reg, val);
}
break;
case MISCREG_IP:
{
auto ic = dynamic_cast<RiscvISA::Interrupts *>(
tc->getCpuPtr()->getInterruptController(tc->threadId()));
ic->setIP(val);
}
break;
case MISCREG_IE:
{
auto ic = dynamic_cast<RiscvISA::Interrupts *>(
tc->getCpuPtr()->getInterruptController(tc->threadId()));
ic->setIE(val);
}
break;
case MISCREG_SATP:
{
// we only support bare and Sv39 mode; setting a different mode
// shall have no effect (see 4.1.12 in priv ISA manual)
SATP cur_val = readMiscRegNoEffect(misc_reg);
SATP new_val = val;
if (new_val.mode != AddrXlateMode::BARE &&
new_val.mode != AddrXlateMode::SV39)
new_val.mode = cur_val.mode;
setMiscRegNoEffect(misc_reg, new_val);
}
break;
case MISCREG_TSELECT:
{
// we don't support debugging, so always set a different value
// than written
setMiscRegNoEffect(misc_reg, val + 1);
}
break;
case MISCREG_ISA:
{
auto cur_val = readMiscRegNoEffect(misc_reg);
// only allow to disable compressed instructions
// if the following instruction is 4-byte aligned
if ((val & ISA_EXT_C_MASK) == 0 &&
bits(tc->pcState().npc(), 2, 0) != 0)
val |= cur_val & ISA_EXT_C_MASK;
setMiscRegNoEffect(misc_reg, val);
}
break;
case MISCREG_STATUS:
{
// SXL and UXL are hard-wired to 64 bit
auto cur = readMiscRegNoEffect(misc_reg);
val &= ~(STATUS_SXL_MASK | STATUS_UXL_MASK);
val |= cur & (STATUS_SXL_MASK | STATUS_UXL_MASK);
setMiscRegNoEffect(misc_reg, val);
}
break;
default:
setMiscRegNoEffect(misc_reg, val);
}
}
}
void
ISA::serialize(CheckpointOut &cp) const
{
DPRINTF(Checkpoint, "Serializing Riscv Misc Registers\n");
SERIALIZE_CONTAINER(miscRegFile);
}
void
ISA::unserialize(CheckpointIn &cp)
{
DPRINTF(Checkpoint, "Unserializing Riscv Misc Registers\n");
UNSERIALIZE_CONTAINER(miscRegFile);
}
const int WARN_FAILURE = 10000;
// RISC-V allows multiple locks per hart, but each SC has to unlock the most
// recent one, so we use a stack here.
std::unordered_map<int, std::stack<Addr>> locked_addrs;
void
ISA::handleLockedSnoop(PacketPtr pkt, Addr cacheBlockMask)
{
std::stack<Addr>& locked_addr_stack = locked_addrs[tc->contextId()];
if (locked_addr_stack.empty())
return;
Addr snoop_addr = pkt->getAddr() & cacheBlockMask;
DPRINTF(LLSC, "Locked snoop on address %x.\n", snoop_addr);
if ((locked_addr_stack.top() & cacheBlockMask) == snoop_addr)
locked_addr_stack.pop();
}
void
ISA::handleLockedRead(const RequestPtr &req)
{
std::stack<Addr>& locked_addr_stack = locked_addrs[tc->contextId()];
locked_addr_stack.push(req->getPaddr() & ~0xF);
DPRINTF(LLSC, "[cid:%d]: Reserved address %x.\n",
req->contextId(), req->getPaddr() & ~0xF);
}
bool
ISA::handleLockedWrite(const RequestPtr &req, Addr cacheBlockMask)
{
std::stack<Addr>& locked_addr_stack = locked_addrs[tc->contextId()];
// Normally RISC-V uses zero to indicate success and nonzero to indicate
// failure (right now only 1 is reserved), but in gem5 zero indicates
// failure and one indicates success, so here we conform to that (it should
// be switched in the instruction's implementation)
DPRINTF(LLSC, "[cid:%d]: locked_addrs empty? %s.\n", req->contextId(),
locked_addr_stack.empty() ? "yes" : "no");
if (!locked_addr_stack.empty()) {
DPRINTF(LLSC, "[cid:%d]: addr = %x.\n", req->contextId(),
req->getPaddr() & ~0xF);
DPRINTF(LLSC, "[cid:%d]: last locked addr = %x.\n", req->contextId(),
locked_addr_stack.top());
}
if (locked_addr_stack.empty()
|| locked_addr_stack.top() != ((req->getPaddr() & ~0xF))) {
req->setExtraData(0);
int stCondFailures = tc->readStCondFailures();
tc->setStCondFailures(++stCondFailures);
if (stCondFailures % WARN_FAILURE == 0) {
warn("%i: context %d: %d consecutive SC failures.\n",
curTick(), tc->contextId(), stCondFailures);
}
return false;
}
if (req->isUncacheable()) {
req->setExtraData(2);
}
return true;
}
void
ISA::globalClearExclusive()
{
tc->getCpuPtr()->wakeup(tc->threadId());
}
} // namespace RiscvISA
} // namespace gem5