disk_image.cc
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· CC 代码 · 共 428 行
CC
428 行
/* * Copyright (c) 2001, 2002, 2003, 2004, 2005 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator. * * Permission is granted to use, copy, create derivative works and * redistribute this software and such derivative works for any * purpose, so long as the copyright notice above, this grant of * permission, and the disclaimer below appear in all copies made; and * so long as the name of The University of Michigan is not used in * any advertising or publicity pertaining to the use or distribution * of this software without specific, written prior authorization. * * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. * * Authors: Nathan L. Binkert *//** @file * Disk Image Definitions */#include <sys/types.h>#include <sys/uio.h>#include <errno.h>#include <unistd.h>#include <cstring>#include <fstream>#include <string>#include "base/callback.hh"#include "base/misc.hh"#include "base/trace.hh"#include "dev/disk_image.hh"#include "sim/sim_exit.hh"#include "sim/byteswap.hh"using namespace std;//////////////////////////////////////////////////////////////////////////// Raw Disk image//RawDiskImage::RawDiskImage(const Params* p) : DiskImage(p), disk_size(0){ open(p->image_file, p->read_only); }RawDiskImage::~RawDiskImage(){ close(); }voidRawDiskImage::open(const string &filename, bool rd_only){ if (!filename.empty()) { initialized = true; readonly = rd_only; file = filename; ios::openmode mode = ios::in | ios::binary; if (!readonly) mode |= ios::out; stream.open(file.c_str(), mode); if (!stream.is_open()) panic("Error opening %s", filename); }}voidRawDiskImage::close(){ stream.close();}off_tRawDiskImage::size() const{ if (disk_size == 0) { if (!stream.is_open()) panic("file not open!\n"); stream.seekg(0, ios::end); disk_size = stream.tellg(); } return disk_size / SectorSize;}off_tRawDiskImage::read(uint8_t *data, off_t offset) const{ if (!initialized) panic("RawDiskImage not initialized"); if (!stream.is_open()) panic("file not open!\n"); if (stream.seekg(offset * SectorSize, ios::beg) < 0) panic("Could not seek to location in file"); streampos pos = stream.tellg(); stream.read((char *)data, SectorSize); DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset); DDUMP(DiskImageRead, data, SectorSize); return stream.tellg() - pos;}off_tRawDiskImage::write(const uint8_t *data, off_t offset){ if (!initialized) panic("RawDiskImage not initialized"); if (readonly) panic("Cannot write to a read only disk image"); if (!stream.is_open()) panic("file not open!\n"); if (stream.seekp(offset * SectorSize, ios::beg) < 0) panic("Could not seek to location in file"); DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset); DDUMP(DiskImageWrite, data, SectorSize); streampos pos = stream.tellp(); stream.write((const char *)data, SectorSize); return stream.tellp() - pos;}RawDiskImage *RawDiskImageParams::create(){ return new RawDiskImage(this);}//////////////////////////////////////////////////////////////////////////// Copy on Write Disk image//const int CowDiskImage::VersionMajor = 1;const int CowDiskImage::VersionMinor = 0;class CowDiskCallback : public Callback{ private: CowDiskImage *image; public: CowDiskCallback(CowDiskImage *i) : image(i) {} void process() { image->save(); delete this; }};CowDiskImage::CowDiskImage(const Params *p) : DiskImage(p), filename(p->image_file), child(p->child), table(NULL){ if (filename.empty()) { init(p->table_size); } else { if (!open(filename)) { if (p->read_only) fatal("could not open read-only file"); init(p->table_size); } if (!p->read_only) registerExitCallback(new CowDiskCallback(this)); }}CowDiskImage::~CowDiskImage(){ SectorTable::iterator i = table->begin(); SectorTable::iterator end = table->end(); while (i != end) { delete (*i).second; ++i; }}voidSafeRead(ifstream &stream, void *data, int count){ stream.read((char *)data, count); if (!stream.is_open()) panic("file not open"); if (stream.eof()) panic("premature end-of-file"); if (stream.bad() || stream.fail()) panic("error reading cowdisk image");}template<class T>voidSafeRead(ifstream &stream, T &data){ SafeRead(stream, &data, sizeof(data));}template<class T>voidSafeReadSwap(ifstream &stream, T &data){ SafeRead(stream, &data, sizeof(data)); data = letoh(data); //is this the proper byte order conversion?}boolCowDiskImage::open(const string &file){ ifstream stream(file.c_str()); if (!stream.is_open()) return false; if (stream.fail() || stream.bad()) panic("Error opening %s", file); uint64_t magic; SafeRead(stream, magic); if (memcmp(&magic, "COWDISK!", sizeof(magic)) != 0) panic("Could not open %s: Invalid magic", file); uint32_t major, minor; SafeReadSwap(stream, major); SafeReadSwap(stream, minor); if (major != VersionMajor && minor != VersionMinor) panic("Could not open %s: invalid version %d.%d != %d.%d", file, major, minor, VersionMajor, VersionMinor); uint64_t sector_count; SafeReadSwap(stream, sector_count); table = new SectorTable(sector_count); for (uint64_t i = 0; i < sector_count; i++) { uint64_t offset; SafeReadSwap(stream, offset); Sector *sector = new Sector; SafeRead(stream, sector, sizeof(Sector)); assert(table->find(offset) == table->end()); (*table)[offset] = sector; } stream.close(); initialized = true; return true;}voidCowDiskImage::init(int hash_size){ table = new SectorTable(hash_size); initialized = true;}voidSafeWrite(ofstream &stream, const void *data, int count){ stream.write((const char *)data, count); if (!stream.is_open()) panic("file not open"); if (stream.eof()) panic("premature end-of-file"); if (stream.bad() || stream.fail()) panic("error reading cowdisk image");}template<class T>voidSafeWrite(ofstream &stream, const T &data){ SafeWrite(stream, &data, sizeof(data));}template<class T>voidSafeWriteSwap(ofstream &stream, const T &data){ T swappeddata = letoh(data); //is this the proper byte order conversion? SafeWrite(stream, &swappeddata, sizeof(data));}voidCowDiskImage::save(){ save(filename);}voidCowDiskImage::save(const string &file){ if (!initialized) panic("RawDiskImage not initialized"); ofstream stream(file.c_str()); if (!stream.is_open() || stream.fail() || stream.bad()) panic("Error opening %s", file); uint64_t magic; memcpy(&magic, "COWDISK!", sizeof(magic)); SafeWrite(stream, magic); SafeWriteSwap(stream, (uint32_t)VersionMajor); SafeWriteSwap(stream, (uint32_t)VersionMinor); SafeWriteSwap(stream, (uint64_t)table->size()); uint64_t size = table->size(); SectorTable::iterator iter = table->begin(); SectorTable::iterator end = table->end(); for (uint64_t i = 0; i < size; i++) { if (iter == end) panic("Incorrect Table Size during save of COW disk image"); SafeWriteSwap(stream, (uint64_t)(*iter).first); SafeWrite(stream, (*iter).second->data, sizeof(Sector)); ++iter; } stream.close();}voidCowDiskImage::writeback(){ SectorTable::iterator i = table->begin(); SectorTable::iterator end = table->end(); while (i != end) { child->write((*i).second->data, (*i).first); ++i; }}off_tCowDiskImage::size() const{ return child->size(); }off_tCowDiskImage::read(uint8_t *data, off_t offset) const{ if (!initialized) panic("CowDiskImage not initialized"); if (offset > size()) panic("access out of bounds"); SectorTable::const_iterator i = table->find(offset); if (i == table->end()) return child->read(data, offset); else { memcpy(data, (*i).second->data, SectorSize); DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset); DDUMP(DiskImageRead, data, SectorSize); return SectorSize; }}off_tCowDiskImage::write(const uint8_t *data, off_t offset){ if (!initialized) panic("RawDiskImage not initialized"); if (offset > size()) panic("access out of bounds"); SectorTable::iterator i = table->find(offset); if (i == table->end()) { Sector *sector = new Sector; memcpy(sector, data, SectorSize); table->insert(make_pair(offset, sector)); } else { memcpy((*i).second->data, data, SectorSize); } DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset); DDUMP(DiskImageWrite, data, SectorSize); return SectorSize;}voidCowDiskImage::serialize(ostream &os){ string cowFilename = name() + ".cow"; SERIALIZE_SCALAR(cowFilename); save(Checkpoint::dir() + "/" + cowFilename);}voidCowDiskImage::unserialize(Checkpoint *cp, const string §ion){ string cowFilename; UNSERIALIZE_SCALAR(cowFilename); cowFilename = cp->cptDir + "/" + cowFilename; open(cowFilename);}CowDiskImage *CowDiskImageParams::create(){ return new CowDiskImage(this);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?