physical.cc revision 8922:17f037ad8918
19241Sandreas.hansson@arm.com/* 29241Sandreas.hansson@arm.com * Copyright (c) 2010-2011 ARM Limited 39241Sandreas.hansson@arm.com * All rights reserved 49241Sandreas.hansson@arm.com * 59241Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 69241Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 79241Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 89241Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 99241Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 109241Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 119241Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 129241Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 139241Sandreas.hansson@arm.com * 149241Sandreas.hansson@arm.com * Copyright (c) 2001-2005 The Regents of The University of Michigan 159241Sandreas.hansson@arm.com * All rights reserved. 169241Sandreas.hansson@arm.com * 179241Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 189241Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 199241Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 209241Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 219241Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 229241Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 239241Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 249241Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 259241Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 269241Sandreas.hansson@arm.com * this software without specific prior written permission. 279241Sandreas.hansson@arm.com * 289241Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 299241Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 309241Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 319241Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 329241Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 339241Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 349241Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 359241Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 369241Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 379241Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 389241Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 399241Sandreas.hansson@arm.com * 409241Sandreas.hansson@arm.com * Authors: Ron Dreslinski 419241Sandreas.hansson@arm.com * Ali Saidi 429241Sandreas.hansson@arm.com */ 439241Sandreas.hansson@arm.com 449241Sandreas.hansson@arm.com#include <sys/mman.h> 459241Sandreas.hansson@arm.com#include <sys/types.h> 469241Sandreas.hansson@arm.com#include <sys/user.h> 479241Sandreas.hansson@arm.com#include <fcntl.h> 489402Sandreas.hansson@arm.com#include <unistd.h> 499241Sandreas.hansson@arm.com#include <zlib.h> 509241Sandreas.hansson@arm.com 519241Sandreas.hansson@arm.com#include <cerrno> 529241Sandreas.hansson@arm.com#include <cstdio> 539241Sandreas.hansson@arm.com#include <iostream> 549241Sandreas.hansson@arm.com#include <string> 559241Sandreas.hansson@arm.com 569241Sandreas.hansson@arm.com#include "arch/isa_traits.hh" 579241Sandreas.hansson@arm.com#include "arch/registers.hh" 589241Sandreas.hansson@arm.com#include "base/intmath.hh" 599241Sandreas.hansson@arm.com#include "base/misc.hh" 609241Sandreas.hansson@arm.com#include "base/random.hh" 619241Sandreas.hansson@arm.com#include "base/types.hh" 629241Sandreas.hansson@arm.com#include "config/the_isa.hh" 639241Sandreas.hansson@arm.com#include "debug/LLSC.hh" 649241Sandreas.hansson@arm.com#include "debug/MemoryAccess.hh" 659241Sandreas.hansson@arm.com#include "mem/packet_access.hh" 669241Sandreas.hansson@arm.com#include "mem/physical.hh" 679241Sandreas.hansson@arm.com#include "sim/eventq.hh" 689241Sandreas.hansson@arm.com 699241Sandreas.hansson@arm.comusing namespace std; 709241Sandreas.hansson@arm.comusing namespace TheISA; 719241Sandreas.hansson@arm.com 729241Sandreas.hansson@arm.comPhysicalMemory::PhysicalMemory(const Params *p) 739241Sandreas.hansson@arm.com : MemObject(p), pmemAddr(NULL), lat(p->latency), lat_var(p->latency_var), 749241Sandreas.hansson@arm.com _size(params()->range.size()), _start(params()->range.start) 759241Sandreas.hansson@arm.com{ 769241Sandreas.hansson@arm.com if (size() % TheISA::PageBytes != 0) 779241Sandreas.hansson@arm.com panic("Memory Size not divisible by page size\n"); 789241Sandreas.hansson@arm.com 799241Sandreas.hansson@arm.com // create the appropriate number of ports 809241Sandreas.hansson@arm.com for (int i = 0; i < p->port_port_connection_count; ++i) { 819241Sandreas.hansson@arm.com ports.push_back(new MemoryPort(csprintf("%s-port%d", name(), i), 829241Sandreas.hansson@arm.com this)); 839241Sandreas.hansson@arm.com } 849241Sandreas.hansson@arm.com 859241Sandreas.hansson@arm.com if (params()->null) 869241Sandreas.hansson@arm.com return; 879241Sandreas.hansson@arm.com 889241Sandreas.hansson@arm.com 899241Sandreas.hansson@arm.com if (params()->file == "") { 909241Sandreas.hansson@arm.com int map_flags = MAP_ANON | MAP_PRIVATE; 919241Sandreas.hansson@arm.com pmemAddr = (uint8_t *)mmap(NULL, size(), 929241Sandreas.hansson@arm.com PROT_READ | PROT_WRITE, map_flags, -1, 0); 939241Sandreas.hansson@arm.com } else { 949241Sandreas.hansson@arm.com int map_flags = MAP_PRIVATE; 959241Sandreas.hansson@arm.com int fd = open(params()->file.c_str(), O_RDONLY); 969241Sandreas.hansson@arm.com _size = lseek(fd, 0, SEEK_END); 979241Sandreas.hansson@arm.com lseek(fd, 0, SEEK_SET); 989241Sandreas.hansson@arm.com pmemAddr = (uint8_t *)mmap(NULL, roundUp(size(), sysconf(_SC_PAGESIZE)), 999241Sandreas.hansson@arm.com PROT_READ | PROT_WRITE, map_flags, fd, 0); 1009241Sandreas.hansson@arm.com } 1019241Sandreas.hansson@arm.com 1029241Sandreas.hansson@arm.com if (pmemAddr == (void *)MAP_FAILED) { 1039241Sandreas.hansson@arm.com perror("mmap"); 1049241Sandreas.hansson@arm.com if (params()->file == "") 1059241Sandreas.hansson@arm.com fatal("Could not mmap!\n"); 1069241Sandreas.hansson@arm.com else 1079241Sandreas.hansson@arm.com fatal("Could not find file: %s\n", params()->file); 1089241Sandreas.hansson@arm.com } 1099241Sandreas.hansson@arm.com 1109241Sandreas.hansson@arm.com //If requested, initialize all the memory to 0 1119241Sandreas.hansson@arm.com if (p->zero) 1129241Sandreas.hansson@arm.com memset(pmemAddr, 0, size()); 1139241Sandreas.hansson@arm.com} 1149241Sandreas.hansson@arm.com 1159241Sandreas.hansson@arm.comvoid 1169241Sandreas.hansson@arm.comPhysicalMemory::init() 1179241Sandreas.hansson@arm.com{ 1189241Sandreas.hansson@arm.com if (ports.empty()) { 1199241Sandreas.hansson@arm.com fatal("PhysicalMemory object %s is unconnected!", name()); 1209241Sandreas.hansson@arm.com } 1219241Sandreas.hansson@arm.com 1229241Sandreas.hansson@arm.com for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { 1239241Sandreas.hansson@arm.com (*pi)->sendRangeChange(); 1249241Sandreas.hansson@arm.com } 1259241Sandreas.hansson@arm.com} 1269241Sandreas.hansson@arm.com 1279241Sandreas.hansson@arm.comPhysicalMemory::~PhysicalMemory() 1289241Sandreas.hansson@arm.com{ 1299241Sandreas.hansson@arm.com if (pmemAddr) 1309241Sandreas.hansson@arm.com munmap((char*)pmemAddr, size()); 1319241Sandreas.hansson@arm.com} 1329241Sandreas.hansson@arm.com 1339241Sandreas.hansson@arm.comvoid 1349241Sandreas.hansson@arm.comPhysicalMemory::regStats() 1359241Sandreas.hansson@arm.com{ 1369241Sandreas.hansson@arm.com using namespace Stats; 1379241Sandreas.hansson@arm.com 1389241Sandreas.hansson@arm.com bytesRead 1399241Sandreas.hansson@arm.com .name(name() + ".bytes_read") 1409241Sandreas.hansson@arm.com .desc("Number of bytes read from this memory") 1419241Sandreas.hansson@arm.com ; 1429241Sandreas.hansson@arm.com bytesInstRead 1439241Sandreas.hansson@arm.com .name(name() + ".bytes_inst_read") 1449241Sandreas.hansson@arm.com .desc("Number of instructions bytes read from this memory") 1459241Sandreas.hansson@arm.com ; 1469241Sandreas.hansson@arm.com bytesWritten 1479241Sandreas.hansson@arm.com .name(name() + ".bytes_written") 1489241Sandreas.hansson@arm.com .desc("Number of bytes written to this memory") 1499241Sandreas.hansson@arm.com ; 1509241Sandreas.hansson@arm.com numReads 1519241Sandreas.hansson@arm.com .name(name() + ".num_reads") 1529241Sandreas.hansson@arm.com .desc("Number of read requests responded to by this memory") 1539241Sandreas.hansson@arm.com ; 1549241Sandreas.hansson@arm.com numWrites 1559241Sandreas.hansson@arm.com .name(name() + ".num_writes") 1569241Sandreas.hansson@arm.com .desc("Number of write requests responded to by this memory") 1579241Sandreas.hansson@arm.com ; 1589241Sandreas.hansson@arm.com numOther 1599241Sandreas.hansson@arm.com .name(name() + ".num_other") 1609241Sandreas.hansson@arm.com .desc("Number of other requests responded to by this memory") 1619241Sandreas.hansson@arm.com ; 1629241Sandreas.hansson@arm.com bwRead 1639241Sandreas.hansson@arm.com .name(name() + ".bw_read") 1649241Sandreas.hansson@arm.com .desc("Total read bandwidth from this memory (bytes/s)") 1659241Sandreas.hansson@arm.com .precision(0) 1669241Sandreas.hansson@arm.com .prereq(bytesRead) 1679241Sandreas.hansson@arm.com ; 1689241Sandreas.hansson@arm.com bwInstRead 1699241Sandreas.hansson@arm.com .name(name() + ".bw_inst_read") 1709241Sandreas.hansson@arm.com .desc("Instruction read bandwidth from this memory (bytes/s)") 1719241Sandreas.hansson@arm.com .precision(0) 1729241Sandreas.hansson@arm.com .prereq(bytesInstRead) 1739241Sandreas.hansson@arm.com ; 1749403Sandreas.hansson@arm.com bwWrite 1759403Sandreas.hansson@arm.com .name(name() + ".bw_write") 1769403Sandreas.hansson@arm.com .desc("Write bandwidth from this memory (bytes/s)") 1779403Sandreas.hansson@arm.com .precision(0) 1789403Sandreas.hansson@arm.com .prereq(bytesWritten) 1799403Sandreas.hansson@arm.com ; 1809403Sandreas.hansson@arm.com bwTotal 1819403Sandreas.hansson@arm.com .name(name() + ".bw_total") 1829403Sandreas.hansson@arm.com .desc("Total bandwidth to/from this memory (bytes/s)") 1839403Sandreas.hansson@arm.com .precision(0) 1849241Sandreas.hansson@arm.com .prereq(bwTotal) 1859241Sandreas.hansson@arm.com ; 1869241Sandreas.hansson@arm.com bwRead = bytesRead / simSeconds; 1879241Sandreas.hansson@arm.com bwInstRead = bytesInstRead / simSeconds; 1889241Sandreas.hansson@arm.com bwWrite = bytesWritten / simSeconds; 1899241Sandreas.hansson@arm.com bwTotal = (bytesRead + bytesWritten) / simSeconds; 1909241Sandreas.hansson@arm.com} 1919241Sandreas.hansson@arm.com 1929241Sandreas.hansson@arm.comunsigned 1939241Sandreas.hansson@arm.comPhysicalMemory::deviceBlockSize() const 1949241Sandreas.hansson@arm.com{ 1959241Sandreas.hansson@arm.com //Can accept anysize request 1969241Sandreas.hansson@arm.com return 0; 1979241Sandreas.hansson@arm.com} 1989241Sandreas.hansson@arm.com 1999241Sandreas.hansson@arm.comTick 2009241Sandreas.hansson@arm.comPhysicalMemory::calculateLatency(PacketPtr pkt) 2019241Sandreas.hansson@arm.com{ 2029241Sandreas.hansson@arm.com Tick latency = lat; 2039241Sandreas.hansson@arm.com if (lat_var != 0) 2049241Sandreas.hansson@arm.com latency += random_mt.random<Tick>(0, lat_var); 2059241Sandreas.hansson@arm.com return latency; 2069241Sandreas.hansson@arm.com} 2079241Sandreas.hansson@arm.com 2089241Sandreas.hansson@arm.com 2099241Sandreas.hansson@arm.com 2109241Sandreas.hansson@arm.com// Add load-locked to tracking list. Should only be called if the 2119241Sandreas.hansson@arm.com// operation is a load and the LLSC flag is set. 2129241Sandreas.hansson@arm.comvoid 2139241Sandreas.hansson@arm.comPhysicalMemory::trackLoadLocked(PacketPtr pkt) 2149241Sandreas.hansson@arm.com{ 2159241Sandreas.hansson@arm.com Request *req = pkt->req; 2169241Sandreas.hansson@arm.com Addr paddr = LockedAddr::mask(req->getPaddr()); 2179241Sandreas.hansson@arm.com 2189241Sandreas.hansson@arm.com // first we check if we already have a locked addr for this 2199241Sandreas.hansson@arm.com // xc. Since each xc only gets one, we just update the 2209241Sandreas.hansson@arm.com // existing record with the new address. 2219241Sandreas.hansson@arm.com list<LockedAddr>::iterator i; 2229241Sandreas.hansson@arm.com 2239241Sandreas.hansson@arm.com for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) { 2249241Sandreas.hansson@arm.com if (i->matchesContext(req)) { 2259241Sandreas.hansson@arm.com DPRINTF(LLSC, "Modifying lock record: context %d addr %#x\n", 2269241Sandreas.hansson@arm.com req->contextId(), paddr); 2279241Sandreas.hansson@arm.com i->addr = paddr; 2289241Sandreas.hansson@arm.com return; 2299241Sandreas.hansson@arm.com } 2309241Sandreas.hansson@arm.com } 2319241Sandreas.hansson@arm.com 2329241Sandreas.hansson@arm.com // no record for this xc: need to allocate a new one 2339241Sandreas.hansson@arm.com DPRINTF(LLSC, "Adding lock record: context %d addr %#x\n", 2349241Sandreas.hansson@arm.com req->contextId(), paddr); 2359241Sandreas.hansson@arm.com lockedAddrList.push_front(LockedAddr(req)); 2369241Sandreas.hansson@arm.com} 2379241Sandreas.hansson@arm.com 2389241Sandreas.hansson@arm.com 2399241Sandreas.hansson@arm.com// Called on *writes* only... both regular stores and 2409241Sandreas.hansson@arm.com// store-conditional operations. Check for conventional stores which 2419241Sandreas.hansson@arm.com// conflict with locked addresses, and for success/failure of store 2429241Sandreas.hansson@arm.com// conditionals. 2439241Sandreas.hansson@arm.combool 2449241Sandreas.hansson@arm.comPhysicalMemory::checkLockedAddrList(PacketPtr pkt) 2459241Sandreas.hansson@arm.com{ 2469241Sandreas.hansson@arm.com Request *req = pkt->req; 2479241Sandreas.hansson@arm.com Addr paddr = LockedAddr::mask(req->getPaddr()); 2489241Sandreas.hansson@arm.com bool isLLSC = pkt->isLLSC(); 2499241Sandreas.hansson@arm.com 2509241Sandreas.hansson@arm.com // Initialize return value. Non-conditional stores always 2519241Sandreas.hansson@arm.com // succeed. Assume conditional stores will fail until proven 2529241Sandreas.hansson@arm.com // otherwise. 2539241Sandreas.hansson@arm.com bool success = !isLLSC; 2549241Sandreas.hansson@arm.com 2559241Sandreas.hansson@arm.com // Iterate over list. Note that there could be multiple matching 2569241Sandreas.hansson@arm.com // records, as more than one context could have done a load locked 2579241Sandreas.hansson@arm.com // to this location. 2589241Sandreas.hansson@arm.com list<LockedAddr>::iterator i = lockedAddrList.begin(); 2599241Sandreas.hansson@arm.com 2609241Sandreas.hansson@arm.com while (i != lockedAddrList.end()) { 2619241Sandreas.hansson@arm.com 2629241Sandreas.hansson@arm.com if (i->addr == paddr) { 2639241Sandreas.hansson@arm.com // we have a matching address 2649241Sandreas.hansson@arm.com 2659241Sandreas.hansson@arm.com if (isLLSC && i->matchesContext(req)) { 2669241Sandreas.hansson@arm.com // it's a store conditional, and as far as the memory 2679241Sandreas.hansson@arm.com // system can tell, the requesting context's lock is 2689241Sandreas.hansson@arm.com // still valid. 2699241Sandreas.hansson@arm.com DPRINTF(LLSC, "StCond success: context %d addr %#x\n", 2709241Sandreas.hansson@arm.com req->contextId(), paddr); 2719241Sandreas.hansson@arm.com success = true; 2729241Sandreas.hansson@arm.com } 2739241Sandreas.hansson@arm.com 2749241Sandreas.hansson@arm.com // Get rid of our record of this lock and advance to next 2759241Sandreas.hansson@arm.com DPRINTF(LLSC, "Erasing lock record: context %d addr %#x\n", 2769241Sandreas.hansson@arm.com i->contextId, paddr); 2779241Sandreas.hansson@arm.com i = lockedAddrList.erase(i); 2789241Sandreas.hansson@arm.com } 2799241Sandreas.hansson@arm.com else { 2809241Sandreas.hansson@arm.com // no match: advance to next record 2819241Sandreas.hansson@arm.com ++i; 2829241Sandreas.hansson@arm.com } 2839241Sandreas.hansson@arm.com } 2849241Sandreas.hansson@arm.com 2859241Sandreas.hansson@arm.com if (isLLSC) { 2869241Sandreas.hansson@arm.com req->setExtraData(success ? 1 : 0); 2879241Sandreas.hansson@arm.com } 2889241Sandreas.hansson@arm.com 2899241Sandreas.hansson@arm.com return success; 2909241Sandreas.hansson@arm.com} 2919241Sandreas.hansson@arm.com 2929241Sandreas.hansson@arm.com 2939241Sandreas.hansson@arm.com#if TRACING_ON 2949241Sandreas.hansson@arm.com 2959241Sandreas.hansson@arm.com#define CASE(A, T) \ 2969241Sandreas.hansson@arm.com case sizeof(T): \ 2979241Sandreas.hansson@arm.com DPRINTF(MemoryAccess,"%s of size %i on address 0x%x data 0x%x\n", \ 2989241Sandreas.hansson@arm.com A, pkt->getSize(), pkt->getAddr(), pkt->get<T>()); \ 2999241Sandreas.hansson@arm.com break 3009241Sandreas.hansson@arm.com 3019241Sandreas.hansson@arm.com 3029241Sandreas.hansson@arm.com#define TRACE_PACKET(A) \ 3039241Sandreas.hansson@arm.com do { \ 3049241Sandreas.hansson@arm.com switch (pkt->getSize()) { \ 3059241Sandreas.hansson@arm.com CASE(A, uint64_t); \ 3069241Sandreas.hansson@arm.com CASE(A, uint32_t); \ 3079241Sandreas.hansson@arm.com CASE(A, uint16_t); \ 3089241Sandreas.hansson@arm.com CASE(A, uint8_t); \ 3099241Sandreas.hansson@arm.com default: \ 3109241Sandreas.hansson@arm.com DPRINTF(MemoryAccess, "%s of size %i on address 0x%x\n", \ 3119241Sandreas.hansson@arm.com A, pkt->getSize(), pkt->getAddr()); \ 3129241Sandreas.hansson@arm.com DDUMP(MemoryAccess, pkt->getPtr<uint8_t>(), pkt->getSize());\ 3139241Sandreas.hansson@arm.com } \ 3149241Sandreas.hansson@arm.com } while (0) 3159241Sandreas.hansson@arm.com 3169241Sandreas.hansson@arm.com#else 3179241Sandreas.hansson@arm.com 3189241Sandreas.hansson@arm.com#define TRACE_PACKET(A) 3199241Sandreas.hansson@arm.com 3209241Sandreas.hansson@arm.com#endif 3219241Sandreas.hansson@arm.com 3229241Sandreas.hansson@arm.comTick 3239241Sandreas.hansson@arm.comPhysicalMemory::doAtomicAccess(PacketPtr pkt) 3249241Sandreas.hansson@arm.com{ 3259241Sandreas.hansson@arm.com assert(pkt->getAddr() >= start() && 3269241Sandreas.hansson@arm.com pkt->getAddr() + pkt->getSize() <= start() + size()); 3279241Sandreas.hansson@arm.com 3289241Sandreas.hansson@arm.com if (pkt->memInhibitAsserted()) { 3299241Sandreas.hansson@arm.com DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n", 3309241Sandreas.hansson@arm.com pkt->getAddr()); 3319241Sandreas.hansson@arm.com return 0; 3329241Sandreas.hansson@arm.com } 3339241Sandreas.hansson@arm.com 3349241Sandreas.hansson@arm.com uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start(); 3359241Sandreas.hansson@arm.com 3369241Sandreas.hansson@arm.com if (pkt->cmd == MemCmd::SwapReq) { 3379241Sandreas.hansson@arm.com IntReg overwrite_val; 3389241Sandreas.hansson@arm.com bool overwrite_mem; 3399241Sandreas.hansson@arm.com uint64_t condition_val64; 3409241Sandreas.hansson@arm.com uint32_t condition_val32; 3419241Sandreas.hansson@arm.com 3429241Sandreas.hansson@arm.com if (!pmemAddr) 3439241Sandreas.hansson@arm.com panic("Swap only works if there is real memory (i.e. null=False)"); 3449241Sandreas.hansson@arm.com assert(sizeof(IntReg) >= pkt->getSize()); 3459241Sandreas.hansson@arm.com 3469241Sandreas.hansson@arm.com overwrite_mem = true; 3479241Sandreas.hansson@arm.com // keep a copy of our possible write value, and copy what is at the 3489241Sandreas.hansson@arm.com // memory address into the packet 3499241Sandreas.hansson@arm.com std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize()); 3509241Sandreas.hansson@arm.com std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 3519241Sandreas.hansson@arm.com 3529241Sandreas.hansson@arm.com if (pkt->req->isCondSwap()) { 3539241Sandreas.hansson@arm.com if (pkt->getSize() == sizeof(uint64_t)) { 3549241Sandreas.hansson@arm.com condition_val64 = pkt->req->getExtraData(); 3559241Sandreas.hansson@arm.com overwrite_mem = !std::memcmp(&condition_val64, hostAddr, 3569241Sandreas.hansson@arm.com sizeof(uint64_t)); 3579241Sandreas.hansson@arm.com } else if (pkt->getSize() == sizeof(uint32_t)) { 3589241Sandreas.hansson@arm.com condition_val32 = (uint32_t)pkt->req->getExtraData(); 3599241Sandreas.hansson@arm.com overwrite_mem = !std::memcmp(&condition_val32, hostAddr, 3609241Sandreas.hansson@arm.com sizeof(uint32_t)); 3619241Sandreas.hansson@arm.com } else 3629241Sandreas.hansson@arm.com panic("Invalid size for conditional read/write\n"); 3639241Sandreas.hansson@arm.com } 3649241Sandreas.hansson@arm.com 3659241Sandreas.hansson@arm.com if (overwrite_mem) 3669241Sandreas.hansson@arm.com std::memcpy(hostAddr, &overwrite_val, pkt->getSize()); 3679241Sandreas.hansson@arm.com 3689241Sandreas.hansson@arm.com assert(!pkt->req->isInstFetch()); 3699241Sandreas.hansson@arm.com TRACE_PACKET("Read/Write"); 3709241Sandreas.hansson@arm.com numOther++; 3719241Sandreas.hansson@arm.com } else if (pkt->isRead()) { 3729241Sandreas.hansson@arm.com assert(!pkt->isWrite()); 3739241Sandreas.hansson@arm.com if (pkt->isLLSC()) { 3749241Sandreas.hansson@arm.com trackLoadLocked(pkt); 3759241Sandreas.hansson@arm.com } 3769241Sandreas.hansson@arm.com if (pmemAddr) 3779241Sandreas.hansson@arm.com memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 3789241Sandreas.hansson@arm.com TRACE_PACKET(pkt->req->isInstFetch() ? "IFetch" : "Read"); 3799241Sandreas.hansson@arm.com numReads++; 3809241Sandreas.hansson@arm.com bytesRead += pkt->getSize(); 3819241Sandreas.hansson@arm.com if (pkt->req->isInstFetch()) 3829241Sandreas.hansson@arm.com bytesInstRead += pkt->getSize(); 3839241Sandreas.hansson@arm.com } else if (pkt->isWrite()) { 3849241Sandreas.hansson@arm.com if (writeOK(pkt)) { 3859241Sandreas.hansson@arm.com if (pmemAddr) 3869241Sandreas.hansson@arm.com memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 3879241Sandreas.hansson@arm.com assert(!pkt->req->isInstFetch()); 3889241Sandreas.hansson@arm.com TRACE_PACKET("Write"); 3899241Sandreas.hansson@arm.com numWrites++; 3909241Sandreas.hansson@arm.com bytesWritten += pkt->getSize(); 3919241Sandreas.hansson@arm.com } 3929241Sandreas.hansson@arm.com } else if (pkt->isInvalidate()) { 3939241Sandreas.hansson@arm.com //upgrade or invalidate 3949241Sandreas.hansson@arm.com if (pkt->needsResponse()) { 3959241Sandreas.hansson@arm.com pkt->makeAtomicResponse(); 3969241Sandreas.hansson@arm.com } 3979241Sandreas.hansson@arm.com } else { 3989241Sandreas.hansson@arm.com panic("unimplemented"); 3999241Sandreas.hansson@arm.com } 4009241Sandreas.hansson@arm.com 4019241Sandreas.hansson@arm.com if (pkt->needsResponse()) { 4029241Sandreas.hansson@arm.com pkt->makeAtomicResponse(); 4039241Sandreas.hansson@arm.com } 4049241Sandreas.hansson@arm.com return calculateLatency(pkt); 4059241Sandreas.hansson@arm.com} 4069241Sandreas.hansson@arm.com 4079241Sandreas.hansson@arm.com 4089241Sandreas.hansson@arm.comvoid 4099241Sandreas.hansson@arm.comPhysicalMemory::doFunctionalAccess(PacketPtr pkt) 4109241Sandreas.hansson@arm.com{ 4119241Sandreas.hansson@arm.com assert(pkt->getAddr() >= start() && 4129241Sandreas.hansson@arm.com pkt->getAddr() + pkt->getSize() <= start() + size()); 4139241Sandreas.hansson@arm.com 4149241Sandreas.hansson@arm.com 4159241Sandreas.hansson@arm.com uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start(); 4169241Sandreas.hansson@arm.com 4179241Sandreas.hansson@arm.com if (pkt->isRead()) { 4189241Sandreas.hansson@arm.com if (pmemAddr) 4199241Sandreas.hansson@arm.com memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 4209241Sandreas.hansson@arm.com TRACE_PACKET("Read"); 4219241Sandreas.hansson@arm.com pkt->makeAtomicResponse(); 4229241Sandreas.hansson@arm.com } else if (pkt->isWrite()) { 4239241Sandreas.hansson@arm.com if (pmemAddr) 4249241Sandreas.hansson@arm.com memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 4259241Sandreas.hansson@arm.com TRACE_PACKET("Write"); 4269241Sandreas.hansson@arm.com pkt->makeAtomicResponse(); 4279241Sandreas.hansson@arm.com } else if (pkt->isPrint()) { 4289241Sandreas.hansson@arm.com Packet::PrintReqState *prs = 4299241Sandreas.hansson@arm.com dynamic_cast<Packet::PrintReqState*>(pkt->senderState); 4309241Sandreas.hansson@arm.com // Need to call printLabels() explicitly since we're not going 4319241Sandreas.hansson@arm.com // through printObj(). 4329241Sandreas.hansson@arm.com prs->printLabels(); 4339241Sandreas.hansson@arm.com // Right now we just print the single byte at the specified address. 4349241Sandreas.hansson@arm.com ccprintf(prs->os, "%s%#x\n", prs->curPrefix(), *hostAddr); 4359241Sandreas.hansson@arm.com } else { 4369241Sandreas.hansson@arm.com panic("PhysicalMemory: unimplemented functional command %s", 4379241Sandreas.hansson@arm.com pkt->cmdString()); 4389241Sandreas.hansson@arm.com } 4399241Sandreas.hansson@arm.com} 4409241Sandreas.hansson@arm.com 4419241Sandreas.hansson@arm.com 4429241Sandreas.hansson@arm.comSlavePort & 4439241Sandreas.hansson@arm.comPhysicalMemory::getSlavePort(const std::string &if_name, int idx) 4449241Sandreas.hansson@arm.com{ 4459241Sandreas.hansson@arm.com if (if_name != "port") { 4469241Sandreas.hansson@arm.com return MemObject::getSlavePort(if_name, idx); 4479241Sandreas.hansson@arm.com } else { 4489241Sandreas.hansson@arm.com if (idx >= static_cast<int>(ports.size())) { 4499241Sandreas.hansson@arm.com fatal("PhysicalMemory::getSlavePort: unknown index %d\n", idx); 4509241Sandreas.hansson@arm.com } 4519400Sandreas.hansson@arm.com 4529400Sandreas.hansson@arm.com return *ports[idx]; 4539400Sandreas.hansson@arm.com } 4549400Sandreas.hansson@arm.com} 4559400Sandreas.hansson@arm.com 4569400Sandreas.hansson@arm.comPhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, 4579400Sandreas.hansson@arm.com PhysicalMemory *_memory) 4589400Sandreas.hansson@arm.com : SimpleTimingPort(_name, _memory), memory(_memory) 4599400Sandreas.hansson@arm.com{ } 4609400Sandreas.hansson@arm.com 4619402Sandreas.hansson@arm.comAddrRangeList 4629402Sandreas.hansson@arm.comPhysicalMemory::MemoryPort::getAddrRanges() 4639400Sandreas.hansson@arm.com{ 4649400Sandreas.hansson@arm.com return memory->getAddrRanges(); 4659400Sandreas.hansson@arm.com} 4669400Sandreas.hansson@arm.com 4679400Sandreas.hansson@arm.comAddrRangeList 4689400Sandreas.hansson@arm.comPhysicalMemory::getAddrRanges() 4699400Sandreas.hansson@arm.com{ 4709400Sandreas.hansson@arm.com AddrRangeList ranges; 4719400Sandreas.hansson@arm.com ranges.push_back(RangeSize(start(), size())); 4729400Sandreas.hansson@arm.com return ranges; 4739400Sandreas.hansson@arm.com} 4749400Sandreas.hansson@arm.com 4759400Sandreas.hansson@arm.comunsigned 4769400Sandreas.hansson@arm.comPhysicalMemory::MemoryPort::deviceBlockSize() const 4779400Sandreas.hansson@arm.com{ 4789400Sandreas.hansson@arm.com return memory->deviceBlockSize(); 4799400Sandreas.hansson@arm.com} 4809400Sandreas.hansson@arm.com 4819400Sandreas.hansson@arm.comTick 4829400Sandreas.hansson@arm.comPhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt) 4839400Sandreas.hansson@arm.com{ 4849400Sandreas.hansson@arm.com return memory->doAtomicAccess(pkt); 4859400Sandreas.hansson@arm.com} 4869400Sandreas.hansson@arm.com 4879400Sandreas.hansson@arm.comvoid 4889400Sandreas.hansson@arm.comPhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt) 4899400Sandreas.hansson@arm.com{ 4909241Sandreas.hansson@arm.com pkt->pushLabel(memory->name()); 4919241Sandreas.hansson@arm.com 4929241Sandreas.hansson@arm.com if (!queue.checkFunctional(pkt)) { 4939241Sandreas.hansson@arm.com // Default implementation of SimpleTimingPort::recvFunctional() 4949241Sandreas.hansson@arm.com // calls recvAtomic() and throws away the latency; we can save a 4959241Sandreas.hansson@arm.com // little here by just not calculating the latency. 4969241Sandreas.hansson@arm.com memory->doFunctionalAccess(pkt); 4979241Sandreas.hansson@arm.com } 4989241Sandreas.hansson@arm.com 4999241Sandreas.hansson@arm.com pkt->popLabel(); 5009241Sandreas.hansson@arm.com} 5019241Sandreas.hansson@arm.com 5029241Sandreas.hansson@arm.comunsigned int 5039241Sandreas.hansson@arm.comPhysicalMemory::drain(Event *de) 5049241Sandreas.hansson@arm.com{ 5059400Sandreas.hansson@arm.com int count = 0; 5069241Sandreas.hansson@arm.com for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { 5079241Sandreas.hansson@arm.com count += (*pi)->drain(de); 5089241Sandreas.hansson@arm.com } 5099241Sandreas.hansson@arm.com 5109241Sandreas.hansson@arm.com if (count) 5119241Sandreas.hansson@arm.com changeState(Draining); 5129241Sandreas.hansson@arm.com else 5139241Sandreas.hansson@arm.com changeState(Drained); 5149241Sandreas.hansson@arm.com return count; 5159241Sandreas.hansson@arm.com} 5169241Sandreas.hansson@arm.com 5179241Sandreas.hansson@arm.comvoid 5189241Sandreas.hansson@arm.comPhysicalMemory::serialize(ostream &os) 5199241Sandreas.hansson@arm.com{ 5209241Sandreas.hansson@arm.com if (!pmemAddr) 5219241Sandreas.hansson@arm.com return; 5229241Sandreas.hansson@arm.com 5239241Sandreas.hansson@arm.com gzFile compressedMem; 5249241Sandreas.hansson@arm.com string filename = name() + ".physmem"; 5259241Sandreas.hansson@arm.com 5269241Sandreas.hansson@arm.com SERIALIZE_SCALAR(filename); 5279241Sandreas.hansson@arm.com SERIALIZE_SCALAR(_size); 5289400Sandreas.hansson@arm.com 5299241Sandreas.hansson@arm.com // write memory file 5309241Sandreas.hansson@arm.com string thefile = Checkpoint::dir() + "/" + filename.c_str(); 5319241Sandreas.hansson@arm.com int fd = creat(thefile.c_str(), 0664); 5329241Sandreas.hansson@arm.com if (fd < 0) { 5339241Sandreas.hansson@arm.com perror("creat"); 5349241Sandreas.hansson@arm.com fatal("Can't open physical memory checkpoint file '%s'\n", filename); 5359241Sandreas.hansson@arm.com } 5369241Sandreas.hansson@arm.com 5379241Sandreas.hansson@arm.com compressedMem = gzdopen(fd, "wb"); 5389241Sandreas.hansson@arm.com if (compressedMem == NULL) 5399241Sandreas.hansson@arm.com fatal("Insufficient memory to allocate compression state for %s\n", 5409241Sandreas.hansson@arm.com filename); 5419241Sandreas.hansson@arm.com 5429241Sandreas.hansson@arm.com if (gzwrite(compressedMem, pmemAddr, size()) != (int)size()) { 5439241Sandreas.hansson@arm.com fatal("Write failed on physical memory checkpoint file '%s'\n", 5449241Sandreas.hansson@arm.com filename); 5459241Sandreas.hansson@arm.com } 5469241Sandreas.hansson@arm.com 5479241Sandreas.hansson@arm.com if (gzclose(compressedMem)) 5489241Sandreas.hansson@arm.com fatal("Close failed on physical memory checkpoint file '%s'\n", 5499241Sandreas.hansson@arm.com filename); 5509241Sandreas.hansson@arm.com 5519241Sandreas.hansson@arm.com list<LockedAddr>::iterator i = lockedAddrList.begin(); 5529241Sandreas.hansson@arm.com 5539241Sandreas.hansson@arm.com vector<Addr> lal_addr; 5549241Sandreas.hansson@arm.com vector<int> lal_cid; 5559241Sandreas.hansson@arm.com while (i != lockedAddrList.end()) { 5569241Sandreas.hansson@arm.com lal_addr.push_back(i->addr); 5579241Sandreas.hansson@arm.com lal_cid.push_back(i->contextId); 5589241Sandreas.hansson@arm.com i++; 5599241Sandreas.hansson@arm.com } 5609241Sandreas.hansson@arm.com arrayParamOut(os, "lal_addr", lal_addr); 5619241Sandreas.hansson@arm.com arrayParamOut(os, "lal_cid", lal_cid); 5629241Sandreas.hansson@arm.com} 5639241Sandreas.hansson@arm.com 5649241Sandreas.hansson@arm.comvoid 5659241Sandreas.hansson@arm.comPhysicalMemory::unserialize(Checkpoint *cp, const string §ion) 5669241Sandreas.hansson@arm.com{ 5679241Sandreas.hansson@arm.com if (!pmemAddr) 5689241Sandreas.hansson@arm.com return; 5699241Sandreas.hansson@arm.com 5709241Sandreas.hansson@arm.com gzFile compressedMem; 5719241Sandreas.hansson@arm.com long *tempPage; 5729241Sandreas.hansson@arm.com long *pmem_current; 5739241Sandreas.hansson@arm.com uint64_t curSize; 5749241Sandreas.hansson@arm.com uint32_t bytesRead; 5759241Sandreas.hansson@arm.com const uint32_t chunkSize = 16384; 5769241Sandreas.hansson@arm.com 5779241Sandreas.hansson@arm.com string filename; 5789241Sandreas.hansson@arm.com 5799241Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(filename); 5809241Sandreas.hansson@arm.com 5819241Sandreas.hansson@arm.com filename = cp->cptDir + "/" + filename; 5829241Sandreas.hansson@arm.com 5839241Sandreas.hansson@arm.com // mmap memoryfile 5849241Sandreas.hansson@arm.com int fd = open(filename.c_str(), O_RDONLY); 5859241Sandreas.hansson@arm.com if (fd < 0) { 5869241Sandreas.hansson@arm.com perror("open"); 5879241Sandreas.hansson@arm.com fatal("Can't open physical memory checkpoint file '%s'", filename); 5889241Sandreas.hansson@arm.com } 5899241Sandreas.hansson@arm.com 5909241Sandreas.hansson@arm.com compressedMem = gzdopen(fd, "rb"); 5919241Sandreas.hansson@arm.com if (compressedMem == NULL) 5929241Sandreas.hansson@arm.com fatal("Insufficient memory to allocate compression state for %s\n", 5939241Sandreas.hansson@arm.com filename); 5949241Sandreas.hansson@arm.com 5959241Sandreas.hansson@arm.com // unmap file that was mmapped in the constructor 5969241Sandreas.hansson@arm.com // This is done here to make sure that gzip and open don't muck with our 5979241Sandreas.hansson@arm.com // nice large space of memory before we reallocate it 5989241Sandreas.hansson@arm.com munmap((char*)pmemAddr, size()); 5999241Sandreas.hansson@arm.com 6009241Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(_size); 6019241Sandreas.hansson@arm.com if (size() > params()->range.size()) 6029241Sandreas.hansson@arm.com fatal("Memory size has changed! size %lld, param size %lld\n", 6039241Sandreas.hansson@arm.com size(), params()->range.size()); 6049241Sandreas.hansson@arm.com 6059241Sandreas.hansson@arm.com pmemAddr = (uint8_t *)mmap(NULL, size(), 6069241Sandreas.hansson@arm.com PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); 6079241Sandreas.hansson@arm.com 6089241Sandreas.hansson@arm.com if (pmemAddr == (void *)MAP_FAILED) { 6099241Sandreas.hansson@arm.com perror("mmap"); 6109241Sandreas.hansson@arm.com fatal("Could not mmap physical memory!\n"); 6119241Sandreas.hansson@arm.com } 6129241Sandreas.hansson@arm.com 6139241Sandreas.hansson@arm.com curSize = 0; 6149241Sandreas.hansson@arm.com tempPage = (long*)malloc(chunkSize); 6159241Sandreas.hansson@arm.com if (tempPage == NULL) 6169241Sandreas.hansson@arm.com fatal("Unable to malloc memory to read file %s\n", filename); 6179241Sandreas.hansson@arm.com 6189241Sandreas.hansson@arm.com /* Only copy bytes that are non-zero, so we don't give the VM system hell */ 6199241Sandreas.hansson@arm.com while (curSize < size()) { 6209241Sandreas.hansson@arm.com bytesRead = gzread(compressedMem, tempPage, chunkSize); 6219241Sandreas.hansson@arm.com if (bytesRead == 0) 6229241Sandreas.hansson@arm.com break; 6239241Sandreas.hansson@arm.com 6249294Sandreas.hansson@arm.com assert(bytesRead % sizeof(long) == 0); 6259294Sandreas.hansson@arm.com 6269241Sandreas.hansson@arm.com for (uint32_t x = 0; x < bytesRead / sizeof(long); x++) 6279241Sandreas.hansson@arm.com { 6289241Sandreas.hansson@arm.com if (*(tempPage+x) != 0) { 6299241Sandreas.hansson@arm.com pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long)); 6309241Sandreas.hansson@arm.com *pmem_current = *(tempPage+x); 6319342SAndreas.Sandberg@arm.com } 6329241Sandreas.hansson@arm.com } 6339241Sandreas.hansson@arm.com curSize += bytesRead; 6349241Sandreas.hansson@arm.com } 6359241Sandreas.hansson@arm.com 6369241Sandreas.hansson@arm.com free(tempPage); 6379241Sandreas.hansson@arm.com 6389241Sandreas.hansson@arm.com if (gzclose(compressedMem)) 6399241Sandreas.hansson@arm.com fatal("Close failed on physical memory checkpoint file '%s'\n", 640 filename); 641 642 vector<Addr> lal_addr; 643 vector<int> lal_cid; 644 arrayParamIn(cp, section, "lal_addr", lal_addr); 645 arrayParamIn(cp, section, "lal_cid", lal_cid); 646 for(int i = 0; i < lal_addr.size(); i++) 647 lockedAddrList.push_front(LockedAddr(lal_addr[i], lal_cid[i])); 648} 649 650PhysicalMemory * 651PhysicalMemoryParams::create() 652{ 653 return new PhysicalMemory(this); 654} 655