physical.cc revision 2592
12SN/A/* 21762SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan 32SN/A * All rights reserved. 42SN/A * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu */ 282665Ssaidi@eecs.umich.edu 292665Ssaidi@eecs.umich.edu#include <sys/types.h> 302SN/A#include <sys/mman.h> 312SN/A#include <errno.h> 321388SN/A#include <fcntl.h> 332SN/A#include <unistd.h> 342SN/A#include <zlib.h> 352SN/A 361191SN/A#include <cstdio> 371191SN/A#include <iostream> 381191SN/A#include <string> 391388SN/A 401717SN/A 412651Ssaidi@eecs.umich.edu#include "base/misc.hh" 422680Sktlim@umich.edu#include "config/full_system.hh" 431977SN/A#include "mem/packet_impl.hh" 443144Shsul@eecs.umich.edu#include "mem/physical.hh" 45161SN/A#include "sim/host.hh" 462190SN/A#include "sim/builder.hh" 4756SN/A#include "sim/eventq.hh" 482190SN/A#include "arch/isa_traits.hh" 492SN/A 501062SN/A 511062SN/Ausing namespace std; 522359SN/Ausing namespace TheISA; 532359SN/A 542359SN/APhysicalMemory::MemResponseEvent::MemResponseEvent(Packet &pkt, MemoryPort* _m) 552SN/A : Event(&mainEventQueue, CPU_Tick_Pri), pkt(pkt), memoryPort(_m) 562SN/A{ 572SN/A 582SN/A this->setFlags(AutoDelete); 592SN/A} 602SN/A 612SN/Avoid 622SN/APhysicalMemory::MemResponseEvent::process() 632SN/A{ 643126Sktlim@umich.edu memoryPort->sendTiming(pkt); 653126Sktlim@umich.edu} 663126Sktlim@umich.edu 673126Sktlim@umich.educonst char * 683126Sktlim@umich.eduPhysicalMemory::MemResponseEvent::description() 693126Sktlim@umich.edu{ 703126Sktlim@umich.edu return "Physical Memory Timing Access respnse event"; 713126Sktlim@umich.edu} 723126Sktlim@umich.edu 732356SN/APhysicalMemory::PhysicalMemory(const string &n, Tick latency) 742356SN/A : MemObject(n),base_addr(0), pmem_addr(NULL), port(NULL), lat(latency) 752356SN/A{ 762367SN/A // Hardcoded to 128 MB for now. 772356SN/A pmem_size = 1 << 27; 782356SN/A 792367SN/A if (pmem_size % TheISA::PageBytes != 0) 802356SN/A panic("Memory Size not divisible by page size\n"); 812356SN/A 822356SN/A int map_flags = MAP_ANON | MAP_PRIVATE; 832367SN/A pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE, 842367SN/A map_flags, -1, 0); 852367SN/A 862367SN/A if (pmem_addr == (void *)MAP_FAILED) { 872356SN/A perror("mmap"); 882356SN/A fatal("Could not mmap!\n"); 892356SN/A } 902356SN/A 912356SN/A page_ptr = 0; 922356SN/A} 932356SN/A 942356SN/Avoid 952356SN/APhysicalMemory::init() 962356SN/A{ 971858SN/A if (!port) 981400SN/A panic("PhysicalMemory not connected to anything!"); 992881Srdreslin@umich.edu port->sendStatusChange(Port::RangeChange); 1001400SN/A} 1012SN/A 1021400SN/APhysicalMemory::~PhysicalMemory() 1032856Srdreslin@umich.edu{ 1042378SN/A if (pmem_addr) 1052SN/A munmap(pmem_addr, pmem_size); 1062SN/A //Remove memPorts? 1072359SN/A} 1082831Sksewell@umich.edu 1091062SN/AAddr 1102SN/APhysicalMemory::new_page() 1112SN/A{ 1122SN/A Addr return_addr = page_ptr << LogVMPageSize; 1132831Sksewell@umich.edu return_addr += base_addr; 1141062SN/A 1151062SN/A ++page_ptr; 1162SN/A return return_addr; 1172SN/A} 1182SN/A 1192SN/Aint 1201354SN/APhysicalMemory::deviceBlockSize() 1212SN/A{ 122503SN/A //Can accept anysize request 1232SN/A return 0; 1242SN/A} 1252SN/A 1262SN/Abool 1271400SN/APhysicalMemory::doTimingAccess (Packet &pkt, MemoryPort* memoryPort) 1282SN/A{ 1293144Shsul@eecs.umich.edu doFunctionalAccess(pkt); 1303144Shsul@eecs.umich.edu 1313144Shsul@eecs.umich.edu MemResponseEvent* response = new MemResponseEvent(pkt, memoryPort); 1322SN/A response->schedule(curTick + lat); 1331400SN/A 1342SN/A return true; 1352SN/A} 1362SN/A 1372SN/ATick 1382SN/APhysicalMemory::doAtomicAccess(Packet &pkt) 1392SN/A{ 140503SN/A doFunctionalAccess(pkt); 1412SN/A pkt.time = curTick + lat; 1421400SN/A return curTick + lat; 1432SN/A} 1442SN/A 145124SN/Avoid 1461354SN/APhysicalMemory::doFunctionalAccess(Packet &pkt) 147124SN/A{ 148124SN/A assert(pkt.addr + pkt.size < pmem_size); 149124SN/A 150124SN/A switch (pkt.cmd) { 151124SN/A case Read: 152124SN/A memcpy(pkt.getPtr<uint8_t>(), pmem_addr + pkt.addr - base_addr, 1531400SN/A pkt.size); 154124SN/A break; 1553144Shsul@eecs.umich.edu case Write: 1563144Shsul@eecs.umich.edu memcpy(pmem_addr + pkt.addr - base_addr, pkt.getPtr<uint8_t>(), 1573144Shsul@eecs.umich.edu pkt.size); 158124SN/A break; 1591400SN/A default: 160124SN/A panic("unimplemented"); 161124SN/A } 162124SN/A 163124SN/A pkt.result = Success; 164124SN/A} 165124SN/A 166124SN/APort * 167124SN/APhysicalMemory::getPort(const std::string &if_name) 1681400SN/A{ 169124SN/A if (if_name == "") { 170124SN/A if (port != NULL) 1711191SN/A panic("PhysicalMemory::getPort: additional port requested to memory!"); 1721400SN/A port = new MemoryPort(this); 1731388SN/A return port; 1741191SN/A } else if (if_name == "functional") { 1751400SN/A /* special port for functional writes at startup. */ 1761191SN/A return new MemoryPort(this); 1771400SN/A } else { 1781191SN/A panic("PhysicalMemory::getPort: unknown port %s requested", if_name); 1791191SN/A } 1801191SN/A} 1811191SN/A 1821191SN/Avoid 1831400SN/APhysicalMemory::recvStatusChange(Port::Status status) 1841191SN/A{ 1851191SN/A} 1861917SN/A 1871917SN/APhysicalMemory::MemoryPort::MemoryPort(PhysicalMemory *_memory) 1881917SN/A : memory(_memory) 1891917SN/A{ } 1901917SN/A 1912SN/Avoid 1922SN/APhysicalMemory::MemoryPort::recvStatusChange(Port::Status status) 1931917SN/A{ 1941917SN/A memory->recvStatusChange(status); 1951917SN/A} 1961917SN/A 1971917SN/Avoid 1982315SN/APhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp, 1991917SN/A AddrRangeList &snoop) 2001191SN/A{ 2011191SN/A memory->getAddressRanges(resp, snoop); 2021191SN/A} 2031191SN/A 2041191SN/Avoid 2051191SN/APhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) 2061191SN/A{ 2071191SN/A snoop.clear(); 2081191SN/A resp.clear(); 2091191SN/A resp.push_back(RangeSize(base_addr, pmem_size)); 2101191SN/A} 2111129SN/A 2121129SN/Aint 2131129SN/APhysicalMemory::MemoryPort::deviceBlockSize() 2141400SN/A{ 2152680Sktlim@umich.edu return memory->deviceBlockSize(); 2161129SN/A} 217180SN/A 2182SN/Abool 2191917SN/APhysicalMemory::MemoryPort::recvTiming(Packet &pkt) 2201917SN/A{ 2211917SN/A return memory->doTimingAccess(pkt, this); 2221917SN/A} 2231917SN/A 2241917SN/ATick 2252356SN/APhysicalMemory::MemoryPort::recvAtomic(Packet &pkt) 2262356SN/A{ 2272356SN/A return memory->doAtomicAccess(pkt); 2282356SN/A} 2292356SN/A 2301917SN/Avoid 2311917SN/APhysicalMemory::MemoryPort::recvFunctional(Packet &pkt) 2321917SN/A{ 2331917SN/A memory->doFunctionalAccess(pkt); 2342SN/A} 2352SN/A 236729SN/A 237707SN/A 238707SN/Avoid 239707SN/APhysicalMemory::serialize(ostream &os) 240707SN/A{ 241707SN/A gzFile compressedMem; 242707SN/A string filename = name() + ".physmem"; 2432680Sktlim@umich.edu 2442SN/A SERIALIZE_SCALAR(pmem_size); 2452SN/A SERIALIZE_SCALAR(filename); 2462SN/A 2472SN/A // write memory file 2482680Sktlim@umich.edu string thefile = Checkpoint::dir() + "/" + filename.c_str(); 2492SN/A int fd = creat(thefile.c_str(), 0664); 2502SN/A if (fd < 0) { 2512680Sktlim@umich.edu perror("creat"); 2522190SN/A fatal("Can't open physical memory checkpoint file '%s'\n", filename); 2532190SN/A } 2542190SN/A 2552SN/A compressedMem = gzdopen(fd, "wb"); 2562SN/A if (compressedMem == NULL) 257180SN/A fatal("Insufficient memory to allocate compression state for %s\n", 258180SN/A filename); 2592680Sktlim@umich.edu 260180SN/A if (gzwrite(compressedMem, pmem_addr, pmem_size) != pmem_size) { 2612680Sktlim@umich.edu fatal("Write failed on physical memory checkpoint file '%s'\n", 2622680Sktlim@umich.edu filename); 2632378SN/A } 2641858SN/A 2651806SN/A if (gzclose(compressedMem)) 2661806SN/A fatal("Close failed on physical memory checkpoint file '%s'\n", 2671806SN/A filename); 268180SN/A} 2692680Sktlim@umich.edu 270180SN/Avoid 2712680Sktlim@umich.eduPhysicalMemory::unserialize(Checkpoint *cp, const string §ion) 272180SN/A{ 273180SN/A gzFile compressedMem; 274180SN/A long *tempPage; 275180SN/A long *pmem_current; 276180SN/A uint64_t curSize; 277180SN/A uint32_t bytesRead; 2782798Sktlim@umich.edu const int chunkSize = 16384; 279180SN/A 2802359SN/A 2812359SN/A // unmap file that was mmaped in the constructor 2822359SN/A munmap(pmem_addr, pmem_size); 2832359SN/A 2842359SN/A string filename; 285180SN/A 286180SN/A UNSERIALIZE_SCALAR(pmem_size); 287180SN/A UNSERIALIZE_SCALAR(filename); 288180SN/A 289180SN/A filename = cp->cptDir + "/" + filename; 2902680Sktlim@umich.edu 291180SN/A // mmap memoryfile 2922680Sktlim@umich.edu int fd = open(filename.c_str(), O_RDONLY); 2932680Sktlim@umich.edu if (fd < 0) { 2942680Sktlim@umich.edu perror("open"); 295180SN/A fatal("Can't open physical memory checkpoint file '%s'", filename); 2962680Sktlim@umich.edu } 2972651Ssaidi@eecs.umich.edu 2982680Sktlim@umich.edu compressedMem = gzdopen(fd, "rb"); 2992651Ssaidi@eecs.umich.edu if (compressedMem == NULL) 3002680Sktlim@umich.edu fatal("Insufficient memory to allocate compression state for %s\n", 3011858SN/A filename); 3022680Sktlim@umich.edu 303180SN/A 3042680Sktlim@umich.edu pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE, 3052680Sktlim@umich.edu MAP_ANON | MAP_PRIVATE, -1, 0); 306180SN/A 3072359SN/A if (pmem_addr == (void *)MAP_FAILED) { 3082359SN/A perror("mmap"); 309180SN/A fatal("Could not mmap physical memory!\n"); 310605SN/A } 3111858SN/A 3123520Sgblack@eecs.umich.edu curSize = 0; 3132359SN/A tempPage = (long*)malloc(chunkSize); 3142254SN/A if (tempPage == NULL) 3152680Sktlim@umich.edu fatal("Unable to malloc memory to read file %s\n", filename); 3162680Sktlim@umich.edu 3172254SN/A /* Only copy bytes that are non-zero, so we don't give the VM system hell */ 3182359SN/A while (curSize < pmem_size) { 3192359SN/A bytesRead = gzread(compressedMem, tempPage, chunkSize); 3202359SN/A if (bytesRead != chunkSize && bytesRead != pmem_size - curSize) 321612SN/A fatal("Read failed on physical memory checkpoint file '%s'" 322180SN/A " got %d bytes, expected %d or %d bytes\n", 323180SN/A filename, bytesRead, chunkSize, pmem_size-curSize); 324180SN/A 3251858SN/A assert(bytesRead % sizeof(long) == 0); 3261917SN/A 3271917SN/A for (int x = 0; x < bytesRead/sizeof(long); x++) 3281917SN/A { 3291917SN/A if (*(tempPage+x) != 0) { 3301917SN/A pmem_current = (long*)(pmem_addr + curSize + x * sizeof(long)); 3311917SN/A *pmem_current = *(tempPage+x); 3321917SN/A } 3332680Sktlim@umich.edu } 3342680Sktlim@umich.edu curSize += bytesRead; 3352680Sktlim@umich.edu } 3361917SN/A 3372254SN/A free(tempPage); 3381917SN/A 3391917SN/A if (gzclose(compressedMem)) 3401917SN/A fatal("Close failed on physical memory checkpoint file '%s'\n", 3412SN/A filename); 3422SN/A 3432SN/A} 3441133SN/A 3453520Sgblack@eecs.umich.edu 3462SN/ABEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) 3472SN/A 3482SN/A Param<string> file; 3492SN/A Param<Range<Addr> > range; 3502SN/A Param<Tick> latency; 3513520Sgblack@eecs.umich.edu 3522SN/AEND_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) 3532SN/A 3542SN/ABEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) 3552SN/A 3562SN/A INIT_PARAM_DFLT(file, "memory mapped file", ""), 3573520Sgblack@eecs.umich.edu INIT_PARAM(range, "Device Address Range"), 3582SN/A INIT_PARAM(latency, "Memory access latency") 3592SN/A 360921SN/AEND_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) 361921SN/A 362921SN/ACREATE_SIM_OBJECT(PhysicalMemory) 363921SN/A{ 3643520Sgblack@eecs.umich.edu 365921SN/A return new PhysicalMemory(getInstanceName(), latency); 366921SN/A} 367921SN/A 368921SN/AREGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory) 369921SN/A