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 &section)
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