block.cc revision 14239:73109c2181d3
112855Sgabeblack@google.com/* 212855Sgabeblack@google.com * Copyright (c) 2014 ARM Limited 312855Sgabeblack@google.com * All rights reserved 412855Sgabeblack@google.com * 512855Sgabeblack@google.com * The license below extends only to copyright in the software and shall 612855Sgabeblack@google.com * not be construed as granting a license to any other intellectual 712855Sgabeblack@google.com * property including but not limited to intellectual property relating 812855Sgabeblack@google.com * to a hardware implementation of the functionality of the software 912855Sgabeblack@google.com * licensed hereunder. You may use the software subject to the license 1012855Sgabeblack@google.com * terms below provided that you ensure that this notice is replicated 1112855Sgabeblack@google.com * unmodified and in its entirety in all distributions of the software, 1212855Sgabeblack@google.com * modified or unmodified, in source code or in binary form. 1312855Sgabeblack@google.com * 1412855Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 1512855Sgabeblack@google.com * modification, are permitted provided that the following conditions are 1612855Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 1712855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 1812855Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 1912855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 2012855Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 2112855Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 2212855Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 2312855Sgabeblack@google.com * this software without specific prior written permission. 2412855Sgabeblack@google.com * 2512855Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2612855Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2712855Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2812855Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2912855Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3012855Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3112855Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3212855Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3312855Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3412855Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3512855Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3612855Sgabeblack@google.com * 3712855Sgabeblack@google.com * Authors: Andreas Sandberg 3812855Sgabeblack@google.com */ 3912855Sgabeblack@google.com 4012855Sgabeblack@google.com#include "dev/virtio/block.hh" 4112855Sgabeblack@google.com 4212855Sgabeblack@google.com#include "debug/VIOBlock.hh" 4312855Sgabeblack@google.com#include "params/VirtIOBlock.hh" 4412855Sgabeblack@google.com#include "sim/system.hh" 4512855Sgabeblack@google.com 4612855Sgabeblack@google.comVirtIOBlock::VirtIOBlock(Params *params) 4712855Sgabeblack@google.com : VirtIODeviceBase(params, ID_BLOCK, sizeof(Config), 0), 4812855Sgabeblack@google.com qRequests(params->system->physProxy, params->queueSize, *this), 4912855Sgabeblack@google.com image(*params->image) 5012855Sgabeblack@google.com{ 5112855Sgabeblack@google.com registerQueue(qRequests); 5212855Sgabeblack@google.com 5312855Sgabeblack@google.com config.capacity = image.size(); 5412855Sgabeblack@google.com} 5512855Sgabeblack@google.com 5612855Sgabeblack@google.com 5712855Sgabeblack@google.comVirtIOBlock::~VirtIOBlock() 5812855Sgabeblack@google.com{ 5912855Sgabeblack@google.com} 6012855Sgabeblack@google.com 6112855Sgabeblack@google.comvoid 6212855Sgabeblack@google.comVirtIOBlock::readConfig(PacketPtr pkt, Addr cfgOffset) 6312855Sgabeblack@google.com{ 6412855Sgabeblack@google.com Config cfg_out; 6512855Sgabeblack@google.com cfg_out.capacity = htov_legacy(config.capacity); 6612855Sgabeblack@google.com 6712855Sgabeblack@google.com readConfigBlob(pkt, cfgOffset, (uint8_t *)&cfg_out); 6812855Sgabeblack@google.com} 6912855Sgabeblack@google.com 7012855Sgabeblack@google.comVirtIOBlock::Status 7112855Sgabeblack@google.comVirtIOBlock::read(const BlkRequest &req, VirtDescriptor *desc_chain, 7212855Sgabeblack@google.com size_t off_data, size_t size) 7312855Sgabeblack@google.com{ 7412855Sgabeblack@google.com std::vector<uint8_t> data(size); 7512855Sgabeblack@google.com uint64_t sector(req.sector); 7612855Sgabeblack@google.com 7712855Sgabeblack@google.com DPRINTF(VIOBlock, "Read request starting @ sector %i (size: %i)\n", 7812855Sgabeblack@google.com sector, size); 7912855Sgabeblack@google.com 8012855Sgabeblack@google.com if (size % SectorSize != 0) 8112855Sgabeblack@google.com panic("Unexpected request/sector size relationship\n"); 8212855Sgabeblack@google.com 8312855Sgabeblack@google.com for (Addr offset = 0; offset < size; offset += SectorSize) { 8412855Sgabeblack@google.com if (image.read(&data[offset], sector) != SectorSize) { 8512855Sgabeblack@google.com warn("Failed to read sector %i\n", sector); 8612855Sgabeblack@google.com return S_IOERR; 8712855Sgabeblack@google.com } 8812855Sgabeblack@google.com ++sector; 8912855Sgabeblack@google.com } 9012855Sgabeblack@google.com 9112855Sgabeblack@google.com desc_chain->chainWrite(off_data, &data[0], size); 9212855Sgabeblack@google.com 9312855Sgabeblack@google.com return S_OK; 9412855Sgabeblack@google.com} 9512855Sgabeblack@google.com 9612855Sgabeblack@google.comVirtIOBlock::Status 9712855Sgabeblack@google.comVirtIOBlock::write(const BlkRequest &req, VirtDescriptor *desc_chain, 9812855Sgabeblack@google.com size_t off_data, size_t size) 9912855Sgabeblack@google.com{ 10012855Sgabeblack@google.com std::vector<uint8_t> data(size); 10112855Sgabeblack@google.com uint64_t sector(req.sector); 10212855Sgabeblack@google.com 10312855Sgabeblack@google.com DPRINTF(VIOBlock, "Write request starting @ sector %i (size: %i)\n", 10412855Sgabeblack@google.com sector, size); 10512855Sgabeblack@google.com 10612855Sgabeblack@google.com if (size % SectorSize != 0) 10712855Sgabeblack@google.com panic("Unexpected request/sector size relationship\n"); 10812855Sgabeblack@google.com 10912855Sgabeblack@google.com 11012855Sgabeblack@google.com desc_chain->chainRead(off_data, &data[0], size); 11112855Sgabeblack@google.com 11212855Sgabeblack@google.com for (Addr offset = 0; offset < size; offset += SectorSize) { 11312855Sgabeblack@google.com if (image.write(&data[offset], sector) != SectorSize) { 11412855Sgabeblack@google.com warn("Failed to write sector %i\n", sector); 11512855Sgabeblack@google.com return S_IOERR; 11612855Sgabeblack@google.com } 11712855Sgabeblack@google.com ++sector; 11812855Sgabeblack@google.com } 11912855Sgabeblack@google.com 12012855Sgabeblack@google.com return S_OK; 12112855Sgabeblack@google.com 12212855Sgabeblack@google.com} 12312855Sgabeblack@google.com 12412855Sgabeblack@google.comvoid 12512855Sgabeblack@google.comVirtIOBlock::RequestQueue::onNotifyDescriptor(VirtDescriptor *desc) 12612855Sgabeblack@google.com{ 12712855Sgabeblack@google.com DPRINTF(VIOBlock, "Got input data descriptor (len: %i)\n", 12812855Sgabeblack@google.com desc->size()); 12912855Sgabeblack@google.com /* 13012855Sgabeblack@google.com * Read the request structure and do endian conversion if 13112855Sgabeblack@google.com * necessary. 13212855Sgabeblack@google.com */ 13312855Sgabeblack@google.com BlkRequest req; 13412855Sgabeblack@google.com desc->chainRead(0, (uint8_t *)&req, sizeof(req)); 13512855Sgabeblack@google.com req.type = htov_legacy(req.type); 13612855Sgabeblack@google.com req.sector = htov_legacy(req.sector); 13712855Sgabeblack@google.com 13812855Sgabeblack@google.com Status status; 13912855Sgabeblack@google.com const size_t data_size(desc->chainSize() 14012855Sgabeblack@google.com - sizeof(BlkRequest) - sizeof(Status)); 14112855Sgabeblack@google.com 14212855Sgabeblack@google.com switch (req.type) { 14312855Sgabeblack@google.com case T_IN: 14412855Sgabeblack@google.com status = parent.read(req, desc, sizeof(BlkRequest), data_size); 14512855Sgabeblack@google.com break; 14612855Sgabeblack@google.com 14712855Sgabeblack@google.com case T_OUT: 14812855Sgabeblack@google.com status = parent.write(req, desc, sizeof(BlkRequest), data_size); 14912855Sgabeblack@google.com break; 15012855Sgabeblack@google.com 15112855Sgabeblack@google.com case T_FLUSH: 15212855Sgabeblack@google.com status = S_OK; 15312855Sgabeblack@google.com break; 15412855Sgabeblack@google.com 15512855Sgabeblack@google.com default: 15612855Sgabeblack@google.com warn("Unsupported IO request: %i\n", req.type); 15712855Sgabeblack@google.com status = S_UNSUPP; 15812855Sgabeblack@google.com break; 15912855Sgabeblack@google.com } 16012855Sgabeblack@google.com 16112855Sgabeblack@google.com desc->chainWrite(sizeof(BlkRequest) + data_size, 16212855Sgabeblack@google.com &status, sizeof(status)); 16312855Sgabeblack@google.com 16412855Sgabeblack@google.com // Tell the guest that we are done with this descriptor. 16512855Sgabeblack@google.com produceDescriptor(desc, sizeof(BlkRequest) + data_size + sizeof(Status)); 16612855Sgabeblack@google.com parent.kick(); 16712855Sgabeblack@google.com} 16812855Sgabeblack@google.com 16912855Sgabeblack@google.comVirtIOBlock * 17012855Sgabeblack@google.comVirtIOBlockParams::create() 17112855Sgabeblack@google.com{ 17212855Sgabeblack@google.com return new VirtIOBlock(this); 17312855Sgabeblack@google.com} 17412855Sgabeblack@google.com