abstract_mem.cc revision 2391
16242Sgblack@eecs.umich.edu/* 27093Sgblack@eecs.umich.edu * Copyright (c) 2001-2005 The Regents of The University of Michigan 37093Sgblack@eecs.umich.edu * All rights reserved. 47093Sgblack@eecs.umich.edu * 57093Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67093Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77093Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97093Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117093Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127093Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137093Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 146242Sgblack@eecs.umich.edu * this software without specific prior written permission. 156242Sgblack@eecs.umich.edu * 166242Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176242Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186242Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196242Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206242Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216242Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226242Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236242Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246242Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256242Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266242Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276242Sgblack@eecs.umich.edu */ 286242Sgblack@eecs.umich.edu 296242Sgblack@eecs.umich.edu#include <sys/types.h> 306242Sgblack@eecs.umich.edu#include <sys/mman.h> 316242Sgblack@eecs.umich.edu#include <errno.h> 326242Sgblack@eecs.umich.edu#include <fcntl.h> 336242Sgblack@eecs.umich.edu#include <unistd.h> 346242Sgblack@eecs.umich.edu#include <zlib.h> 356242Sgblack@eecs.umich.edu 366242Sgblack@eecs.umich.edu#include <cstdio> 376242Sgblack@eecs.umich.edu#include <iostream> 386242Sgblack@eecs.umich.edu#include <string> 396242Sgblack@eecs.umich.edu 406242Sgblack@eecs.umich.edu 416242Sgblack@eecs.umich.edu#include "base/misc.hh" 426242Sgblack@eecs.umich.edu#include "config/full_system.hh" 436242Sgblack@eecs.umich.edu#if FULL_SYSTEM 446242Sgblack@eecs.umich.edu#include "mem/functional/memory_control.hh" 456242Sgblack@eecs.umich.edu#endif 466242Sgblack@eecs.umich.edu#include "mem/functional/physical.hh" 476242Sgblack@eecs.umich.edu#include "sim/host.hh" 486242Sgblack@eecs.umich.edu#include "sim/builder.hh" 496242Sgblack@eecs.umich.edu#include "targetarch/isa_traits.hh" 506242Sgblack@eecs.umich.edu 516242Sgblack@eecs.umich.eduusing namespace std; 526242Sgblack@eecs.umich.edu 536242Sgblack@eecs.umich.edu#if FULL_SYSTEM 546242Sgblack@eecs.umich.eduPhysicalMemory::PhysicalMemory(const string &n, Range<Addr> range, 556242Sgblack@eecs.umich.edu MemoryController *mmu, const std::string &fname) 566242Sgblack@eecs.umich.edu : FunctionalMemory(n), base_addr(range.start), pmem_size(range.size()), 576242Sgblack@eecs.umich.edu pmem_addr(NULL) 586242Sgblack@eecs.umich.edu{ 596242Sgblack@eecs.umich.edu if (pmem_size % TheISA::PageBytes != 0) 606242Sgblack@eecs.umich.edu panic("Memory Size not divisible by page size\n"); 616242Sgblack@eecs.umich.edu 626242Sgblack@eecs.umich.edu mmu->add_child(this, range); 636242Sgblack@eecs.umich.edu 646242Sgblack@eecs.umich.edu int fd = -1; 657111Sgblack@eecs.umich.edu 666242Sgblack@eecs.umich.edu if (!fname.empty()) { 676242Sgblack@eecs.umich.edu fd = open(fname.c_str(), O_RDWR | O_CREAT, 0644); 686242Sgblack@eecs.umich.edu if (fd == -1) { 696242Sgblack@eecs.umich.edu perror("open"); 707408Sgblack@eecs.umich.edu fatal("Could not open physical memory file: %s\n", fname); 716735Sgblack@eecs.umich.edu } 726242Sgblack@eecs.umich.edu ftruncate(fd, pmem_size); 736242Sgblack@eecs.umich.edu } 746242Sgblack@eecs.umich.edu 756723Sgblack@eecs.umich.edu int map_flags = (fd == -1) ? (MAP_ANON | MAP_PRIVATE) : MAP_SHARED; 766242Sgblack@eecs.umich.edu pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE, 776242Sgblack@eecs.umich.edu map_flags, fd, 0); 786261Sgblack@eecs.umich.edu 796403Sgblack@eecs.umich.edu if (fd != -1) 806403Sgblack@eecs.umich.edu close(fd); 817783SGiacomo.Gabrielli@arm.com 827783SGiacomo.Gabrielli@arm.com if (pmem_addr == (void *)MAP_FAILED) { 836403Sgblack@eecs.umich.edu perror("mmap"); 847325Sgblack@eecs.umich.edu fatal("Could not mmap!\n"); 857325Sgblack@eecs.umich.edu } 867400SAli.Saidi@ARM.com 877350SAli.Saidi@ARM.com page_ptr = 0; 887259Sgblack@eecs.umich.edu} 897259Sgblack@eecs.umich.edu#endif 907259Sgblack@eecs.umich.edu 917259Sgblack@eecs.umich.eduPhysicalMemory::PhysicalMemory(const string &n) 927264Sgblack@eecs.umich.edu : FunctionalMemory(n), base_addr(0), pmem_addr(NULL) 937267Sgblack@eecs.umich.edu{ 947285Sgblack@eecs.umich.edu // Hardcoded to 128 MB for now. 957265Sgblack@eecs.umich.edu pmem_size = 1 << 27; 967266Sgblack@eecs.umich.edu 977266Sgblack@eecs.umich.edu if (pmem_size % TheISA::PageBytes != 0) 987266Sgblack@eecs.umich.edu panic("Memory Size not divisible by page size\n"); 997268Sgblack@eecs.umich.edu 1007272Sgblack@eecs.umich.edu int map_flags = MAP_ANON | MAP_PRIVATE; 1017272Sgblack@eecs.umich.edu pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE, 1027271Sgblack@eecs.umich.edu map_flags, -1, 0); 1037273Sgblack@eecs.umich.edu 1047287Sgblack@eecs.umich.edu if (pmem_addr == (void *)MAP_FAILED) { 1057287Sgblack@eecs.umich.edu perror("mmap"); 1067274Sgblack@eecs.umich.edu fatal("Could not mmap!\n"); 1077275Sgblack@eecs.umich.edu } 1087276Sgblack@eecs.umich.edu 1097286Sgblack@eecs.umich.edu page_ptr = 0; 1107297Sgblack@eecs.umich.edu} 1117297Sgblack@eecs.umich.edu 1127298Sgblack@eecs.umich.eduPhysicalMemory::~PhysicalMemory() 1137352Sgblack@eecs.umich.edu{ 1147352Sgblack@eecs.umich.edu if (pmem_addr) 1157354Sgblack@eecs.umich.edu munmap(pmem_addr, pmem_size); 1167353Sgblack@eecs.umich.edu} 1177355Sgblack@eecs.umich.edu 1187355Sgblack@eecs.umich.eduAddr 1197355Sgblack@eecs.umich.eduPhysicalMemory::new_page() 1207355Sgblack@eecs.umich.edu{ 1217355Sgblack@eecs.umich.edu Addr return_addr = page_ptr << LogVMPageSize; 1227355Sgblack@eecs.umich.edu return_addr += base_addr; 1237355Sgblack@eecs.umich.edu 1247355Sgblack@eecs.umich.edu ++page_ptr; 1257355Sgblack@eecs.umich.edu return return_addr; 1267355Sgblack@eecs.umich.edu} 1277355Sgblack@eecs.umich.edu 1287355Sgblack@eecs.umich.edu// 1297355Sgblack@eecs.umich.edu// little helper for better prot_* error messages 1307355Sgblack@eecs.umich.edu// 1317362Sgblack@eecs.umich.eduvoid 1327362Sgblack@eecs.umich.eduPhysicalMemory::prot_access_error(Addr addr, int size, const string &func) 1337362Sgblack@eecs.umich.edu{ 1347362Sgblack@eecs.umich.edu panic("invalid physical memory access!\n" 1357390Sgblack@eecs.umich.edu "%s: %s(addr=%#x, size=%d) out of range (max=%#x)\n", 1367404SAli.Saidi@ARM.com name(), func, addr, size, pmem_size - 1); 1377404SAli.Saidi@ARM.com} 1387404SAli.Saidi@ARM.com 1397404SAli.Saidi@ARM.comvoid 1407406SAli.Saidi@ARM.comPhysicalMemory::prot_read(Addr addr, uint8_t *p, int size) 1417406SAli.Saidi@ARM.com{ 1427406SAli.Saidi@ARM.com if (addr + size >= pmem_size) 1437436Sdam.sunwoo@arm.com prot_access_error(addr, size, "prot_read"); 1447436Sdam.sunwoo@arm.com 1457436Sdam.sunwoo@arm.com memcpy(p, pmem_addr + addr - base_addr, size); 1467436Sdam.sunwoo@arm.com} 1477436Sdam.sunwoo@arm.com 1487436Sdam.sunwoo@arm.comvoid 1497436Sdam.sunwoo@arm.comPhysicalMemory::prot_write(Addr addr, const uint8_t *p, int size) 1507436Sdam.sunwoo@arm.com{ 1517436Sdam.sunwoo@arm.com if (addr + size >= pmem_size) 1527583SAli.Saidi@arm.com prot_access_error(addr, size, "prot_write"); 1537583SAli.Saidi@arm.com 1547583SAli.Saidi@arm.com memcpy(pmem_addr + addr - base_addr, p, size); 1557583SAli.Saidi@arm.com} 1567583SAli.Saidi@arm.com 1577583SAli.Saidi@arm.comvoid 1587583SAli.Saidi@arm.comPhysicalMemory::prot_memset(Addr addr, uint8_t val, int size) 1597583SAli.Saidi@arm.com{ 1607583SAli.Saidi@arm.com if (addr + size >= pmem_size) 1617583SAli.Saidi@arm.com prot_access_error(addr, size, "prot_memset"); 1627583SAli.Saidi@arm.com 1637583SAli.Saidi@arm.com memset(pmem_addr + addr - base_addr, val, size); 1647583SAli.Saidi@arm.com} 1657583SAli.Saidi@arm.com 1667583SAli.Saidi@arm.comvoid 1677583SAli.Saidi@arm.comPhysicalMemory::serialize(ostream &os) 1687259Sgblack@eecs.umich.edu{ 1697406SAli.Saidi@ARM.com gzFile compressedMem; 1707259Sgblack@eecs.umich.edu string filename = name() + ".physmem"; 1717259Sgblack@eecs.umich.edu 1727259Sgblack@eecs.umich.edu SERIALIZE_SCALAR(pmem_size); 1737259Sgblack@eecs.umich.edu SERIALIZE_SCALAR(filename); 1747259Sgblack@eecs.umich.edu 1757259Sgblack@eecs.umich.edu // write memory file 1767259Sgblack@eecs.umich.edu string thefile = Checkpoint::dir() + "/" + filename.c_str(); 1777259Sgblack@eecs.umich.edu int fd = creat(thefile.c_str(), 0664); 1787259Sgblack@eecs.umich.edu if (fd < 0) { 1797259Sgblack@eecs.umich.edu perror("creat"); 1807259Sgblack@eecs.umich.edu fatal("Can't open physical memory checkpoint file '%s'\n", filename); 1817259Sgblack@eecs.umich.edu } 1827259Sgblack@eecs.umich.edu 1837259Sgblack@eecs.umich.edu compressedMem = gzdopen(fd, "wb"); 1847259Sgblack@eecs.umich.edu if (compressedMem == NULL) 1857259Sgblack@eecs.umich.edu fatal("Insufficient memory to allocate compression state for %s\n", 1867259Sgblack@eecs.umich.edu filename); 1877259Sgblack@eecs.umich.edu 1887259Sgblack@eecs.umich.edu if (gzwrite(compressedMem, pmem_addr, pmem_size) != pmem_size) { 1897351Sgblack@eecs.umich.edu fatal("Write failed on physical memory checkpoint file '%s'\n", 1907351Sgblack@eecs.umich.edu filename); 1917351Sgblack@eecs.umich.edu } 1927351Sgblack@eecs.umich.edu 1937351Sgblack@eecs.umich.edu if (gzclose(compressedMem)) 1948058SAli.Saidi@ARM.com fatal("Close failed on physical memory checkpoint file '%s'\n", 1957351Sgblack@eecs.umich.edu filename); 1967259Sgblack@eecs.umich.edu} 1977259Sgblack@eecs.umich.edu 1987259Sgblack@eecs.umich.eduvoid 1997259Sgblack@eecs.umich.eduPhysicalMemory::unserialize(Checkpoint *cp, const string §ion) 2007259Sgblack@eecs.umich.edu{ 2017259Sgblack@eecs.umich.edu gzFile compressedMem; 2027259Sgblack@eecs.umich.edu long *tempPage; 2036735Sgblack@eecs.umich.edu long *pmem_current; 2046261Sgblack@eecs.umich.edu uint64_t curSize; 2056261Sgblack@eecs.umich.edu uint32_t bytesRead; 2067259Sgblack@eecs.umich.edu const int chunkSize = 16384; 2077259Sgblack@eecs.umich.edu 2087259Sgblack@eecs.umich.edu 2096261Sgblack@eecs.umich.edu // unmap file that was mmaped in the constructor 2107408Sgblack@eecs.umich.edu munmap(pmem_addr, pmem_size); 2117259Sgblack@eecs.umich.edu 2127783SGiacomo.Gabrielli@arm.com string filename; 2137783SGiacomo.Gabrielli@arm.com 2147400SAli.Saidi@ARM.com UNSERIALIZE_SCALAR(pmem_size); 2157285Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(filename); 2167267Sgblack@eecs.umich.edu 2177287Sgblack@eecs.umich.edu filename = cp->cptDir + "/" + filename; 2187287Sgblack@eecs.umich.edu 2197297Sgblack@eecs.umich.edu // mmap memoryfile 2207297Sgblack@eecs.umich.edu int fd = open(filename.c_str(), O_RDONLY); 2217355Sgblack@eecs.umich.edu if (fd < 0) { 2227355Sgblack@eecs.umich.edu perror("open"); 2237355Sgblack@eecs.umich.edu fatal("Can't open physical memory checkpoint file '%s'", filename); 2247355Sgblack@eecs.umich.edu } 2257355Sgblack@eecs.umich.edu 2267390Sgblack@eecs.umich.edu compressedMem = gzdopen(fd, "rb"); 2277436Sdam.sunwoo@arm.com if (compressedMem == NULL) 2287436Sdam.sunwoo@arm.com fatal("Insufficient memory to allocate compression state for %s\n", 2297436Sdam.sunwoo@arm.com filename); 2307436Sdam.sunwoo@arm.com 2317583SAli.Saidi@arm.com 2327583SAli.Saidi@arm.com pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE, 2337583SAli.Saidi@arm.com MAP_ANON | MAP_PRIVATE, -1, 0); 2347583SAli.Saidi@arm.com 2357583SAli.Saidi@arm.com if (pmem_addr == (void *)MAP_FAILED) { 2367583SAli.Saidi@arm.com perror("mmap"); 2377406SAli.Saidi@ARM.com fatal("Could not mmap physical memory!\n"); 2387404SAli.Saidi@ARM.com } 2397583SAli.Saidi@arm.com 2407259Sgblack@eecs.umich.edu curSize = 0; 2417583SAli.Saidi@arm.com tempPage = (long*)malloc(chunkSize); 2427362Sgblack@eecs.umich.edu if (tempPage == NULL) 2437297Sgblack@eecs.umich.edu fatal("Unable to malloc memory to read file %s\n", filename); 2447272Sgblack@eecs.umich.edu 2457406SAli.Saidi@ARM.com /* Only copy bytes that are non-zero, so we don't give the VM system hell */ 2467404SAli.Saidi@ARM.com while (curSize < pmem_size) { 2477259Sgblack@eecs.umich.edu bytesRead = gzread(compressedMem, tempPage, chunkSize); 2486242Sgblack@eecs.umich.edu if (bytesRead != chunkSize && bytesRead != pmem_size - curSize) 2496242Sgblack@eecs.umich.edu fatal("Read failed on physical memory checkpoint file '%s'" 2506242Sgblack@eecs.umich.edu " got %d bytes, expected %d or %d bytes\n", 2516242Sgblack@eecs.umich.edu filename, bytesRead, chunkSize, pmem_size-curSize); 2526242Sgblack@eecs.umich.edu 2536242Sgblack@eecs.umich.edu assert(bytesRead % sizeof(long) == 0); 2546242Sgblack@eecs.umich.edu 2556242Sgblack@eecs.umich.edu for (int x = 0; x < bytesRead/sizeof(long); x++) 2566735Sgblack@eecs.umich.edu { 2576242Sgblack@eecs.umich.edu if (*(tempPage+x) != 0) { 2586242Sgblack@eecs.umich.edu pmem_current = (long*)(pmem_addr + curSize + x * sizeof(long)); 2596735Sgblack@eecs.umich.edu *pmem_current = *(tempPage+x); 2606242Sgblack@eecs.umich.edu } 2616242Sgblack@eecs.umich.edu } 2626242Sgblack@eecs.umich.edu curSize += bytesRead; 2636242Sgblack@eecs.umich.edu } 2646242Sgblack@eecs.umich.edu 2656242Sgblack@eecs.umich.edu free(tempPage); 2666242Sgblack@eecs.umich.edu 2676735Sgblack@eecs.umich.edu if (gzclose(compressedMem)) 2687408Sgblack@eecs.umich.edu fatal("Close failed on physical memory checkpoint file '%s'\n", 2697762SAli.Saidi@ARM.com filename); 2707762SAli.Saidi@ARM.com 2717762SAli.Saidi@ARM.com} 2727762SAli.Saidi@ARM.com 2737762SAli.Saidi@ARM.comBEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) 2747762SAli.Saidi@ARM.com 2757408Sgblack@eecs.umich.edu Param<string> file; 2767408Sgblack@eecs.umich.edu#if FULL_SYSTEM 2777408Sgblack@eecs.umich.edu SimObjectParam<MemoryController *> mmu; 2787408Sgblack@eecs.umich.edu#endif 2797408Sgblack@eecs.umich.edu Param<Range<Addr> > range; 2807408Sgblack@eecs.umich.edu 2817408Sgblack@eecs.umich.eduEND_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) 2826750Sgblack@eecs.umich.edu 2836750Sgblack@eecs.umich.eduBEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) 2846750Sgblack@eecs.umich.edu 2856750Sgblack@eecs.umich.edu INIT_PARAM_DFLT(file, "memory mapped file", ""), 2866735Sgblack@eecs.umich.edu#if FULL_SYSTEM 2877360Sgblack@eecs.umich.edu INIT_PARAM(mmu, "Memory Controller"), 2886735Sgblack@eecs.umich.edu#endif 2896735Sgblack@eecs.umich.edu INIT_PARAM(range, "Device Address Range") 2906735Sgblack@eecs.umich.edu 2916735Sgblack@eecs.umich.eduEND_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) 2926735Sgblack@eecs.umich.edu 2936735Sgblack@eecs.umich.eduCREATE_SIM_OBJECT(PhysicalMemory) 2947406SAli.Saidi@ARM.com{ 2956735Sgblack@eecs.umich.edu#if FULL_SYSTEM 2966735Sgblack@eecs.umich.edu if (mmu) { 2977360Sgblack@eecs.umich.edu return new PhysicalMemory(getInstanceName(), range, mmu, file); 2986735Sgblack@eecs.umich.edu } 2997360Sgblack@eecs.umich.edu#endif 3006735Sgblack@eecs.umich.edu 3016735Sgblack@eecs.umich.edu return new PhysicalMemory(getInstanceName()); 3026735Sgblack@eecs.umich.edu} 3036735Sgblack@eecs.umich.edu 3046735Sgblack@eecs.umich.eduREGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory) 3056735Sgblack@eecs.umich.edu