abstract_mem.cc revision 9203
12SN/A/* 211856Sbrandon.potter@amd.com * Copyright (c) 2010-2012 ARM Limited 31762SN/A * All rights reserved 42SN/A * 52SN/A * The license below extends only to copyright in the software and shall 62SN/A * not be construed as granting a license to any other intellectual 72SN/A * property including but not limited to intellectual property relating 82SN/A * to a hardware implementation of the functionality of the software 92SN/A * licensed hereunder. You may use the software subject to the license 102SN/A * terms below provided that you ensure that this notice is replicated 112SN/A * unmodified and in its entirety in all distributions of the software, 122SN/A * modified or unmodified, in source code or in binary form. 132SN/A * 142SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan 152SN/A * All rights reserved. 162SN/A * 172SN/A * Redistribution and use in source and binary forms, with or without 182SN/A * modification, are permitted provided that the following conditions are 192SN/A * met: redistributions of source code must retain the above copyright 202SN/A * notice, this list of conditions and the following disclaimer; 212SN/A * redistributions in binary form must reproduce the above copyright 222SN/A * notice, this list of conditions and the following disclaimer in the 232SN/A * documentation and/or other materials provided with the distribution; 242SN/A * neither the name of the copyright holders nor the names of its 252SN/A * contributors may be used to endorse or promote products derived from 262SN/A * this software without specific prior written permission. 272SN/A * 282665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292665Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302665Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3111856Sbrandon.potter@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 322SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34360SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35360SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3711854Sbrandon.potter@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3811854Sbrandon.potter@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3911800Sbrandon.potter@amd.com * 404117Sgblack@eecs.umich.edu * Authors: Ron Dreslinski 41180SN/A * Ali Saidi 422SN/A * Andreas Hansson 436329Sgblack@eecs.umich.edu */ 442378SN/A 456214Snate@binkert.org#include <sys/mman.h> 466658Snate@binkert.org#include <sys/types.h> 478852Sandreas.hansson@arm.com#include <sys/user.h> 4811856Sbrandon.potter@amd.com#include <fcntl.h> 4910930Sbrandon.potter@amd.com#include <unistd.h> 5011905SBrandon.Potter@amd.com#include <zlib.h> 5156SN/A 522SN/A#include <cerrno> 538737Skoansin.tan@gmail.com#include <cstdio> 5411800Sbrandon.potter@amd.com#include <climits> 5511800Sbrandon.potter@amd.com#include <iostream> 5611851Sbrandon.potter@amd.com#include <string> 5712448Sgabeblack@google.com 585154Sgblack@eecs.umich.edu#include "arch/registers.hh" 5911800Sbrandon.potter@amd.com#include "config/the_isa.hh" 605154Sgblack@eecs.umich.edu#include "debug/LLSC.hh" 612680Sktlim@umich.edu#include "debug/MemoryAccess.hh" 622378SN/A#include "mem/abstract_mem.hh" 632SN/A#include "mem/packet_access.hh" 642SN/A#include "sim/system.hh" 652SN/A 6612448Sgabeblack@google.comusing namespace std; 6712431Sgabeblack@google.com 682SN/AAbstractMemory::AbstractMemory(const Params *p) : 6911854Sbrandon.potter@amd.com MemObject(p), range(params()->range), pmemAddr(NULL), 7011854Sbrandon.potter@amd.com confTableReported(p->conf_table_reported), inAddrMap(p->in_addr_map), 712SN/A _system(NULL) 7211169Sandreas.hansson@arm.com{ 7311168Sandreas.hansson@arm.com if (size() % TheISA::PageBytes != 0) 7410905Sandreas.sandberg@arm.com panic("Memory Size not divisible by page size\n"); 7512044Sgabeblack@google.com 7613557Sgabeblack@google.com if (params()->null) 7713557Sgabeblack@google.com return; 7813557Sgabeblack@google.com 7911854Sbrandon.potter@amd.com if (params()->file == "") { 8011854Sbrandon.potter@amd.com int map_flags = MAP_ANON | MAP_PRIVATE; 8111854Sbrandon.potter@amd.com pmemAddr = (uint8_t *)mmap(NULL, size(), 822SN/A PROT_READ | PROT_WRITE, map_flags, -1, 0); 8311854Sbrandon.potter@amd.com } else { 8411854Sbrandon.potter@amd.com int map_flags = MAP_PRIVATE; 8511854Sbrandon.potter@amd.com int fd = open(params()->file.c_str(), O_RDONLY); 8611854Sbrandon.potter@amd.com long _size = lseek(fd, 0, SEEK_END); 8711854Sbrandon.potter@amd.com if (_size != range.size()) { 8811854Sbrandon.potter@amd.com warn("Specified size %d does not match file %s %d\n", range.size(), 8911885Sbrandon.potter@amd.com params()->file, _size); 9011885Sbrandon.potter@amd.com range = RangeSize(range.start, _size); 9111885Sbrandon.potter@amd.com } 9210554Salexandru.dutu@amd.com lseek(fd, 0, SEEK_SET); 9311854Sbrandon.potter@amd.com pmemAddr = (uint8_t *)mmap(NULL, roundUp(_size, sysconf(_SC_PAGESIZE)), 9411854Sbrandon.potter@amd.com PROT_READ | PROT_WRITE, map_flags, fd, 0); 9511854Sbrandon.potter@amd.com } 968852Sandreas.hansson@arm.com 9711854Sbrandon.potter@amd.com if (pmemAddr == (void *)MAP_FAILED) { 9811854Sbrandon.potter@amd.com perror("mmap"); 9911854Sbrandon.potter@amd.com if (params()->file == "") 10011854Sbrandon.potter@amd.com fatal("Could not mmap!\n"); 10111919SBrandon.Potter@amd.com else 10211854Sbrandon.potter@amd.com fatal("Could not find file: %s\n", params()->file); 10311854Sbrandon.potter@amd.com } 1048852Sandreas.hansson@arm.com 10511854Sbrandon.potter@amd.com //If requested, initialize all the memory to 0 10611854Sbrandon.potter@amd.com if (p->zero) 10711854Sbrandon.potter@amd.com memset(pmemAddr, 0, size()); 10811854Sbrandon.potter@amd.com} 10911854Sbrandon.potter@amd.com 11011854Sbrandon.potter@amd.com 11111854Sbrandon.potter@amd.comAbstractMemory::~AbstractMemory() 1125282Srstrong@cs.ucsd.edu{ 1132SN/A if (pmemAddr) 11411169Sandreas.hansson@arm.com munmap((char*)pmemAddr, size()); 1152SN/A} 1168601Ssteve.reinhardt@amd.com 1178601Ssteve.reinhardt@amd.comvoid 1188539Sgblack@eecs.umich.eduAbstractMemory::regStats() 1198539Sgblack@eecs.umich.edu{ 1208539Sgblack@eecs.umich.edu using namespace Stats; 1214434Ssaidi@eecs.umich.edu 12211854Sbrandon.potter@amd.com assert(system()); 12311854Sbrandon.potter@amd.com 12411854Sbrandon.potter@amd.com bytesRead 12511854Sbrandon.potter@amd.com .init(system()->maxMasters()) 12611854Sbrandon.potter@amd.com .name(name() + ".bytes_read") 12711854Sbrandon.potter@amd.com .desc("Number of bytes read from this memory") 12811854Sbrandon.potter@amd.com .flags(total | nozero | nonan) 12911854Sbrandon.potter@amd.com ; 13011854Sbrandon.potter@amd.com for (int i = 0; i < system()->maxMasters(); i++) { 13111854Sbrandon.potter@amd.com bytesRead.subname(i, system()->getMasterName(i)); 13211854Sbrandon.potter@amd.com } 13311854Sbrandon.potter@amd.com bytesInstRead 13411886Sbrandon.potter@amd.com .init(system()->maxMasters()) 13511886Sbrandon.potter@amd.com .name(name() + ".bytes_inst_read") 13611886Sbrandon.potter@amd.com .desc("Number of instructions bytes read from this memory") 13711886Sbrandon.potter@amd.com .flags(total | nozero | nonan) 13811886Sbrandon.potter@amd.com ; 13911886Sbrandon.potter@amd.com for (int i = 0; i < system()->maxMasters(); i++) { 14011886Sbrandon.potter@amd.com bytesInstRead.subname(i, system()->getMasterName(i)); 14111854Sbrandon.potter@amd.com } 14211854Sbrandon.potter@amd.com bytesWritten 14311854Sbrandon.potter@amd.com .init(system()->maxMasters()) 14411854Sbrandon.potter@amd.com .name(name() + ".bytes_written") 14511854Sbrandon.potter@amd.com .desc("Number of bytes written to this memory") 1469110Ssteve.reinhardt@amd.com .flags(total | nozero | nonan) 14710558Salexandru.dutu@amd.com ; 1489110Ssteve.reinhardt@amd.com for (int i = 0; i < system()->maxMasters(); i++) { 14910558Salexandru.dutu@amd.com bytesWritten.subname(i, system()->getMasterName(i)); 15010558Salexandru.dutu@amd.com } 1519110Ssteve.reinhardt@amd.com numReads 1529110Ssteve.reinhardt@amd.com .init(system()->maxMasters()) 1539110Ssteve.reinhardt@amd.com .name(name() + ".num_reads") 1549110Ssteve.reinhardt@amd.com .desc("Number of read requests responded to by this memory") 15510558Salexandru.dutu@amd.com .flags(total | nozero | nonan) 1569110Ssteve.reinhardt@amd.com ; 1579110Ssteve.reinhardt@amd.com for (int i = 0; i < system()->maxMasters(); i++) { 1589110Ssteve.reinhardt@amd.com numReads.subname(i, system()->getMasterName(i)); 15910558Salexandru.dutu@amd.com } 1609110Ssteve.reinhardt@amd.com numWrites 16111886Sbrandon.potter@amd.com .init(system()->maxMasters()) 16211886Sbrandon.potter@amd.com .name(name() + ".num_writes") 16311886Sbrandon.potter@amd.com .desc("Number of write requests responded to by this memory") 16412141Sspwilson2@wisc.edu .flags(total | nozero | nonan) 16513557Sgabeblack@google.com ; 16611886Sbrandon.potter@amd.com for (int i = 0; i < system()->maxMasters(); i++) { 16711854Sbrandon.potter@amd.com numWrites.subname(i, system()->getMasterName(i)); 16811854Sbrandon.potter@amd.com } 16911854Sbrandon.potter@amd.com numOther 17011854Sbrandon.potter@amd.com .init(system()->maxMasters()) 17111854Sbrandon.potter@amd.com .name(name() + ".num_other") 17211854Sbrandon.potter@amd.com .desc("Number of other requests responded to by this memory") 17311886Sbrandon.potter@amd.com .flags(total | nozero | nonan) 17411854Sbrandon.potter@amd.com ; 17511854Sbrandon.potter@amd.com for (int i = 0; i < system()->maxMasters(); i++) { 17611854Sbrandon.potter@amd.com numOther.subname(i, system()->getMasterName(i)); 17711854Sbrandon.potter@amd.com } 17812448Sgabeblack@google.com bwRead 17911854Sbrandon.potter@amd.com .name(name() + ".bw_read") 18011854Sbrandon.potter@amd.com .desc("Total read bandwidth from this memory (bytes/s)") 18111854Sbrandon.potter@amd.com .precision(0) 18211851Sbrandon.potter@amd.com .prereq(bytesRead) 18311851Sbrandon.potter@amd.com .flags(total | nozero | nonan) 18411851Sbrandon.potter@amd.com ; 18511851Sbrandon.potter@amd.com for (int i = 0; i < system()->maxMasters(); i++) { 18611851Sbrandon.potter@amd.com bwRead.subname(i, system()->getMasterName(i)); 18711851Sbrandon.potter@amd.com } 18811801Sbrandon.potter@amd.com 18911801Sbrandon.potter@amd.com bwInstRead 19011801Sbrandon.potter@amd.com .name(name() + ".bw_inst_read") 19111801Sbrandon.potter@amd.com .desc("Instruction read bandwidth from this memory (bytes/s)") 19211801Sbrandon.potter@amd.com .precision(0) 19311801Sbrandon.potter@amd.com .prereq(bytesInstRead) 19411801Sbrandon.potter@amd.com .flags(total | nozero | nonan) 19511801Sbrandon.potter@amd.com ; 19611801Sbrandon.potter@amd.com for (int i = 0; i < system()->maxMasters(); i++) { 19711885Sbrandon.potter@amd.com bwInstRead.subname(i, system()->getMasterName(i)); 19811885Sbrandon.potter@amd.com } 19911801Sbrandon.potter@amd.com bwWrite 20010496Ssteve.reinhardt@amd.com .name(name() + ".bw_write") 20110496Ssteve.reinhardt@amd.com .desc("Write bandwidth from this memory (bytes/s)") 20211856Sbrandon.potter@amd.com .precision(0) 20311856Sbrandon.potter@amd.com .prereq(bytesWritten) 20411886Sbrandon.potter@amd.com .flags(total | nozero | nonan) 20511886Sbrandon.potter@amd.com ; 20611905SBrandon.Potter@amd.com for (int i = 0; i < system()->maxMasters(); i++) { 20711886Sbrandon.potter@amd.com bwWrite.subname(i, system()->getMasterName(i)); 20811886Sbrandon.potter@amd.com } 20911886Sbrandon.potter@amd.com bwTotal 21011886Sbrandon.potter@amd.com .name(name() + ".bw_total") 21111886Sbrandon.potter@amd.com .desc("Total bandwidth to/from this memory (bytes/s)") 21211886Sbrandon.potter@amd.com .precision(0) 21311886Sbrandon.potter@amd.com .prereq(bwTotal) 21411886Sbrandon.potter@amd.com .flags(total | nozero | nonan) 21511886Sbrandon.potter@amd.com ; 2162SN/A for (int i = 0; i < system()->maxMasters(); i++) { 2172SN/A bwTotal.subname(i, system()->getMasterName(i)); 218360SN/A } 219 bwRead = bytesRead / simSeconds; 220 bwInstRead = bytesInstRead / simSeconds; 221 bwWrite = bytesWritten / simSeconds; 222 bwTotal = (bytesRead + bytesWritten) / simSeconds; 223} 224 225Range<Addr> 226AbstractMemory::getAddrRange() const 227{ 228 return range; 229} 230 231// Add load-locked to tracking list. Should only be called if the 232// operation is a load and the LLSC flag is set. 233void 234AbstractMemory::trackLoadLocked(PacketPtr pkt) 235{ 236 Request *req = pkt->req; 237 Addr paddr = LockedAddr::mask(req->getPaddr()); 238 239 // first we check if we already have a locked addr for this 240 // xc. Since each xc only gets one, we just update the 241 // existing record with the new address. 242 list<LockedAddr>::iterator i; 243 244 for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) { 245 if (i->matchesContext(req)) { 246 DPRINTF(LLSC, "Modifying lock record: context %d addr %#x\n", 247 req->contextId(), paddr); 248 i->addr = paddr; 249 return; 250 } 251 } 252 253 // no record for this xc: need to allocate a new one 254 DPRINTF(LLSC, "Adding lock record: context %d addr %#x\n", 255 req->contextId(), paddr); 256 lockedAddrList.push_front(LockedAddr(req)); 257} 258 259 260// Called on *writes* only... both regular stores and 261// store-conditional operations. Check for conventional stores which 262// conflict with locked addresses, and for success/failure of store 263// conditionals. 264bool 265AbstractMemory::checkLockedAddrList(PacketPtr pkt) 266{ 267 Request *req = pkt->req; 268 Addr paddr = LockedAddr::mask(req->getPaddr()); 269 bool isLLSC = pkt->isLLSC(); 270 271 // Initialize return value. Non-conditional stores always 272 // succeed. Assume conditional stores will fail until proven 273 // otherwise. 274 bool allowStore = !isLLSC; 275 276 // Iterate over list. Note that there could be multiple matching records, 277 // as more than one context could have done a load locked to this location. 278 // Only remove records when we succeed in finding a record for (xc, addr); 279 // then, remove all records with this address. Failed store-conditionals do 280 // not blow unrelated reservations. 281 list<LockedAddr>::iterator i = lockedAddrList.begin(); 282 283 if (isLLSC) { 284 while (i != lockedAddrList.end()) { 285 if (i->addr == paddr && i->matchesContext(req)) { 286 // it's a store conditional, and as far as the memory system can 287 // tell, the requesting context's lock is still valid. 288 DPRINTF(LLSC, "StCond success: context %d addr %#x\n", 289 req->contextId(), paddr); 290 allowStore = true; 291 break; 292 } 293 // If we didn't find a match, keep searching! Someone else may well 294 // have a reservation on this line here but we may find ours in just 295 // a little while. 296 i++; 297 } 298 req->setExtraData(allowStore ? 1 : 0); 299 } 300 // LLSCs that succeeded AND non-LLSC stores both fall into here: 301 if (allowStore) { 302 // We write address paddr. However, there may be several entries with a 303 // reservation on this address (for other contextIds) and they must all 304 // be removed. 305 i = lockedAddrList.begin(); 306 while (i != lockedAddrList.end()) { 307 if (i->addr == paddr) { 308 DPRINTF(LLSC, "Erasing lock record: context %d addr %#x\n", 309 i->contextId, paddr); 310 i = lockedAddrList.erase(i); 311 } else { 312 i++; 313 } 314 } 315 } 316 317 return allowStore; 318} 319 320 321#if TRACING_ON 322 323#define CASE(A, T) \ 324 case sizeof(T): \ 325 DPRINTF(MemoryAccess,"%s of size %i on address 0x%x data 0x%x\n", \ 326 A, pkt->getSize(), pkt->getAddr(), pkt->get<T>()); \ 327 break 328 329 330#define TRACE_PACKET(A) \ 331 do { \ 332 switch (pkt->getSize()) { \ 333 CASE(A, uint64_t); \ 334 CASE(A, uint32_t); \ 335 CASE(A, uint16_t); \ 336 CASE(A, uint8_t); \ 337 default: \ 338 DPRINTF(MemoryAccess, "%s of size %i on address 0x%x\n", \ 339 A, pkt->getSize(), pkt->getAddr()); \ 340 DDUMP(MemoryAccess, pkt->getPtr<uint8_t>(), pkt->getSize());\ 341 } \ 342 } while (0) 343 344#else 345 346#define TRACE_PACKET(A) 347 348#endif 349 350void 351AbstractMemory::access(PacketPtr pkt) 352{ 353 assert(pkt->getAddr() >= range.start && 354 (pkt->getAddr() + pkt->getSize() - 1) <= range.end); 355 356 if (pkt->memInhibitAsserted()) { 357 DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n", 358 pkt->getAddr()); 359 return; 360 } 361 362 uint8_t *hostAddr = pmemAddr + pkt->getAddr() - range.start; 363 364 if (pkt->cmd == MemCmd::SwapReq) { 365 TheISA::IntReg overwrite_val; 366 bool overwrite_mem; 367 uint64_t condition_val64; 368 uint32_t condition_val32; 369 370 if (!pmemAddr) 371 panic("Swap only works if there is real memory (i.e. null=False)"); 372 assert(sizeof(TheISA::IntReg) >= pkt->getSize()); 373 374 overwrite_mem = true; 375 // keep a copy of our possible write value, and copy what is at the 376 // memory address into the packet 377 std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize()); 378 std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 379 380 if (pkt->req->isCondSwap()) { 381 if (pkt->getSize() == sizeof(uint64_t)) { 382 condition_val64 = pkt->req->getExtraData(); 383 overwrite_mem = !std::memcmp(&condition_val64, hostAddr, 384 sizeof(uint64_t)); 385 } else if (pkt->getSize() == sizeof(uint32_t)) { 386 condition_val32 = (uint32_t)pkt->req->getExtraData(); 387 overwrite_mem = !std::memcmp(&condition_val32, hostAddr, 388 sizeof(uint32_t)); 389 } else 390 panic("Invalid size for conditional read/write\n"); 391 } 392 393 if (overwrite_mem) 394 std::memcpy(hostAddr, &overwrite_val, pkt->getSize()); 395 396 assert(!pkt->req->isInstFetch()); 397 TRACE_PACKET("Read/Write"); 398 numOther[pkt->req->masterId()]++; 399 } else if (pkt->isRead()) { 400 assert(!pkt->isWrite()); 401 if (pkt->isLLSC()) { 402 trackLoadLocked(pkt); 403 } 404 if (pmemAddr) 405 memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 406 TRACE_PACKET(pkt->req->isInstFetch() ? "IFetch" : "Read"); 407 numReads[pkt->req->masterId()]++; 408 bytesRead[pkt->req->masterId()] += pkt->getSize(); 409 if (pkt->req->isInstFetch()) 410 bytesInstRead[pkt->req->masterId()] += pkt->getSize(); 411 } else if (pkt->isWrite()) { 412 if (writeOK(pkt)) { 413 if (pmemAddr) 414 memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 415 assert(!pkt->req->isInstFetch()); 416 TRACE_PACKET("Write"); 417 numWrites[pkt->req->masterId()]++; 418 bytesWritten[pkt->req->masterId()] += pkt->getSize(); 419 } 420 } else if (pkt->isInvalidate()) { 421 // no need to do anything 422 } else { 423 panic("unimplemented"); 424 } 425 426 if (pkt->needsResponse()) { 427 pkt->makeResponse(); 428 } 429} 430 431void 432AbstractMemory::functionalAccess(PacketPtr pkt) 433{ 434 assert(pkt->getAddr() >= range.start && 435 (pkt->getAddr() + pkt->getSize() - 1) <= range.end); 436 437 uint8_t *hostAddr = pmemAddr + pkt->getAddr() - range.start; 438 439 if (pkt->isRead()) { 440 if (pmemAddr) 441 memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 442 TRACE_PACKET("Read"); 443 pkt->makeResponse(); 444 } else if (pkt->isWrite()) { 445 if (pmemAddr) 446 memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 447 TRACE_PACKET("Write"); 448 pkt->makeResponse(); 449 } else if (pkt->isPrint()) { 450 Packet::PrintReqState *prs = 451 dynamic_cast<Packet::PrintReqState*>(pkt->senderState); 452 assert(prs); 453 // Need to call printLabels() explicitly since we're not going 454 // through printObj(). 455 prs->printLabels(); 456 // Right now we just print the single byte at the specified address. 457 ccprintf(prs->os, "%s%#x\n", prs->curPrefix(), *hostAddr); 458 } else { 459 panic("AbstractMemory: unimplemented functional command %s", 460 pkt->cmdString()); 461 } 462} 463 464void 465AbstractMemory::serialize(ostream &os) 466{ 467 if (!pmemAddr) 468 return; 469 470 gzFile compressedMem; 471 string filename = name() + ".physmem"; 472 long _size = range.size(); 473 474 SERIALIZE_SCALAR(filename); 475 SERIALIZE_SCALAR(_size); 476 477 // write memory file 478 string thefile = Checkpoint::dir() + "/" + filename.c_str(); 479 int fd = creat(thefile.c_str(), 0664); 480 if (fd < 0) { 481 perror("creat"); 482 fatal("Can't open physical memory checkpoint file '%s'\n", filename); 483 } 484 485 compressedMem = gzdopen(fd, "wb"); 486 if (compressedMem == NULL) 487 fatal("Insufficient memory to allocate compression state for %s\n", 488 filename); 489 490 uint64_t pass_size = 0; 491 // gzwrite fails if (int)len < 0 (gzwrite returns int) 492 for (uint64_t written = 0; written < size(); written += pass_size) { 493 pass_size = (uint64_t)INT_MAX < (size() - written) ? 494 (uint64_t)INT_MAX : (size() - written); 495 496 if (gzwrite(compressedMem, pmemAddr + written, 497 (unsigned int) pass_size) != (int)pass_size) { 498 fatal("Write failed on physical memory checkpoint file '%s'\n", 499 filename); 500 } 501 } 502 503 if (gzclose(compressedMem)) 504 fatal("Close failed on physical memory checkpoint file '%s'\n", 505 filename); 506 507 list<LockedAddr>::iterator i = lockedAddrList.begin(); 508 509 vector<Addr> lal_addr; 510 vector<int> lal_cid; 511 while (i != lockedAddrList.end()) { 512 lal_addr.push_back(i->addr); 513 lal_cid.push_back(i->contextId); 514 i++; 515 } 516 arrayParamOut(os, "lal_addr", lal_addr); 517 arrayParamOut(os, "lal_cid", lal_cid); 518} 519 520void 521AbstractMemory::unserialize(Checkpoint *cp, const string §ion) 522{ 523 if (!pmemAddr) 524 return; 525 526 gzFile compressedMem; 527 long *tempPage; 528 long *pmem_current; 529 uint64_t curSize; 530 uint32_t bytesRead; 531 const uint32_t chunkSize = 16384; 532 533 string filename; 534 535 UNSERIALIZE_SCALAR(filename); 536 537 filename = cp->cptDir + "/" + filename; 538 539 // mmap memoryfile 540 int fd = open(filename.c_str(), O_RDONLY); 541 if (fd < 0) { 542 perror("open"); 543 fatal("Can't open physical memory checkpoint file '%s'", filename); 544 } 545 546 compressedMem = gzdopen(fd, "rb"); 547 if (compressedMem == NULL) 548 fatal("Insufficient memory to allocate compression state for %s\n", 549 filename); 550 551 // unmap file that was mmapped in the constructor 552 // This is done here to make sure that gzip and open don't muck with our 553 // nice large space of memory before we reallocate it 554 munmap((char*)pmemAddr, size()); 555 556 long _size; 557 UNSERIALIZE_SCALAR(_size); 558 if (_size > params()->range.size()) 559 fatal("Memory size has changed! size %lld, param size %lld\n", 560 _size, params()->range.size()); 561 562 pmemAddr = (uint8_t *)mmap(NULL, size(), 563 PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); 564 565 if (pmemAddr == (void *)MAP_FAILED) { 566 perror("mmap"); 567 fatal("Could not mmap physical memory!\n"); 568 } 569 570 curSize = 0; 571 tempPage = (long*)malloc(chunkSize); 572 if (tempPage == NULL) 573 fatal("Unable to malloc memory to read file %s\n", filename); 574 575 /* Only copy bytes that are non-zero, so we don't give the VM system hell */ 576 while (curSize < size()) { 577 bytesRead = gzread(compressedMem, tempPage, chunkSize); 578 if (bytesRead == 0) 579 break; 580 581 assert(bytesRead % sizeof(long) == 0); 582 583 for (uint32_t x = 0; x < bytesRead / sizeof(long); x++) 584 { 585 if (*(tempPage+x) != 0) { 586 pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long)); 587 *pmem_current = *(tempPage+x); 588 } 589 } 590 curSize += bytesRead; 591 } 592 593 free(tempPage); 594 595 if (gzclose(compressedMem)) 596 fatal("Close failed on physical memory checkpoint file '%s'\n", 597 filename); 598 599 vector<Addr> lal_addr; 600 vector<int> lal_cid; 601 arrayParamIn(cp, section, "lal_addr", lal_addr); 602 arrayParamIn(cp, section, "lal_cid", lal_cid); 603 for(int i = 0; i < lal_addr.size(); i++) 604 lockedAddrList.push_front(LockedAddr(lal_addr[i], lal_cid[i])); 605} 606