physical.cc revision 8799:dac1e33e07b0
110259SAndrew.Bardsley@arm.com/* 210259SAndrew.Bardsley@arm.com * Copyright (c) 2010-2011 ARM Limited 310259SAndrew.Bardsley@arm.com * All rights reserved 410259SAndrew.Bardsley@arm.com * 510259SAndrew.Bardsley@arm.com * The license below extends only to copyright in the software and shall 610259SAndrew.Bardsley@arm.com * not be construed as granting a license to any other intellectual 710259SAndrew.Bardsley@arm.com * property including but not limited to intellectual property relating 810259SAndrew.Bardsley@arm.com * to a hardware implementation of the functionality of the software 910259SAndrew.Bardsley@arm.com * licensed hereunder. You may use the software subject to the license 1010259SAndrew.Bardsley@arm.com * terms below provided that you ensure that this notice is replicated 1110259SAndrew.Bardsley@arm.com * unmodified and in its entirety in all distributions of the software, 1210259SAndrew.Bardsley@arm.com * modified or unmodified, in source code or in binary form. 1310259SAndrew.Bardsley@arm.com * 1410259SAndrew.Bardsley@arm.com * Copyright (c) 2001-2005 The Regents of The University of Michigan 1510259SAndrew.Bardsley@arm.com * All rights reserved. 1610259SAndrew.Bardsley@arm.com * 1710259SAndrew.Bardsley@arm.com * Redistribution and use in source and binary forms, with or without 1810259SAndrew.Bardsley@arm.com * modification, are permitted provided that the following conditions are 1910259SAndrew.Bardsley@arm.com * met: redistributions of source code must retain the above copyright 2010259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer; 2110259SAndrew.Bardsley@arm.com * redistributions in binary form must reproduce the above copyright 2210259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer in the 2310259SAndrew.Bardsley@arm.com * documentation and/or other materials provided with the distribution; 2410259SAndrew.Bardsley@arm.com * neither the name of the copyright holders nor the names of its 2510259SAndrew.Bardsley@arm.com * contributors may be used to endorse or promote products derived from 2610259SAndrew.Bardsley@arm.com * this software without specific prior written permission. 2710259SAndrew.Bardsley@arm.com * 2810259SAndrew.Bardsley@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2910259SAndrew.Bardsley@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3010259SAndrew.Bardsley@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3110259SAndrew.Bardsley@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3210259SAndrew.Bardsley@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3310259SAndrew.Bardsley@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3410259SAndrew.Bardsley@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3510259SAndrew.Bardsley@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3610259SAndrew.Bardsley@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3710259SAndrew.Bardsley@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3810259SAndrew.Bardsley@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3910259SAndrew.Bardsley@arm.com * 4010259SAndrew.Bardsley@arm.com * Authors: Ron Dreslinski 4110259SAndrew.Bardsley@arm.com * Ali Saidi 4210259SAndrew.Bardsley@arm.com */ 4310259SAndrew.Bardsley@arm.com 4410259SAndrew.Bardsley@arm.com#include <sys/mman.h> 4510259SAndrew.Bardsley@arm.com#include <sys/types.h> 4610259SAndrew.Bardsley@arm.com#include <sys/user.h> 4710259SAndrew.Bardsley@arm.com#include <fcntl.h> 4810259SAndrew.Bardsley@arm.com#include <unistd.h> 4910259SAndrew.Bardsley@arm.com#include <zlib.h> 5010259SAndrew.Bardsley@arm.com 5110259SAndrew.Bardsley@arm.com#include <cerrno> 5210259SAndrew.Bardsley@arm.com#include <cstdio> 5310259SAndrew.Bardsley@arm.com#include <iostream> 5410259SAndrew.Bardsley@arm.com#include <string> 5510259SAndrew.Bardsley@arm.com 5610259SAndrew.Bardsley@arm.com#include "arch/isa_traits.hh" 5710259SAndrew.Bardsley@arm.com#include "arch/registers.hh" 5810259SAndrew.Bardsley@arm.com#include "base/intmath.hh" 5910259SAndrew.Bardsley@arm.com#include "base/misc.hh" 6010259SAndrew.Bardsley@arm.com#include "base/random.hh" 6110259SAndrew.Bardsley@arm.com#include "base/types.hh" 6210259SAndrew.Bardsley@arm.com#include "config/the_isa.hh" 6310259SAndrew.Bardsley@arm.com#include "debug/LLSC.hh" 6410259SAndrew.Bardsley@arm.com#include "debug/MemoryAccess.hh" 6510259SAndrew.Bardsley@arm.com#include "mem/packet_access.hh" 6610259SAndrew.Bardsley@arm.com#include "mem/physical.hh" 6710259SAndrew.Bardsley@arm.com#include "sim/eventq.hh" 6810259SAndrew.Bardsley@arm.com 6910259SAndrew.Bardsley@arm.comusing namespace std; 7010259SAndrew.Bardsley@arm.comusing namespace TheISA; 7110259SAndrew.Bardsley@arm.com 7210259SAndrew.Bardsley@arm.comPhysicalMemory::PhysicalMemory(const Params *p) 7310259SAndrew.Bardsley@arm.com : MemObject(p), pmemAddr(NULL), lat(p->latency), lat_var(p->latency_var), 7410259SAndrew.Bardsley@arm.com _size(params()->range.size()), _start(params()->range.start) 7510259SAndrew.Bardsley@arm.com{ 7610259SAndrew.Bardsley@arm.com if (size() % TheISA::PageBytes != 0) 7710259SAndrew.Bardsley@arm.com panic("Memory Size not divisible by page size\n"); 7810259SAndrew.Bardsley@arm.com 7910259SAndrew.Bardsley@arm.com if (params()->null) 8010259SAndrew.Bardsley@arm.com return; 8110259SAndrew.Bardsley@arm.com 8210259SAndrew.Bardsley@arm.com 8310259SAndrew.Bardsley@arm.com if (params()->file == "") { 8410259SAndrew.Bardsley@arm.com int map_flags = MAP_ANON | MAP_PRIVATE; 8510259SAndrew.Bardsley@arm.com pmemAddr = (uint8_t *)mmap(NULL, size(), 8610259SAndrew.Bardsley@arm.com PROT_READ | PROT_WRITE, map_flags, -1, 0); 8710259SAndrew.Bardsley@arm.com } else { 8810259SAndrew.Bardsley@arm.com int map_flags = MAP_PRIVATE; 8910259SAndrew.Bardsley@arm.com int fd = open(params()->file.c_str(), O_RDONLY); 9010259SAndrew.Bardsley@arm.com _size = lseek(fd, 0, SEEK_END); 9110259SAndrew.Bardsley@arm.com lseek(fd, 0, SEEK_SET); 9210259SAndrew.Bardsley@arm.com pmemAddr = (uint8_t *)mmap(NULL, roundUp(size(), sysconf(_SC_PAGESIZE)), 9310259SAndrew.Bardsley@arm.com PROT_READ | PROT_WRITE, map_flags, fd, 0); 9410259SAndrew.Bardsley@arm.com } 9510259SAndrew.Bardsley@arm.com 9610259SAndrew.Bardsley@arm.com if (pmemAddr == (void *)MAP_FAILED) { 9710259SAndrew.Bardsley@arm.com perror("mmap"); 9810259SAndrew.Bardsley@arm.com if (params()->file == "") 9910259SAndrew.Bardsley@arm.com fatal("Could not mmap!\n"); 10010259SAndrew.Bardsley@arm.com else 10110259SAndrew.Bardsley@arm.com fatal("Could not find file: %s\n", params()->file); 10210259SAndrew.Bardsley@arm.com } 10310259SAndrew.Bardsley@arm.com 10410259SAndrew.Bardsley@arm.com //If requested, initialize all the memory to 0 10510259SAndrew.Bardsley@arm.com if (p->zero) 10610259SAndrew.Bardsley@arm.com memset(pmemAddr, 0, size()); 10710259SAndrew.Bardsley@arm.com} 10810259SAndrew.Bardsley@arm.com 10910259SAndrew.Bardsley@arm.comvoid 11010259SAndrew.Bardsley@arm.comPhysicalMemory::init() 11110259SAndrew.Bardsley@arm.com{ 11210259SAndrew.Bardsley@arm.com if (ports.size() == 0) { 11310259SAndrew.Bardsley@arm.com fatal("PhysicalMemory object %s is unconnected!", name()); 11410259SAndrew.Bardsley@arm.com } 11510259SAndrew.Bardsley@arm.com 11610259SAndrew.Bardsley@arm.com for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { 11710259SAndrew.Bardsley@arm.com if (*pi) 11810259SAndrew.Bardsley@arm.com (*pi)->sendRangeChange(); 11910259SAndrew.Bardsley@arm.com } 12010259SAndrew.Bardsley@arm.com} 12110259SAndrew.Bardsley@arm.com 12210259SAndrew.Bardsley@arm.comPhysicalMemory::~PhysicalMemory() 12310259SAndrew.Bardsley@arm.com{ 12410259SAndrew.Bardsley@arm.com if (pmemAddr) 12510259SAndrew.Bardsley@arm.com munmap((char*)pmemAddr, size()); 12610259SAndrew.Bardsley@arm.com} 12710259SAndrew.Bardsley@arm.com 12810259SAndrew.Bardsley@arm.comvoid 12910259SAndrew.Bardsley@arm.comPhysicalMemory::regStats() 13010259SAndrew.Bardsley@arm.com{ 13110259SAndrew.Bardsley@arm.com using namespace Stats; 13210259SAndrew.Bardsley@arm.com 13310259SAndrew.Bardsley@arm.com bytesRead 13410259SAndrew.Bardsley@arm.com .name(name() + ".bytes_read") 13510259SAndrew.Bardsley@arm.com .desc("Number of bytes read from this memory") 13610259SAndrew.Bardsley@arm.com ; 13710259SAndrew.Bardsley@arm.com bytesInstRead 13810259SAndrew.Bardsley@arm.com .name(name() + ".bytes_inst_read") 13910259SAndrew.Bardsley@arm.com .desc("Number of instructions bytes read from this memory") 14010259SAndrew.Bardsley@arm.com ; 14110259SAndrew.Bardsley@arm.com bytesWritten 14210259SAndrew.Bardsley@arm.com .name(name() + ".bytes_written") 14310259SAndrew.Bardsley@arm.com .desc("Number of bytes written to this memory") 14410259SAndrew.Bardsley@arm.com ; 14510259SAndrew.Bardsley@arm.com numReads 14610259SAndrew.Bardsley@arm.com .name(name() + ".num_reads") 14710259SAndrew.Bardsley@arm.com .desc("Number of read requests responded to by this memory") 14810259SAndrew.Bardsley@arm.com ; 14910259SAndrew.Bardsley@arm.com numWrites 15010259SAndrew.Bardsley@arm.com .name(name() + ".num_writes") 15110259SAndrew.Bardsley@arm.com .desc("Number of write requests responded to by this memory") 15210259SAndrew.Bardsley@arm.com ; 15310814Sandreas.hansson@arm.com numOther 15410259SAndrew.Bardsley@arm.com .name(name() + ".num_other") 15510259SAndrew.Bardsley@arm.com .desc("Number of other requests responded to by this memory") 15610259SAndrew.Bardsley@arm.com ; 15710259SAndrew.Bardsley@arm.com bwRead 15810259SAndrew.Bardsley@arm.com .name(name() + ".bw_read") 15910259SAndrew.Bardsley@arm.com .desc("Total read bandwidth from this memory (bytes/s)") 16010259SAndrew.Bardsley@arm.com .precision(0) 16110259SAndrew.Bardsley@arm.com .prereq(bytesRead) 16210259SAndrew.Bardsley@arm.com ; 16310259SAndrew.Bardsley@arm.com bwInstRead 16410259SAndrew.Bardsley@arm.com .name(name() + ".bw_inst_read") 16510259SAndrew.Bardsley@arm.com .desc("Instruction read bandwidth from this memory (bytes/s)") 16610259SAndrew.Bardsley@arm.com .precision(0) 16710259SAndrew.Bardsley@arm.com .prereq(bytesInstRead) 16810259SAndrew.Bardsley@arm.com ; 16910259SAndrew.Bardsley@arm.com bwWrite 17010259SAndrew.Bardsley@arm.com .name(name() + ".bw_write") 17110259SAndrew.Bardsley@arm.com .desc("Write bandwidth from this memory (bytes/s)") 17210259SAndrew.Bardsley@arm.com .precision(0) 17310259SAndrew.Bardsley@arm.com .prereq(bytesWritten) 17410259SAndrew.Bardsley@arm.com ; 17510259SAndrew.Bardsley@arm.com bwTotal 17610259SAndrew.Bardsley@arm.com .name(name() + ".bw_total") 17710259SAndrew.Bardsley@arm.com .desc("Total bandwidth to/from this memory (bytes/s)") 17810259SAndrew.Bardsley@arm.com .precision(0) 17910259SAndrew.Bardsley@arm.com .prereq(bwTotal) 18010259SAndrew.Bardsley@arm.com ; 18110259SAndrew.Bardsley@arm.com bwRead = bytesRead / simSeconds; 18210259SAndrew.Bardsley@arm.com bwInstRead = bytesInstRead / simSeconds; 18310259SAndrew.Bardsley@arm.com bwWrite = bytesWritten / simSeconds; 18410259SAndrew.Bardsley@arm.com bwTotal = (bytesRead + bytesWritten) / simSeconds; 18510259SAndrew.Bardsley@arm.com} 18610259SAndrew.Bardsley@arm.com 18710259SAndrew.Bardsley@arm.comunsigned 18810259SAndrew.Bardsley@arm.comPhysicalMemory::deviceBlockSize() const 18910259SAndrew.Bardsley@arm.com{ 19010259SAndrew.Bardsley@arm.com //Can accept anysize request 19110259SAndrew.Bardsley@arm.com return 0; 19210259SAndrew.Bardsley@arm.com} 19310259SAndrew.Bardsley@arm.com 19410259SAndrew.Bardsley@arm.comTick 19510259SAndrew.Bardsley@arm.comPhysicalMemory::calculateLatency(PacketPtr pkt) 19610259SAndrew.Bardsley@arm.com{ 19710259SAndrew.Bardsley@arm.com Tick latency = lat; 19810259SAndrew.Bardsley@arm.com if (lat_var != 0) 19910259SAndrew.Bardsley@arm.com latency += random_mt.random<Tick>(0, lat_var); 20010259SAndrew.Bardsley@arm.com return latency; 20110259SAndrew.Bardsley@arm.com} 20210259SAndrew.Bardsley@arm.com 20310259SAndrew.Bardsley@arm.com 20410259SAndrew.Bardsley@arm.com 20510259SAndrew.Bardsley@arm.com// Add load-locked to tracking list. Should only be called if the 20610259SAndrew.Bardsley@arm.com// operation is a load and the LLSC flag is set. 20710259SAndrew.Bardsley@arm.comvoid 20810259SAndrew.Bardsley@arm.comPhysicalMemory::trackLoadLocked(PacketPtr pkt) 20910259SAndrew.Bardsley@arm.com{ 21010259SAndrew.Bardsley@arm.com Request *req = pkt->req; 21110259SAndrew.Bardsley@arm.com Addr paddr = LockedAddr::mask(req->getPaddr()); 21210259SAndrew.Bardsley@arm.com 21310259SAndrew.Bardsley@arm.com // first we check if we already have a locked addr for this 21410259SAndrew.Bardsley@arm.com // xc. Since each xc only gets one, we just update the 21510259SAndrew.Bardsley@arm.com // existing record with the new address. 21610259SAndrew.Bardsley@arm.com list<LockedAddr>::iterator i; 21710259SAndrew.Bardsley@arm.com 21810259SAndrew.Bardsley@arm.com for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) { 21910259SAndrew.Bardsley@arm.com if (i->matchesContext(req)) { 22010259SAndrew.Bardsley@arm.com DPRINTF(LLSC, "Modifying lock record: context %d addr %#x\n", 22110259SAndrew.Bardsley@arm.com req->contextId(), paddr); 22210259SAndrew.Bardsley@arm.com i->addr = paddr; 22310259SAndrew.Bardsley@arm.com return; 22410259SAndrew.Bardsley@arm.com } 22510259SAndrew.Bardsley@arm.com } 22610259SAndrew.Bardsley@arm.com 22710259SAndrew.Bardsley@arm.com // no record for this xc: need to allocate a new one 22810259SAndrew.Bardsley@arm.com DPRINTF(LLSC, "Adding lock record: context %d addr %#x\n", 22910259SAndrew.Bardsley@arm.com req->contextId(), paddr); 23010259SAndrew.Bardsley@arm.com lockedAddrList.push_front(LockedAddr(req)); 23110259SAndrew.Bardsley@arm.com} 23210259SAndrew.Bardsley@arm.com 23310259SAndrew.Bardsley@arm.com 23410259SAndrew.Bardsley@arm.com// Called on *writes* only... both regular stores and 23510259SAndrew.Bardsley@arm.com// store-conditional operations. Check for conventional stores which 23610259SAndrew.Bardsley@arm.com// conflict with locked addresses, and for success/failure of store 23710259SAndrew.Bardsley@arm.com// conditionals. 23810259SAndrew.Bardsley@arm.combool 23910259SAndrew.Bardsley@arm.comPhysicalMemory::checkLockedAddrList(PacketPtr pkt) 24010259SAndrew.Bardsley@arm.com{ 24110259SAndrew.Bardsley@arm.com Request *req = pkt->req; 24210259SAndrew.Bardsley@arm.com Addr paddr = LockedAddr::mask(req->getPaddr()); 24310259SAndrew.Bardsley@arm.com bool isLLSC = pkt->isLLSC(); 24410259SAndrew.Bardsley@arm.com 24510259SAndrew.Bardsley@arm.com // Initialize return value. Non-conditional stores always 24610259SAndrew.Bardsley@arm.com // succeed. Assume conditional stores will fail until proven 24710259SAndrew.Bardsley@arm.com // otherwise. 24810259SAndrew.Bardsley@arm.com bool success = !isLLSC; 24910259SAndrew.Bardsley@arm.com 25010259SAndrew.Bardsley@arm.com // Iterate over list. Note that there could be multiple matching 25110259SAndrew.Bardsley@arm.com // records, as more than one context could have done a load locked 25210259SAndrew.Bardsley@arm.com // to this location. 25310259SAndrew.Bardsley@arm.com list<LockedAddr>::iterator i = lockedAddrList.begin(); 25410259SAndrew.Bardsley@arm.com 25510259SAndrew.Bardsley@arm.com while (i != lockedAddrList.end()) { 25610259SAndrew.Bardsley@arm.com 25710259SAndrew.Bardsley@arm.com if (i->addr == paddr) { 25810259SAndrew.Bardsley@arm.com // we have a matching address 25910259SAndrew.Bardsley@arm.com 26010259SAndrew.Bardsley@arm.com if (isLLSC && i->matchesContext(req)) { 26110259SAndrew.Bardsley@arm.com // it's a store conditional, and as far as the memory 26210366Sandreas.hansson@arm.com // system can tell, the requesting context's lock is 26310366Sandreas.hansson@arm.com // still valid. 26410366Sandreas.hansson@arm.com DPRINTF(LLSC, "StCond success: context %d addr %#x\n", 26510259SAndrew.Bardsley@arm.com req->contextId(), paddr); 26610259SAndrew.Bardsley@arm.com success = true; 26710259SAndrew.Bardsley@arm.com } 26810259SAndrew.Bardsley@arm.com 26910259SAndrew.Bardsley@arm.com // Get rid of our record of this lock and advance to next 27010259SAndrew.Bardsley@arm.com DPRINTF(LLSC, "Erasing lock record: context %d addr %#x\n", 27110259SAndrew.Bardsley@arm.com i->contextId, paddr); 27210259SAndrew.Bardsley@arm.com i = lockedAddrList.erase(i); 27310259SAndrew.Bardsley@arm.com } 27410259SAndrew.Bardsley@arm.com else { 27510259SAndrew.Bardsley@arm.com // no match: advance to next record 27610259SAndrew.Bardsley@arm.com ++i; 27710259SAndrew.Bardsley@arm.com } 27810259SAndrew.Bardsley@arm.com } 27910259SAndrew.Bardsley@arm.com 28010259SAndrew.Bardsley@arm.com if (isLLSC) { 28110259SAndrew.Bardsley@arm.com req->setExtraData(success ? 1 : 0); 28210259SAndrew.Bardsley@arm.com } 28310259SAndrew.Bardsley@arm.com 28410259SAndrew.Bardsley@arm.com return success; 28510259SAndrew.Bardsley@arm.com} 28610259SAndrew.Bardsley@arm.com 28710259SAndrew.Bardsley@arm.com 28810259SAndrew.Bardsley@arm.com#if TRACING_ON 28910259SAndrew.Bardsley@arm.com 29010259SAndrew.Bardsley@arm.com#define CASE(A, T) \ 29110259SAndrew.Bardsley@arm.com case sizeof(T): \ 29210259SAndrew.Bardsley@arm.com DPRINTF(MemoryAccess,"%s of size %i on address 0x%x data 0x%x\n", \ 29310259SAndrew.Bardsley@arm.com A, pkt->getSize(), pkt->getAddr(), pkt->get<T>()); \ 29410259SAndrew.Bardsley@arm.com break 29510259SAndrew.Bardsley@arm.com 29610259SAndrew.Bardsley@arm.com 29710259SAndrew.Bardsley@arm.com#define TRACE_PACKET(A) \ 29810259SAndrew.Bardsley@arm.com do { \ 29910259SAndrew.Bardsley@arm.com switch (pkt->getSize()) { \ 30010259SAndrew.Bardsley@arm.com CASE(A, uint64_t); \ 30110259SAndrew.Bardsley@arm.com CASE(A, uint32_t); \ 30210259SAndrew.Bardsley@arm.com CASE(A, uint16_t); \ 30310259SAndrew.Bardsley@arm.com CASE(A, uint8_t); \ 30410259SAndrew.Bardsley@arm.com default: \ 30510259SAndrew.Bardsley@arm.com DPRINTF(MemoryAccess, "%s of size %i on address 0x%x\n", \ 30610259SAndrew.Bardsley@arm.com A, pkt->getSize(), pkt->getAddr()); \ 30710259SAndrew.Bardsley@arm.com DDUMP(MemoryAccess, pkt->getPtr<uint8_t>(), pkt->getSize());\ 30810259SAndrew.Bardsley@arm.com } \ 30910259SAndrew.Bardsley@arm.com } while (0) 31010259SAndrew.Bardsley@arm.com 31110259SAndrew.Bardsley@arm.com#else 31210259SAndrew.Bardsley@arm.com 31310259SAndrew.Bardsley@arm.com#define TRACE_PACKET(A) 31410259SAndrew.Bardsley@arm.com 31510259SAndrew.Bardsley@arm.com#endif 31610259SAndrew.Bardsley@arm.com 31710259SAndrew.Bardsley@arm.comTick 31810259SAndrew.Bardsley@arm.comPhysicalMemory::doAtomicAccess(PacketPtr pkt) 31910259SAndrew.Bardsley@arm.com{ 32010259SAndrew.Bardsley@arm.com assert(pkt->getAddr() >= start() && 32110259SAndrew.Bardsley@arm.com pkt->getAddr() + pkt->getSize() <= start() + size()); 32210259SAndrew.Bardsley@arm.com 32310259SAndrew.Bardsley@arm.com if (pkt->memInhibitAsserted()) { 32410259SAndrew.Bardsley@arm.com DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n", 32510259SAndrew.Bardsley@arm.com pkt->getAddr()); 32610259SAndrew.Bardsley@arm.com return 0; 32710259SAndrew.Bardsley@arm.com } 32810259SAndrew.Bardsley@arm.com 32910259SAndrew.Bardsley@arm.com uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start(); 33010259SAndrew.Bardsley@arm.com 33110259SAndrew.Bardsley@arm.com if (pkt->cmd == MemCmd::SwapReq) { 33210259SAndrew.Bardsley@arm.com IntReg overwrite_val; 33310259SAndrew.Bardsley@arm.com bool overwrite_mem; 33410259SAndrew.Bardsley@arm.com uint64_t condition_val64; 33510259SAndrew.Bardsley@arm.com uint32_t condition_val32; 33610259SAndrew.Bardsley@arm.com 33710259SAndrew.Bardsley@arm.com if (!pmemAddr) 33810259SAndrew.Bardsley@arm.com panic("Swap only works if there is real memory (i.e. null=False)"); 33910259SAndrew.Bardsley@arm.com assert(sizeof(IntReg) >= pkt->getSize()); 34010259SAndrew.Bardsley@arm.com 34110259SAndrew.Bardsley@arm.com overwrite_mem = true; 34210259SAndrew.Bardsley@arm.com // keep a copy of our possible write value, and copy what is at the 34310259SAndrew.Bardsley@arm.com // memory address into the packet 34410259SAndrew.Bardsley@arm.com std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize()); 34510259SAndrew.Bardsley@arm.com std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 34610259SAndrew.Bardsley@arm.com 34710259SAndrew.Bardsley@arm.com if (pkt->req->isCondSwap()) { 34810259SAndrew.Bardsley@arm.com if (pkt->getSize() == sizeof(uint64_t)) { 34910259SAndrew.Bardsley@arm.com condition_val64 = pkt->req->getExtraData(); 35010259SAndrew.Bardsley@arm.com overwrite_mem = !std::memcmp(&condition_val64, hostAddr, 35110259SAndrew.Bardsley@arm.com sizeof(uint64_t)); 35210259SAndrew.Bardsley@arm.com } else if (pkt->getSize() == sizeof(uint32_t)) { 35310259SAndrew.Bardsley@arm.com condition_val32 = (uint32_t)pkt->req->getExtraData(); 35410259SAndrew.Bardsley@arm.com overwrite_mem = !std::memcmp(&condition_val32, hostAddr, 35510259SAndrew.Bardsley@arm.com sizeof(uint32_t)); 35610259SAndrew.Bardsley@arm.com } else 35710259SAndrew.Bardsley@arm.com panic("Invalid size for conditional read/write\n"); 35810563Sandreas.hansson@arm.com } 35910259SAndrew.Bardsley@arm.com 36010259SAndrew.Bardsley@arm.com if (overwrite_mem) 36110259SAndrew.Bardsley@arm.com std::memcpy(hostAddr, &overwrite_val, pkt->getSize()); 36210259SAndrew.Bardsley@arm.com 36310259SAndrew.Bardsley@arm.com assert(!pkt->req->isInstFetch()); 36410259SAndrew.Bardsley@arm.com TRACE_PACKET("Read/Write"); 36510259SAndrew.Bardsley@arm.com numOther++; 36610259SAndrew.Bardsley@arm.com } else if (pkt->isRead()) { 36710259SAndrew.Bardsley@arm.com assert(!pkt->isWrite()); 36810259SAndrew.Bardsley@arm.com if (pkt->isLLSC()) { 36910259SAndrew.Bardsley@arm.com trackLoadLocked(pkt); 37010259SAndrew.Bardsley@arm.com } 37110259SAndrew.Bardsley@arm.com if (pmemAddr) 37210259SAndrew.Bardsley@arm.com memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 37310259SAndrew.Bardsley@arm.com TRACE_PACKET(pkt->req->isInstFetch() ? "IFetch" : "Read"); 37410259SAndrew.Bardsley@arm.com numReads++; 37510259SAndrew.Bardsley@arm.com bytesRead += pkt->getSize(); 37610259SAndrew.Bardsley@arm.com if (pkt->req->isInstFetch()) 37710259SAndrew.Bardsley@arm.com bytesInstRead += pkt->getSize(); 37810259SAndrew.Bardsley@arm.com } else if (pkt->isWrite()) { 37910259SAndrew.Bardsley@arm.com if (writeOK(pkt)) { 38010259SAndrew.Bardsley@arm.com if (pmemAddr) 38110259SAndrew.Bardsley@arm.com memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 38210259SAndrew.Bardsley@arm.com assert(!pkt->req->isInstFetch()); 38310259SAndrew.Bardsley@arm.com TRACE_PACKET("Write"); 38410259SAndrew.Bardsley@arm.com numWrites++; 38510259SAndrew.Bardsley@arm.com bytesWritten += pkt->getSize(); 38610259SAndrew.Bardsley@arm.com } 38710259SAndrew.Bardsley@arm.com } else if (pkt->isInvalidate()) { 38810259SAndrew.Bardsley@arm.com //upgrade or invalidate 38910259SAndrew.Bardsley@arm.com if (pkt->needsResponse()) { 39010259SAndrew.Bardsley@arm.com pkt->makeAtomicResponse(); 39110259SAndrew.Bardsley@arm.com } 39210259SAndrew.Bardsley@arm.com } else { 39310259SAndrew.Bardsley@arm.com panic("unimplemented"); 39410259SAndrew.Bardsley@arm.com } 39510259SAndrew.Bardsley@arm.com 39610259SAndrew.Bardsley@arm.com if (pkt->needsResponse()) { 39710259SAndrew.Bardsley@arm.com pkt->makeAtomicResponse(); 39810259SAndrew.Bardsley@arm.com } 39910259SAndrew.Bardsley@arm.com return calculateLatency(pkt); 40010259SAndrew.Bardsley@arm.com} 40110259SAndrew.Bardsley@arm.com 40210259SAndrew.Bardsley@arm.com 40310259SAndrew.Bardsley@arm.comvoid 40410259SAndrew.Bardsley@arm.comPhysicalMemory::doFunctionalAccess(PacketPtr pkt) 40510259SAndrew.Bardsley@arm.com{ 40610259SAndrew.Bardsley@arm.com assert(pkt->getAddr() >= start() && 40710259SAndrew.Bardsley@arm.com pkt->getAddr() + pkt->getSize() <= start() + size()); 40810259SAndrew.Bardsley@arm.com 40910259SAndrew.Bardsley@arm.com 41010259SAndrew.Bardsley@arm.com uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start(); 41110259SAndrew.Bardsley@arm.com 41210259SAndrew.Bardsley@arm.com if (pkt->isRead()) { 41310259SAndrew.Bardsley@arm.com if (pmemAddr) 41410259SAndrew.Bardsley@arm.com memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 41510259SAndrew.Bardsley@arm.com TRACE_PACKET("Read"); 41610259SAndrew.Bardsley@arm.com pkt->makeAtomicResponse(); 41710259SAndrew.Bardsley@arm.com } else if (pkt->isWrite()) { 41810259SAndrew.Bardsley@arm.com if (pmemAddr) 41910259SAndrew.Bardsley@arm.com memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 42010259SAndrew.Bardsley@arm.com TRACE_PACKET("Write"); 42110259SAndrew.Bardsley@arm.com pkt->makeAtomicResponse(); 42210259SAndrew.Bardsley@arm.com } else if (pkt->isPrint()) { 42310259SAndrew.Bardsley@arm.com Packet::PrintReqState *prs = 42410259SAndrew.Bardsley@arm.com dynamic_cast<Packet::PrintReqState*>(pkt->senderState); 42510259SAndrew.Bardsley@arm.com // Need to call printLabels() explicitly since we're not going 42610259SAndrew.Bardsley@arm.com // through printObj(). 42710259SAndrew.Bardsley@arm.com prs->printLabels(); 42810259SAndrew.Bardsley@arm.com // Right now we just print the single byte at the specified address. 42910259SAndrew.Bardsley@arm.com ccprintf(prs->os, "%s%#x\n", prs->curPrefix(), *hostAddr); 43010259SAndrew.Bardsley@arm.com } else { 43110259SAndrew.Bardsley@arm.com panic("PhysicalMemory: unimplemented functional command %s", 43210259SAndrew.Bardsley@arm.com pkt->cmdString()); 43310259SAndrew.Bardsley@arm.com } 43410259SAndrew.Bardsley@arm.com} 43510259SAndrew.Bardsley@arm.com 43610259SAndrew.Bardsley@arm.com 43710259SAndrew.Bardsley@arm.comPort * 43810259SAndrew.Bardsley@arm.comPhysicalMemory::getPort(const std::string &if_name, int idx) 43910259SAndrew.Bardsley@arm.com{ 44010259SAndrew.Bardsley@arm.com if (if_name != "port") { 44110259SAndrew.Bardsley@arm.com panic("PhysicalMemory::getPort: unknown port %s requested", if_name); 44210259SAndrew.Bardsley@arm.com } 44310259SAndrew.Bardsley@arm.com 44410259SAndrew.Bardsley@arm.com if (idx >= (int)ports.size()) { 44510259SAndrew.Bardsley@arm.com ports.resize(idx + 1); 44610259SAndrew.Bardsley@arm.com } 44710259SAndrew.Bardsley@arm.com 44810259SAndrew.Bardsley@arm.com if (ports[idx] != NULL) { 44910259SAndrew.Bardsley@arm.com panic("PhysicalMemory::getPort: port %d already assigned", idx); 45010259SAndrew.Bardsley@arm.com } 45110259SAndrew.Bardsley@arm.com 45210259SAndrew.Bardsley@arm.com MemoryPort *port = 45310259SAndrew.Bardsley@arm.com new MemoryPort(csprintf("%s-port%d", name(), idx), this); 45410259SAndrew.Bardsley@arm.com 45510259SAndrew.Bardsley@arm.com ports[idx] = port; 45610259SAndrew.Bardsley@arm.com return port; 45710259SAndrew.Bardsley@arm.com} 45810259SAndrew.Bardsley@arm.com 45910259SAndrew.Bardsley@arm.comPhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, 46010259SAndrew.Bardsley@arm.com PhysicalMemory *_memory) 46110259SAndrew.Bardsley@arm.com : SimpleTimingPort(_name, _memory), memory(_memory) 46210259SAndrew.Bardsley@arm.com{ } 46310259SAndrew.Bardsley@arm.com 46410259SAndrew.Bardsley@arm.comvoid 46510259SAndrew.Bardsley@arm.comPhysicalMemory::MemoryPort::recvRangeChange() 46610259SAndrew.Bardsley@arm.com{ 46710259SAndrew.Bardsley@arm.com // memory is a slave and thus should never have to worry about its 46810259SAndrew.Bardsley@arm.com // neighbours address ranges 46910259SAndrew.Bardsley@arm.com} 47010259SAndrew.Bardsley@arm.com 47110259SAndrew.Bardsley@arm.comAddrRangeList 47210259SAndrew.Bardsley@arm.comPhysicalMemory::MemoryPort::getAddrRanges() 47310259SAndrew.Bardsley@arm.com{ 47410259SAndrew.Bardsley@arm.com return memory->getAddrRanges(); 47510259SAndrew.Bardsley@arm.com} 47610259SAndrew.Bardsley@arm.com 47710259SAndrew.Bardsley@arm.comAddrRangeList 47810259SAndrew.Bardsley@arm.comPhysicalMemory::getAddrRanges() 47910259SAndrew.Bardsley@arm.com{ 48010259SAndrew.Bardsley@arm.com AddrRangeList ranges; 48110259SAndrew.Bardsley@arm.com ranges.push_back(RangeSize(start(), size())); 48210259SAndrew.Bardsley@arm.com return ranges; 48310259SAndrew.Bardsley@arm.com} 48410259SAndrew.Bardsley@arm.com 48510259SAndrew.Bardsley@arm.comunsigned 48610259SAndrew.Bardsley@arm.comPhysicalMemory::MemoryPort::deviceBlockSize() const 48710259SAndrew.Bardsley@arm.com{ 48810259SAndrew.Bardsley@arm.com return memory->deviceBlockSize(); 48910259SAndrew.Bardsley@arm.com} 49010259SAndrew.Bardsley@arm.com 49110259SAndrew.Bardsley@arm.comTick 49210259SAndrew.Bardsley@arm.comPhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt) 49310259SAndrew.Bardsley@arm.com{ 49410259SAndrew.Bardsley@arm.com return memory->doAtomicAccess(pkt); 49510259SAndrew.Bardsley@arm.com} 49610259SAndrew.Bardsley@arm.com 49710259SAndrew.Bardsley@arm.comvoid 49810259SAndrew.Bardsley@arm.comPhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt) 49910259SAndrew.Bardsley@arm.com{ 50010259SAndrew.Bardsley@arm.com pkt->pushLabel(memory->name()); 50110259SAndrew.Bardsley@arm.com 50210259SAndrew.Bardsley@arm.com if (!checkFunctional(pkt)) { 50310259SAndrew.Bardsley@arm.com // Default implementation of SimpleTimingPort::recvFunctional() 50410259SAndrew.Bardsley@arm.com // calls recvAtomic() and throws away the latency; we can save a 50510259SAndrew.Bardsley@arm.com // little here by just not calculating the latency. 50610259SAndrew.Bardsley@arm.com memory->doFunctionalAccess(pkt); 50710259SAndrew.Bardsley@arm.com } 50810259SAndrew.Bardsley@arm.com 50910259SAndrew.Bardsley@arm.com pkt->popLabel(); 51010259SAndrew.Bardsley@arm.com} 51110259SAndrew.Bardsley@arm.com 51210259SAndrew.Bardsley@arm.comunsigned int 51310259SAndrew.Bardsley@arm.comPhysicalMemory::drain(Event *de) 51410259SAndrew.Bardsley@arm.com{ 51510259SAndrew.Bardsley@arm.com int count = 0; 51610259SAndrew.Bardsley@arm.com for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { 51710259SAndrew.Bardsley@arm.com count += (*pi)->drain(de); 51810259SAndrew.Bardsley@arm.com } 51910259SAndrew.Bardsley@arm.com 52010259SAndrew.Bardsley@arm.com if (count) 52110259SAndrew.Bardsley@arm.com changeState(Draining); 52210259SAndrew.Bardsley@arm.com else 52310259SAndrew.Bardsley@arm.com changeState(Drained); 52410259SAndrew.Bardsley@arm.com return count; 52510259SAndrew.Bardsley@arm.com} 52610259SAndrew.Bardsley@arm.com 52710259SAndrew.Bardsley@arm.comvoid 52810259SAndrew.Bardsley@arm.comPhysicalMemory::serialize(ostream &os) 52910259SAndrew.Bardsley@arm.com{ 53010259SAndrew.Bardsley@arm.com if (!pmemAddr) 53110259SAndrew.Bardsley@arm.com return; 53210259SAndrew.Bardsley@arm.com 53310259SAndrew.Bardsley@arm.com gzFile compressedMem; 53410259SAndrew.Bardsley@arm.com string filename = name() + ".physmem"; 53510259SAndrew.Bardsley@arm.com 53610259SAndrew.Bardsley@arm.com SERIALIZE_SCALAR(filename); 53710259SAndrew.Bardsley@arm.com SERIALIZE_SCALAR(_size); 53810259SAndrew.Bardsley@arm.com 53910259SAndrew.Bardsley@arm.com // write memory file 54010259SAndrew.Bardsley@arm.com string thefile = Checkpoint::dir() + "/" + filename.c_str(); 54110259SAndrew.Bardsley@arm.com int fd = creat(thefile.c_str(), 0664); 54210259SAndrew.Bardsley@arm.com if (fd < 0) { 54310259SAndrew.Bardsley@arm.com perror("creat"); 54410259SAndrew.Bardsley@arm.com fatal("Can't open physical memory checkpoint file '%s'\n", filename); 54510259SAndrew.Bardsley@arm.com } 54610259SAndrew.Bardsley@arm.com 54710259SAndrew.Bardsley@arm.com compressedMem = gzdopen(fd, "wb"); 54810259SAndrew.Bardsley@arm.com if (compressedMem == NULL) 54910259SAndrew.Bardsley@arm.com fatal("Insufficient memory to allocate compression state for %s\n", 55010259SAndrew.Bardsley@arm.com filename); 55110259SAndrew.Bardsley@arm.com 55210259SAndrew.Bardsley@arm.com if (gzwrite(compressedMem, pmemAddr, size()) != (int)size()) { 55310259SAndrew.Bardsley@arm.com fatal("Write failed on physical memory checkpoint file '%s'\n", 55410259SAndrew.Bardsley@arm.com filename); 55510259SAndrew.Bardsley@arm.com } 55610259SAndrew.Bardsley@arm.com 55710259SAndrew.Bardsley@arm.com if (gzclose(compressedMem)) 55810259SAndrew.Bardsley@arm.com fatal("Close failed on physical memory checkpoint file '%s'\n", 55910259SAndrew.Bardsley@arm.com filename); 56010259SAndrew.Bardsley@arm.com 56110259SAndrew.Bardsley@arm.com list<LockedAddr>::iterator i = lockedAddrList.begin(); 56210259SAndrew.Bardsley@arm.com 56310259SAndrew.Bardsley@arm.com vector<Addr> lal_addr; 56410259SAndrew.Bardsley@arm.com vector<int> lal_cid; 56510259SAndrew.Bardsley@arm.com while (i != lockedAddrList.end()) { 56610259SAndrew.Bardsley@arm.com lal_addr.push_back(i->addr); 56710259SAndrew.Bardsley@arm.com lal_cid.push_back(i->contextId); 56810259SAndrew.Bardsley@arm.com i++; 56910259SAndrew.Bardsley@arm.com } 57010259SAndrew.Bardsley@arm.com arrayParamOut(os, "lal_addr", lal_addr); 57110259SAndrew.Bardsley@arm.com arrayParamOut(os, "lal_cid", lal_cid); 57210259SAndrew.Bardsley@arm.com} 57310259SAndrew.Bardsley@arm.com 57410259SAndrew.Bardsley@arm.comvoid 57510259SAndrew.Bardsley@arm.comPhysicalMemory::unserialize(Checkpoint *cp, const string §ion) 57610259SAndrew.Bardsley@arm.com{ 57710259SAndrew.Bardsley@arm.com if (!pmemAddr) 57810259SAndrew.Bardsley@arm.com return; 57910259SAndrew.Bardsley@arm.com 58010259SAndrew.Bardsley@arm.com gzFile compressedMem; 58110259SAndrew.Bardsley@arm.com long *tempPage; 58210259SAndrew.Bardsley@arm.com long *pmem_current; 58310259SAndrew.Bardsley@arm.com uint64_t curSize; 58410259SAndrew.Bardsley@arm.com uint32_t bytesRead; 58510259SAndrew.Bardsley@arm.com const uint32_t chunkSize = 16384; 58610259SAndrew.Bardsley@arm.com 58710259SAndrew.Bardsley@arm.com string filename; 58810259SAndrew.Bardsley@arm.com 58910259SAndrew.Bardsley@arm.com UNSERIALIZE_SCALAR(filename); 59010259SAndrew.Bardsley@arm.com 59110259SAndrew.Bardsley@arm.com filename = cp->cptDir + "/" + filename; 59210259SAndrew.Bardsley@arm.com 59310259SAndrew.Bardsley@arm.com // mmap memoryfile 59410259SAndrew.Bardsley@arm.com int fd = open(filename.c_str(), O_RDONLY); 59510259SAndrew.Bardsley@arm.com if (fd < 0) { 59610259SAndrew.Bardsley@arm.com perror("open"); 59710259SAndrew.Bardsley@arm.com fatal("Can't open physical memory checkpoint file '%s'", filename); 59810259SAndrew.Bardsley@arm.com } 59910259SAndrew.Bardsley@arm.com 60010259SAndrew.Bardsley@arm.com compressedMem = gzdopen(fd, "rb"); 60110259SAndrew.Bardsley@arm.com if (compressedMem == NULL) 60210259SAndrew.Bardsley@arm.com fatal("Insufficient memory to allocate compression state for %s\n", 60310259SAndrew.Bardsley@arm.com filename); 60410259SAndrew.Bardsley@arm.com 60510259SAndrew.Bardsley@arm.com // unmap file that was mmapped in the constructor 60610259SAndrew.Bardsley@arm.com // This is done here to make sure that gzip and open don't muck with our 60710259SAndrew.Bardsley@arm.com // nice large space of memory before we reallocate it 60810259SAndrew.Bardsley@arm.com munmap((char*)pmemAddr, size()); 60910259SAndrew.Bardsley@arm.com 61010259SAndrew.Bardsley@arm.com UNSERIALIZE_SCALAR(_size); 61110259SAndrew.Bardsley@arm.com if (size() > params()->range.size()) 61210259SAndrew.Bardsley@arm.com fatal("Memory size has changed! size %lld, param size %lld\n", 61310259SAndrew.Bardsley@arm.com size(), params()->range.size()); 61410259SAndrew.Bardsley@arm.com 61510259SAndrew.Bardsley@arm.com pmemAddr = (uint8_t *)mmap(NULL, size(), 61610259SAndrew.Bardsley@arm.com PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); 61710259SAndrew.Bardsley@arm.com 61810259SAndrew.Bardsley@arm.com if (pmemAddr == (void *)MAP_FAILED) { 61910259SAndrew.Bardsley@arm.com perror("mmap"); 62010259SAndrew.Bardsley@arm.com fatal("Could not mmap physical memory!\n"); 62110259SAndrew.Bardsley@arm.com } 62210259SAndrew.Bardsley@arm.com 62310259SAndrew.Bardsley@arm.com curSize = 0; 62410259SAndrew.Bardsley@arm.com tempPage = (long*)malloc(chunkSize); 62510259SAndrew.Bardsley@arm.com if (tempPage == NULL) 62610259SAndrew.Bardsley@arm.com fatal("Unable to malloc memory to read file %s\n", filename); 62710259SAndrew.Bardsley@arm.com 62810259SAndrew.Bardsley@arm.com /* Only copy bytes that are non-zero, so we don't give the VM system hell */ 62910259SAndrew.Bardsley@arm.com while (curSize < size()) { 63010259SAndrew.Bardsley@arm.com bytesRead = gzread(compressedMem, tempPage, chunkSize); 63110259SAndrew.Bardsley@arm.com if (bytesRead == 0) 63210259SAndrew.Bardsley@arm.com break; 63310259SAndrew.Bardsley@arm.com 63410259SAndrew.Bardsley@arm.com assert(bytesRead % sizeof(long) == 0); 63510259SAndrew.Bardsley@arm.com 63610259SAndrew.Bardsley@arm.com for (uint32_t x = 0; x < bytesRead / sizeof(long); x++) 63710259SAndrew.Bardsley@arm.com { 63810259SAndrew.Bardsley@arm.com if (*(tempPage+x) != 0) { 63910259SAndrew.Bardsley@arm.com pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long)); 64010259SAndrew.Bardsley@arm.com *pmem_current = *(tempPage+x); 64110259SAndrew.Bardsley@arm.com } 64210259SAndrew.Bardsley@arm.com } 64310259SAndrew.Bardsley@arm.com curSize += bytesRead; 64410259SAndrew.Bardsley@arm.com } 64510259SAndrew.Bardsley@arm.com 64610259SAndrew.Bardsley@arm.com free(tempPage); 64710259SAndrew.Bardsley@arm.com 64810259SAndrew.Bardsley@arm.com if (gzclose(compressedMem)) 64910259SAndrew.Bardsley@arm.com fatal("Close failed on physical memory checkpoint file '%s'\n", 65010259SAndrew.Bardsley@arm.com filename); 65110259SAndrew.Bardsley@arm.com 65210259SAndrew.Bardsley@arm.com vector<Addr> lal_addr; 65310259SAndrew.Bardsley@arm.com vector<int> lal_cid; 65410259SAndrew.Bardsley@arm.com arrayParamIn(cp, section, "lal_addr", lal_addr); 65510259SAndrew.Bardsley@arm.com arrayParamIn(cp, section, "lal_cid", lal_cid); 65610259SAndrew.Bardsley@arm.com for(int i = 0; i < lal_addr.size(); i++) 65710259SAndrew.Bardsley@arm.com lockedAddrList.push_front(LockedAddr(lal_addr[i], lal_cid[i])); 65810259SAndrew.Bardsley@arm.com} 65910259SAndrew.Bardsley@arm.com 66010259SAndrew.Bardsley@arm.comPhysicalMemory * 66110259SAndrew.Bardsley@arm.comPhysicalMemoryParams::create() 66210259SAndrew.Bardsley@arm.com{ 66310259SAndrew.Bardsley@arm.com return new PhysicalMemory(this); 66410259SAndrew.Bardsley@arm.com} 66510259SAndrew.Bardsley@arm.com