mm_disk.cc revision 10905:a6ca6831e775
15615Sgblack@eecs.umich.edu/*
25615Sgblack@eecs.umich.edu * Copyright (c) 2006 The Regents of The University of Michigan
35615Sgblack@eecs.umich.edu * All rights reserved.
47087Snate@binkert.org *
57087Snate@binkert.org * Redistribution and use in source and binary forms, with or without
67087Snate@binkert.org * modification, are permitted provided that the following conditions are
77087Snate@binkert.org * met: redistributions of source code must retain the above copyright
87087Snate@binkert.org * notice, this list of conditions and the following disclaimer;
97087Snate@binkert.org * redistributions in binary form must reproduce the above copyright
107087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
117087Snate@binkert.org * documentation and/or other materials provided with the distribution;
125615Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137087Snate@binkert.org * contributors may be used to endorse or promote products derived from
147087Snate@binkert.org * this software without specific prior written permission.
157087Snate@binkert.org *
167087Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177087Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187087Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197087Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207087Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215615Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227087Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235615Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245615Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255615Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265615Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275615Sgblack@eecs.umich.edu *
285615Sgblack@eecs.umich.edu * Authors: Ali Saidi
295615Sgblack@eecs.umich.edu */
305615Sgblack@eecs.umich.edu
315615Sgblack@eecs.umich.edu/** @file
325615Sgblack@eecs.umich.edu * This device acts as a disk similar to the memory mapped disk device
335615Sgblack@eecs.umich.edu * in legion. Any access is translated to an offset in the disk image.
345615Sgblack@eecs.umich.edu */
355615Sgblack@eecs.umich.edu
365615Sgblack@eecs.umich.edu#include <cstring>
375615Sgblack@eecs.umich.edu
385615Sgblack@eecs.umich.edu#include "base/trace.hh"
395615Sgblack@eecs.umich.edu#include "debug/IdeDisk.hh"
405615Sgblack@eecs.umich.edu#include "dev/sparc/mm_disk.hh"
415615Sgblack@eecs.umich.edu#include "dev/platform.hh"
425615Sgblack@eecs.umich.edu#include "mem/packet_access.hh"
435615Sgblack@eecs.umich.edu#include "mem/port.hh"
449338SAndreas.Sandberg@arm.com#include "sim/byteswap.hh"
455615Sgblack@eecs.umich.edu#include "sim/system.hh"
465615Sgblack@eecs.umich.edu
475615Sgblack@eecs.umich.eduMmDisk::MmDisk(const Params *p)
485615Sgblack@eecs.umich.edu    : BasicPioDevice(p, p->image->size() * SectorSize),
495615Sgblack@eecs.umich.edu      image(p->image), curSector((off_t)-1), dirty(false)
505615Sgblack@eecs.umich.edu{
515615Sgblack@eecs.umich.edu    std::memset(&diskData, 0, SectorSize);
525615Sgblack@eecs.umich.edu}
535615Sgblack@eecs.umich.edu
545615Sgblack@eecs.umich.eduTick
555615Sgblack@eecs.umich.eduMmDisk::read(PacketPtr pkt)
565615Sgblack@eecs.umich.edu{
575615Sgblack@eecs.umich.edu    Addr accessAddr;
585615Sgblack@eecs.umich.edu    off_t sector;
595615Sgblack@eecs.umich.edu    uint16_t d16;
605615Sgblack@eecs.umich.edu    uint32_t d32;
615615Sgblack@eecs.umich.edu    uint64_t d64;
625615Sgblack@eecs.umich.edu
635615Sgblack@eecs.umich.edu    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
645615Sgblack@eecs.umich.edu    accessAddr = pkt->getAddr() - pioAddr;
655615Sgblack@eecs.umich.edu
665615Sgblack@eecs.umich.edu    sector = accessAddr / SectorSize;
675615Sgblack@eecs.umich.edu
685615Sgblack@eecs.umich.edu    if (sector != curSector) {
695615Sgblack@eecs.umich.edu        if (dirty) {
705615Sgblack@eecs.umich.edu#ifndef NDEBUG
715615Sgblack@eecs.umich.edu            off_t bytes_written =
725615Sgblack@eecs.umich.edu#endif
735615Sgblack@eecs.umich.edu                image->write(diskData, curSector);
745615Sgblack@eecs.umich.edu            assert(bytes_written == SectorSize);
755615Sgblack@eecs.umich.edu        }
765615Sgblack@eecs.umich.edu#ifndef NDEBUG
775615Sgblack@eecs.umich.edu        off_t bytes_read =
785615Sgblack@eecs.umich.edu#endif
795615Sgblack@eecs.umich.edu            image->read(diskData, sector);
805615Sgblack@eecs.umich.edu        assert(bytes_read == SectorSize);
815615Sgblack@eecs.umich.edu        curSector = sector;
825615Sgblack@eecs.umich.edu    }
835615Sgblack@eecs.umich.edu    switch (pkt->getSize()) {
845615Sgblack@eecs.umich.edu      case sizeof(uint8_t):
855615Sgblack@eecs.umich.edu        pkt->set(diskData[accessAddr % SectorSize]);
865615Sgblack@eecs.umich.edu        DPRINTF(IdeDisk, "reading byte %#x value= %#x\n", accessAddr, diskData[accessAddr %
875615Sgblack@eecs.umich.edu                SectorSize]);
885615Sgblack@eecs.umich.edu        break;
895615Sgblack@eecs.umich.edu      case sizeof(uint16_t):
905615Sgblack@eecs.umich.edu        memcpy(&d16, diskData + (accessAddr % SectorSize), 2);
915615Sgblack@eecs.umich.edu        pkt->set(htobe(d16));
925615Sgblack@eecs.umich.edu        DPRINTF(IdeDisk, "reading word %#x value= %#x\n", accessAddr, d16);
935615Sgblack@eecs.umich.edu        break;
945615Sgblack@eecs.umich.edu      case sizeof(uint32_t):
955615Sgblack@eecs.umich.edu        memcpy(&d32, diskData + (accessAddr % SectorSize), 4);
965615Sgblack@eecs.umich.edu        pkt->set(htobe(d32));
979338SAndreas.Sandberg@arm.com        DPRINTF(IdeDisk, "reading dword %#x value= %#x\n", accessAddr, d32);
985615Sgblack@eecs.umich.edu        break;
995615Sgblack@eecs.umich.edu      case sizeof(uint64_t):
1005615Sgblack@eecs.umich.edu        memcpy(&d64, diskData + (accessAddr % SectorSize), 8);
1015615Sgblack@eecs.umich.edu        pkt->set(htobe(d64));
1025615Sgblack@eecs.umich.edu        DPRINTF(IdeDisk, "reading qword %#x value= %#x\n", accessAddr, d64);
1035615Sgblack@eecs.umich.edu        break;
1045615Sgblack@eecs.umich.edu      default:
1055615Sgblack@eecs.umich.edu        panic("Invalid access size\n");
1065615Sgblack@eecs.umich.edu    }
1075615Sgblack@eecs.umich.edu
1085615Sgblack@eecs.umich.edu    pkt->makeAtomicResponse();
1095615Sgblack@eecs.umich.edu    return pioDelay;
1105615Sgblack@eecs.umich.edu}
1115615Sgblack@eecs.umich.edu
1125615Sgblack@eecs.umich.eduTick
1135615Sgblack@eecs.umich.eduMmDisk::write(PacketPtr pkt)
1145615Sgblack@eecs.umich.edu{
1155615Sgblack@eecs.umich.edu    Addr accessAddr;
1165615Sgblack@eecs.umich.edu    off_t sector;
1175615Sgblack@eecs.umich.edu    uint16_t d16;
1185615Sgblack@eecs.umich.edu    uint32_t d32;
1195615Sgblack@eecs.umich.edu    uint64_t d64;
1209338SAndreas.Sandberg@arm.com
1215615Sgblack@eecs.umich.edu    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
1225615Sgblack@eecs.umich.edu    accessAddr = pkt->getAddr() - pioAddr;
1235615Sgblack@eecs.umich.edu
1245615Sgblack@eecs.umich.edu    sector = accessAddr / SectorSize;
1255615Sgblack@eecs.umich.edu
126    if (sector != curSector) {
127        if (dirty) {
128#ifndef NDEBUG
129            off_t bytes_written =
130#endif
131                image->write(diskData, curSector);
132            assert(bytes_written == SectorSize);
133        }
134#ifndef NDEBUG
135        off_t bytes_read =
136#endif
137            image->read(diskData,  sector);
138        assert(bytes_read == SectorSize);
139        curSector = sector;
140    }
141    dirty = true;
142
143    switch (pkt->getSize()) {
144      case sizeof(uint8_t):
145        diskData[accessAddr % SectorSize] = htobe(pkt->get<uint8_t>());
146        DPRINTF(IdeDisk, "writing byte %#x value= %#x\n", accessAddr, diskData[accessAddr %
147                SectorSize]);
148        break;
149      case sizeof(uint16_t):
150        d16 = htobe(pkt->get<uint16_t>());
151        memcpy(diskData + (accessAddr % SectorSize), &d16, 2);
152        DPRINTF(IdeDisk, "writing word %#x value= %#x\n", accessAddr, d16);
153        break;
154      case sizeof(uint32_t):
155        d32 = htobe(pkt->get<uint32_t>());
156        memcpy(diskData + (accessAddr % SectorSize), &d32, 4);
157        DPRINTF(IdeDisk, "writing dword %#x value= %#x\n", accessAddr, d32);
158        break;
159      case sizeof(uint64_t):
160        d64 = htobe(pkt->get<uint64_t>());
161        memcpy(diskData + (accessAddr % SectorSize), &d64, 8);
162        DPRINTF(IdeDisk, "writing qword %#x value= %#x\n", accessAddr, d64);
163        break;
164      default:
165        panic("Invalid access size\n");
166    }
167
168    pkt->makeAtomicResponse();
169    return pioDelay;
170}
171
172void
173MmDisk::serialize(CheckpointOut &cp) const
174{
175    // just write any dirty changes to the cow layer it will take care of
176    // serialization
177    if (dirty) {
178#ifndef NDEBUG
179        int bytes_read =
180#endif
181            image->write(diskData, curSector);
182        assert(bytes_read == SectorSize);
183    }
184}
185
186MmDisk *
187MmDiskParams::create()
188{
189    return new MmDisk(this);
190}
191