abstract_mem.cc revision 4052
12968SN/A/* 22968SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan 310409Sandreas.hansson@arm.com * All rights reserved. 411754Sandreas.hansson@arm.com * 511754Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 68721SN/A * modification, are permitted provided that the following conditions are 711754Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 811754Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 911754Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 1011754Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 1111754Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 1211336Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 1311336Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 1410036SAli.Saidi@ARM.com * this software without specific prior written permission. 1510036SAli.Saidi@ARM.com * 1611754Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1711201Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1811606Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1911336Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2011606Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2110352Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2211606Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2311201Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2411336Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2511336Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2611606Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2711606Sandreas.sandberg@arm.com * 2811201Sandreas.hansson@arm.com * Authors: Ron Dreslinski 2911606Sandreas.sandberg@arm.com * Ali Saidi 3011336Sandreas.hansson@arm.com */ 3111606Sandreas.sandberg@arm.com 3210352Sandreas.hansson@arm.com#include <sys/types.h> 3311606Sandreas.sandberg@arm.com#include <sys/mman.h> 3411606Sandreas.sandberg@arm.com#include <errno.h> 3511606Sandreas.sandberg@arm.com#include <fcntl.h> 3611201Sandreas.hansson@arm.com#include <unistd.h> 3711754Sandreas.hansson@arm.com#include <zlib.h> 3811336Sandreas.hansson@arm.com 3911606Sandreas.sandberg@arm.com#include <iostream> 4010409Sandreas.hansson@arm.com#include <string> 4111754Sandreas.hansson@arm.com 4211201Sandreas.hansson@arm.com#include "arch/isa_traits.hh" 4311336Sandreas.hansson@arm.com#include "base/misc.hh" 4411336Sandreas.hansson@arm.com#include "config/full_system.hh" 4511606Sandreas.sandberg@arm.com#include "mem/packet_access.hh" 4611606Sandreas.sandberg@arm.com#include "mem/physical.hh" 4711606Sandreas.sandberg@arm.com#include "sim/builder.hh" 4811201Sandreas.hansson@arm.com#include "sim/eventq.hh" 4911754Sandreas.hansson@arm.com#include "sim/host.hh" 5011336Sandreas.hansson@arm.com 5111606Sandreas.sandberg@arm.comusing namespace std; 5210585Sandreas.hansson@arm.comusing namespace TheISA; 5311754Sandreas.hansson@arm.com 5411754Sandreas.hansson@arm.comPhysicalMemory::PhysicalMemory(Params *p) 5511754Sandreas.hansson@arm.com : MemObject(p->name), pmemAddr(NULL), port(NULL), lat(p->latency), _params(p) 5610036SAli.Saidi@ARM.com{ 578721SN/A if (params()->addrRange.size() % TheISA::PageBytes != 0) 588721SN/A panic("Memory Size not divisible by page size\n"); 598721SN/A 608721SN/A int map_flags = MAP_ANON | MAP_PRIVATE; 6111336Sandreas.hansson@arm.com pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE, 6210409Sandreas.hansson@arm.com map_flags, -1, 0); 638721SN/A 6410409Sandreas.hansson@arm.com if (pmemAddr == (void *)MAP_FAILED) { 6511336Sandreas.hansson@arm.com perror("mmap"); 6610409Sandreas.hansson@arm.com fatal("Could not mmap!\n"); 6710409Sandreas.hansson@arm.com } 6810409Sandreas.hansson@arm.com 6911336Sandreas.hansson@arm.com //If requested, initialize all the memory to 0 7010409Sandreas.hansson@arm.com if(params()->zero) 7110409Sandreas.hansson@arm.com memset(pmemAddr, 0, params()->addrRange.size()); 7210409Sandreas.hansson@arm.com 7311336Sandreas.hansson@arm.com pagePtr = 0; 7410409Sandreas.hansson@arm.com} 758721SN/A 7611336Sandreas.hansson@arm.comvoid 778721SN/APhysicalMemory::init() 788721SN/A{ 798721SN/A if (!port) 808721SN/A panic("PhysicalMemory not connected to anything!"); 818721SN/A port->sendStatusChange(Port::RangeChange); 828721SN/A} 838721SN/A 848721SN/APhysicalMemory::~PhysicalMemory() 856024SN/A{ 866024SN/A if (pmemAddr) 878721SN/A munmap((char*)pmemAddr, params()->addrRange.size()); 888721SN/A //Remove memPorts? 8911530Sandreas.sandberg@arm.com} 9011530Sandreas.sandberg@arm.com 9111754Sandreas.hansson@arm.comAddr 9211754Sandreas.hansson@arm.comPhysicalMemory::new_page() 9311530Sandreas.sandberg@arm.com{ 9411530Sandreas.sandberg@arm.com Addr return_addr = pagePtr << LogVMPageSize; 9511530Sandreas.sandberg@arm.com return_addr += start(); 9611530Sandreas.sandberg@arm.com 9711530Sandreas.sandberg@arm.com ++pagePtr; 9811754Sandreas.hansson@arm.com return return_addr; 9911754Sandreas.hansson@arm.com} 1008721SN/A 1018721SN/Aint 1022968SN/APhysicalMemory::deviceBlockSize() 10310409Sandreas.hansson@arm.com{ 10411336Sandreas.hansson@arm.com //Can accept anysize request 10510409Sandreas.hansson@arm.com return 0; 10611336Sandreas.hansson@arm.com} 10710409Sandreas.hansson@arm.com 10810409Sandreas.hansson@arm.comTick 10911336Sandreas.hansson@arm.comPhysicalMemory::calculateLatency(PacketPtr pkt) 11011336Sandreas.hansson@arm.com{ 11110409Sandreas.hansson@arm.com return lat; 11210409Sandreas.hansson@arm.com} 11310409Sandreas.hansson@arm.com 11410409Sandreas.hansson@arm.com 11510409Sandreas.hansson@arm.com 11610409Sandreas.hansson@arm.com// Add load-locked to tracking list. Should only be called if the 11711754Sandreas.hansson@arm.com// operation is a load and the LOCKED flag is set. 11810409Sandreas.hansson@arm.comvoid 11910409Sandreas.hansson@arm.comPhysicalMemory::trackLoadLocked(Request *req) 12010409Sandreas.hansson@arm.com{ 12111336Sandreas.hansson@arm.com Addr paddr = LockedAddr::mask(req->getPaddr()); 12211754Sandreas.hansson@arm.com 12310409Sandreas.hansson@arm.com // first we check if we already have a locked addr for this 1246127SN/A // xc. Since each xc only gets one, we just update the 1256127SN/A // existing record with the new address. 1266127SN/A list<LockedAddr>::iterator i; 12711336Sandreas.hansson@arm.com 12811336Sandreas.hansson@arm.com for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) { 1298721SN/A if (i->matchesContext(req)) { 13010409Sandreas.hansson@arm.com DPRINTF(LLSC, "Modifying lock record: cpu %d thread %d addr %#x\n", 13110409Sandreas.hansson@arm.com req->getCpuNum(), req->getThreadNum(), paddr); 13210409Sandreas.hansson@arm.com i->addr = paddr; 13310409Sandreas.hansson@arm.com return; 13410409Sandreas.hansson@arm.com } 13510409Sandreas.hansson@arm.com } 13610409Sandreas.hansson@arm.com 13711336Sandreas.hansson@arm.com // no record for this xc: need to allocate a new one 13810409Sandreas.hansson@arm.com DPRINTF(LLSC, "Adding lock record: cpu %d thread %d addr %#x\n", 13910409Sandreas.hansson@arm.com req->getCpuNum(), req->getThreadNum(), paddr); 14010409Sandreas.hansson@arm.com lockedAddrList.push_front(LockedAddr(req)); 14110409Sandreas.hansson@arm.com} 14210409Sandreas.hansson@arm.com 14310409Sandreas.hansson@arm.com 14410409Sandreas.hansson@arm.com// Called on *writes* only... both regular stores and 14510409Sandreas.hansson@arm.com// store-conditional operations. Check for conventional stores which 14611336Sandreas.hansson@arm.com// conflict with locked addresses, and for success/failure of store 14710409Sandreas.hansson@arm.com// conditionals. 14811336Sandreas.hansson@arm.combool 1498721SN/APhysicalMemory::checkLockedAddrList(Request *req) 15011336Sandreas.hansson@arm.com{ 15111336Sandreas.hansson@arm.com Addr paddr = LockedAddr::mask(req->getPaddr()); 1528721SN/A bool isLocked = req->isLocked(); 15311336Sandreas.hansson@arm.com 1548721SN/A // Initialize return value. Non-conditional stores always 1558983Snate@binkert.org // succeed. Assume conditional stores will fail until proven 15611336Sandreas.hansson@arm.com // otherwise. 15711754Sandreas.hansson@arm.com bool success = !isLocked; 15811336Sandreas.hansson@arm.com 1598721SN/A // Iterate over list. Note that there could be multiple matching 16010409Sandreas.hansson@arm.com // records, as more than one context could have done a load locked 16111336Sandreas.hansson@arm.com // to this location. 16211336Sandreas.hansson@arm.com list<LockedAddr>::iterator i = lockedAddrList.begin(); 16311336Sandreas.hansson@arm.com 16411201Sandreas.hansson@arm.com while (i != lockedAddrList.end()) { 16511336Sandreas.hansson@arm.com 16611336Sandreas.hansson@arm.com if (i->addr == paddr) { 16711336Sandreas.hansson@arm.com // we have a matching address 16811201Sandreas.hansson@arm.com 16911336Sandreas.hansson@arm.com if (isLocked && i->matchesContext(req)) { 17011336Sandreas.hansson@arm.com // it's a store conditional, and as far as the memory 17111201Sandreas.hansson@arm.com // system can tell, the requesting context's lock is 17211201Sandreas.hansson@arm.com // still valid. 17311336Sandreas.hansson@arm.com DPRINTF(LLSC, "StCond success: cpu %d thread %d addr %#x\n", 17411336Sandreas.hansson@arm.com req->getCpuNum(), req->getThreadNum(), paddr); 17511336Sandreas.hansson@arm.com success = true; 17611754Sandreas.hansson@arm.com } 17711754Sandreas.hansson@arm.com 17811201Sandreas.hansson@arm.com // Get rid of our record of this lock and advance to next 17911201Sandreas.hansson@arm.com DPRINTF(LLSC, "Erasing lock record: cpu %d thread %d addr %#x\n", 18011336Sandreas.hansson@arm.com i->cpuNum, i->threadNum, paddr); 18111336Sandreas.hansson@arm.com i = lockedAddrList.erase(i); 18211336Sandreas.hansson@arm.com } 18311336Sandreas.hansson@arm.com else { 18411201Sandreas.hansson@arm.com // no match: advance to next record 18511201Sandreas.hansson@arm.com ++i; 18611201Sandreas.hansson@arm.com } 18711201Sandreas.hansson@arm.com } 18811201Sandreas.hansson@arm.com 18911687Sandreas.hansson@arm.com if (isLocked) { 19011201Sandreas.hansson@arm.com req->setExtraData(success ? 1 : 0); 19111687Sandreas.hansson@arm.com } 19211201Sandreas.hansson@arm.com 19311201Sandreas.hansson@arm.com return success; 19411201Sandreas.hansson@arm.com} 19511201Sandreas.hansson@arm.com 19611201Sandreas.hansson@arm.comvoid 19711201Sandreas.hansson@arm.comPhysicalMemory::doFunctionalAccess(PacketPtr pkt) 19811201Sandreas.hansson@arm.com{ 19911201Sandreas.hansson@arm.com assert(pkt->getAddr() >= start() && 20011201Sandreas.hansson@arm.com pkt->getAddr() + pkt->getSize() <= start() + size()); 20111201Sandreas.hansson@arm.com 20211201Sandreas.hansson@arm.com if (pkt->isRead()) { 20311201Sandreas.hansson@arm.com if (pkt->req->isLocked()) { 20411201Sandreas.hansson@arm.com trackLoadLocked(pkt->req); 20511201Sandreas.hansson@arm.com } 20611201Sandreas.hansson@arm.com memcpy(pkt->getPtr<uint8_t>(), pmemAddr + pkt->getAddr() - start(), 20711201Sandreas.hansson@arm.com pkt->getSize()); 20811201Sandreas.hansson@arm.com#if TRACING_ON 20911201Sandreas.hansson@arm.com switch (pkt->getSize()) { 21011201Sandreas.hansson@arm.com case sizeof(uint64_t): 21111201Sandreas.hansson@arm.com DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n", 21211201Sandreas.hansson@arm.com pkt->getSize(), pkt->getAddr(),pkt->get<uint64_t>()); 21311687Sandreas.hansson@arm.com break; 21411687Sandreas.hansson@arm.com case sizeof(uint32_t): 21511687Sandreas.hansson@arm.com DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n", 21611687Sandreas.hansson@arm.com pkt->getSize(), pkt->getAddr(),pkt->get<uint32_t>()); 21711336Sandreas.hansson@arm.com break; 21811201Sandreas.hansson@arm.com case sizeof(uint16_t): 21911336Sandreas.hansson@arm.com DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n", 22011754Sandreas.hansson@arm.com pkt->getSize(), pkt->getAddr(),pkt->get<uint16_t>()); 22111502SCurtis.Dunham@arm.com break; 22211754Sandreas.hansson@arm.com case sizeof(uint8_t): 22311502SCurtis.Dunham@arm.com DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n", 22411502SCurtis.Dunham@arm.com pkt->getSize(), pkt->getAddr(),pkt->get<uint8_t>()); 22511502SCurtis.Dunham@arm.com break; 22610585Sandreas.hansson@arm.com default: 22711754Sandreas.hansson@arm.com DPRINTF(MemoryAccess, "Read of size %i on address 0x%x\n", 22810585Sandreas.hansson@arm.com pkt->getSize(), pkt->getAddr()); 22910585Sandreas.hansson@arm.com } 23010585Sandreas.hansson@arm.com#endif 23110585Sandreas.hansson@arm.com } 23210585Sandreas.hansson@arm.com else if (pkt->isWrite()) { 23310585Sandreas.hansson@arm.com if (writeOK(pkt->req)) { 23410585Sandreas.hansson@arm.com memcpy(pmemAddr + pkt->getAddr() - start(), pkt->getPtr<uint8_t>(), 23511502SCurtis.Dunham@arm.com pkt->getSize()); 23611502SCurtis.Dunham@arm.com#if TRACING_ON 23711754Sandreas.hansson@arm.com switch (pkt->getSize()) { 23811502SCurtis.Dunham@arm.com case sizeof(uint64_t): 23911502SCurtis.Dunham@arm.com DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n", 24011606Sandreas.sandberg@arm.com pkt->getSize(), pkt->getAddr(),pkt->get<uint64_t>()); 24111606Sandreas.sandberg@arm.com break; 24211336Sandreas.hansson@arm.com case sizeof(uint32_t): 24311336Sandreas.hansson@arm.com DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n", 24411606Sandreas.sandberg@arm.com pkt->getSize(), pkt->getAddr(),pkt->get<uint32_t>()); 24511606Sandreas.sandberg@arm.com break; 24611606Sandreas.sandberg@arm.com case sizeof(uint16_t): 24711606Sandreas.sandberg@arm.com DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n", 24811606Sandreas.sandberg@arm.com pkt->getSize(), pkt->getAddr(),pkt->get<uint16_t>()); 24911606Sandreas.sandberg@arm.com break; 25011502SCurtis.Dunham@arm.com case sizeof(uint8_t): 25111502SCurtis.Dunham@arm.com DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n", 25211606Sandreas.sandberg@arm.com pkt->getSize(), pkt->getAddr(),pkt->get<uint8_t>()); 25311606Sandreas.sandberg@arm.com break; 25411336Sandreas.hansson@arm.com default: 25511336Sandreas.hansson@arm.com DPRINTF(MemoryAccess, "Write of size %i on address 0x%x\n", 25611606Sandreas.sandberg@arm.com pkt->getSize(), pkt->getAddr()); 25711606Sandreas.sandberg@arm.com } 25811606Sandreas.sandberg@arm.com#endif 25911606Sandreas.sandberg@arm.com } 26011606Sandreas.sandberg@arm.com } else if (pkt->isInvalidate()) { 26111606Sandreas.sandberg@arm.com //upgrade or invalidate 26211336Sandreas.hansson@arm.com pkt->flags |= SATISFIED; 26311336Sandreas.hansson@arm.com } else if (pkt->isReadWrite()) { 26411336Sandreas.hansson@arm.com IntReg overwrite_val; 26511336Sandreas.hansson@arm.com bool overwrite_mem; 26610585Sandreas.hansson@arm.com uint64_t condition_val64; 26710585Sandreas.hansson@arm.com uint32_t condition_val32; 26810585Sandreas.hansson@arm.com 26910585Sandreas.hansson@arm.com assert(sizeof(IntReg) >= pkt->getSize()); 27011336Sandreas.hansson@arm.com 27111336Sandreas.hansson@arm.com overwrite_mem = true; 27211336Sandreas.hansson@arm.com // keep a copy of our possible write value, and copy what is at the 27311336Sandreas.hansson@arm.com // memory address into the packet 27411336Sandreas.hansson@arm.com std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize()); 27511336Sandreas.hansson@arm.com std::memcpy(pkt->getPtr<uint8_t>(), pmemAddr + pkt->getAddr() - start(), 27611606Sandreas.sandberg@arm.com pkt->getSize()); 27711606Sandreas.sandberg@arm.com 27811336Sandreas.hansson@arm.com if (pkt->req->isCondSwap()) { 27911336Sandreas.hansson@arm.com if (pkt->getSize() == sizeof(uint64_t)) { 28011606Sandreas.sandberg@arm.com condition_val64 = pkt->req->getExtraData(); 28111606Sandreas.sandberg@arm.com overwrite_mem = !std::memcmp(&condition_val64, pmemAddr + 28211606Sandreas.sandberg@arm.com pkt->getAddr() - start(), sizeof(uint64_t)); 28311606Sandreas.sandberg@arm.com } else if (pkt->getSize() == sizeof(uint32_t)) { 28411606Sandreas.sandberg@arm.com condition_val32 = (uint32_t)pkt->req->getExtraData(); 28511606Sandreas.sandberg@arm.com overwrite_mem = !std::memcmp(&condition_val32, pmemAddr + 28610585Sandreas.hansson@arm.com pkt->getAddr() - start(), sizeof(uint32_t)); 28710585Sandreas.hansson@arm.com } else 28810585Sandreas.hansson@arm.com panic("Invalid size for conditional read/write\n"); 28910585Sandreas.hansson@arm.com } 29010585Sandreas.hansson@arm.com 29110585Sandreas.hansson@arm.com if (overwrite_mem) 29211606Sandreas.sandberg@arm.com std::memcpy(pmemAddr + pkt->getAddr() - start(), 29311606Sandreas.sandberg@arm.com &overwrite_val, pkt->getSize()); 29411754Sandreas.hansson@arm.com 29511336Sandreas.hansson@arm.com#if TRACING_ON 29611336Sandreas.hansson@arm.com switch (pkt->getSize()) { 29711336Sandreas.hansson@arm.com case sizeof(uint64_t): 29811336Sandreas.hansson@arm.com DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n", 29911336Sandreas.hansson@arm.com pkt->getSize(), pkt->getAddr(),pkt->get<uint64_t>()); 30010409Sandreas.hansson@arm.com DPRINTF(MemoryAccess, "New Data 0x%x %s conditional (0x%x) and %s \n", 30111336Sandreas.hansson@arm.com overwrite_mem, pkt->req->isCondSwap() ? "was" : "wasn't", 30210409Sandreas.hansson@arm.com condition_val64, overwrite_mem ? "happened" : "didn't happen"); 30310409Sandreas.hansson@arm.com break; 30410036SAli.Saidi@ARM.com case sizeof(uint32_t): 30510409Sandreas.hansson@arm.com DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n", 30610409Sandreas.hansson@arm.com pkt->getSize(), pkt->getAddr(),pkt->get<uint32_t>()); 30710409Sandreas.hansson@arm.com DPRINTF(MemoryAccess, "New Data 0x%x %s conditional (0x%x) and %s \n", 30810036SAli.Saidi@ARM.com overwrite_mem, pkt->req->isCondSwap() ? "was" : "wasn't", 30911336Sandreas.hansson@arm.com condition_val32, overwrite_mem ? "happened" : "didn't happen"); 31011336Sandreas.hansson@arm.com break; 31111754Sandreas.hansson@arm.com case sizeof(uint16_t): 31211336Sandreas.hansson@arm.com DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n", 31311336Sandreas.hansson@arm.com pkt->getSize(), pkt->getAddr(),pkt->get<uint16_t>()); 31411336Sandreas.hansson@arm.com DPRINTF(MemoryAccess, "New Data 0x%x wasn't conditional and happned\n", 31511336Sandreas.hansson@arm.com overwrite_mem); 31611336Sandreas.hansson@arm.com break; 31711336Sandreas.hansson@arm.com case sizeof(uint8_t): 31811336Sandreas.hansson@arm.com DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n", 31911336Sandreas.hansson@arm.com pkt->getSize(), pkt->getAddr(),pkt->get<uint8_t>()); 32011336Sandreas.hansson@arm.com DPRINTF(MemoryAccess, "New Data 0x%x wasn't conditional and happned\n", 32111336Sandreas.hansson@arm.com overwrite_mem); 32211336Sandreas.hansson@arm.com break; 32311336Sandreas.hansson@arm.com default: 32411336Sandreas.hansson@arm.com DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x\n", 32511336Sandreas.hansson@arm.com pkt->getSize(), pkt->getAddr()); 32611336Sandreas.hansson@arm.com } 32711336Sandreas.hansson@arm.com#endif 32811336Sandreas.hansson@arm.com } else { 32911336Sandreas.hansson@arm.com panic("unimplemented"); 33010409Sandreas.hansson@arm.com } 33110409Sandreas.hansson@arm.com 33210409Sandreas.hansson@arm.com pkt->result = Packet::Success; 33310409Sandreas.hansson@arm.com} 33410409Sandreas.hansson@arm.com 33510409Sandreas.hansson@arm.comPort * 3368721SN/APhysicalMemory::getPort(const std::string &if_name, int idx) 3378721SN/A{ 3388721SN/A if (if_name == "port" && idx == -1) { 3398721SN/A if (port != NULL) 3408983Snate@binkert.org panic("PhysicalMemory::getPort: additional port requested to memory!"); 3418983Snate@binkert.org port = new MemoryPort(name() + "-port", this); 34211336Sandreas.hansson@arm.com return port; 34311336Sandreas.hansson@arm.com } else if (if_name == "functional") { 3448721SN/A /* special port for functional writes at startup. And for memtester */ 3458721SN/A return new MemoryPort(name() + "-funcport", this); 3468721SN/A } else { 3478721SN/A panic("PhysicalMemory::getPort: unknown port %s requested", if_name); 34811336Sandreas.hansson@arm.com } 34910409Sandreas.hansson@arm.com} 3508721SN/A 35110409Sandreas.hansson@arm.comvoid 35210409Sandreas.hansson@arm.comPhysicalMemory::recvStatusChange(Port::Status status) 35310409Sandreas.hansson@arm.com{ 35410409Sandreas.hansson@arm.com} 35510409Sandreas.hansson@arm.com 35611336Sandreas.hansson@arm.comPhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, 35710409Sandreas.hansson@arm.com PhysicalMemory *_memory) 35810409Sandreas.hansson@arm.com : SimpleTimingPort(_name), memory(_memory) 35910409Sandreas.hansson@arm.com{ } 36010409Sandreas.hansson@arm.com 36110409Sandreas.hansson@arm.comvoid 3628721SN/APhysicalMemory::MemoryPort::recvStatusChange(Port::Status status) 36310409Sandreas.hansson@arm.com{ 3648721SN/A memory->recvStatusChange(status); 3658721SN/A} 3668721SN/A 3678721SN/Avoid 3688721SN/APhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp, 3698721SN/A AddrRangeList &snoop) 3708721SN/A{ 3718721SN/A memory->getAddressRanges(resp, snoop); 3726024SN/A} 3736024SN/A 3748721SN/Avoid 3758721SN/APhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) 37611530Sandreas.sandberg@arm.com{ 37711530Sandreas.sandberg@arm.com snoop.clear(); 37811754Sandreas.hansson@arm.com resp.clear(); 37911754Sandreas.hansson@arm.com resp.push_back(RangeSize(start(), 38011530Sandreas.sandberg@arm.com params()->addrRange.size())); 38111530Sandreas.sandberg@arm.com} 38211530Sandreas.sandberg@arm.com 38311530Sandreas.sandberg@arm.comint 38411530Sandreas.sandberg@arm.comPhysicalMemory::MemoryPort::deviceBlockSize() 38511754Sandreas.hansson@arm.com{ 38611754Sandreas.hansson@arm.com return memory->deviceBlockSize(); 3878721SN/A} 3888721SN/A 3892968SN/ATick 39010409Sandreas.hansson@arm.comPhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt) 39110409Sandreas.hansson@arm.com{ 39210409Sandreas.hansson@arm.com memory->doFunctionalAccess(pkt); 39310409Sandreas.hansson@arm.com return memory->calculateLatency(pkt); 39410409Sandreas.hansson@arm.com} 39510409Sandreas.hansson@arm.com 39610409Sandreas.hansson@arm.comvoid 39710409Sandreas.hansson@arm.comPhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt) 39810409Sandreas.hansson@arm.com{ 39910409Sandreas.hansson@arm.com //Since we are overriding the function, make sure to have the impl of the 40010409Sandreas.hansson@arm.com //check or functional accesses here. 40110409Sandreas.hansson@arm.com std::list<std::pair<Tick,PacketPtr> >::iterator i = transmitList.begin(); 40211754Sandreas.hansson@arm.com std::list<std::pair<Tick,PacketPtr> >::iterator end = transmitList.end(); 40310409Sandreas.hansson@arm.com bool notDone = true; 40410409Sandreas.hansson@arm.com 40511336Sandreas.hansson@arm.com while (i != end && notDone) { 40611754Sandreas.hansson@arm.com PacketPtr target = i->second; 40710409Sandreas.hansson@arm.com // If the target contains data, and it overlaps the 4086127SN/A // probed request, need to update data 4096127SN/A if (target->intersect(pkt)) 41010409Sandreas.hansson@arm.com notDone = fixPacket(pkt, target); 41110409Sandreas.hansson@arm.com i++; 4128721SN/A } 41310409Sandreas.hansson@arm.com 41410409Sandreas.hansson@arm.com // Default implementation of SimpleTimingPort::recvFunctional() 41510409Sandreas.hansson@arm.com // calls recvAtomic() and throws away the latency; we can save a 41610409Sandreas.hansson@arm.com // little here by just not calculating the latency. 41710409Sandreas.hansson@arm.com memory->doFunctionalAccess(pkt); 41810409Sandreas.hansson@arm.com} 41910409Sandreas.hansson@arm.com 42010409Sandreas.hansson@arm.comunsigned int 42110409Sandreas.hansson@arm.comPhysicalMemory::drain(Event *de) 42210409Sandreas.hansson@arm.com{ 42310409Sandreas.hansson@arm.com int count = port->drain(de); 42410409Sandreas.hansson@arm.com if (count) 42510409Sandreas.hansson@arm.com changeState(Draining); 42610409Sandreas.hansson@arm.com else 42710409Sandreas.hansson@arm.com changeState(Drained); 4288721SN/A return count; 42910409Sandreas.hansson@arm.com} 43010409Sandreas.hansson@arm.com 43110409Sandreas.hansson@arm.comvoid 43210409Sandreas.hansson@arm.comPhysicalMemory::serialize(ostream &os) 43310409Sandreas.hansson@arm.com{ 43410409Sandreas.hansson@arm.com gzFile compressedMem; 43510409Sandreas.hansson@arm.com string filename = name() + ".physmem"; 43610409Sandreas.hansson@arm.com 4378721SN/A SERIALIZE_SCALAR(filename); 43810409Sandreas.hansson@arm.com 43910409Sandreas.hansson@arm.com // write memory file 44011336Sandreas.hansson@arm.com string thefile = Checkpoint::dir() + "/" + filename.c_str(); 44110409Sandreas.hansson@arm.com int fd = creat(thefile.c_str(), 0664); 44211754Sandreas.hansson@arm.com if (fd < 0) { 44310409Sandreas.hansson@arm.com perror("creat"); 44411336Sandreas.hansson@arm.com fatal("Can't open physical memory checkpoint file '%s'\n", filename); 44511336Sandreas.hansson@arm.com } 44611336Sandreas.hansson@arm.com 44711201Sandreas.hansson@arm.com compressedMem = gzdopen(fd, "wb"); 44811201Sandreas.hansson@arm.com if (compressedMem == NULL) 44911336Sandreas.hansson@arm.com fatal("Insufficient memory to allocate compression state for %s\n", 45011336Sandreas.hansson@arm.com filename); 45111201Sandreas.hansson@arm.com 45211336Sandreas.hansson@arm.com if (gzwrite(compressedMem, pmemAddr, params()->addrRange.size()) != params()->addrRange.size()) { 45311336Sandreas.hansson@arm.com fatal("Write failed on physical memory checkpoint file '%s'\n", 45411201Sandreas.hansson@arm.com filename); 45511201Sandreas.hansson@arm.com } 45611336Sandreas.hansson@arm.com 45711336Sandreas.hansson@arm.com if (gzclose(compressedMem)) 45811201Sandreas.hansson@arm.com fatal("Close failed on physical memory checkpoint file '%s'\n", 45911754Sandreas.hansson@arm.com filename); 46011754Sandreas.hansson@arm.com} 46111201Sandreas.hansson@arm.com 46211201Sandreas.hansson@arm.comvoid 46311336Sandreas.hansson@arm.comPhysicalMemory::unserialize(Checkpoint *cp, const string §ion) 46411201Sandreas.hansson@arm.com{ 46511336Sandreas.hansson@arm.com gzFile compressedMem; 46611201Sandreas.hansson@arm.com long *tempPage; 46711201Sandreas.hansson@arm.com long *pmem_current; 46811201Sandreas.hansson@arm.com uint64_t curSize; 46911201Sandreas.hansson@arm.com uint32_t bytesRead; 47011201Sandreas.hansson@arm.com const int chunkSize = 16384; 47111201Sandreas.hansson@arm.com 47211687Sandreas.hansson@arm.com 47311201Sandreas.hansson@arm.com string filename; 47411687Sandreas.hansson@arm.com 47511201Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(filename); 47611201Sandreas.hansson@arm.com 47711201Sandreas.hansson@arm.com filename = cp->cptDir + "/" + filename; 47811201Sandreas.hansson@arm.com 47911201Sandreas.hansson@arm.com // mmap memoryfile 48011201Sandreas.hansson@arm.com int fd = open(filename.c_str(), O_RDONLY); 48111201Sandreas.hansson@arm.com if (fd < 0) { 48211201Sandreas.hansson@arm.com perror("open"); 48311201Sandreas.hansson@arm.com fatal("Can't open physical memory checkpoint file '%s'", filename); 48411201Sandreas.hansson@arm.com } 48511201Sandreas.hansson@arm.com 48611201Sandreas.hansson@arm.com compressedMem = gzdopen(fd, "rb"); 48711201Sandreas.hansson@arm.com if (compressedMem == NULL) 48811201Sandreas.hansson@arm.com fatal("Insufficient memory to allocate compression state for %s\n", 48911201Sandreas.hansson@arm.com filename); 49011201Sandreas.hansson@arm.com 49111201Sandreas.hansson@arm.com // unmap file that was mmaped in the constructor 49211201Sandreas.hansson@arm.com // This is done here to make sure that gzip and open don't muck with our 49311201Sandreas.hansson@arm.com // nice large space of memory before we reallocate it 49411201Sandreas.hansson@arm.com munmap((char*)pmemAddr, params()->addrRange.size()); 49511201Sandreas.hansson@arm.com 49611687Sandreas.hansson@arm.com pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE, 49711687Sandreas.hansson@arm.com MAP_ANON | MAP_PRIVATE, -1, 0); 49811687Sandreas.hansson@arm.com 49911687Sandreas.hansson@arm.com if (pmemAddr == (void *)MAP_FAILED) { 50011201Sandreas.hansson@arm.com perror("mmap"); 50111201Sandreas.hansson@arm.com fatal("Could not mmap physical memory!\n"); 50211336Sandreas.hansson@arm.com } 50311754Sandreas.hansson@arm.com 50411336Sandreas.hansson@arm.com curSize = 0; 50511754Sandreas.hansson@arm.com tempPage = (long*)malloc(chunkSize); 50611336Sandreas.hansson@arm.com if (tempPage == NULL) 50711336Sandreas.hansson@arm.com fatal("Unable to malloc memory to read file %s\n", filename); 50811336Sandreas.hansson@arm.com 50910409Sandreas.hansson@arm.com /* Only copy bytes that are non-zero, so we don't give the VM system hell */ 51011754Sandreas.hansson@arm.com while (curSize < params()->addrRange.size()) { 51111336Sandreas.hansson@arm.com bytesRead = gzread(compressedMem, tempPage, chunkSize); 51211336Sandreas.hansson@arm.com if (bytesRead != chunkSize && bytesRead != params()->addrRange.size() - curSize) 51310409Sandreas.hansson@arm.com fatal("Read failed on physical memory checkpoint file '%s'" 51410409Sandreas.hansson@arm.com " got %d bytes, expected %d or %d bytes\n", 51510409Sandreas.hansson@arm.com filename, bytesRead, chunkSize, params()->addrRange.size()-curSize); 51610409Sandreas.hansson@arm.com 51711336Sandreas.hansson@arm.com assert(bytesRead % sizeof(long) == 0); 51811336Sandreas.hansson@arm.com 51911754Sandreas.hansson@arm.com for (int x = 0; x < bytesRead/sizeof(long); x++) 52011336Sandreas.hansson@arm.com { 52111336Sandreas.hansson@arm.com if (*(tempPage+x) != 0) { 52211606Sandreas.sandberg@arm.com pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long)); 52311606Sandreas.sandberg@arm.com *pmem_current = *(tempPage+x); 52411336Sandreas.hansson@arm.com } 52511336Sandreas.hansson@arm.com } 52611606Sandreas.sandberg@arm.com curSize += bytesRead; 52711606Sandreas.sandberg@arm.com } 52811606Sandreas.sandberg@arm.com 52911606Sandreas.sandberg@arm.com free(tempPage); 53011606Sandreas.sandberg@arm.com 53111606Sandreas.sandberg@arm.com if (gzclose(compressedMem)) 53211336Sandreas.hansson@arm.com fatal("Close failed on physical memory checkpoint file '%s'\n", 53311336Sandreas.hansson@arm.com filename); 53411606Sandreas.sandberg@arm.com 53511606Sandreas.sandberg@arm.com} 53611336Sandreas.hansson@arm.com 53711336Sandreas.hansson@arm.com 53811606Sandreas.sandberg@arm.comBEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) 53911606Sandreas.sandberg@arm.com 54011606Sandreas.sandberg@arm.com Param<string> file; 54111606Sandreas.sandberg@arm.com Param<Range<Addr> > range; 54211606Sandreas.sandberg@arm.com Param<Tick> latency; 54311606Sandreas.sandberg@arm.com Param<bool> zero; 54411336Sandreas.hansson@arm.com 54511336Sandreas.hansson@arm.comEND_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) 54610409Sandreas.hansson@arm.com 54710409Sandreas.hansson@arm.comBEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) 54810409Sandreas.hansson@arm.com 54910409Sandreas.hansson@arm.com INIT_PARAM_DFLT(file, "memory mapped file", ""), 55010409Sandreas.hansson@arm.com INIT_PARAM(range, "Device Address Range"), 55110409Sandreas.hansson@arm.com INIT_PARAM(latency, "Memory access latency"), 55211336Sandreas.hansson@arm.com INIT_PARAM(zero, "Zero initialize memory") 55311336Sandreas.hansson@arm.com 55411336Sandreas.hansson@arm.comEND_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) 55511336Sandreas.hansson@arm.com 55610409Sandreas.hansson@arm.comCREATE_SIM_OBJECT(PhysicalMemory) 55710409Sandreas.hansson@arm.com{ 55811606Sandreas.sandberg@arm.com PhysicalMemory::Params *p = new PhysicalMemory::Params; 55911606Sandreas.sandberg@arm.com p->name = getInstanceName(); 56011336Sandreas.hansson@arm.com p->addrRange = range; 56111336Sandreas.hansson@arm.com p->latency = latency; 56211606Sandreas.sandberg@arm.com p->zero = zero; 56311606Sandreas.sandberg@arm.com return new PhysicalMemory(p); 56411606Sandreas.sandberg@arm.com} 56511606Sandreas.sandberg@arm.com 56611606Sandreas.sandberg@arm.comREGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory) 56711606Sandreas.sandberg@arm.com