block.cc revision 10390
110390SAndreas.Sandberg@ARM.com/* 210390SAndreas.Sandberg@ARM.com * Copyright (c) 2014 ARM Limited 310390SAndreas.Sandberg@ARM.com * All rights reserved 410390SAndreas.Sandberg@ARM.com * 510390SAndreas.Sandberg@ARM.com * The license below extends only to copyright in the software and shall 610390SAndreas.Sandberg@ARM.com * not be construed as granting a license to any other intellectual 710390SAndreas.Sandberg@ARM.com * property including but not limited to intellectual property relating 810390SAndreas.Sandberg@ARM.com * to a hardware implementation of the functionality of the software 910390SAndreas.Sandberg@ARM.com * licensed hereunder. You may use the software subject to the license 1010390SAndreas.Sandberg@ARM.com * terms below provided that you ensure that this notice is replicated 1110390SAndreas.Sandberg@ARM.com * unmodified and in its entirety in all distributions of the software, 1210390SAndreas.Sandberg@ARM.com * modified or unmodified, in source code or in binary form. 1310390SAndreas.Sandberg@ARM.com * 1410390SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without 1510390SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are 1610390SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright 1710390SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer; 1810390SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright 1910390SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the 2010390SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution; 2110390SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its 2210390SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from 2310390SAndreas.Sandberg@ARM.com * this software without specific prior written permission. 2410390SAndreas.Sandberg@ARM.com * 2510390SAndreas.Sandberg@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2610390SAndreas.Sandberg@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2710390SAndreas.Sandberg@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2810390SAndreas.Sandberg@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2910390SAndreas.Sandberg@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3010390SAndreas.Sandberg@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3110390SAndreas.Sandberg@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3210390SAndreas.Sandberg@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3310390SAndreas.Sandberg@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3410390SAndreas.Sandberg@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3510390SAndreas.Sandberg@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3610390SAndreas.Sandberg@ARM.com * 3710390SAndreas.Sandberg@ARM.com * Authors: Andreas Sandberg 3810390SAndreas.Sandberg@ARM.com */ 3910390SAndreas.Sandberg@ARM.com 4010390SAndreas.Sandberg@ARM.com#include "debug/VIOBlock.hh" 4110390SAndreas.Sandberg@ARM.com#include "dev/virtio/block.hh" 4210390SAndreas.Sandberg@ARM.com#include "params/VirtIOBlock.hh" 4310390SAndreas.Sandberg@ARM.com#include "sim/system.hh" 4410390SAndreas.Sandberg@ARM.com 4510390SAndreas.Sandberg@ARM.comVirtIOBlock::VirtIOBlock(Params *params) 4610390SAndreas.Sandberg@ARM.com : VirtIODeviceBase(params, ID_BLOCK, sizeof(Config), 0), 4710390SAndreas.Sandberg@ARM.com qRequests(params->system->physProxy, params->queueSize, *this), 4810390SAndreas.Sandberg@ARM.com image(*params->image) 4910390SAndreas.Sandberg@ARM.com{ 5010390SAndreas.Sandberg@ARM.com registerQueue(qRequests); 5110390SAndreas.Sandberg@ARM.com 5210390SAndreas.Sandberg@ARM.com config.capacity = image.size(); 5310390SAndreas.Sandberg@ARM.com} 5410390SAndreas.Sandberg@ARM.com 5510390SAndreas.Sandberg@ARM.com 5610390SAndreas.Sandberg@ARM.comVirtIOBlock::~VirtIOBlock() 5710390SAndreas.Sandberg@ARM.com{ 5810390SAndreas.Sandberg@ARM.com} 5910390SAndreas.Sandberg@ARM.com 6010390SAndreas.Sandberg@ARM.comvoid 6110390SAndreas.Sandberg@ARM.comVirtIOBlock::readConfig(PacketPtr pkt, Addr cfgOffset) 6210390SAndreas.Sandberg@ARM.com{ 6310390SAndreas.Sandberg@ARM.com Config cfg_out; 6410390SAndreas.Sandberg@ARM.com cfg_out.capacity = htov_legacy(config.capacity); 6510390SAndreas.Sandberg@ARM.com 6610390SAndreas.Sandberg@ARM.com readConfigBlob(pkt, cfgOffset, (uint8_t *)&cfg_out); 6710390SAndreas.Sandberg@ARM.com} 6810390SAndreas.Sandberg@ARM.com 6910390SAndreas.Sandberg@ARM.comVirtIOBlock::Status 7010390SAndreas.Sandberg@ARM.comVirtIOBlock::read(const BlkRequest &req, VirtDescriptor *desc_chain, 7110390SAndreas.Sandberg@ARM.com size_t off_data, size_t size) 7210390SAndreas.Sandberg@ARM.com{ 7310390SAndreas.Sandberg@ARM.com uint8_t data[size]; 7410390SAndreas.Sandberg@ARM.com uint64_t sector(req.sector); 7510390SAndreas.Sandberg@ARM.com 7610390SAndreas.Sandberg@ARM.com DPRINTF(VIOBlock, "Read request starting @ sector %i (size: %i)\n", 7710390SAndreas.Sandberg@ARM.com sector, size); 7810390SAndreas.Sandberg@ARM.com 7910390SAndreas.Sandberg@ARM.com if (size % SectorSize != 0) 8010390SAndreas.Sandberg@ARM.com panic("Unexpected request/sector size relationship\n"); 8110390SAndreas.Sandberg@ARM.com 8210390SAndreas.Sandberg@ARM.com for (Addr offset = 0; offset < size; offset += SectorSize) { 8310390SAndreas.Sandberg@ARM.com if (image.read(data + offset, sector) != SectorSize) { 8410390SAndreas.Sandberg@ARM.com warn("Failed to read sector %i\n", sector); 8510390SAndreas.Sandberg@ARM.com return S_IOERR; 8610390SAndreas.Sandberg@ARM.com } 8710390SAndreas.Sandberg@ARM.com ++sector; 8810390SAndreas.Sandberg@ARM.com } 8910390SAndreas.Sandberg@ARM.com 9010390SAndreas.Sandberg@ARM.com desc_chain->chainWrite(off_data, data, size); 9110390SAndreas.Sandberg@ARM.com 9210390SAndreas.Sandberg@ARM.com return S_OK; 9310390SAndreas.Sandberg@ARM.com} 9410390SAndreas.Sandberg@ARM.com 9510390SAndreas.Sandberg@ARM.comVirtIOBlock::Status 9610390SAndreas.Sandberg@ARM.comVirtIOBlock::write(const BlkRequest &req, VirtDescriptor *desc_chain, 9710390SAndreas.Sandberg@ARM.com size_t off_data, size_t size) 9810390SAndreas.Sandberg@ARM.com{ 9910390SAndreas.Sandberg@ARM.com uint8_t data[size]; 10010390SAndreas.Sandberg@ARM.com uint64_t sector(req.sector); 10110390SAndreas.Sandberg@ARM.com 10210390SAndreas.Sandberg@ARM.com DPRINTF(VIOBlock, "Write request starting @ sector %i (size: %i)\n", 10310390SAndreas.Sandberg@ARM.com sector, size); 10410390SAndreas.Sandberg@ARM.com 10510390SAndreas.Sandberg@ARM.com if (size % SectorSize != 0) 10610390SAndreas.Sandberg@ARM.com panic("Unexpected request/sector size relationship\n"); 10710390SAndreas.Sandberg@ARM.com 10810390SAndreas.Sandberg@ARM.com 10910390SAndreas.Sandberg@ARM.com desc_chain->chainRead(off_data, data, size); 11010390SAndreas.Sandberg@ARM.com 11110390SAndreas.Sandberg@ARM.com for (Addr offset = 0; offset < size; offset += SectorSize) { 11210390SAndreas.Sandberg@ARM.com if (image.write(data + offset, sector) != SectorSize) { 11310390SAndreas.Sandberg@ARM.com warn("Failed to write sector %i\n", sector); 11410390SAndreas.Sandberg@ARM.com return S_IOERR; 11510390SAndreas.Sandberg@ARM.com } 11610390SAndreas.Sandberg@ARM.com ++sector; 11710390SAndreas.Sandberg@ARM.com } 11810390SAndreas.Sandberg@ARM.com 11910390SAndreas.Sandberg@ARM.com return S_OK; 12010390SAndreas.Sandberg@ARM.com 12110390SAndreas.Sandberg@ARM.com} 12210390SAndreas.Sandberg@ARM.com 12310390SAndreas.Sandberg@ARM.comvoid 12410390SAndreas.Sandberg@ARM.comVirtIOBlock::RequestQueue::onNotifyDescriptor(VirtDescriptor *desc) 12510390SAndreas.Sandberg@ARM.com{ 12610390SAndreas.Sandberg@ARM.com DPRINTF(VIOBlock, "Got input data descriptor (len: %i)\n", 12710390SAndreas.Sandberg@ARM.com desc->size()); 12810390SAndreas.Sandberg@ARM.com /* 12910390SAndreas.Sandberg@ARM.com * Read the request structure and do endian conversion if 13010390SAndreas.Sandberg@ARM.com * necessary. 13110390SAndreas.Sandberg@ARM.com */ 13210390SAndreas.Sandberg@ARM.com BlkRequest req; 13310390SAndreas.Sandberg@ARM.com desc->chainRead(0, (uint8_t *)&req, sizeof(req)); 13410390SAndreas.Sandberg@ARM.com req.type = htov_legacy(req.type); 13510390SAndreas.Sandberg@ARM.com req.sector = htov_legacy(req.sector); 13610390SAndreas.Sandberg@ARM.com 13710390SAndreas.Sandberg@ARM.com Status status; 13810390SAndreas.Sandberg@ARM.com const size_t data_size(desc->chainSize() 13910390SAndreas.Sandberg@ARM.com - sizeof(BlkRequest) - sizeof(Status)); 14010390SAndreas.Sandberg@ARM.com 14110390SAndreas.Sandberg@ARM.com switch (req.type) { 14210390SAndreas.Sandberg@ARM.com case T_IN: 14310390SAndreas.Sandberg@ARM.com status = parent.read(req, desc, sizeof(BlkRequest), data_size); 14410390SAndreas.Sandberg@ARM.com break; 14510390SAndreas.Sandberg@ARM.com 14610390SAndreas.Sandberg@ARM.com case T_OUT: 14710390SAndreas.Sandberg@ARM.com status = parent.write(req, desc, sizeof(BlkRequest), data_size); 14810390SAndreas.Sandberg@ARM.com break; 14910390SAndreas.Sandberg@ARM.com 15010390SAndreas.Sandberg@ARM.com case T_FLUSH: 15110390SAndreas.Sandberg@ARM.com status = S_OK; 15210390SAndreas.Sandberg@ARM.com break; 15310390SAndreas.Sandberg@ARM.com 15410390SAndreas.Sandberg@ARM.com default: 15510390SAndreas.Sandberg@ARM.com warn("Unsupported IO request: %i\n", req.type); 15610390SAndreas.Sandberg@ARM.com status = S_UNSUPP; 15710390SAndreas.Sandberg@ARM.com break; 15810390SAndreas.Sandberg@ARM.com } 15910390SAndreas.Sandberg@ARM.com 16010390SAndreas.Sandberg@ARM.com desc->chainWrite(sizeof(BlkRequest) + data_size, 16110390SAndreas.Sandberg@ARM.com &status, sizeof(status)); 16210390SAndreas.Sandberg@ARM.com 16310390SAndreas.Sandberg@ARM.com // Tell the guest that we are done with this descriptor. 16410390SAndreas.Sandberg@ARM.com produceDescriptor(desc, sizeof(BlkRequest) + data_size + sizeof(Status)); 16510390SAndreas.Sandberg@ARM.com parent.kick(); 16610390SAndreas.Sandberg@ARM.com} 16710390SAndreas.Sandberg@ARM.com 16810390SAndreas.Sandberg@ARM.comVirtIOBlock * 16910390SAndreas.Sandberg@ARM.comVirtIOBlockParams::create() 17010390SAndreas.Sandberg@ARM.com{ 17110390SAndreas.Sandberg@ARM.com return new VirtIOBlock(this); 17210390SAndreas.Sandberg@ARM.com} 173