physical.cc revision 7733
12391SN/A/* 27733SAli.Saidi@ARM.com * Copyright (c) 2010 ARM Limited 37733SAli.Saidi@ARM.com * All rights reserved 47733SAli.Saidi@ARM.com * 57733SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall 67733SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual 77733SAli.Saidi@ARM.com * property including but not limited to intellectual property relating 87733SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software 97733SAli.Saidi@ARM.com * licensed hereunder. You may use the software subject to the license 107733SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated 117733SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software, 127733SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form. 137733SAli.Saidi@ARM.com * 142391SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan 152391SN/A * All rights reserved. 162391SN/A * 172391SN/A * Redistribution and use in source and binary forms, with or without 182391SN/A * modification, are permitted provided that the following conditions are 192391SN/A * met: redistributions of source code must retain the above copyright 202391SN/A * notice, this list of conditions and the following disclaimer; 212391SN/A * redistributions in binary form must reproduce the above copyright 222391SN/A * notice, this list of conditions and the following disclaimer in the 232391SN/A * documentation and/or other materials provided with the distribution; 242391SN/A * neither the name of the copyright holders nor the names of its 252391SN/A * contributors may be used to endorse or promote products derived from 262391SN/A * this software without specific prior written permission. 272391SN/A * 282391SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292391SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302391SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 312391SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 322391SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332391SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 342391SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 352391SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362391SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 372391SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 382391SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392665Ssaidi@eecs.umich.edu * 402665Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski 412914Ssaidi@eecs.umich.edu * Ali Saidi 422391SN/A */ 432391SN/A 442391SN/A#include <sys/types.h> 452391SN/A#include <sys/mman.h> 467730SAli.Saidi@ARM.com#include <sys/user.h> 472391SN/A#include <errno.h> 482391SN/A#include <fcntl.h> 492391SN/A#include <unistd.h> 502391SN/A#include <zlib.h> 512391SN/A 526712Snate@binkert.org#include <cstdio> 532391SN/A#include <iostream> 542391SN/A#include <string> 552391SN/A 566329Sgblack@eecs.umich.edu#include "arch/registers.hh" 577730SAli.Saidi@ARM.com#include "base/intmath.hh" 582391SN/A#include "base/misc.hh" 595399Ssaidi@eecs.umich.edu#include "base/random.hh" 606216Snate@binkert.org#include "base/types.hh" 612391SN/A#include "config/full_system.hh" 626658Snate@binkert.org#include "config/the_isa.hh" 633879Ssaidi@eecs.umich.edu#include "mem/packet_access.hh" 642394SN/A#include "mem/physical.hh" 652415SN/A#include "sim/eventq.hh" 662394SN/A 672391SN/Ausing namespace std; 682423SN/Ausing namespace TheISA; 692391SN/A 704762Snate@binkert.orgPhysicalMemory::PhysicalMemory(const Params *p) 715477Snate@binkert.org : MemObject(p), pmemAddr(NULL), pagePtr(0), 725477Snate@binkert.org lat(p->latency), lat_var(p->latency_var), 737730SAli.Saidi@ARM.com _size(params()->range.size()), _start(params()->range.start) 742391SN/A{ 757730SAli.Saidi@ARM.com if (size() % TheISA::PageBytes != 0) 762391SN/A panic("Memory Size not divisible by page size\n"); 772391SN/A 785477Snate@binkert.org if (params()->null) 795477Snate@binkert.org return; 805477Snate@binkert.org 817730SAli.Saidi@ARM.com 827730SAli.Saidi@ARM.com if (params()->file == "") { 837730SAli.Saidi@ARM.com int map_flags = MAP_ANON | MAP_PRIVATE; 847730SAli.Saidi@ARM.com pmemAddr = (uint8_t *)mmap(NULL, size(), 857730SAli.Saidi@ARM.com PROT_READ | PROT_WRITE, map_flags, -1, 0); 867730SAli.Saidi@ARM.com } else { 877730SAli.Saidi@ARM.com int map_flags = MAP_PRIVATE; 887730SAli.Saidi@ARM.com int fd = open(params()->file.c_str(), O_RDONLY); 897730SAli.Saidi@ARM.com _size = lseek(fd, 0, SEEK_END); 907730SAli.Saidi@ARM.com lseek(fd, 0, SEEK_SET); 917730SAli.Saidi@ARM.com pmemAddr = (uint8_t *)mmap(NULL, roundUp(size(), PAGE_SIZE), 927730SAli.Saidi@ARM.com PROT_READ | PROT_WRITE, map_flags, fd, 0); 937730SAli.Saidi@ARM.com } 942391SN/A 953012Ssaidi@eecs.umich.edu if (pmemAddr == (void *)MAP_FAILED) { 962391SN/A perror("mmap"); 977730SAli.Saidi@ARM.com if (params()->file == "") 987730SAli.Saidi@ARM.com fatal("Could not mmap!\n"); 997730SAli.Saidi@ARM.com else 1007730SAli.Saidi@ARM.com fatal("Could not find file: %s\n", params()->file); 1012391SN/A } 1022391SN/A 1033751Sgblack@eecs.umich.edu //If requested, initialize all the memory to 0 1044762Snate@binkert.org if (p->zero) 1057730SAli.Saidi@ARM.com memset(pmemAddr, 0, size()); 1062391SN/A} 1072391SN/A 1082541SN/Avoid 1092541SN/APhysicalMemory::init() 1102541SN/A{ 1114470Sstever@eecs.umich.edu if (ports.size() == 0) { 1124470Sstever@eecs.umich.edu fatal("PhysicalMemory object %s is unconnected!", name()); 1134470Sstever@eecs.umich.edu } 1144470Sstever@eecs.umich.edu 1154467Sstever@eecs.umich.edu for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { 1164467Sstever@eecs.umich.edu if (*pi) 1174467Sstever@eecs.umich.edu (*pi)->sendStatusChange(Port::RangeChange); 1184467Sstever@eecs.umich.edu } 1192541SN/A} 1202541SN/A 1212391SN/APhysicalMemory::~PhysicalMemory() 1222391SN/A{ 1233012Ssaidi@eecs.umich.edu if (pmemAddr) 1247730SAli.Saidi@ARM.com munmap((char*)pmemAddr, size()); 1252391SN/A} 1262391SN/A 1272391SN/AAddr 1282391SN/APhysicalMemory::new_page() 1292391SN/A{ 1303012Ssaidi@eecs.umich.edu Addr return_addr = pagePtr << LogVMPageSize; 1314040Ssaidi@eecs.umich.edu return_addr += start(); 1322391SN/A 1333012Ssaidi@eecs.umich.edu ++pagePtr; 1342391SN/A return return_addr; 1352391SN/A} 1362391SN/A 1376227Snate@binkert.orgunsigned 1386227Snate@binkert.orgPhysicalMemory::deviceBlockSize() const 1392408SN/A{ 1402409SN/A //Can accept anysize request 1412409SN/A return 0; 1422408SN/A} 1432408SN/A 1443012Ssaidi@eecs.umich.eduTick 1453349Sbinkertn@umich.eduPhysicalMemory::calculateLatency(PacketPtr pkt) 1463012Ssaidi@eecs.umich.edu{ 1475399Ssaidi@eecs.umich.edu Tick latency = lat; 1485399Ssaidi@eecs.umich.edu if (lat_var != 0) 1495399Ssaidi@eecs.umich.edu latency += random_mt.random<Tick>(0, lat_var); 1505399Ssaidi@eecs.umich.edu return latency; 1513012Ssaidi@eecs.umich.edu} 1522413SN/A 1533170Sstever@eecs.umich.edu 1543170Sstever@eecs.umich.edu 1553170Sstever@eecs.umich.edu// Add load-locked to tracking list. Should only be called if the 1566076Sgblack@eecs.umich.edu// operation is a load and the LLSC flag is set. 1573170Sstever@eecs.umich.eduvoid 1584626Sstever@eecs.umich.eduPhysicalMemory::trackLoadLocked(PacketPtr pkt) 1593170Sstever@eecs.umich.edu{ 1604626Sstever@eecs.umich.edu Request *req = pkt->req; 1613170Sstever@eecs.umich.edu Addr paddr = LockedAddr::mask(req->getPaddr()); 1623170Sstever@eecs.umich.edu 1633170Sstever@eecs.umich.edu // first we check if we already have a locked addr for this 1643170Sstever@eecs.umich.edu // xc. Since each xc only gets one, we just update the 1653170Sstever@eecs.umich.edu // existing record with the new address. 1663170Sstever@eecs.umich.edu list<LockedAddr>::iterator i; 1673170Sstever@eecs.umich.edu 1683170Sstever@eecs.umich.edu for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) { 1693170Sstever@eecs.umich.edu if (i->matchesContext(req)) { 1705714Shsul@eecs.umich.edu DPRINTF(LLSC, "Modifying lock record: context %d addr %#x\n", 1715714Shsul@eecs.umich.edu req->contextId(), paddr); 1723170Sstever@eecs.umich.edu i->addr = paddr; 1733170Sstever@eecs.umich.edu return; 1743170Sstever@eecs.umich.edu } 1753170Sstever@eecs.umich.edu } 1763170Sstever@eecs.umich.edu 1773170Sstever@eecs.umich.edu // no record for this xc: need to allocate a new one 1785714Shsul@eecs.umich.edu DPRINTF(LLSC, "Adding lock record: context %d addr %#x\n", 1795714Shsul@eecs.umich.edu req->contextId(), paddr); 1803170Sstever@eecs.umich.edu lockedAddrList.push_front(LockedAddr(req)); 1813170Sstever@eecs.umich.edu} 1823170Sstever@eecs.umich.edu 1833170Sstever@eecs.umich.edu 1843170Sstever@eecs.umich.edu// Called on *writes* only... both regular stores and 1853170Sstever@eecs.umich.edu// store-conditional operations. Check for conventional stores which 1863170Sstever@eecs.umich.edu// conflict with locked addresses, and for success/failure of store 1873170Sstever@eecs.umich.edu// conditionals. 1883170Sstever@eecs.umich.edubool 1894626Sstever@eecs.umich.eduPhysicalMemory::checkLockedAddrList(PacketPtr pkt) 1903170Sstever@eecs.umich.edu{ 1914626Sstever@eecs.umich.edu Request *req = pkt->req; 1923170Sstever@eecs.umich.edu Addr paddr = LockedAddr::mask(req->getPaddr()); 1936102Sgblack@eecs.umich.edu bool isLLSC = pkt->isLLSC(); 1943170Sstever@eecs.umich.edu 1953170Sstever@eecs.umich.edu // Initialize return value. Non-conditional stores always 1963170Sstever@eecs.umich.edu // succeed. Assume conditional stores will fail until proven 1973170Sstever@eecs.umich.edu // otherwise. 1986102Sgblack@eecs.umich.edu bool success = !isLLSC; 1993170Sstever@eecs.umich.edu 2003170Sstever@eecs.umich.edu // Iterate over list. Note that there could be multiple matching 2013170Sstever@eecs.umich.edu // records, as more than one context could have done a load locked 2023170Sstever@eecs.umich.edu // to this location. 2033170Sstever@eecs.umich.edu list<LockedAddr>::iterator i = lockedAddrList.begin(); 2043170Sstever@eecs.umich.edu 2053170Sstever@eecs.umich.edu while (i != lockedAddrList.end()) { 2063170Sstever@eecs.umich.edu 2073170Sstever@eecs.umich.edu if (i->addr == paddr) { 2083170Sstever@eecs.umich.edu // we have a matching address 2093170Sstever@eecs.umich.edu 2106102Sgblack@eecs.umich.edu if (isLLSC && i->matchesContext(req)) { 2113170Sstever@eecs.umich.edu // it's a store conditional, and as far as the memory 2123170Sstever@eecs.umich.edu // system can tell, the requesting context's lock is 2133170Sstever@eecs.umich.edu // still valid. 2145714Shsul@eecs.umich.edu DPRINTF(LLSC, "StCond success: context %d addr %#x\n", 2155714Shsul@eecs.umich.edu req->contextId(), paddr); 2163170Sstever@eecs.umich.edu success = true; 2173170Sstever@eecs.umich.edu } 2183170Sstever@eecs.umich.edu 2193170Sstever@eecs.umich.edu // Get rid of our record of this lock and advance to next 2205714Shsul@eecs.umich.edu DPRINTF(LLSC, "Erasing lock record: context %d addr %#x\n", 2215714Shsul@eecs.umich.edu i->contextId, paddr); 2223170Sstever@eecs.umich.edu i = lockedAddrList.erase(i); 2233170Sstever@eecs.umich.edu } 2243170Sstever@eecs.umich.edu else { 2253170Sstever@eecs.umich.edu // no match: advance to next record 2263170Sstever@eecs.umich.edu ++i; 2273170Sstever@eecs.umich.edu } 2283170Sstever@eecs.umich.edu } 2293170Sstever@eecs.umich.edu 2306102Sgblack@eecs.umich.edu if (isLLSC) { 2314040Ssaidi@eecs.umich.edu req->setExtraData(success ? 1 : 0); 2323170Sstever@eecs.umich.edu } 2333170Sstever@eecs.umich.edu 2343170Sstever@eecs.umich.edu return success; 2353170Sstever@eecs.umich.edu} 2363170Sstever@eecs.umich.edu 2374626Sstever@eecs.umich.edu 2384626Sstever@eecs.umich.edu#if TRACING_ON 2394626Sstever@eecs.umich.edu 2404626Sstever@eecs.umich.edu#define CASE(A, T) \ 2414626Sstever@eecs.umich.edu case sizeof(T): \ 2426429Ssteve.reinhardt@amd.com DPRINTF(MemoryAccess,"%s of size %i on address 0x%x data 0x%x\n", \ 2436429Ssteve.reinhardt@amd.com A, pkt->getSize(), pkt->getAddr(), pkt->get<T>()); \ 2444626Sstever@eecs.umich.edu break 2454626Sstever@eecs.umich.edu 2464626Sstever@eecs.umich.edu 2474626Sstever@eecs.umich.edu#define TRACE_PACKET(A) \ 2484626Sstever@eecs.umich.edu do { \ 2494626Sstever@eecs.umich.edu switch (pkt->getSize()) { \ 2504626Sstever@eecs.umich.edu CASE(A, uint64_t); \ 2514626Sstever@eecs.umich.edu CASE(A, uint32_t); \ 2524626Sstever@eecs.umich.edu CASE(A, uint16_t); \ 2534626Sstever@eecs.umich.edu CASE(A, uint8_t); \ 2544626Sstever@eecs.umich.edu default: \ 2556429Ssteve.reinhardt@amd.com DPRINTF(MemoryAccess, "%s of size %i on address 0x%x\n", \ 2566429Ssteve.reinhardt@amd.com A, pkt->getSize(), pkt->getAddr()); \ 2574626Sstever@eecs.umich.edu } \ 2584626Sstever@eecs.umich.edu } while (0) 2594626Sstever@eecs.umich.edu 2604626Sstever@eecs.umich.edu#else 2614626Sstever@eecs.umich.edu 2624626Sstever@eecs.umich.edu#define TRACE_PACKET(A) 2634626Sstever@eecs.umich.edu 2644626Sstever@eecs.umich.edu#endif 2654626Sstever@eecs.umich.edu 2664626Sstever@eecs.umich.eduTick 2674626Sstever@eecs.umich.eduPhysicalMemory::doAtomicAccess(PacketPtr pkt) 2682413SN/A{ 2694040Ssaidi@eecs.umich.edu assert(pkt->getAddr() >= start() && 2704040Ssaidi@eecs.umich.edu pkt->getAddr() + pkt->getSize() <= start() + size()); 2712414SN/A 2724626Sstever@eecs.umich.edu if (pkt->memInhibitAsserted()) { 2734626Sstever@eecs.umich.edu DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n", 2744626Sstever@eecs.umich.edu pkt->getAddr()); 2754626Sstever@eecs.umich.edu return 0; 2763175Srdreslin@umich.edu } 2774626Sstever@eecs.umich.edu 2784626Sstever@eecs.umich.edu uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start(); 2794626Sstever@eecs.umich.edu 2804626Sstever@eecs.umich.edu if (pkt->cmd == MemCmd::SwapReq) { 2814040Ssaidi@eecs.umich.edu IntReg overwrite_val; 2824040Ssaidi@eecs.umich.edu bool overwrite_mem; 2834040Ssaidi@eecs.umich.edu uint64_t condition_val64; 2844040Ssaidi@eecs.umich.edu uint32_t condition_val32; 2854040Ssaidi@eecs.umich.edu 2865477Snate@binkert.org if (!pmemAddr) 2875477Snate@binkert.org panic("Swap only works if there is real memory (i.e. null=False)"); 2884040Ssaidi@eecs.umich.edu assert(sizeof(IntReg) >= pkt->getSize()); 2894040Ssaidi@eecs.umich.edu 2904040Ssaidi@eecs.umich.edu overwrite_mem = true; 2914040Ssaidi@eecs.umich.edu // keep a copy of our possible write value, and copy what is at the 2924040Ssaidi@eecs.umich.edu // memory address into the packet 2934052Ssaidi@eecs.umich.edu std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize()); 2944626Sstever@eecs.umich.edu std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 2954040Ssaidi@eecs.umich.edu 2964040Ssaidi@eecs.umich.edu if (pkt->req->isCondSwap()) { 2974040Ssaidi@eecs.umich.edu if (pkt->getSize() == sizeof(uint64_t)) { 2984052Ssaidi@eecs.umich.edu condition_val64 = pkt->req->getExtraData(); 2994626Sstever@eecs.umich.edu overwrite_mem = !std::memcmp(&condition_val64, hostAddr, 3004626Sstever@eecs.umich.edu sizeof(uint64_t)); 3014040Ssaidi@eecs.umich.edu } else if (pkt->getSize() == sizeof(uint32_t)) { 3024052Ssaidi@eecs.umich.edu condition_val32 = (uint32_t)pkt->req->getExtraData(); 3034626Sstever@eecs.umich.edu overwrite_mem = !std::memcmp(&condition_val32, hostAddr, 3044626Sstever@eecs.umich.edu sizeof(uint32_t)); 3054040Ssaidi@eecs.umich.edu } else 3064040Ssaidi@eecs.umich.edu panic("Invalid size for conditional read/write\n"); 3074040Ssaidi@eecs.umich.edu } 3084040Ssaidi@eecs.umich.edu 3094040Ssaidi@eecs.umich.edu if (overwrite_mem) 3104626Sstever@eecs.umich.edu std::memcpy(hostAddr, &overwrite_val, pkt->getSize()); 3114040Ssaidi@eecs.umich.edu 3126429Ssteve.reinhardt@amd.com assert(!pkt->req->isInstFetch()); 3134626Sstever@eecs.umich.edu TRACE_PACKET("Read/Write"); 3144626Sstever@eecs.umich.edu } else if (pkt->isRead()) { 3154626Sstever@eecs.umich.edu assert(!pkt->isWrite()); 3166102Sgblack@eecs.umich.edu if (pkt->isLLSC()) { 3174626Sstever@eecs.umich.edu trackLoadLocked(pkt); 3184040Ssaidi@eecs.umich.edu } 3195477Snate@binkert.org if (pmemAddr) 3205477Snate@binkert.org memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 3216429Ssteve.reinhardt@amd.com TRACE_PACKET(pkt->req->isInstFetch() ? "IFetch" : "Read"); 3224626Sstever@eecs.umich.edu } else if (pkt->isWrite()) { 3234626Sstever@eecs.umich.edu if (writeOK(pkt)) { 3245477Snate@binkert.org if (pmemAddr) 3255477Snate@binkert.org memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 3266429Ssteve.reinhardt@amd.com assert(!pkt->req->isInstFetch()); 3274626Sstever@eecs.umich.edu TRACE_PACKET("Write"); 3284626Sstever@eecs.umich.edu } 3294626Sstever@eecs.umich.edu } else if (pkt->isInvalidate()) { 3304626Sstever@eecs.umich.edu //upgrade or invalidate 3314626Sstever@eecs.umich.edu if (pkt->needsResponse()) { 3324626Sstever@eecs.umich.edu pkt->makeAtomicResponse(); 3334626Sstever@eecs.umich.edu } 3344040Ssaidi@eecs.umich.edu } else { 3352413SN/A panic("unimplemented"); 3362413SN/A } 3372420SN/A 3384626Sstever@eecs.umich.edu if (pkt->needsResponse()) { 3394626Sstever@eecs.umich.edu pkt->makeAtomicResponse(); 3404626Sstever@eecs.umich.edu } 3414626Sstever@eecs.umich.edu return calculateLatency(pkt); 3422413SN/A} 3432413SN/A 3444626Sstever@eecs.umich.edu 3454626Sstever@eecs.umich.eduvoid 3464626Sstever@eecs.umich.eduPhysicalMemory::doFunctionalAccess(PacketPtr pkt) 3474626Sstever@eecs.umich.edu{ 3484626Sstever@eecs.umich.edu assert(pkt->getAddr() >= start() && 3494626Sstever@eecs.umich.edu pkt->getAddr() + pkt->getSize() <= start() + size()); 3504626Sstever@eecs.umich.edu 3515222Sksewell@umich.edu 3524626Sstever@eecs.umich.edu uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start(); 3534626Sstever@eecs.umich.edu 3545314Sstever@gmail.com if (pkt->isRead()) { 3555477Snate@binkert.org if (pmemAddr) 3565477Snate@binkert.org memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 3574626Sstever@eecs.umich.edu TRACE_PACKET("Read"); 3585314Sstever@gmail.com pkt->makeAtomicResponse(); 3595314Sstever@gmail.com } else if (pkt->isWrite()) { 3605477Snate@binkert.org if (pmemAddr) 3615477Snate@binkert.org memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 3624626Sstever@eecs.umich.edu TRACE_PACKET("Write"); 3635314Sstever@gmail.com pkt->makeAtomicResponse(); 3645314Sstever@gmail.com } else if (pkt->isPrint()) { 3655315Sstever@gmail.com Packet::PrintReqState *prs = 3665315Sstever@gmail.com dynamic_cast<Packet::PrintReqState*>(pkt->senderState); 3675315Sstever@gmail.com // Need to call printLabels() explicitly since we're not going 3685315Sstever@gmail.com // through printObj(). 3695314Sstever@gmail.com prs->printLabels(); 3705315Sstever@gmail.com // Right now we just print the single byte at the specified address. 3715314Sstever@gmail.com ccprintf(prs->os, "%s%#x\n", prs->curPrefix(), *hostAddr); 3724626Sstever@eecs.umich.edu } else { 3734626Sstever@eecs.umich.edu panic("PhysicalMemory: unimplemented functional command %s", 3744626Sstever@eecs.umich.edu pkt->cmdString()); 3754626Sstever@eecs.umich.edu } 3764490Sstever@eecs.umich.edu} 3774490Sstever@eecs.umich.edu 3784626Sstever@eecs.umich.edu 3792413SN/APort * 3802738Sstever@eecs.umich.eduPhysicalMemory::getPort(const std::string &if_name, int idx) 3812413SN/A{ 3824468Sstever@eecs.umich.edu // Accept request for "functional" port for backwards compatibility 3834468Sstever@eecs.umich.edu // with places where this function is called from C++. I'd prefer 3844468Sstever@eecs.umich.edu // to move all these into Python someday. 3854468Sstever@eecs.umich.edu if (if_name == "functional") { 3864468Sstever@eecs.umich.edu return new MemoryPort(csprintf("%s-functional", name()), this); 3874468Sstever@eecs.umich.edu } 3884468Sstever@eecs.umich.edu 3894467Sstever@eecs.umich.edu if (if_name != "port") { 3902462SN/A panic("PhysicalMemory::getPort: unknown port %s requested", if_name); 3912462SN/A } 3924467Sstever@eecs.umich.edu 3936227Snate@binkert.org if (idx >= (int)ports.size()) { 3946227Snate@binkert.org ports.resize(idx + 1); 3954467Sstever@eecs.umich.edu } 3964467Sstever@eecs.umich.edu 3974467Sstever@eecs.umich.edu if (ports[idx] != NULL) { 3984467Sstever@eecs.umich.edu panic("PhysicalMemory::getPort: port %d already assigned", idx); 3994467Sstever@eecs.umich.edu } 4004467Sstever@eecs.umich.edu 4014467Sstever@eecs.umich.edu MemoryPort *port = 4024467Sstever@eecs.umich.edu new MemoryPort(csprintf("%s-port%d", name(), idx), this); 4034467Sstever@eecs.umich.edu 4044467Sstever@eecs.umich.edu ports[idx] = port; 4054467Sstever@eecs.umich.edu return port; 4062413SN/A} 4072413SN/A 4084467Sstever@eecs.umich.edu 4092413SN/Avoid 4102413SN/APhysicalMemory::recvStatusChange(Port::Status status) 4112413SN/A{ 4122413SN/A} 4132413SN/A 4142640Sstever@eecs.umich.eduPhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, 4152640Sstever@eecs.umich.edu PhysicalMemory *_memory) 4165606Snate@binkert.org : SimpleTimingPort(_name, _memory), memory(_memory) 4172413SN/A{ } 4182413SN/A 4192413SN/Avoid 4202413SN/APhysicalMemory::MemoryPort::recvStatusChange(Port::Status status) 4212413SN/A{ 4222413SN/A memory->recvStatusChange(status); 4232413SN/A} 4242413SN/A 4252413SN/Avoid 4262522SN/APhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp, 4274475Sstever@eecs.umich.edu bool &snoop) 4282413SN/A{ 4292522SN/A memory->getAddressRanges(resp, snoop); 4302497SN/A} 4312497SN/A 4322497SN/Avoid 4334475Sstever@eecs.umich.eduPhysicalMemory::getAddressRanges(AddrRangeList &resp, bool &snoop) 4342497SN/A{ 4354475Sstever@eecs.umich.edu snoop = false; 4362522SN/A resp.clear(); 4377730SAli.Saidi@ARM.com resp.push_back(RangeSize(start(), size())); 4382413SN/A} 4392413SN/A 4406227Snate@binkert.orgunsigned 4416227Snate@binkert.orgPhysicalMemory::MemoryPort::deviceBlockSize() const 4422415SN/A{ 4432415SN/A return memory->deviceBlockSize(); 4442415SN/A} 4452413SN/A 4462413SN/ATick 4473349Sbinkertn@umich.eduPhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt) 4482413SN/A{ 4494626Sstever@eecs.umich.edu return memory->doAtomicAccess(pkt); 4502413SN/A} 4512413SN/A 4522413SN/Avoid 4533349Sbinkertn@umich.eduPhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt) 4542413SN/A{ 4555314Sstever@gmail.com pkt->pushLabel(memory->name()); 4565314Sstever@gmail.com 4574929Sstever@gmail.com if (!checkFunctional(pkt)) { 4584929Sstever@gmail.com // Default implementation of SimpleTimingPort::recvFunctional() 4594929Sstever@gmail.com // calls recvAtomic() and throws away the latency; we can save a 4604929Sstever@gmail.com // little here by just not calculating the latency. 4614929Sstever@gmail.com memory->doFunctionalAccess(pkt); 4624929Sstever@gmail.com } 4635314Sstever@gmail.com 4645314Sstever@gmail.com pkt->popLabel(); 4652413SN/A} 4662413SN/A 4672914Ssaidi@eecs.umich.eduunsigned int 4682914Ssaidi@eecs.umich.eduPhysicalMemory::drain(Event *de) 4692914Ssaidi@eecs.umich.edu{ 4704467Sstever@eecs.umich.edu int count = 0; 4714467Sstever@eecs.umich.edu for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { 4724467Sstever@eecs.umich.edu count += (*pi)->drain(de); 4734467Sstever@eecs.umich.edu } 4744467Sstever@eecs.umich.edu 4752914Ssaidi@eecs.umich.edu if (count) 4762914Ssaidi@eecs.umich.edu changeState(Draining); 4772914Ssaidi@eecs.umich.edu else 4782914Ssaidi@eecs.umich.edu changeState(Drained); 4792914Ssaidi@eecs.umich.edu return count; 4802914Ssaidi@eecs.umich.edu} 4812413SN/A 4822391SN/Avoid 4832391SN/APhysicalMemory::serialize(ostream &os) 4842391SN/A{ 4855477Snate@binkert.org if (!pmemAddr) 4865477Snate@binkert.org return; 4875477Snate@binkert.org 4882391SN/A gzFile compressedMem; 4892391SN/A string filename = name() + ".physmem"; 4902391SN/A 4912391SN/A SERIALIZE_SCALAR(filename); 4927730SAli.Saidi@ARM.com SERIALIZE_SCALAR(_size); 4932391SN/A 4942391SN/A // write memory file 4952391SN/A string thefile = Checkpoint::dir() + "/" + filename.c_str(); 4962391SN/A int fd = creat(thefile.c_str(), 0664); 4972391SN/A if (fd < 0) { 4982391SN/A perror("creat"); 4992391SN/A fatal("Can't open physical memory checkpoint file '%s'\n", filename); 5002391SN/A } 5012391SN/A 5022391SN/A compressedMem = gzdopen(fd, "wb"); 5032391SN/A if (compressedMem == NULL) 5042391SN/A fatal("Insufficient memory to allocate compression state for %s\n", 5052391SN/A filename); 5062391SN/A 5077730SAli.Saidi@ARM.com if (gzwrite(compressedMem, pmemAddr, size()) != (int)size()) { 5082391SN/A fatal("Write failed on physical memory checkpoint file '%s'\n", 5092391SN/A filename); 5102391SN/A } 5112391SN/A 5122391SN/A if (gzclose(compressedMem)) 5132391SN/A fatal("Close failed on physical memory checkpoint file '%s'\n", 5142391SN/A filename); 5157733SAli.Saidi@ARM.com 5167733SAli.Saidi@ARM.com list<LockedAddr>::iterator i = lockedAddrList.begin(); 5177733SAli.Saidi@ARM.com 5187733SAli.Saidi@ARM.com vector<Addr> lal_addr; 5197733SAli.Saidi@ARM.com vector<int> lal_cid; 5207733SAli.Saidi@ARM.com while (i != lockedAddrList.end()) { 5217733SAli.Saidi@ARM.com lal_addr.push_back(i->addr); 5227733SAli.Saidi@ARM.com lal_cid.push_back(i->contextId); 5237733SAli.Saidi@ARM.com i++; 5247733SAli.Saidi@ARM.com } 5257733SAli.Saidi@ARM.com arrayParamOut(os, "lal_addr", lal_addr); 5267733SAli.Saidi@ARM.com arrayParamOut(os, "lal_cid", lal_cid); 5272391SN/A} 5282391SN/A 5292391SN/Avoid 5302391SN/APhysicalMemory::unserialize(Checkpoint *cp, const string §ion) 5312391SN/A{ 5325477Snate@binkert.org if (!pmemAddr) 5335477Snate@binkert.org return; 5345477Snate@binkert.org 5352391SN/A gzFile compressedMem; 5362391SN/A long *tempPage; 5372391SN/A long *pmem_current; 5382391SN/A uint64_t curSize; 5392391SN/A uint32_t bytesRead; 5406227Snate@binkert.org const uint32_t chunkSize = 16384; 5412391SN/A 5422391SN/A string filename; 5432391SN/A 5442391SN/A UNSERIALIZE_SCALAR(filename); 5452391SN/A 5462391SN/A filename = cp->cptDir + "/" + filename; 5472391SN/A 5482391SN/A // mmap memoryfile 5492391SN/A int fd = open(filename.c_str(), O_RDONLY); 5502391SN/A if (fd < 0) { 5512391SN/A perror("open"); 5522391SN/A fatal("Can't open physical memory checkpoint file '%s'", filename); 5532391SN/A } 5542391SN/A 5552391SN/A compressedMem = gzdopen(fd, "rb"); 5562391SN/A if (compressedMem == NULL) 5572391SN/A fatal("Insufficient memory to allocate compression state for %s\n", 5582391SN/A filename); 5592391SN/A 5603012Ssaidi@eecs.umich.edu // unmap file that was mmaped in the constructor 5613012Ssaidi@eecs.umich.edu // This is done here to make sure that gzip and open don't muck with our 5623012Ssaidi@eecs.umich.edu // nice large space of memory before we reallocate it 5637730SAli.Saidi@ARM.com munmap((char*)pmemAddr, size()); 5642391SN/A 5657730SAli.Saidi@ARM.com UNSERIALIZE_SCALAR(_size); 5667730SAli.Saidi@ARM.com if (size() > params()->range.size()) 5677730SAli.Saidi@ARM.com fatal("Memory size has changed!\n"); 5687730SAli.Saidi@ARM.com 5697730SAli.Saidi@ARM.com pmemAddr = (uint8_t *)mmap(NULL, size(), 5704762Snate@binkert.org PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); 5712391SN/A 5723012Ssaidi@eecs.umich.edu if (pmemAddr == (void *)MAP_FAILED) { 5732391SN/A perror("mmap"); 5742391SN/A fatal("Could not mmap physical memory!\n"); 5752391SN/A } 5762391SN/A 5772391SN/A curSize = 0; 5782391SN/A tempPage = (long*)malloc(chunkSize); 5792391SN/A if (tempPage == NULL) 5802391SN/A fatal("Unable to malloc memory to read file %s\n", filename); 5812391SN/A 5822391SN/A /* Only copy bytes that are non-zero, so we don't give the VM system hell */ 5837730SAli.Saidi@ARM.com while (curSize < size()) { 5842391SN/A bytesRead = gzread(compressedMem, tempPage, chunkSize); 5856820SLisa.Hsu@amd.com if (bytesRead == 0) 5866820SLisa.Hsu@amd.com break; 5872391SN/A 5882391SN/A assert(bytesRead % sizeof(long) == 0); 5892391SN/A 5906227Snate@binkert.org for (uint32_t x = 0; x < bytesRead / sizeof(long); x++) 5912391SN/A { 5922391SN/A if (*(tempPage+x) != 0) { 5933012Ssaidi@eecs.umich.edu pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long)); 5942391SN/A *pmem_current = *(tempPage+x); 5952391SN/A } 5962391SN/A } 5972391SN/A curSize += bytesRead; 5982391SN/A } 5992391SN/A 6002391SN/A free(tempPage); 6012391SN/A 6022391SN/A if (gzclose(compressedMem)) 6032391SN/A fatal("Close failed on physical memory checkpoint file '%s'\n", 6042391SN/A filename); 6052391SN/A 6067733SAli.Saidi@ARM.com vector<Addr> lal_addr; 6077733SAli.Saidi@ARM.com vector<int> lal_cid; 6087733SAli.Saidi@ARM.com arrayParamIn(cp, section, "lal_addr", lal_addr); 6097733SAli.Saidi@ARM.com arrayParamIn(cp, section, "lal_cid", lal_cid); 6107733SAli.Saidi@ARM.com for(int i = 0; i < lal_addr.size(); i++) 6117733SAli.Saidi@ARM.com lockedAddrList.push_front(LockedAddr(lal_addr[i], lal_cid[i])); 6122391SN/A} 6132391SN/A 6144762Snate@binkert.orgPhysicalMemory * 6154762Snate@binkert.orgPhysicalMemoryParams::create() 6162391SN/A{ 6174762Snate@binkert.org return new PhysicalMemory(this); 6182391SN/A} 619