block.cc revision 14239
12689Sktlim@umich.edu/*
22689Sktlim@umich.edu * Copyright (c) 2014 ARM Limited
32689Sktlim@umich.edu * All rights reserved
42689Sktlim@umich.edu *
52689Sktlim@umich.edu * The license below extends only to copyright in the software and shall
62689Sktlim@umich.edu * not be construed as granting a license to any other intellectual
72689Sktlim@umich.edu * property including but not limited to intellectual property relating
82689Sktlim@umich.edu * to a hardware implementation of the functionality of the software
92689Sktlim@umich.edu * licensed hereunder.  You may use the software subject to the license
102689Sktlim@umich.edu * terms below provided that you ensure that this notice is replicated
112689Sktlim@umich.edu * unmodified and in its entirety in all distributions of the software,
122689Sktlim@umich.edu * modified or unmodified, in source code or in binary form.
132689Sktlim@umich.edu *
142689Sktlim@umich.edu * Redistribution and use in source and binary forms, with or without
152689Sktlim@umich.edu * modification, are permitted provided that the following conditions are
162689Sktlim@umich.edu * met: redistributions of source code must retain the above copyright
172689Sktlim@umich.edu * notice, this list of conditions and the following disclaimer;
182689Sktlim@umich.edu * redistributions in binary form must reproduce the above copyright
192689Sktlim@umich.edu * notice, this list of conditions and the following disclaimer in the
202689Sktlim@umich.edu * documentation and/or other materials provided with the distribution;
212689Sktlim@umich.edu * neither the name of the copyright holders nor the names of its
222689Sktlim@umich.edu * contributors may be used to endorse or promote products derived from
232689Sktlim@umich.edu * this software without specific prior written permission.
242689Sktlim@umich.edu *
252689Sktlim@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
262689Sktlim@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
272689Sktlim@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
282689Sktlim@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
292689Sktlim@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
302689Sktlim@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
312689Sktlim@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
322689Sktlim@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
332689Sktlim@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
342521SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
353960Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
364194Ssaidi@eecs.umich.edu *
371070SN/A * Authors: Andreas Sandberg
381070SN/A */
392521SN/A
402680Sktlim@umich.edu#include "dev/virtio/block.hh"
412521SN/A
422522SN/A#include "debug/VIOBlock.hh"
432037SN/A#include "params/VirtIOBlock.hh"
4456SN/A#include "sim/system.hh"
452378SN/A
462521SN/AVirtIOBlock::VirtIOBlock(Params *params)
472378SN/A    : VirtIODeviceBase(params, ID_BLOCK, sizeof(Config), 0),
484762Snate@binkert.org      qRequests(params->system->physProxy, params->queueSize, *this),
494762Snate@binkert.org      image(*params->image)
502378SN/A{
512SN/A    registerQueue(qRequests);
522SN/A
532107SN/A    config.capacity = image.size();
542SN/A}
552SN/A
562SN/A
572SN/AVirtIOBlock::~VirtIOBlock()
582SN/A{
591070SN/A}
602378SN/A
612378SN/Avoid
622521SN/AVirtIOBlock::readConfig(PacketPtr pkt, Addr cfgOffset)
632640Sstever@eecs.umich.edu{
642640Sstever@eecs.umich.edu    Config cfg_out;
652378SN/A    cfg_out.capacity = htov_legacy(config.capacity);
662378SN/A
672378SN/A    readConfigBlob(pkt, cfgOffset, (uint8_t *)&cfg_out);
682902Ssaidi@eecs.umich.edu}
692SN/A
701070SN/AVirtIOBlock::Status
711070SN/AVirtIOBlock::read(const BlkRequest &req, VirtDescriptor *desc_chain,
721070SN/A                  size_t off_data, size_t size)
732378SN/A{
741070SN/A    std::vector<uint8_t> data(size);
754838Ssaidi@eecs.umich.edu    uint64_t sector(req.sector);
764838Ssaidi@eecs.umich.edu
771070SN/A    DPRINTF(VIOBlock, "Read request starting @ sector %i (size: %i)\n",
782520SN/A            sector, size);
792520SN/A
802520SN/A    if (size % SectorSize != 0)
812520SN/A        panic("Unexpected request/sector size relationship\n");
822520SN/A
832520SN/A    for (Addr offset = 0; offset < size; offset += SectorSize) {
842520SN/A        if (image.read(&data[offset], sector) != SectorSize) {
852520SN/A            warn("Failed to read sector %i\n", sector);
862520SN/A            return S_IOERR;
872521SN/A        }
882521SN/A        ++sector;
892521SN/A    }
902521SN/A
912520SN/A    desc_chain->chainWrite(off_data, &data[0], size);
921070SN/A
932158SN/A    return S_OK;
941070SN/A}
954762Snate@binkert.org
963812Ssaidi@eecs.umich.eduVirtIOBlock::Status
973812Ssaidi@eecs.umich.eduVirtIOBlock::write(const BlkRequest &req, VirtDescriptor *desc_chain,
983812Ssaidi@eecs.umich.edu                  size_t off_data, size_t size)
993812Ssaidi@eecs.umich.edu{
1004762Snate@binkert.org    std::vector<uint8_t> data(size);
1013812Ssaidi@eecs.umich.edu    uint64_t sector(req.sector);
1024762Snate@binkert.org
1031070SN/A    DPRINTF(VIOBlock, "Write request starting @ sector %i (size: %i)\n",
1043812Ssaidi@eecs.umich.edu            sector, size);
1053812Ssaidi@eecs.umich.edu
1061070SN/A    if (size % SectorSize != 0)
1073812Ssaidi@eecs.umich.edu        panic("Unexpected request/sector size relationship\n");
1083812Ssaidi@eecs.umich.edu
1093812Ssaidi@eecs.umich.edu
1103812Ssaidi@eecs.umich.edu    desc_chain->chainRead(off_data, &data[0], size);
1111070SN/A
1123812Ssaidi@eecs.umich.edu    for (Addr offset = 0; offset < size; offset += SectorSize) {
1133812Ssaidi@eecs.umich.edu        if (image.write(&data[offset], sector) != SectorSize) {
1143812Ssaidi@eecs.umich.edu            warn("Failed to write sector %i\n", sector);
1151070SN/A            return S_IOERR;
1163812Ssaidi@eecs.umich.edu        }
1173812Ssaidi@eecs.umich.edu        ++sector;
1181070SN/A    }
1193812Ssaidi@eecs.umich.edu
1203812Ssaidi@eecs.umich.edu    return S_OK;
1211074SN/A
1223812Ssaidi@eecs.umich.edu}
1233812Ssaidi@eecs.umich.edu
1241074SN/Avoid
1253812Ssaidi@eecs.umich.eduVirtIOBlock::RequestQueue::onNotifyDescriptor(VirtDescriptor *desc)
1263812Ssaidi@eecs.umich.edu{
1273812Ssaidi@eecs.umich.edu    DPRINTF(VIOBlock, "Got input data descriptor (len: %i)\n",
1283812Ssaidi@eecs.umich.edu            desc->size());
1293812Ssaidi@eecs.umich.edu    /*
1302378SN/A     * Read the request structure and do endian conversion if
1312378SN/A     * necessary.
1321070SN/A     */
133878SN/A    BlkRequest req;
1342SN/A    desc->chainRead(0, (uint8_t *)&req, sizeof(req));
1352SN/A    req.type = htov_legacy(req.type);
1362SN/A    req.sector = htov_legacy(req.sector);
1372SN/A
1382378SN/A    Status status;
1391070SN/A    const size_t data_size(desc->chainSize()
1401070SN/A                           - sizeof(BlkRequest) - sizeof(Status));
1412378SN/A
1422378SN/A    switch (req.type) {
1432378SN/A      case T_IN:
1442378SN/A        status = parent.read(req, desc, sizeof(BlkRequest), data_size);
1452SN/A        break;
1462SN/A
1471808SN/A      case T_OUT:
1484095Sbinkertn@umich.edu        status = parent.write(req, desc, sizeof(BlkRequest), data_size);
1491808SN/A        break;
1502901Ssaidi@eecs.umich.edu
1514762Snate@binkert.org      case T_FLUSH:
1522901Ssaidi@eecs.umich.edu        status = S_OK;
1532901Ssaidi@eecs.umich.edu        break;
1542901Ssaidi@eecs.umich.edu
1552901Ssaidi@eecs.umich.edu      default:
1562901Ssaidi@eecs.umich.edu        warn("Unsupported IO request: %i\n", req.type);
1573960Sgblack@eecs.umich.edu        status = S_UNSUPP;
1583960Sgblack@eecs.umich.edu        break;
1594095Sbinkertn@umich.edu    }
1604095Sbinkertn@umich.edu
1614095Sbinkertn@umich.edu    desc->chainWrite(sizeof(BlkRequest) + data_size,
1623960Sgblack@eecs.umich.edu                     &status, sizeof(status));
1633960Sgblack@eecs.umich.edu
164180SN/A    // Tell the guest that we are done with this descriptor.
1652680Sktlim@umich.edu    produceDescriptor(desc, sizeof(BlkRequest) + data_size + sizeof(Status));
1662SN/A    parent.kick();
1671806SN/A}
1682680Sktlim@umich.edu
1692680Sktlim@umich.eduVirtIOBlock *
1701806SN/AVirtIOBlockParams::create()
1711806SN/A{
1721806SN/A    return new VirtIOBlock(this);
1731806SN/A}
1742680Sktlim@umich.edu