/*
- * Copyright (c) 2010-2012 ARM Limited
+ * Copyright (c) 2010-2012,2017 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* Andreas Hansson
*/
-#include "arch/registers.hh"
-#include "config/the_isa.hh"
+#include "mem/abstract_mem.hh"
+
+#include <vector>
+
+#include "arch/locked_mem.hh"
+#include "cpu/base.hh"
+#include "cpu/thread_context.hh"
#include "debug/LLSC.hh"
#include "debug/MemoryAccess.hh"
-#include "mem/abstract_mem.hh"
#include "mem/packet_access.hh"
#include "sim/system.hh"
AbstractMemory::AbstractMemory(const Params *p) :
MemObject(p), range(params()->range), pmemAddr(NULL),
+ backdoor(params()->range, nullptr,
+ (MemBackdoor::Flags)(MemBackdoor::Readable |
+ MemBackdoor::Writeable)),
confTableReported(p->conf_table_reported), inAddrMap(p->in_addr_map),
- _system(NULL)
+ kvmMap(p->kvm_map), _system(NULL)
+{
+}
+
+void
+AbstractMemory::init()
{
- if (size() % TheISA::PageBytes != 0)
+ assert(system());
+
+ if (size() % _system->getPageBytes() != 0)
panic("Memory Size not divisible by page size\n");
}
void
AbstractMemory::setBackingStore(uint8_t* pmem_addr)
{
+ // If there was an existing backdoor, let everybody know it's going away.
+ if (backdoor.ptr())
+ backdoor.invalidate();
+
+ // The back door can't handle interleaved memory.
+ backdoor.ptr(range.interleaved() ? nullptr : pmem_addr);
+
pmemAddr = pmem_addr;
}
void
AbstractMemory::regStats()
{
+ MemObject::regStats();
+
using namespace Stats;
assert(system());
void
AbstractMemory::trackLoadLocked(PacketPtr pkt)
{
- Request *req = pkt->req;
+ const RequestPtr &req = pkt->req;
Addr paddr = LockedAddr::mask(req->getPaddr());
// first we check if we already have a locked addr for this
bool
AbstractMemory::checkLockedAddrList(PacketPtr pkt)
{
- Request *req = pkt->req;
+ const RequestPtr &req = pkt->req;
Addr paddr = LockedAddr::mask(req->getPaddr());
bool isLLSC = pkt->isLLSC();
if (i->addr == paddr) {
DPRINTF(LLSC, "Erasing lock record: context %d addr %#x\n",
i->contextId, paddr);
+ ContextID owner_cid = i->contextId;
+ ContextID requester_cid = pkt->req->contextId();
+ if (owner_cid != requester_cid) {
+ ThreadContext* ctx = system()->getThreadContext(owner_cid);
+ TheISA::globalClearExclusive(ctx);
+ }
i = lockedAddrList.erase(i);
} else {
i++;
return allowStore;
}
-
#if TRACING_ON
+static inline void
+tracePacket(System *sys, const char *label, PacketPtr pkt)
+{
+ int size = pkt->getSize();
+#if THE_ISA != NULL_ISA
+ if (size == 1 || size == 2 || size == 4 || size == 8) {
+ DPRINTF(MemoryAccess,"%s from %s of size %i on address %#x data "
+ "%#x %c\n", label, sys->getMasterName(pkt->req->masterId()),
+ size, pkt->getAddr(), pkt->getUintX(TheISA::GuestByteOrder),
+ pkt->req->isUncacheable() ? 'U' : 'C');
+ return;
+ }
+#endif
+ DPRINTF(MemoryAccess, "%s from %s of size %i on address %#x %c\n",
+ label, sys->getMasterName(pkt->req->masterId()),
+ size, pkt->getAddr(), pkt->req->isUncacheable() ? 'U' : 'C');
+ DDUMP(MemoryAccess, pkt->getConstPtr<uint8_t>(), pkt->getSize());
+}
-#define CASE(A, T) \
- case sizeof(T): \
- DPRINTF(MemoryAccess,"%s of size %i on address 0x%x data 0x%x\n", \
- A, pkt->getSize(), pkt->getAddr(), pkt->get<T>()); \
- break
-
-
-#define TRACE_PACKET(A) \
- do { \
- switch (pkt->getSize()) { \
- CASE(A, uint64_t); \
- CASE(A, uint32_t); \
- CASE(A, uint16_t); \
- CASE(A, uint8_t); \
- default: \
- DPRINTF(MemoryAccess, "%s of size %i on address 0x%x\n", \
- A, pkt->getSize(), pkt->getAddr()); \
- DDUMP(MemoryAccess, pkt->getPtr<uint8_t>(), pkt->getSize());\
- } \
- } while (0)
-
+# define TRACE_PACKET(A) tracePacket(system(), A, pkt)
#else
-
-#define TRACE_PACKET(A)
-
+# define TRACE_PACKET(A)
#endif
void
AbstractMemory::access(PacketPtr pkt)
{
- assert(AddrRange(pkt->getAddr(),
- pkt->getAddr() + pkt->getSize() - 1).isSubset(range));
-
- if (pkt->memInhibitAsserted()) {
- DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n",
+ if (pkt->cacheResponding()) {
+ DPRINTF(MemoryAccess, "Cache responding to %#llx: not responding\n",
pkt->getAddr());
return;
}
+ if (pkt->cmd == MemCmd::CleanEvict || pkt->cmd == MemCmd::WritebackClean) {
+ DPRINTF(MemoryAccess, "CleanEvict on 0x%x: not responding\n",
+ pkt->getAddr());
+ return;
+ }
+
+ assert(pkt->getAddrRange().isSubset(range));
+
uint8_t *hostAddr = pmemAddr + pkt->getAddr() - range.start();
if (pkt->cmd == MemCmd::SwapReq) {
- TheISA::IntReg overwrite_val;
- bool overwrite_mem;
- uint64_t condition_val64;
- uint32_t condition_val32;
-
- if (!pmemAddr)
- panic("Swap only works if there is real memory (i.e. null=False)");
- assert(sizeof(TheISA::IntReg) >= pkt->getSize());
-
- overwrite_mem = true;
- // keep a copy of our possible write value, and copy what is at the
- // memory address into the packet
- std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize());
- std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
-
- if (pkt->req->isCondSwap()) {
- if (pkt->getSize() == sizeof(uint64_t)) {
- condition_val64 = pkt->req->getExtraData();
- overwrite_mem = !std::memcmp(&condition_val64, hostAddr,
- sizeof(uint64_t));
- } else if (pkt->getSize() == sizeof(uint32_t)) {
- condition_val32 = (uint32_t)pkt->req->getExtraData();
- overwrite_mem = !std::memcmp(&condition_val32, hostAddr,
- sizeof(uint32_t));
- } else
- panic("Invalid size for conditional read/write\n");
- }
+ if (pkt->isAtomicOp()) {
+ if (pmemAddr) {
+ pkt->setData(hostAddr);
+ (*(pkt->getAtomicOp()))(hostAddr);
+ }
+ } else {
+ std::vector<uint8_t> overwrite_val(pkt->getSize());
+ uint64_t condition_val64;
+ uint32_t condition_val32;
+
+ panic_if(!pmemAddr, "Swap only works if there is real memory " \
+ "(i.e. null=False)");
+
+ bool overwrite_mem = true;
+ // keep a copy of our possible write value, and copy what is at the
+ // memory address into the packet
+ pkt->writeData(&overwrite_val[0]);
+ pkt->setData(hostAddr);
+
+ if (pkt->req->isCondSwap()) {
+ if (pkt->getSize() == sizeof(uint64_t)) {
+ condition_val64 = pkt->req->getExtraData();
+ overwrite_mem = !std::memcmp(&condition_val64, hostAddr,
+ sizeof(uint64_t));
+ } else if (pkt->getSize() == sizeof(uint32_t)) {
+ condition_val32 = (uint32_t)pkt->req->getExtraData();
+ overwrite_mem = !std::memcmp(&condition_val32, hostAddr,
+ sizeof(uint32_t));
+ } else
+ panic("Invalid size for conditional read/write\n");
+ }
- if (overwrite_mem)
- std::memcpy(hostAddr, &overwrite_val, pkt->getSize());
+ if (overwrite_mem)
+ std::memcpy(hostAddr, &overwrite_val[0], pkt->getSize());
- assert(!pkt->req->isInstFetch());
- TRACE_PACKET("Read/Write");
- numOther[pkt->req->masterId()]++;
+ assert(!pkt->req->isInstFetch());
+ TRACE_PACKET("Read/Write");
+ numOther[pkt->req->masterId()]++;
+ }
} else if (pkt->isRead()) {
assert(!pkt->isWrite());
if (pkt->isLLSC()) {
+ assert(!pkt->fromCache());
+ // if the packet is not coming from a cache then we have
+ // to do the LL/SC tracking here
trackLoadLocked(pkt);
}
- if (pmemAddr)
- memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
+ if (pmemAddr) {
+ pkt->setData(hostAddr);
+ }
TRACE_PACKET(pkt->req->isInstFetch() ? "IFetch" : "Read");
numReads[pkt->req->masterId()]++;
bytesRead[pkt->req->masterId()] += pkt->getSize();
if (pkt->req->isInstFetch())
bytesInstRead[pkt->req->masterId()] += pkt->getSize();
+ } else if (pkt->isInvalidate() || pkt->isClean()) {
+ assert(!pkt->isWrite());
+ // in a fastmem system invalidating and/or cleaning packets
+ // can be seen due to cache maintenance requests
+
+ // no need to do anything
} else if (pkt->isWrite()) {
if (writeOK(pkt)) {
if (pmemAddr) {
- memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
- DPRINTF(MemoryAccess, "%s wrote %x bytes to address %x\n",
+ pkt->writeData(hostAddr);
+ DPRINTF(MemoryAccess, "%s wrote %i bytes to address %x\n",
__func__, pkt->getSize(), pkt->getAddr());
}
assert(!pkt->req->isInstFetch());
numWrites[pkt->req->masterId()]++;
bytesWritten[pkt->req->masterId()] += pkt->getSize();
}
- } else if (pkt->isInvalidate()) {
- // no need to do anything
} else {
- panic("unimplemented");
+ panic("Unexpected packet %s", pkt->print());
}
if (pkt->needsResponse()) {
void
AbstractMemory::functionalAccess(PacketPtr pkt)
{
- assert(AddrRange(pkt->getAddr(),
- pkt->getAddr() + pkt->getSize() - 1).isSubset(range));
+ assert(pkt->getAddrRange().isSubset(range));
uint8_t *hostAddr = pmemAddr + pkt->getAddr() - range.start();
if (pkt->isRead()) {
- if (pmemAddr)
- memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
+ if (pmemAddr) {
+ pkt->setData(hostAddr);
+ }
TRACE_PACKET("Read");
pkt->makeResponse();
} else if (pkt->isWrite()) {
- if (pmemAddr)
- memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
+ if (pmemAddr) {
+ pkt->writeData(hostAddr);
+ }
TRACE_PACKET("Write");
pkt->makeResponse();
} else if (pkt->isPrint()) {