arm: Add support for the dc {civac, cvac, cvau, ivac} instr
This patch adds support for decoding and executing the following ARMv8
cache maintenance instructions by Virtual Address:
* dc civac: Clean and Invalidate by Virtual Address to the Point
of Coherency
* dc cvac: Clean by Virtual Address to the Point of Coherency
* dc cvau: Clean by Virtual Address to the Point of Unification
* dc ivac: Invalidate by Virtual Addrsess to the Point of Coherency
Change-Id: I58cabda37f9636105fda1b1e84a0a04965fb5670
Reviewed-by: Sudhanshu Jha <sudhanshu.jha@arm.com>
Reviewed-by: Stephan Diestelhorst <stephan.diestelhorst@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/5060
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2013 ARM Limited
|
||||
* Copyright (c) 2011-2013,2017 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -52,9 +52,9 @@ class SysDC64 : public ArmStaticInst
|
||||
uint64_t imm;
|
||||
|
||||
SysDC64(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
|
||||
IntRegIndex _base, IntRegIndex _dest, uint64_t _imm)
|
||||
: ArmStaticInst(mnem, _machInst, __opClass), base(_base), dest(_dest),
|
||||
imm(_imm)
|
||||
IntRegIndex _base, MiscRegIndex miscReg, uint64_t _imm)
|
||||
: ArmStaticInst(mnem, _machInst, __opClass), base(_base),
|
||||
dest((IntRegIndex)miscReg), imm(_imm)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
@@ -350,6 +350,7 @@ namespace Aarch64
|
||||
if (read) {
|
||||
if ((miscReg == MISCREG_DC_CIVAC_Xt) ||
|
||||
(miscReg == MISCREG_DC_CVAC_Xt) ||
|
||||
(miscReg == MISCREG_DC_IVAC_Xt) ||
|
||||
(miscReg == MISCREG_DC_ZVA_Xt)) {
|
||||
return new Unknown64(machInst);
|
||||
}
|
||||
@@ -365,16 +366,26 @@ namespace Aarch64
|
||||
return new MsrNZCV64(machInst, (IntRegIndex) miscReg, rt);
|
||||
}
|
||||
uint32_t iss = msrMrs64IssBuild(read, op0, op1, crn, crm, op2, rt);
|
||||
if (miscReg == MISCREG_DC_ZVA_Xt && !read)
|
||||
return new Dczva(machInst, rt, (IntRegIndex) miscReg, iss);
|
||||
|
||||
if (read) {
|
||||
StaticInstPtr si = new Mrs64(machInst, rt, miscReg, iss);
|
||||
if (miscRegInfo[miscReg][MISCREG_UNVERIFIABLE])
|
||||
si->setFlag(StaticInst::IsUnverifiable);
|
||||
return si;
|
||||
} else {
|
||||
return new Msr64(machInst, miscReg, rt, iss);
|
||||
switch (miscReg) {
|
||||
case MISCREG_DC_ZVA_Xt:
|
||||
return new Dczva(machInst, rt, miscReg, iss);
|
||||
case MISCREG_DC_CVAU_Xt:
|
||||
return new Dccvau(machInst, rt, miscReg, iss);
|
||||
case MISCREG_DC_CVAC_Xt:
|
||||
return new Dccvac(machInst, rt, miscReg, iss);
|
||||
case MISCREG_DC_CIVAC_Xt:
|
||||
return new Dccivac(machInst, rt, miscReg, iss);
|
||||
case MISCREG_DC_IVAC_Xt:
|
||||
return new Dcivac(machInst, rt, miscReg, iss);
|
||||
default:
|
||||
return new Msr64(machInst, miscReg, rt, iss);
|
||||
}
|
||||
}
|
||||
} else if (miscRegInfo[miscReg][MISCREG_WARN_NOT_FAIL]) {
|
||||
std::string full_mnem = csprintf("%s %s",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// -*- mode:c++ -*-
|
||||
|
||||
// Copyright (c) 2011-2013, 2016 ARM Limited
|
||||
// Copyright (c) 2011-2013, 2016-2017 ARM Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// The license below extends only to copyright in the software and shall
|
||||
@@ -317,7 +317,8 @@ let {{
|
||||
if (flat_idx == MISCREG_DAIF ||
|
||||
flat_idx == MISCREG_DC_ZVA_Xt ||
|
||||
flat_idx == MISCREG_DC_CVAC_Xt ||
|
||||
flat_idx == MISCREG_DC_CIVAC_Xt
|
||||
flat_idx == MISCREG_DC_CIVAC_Xt ||
|
||||
flat_idx == MISCREG_DC_IVAC_Xt
|
||||
)
|
||||
return std::make_shared<UndefinedInstruction>(
|
||||
machInst, 0, EC_TRAPPED_MSR_MRS_64,
|
||||
@@ -427,6 +428,117 @@ let {{
|
||||
exec_output += Store64CompleteAcc.subst(msrDCZVAIop);
|
||||
|
||||
|
||||
msrdccvau_ea_code = '''
|
||||
MiscRegIndex flat_idx = (MiscRegIndex) xc->tcBase()->flattenRegId(
|
||||
RegId(MiscRegClass, dest)).index();
|
||||
CPSR cpsr = Cpsr;
|
||||
ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
|
||||
'''
|
||||
|
||||
msrdccvau_ea_code += msrMrs64EnabledCheckCode % ('Write', 'false')
|
||||
msrdccvau_ea_code += '''
|
||||
Request::Flags memAccessFlags = Request::CLEAN | Request::DST_POU |
|
||||
ArmISA::TLB::MustBeOne;
|
||||
EA = XBase;
|
||||
System *sys = xc->tcBase()->getSystemPtr();
|
||||
Addr op_size = sys->cacheLineSize();
|
||||
EA &= ~(op_size - 1);
|
||||
'''
|
||||
|
||||
msrDCCVAUIop = InstObjParams("dc cvau", "Dccvau", "SysDC64",
|
||||
{ "ea_code" : msrdccvau_ea_code,
|
||||
"memacc_code" : ";", "use_uops" : 0,
|
||||
"op_wb" : ";", "fa_code" : ";"}, ['IsStore', 'IsMemRef']);
|
||||
header_output += DCStore64Declare.subst(msrDCCVAUIop);
|
||||
decoder_output += DCStore64Constructor.subst(msrDCCVAUIop);
|
||||
exec_output += DCStore64Execute.subst(msrDCCVAUIop);
|
||||
exec_output += DCStore64InitiateAcc.subst(msrDCCVAUIop);
|
||||
exec_output += Store64CompleteAcc.subst(msrDCCVAUIop);
|
||||
|
||||
|
||||
msrdccvac_ea_code = '''
|
||||
MiscRegIndex flat_idx = (MiscRegIndex) xc->tcBase()->flattenRegId(
|
||||
RegId(MiscRegClass, dest)).index();
|
||||
CPSR cpsr = Cpsr;
|
||||
ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
|
||||
'''
|
||||
|
||||
msrdccvac_ea_code += msrMrs64EnabledCheckCode % ('Write', 'false')
|
||||
msrdccvac_ea_code += '''
|
||||
Request::Flags memAccessFlags = Request::CLEAN | Request::DST_POC |
|
||||
ArmISA::TLB::MustBeOne;
|
||||
EA = XBase;
|
||||
System *sys = xc->tcBase()->getSystemPtr();
|
||||
Addr op_size = sys->cacheLineSize();
|
||||
EA &= ~(op_size - 1);
|
||||
'''
|
||||
|
||||
msrDCCVACIop = InstObjParams("dc cvac", "Dccvac", "SysDC64",
|
||||
{ "ea_code" : msrdccvac_ea_code,
|
||||
"memacc_code" : ";", "use_uops" : 0,
|
||||
"op_wb" : ";", "fa_code" : ";"}, ['IsStore', 'IsMemRef']);
|
||||
header_output += DCStore64Declare.subst(msrDCCVACIop);
|
||||
decoder_output += DCStore64Constructor.subst(msrDCCVACIop);
|
||||
exec_output += DCStore64Execute.subst(msrDCCVACIop);
|
||||
exec_output += DCStore64InitiateAcc.subst(msrDCCVACIop);
|
||||
exec_output += Store64CompleteAcc.subst(msrDCCVACIop);
|
||||
|
||||
|
||||
msrdccivac_ea_code = '''
|
||||
MiscRegIndex flat_idx = (MiscRegIndex) xc->tcBase()->flattenRegId(
|
||||
RegId(MiscRegClass, dest)).index();
|
||||
CPSR cpsr = Cpsr;
|
||||
ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
|
||||
'''
|
||||
|
||||
msrdccivac_ea_code += msrMrs64EnabledCheckCode % ('Write', 'false')
|
||||
msrdccivac_ea_code += '''
|
||||
Request::Flags memAccessFlags = Request::CLEAN |
|
||||
Request::INVALIDATE | Request::DST_POC | ArmISA::TLB::MustBeOne;
|
||||
EA = XBase;
|
||||
System *sys = xc->tcBase()->getSystemPtr();
|
||||
Addr op_size = sys->cacheLineSize();
|
||||
EA &= ~(op_size - 1);
|
||||
'''
|
||||
|
||||
msrDCCIVACIop = InstObjParams("dc civac", "Dccivac", "SysDC64",
|
||||
{ "ea_code" : msrdccivac_ea_code,
|
||||
"memacc_code" : ";", "use_uops" : 0,
|
||||
"op_wb" : ";", "fa_code" : ";"}, ['IsStore', 'IsMemRef']);
|
||||
header_output += DCStore64Declare.subst(msrDCCIVACIop);
|
||||
decoder_output += DCStore64Constructor.subst(msrDCCIVACIop);
|
||||
exec_output += DCStore64Execute.subst(msrDCCIVACIop);
|
||||
exec_output += DCStore64InitiateAcc.subst(msrDCCIVACIop);
|
||||
exec_output += Store64CompleteAcc.subst(msrDCCIVACIop);
|
||||
|
||||
|
||||
msrdcivac_ea_code = '''
|
||||
MiscRegIndex flat_idx = (MiscRegIndex) xc->tcBase()->flattenRegId(
|
||||
RegId(MiscRegClass, dest)).index();
|
||||
CPSR cpsr = Cpsr;
|
||||
ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
|
||||
'''
|
||||
|
||||
msrdcivac_ea_code += msrMrs64EnabledCheckCode % ('Write', 'false')
|
||||
msrdcivac_ea_code += '''
|
||||
Request::Flags memAccessFlags = Request::INVALIDATE |
|
||||
Request::DST_POC | ArmISA::TLB::MustBeOne;
|
||||
EA = XBase;
|
||||
System *sys = xc->tcBase()->getSystemPtr();
|
||||
Addr op_size = sys->cacheLineSize();
|
||||
EA &= ~(op_size - 1);
|
||||
'''
|
||||
|
||||
msrDCIVACIop = InstObjParams("dc ivac", "Dcivac", "SysDC64",
|
||||
{ "ea_code" : msrdcivac_ea_code,
|
||||
"memacc_code" : ";", "use_uops" : 0,
|
||||
"op_wb" : ";", "fa_code" : ";"}, ['IsStore', 'IsMemRef']);
|
||||
header_output += DCStore64Declare.subst(msrDCIVACIop);
|
||||
decoder_output += DCStore64Constructor.subst(msrDCIVACIop);
|
||||
exec_output += DCStore64Execute.subst(msrDCIVACIop);
|
||||
exec_output += DCStore64InitiateAcc.subst(msrDCIVACIop);
|
||||
exec_output += Store64CompleteAcc.subst(msrDCIVACIop);
|
||||
|
||||
|
||||
buildDataXImmInst("msrSP", '''
|
||||
if (!canWriteAArch64SysReg(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// -*- mode:c++ -*-
|
||||
|
||||
// Copyright (c) 2011-2014 ARM Limited
|
||||
// Copyright (c) 2011-2014, 2017 ARM Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// The license below extends only to copyright in the software and shall
|
||||
@@ -256,7 +256,8 @@ def template DCStore64Declare {{
|
||||
public:
|
||||
|
||||
/// Constructor.
|
||||
%(class_name)s(ExtMachInst machInst, IntRegIndex _base, IntRegIndex _dest, uint64_t _imm);
|
||||
%(class_name)s(ExtMachInst machInst, IntRegIndex _base,
|
||||
MiscRegIndex _dest, uint64_t _imm);
|
||||
|
||||
Fault execute(ExecContext *, Trace::InstRecord *) const;
|
||||
Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
|
||||
@@ -270,9 +271,10 @@ def template DCStore64Declare {{
|
||||
}};
|
||||
|
||||
def template DCStore64Constructor {{
|
||||
%(class_name)s::%(class_name)s(ExtMachInst machInst, IntRegIndex _base, IntRegIndex _dest, uint64_t _imm)
|
||||
%(class_name)s::%(class_name)s(ExtMachInst machInst, IntRegIndex _base,
|
||||
MiscRegIndex _dest, uint64_t _imm)
|
||||
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
|
||||
(IntRegIndex)_base, _dest, _imm)
|
||||
_base, _dest, _imm)
|
||||
{
|
||||
%(constructor)s;
|
||||
assert(!%(use_uops)d);
|
||||
|
||||
Reference in New Issue
Block a user