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 &section){    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 + -
显示快捷键?