arm: Add support for the mcr dc{ic,i,c}mvac, dccmvau instructions

This patch adds support for the ARMv7 cache maintenance
intructions:
* mcr dccmvac cleans a VA to the PoC
* mcr dcimvac invalidates a VA to the PoC
* mcr dccimvac cleans and invalidates a VA to the PoC
* mcr dccmvau cleans a VA to the PoU

Change-Id: I6511f203039ca145cc9128ddf61d09d6d7e40c10
Reviewed-by: Stephan Diestelhorst <stephan.diestelhorst@arm.com>
Reviewed-by: Anouk Van Laer <anouk.vanlaer@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/5059
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
This commit is contained in:
Nikos Nikoleris
2017-02-07 11:35:10 +00:00
parent b9edb35145
commit eeb36e5b6e
5 changed files with 220 additions and 7 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2012-2013 ARM Limited
* Copyright (c) 2010, 2012-2013, 2017 ARM Limited
* Copyright (c) 2013 Advanced Micro Devices, Inc.
* All rights reserved
*
@@ -321,6 +321,16 @@ RegImmRegShiftOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
return ss.str();
}
std::string
MiscRegRegImmMemOp::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
std::stringstream ss;
printMnemonic(ss);
printIntReg(ss, op1);
return ss.str();
}
std::string
UnknownOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2012-2013 ARM Limited
* Copyright (c) 2010, 2012-2013, 2017 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -344,6 +344,23 @@ class RegImmRegShiftOp : public PredOp
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
class MiscRegRegImmMemOp : public PredOp
{
protected:
MiscRegIndex dest;
IntRegIndex op1;
uint64_t imm;
MiscRegRegImmMemOp(const char *mnem, ExtMachInst _machInst,
OpClass __opClass, MiscRegIndex _dest, IntRegIndex _op1,
uint64_t _imm) :
PredOp(mnem, _machInst, __opClass),
dest(_dest), op1(_op1), imm(_imm)
{}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
class UnknownOp : public PredOp
{
protected:

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2010-2013,2016 ARM Limited
// Copyright (c) 2010-2013,2016-2017 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@@ -219,15 +219,20 @@ let {{
machInst,
csprintf("miscreg crn:%d opc1:%d crm:%d opc2:%d %s unknown",
crn, opc1, crm, opc2, isRead ? "read" : "write"));
case MISCREG_DCCMVAC:
return new McrMrcMiscInst(isRead ? "mrc dccmvac" : "mcr dccmvac",
machInst, iss, MISCREG_DCCMVAC);
case MISCREG_CP15ISB:
return new Isb(machInst, iss);
case MISCREG_CP15DSB:
return new Dsb(machInst, iss);
case MISCREG_CP15DMB:
return new Dmb(machInst, iss);
case MISCREG_DCIMVAC:
return new McrDcimvac(machInst, miscReg, rt, iss);
case MISCREG_DCCMVAC:
return new McrDccmvac(machInst, miscReg, rt, iss);
case MISCREG_DCCMVAU:
return new McrDccmvau(machInst, miscReg, rt, iss);
case MISCREG_DCCIMVAC:
return new McrDccimvac(machInst, miscReg, rt, iss);
default:
if (miscRegInfo[miscReg][MISCREG_WARN_NOT_FAIL]) {
std::string full_mnem = csprintf("%s %s",

View File

@@ -1063,6 +1063,106 @@ let {{
decoder_output += BasicConstructor.subst(clrexIop)
exec_output += PredOpExecute.subst(clrexIop)
McrDcCheckCode = '''
int preFlatDest = flattenMiscRegNsBanked(dest, xc->tcBase());
MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenRegId(
RegId(MiscRegClass, preFlatDest)).index();
bool hypTrap = mcrMrc15TrapToHyp(miscReg, Hcr, Cpsr, Scr, Hdcr, Hstr,
Hcptr, imm);
bool can_write, undefined;
std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr);
// if we're in non secure PL1 mode then we can trap regardless
// of whether the register is accessible, in other modes we
// trap if only if the register IS accessible.
if (undefined || (!can_write & !(hypTrap & !inUserMode(Cpsr) &
!inSecureState(Scr, Cpsr)))) {
return std::make_shared<UndefinedInstruction>(machInst, false,
mnemonic);
}
if (hypTrap) {
return std::make_shared<HypervisorTrap>(machInst, imm,
EC_TRAPPED_CP15_MCR_MRC);
}
'''
McrDcimvacCode = '''
const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne |
Request::INVALIDATE |
Request::DST_POC);
EA = Op1;
'''
McrDcimvacIop = InstObjParams("mcr dcimvac", "McrDcimvac",
"MiscRegRegImmMemOp",
{"memacc_code": McrDcCheckCode,
"postacc_code": "",
"ea_code": McrDcimvacCode,
"predicate_test": predicateTest},
['IsMemRef', 'IsStore'])
header_output += MiscRegRegImmMemOpDeclare.subst(McrDcimvacIop)
decoder_output += MiscRegRegImmOpConstructor.subst(McrDcimvacIop)
exec_output += Mcr15Execute.subst(McrDcimvacIop) + \
Mcr15InitiateAcc.subst(McrDcimvacIop) + \
Mcr15CompleteAcc.subst(McrDcimvacIop)
McrDccmvacCode = '''
const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne |
Request::CLEAN |
Request::DST_POC);
EA = Op1;
'''
McrDccmvacIop = InstObjParams("mcr dccmvac", "McrDccmvac",
"MiscRegRegImmMemOp",
{"memacc_code": McrDcCheckCode,
"postacc_code": "",
"ea_code": McrDccmvacCode,
"predicate_test": predicateTest},
['IsMemRef', 'IsStore'])
header_output += MiscRegRegImmMemOpDeclare.subst(McrDccmvacIop)
decoder_output += MiscRegRegImmOpConstructor.subst(McrDccmvacIop)
exec_output += Mcr15Execute.subst(McrDccmvacIop) + \
Mcr15InitiateAcc.subst(McrDccmvacIop) + \
Mcr15CompleteAcc.subst(McrDccmvacIop)
McrDccmvauCode = '''
const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne |
Request::CLEAN |
Request::DST_POU);
EA = Op1;
'''
McrDccmvauIop = InstObjParams("mcr dccmvau", "McrDccmvau",
"MiscRegRegImmMemOp",
{"memacc_code": McrDcCheckCode,
"postacc_code": "",
"ea_code": McrDccmvauCode,
"predicate_test": predicateTest},
['IsMemRef', 'IsStore'])
header_output += MiscRegRegImmMemOpDeclare.subst(McrDccmvauIop)
decoder_output += MiscRegRegImmOpConstructor.subst(McrDccmvauIop)
exec_output += Mcr15Execute.subst(McrDccmvauIop) + \
Mcr15InitiateAcc.subst(McrDccmvauIop) + \
Mcr15CompleteAcc.subst(McrDccmvauIop)
McrDccimvacCode = '''
const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne |
Request::CLEAN |
Request::INVALIDATE |
Request::DST_POC);
EA = Op1;
'''
McrDccimvacIop = InstObjParams("mcr dccimvac", "McrDccimvac",
"MiscRegRegImmMemOp",
{"memacc_code": McrDcCheckCode,
"postacc_code": "",
"ea_code": McrDccimvacCode,
"predicate_test": predicateTest},
['IsMemRef', 'IsStore'])
header_output += MiscRegRegImmMemOpDeclare.subst(McrDccimvacIop)
decoder_output += MiscRegRegImmOpConstructor.subst(McrDccimvacIop)
exec_output += Mcr15Execute.subst(McrDccimvacIop) + \
Mcr15InitiateAcc.subst(McrDccimvacIop) + \
Mcr15CompleteAcc.subst(McrDccimvacIop)
isbCode = '''
// If the barrier is due to a CP15 access check for hyp traps
if ((imm != 0) && mcrMrc15TrapToHyp(MISCREG_CP15ISB, Hcr, Cpsr, Scr,

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2010-2013 ARM Limited
// Copyright (c) 2010-2013,2017 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@@ -614,3 +614,84 @@ def template RegImmRegShiftOpConstructor {{
}
}};
def template MiscRegRegImmMemOpDeclare {{
class %(class_name)s : public %(base_class)s
{
protected:
public:
// Constructor
%(class_name)s(ExtMachInst machInst,
MiscRegIndex _dest, IntRegIndex _op1,
uint64_t _imm);
Fault execute(ExecContext *, Trace::InstRecord *) const;
Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
};
}};
def template Mcr15Execute {{
Fault %(class_name)s::execute(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
if (%(predicate_test)s) {
if (fault == NoFault) {
%(memacc_code)s;
}
if (fault == NoFault) {
Addr size = 64;
EA &= ~(size - 1);
fault = xc->writeMem(NULL, size, EA, memAccessFlags, NULL);
}
} else {
xc->setPredicate(false);
}
return fault;
}
}};
def template Mcr15InitiateAcc {{
Fault %(class_name)s::initiateAcc(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
if (%(predicate_test)s) {
if (fault == NoFault) {
%(memacc_code)s;
}
if (fault == NoFault) {
Addr size = 64;
EA &= ~(size - 1);
fault = xc->writeMem(NULL, size, EA, memAccessFlags, NULL);
}
} else {
xc->setPredicate(false);
}
return fault;
}
}};
def template Mcr15CompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
ExecContext *xc,
Trace::InstRecord *traceData) const
{
return NoFault;
}
}};