diff --git a/src/arch/alpha/mmapped_ipr.hh b/src/arch/alpha/mmapped_ipr.hh index 24f7ce335..46ed6bd49 100644 --- a/src/arch/alpha/mmapped_ipr.hh +++ b/src/arch/alpha/mmapped_ipr.hh @@ -37,27 +37,11 @@ * ISA-specific helper functions for memory mapped IPR accesses. */ -#include "base/types.hh" -#include "mem/packet.hh" - -class ThreadContext; +#include "arch/generic/mmapped_ipr.hh" namespace AlphaISA { - -inline Cycles -handleIprRead(ThreadContext *xc, Packet *pkt) -{ - panic("No handleIprRead implementation in Alpha\n"); -} - - -inline Cycles -handleIprWrite(ThreadContext *xc, Packet *pkt) -{ - panic("No handleIprWrite implementation in Alpha\n"); -} - - + using GenericISA::handleIprRead; + using GenericISA::handleIprWrite; } // namespace AlphaISA #endif // __ARCH_ALPHA_MMAPPED_IPR_HH__ diff --git a/src/arch/arm/mmapped_ipr.hh b/src/arch/arm/mmapped_ipr.hh index 474aacbcf..d515b8371 100644 --- a/src/arch/arm/mmapped_ipr.hh +++ b/src/arch/arm/mmapped_ipr.hh @@ -39,26 +39,14 @@ * ISA-specific helper functions for memory mapped IPR accesses. */ -#include "base/misc.hh" -#include "mem/packet.hh" +#include "arch/generic/mmapped_ipr.hh" class ThreadContext; namespace ArmISA { -inline Cycles -handleIprRead(ThreadContext *xc, Packet *pkt) -{ - panic("No implementation for handleIprRead in ARM\n"); -} - -inline Cycles -handleIprWrite(ThreadContext *xc, Packet *pkt) -{ - panic("No implementation for handleIprWrite in ARM\n"); -} - - + using GenericISA::handleIprRead; + using GenericISA::handleIprWrite; } // namespace ArmISA #endif diff --git a/src/arch/generic/SConscript b/src/arch/generic/SConscript index 3dfc509a4..bac70fa32 100644 --- a/src/arch/generic/SConscript +++ b/src/arch/generic/SConscript @@ -32,3 +32,4 @@ if env['TARGET_ISA'] == 'null': Return() Source('decode_cache.cc') +Source('mmapped_ipr.cc') diff --git a/src/arch/generic/mmapped_ipr.cc b/src/arch/generic/mmapped_ipr.cc new file mode 100644 index 000000000..3d85eea9f --- /dev/null +++ b/src/arch/generic/mmapped_ipr.cc @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2013 Andreas Sandberg + * 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. + * + * Authors: Andreas Sandberg + */ + +#include "arch/generic/mmapped_ipr.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" +#include "sim/pseudo_inst.hh" + +using namespace GenericISA; + +static void +handlePseudoInst(ThreadContext *xc, Packet *pkt) +{ + const Addr offset(pkt->getAddr() & IPR_IN_CLASS_MASK); + const uint8_t func((offset >> 8) & 0xFF); + const uint8_t subfunc(offset & 0xFF); + uint64_t ret; + + assert((offset >> 16) == 0); + ret = PseudoInst::pseudoInst(xc, func, subfunc); + if (pkt->isRead()) + pkt->set(ret); +} + +Cycles +GenericISA::handleGenericIprRead(ThreadContext *xc, Packet *pkt) +{ + Addr va(pkt->getAddr()); + Addr cls((va & IPR_CLASS_MASK) >> IPR_CLASS_SHIFT); + + switch (cls) { + case IPR_CLASS_PSEUDO_INST: + handlePseudoInst(xc, pkt); + break; + default: + panic("Unhandled generic IPR read: 0x%x\n", va); + } + + return Cycles(1); +} + +Cycles +GenericISA::handleGenericIprWrite(ThreadContext *xc, Packet *pkt) +{ + Addr va(pkt->getAddr()); + Addr cls((va & IPR_CLASS_MASK) >> IPR_CLASS_SHIFT); + + switch (cls) { + case IPR_CLASS_PSEUDO_INST: + handlePseudoInst(xc, pkt); + break; + default: + panic("Unhandled generic IPR write: 0x%x\n", va); + } + + return Cycles(1); +} diff --git a/src/arch/generic/mmapped_ipr.hh b/src/arch/generic/mmapped_ipr.hh new file mode 100644 index 000000000..55ce6e4d5 --- /dev/null +++ b/src/arch/generic/mmapped_ipr.hh @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2013 Andreas Sandberg + * 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. + * + * Authors: Andreas Sandberg + */ + +#ifndef __ARCH_GENERIC_MMAPPED_IPR_HH__ +#define __ARCH_GENERIC_MMAPPED_IPR_HH__ + +#include "base/types.hh" +#include "mem/packet.hh" + +class ThreadContext; + +/** + * @file + * + * ISA-generic helper functions for memory mapped IPR accesses. + */ + +namespace GenericISA +{ + /** @{ */ + /** + * Memory requests with the MMAPPED_IPR flag are generally mapped + * to registers. There is a class of these registers that are + * internal to gem5, for example gem5 pseudo-ops in virtualized + * mode. + * + * In order to make the IPR space manageable we always set bit 63 + * (IPR_GENERIC) for accesses that should be handled by the + * generic ISA code. Architectures may use the rest of the IPR + * space internally. + */ + + /** Is this a generic IPR access? */ + const Addr IPR_GENERIC = ULL(0x8000000000000000); + + /** @{ */ + /** Mask when extracting the class of a generic IPR */ + const Addr IPR_CLASS_MASK = ULL(0x7FFF000000000000); + /** Shift amount when extracting the class of a generic IPR */ + const int IPR_CLASS_SHIFT = 48; + /** @} */ + + /** Mask to extract the offset in within a generic IPR class */ + const Addr IPR_IN_CLASS_MASK = ULL(0x0000FFFFFFFFFFFF); + + /** gem5 pseudo-inst emulation. + * + * Read and writes to this class execute gem5 + * pseudo-instructions. A write discards the return value of the + * instruction, while a read returns it. + * + * @see pseudoInst() + */ + const Addr IPR_CLASS_PSEUDO_INST = 0x0; + + /** @} */ + + /** + * Generate a generic IPR address that emulates a pseudo inst + * + * @see PseudoInst::pseudoInst() + * + * @param func Function ID to call. + * @param subfunc Sub-function, usually 0. + * @return Address in the IPR space corresponding to the call. + */ + inline Addr + iprAddressPseudoInst(uint8_t func, uint8_t subfunc) + { + return IPR_GENERIC | (IPR_CLASS_PSEUDO_INST << IPR_CLASS_SHIFT) | + (func << 8) | subfunc; + } + + /** + * Check if this is an platform independent IPR access + * + * Accesses to internal platform independent gem5 registers are + * handled by handleGenericIprRead() and + * handleGenericIprWrite(). This method determines if a packet + * should be routed to those functions instead of the platform + * specific code. + * + * @see handleGenericIprRead + * @see handleGenericIprWrite + */ + inline bool + isGenericIprAccess(const Packet *pkt) + { + return pkt->getAddr() & IPR_GENERIC; + } + + /** + * Handle generic IPR reads + * + * @param xc Thread context of the current thread. + * @param pkt Packet from the CPU + * @return Latency in CPU cycles + */ + Cycles handleGenericIprRead(ThreadContext *xc, Packet *pkt); + /** + * Handle generic IPR writes + * + * @param xc Thread context of the current thread. + * @param pkt Packet from the CPU + * @return Latency in CPU cycles + */ + Cycles handleGenericIprWrite(ThreadContext *xc, Packet *pkt); + + /** + * Helper function to handle IPRs when the target architecture doesn't + * need its own IPR handling. + * + * This function calls handleGenericIprRead if the accessing a + * generic IPR and panics otherwise. + * + * @param xc Thread context of the current thread. + * @param pkt Packet from the CPU + * @return Latency in CPU cycles + */ + inline Cycles + handleIprRead(ThreadContext *xc, Packet *pkt) + { + if (!isGenericIprAccess(pkt)) + panic("Unhandled IPR access\n"); + + return handleGenericIprRead(xc, pkt); + } + + + /** + * Helper function to handle IPRs when the target architecture + * doesn't need its own IPR handling. + * + * This function calls handleGenericIprWrite if the accessing a + * generic IPR and panics otherwise. + * + * @param xc Thread context of the current thread. + * @param pkt Packet from the CPU + * @return Latency in CPU cycles + */ + inline Cycles + handleIprWrite(ThreadContext *xc, Packet *pkt) + { + if (!isGenericIprAccess(pkt)) + panic("Unhandled IPR access\n"); + + return handleGenericIprWrite(xc, pkt); + } + +} // namespace GenericISA + + + +#endif diff --git a/src/arch/mips/mmapped_ipr.hh b/src/arch/mips/mmapped_ipr.hh index 4c84d05f2..032fa28b2 100644 --- a/src/arch/mips/mmapped_ipr.hh +++ b/src/arch/mips/mmapped_ipr.hh @@ -37,26 +37,14 @@ * ISA-specific helper functions for memory mapped IPR accesses. */ -#include "base/misc.hh" -#include "mem/packet.hh" +#include "arch/generic/mmapped_ipr.hh" class ThreadContext; namespace MipsISA { - -inline Cycles -handleIprRead(ThreadContext *xc, Packet *pkt) -{ - panic("No implementation for handleIprRead in MIPS\n"); -} - -inline Cycles -handleIprWrite(ThreadContext *xc, Packet *pkt) -{ - panic("No implementation for handleIprWrite in MIPS\n"); -} - + using GenericISA::handleIprRead; + using GenericISA::handleIprWrite; } // namespace MipsISA #endif diff --git a/src/arch/power/mmapped_ipr.hh b/src/arch/power/mmapped_ipr.hh index 142253462..28e3b613c 100644 --- a/src/arch/power/mmapped_ipr.hh +++ b/src/arch/power/mmapped_ipr.hh @@ -41,26 +41,14 @@ * ISA-specific helper functions for memory mapped IPR accesses. */ -#include "base/misc.hh" -#include "mem/packet.hh" +#include "arch/generic/mmapped_ipr.hh" class ThreadContext; namespace PowerISA { - -inline Cycles -handleIprRead(ThreadContext *xc, Packet *pkt) -{ - panic("No implementation for handleIprRead in POWER\n"); -} - -inline Cycles -handleIprWrite(ThreadContext *xc, Packet *pkt) -{ - panic("No implementation for handleIprWrite in POWER\n"); -} - + using GenericISA::handleIprRead; + using GenericISA::handleIprWrite; } // namespace PowerISA #endif // __ARCH_POWER_MMAPPED_IPR_HH__ diff --git a/src/arch/sparc/mmapped_ipr.hh b/src/arch/sparc/mmapped_ipr.hh index 153944e9d..e7d27eed5 100644 --- a/src/arch/sparc/mmapped_ipr.hh +++ b/src/arch/sparc/mmapped_ipr.hh @@ -37,6 +37,7 @@ * ISA-specific helper functions for memory mapped IPR accesses. */ +#include "arch/generic/mmapped_ipr.hh" #include "arch/sparc/tlb.hh" #include "cpu/thread_context.hh" #include "mem/packet.hh" @@ -47,13 +48,19 @@ namespace SparcISA inline Cycles handleIprRead(ThreadContext *xc, Packet *pkt) { - return xc->getDTBPtr()->doMmuRegRead(xc, pkt); + if (GenericISA::isGenericIprAccess(pkt)) + return GenericISA::handleGenericIprRead(xc, pkt); + else + return xc->getDTBPtr()->doMmuRegRead(xc, pkt); } inline Cycles handleIprWrite(ThreadContext *xc, Packet *pkt) { - return xc->getDTBPtr()->doMmuRegWrite(xc, pkt); + if (GenericISA::isGenericIprAccess(pkt)) + return GenericISA::handleGenericIprWrite(xc, pkt); + else + return xc->getDTBPtr()->doMmuRegWrite(xc, pkt); } diff --git a/src/arch/x86/mmapped_ipr.hh b/src/arch/x86/mmapped_ipr.hh index 02c125171..bd24d33da 100644 --- a/src/arch/x86/mmapped_ipr.hh +++ b/src/arch/x86/mmapped_ipr.hh @@ -46,6 +46,7 @@ * ISA-specific helper functions for memory mapped IPR accesses. */ +#include "arch/generic/mmapped_ipr.hh" #include "arch/x86/regs/misc.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" @@ -56,27 +57,37 @@ namespace X86ISA inline Cycles handleIprRead(ThreadContext *xc, Packet *pkt) { - Addr offset = pkt->getAddr() & mask(3); - MiscRegIndex index = (MiscRegIndex)(pkt->getAddr() / sizeof(MiscReg)); - MiscReg data = htog(xc->readMiscReg(index)); - // Make sure we don't trot off the end of data. - assert(offset + pkt->getSize() <= sizeof(MiscReg)); - pkt->setData(((uint8_t *)&data) + offset); - return Cycles(1); + if (GenericISA::isGenericIprAccess(pkt)) { + return GenericISA::handleGenericIprRead(xc, pkt); + } else { + Addr offset = pkt->getAddr() & mask(3); + MiscRegIndex index = (MiscRegIndex)( + pkt->getAddr() / sizeof(MiscReg)); + MiscReg data = htog(xc->readMiscReg(index)); + // Make sure we don't trot off the end of data. + assert(offset + pkt->getSize() <= sizeof(MiscReg)); + pkt->setData(((uint8_t *)&data) + offset); + return Cycles(1); + } } inline Cycles handleIprWrite(ThreadContext *xc, Packet *pkt) { - Addr offset = pkt->getAddr() & mask(3); - MiscRegIndex index = (MiscRegIndex)(pkt->getAddr() / sizeof(MiscReg)); - MiscReg data; - data = htog(xc->readMiscRegNoEffect(index)); - // Make sure we don't trot off the end of data. - assert(offset + pkt->getSize() <= sizeof(MiscReg)); - pkt->writeData(((uint8_t *)&data) + offset); - xc->setMiscReg(index, gtoh(data)); - return Cycles(1); + if (GenericISA::isGenericIprAccess(pkt)) { + return GenericISA::handleGenericIprWrite(xc, pkt); + } else { + Addr offset = pkt->getAddr() & mask(3); + MiscRegIndex index = (MiscRegIndex)( + pkt->getAddr() / sizeof(MiscReg)); + MiscReg data; + data = htog(xc->readMiscRegNoEffect(index)); + // Make sure we don't trot off the end of data. + assert(offset + pkt->getSize() <= sizeof(MiscReg)); + pkt->writeData(((uint8_t *)&data) + offset); + xc->setMiscReg(index, gtoh(data)); + return Cycles(1); + } } }