Skip to content

Commit

Permalink
riscv: fix Linux problems with LR and SC ops
Browse files Browse the repository at this point in the history
Some of the functions in the Linux toolchain that allocate memory make
use of paired LR and SC instructions, which didn't work properly for
that toolchain.  This patch fixes that so attempting to use those
functions doesn't cause an endless loop of failed SC instructions.

Change-Id: If27696323dd6229a0277818e3744fbdf7180fca7
Reviewed-on: https://gem5-review.googlesource.com/2340
Maintainer: Alec Roelke <[email protected]>
Reviewed-by: Jason Lowe-Power <[email protected]>
  • Loading branch information
aroelke committed Apr 5, 2017
1 parent 6b7d306 commit a8f1f98
Show file tree
Hide file tree
Showing 7 changed files with 325 additions and 100 deletions.
1 change: 1 addition & 0 deletions src/arch/riscv/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ if env['TARGET_ISA'] == 'riscv':
Source('faults.cc')
Source('isa.cc')
Source('interrupts.cc')
Source('locked_mem.cc')
Source('process.cc')
Source('pagetable.cc')
Source('remote_gdb.cc')
Expand Down
8 changes: 4 additions & 4 deletions src/arch/riscv/isa/decoder.isa
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,12 @@ decode OPCODE default Unknown::unknown() {
0x2: decode AMOFUNCT {
0x2: LoadReserved::lr_w({{
Rd_sd = Mem_sw;
}}, mem_flags=LLSC, aq=AQ, rl=RL);
}}, mem_flags=LLSC);
0x3: StoreCond::sc_w({{
Mem_uw = Rs2_uw;
}}, {{
Rd = result;
}}, inst_flags=IsStoreConditional, mem_flags=LLSC, aq=AQ, rl=RL);
}}, inst_flags=IsStoreConditional, mem_flags=LLSC);
format AtomicMemOp {
0x0: amoadd_w({{Rt_sd = Mem_sw;}}, {{
Mem_sw = Rs2_sw + Rt_sd;
Expand Down Expand Up @@ -218,12 +218,12 @@ decode OPCODE default Unknown::unknown() {
0x3: decode AMOFUNCT {
0x2: LoadReserved::lr_d({{
Rd_sd = Mem_sd;
}}, mem_flags=LLSC, aq=AQ, rl=RL);
}}, mem_flags=LLSC);
0x3: StoreCond::sc_d({{
Mem = Rs2;
}}, {{
Rd = result;
}}, mem_flags=LLSC, inst_flags=IsStoreConditional, aq=AQ, rl=RL);
}}, mem_flags=LLSC, inst_flags=IsStoreConditional);
format AtomicMemOp {
0x0: amoadd_d({{Rt_sd = Mem_sd;}}, {{
Mem_sd = Rs2_sd + Rt_sd;
Expand Down
292 changes: 291 additions & 1 deletion src/arch/riscv/isa/formats/amo.isa
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,33 @@
// Atomic memory operation instructions
//
output header {{
class LoadReserved : public RiscvStaticInst
{
protected:
Request::Flags memAccessFlags;

LoadReserved(const char *mnem, ExtMachInst _machInst,
OpClass __opClass)
: RiscvStaticInst(mnem, _machInst, __opClass)
{}

std::string
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};

class StoreCond : public RiscvStaticInst
{
protected:
Request::Flags memAccessFlags;

StoreCond(const char* mnem, ExtMachInst _machInst, OpClass __opClass)
: RiscvStaticInst(mnem, _machInst, __opClass)
{}

std::string
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};

class AtomicMemOp : public RiscvMacroInst
{
protected:
Expand Down Expand Up @@ -65,11 +92,29 @@ output header {{
}};

output decoder {{
std::string LoadReserved::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
std::stringstream ss;
ss << mnemonic << ' ' << regName(_destRegIdx[0]) << ", ("
<< regName(_srcRegIdx[0]) << ')';
return ss.str();
}

std::string StoreCond::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
std::stringstream ss;
ss << mnemonic << ' ' << regName(_destRegIdx[0]) << ", "
<< regName(_srcRegIdx[1]) << ", ("
<< regName(_srcRegIdx[0]) << ')';
return ss.str();
}

std::string AtomicMemOp::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
std::stringstream ss;
ss << csprintf("0x%08x", machInst) << ' ';
ss << mnemonic << ' ' << regName(_destRegIdx[0]) << ", "
<< regName(_srcRegIdx[1]) << ", ("
<< regName(_srcRegIdx[0]) << ')';
Expand All @@ -85,6 +130,22 @@ output decoder {{
}
}};

def template LRSCDeclare {{
class %(class_name)s : public %(base_class)s
{
public:
%(class_name)s(ExtMachInst machInst);

%(BasicExecDeclare)s

%(EACompDeclare)s

%(InitiateAccDeclare)s

%(CompleteAccDeclare)s
};
}};

def template AtomicMemOpDeclare {{
/**
* Static instruction class for an AtomicMemOp operation
Expand Down Expand Up @@ -129,6 +190,18 @@ def template AtomicMemOpDeclare {{
};
}};

def template LRSCConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst):
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
{
%(constructor)s;
if (AQ)
memAccessFlags = memAccessFlags | Request::ACQUIRE;
if (RL)
memAccessFlags = memAccessFlags | Request::RELEASE;
}
}};

def template AtomicMemOpMacroConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
Expand Down Expand Up @@ -169,6 +242,67 @@ def template AtomicMemOpMacroDecode {{
return new %(class_name)s(machInst);
}};

def template LoadReservedExecute {{
Fault
%(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;

%(op_decl)s;
%(op_rd)s;
%(ea_code)s;

if (fault == NoFault) {
fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags);
%(memacc_code)s;
}

if (fault == NoFault) {
%(op_wb)s;
}

return fault;
}
}};

def template StoreCondExecute {{
Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
uint64_t result;

%(op_decl)s;
%(op_rd)s;
%(ea_code)s;

if (fault == NoFault) {
%(memacc_code)s;
}

if (fault == NoFault) {
fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
&result);
// RISC-V has the opposite convention gem5 has for success flags,
// so we invert the result here.
result = !result;
}

if (fault == NoFault) {
%(postacc_code)s;
}

if (fault == NoFault) {
%(op_wb)s;
}

return fault;
}
}};

def template AtomicMemOpLoadExecute {{
Fault %(class_name)s::%(class_name)sLoad::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
Expand Down Expand Up @@ -224,6 +358,27 @@ def template AtomicMemOpStoreExecute {{
}
}};

def template LRSCEACompExecute {{
Fault
%(class_name)s::eaComp(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;

%(op_decl)s;
%(op_rd)s;
%(ea_code)s;

if (fault == NoFault) {
%(op_wb)s;
xc->setEA(EA);
}

return fault;
}
}};

def template AtomicMemOpLoadEACompExecute {{
Fault %(class_name)s::%(class_name)sLoad::eaComp(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
Expand Down Expand Up @@ -264,6 +419,55 @@ def template AtomicMemOpStoreEACompExecute {{
}
}};

def template LoadReservedInitiateAcc {{
Fault
%(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;

%(op_src_decl)s;
%(op_rd)s;
%(ea_code)s;

if (fault == NoFault) {
fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
}

return fault;
}
}};

def template StoreCondInitiateAcc {{
Fault
%(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;

%(op_decl)s;
%(op_rd)s;
%(ea_code)s;

if (fault == NoFault) {
%(memacc_code)s;
}

if (fault == NoFault) {
fault = writeMemTiming(xc, traceData, Mem, EA,
memAccessFlags, nullptr);
}

if (fault == NoFault) {
%(op_wb)s;
}

return fault;
}
}};

def template AtomicMemOpLoadInitiateAcc {{
Fault %(class_name)s::%(class_name)sLoad::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
Expand Down Expand Up @@ -311,6 +515,54 @@ def template AtomicMemOpStoreInitiateAcc {{
}
}};

def template LoadReservedCompleteAcc {{
Fault
%(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;

%(op_decl)s;
%(op_rd)s;

getMem(pkt, Mem, traceData);

if (fault == NoFault) {
%(memacc_code)s;
}

if (fault == NoFault) {
%(op_wb)s;
}

return fault;
}
}};

def template StoreCondCompleteAcc {{
Fault %(class_name)s::completeAcc(Packet *pkt, CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;

%(op_dest_decl)s;

// RISC-V has the opposite convention gem5 has for success flags,
// so we invert the result here.
uint64_t result = !pkt->req->getExtraData();

if (fault == NoFault) {
%(postacc_code)s;
}

if (fault == NoFault) {
%(op_wb)s;
}

return fault;
}
}};

def template AtomicMemOpLoadCompleteAcc {{
Fault %(class_name)s::%(class_name)sLoad::completeAcc(PacketPtr pkt,
CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
Expand Down Expand Up @@ -342,6 +594,44 @@ def template AtomicMemOpStoreCompleteAcc {{
}
}};

def format LoadReserved(memacc_code, postacc_code={{ }}, ea_code={{EA = Rs1;}},
mem_flags=[], inst_flags=[]) {{
mem_flags = makeList(mem_flags)
inst_flags = makeList(inst_flags)
iop = InstObjParams(name, Name, 'LoadReserved',
{'ea_code': ea_code, 'memacc_code': memacc_code,
'postacc_code': postacc_code}, inst_flags)
iop.constructor += '\n\tmemAccessFlags = memAccessFlags | ' + \
'|'.join(['Request::%s' % flag for flag in mem_flags]) + ';'

header_output = LRSCDeclare.subst(iop)
decoder_output = LRSCConstructor.subst(iop)
decode_block = BasicDecode.subst(iop)
exec_output = LoadReservedExecute.subst(iop) \
+ LRSCEACompExecute.subst(iop) \
+ LoadReservedInitiateAcc.subst(iop) \
+ LoadReservedCompleteAcc.subst(iop)
}};

def format StoreCond(memacc_code, postacc_code={{ }}, ea_code={{EA = Rs1;}},
mem_flags=[], inst_flags=[]) {{
mem_flags = makeList(mem_flags)
inst_flags = makeList(inst_flags)
iop = InstObjParams(name, Name, 'StoreCond',
{'ea_code': ea_code, 'memacc_code': memacc_code,
'postacc_code': postacc_code}, inst_flags)
iop.constructor += '\n\tmemAccessFlags = memAccessFlags | ' + \
'|'.join(['Request::%s' % flag for flag in mem_flags]) + ';'

header_output = LRSCDeclare.subst(iop)
decoder_output = LRSCConstructor.subst(iop)
decode_block = BasicDecode.subst(iop)
exec_output = StoreCondExecute.subst(iop) \
+ LRSCEACompExecute.subst(iop) \
+ StoreCondInitiateAcc.subst(iop) \
+ StoreCondCompleteAcc.subst(iop)
}};

def format AtomicMemOp(load_code, store_code, ea_code, load_flags=[],
store_flags=[], inst_flags=[]) {{
macro_iop = InstObjParams(name, Name, 'AtomicMemOp', ea_code, inst_flags)
Expand Down
Loading

0 comments on commit a8f1f98

Please sign in to comment.