abstract_mem.cc revision 4626
12568SN/A/* 211192Sandreas.hansson@arm.com * Copyright (c) 2001-2005 The Regents of The University of Michigan 38713Sandreas.hansson@arm.com * All rights reserved. 48713Sandreas.hansson@arm.com * 58713Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 68713Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 78713Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 88713Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 98713Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 108713Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 118713Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 128713Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 138713Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 142568SN/A * this software without specific prior written permission. 152568SN/A * 162568SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172568SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182568SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192568SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202568SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212568SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222568SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232568SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242568SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252568SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262568SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272568SN/A * 282568SN/A * Authors: Ron Dreslinski 292568SN/A * Ali Saidi 302568SN/A */ 312568SN/A 322568SN/A#include <sys/types.h> 332568SN/A#include <sys/mman.h> 342568SN/A#include <errno.h> 352568SN/A#include <fcntl.h> 362568SN/A#include <unistd.h> 372568SN/A#include <zlib.h> 382568SN/A 392665Ssaidi@eecs.umich.edu#include <iostream> 402665Ssaidi@eecs.umich.edu#include <string> 412665Ssaidi@eecs.umich.edu 428713Sandreas.hansson@arm.com#include "arch/isa_traits.hh" 432568SN/A#include "base/misc.hh" 442568SN/A#include "config/full_system.hh" 452568SN/A#include "mem/packet_access.hh" 462982Sstever@eecs.umich.edu#include "mem/physical.hh" 4710405Sandreas.hansson@arm.com#include "sim/builder.hh" 488713Sandreas.hansson@arm.com#include "sim/eventq.hh" 492568SN/A#include "sim/host.hh" 502568SN/A 512568SN/Ausing namespace std; 529164Sandreas.hansson@arm.comusing namespace TheISA; 532568SN/A 544762Snate@binkert.orgPhysicalMemory::PhysicalMemory(Params *p) 552568SN/A : MemObject(p->name), pmemAddr(NULL), lat(p->latency), _params(p) 569164Sandreas.hansson@arm.com{ 579164Sandreas.hansson@arm.com if (params()->addrRange.size() % TheISA::PageBytes != 0) 588851Sandreas.hansson@arm.com panic("Memory Size not divisible by page size\n"); 599180Sandreas.hansson@arm.com 609235Sandreas.hansson@arm.com int map_flags = MAP_ANON | MAP_PRIVATE; 619164Sandreas.hansson@arm.com pmemAddr = 629164Sandreas.hansson@arm.com (uint8_t *)mmap(NULL, params()->addrRange.size(), 639164Sandreas.hansson@arm.com PROT_READ | PROT_WRITE, map_flags, -1, 0); 648851Sandreas.hansson@arm.com 658713Sandreas.hansson@arm.com if (pmemAddr == (void *)MAP_FAILED) { 668713Sandreas.hansson@arm.com perror("mmap"); 678713Sandreas.hansson@arm.com fatal("Could not mmap!\n"); 689164Sandreas.hansson@arm.com } 699164Sandreas.hansson@arm.com 708851Sandreas.hansson@arm.com //If requested, initialize all the memory to 0 719180Sandreas.hansson@arm.com if(params()->zero) 729164Sandreas.hansson@arm.com memset(pmemAddr, 0, params()->addrRange.size()); 739164Sandreas.hansson@arm.com 742643Sstever@eecs.umich.edu pagePtr = 0; 752643Sstever@eecs.umich.edu} 762643Sstever@eecs.umich.edu 774435Ssaidi@eecs.umich.eduvoid 785034Smilesck@eecs.umich.eduPhysicalMemory::init() 799180Sandreas.hansson@arm.com{ 809180Sandreas.hansson@arm.com if (ports.size() == 0) { 819180Sandreas.hansson@arm.com fatal("PhysicalMemory object %s is unconnected!", name()); 829180Sandreas.hansson@arm.com } 832643Sstever@eecs.umich.edu 842643Sstever@eecs.umich.edu for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { 852643Sstever@eecs.umich.edu if (*pi) 869294Sandreas.hansson@arm.com (*pi)->sendStatusChange(Port::RangeChange); 879294Sandreas.hansson@arm.com } 888922Swilliam.wang@arm.com} 898922Swilliam.wang@arm.com 908922Swilliam.wang@arm.comPhysicalMemory::~PhysicalMemory() 918922Swilliam.wang@arm.com{ 928922Swilliam.wang@arm.com if (pmemAddr) 938922Swilliam.wang@arm.com munmap((char*)pmemAddr, params()->addrRange.size()); 948922Swilliam.wang@arm.com //Remove memPorts? 958922Swilliam.wang@arm.com} 969294Sandreas.hansson@arm.com 979294Sandreas.hansson@arm.comAddr 982643Sstever@eecs.umich.eduPhysicalMemory::new_page() 998713Sandreas.hansson@arm.com{ 1008922Swilliam.wang@arm.com Addr return_addr = pagePtr << LogVMPageSize; 1018922Swilliam.wang@arm.com return_addr += start(); 1028922Swilliam.wang@arm.com 1038922Swilliam.wang@arm.com ++pagePtr; 1042643Sstever@eecs.umich.edu return return_addr; 1052643Sstever@eecs.umich.edu} 1062568SN/A 1072568SN/Aint 1082568SN/APhysicalMemory::deviceBlockSize() 1098713Sandreas.hansson@arm.com{ 1108713Sandreas.hansson@arm.com //Can accept anysize request 11110405Sandreas.hansson@arm.com return 0; 1124432Ssaidi@eecs.umich.edu} 1138713Sandreas.hansson@arm.com 1148713Sandreas.hansson@arm.comTick 1152568SN/APhysicalMemory::calculateLatency(PacketPtr pkt) 1162568SN/A{ 1174433Ssaidi@eecs.umich.edu return lat; 1189786Sandreas.hansson@arm.com} 1194433Ssaidi@eecs.umich.edu 1208713Sandreas.hansson@arm.com 1214435Ssaidi@eecs.umich.edu 1224435Ssaidi@eecs.umich.edu// Add load-locked to tracking list. Should only be called if the 1234435Ssaidi@eecs.umich.edu// operation is a load and the LOCKED flag is set. 1249786Sandreas.hansson@arm.comvoid 1254435Ssaidi@eecs.umich.eduPhysicalMemory::trackLoadLocked(PacketPtr pkt) 1269164Sandreas.hansson@arm.com{ 1274433Ssaidi@eecs.umich.edu Request *req = pkt->req; 1282568SN/A Addr paddr = LockedAddr::mask(req->getPaddr()); 1292568SN/A 1308975Sandreas.hansson@arm.com // first we check if we already have a locked addr for this 1312568SN/A // xc. Since each xc only gets one, we just update the 1328713Sandreas.hansson@arm.com // existing record with the new address. 1338713Sandreas.hansson@arm.com list<LockedAddr>::iterator i; 1349164Sandreas.hansson@arm.com 1358949Sandreas.hansson@arm.com for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) { 1362643Sstever@eecs.umich.edu if (i->matchesContext(req)) { 1379164Sandreas.hansson@arm.com DPRINTF(LLSC, "Modifying lock record: cpu %d thread %d addr %#x\n", 1384450Ssaidi@eecs.umich.edu req->getCpuNum(), req->getThreadNum(), paddr); 13911193Sandreas.hansson@arm.com i->addr = paddr; 14011193Sandreas.hansson@arm.com return; 14111193Sandreas.hansson@arm.com } 14211193Sandreas.hansson@arm.com } 14310694SMarco.Balboni@ARM.com 1449549Sandreas.hansson@arm.com // no record for this xc: need to allocate a new one 14511193Sandreas.hansson@arm.com DPRINTF(LLSC, "Adding lock record: cpu %d thread %d addr %#x\n", 14611193Sandreas.hansson@arm.com req->getCpuNum(), req->getThreadNum(), paddr); 1478713Sandreas.hansson@arm.com lockedAddrList.push_front(LockedAddr(req)); 1488713Sandreas.hansson@arm.com} 1498713Sandreas.hansson@arm.com 1508713Sandreas.hansson@arm.com 1518713Sandreas.hansson@arm.com// Called on *writes* only... both regular stores and 1528975Sandreas.hansson@arm.com// store-conditional operations. Check for conventional stores which 1538713Sandreas.hansson@arm.com// conflict with locked addresses, and for success/failure of store 1549164Sandreas.hansson@arm.com// conditionals. 1558949Sandreas.hansson@arm.combool 1568713Sandreas.hansson@arm.comPhysicalMemory::checkLockedAddrList(PacketPtr pkt) 15711192Sandreas.hansson@arm.com{ 15811192Sandreas.hansson@arm.com Request *req = pkt->req; 15911192Sandreas.hansson@arm.com Addr paddr = LockedAddr::mask(req->getPaddr()); 16011192Sandreas.hansson@arm.com bool isLocked = pkt->isLocked(); 16111192Sandreas.hansson@arm.com 16211192Sandreas.hansson@arm.com // Initialize return value. Non-conditional stores always 16311192Sandreas.hansson@arm.com // succeed. Assume conditional stores will fail until proven 16411192Sandreas.hansson@arm.com // otherwise. 16511192Sandreas.hansson@arm.com bool success = !isLocked; 16611192Sandreas.hansson@arm.com 16711192Sandreas.hansson@arm.com // Iterate over list. Note that there could be multiple matching 16811192Sandreas.hansson@arm.com // records, as more than one context could have done a load locked 16911192Sandreas.hansson@arm.com // to this location. 17011192Sandreas.hansson@arm.com list<LockedAddr>::iterator i = lockedAddrList.begin(); 1719164Sandreas.hansson@arm.com 1729164Sandreas.hansson@arm.com while (i != lockedAddrList.end()) { 1739164Sandreas.hansson@arm.com 1748713Sandreas.hansson@arm.com if (i->addr == paddr) { 1759786Sandreas.hansson@arm.com // we have a matching address 1768851Sandreas.hansson@arm.com 1779164Sandreas.hansson@arm.com if (isLocked && i->matchesContext(req)) { 1789164Sandreas.hansson@arm.com // it's a store conditional, and as far as the memory 1799786Sandreas.hansson@arm.com // system can tell, the requesting context's lock is 1809786Sandreas.hansson@arm.com // still valid. 18111192Sandreas.hansson@arm.com DPRINTF(LLSC, "StCond success: cpu %d thread %d addr %#x\n", 1829786Sandreas.hansson@arm.com req->getCpuNum(), req->getThreadNum(), paddr); 1839786Sandreas.hansson@arm.com success = true; 1849786Sandreas.hansson@arm.com } 1859786Sandreas.hansson@arm.com 1869786Sandreas.hansson@arm.com // Get rid of our record of this lock and advance to next 1879786Sandreas.hansson@arm.com DPRINTF(LLSC, "Erasing lock record: cpu %d thread %d addr %#x\n", 1889786Sandreas.hansson@arm.com i->cpuNum, i->threadNum, paddr); 1899786Sandreas.hansson@arm.com i = lockedAddrList.erase(i); 1909786Sandreas.hansson@arm.com } 1919549Sandreas.hansson@arm.com else { 1929786Sandreas.hansson@arm.com // no match: advance to next record 1939786Sandreas.hansson@arm.com ++i; 1949786Sandreas.hansson@arm.com } 1959786Sandreas.hansson@arm.com } 1969786Sandreas.hansson@arm.com 1979786Sandreas.hansson@arm.com if (isLocked) { 19811193Sandreas.hansson@arm.com req->setExtraData(success ? 1 : 0); 19911193Sandreas.hansson@arm.com } 20011193Sandreas.hansson@arm.com 20111193Sandreas.hansson@arm.com return success; 20211193Sandreas.hansson@arm.com} 20310694SMarco.Balboni@ARM.com 2049549Sandreas.hansson@arm.com 20511193Sandreas.hansson@arm.com#if TRACING_ON 20611193Sandreas.hansson@arm.com 2074433Ssaidi@eecs.umich.edu#define CASE(A, T) \ 2085562Snate@binkert.org case sizeof(T): \ 2094433Ssaidi@eecs.umich.edu DPRINTF(MemoryAccess, A " of size %i on address 0x%x data 0x%x\n", \ 2109164Sandreas.hansson@arm.com pkt->getSize(), pkt->getAddr(), pkt->get<T>()); \ 2119164Sandreas.hansson@arm.com break 2129164Sandreas.hansson@arm.com 2139164Sandreas.hansson@arm.com 2149164Sandreas.hansson@arm.com#define TRACE_PACKET(A) \ 2152657Ssaidi@eecs.umich.edu do { \ 2162657Ssaidi@eecs.umich.edu switch (pkt->getSize()) { \ 2174433Ssaidi@eecs.umich.edu CASE(A, uint64_t); \ 2189164Sandreas.hansson@arm.com CASE(A, uint32_t); \ 2194433Ssaidi@eecs.umich.edu CASE(A, uint16_t); \ 2209164Sandreas.hansson@arm.com CASE(A, uint8_t); \ 2219164Sandreas.hansson@arm.com default: \ 2229164Sandreas.hansson@arm.com DPRINTF(MemoryAccess, A " of size %i on address 0x%x\n", \ 22310713Sandreas.hansson@arm.com pkt->getSize(), pkt->getAddr()); \ 2244433Ssaidi@eecs.umich.edu } \ 2254433Ssaidi@eecs.umich.edu } while (0) 2264433Ssaidi@eecs.umich.edu 2274433Ssaidi@eecs.umich.edu#else 2289164Sandreas.hansson@arm.com 2292657Ssaidi@eecs.umich.edu#define TRACE_PACKET(A) 2302643Sstever@eecs.umich.edu 2312643Sstever@eecs.umich.edu#endif 2322643Sstever@eecs.umich.edu 2332643Sstever@eecs.umich.eduTick 2349164Sandreas.hansson@arm.comPhysicalMemory::doAtomicAccess(PacketPtr pkt) 2359164Sandreas.hansson@arm.com{ 2362568SN/A assert(pkt->getAddr() >= start() && 2378713Sandreas.hansson@arm.com pkt->getAddr() + pkt->getSize() <= start() + size()); 2389164Sandreas.hansson@arm.com 2398713Sandreas.hansson@arm.com if (pkt->memInhibitAsserted()) { 24010922Sandreas.hansson@arm.com DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n", 2418713Sandreas.hansson@arm.com pkt->getAddr()); 2428713Sandreas.hansson@arm.com return 0; 2438713Sandreas.hansson@arm.com } 2448713Sandreas.hansson@arm.com 2459164Sandreas.hansson@arm.com uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start(); 2468713Sandreas.hansson@arm.com 2478713Sandreas.hansson@arm.com if (pkt->cmd == MemCmd::SwapReq) { 2488713Sandreas.hansson@arm.com IntReg overwrite_val; 2498713Sandreas.hansson@arm.com bool overwrite_mem; 2508713Sandreas.hansson@arm.com uint64_t condition_val64; 2519164Sandreas.hansson@arm.com uint32_t condition_val32; 2529164Sandreas.hansson@arm.com 2538713Sandreas.hansson@arm.com assert(sizeof(IntReg) >= pkt->getSize()); 2549164Sandreas.hansson@arm.com 25510922Sandreas.hansson@arm.com overwrite_mem = true; 2562568SN/A // keep a copy of our possible write value, and copy what is at the 2572568SN/A // memory address into the packet 2582568SN/A std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize()); 2599164Sandreas.hansson@arm.com std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 2602568SN/A 2619164Sandreas.hansson@arm.com if (pkt->req->isCondSwap()) { 2622568SN/A if (pkt->getSize() == sizeof(uint64_t)) { 2639164Sandreas.hansson@arm.com condition_val64 = pkt->req->getExtraData(); 2642643Sstever@eecs.umich.edu overwrite_mem = !std::memcmp(&condition_val64, hostAddr, 2659164Sandreas.hansson@arm.com sizeof(uint64_t)); 2662643Sstever@eecs.umich.edu } else if (pkt->getSize() == sizeof(uint32_t)) { 2679029Sandreas.hansson@arm.com condition_val32 = (uint32_t)pkt->req->getExtraData(); 2682643Sstever@eecs.umich.edu overwrite_mem = !std::memcmp(&condition_val32, hostAddr, 2699164Sandreas.hansson@arm.com sizeof(uint32_t)); 2709164Sandreas.hansson@arm.com } else 2714432Ssaidi@eecs.umich.edu panic("Invalid size for conditional read/write\n"); 2728975Sandreas.hansson@arm.com } 2732643Sstever@eecs.umich.edu 2749164Sandreas.hansson@arm.com if (overwrite_mem) 2759164Sandreas.hansson@arm.com std::memcpy(hostAddr, &overwrite_val, pkt->getSize()); 2762657Ssaidi@eecs.umich.edu 2772657Ssaidi@eecs.umich.edu TRACE_PACKET("Read/Write"); 2789164Sandreas.hansson@arm.com } else if (pkt->isRead()) { 2799786Sandreas.hansson@arm.com assert(!pkt->isWrite()); 2809164Sandreas.hansson@arm.com if (pkt->isLocked()) { 2819786Sandreas.hansson@arm.com trackLoadLocked(pkt); 2829648Sdam.sunwoo@arm.com } 2832657Ssaidi@eecs.umich.edu memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 2849164Sandreas.hansson@arm.com TRACE_PACKET("Read"); 2859164Sandreas.hansson@arm.com } else if (pkt->isWrite()) { 2869164Sandreas.hansson@arm.com if (writeOK(pkt)) { 2879164Sandreas.hansson@arm.com memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 2889164Sandreas.hansson@arm.com TRACE_PACKET("Write"); 2899164Sandreas.hansson@arm.com } 2902643Sstever@eecs.umich.edu } else if (pkt->isInvalidate()) { 2914986Ssaidi@eecs.umich.edu //upgrade or invalidate 2929164Sandreas.hansson@arm.com if (pkt->needsResponse()) { 2939164Sandreas.hansson@arm.com pkt->makeAtomicResponse(); 2942568SN/A } 2952568SN/A } else { 2968713Sandreas.hansson@arm.com panic("unimplemented"); 2979164Sandreas.hansson@arm.com } 2988713Sandreas.hansson@arm.com 2999164Sandreas.hansson@arm.com if (pkt->needsResponse()) { 3008713Sandreas.hansson@arm.com pkt->makeAtomicResponse(); 3019164Sandreas.hansson@arm.com } 3028713Sandreas.hansson@arm.com return calculateLatency(pkt); 3039164Sandreas.hansson@arm.com} 3048713Sandreas.hansson@arm.com 3059029Sandreas.hansson@arm.com 3068713Sandreas.hansson@arm.comvoid 3079164Sandreas.hansson@arm.comPhysicalMemory::doFunctionalAccess(PacketPtr pkt) 3089164Sandreas.hansson@arm.com{ 3098713Sandreas.hansson@arm.com assert(pkt->getAddr() >= start() && 3108975Sandreas.hansson@arm.com pkt->getAddr() + pkt->getSize() <= start() + size()); 3118713Sandreas.hansson@arm.com 3129164Sandreas.hansson@arm.com uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start(); 3139164Sandreas.hansson@arm.com 3148713Sandreas.hansson@arm.com if (pkt->cmd == MemCmd::ReadReq) { 3159164Sandreas.hansson@arm.com memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 3169164Sandreas.hansson@arm.com TRACE_PACKET("Read"); 3179164Sandreas.hansson@arm.com } else if (pkt->cmd == MemCmd::WriteReq) { 3189164Sandreas.hansson@arm.com memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 3199164Sandreas.hansson@arm.com TRACE_PACKET("Write"); 3209786Sandreas.hansson@arm.com } else { 3219164Sandreas.hansson@arm.com panic("PhysicalMemory: unimplemented functional command %s", 3229786Sandreas.hansson@arm.com pkt->cmdString()); 3239648Sdam.sunwoo@arm.com } 3248713Sandreas.hansson@arm.com 3258713Sandreas.hansson@arm.com pkt->result = Packet::Success; 3269164Sandreas.hansson@arm.com} 3279164Sandreas.hansson@arm.com 3289164Sandreas.hansson@arm.com 3299164Sandreas.hansson@arm.comPort * 3309164Sandreas.hansson@arm.comPhysicalMemory::getPort(const std::string &if_name, int idx) 3319164Sandreas.hansson@arm.com{ 33210713Sandreas.hansson@arm.com // Accept request for "functional" port for backwards compatibility 3338713Sandreas.hansson@arm.com // with places where this function is called from C++. I'd prefer 3348713Sandreas.hansson@arm.com // to move all these into Python someday. 3358713Sandreas.hansson@arm.com if (if_name == "functional") { 3369164Sandreas.hansson@arm.com return new MemoryPort(csprintf("%s-functional", name()), this); 3379164Sandreas.hansson@arm.com } 3388713Sandreas.hansson@arm.com 3392568SN/A if (if_name != "port") { 3402657Ssaidi@eecs.umich.edu panic("PhysicalMemory::getPort: unknown port %s requested", if_name); 34110713Sandreas.hansson@arm.com } 3422568SN/A 3439786Sandreas.hansson@arm.com if (idx >= ports.size()) { 3442568SN/A ports.resize(idx+1); 3452568SN/A } 3468713Sandreas.hansson@arm.com 34710713Sandreas.hansson@arm.com if (ports[idx] != NULL) { 3482568SN/A panic("PhysicalMemory::getPort: port %d already assigned", idx); 3499786Sandreas.hansson@arm.com } 3502568SN/A 3512568SN/A MemoryPort *port = 3528713Sandreas.hansson@arm.com new MemoryPort(csprintf("%s-port%d", name(), idx), this); 3538713Sandreas.hansson@arm.com 3548713Sandreas.hansson@arm.com ports[idx] = port; 3559180Sandreas.hansson@arm.com return port; 3568713Sandreas.hansson@arm.com} 3578713Sandreas.hansson@arm.com 3582568SN/A 3598713Sandreas.hansson@arm.comvoid 3602568SN/APhysicalMemory::recvStatusChange(Port::Status status) 3615314Sstever@gmail.com{ 3625314Sstever@gmail.com} 3638713Sandreas.hansson@arm.com 3649786Sandreas.hansson@arm.comPhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, 3659029Sandreas.hansson@arm.com PhysicalMemory *_memory) 3667668Ssteve.reinhardt@amd.com : SimpleTimingPort(_name), memory(_memory) 3674626Sstever@eecs.umich.edu{ } 3687668Ssteve.reinhardt@amd.com 3692568SN/Avoid 3702568SN/APhysicalMemory::MemoryPort::recvStatusChange(Port::Status status) 3718713Sandreas.hansson@arm.com{ 3728851Sandreas.hansson@arm.com memory->recvStatusChange(status); 3738713Sandreas.hansson@arm.com} 3748713Sandreas.hansson@arm.com 3758713Sandreas.hansson@arm.comvoid 3765314Sstever@gmail.comPhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp, 3775314Sstever@gmail.com bool &snoop) 3784626Sstever@eecs.umich.edu{ 3798851Sandreas.hansson@arm.com memory->getAddressRanges(resp, snoop); 3808713Sandreas.hansson@arm.com} 3818713Sandreas.hansson@arm.com 3828713Sandreas.hansson@arm.comvoid 3838713Sandreas.hansson@arm.comPhysicalMemory::getAddressRanges(AddrRangeList &resp, bool &snoop) 3848713Sandreas.hansson@arm.com{ 3858713Sandreas.hansson@arm.com snoop = false; 3869786Sandreas.hansson@arm.com resp.clear(); 3878713Sandreas.hansson@arm.com resp.push_back(RangeSize(start(), params()->addrRange.size())); 3889164Sandreas.hansson@arm.com} 3899029Sandreas.hansson@arm.com 3908713Sandreas.hansson@arm.comint 3918713Sandreas.hansson@arm.comPhysicalMemory::MemoryPort::deviceBlockSize() 3928713Sandreas.hansson@arm.com{ 3938713Sandreas.hansson@arm.com return memory->deviceBlockSize(); 3948713Sandreas.hansson@arm.com} 3958713Sandreas.hansson@arm.com 3968713Sandreas.hansson@arm.comTick 3972568SN/APhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt) 3982568SN/A{ 3998711Sandreas.hansson@arm.com return memory->doAtomicAccess(pkt); 4009090Sandreas.hansson@arm.com} 4012568SN/A 4028711Sandreas.hansson@arm.comvoid 4032568SN/APhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt) 4042568SN/A{ 4054762Snate@binkert.org checkFunctional(pkt); 4064762Snate@binkert.org 4072568SN/A // Default implementation of SimpleTimingPort::recvFunctional() 4084762Snate@binkert.org // calls recvAtomic() and throws away the latency; we can save a 4092568SN/A // little here by just not calculating the latency. 410 memory->doFunctionalAccess(pkt); 411} 412 413unsigned int 414PhysicalMemory::drain(Event *de) 415{ 416 int count = 0; 417 for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { 418 count += (*pi)->drain(de); 419 } 420 421 if (count) 422 changeState(Draining); 423 else 424 changeState(Drained); 425 return count; 426} 427 428void 429PhysicalMemory::serialize(ostream &os) 430{ 431 gzFile compressedMem; 432 string filename = name() + ".physmem"; 433 434 SERIALIZE_SCALAR(filename); 435 436 // write memory file 437 string thefile = Checkpoint::dir() + "/" + filename.c_str(); 438 int fd = creat(thefile.c_str(), 0664); 439 if (fd < 0) { 440 perror("creat"); 441 fatal("Can't open physical memory checkpoint file '%s'\n", filename); 442 } 443 444 compressedMem = gzdopen(fd, "wb"); 445 if (compressedMem == NULL) 446 fatal("Insufficient memory to allocate compression state for %s\n", 447 filename); 448 449 if (gzwrite(compressedMem, pmemAddr, params()->addrRange.size()) != params()->addrRange.size()) { 450 fatal("Write failed on physical memory checkpoint file '%s'\n", 451 filename); 452 } 453 454 if (gzclose(compressedMem)) 455 fatal("Close failed on physical memory checkpoint file '%s'\n", 456 filename); 457} 458 459void 460PhysicalMemory::unserialize(Checkpoint *cp, const string §ion) 461{ 462 gzFile compressedMem; 463 long *tempPage; 464 long *pmem_current; 465 uint64_t curSize; 466 uint32_t bytesRead; 467 const int chunkSize = 16384; 468 469 470 string filename; 471 472 UNSERIALIZE_SCALAR(filename); 473 474 filename = cp->cptDir + "/" + filename; 475 476 // mmap memoryfile 477 int fd = open(filename.c_str(), O_RDONLY); 478 if (fd < 0) { 479 perror("open"); 480 fatal("Can't open physical memory checkpoint file '%s'", filename); 481 } 482 483 compressedMem = gzdopen(fd, "rb"); 484 if (compressedMem == NULL) 485 fatal("Insufficient memory to allocate compression state for %s\n", 486 filename); 487 488 // unmap file that was mmaped in the constructor 489 // This is done here to make sure that gzip and open don't muck with our 490 // nice large space of memory before we reallocate it 491 munmap((char*)pmemAddr, params()->addrRange.size()); 492 493 pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE, 494 MAP_ANON | MAP_PRIVATE, -1, 0); 495 496 if (pmemAddr == (void *)MAP_FAILED) { 497 perror("mmap"); 498 fatal("Could not mmap physical memory!\n"); 499 } 500 501 curSize = 0; 502 tempPage = (long*)malloc(chunkSize); 503 if (tempPage == NULL) 504 fatal("Unable to malloc memory to read file %s\n", filename); 505 506 /* Only copy bytes that are non-zero, so we don't give the VM system hell */ 507 while (curSize < params()->addrRange.size()) { 508 bytesRead = gzread(compressedMem, tempPage, chunkSize); 509 if (bytesRead != chunkSize && bytesRead != params()->addrRange.size() - curSize) 510 fatal("Read failed on physical memory checkpoint file '%s'" 511 " got %d bytes, expected %d or %d bytes\n", 512 filename, bytesRead, chunkSize, params()->addrRange.size()-curSize); 513 514 assert(bytesRead % sizeof(long) == 0); 515 516 for (int x = 0; x < bytesRead/sizeof(long); x++) 517 { 518 if (*(tempPage+x) != 0) { 519 pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long)); 520 *pmem_current = *(tempPage+x); 521 } 522 } 523 curSize += bytesRead; 524 } 525 526 free(tempPage); 527 528 if (gzclose(compressedMem)) 529 fatal("Close failed on physical memory checkpoint file '%s'\n", 530 filename); 531 532} 533 534 535BEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) 536 537 Param<string> file; 538 Param<Range<Addr> > range; 539 Param<Tick> latency; 540 Param<bool> zero; 541 542END_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) 543 544BEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) 545 546 INIT_PARAM_DFLT(file, "memory mapped file", ""), 547 INIT_PARAM(range, "Device Address Range"), 548 INIT_PARAM(latency, "Memory access latency"), 549 INIT_PARAM(zero, "Zero initialize memory") 550 551END_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) 552 553CREATE_SIM_OBJECT(PhysicalMemory) 554{ 555 PhysicalMemory::Params *p = new PhysicalMemory::Params; 556 p->name = getInstanceName(); 557 p->addrRange = range; 558 p->latency = latency; 559 p->zero = zero; 560 return new PhysicalMemory(p); 561} 562 563REGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory) 564