physical.cc revision 3029
12391SN/A/* 22391SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan 32391SN/A * All rights reserved. 42391SN/A * 52391SN/A * Redistribution and use in source and binary forms, with or without 62391SN/A * modification, are permitted provided that the following conditions are 72391SN/A * met: redistributions of source code must retain the above copyright 82391SN/A * notice, this list of conditions and the following disclaimer; 92391SN/A * redistributions in binary form must reproduce the above copyright 102391SN/A * notice, this list of conditions and the following disclaimer in the 112391SN/A * documentation and/or other materials provided with the distribution; 122391SN/A * neither the name of the copyright holders nor the names of its 132391SN/A * contributors may be used to endorse or promote products derived from 142391SN/A * this software without specific prior written permission. 152391SN/A * 162391SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172391SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182391SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192391SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202391SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212391SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222391SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232391SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242391SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252391SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262391SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski 292914Ssaidi@eecs.umich.edu * Ali Saidi 302391SN/A */ 312391SN/A 322391SN/A#include <sys/types.h> 332391SN/A#include <sys/mman.h> 342391SN/A#include <errno.h> 352391SN/A#include <fcntl.h> 362391SN/A#include <unistd.h> 372391SN/A#include <zlib.h> 382391SN/A 392391SN/A#include <iostream> 402391SN/A#include <string> 412391SN/A 422391SN/A 432391SN/A#include "base/misc.hh" 442391SN/A#include "config/full_system.hh" 452592SN/A#include "mem/packet_impl.hh" 462394SN/A#include "mem/physical.hh" 472391SN/A#include "sim/host.hh" 482391SN/A#include "sim/builder.hh" 492415SN/A#include "sim/eventq.hh" 502423SN/A#include "arch/isa_traits.hh" 512391SN/A 522394SN/A 532391SN/Ausing namespace std; 542423SN/Ausing namespace TheISA; 552391SN/A 562415SN/A 573012Ssaidi@eecs.umich.eduPhysicalMemory::PhysicalMemory(Params *p) 583012Ssaidi@eecs.umich.edu : MemObject(p->name), pmemAddr(NULL), port(NULL), lat(p->latency), _params(p) 592391SN/A{ 603012Ssaidi@eecs.umich.edu if (params()->addrRange.size() % TheISA::PageBytes != 0) 612391SN/A panic("Memory Size not divisible by page size\n"); 622391SN/A 632391SN/A int map_flags = MAP_ANON | MAP_PRIVATE; 643012Ssaidi@eecs.umich.edu pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE, 652391SN/A map_flags, -1, 0); 662391SN/A 673012Ssaidi@eecs.umich.edu if (pmemAddr == (void *)MAP_FAILED) { 682391SN/A perror("mmap"); 692391SN/A fatal("Could not mmap!\n"); 702391SN/A } 712391SN/A 723012Ssaidi@eecs.umich.edu pagePtr = 0; 732391SN/A} 742391SN/A 752541SN/Avoid 762541SN/APhysicalMemory::init() 772541SN/A{ 782541SN/A if (!port) 792541SN/A panic("PhysicalMemory not connected to anything!"); 802541SN/A port->sendStatusChange(Port::RangeChange); 812541SN/A} 822541SN/A 832391SN/APhysicalMemory::~PhysicalMemory() 842391SN/A{ 853012Ssaidi@eecs.umich.edu if (pmemAddr) 863012Ssaidi@eecs.umich.edu munmap(pmemAddr, params()->addrRange.size()); 872416SN/A //Remove memPorts? 882391SN/A} 892391SN/A 902391SN/AAddr 912391SN/APhysicalMemory::new_page() 922391SN/A{ 933012Ssaidi@eecs.umich.edu Addr return_addr = pagePtr << LogVMPageSize; 943012Ssaidi@eecs.umich.edu return_addr += params()->addrRange.start; 952391SN/A 963012Ssaidi@eecs.umich.edu ++pagePtr; 972391SN/A return return_addr; 982391SN/A} 992391SN/A 1002408SN/Aint 1012408SN/APhysicalMemory::deviceBlockSize() 1022408SN/A{ 1032409SN/A //Can accept anysize request 1042409SN/A return 0; 1052408SN/A} 1062408SN/A 1073012Ssaidi@eecs.umich.eduTick 1083012Ssaidi@eecs.umich.eduPhysicalMemory::calculateLatency(Packet *pkt) 1093012Ssaidi@eecs.umich.edu{ 1103012Ssaidi@eecs.umich.edu return lat; 1113012Ssaidi@eecs.umich.edu} 1122413SN/A 1133029Ssaidi@eecs.umich.eduvoid 1142630SN/APhysicalMemory::doFunctionalAccess(Packet *pkt) 1152413SN/A{ 1163012Ssaidi@eecs.umich.edu assert(pkt->getAddr() + pkt->getSize() < params()->addrRange.size()); 1172414SN/A 1182630SN/A switch (pkt->cmd) { 1192641Sstever@eecs.umich.edu case Packet::ReadReq: 1202641Sstever@eecs.umich.edu memcpy(pkt->getPtr<uint8_t>(), 1213012Ssaidi@eecs.umich.edu pmemAddr + pkt->getAddr() - params()->addrRange.start, 1222641Sstever@eecs.umich.edu pkt->getSize()); 1232418SN/A break; 1242641Sstever@eecs.umich.edu case Packet::WriteReq: 1253012Ssaidi@eecs.umich.edu memcpy(pmemAddr + pkt->getAddr() - params()->addrRange.start, 1262641Sstever@eecs.umich.edu pkt->getPtr<uint8_t>(), 1272641Sstever@eecs.umich.edu pkt->getSize()); 1282631SN/A // temporary hack: will need to add real LL/SC implementation 1292631SN/A // for cacheless systems later. 1302631SN/A if (pkt->req->getFlags() & LOCKED) { 1312631SN/A pkt->req->setScResult(1); 1322631SN/A } 1332418SN/A break; 1342413SN/A default: 1352413SN/A panic("unimplemented"); 1362413SN/A } 1372420SN/A 1382641Sstever@eecs.umich.edu pkt->result = Packet::Success; 1392413SN/A} 1402413SN/A 1412413SN/APort * 1422738Sstever@eecs.umich.eduPhysicalMemory::getPort(const std::string &if_name, int idx) 1432413SN/A{ 1442738Sstever@eecs.umich.edu if (if_name == "port" && idx == -1) { 1452499SN/A if (port != NULL) 1462499SN/A panic("PhysicalMemory::getPort: additional port requested to memory!"); 1472640Sstever@eecs.umich.edu port = new MemoryPort(name() + "-port", this); 1482499SN/A return port; 1492519SN/A } else if (if_name == "functional") { 1502519SN/A /* special port for functional writes at startup. */ 1512640Sstever@eecs.umich.edu return new MemoryPort(name() + "-funcport", this); 1522462SN/A } else { 1532462SN/A panic("PhysicalMemory::getPort: unknown port %s requested", if_name); 1542462SN/A } 1552413SN/A} 1562413SN/A 1572413SN/Avoid 1582413SN/APhysicalMemory::recvStatusChange(Port::Status status) 1592413SN/A{ 1602413SN/A} 1612413SN/A 1622640Sstever@eecs.umich.eduPhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, 1632640Sstever@eecs.umich.edu PhysicalMemory *_memory) 1642914Ssaidi@eecs.umich.edu : SimpleTimingPort(_name), memory(_memory) 1652413SN/A{ } 1662413SN/A 1672413SN/Avoid 1682413SN/APhysicalMemory::MemoryPort::recvStatusChange(Port::Status status) 1692413SN/A{ 1702413SN/A memory->recvStatusChange(status); 1712413SN/A} 1722413SN/A 1732413SN/Avoid 1742522SN/APhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp, 1752522SN/A AddrRangeList &snoop) 1762413SN/A{ 1772522SN/A memory->getAddressRanges(resp, snoop); 1782497SN/A} 1792497SN/A 1802497SN/Avoid 1812522SN/APhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) 1822497SN/A{ 1832522SN/A snoop.clear(); 1842522SN/A resp.clear(); 1853012Ssaidi@eecs.umich.edu resp.push_back(RangeSize(params()->addrRange.start, params()->addrRange.size())); 1862413SN/A} 1872413SN/A 1882415SN/Aint 1892415SN/APhysicalMemory::MemoryPort::deviceBlockSize() 1902415SN/A{ 1912415SN/A return memory->deviceBlockSize(); 1922415SN/A} 1932413SN/A 1942413SN/Abool 1952630SN/APhysicalMemory::MemoryPort::recvTiming(Packet *pkt) 1962413SN/A{ 1972914Ssaidi@eecs.umich.edu assert(pkt->result != Packet::Nacked); 1982914Ssaidi@eecs.umich.edu 1993029Ssaidi@eecs.umich.edu Tick latency = memory->calculateLatency(pkt); 2003029Ssaidi@eecs.umich.edu 2013029Ssaidi@eecs.umich.edu memory->doFunctionalAccess(pkt); 2022914Ssaidi@eecs.umich.edu 2032914Ssaidi@eecs.umich.edu pkt->makeTimingResponse(); 2042914Ssaidi@eecs.umich.edu sendTiming(pkt, latency); 2052914Ssaidi@eecs.umich.edu 2062914Ssaidi@eecs.umich.edu return true; 2072413SN/A} 2082413SN/A 2092413SN/ATick 2102630SN/APhysicalMemory::MemoryPort::recvAtomic(Packet *pkt) 2112413SN/A{ 2123029Ssaidi@eecs.umich.edu memory->doFunctionalAccess(pkt); 2133029Ssaidi@eecs.umich.edu return memory->calculateLatency(pkt); 2142413SN/A} 2152413SN/A 2162413SN/Avoid 2172630SN/APhysicalMemory::MemoryPort::recvFunctional(Packet *pkt) 2182413SN/A{ 2192413SN/A memory->doFunctionalAccess(pkt); 2202413SN/A} 2212413SN/A 2222914Ssaidi@eecs.umich.eduunsigned int 2232914Ssaidi@eecs.umich.eduPhysicalMemory::drain(Event *de) 2242914Ssaidi@eecs.umich.edu{ 2252914Ssaidi@eecs.umich.edu int count = port->drain(de); 2262914Ssaidi@eecs.umich.edu if (count) 2272914Ssaidi@eecs.umich.edu changeState(Draining); 2282914Ssaidi@eecs.umich.edu else 2292914Ssaidi@eecs.umich.edu changeState(Drained); 2302914Ssaidi@eecs.umich.edu return count; 2312914Ssaidi@eecs.umich.edu} 2322413SN/A 2332391SN/Avoid 2342391SN/APhysicalMemory::serialize(ostream &os) 2352391SN/A{ 2362391SN/A gzFile compressedMem; 2372391SN/A string filename = name() + ".physmem"; 2382391SN/A 2392391SN/A SERIALIZE_SCALAR(filename); 2402391SN/A 2412391SN/A // write memory file 2422391SN/A string thefile = Checkpoint::dir() + "/" + filename.c_str(); 2432391SN/A int fd = creat(thefile.c_str(), 0664); 2442391SN/A if (fd < 0) { 2452391SN/A perror("creat"); 2462391SN/A fatal("Can't open physical memory checkpoint file '%s'\n", filename); 2472391SN/A } 2482391SN/A 2492391SN/A compressedMem = gzdopen(fd, "wb"); 2502391SN/A if (compressedMem == NULL) 2512391SN/A fatal("Insufficient memory to allocate compression state for %s\n", 2522391SN/A filename); 2532391SN/A 2543012Ssaidi@eecs.umich.edu if (gzwrite(compressedMem, pmemAddr, params()->addrRange.size()) != params()->addrRange.size()) { 2552391SN/A fatal("Write failed on physical memory checkpoint file '%s'\n", 2562391SN/A filename); 2572391SN/A } 2582391SN/A 2592391SN/A if (gzclose(compressedMem)) 2602391SN/A fatal("Close failed on physical memory checkpoint file '%s'\n", 2612391SN/A filename); 2622391SN/A} 2632391SN/A 2642391SN/Avoid 2652391SN/APhysicalMemory::unserialize(Checkpoint *cp, const string §ion) 2662391SN/A{ 2672391SN/A gzFile compressedMem; 2682391SN/A long *tempPage; 2692391SN/A long *pmem_current; 2702391SN/A uint64_t curSize; 2712391SN/A uint32_t bytesRead; 2722391SN/A const int chunkSize = 16384; 2732391SN/A 2742391SN/A 2752391SN/A string filename; 2762391SN/A 2772391SN/A UNSERIALIZE_SCALAR(filename); 2782391SN/A 2792391SN/A filename = cp->cptDir + "/" + filename; 2802391SN/A 2812391SN/A // mmap memoryfile 2822391SN/A int fd = open(filename.c_str(), O_RDONLY); 2832391SN/A if (fd < 0) { 2842391SN/A perror("open"); 2852391SN/A fatal("Can't open physical memory checkpoint file '%s'", filename); 2862391SN/A } 2872391SN/A 2882391SN/A compressedMem = gzdopen(fd, "rb"); 2892391SN/A if (compressedMem == NULL) 2902391SN/A fatal("Insufficient memory to allocate compression state for %s\n", 2912391SN/A filename); 2922391SN/A 2933012Ssaidi@eecs.umich.edu // unmap file that was mmaped in the constructor 2943012Ssaidi@eecs.umich.edu // This is done here to make sure that gzip and open don't muck with our 2953012Ssaidi@eecs.umich.edu // nice large space of memory before we reallocate it 2963012Ssaidi@eecs.umich.edu munmap(pmemAddr, params()->addrRange.size()); 2972391SN/A 2983012Ssaidi@eecs.umich.edu pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE, 2992391SN/A MAP_ANON | MAP_PRIVATE, -1, 0); 3002391SN/A 3013012Ssaidi@eecs.umich.edu if (pmemAddr == (void *)MAP_FAILED) { 3022391SN/A perror("mmap"); 3032391SN/A fatal("Could not mmap physical memory!\n"); 3042391SN/A } 3052391SN/A 3062391SN/A curSize = 0; 3072391SN/A tempPage = (long*)malloc(chunkSize); 3082391SN/A if (tempPage == NULL) 3092391SN/A fatal("Unable to malloc memory to read file %s\n", filename); 3102391SN/A 3112391SN/A /* Only copy bytes that are non-zero, so we don't give the VM system hell */ 3123012Ssaidi@eecs.umich.edu while (curSize < params()->addrRange.size()) { 3132391SN/A bytesRead = gzread(compressedMem, tempPage, chunkSize); 3143012Ssaidi@eecs.umich.edu if (bytesRead != chunkSize && bytesRead != params()->addrRange.size() - curSize) 3152391SN/A fatal("Read failed on physical memory checkpoint file '%s'" 3162391SN/A " got %d bytes, expected %d or %d bytes\n", 3173012Ssaidi@eecs.umich.edu filename, bytesRead, chunkSize, params()->addrRange.size()-curSize); 3182391SN/A 3192391SN/A assert(bytesRead % sizeof(long) == 0); 3202391SN/A 3212391SN/A for (int x = 0; x < bytesRead/sizeof(long); x++) 3222391SN/A { 3232391SN/A if (*(tempPage+x) != 0) { 3243012Ssaidi@eecs.umich.edu pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long)); 3252391SN/A *pmem_current = *(tempPage+x); 3262391SN/A } 3272391SN/A } 3282391SN/A curSize += bytesRead; 3292391SN/A } 3302391SN/A 3312391SN/A free(tempPage); 3322391SN/A 3332391SN/A if (gzclose(compressedMem)) 3342391SN/A fatal("Close failed on physical memory checkpoint file '%s'\n", 3352391SN/A filename); 3362391SN/A 3372391SN/A} 3382391SN/A 3392413SN/A 3402391SN/ABEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) 3412391SN/A 3422391SN/A Param<string> file; 3432391SN/A Param<Range<Addr> > range; 3442565SN/A Param<Tick> latency; 3452391SN/A 3462391SN/AEND_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) 3472391SN/A 3482391SN/ABEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) 3492391SN/A 3502391SN/A INIT_PARAM_DFLT(file, "memory mapped file", ""), 3512565SN/A INIT_PARAM(range, "Device Address Range"), 3522565SN/A INIT_PARAM(latency, "Memory access latency") 3532391SN/A 3542391SN/AEND_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) 3552391SN/A 3562391SN/ACREATE_SIM_OBJECT(PhysicalMemory) 3572391SN/A{ 3583012Ssaidi@eecs.umich.edu PhysicalMemory::Params *p = new PhysicalMemory::Params; 3593012Ssaidi@eecs.umich.edu p->name = getInstanceName(); 3603012Ssaidi@eecs.umich.edu p->addrRange = range; 3613012Ssaidi@eecs.umich.edu p->latency = latency; 3623012Ssaidi@eecs.umich.edu return new PhysicalMemory(p); 3632391SN/A} 3642391SN/A 3652391SN/AREGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory) 366