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 4011793Sbrandon.potter@amd.com#include "dev/virtio/block.hh" 4111793Sbrandon.potter@amd.com 4210390SAndreas.Sandberg@ARM.com#include "debug/VIOBlock.hh" 4310390SAndreas.Sandberg@ARM.com#include "params/VirtIOBlock.hh" 4410390SAndreas.Sandberg@ARM.com#include "sim/system.hh" 4510390SAndreas.Sandberg@ARM.com 4610390SAndreas.Sandberg@ARM.comVirtIOBlock::VirtIOBlock(Params *params) 4710390SAndreas.Sandberg@ARM.com : VirtIODeviceBase(params, ID_BLOCK, sizeof(Config), 0), 4810390SAndreas.Sandberg@ARM.com qRequests(params->system->physProxy, params->queueSize, *this), 4910390SAndreas.Sandberg@ARM.com image(*params->image) 5010390SAndreas.Sandberg@ARM.com{ 5110390SAndreas.Sandberg@ARM.com registerQueue(qRequests); 5210390SAndreas.Sandberg@ARM.com 5310390SAndreas.Sandberg@ARM.com config.capacity = image.size(); 5410390SAndreas.Sandberg@ARM.com} 5510390SAndreas.Sandberg@ARM.com 5610390SAndreas.Sandberg@ARM.com 5710390SAndreas.Sandberg@ARM.comVirtIOBlock::~VirtIOBlock() 5810390SAndreas.Sandberg@ARM.com{ 5910390SAndreas.Sandberg@ARM.com} 6010390SAndreas.Sandberg@ARM.com 6110390SAndreas.Sandberg@ARM.comvoid 6210390SAndreas.Sandberg@ARM.comVirtIOBlock::readConfig(PacketPtr pkt, Addr cfgOffset) 6310390SAndreas.Sandberg@ARM.com{ 6410390SAndreas.Sandberg@ARM.com Config cfg_out; 6510390SAndreas.Sandberg@ARM.com cfg_out.capacity = htov_legacy(config.capacity); 6610390SAndreas.Sandberg@ARM.com 6710390SAndreas.Sandberg@ARM.com readConfigBlob(pkt, cfgOffset, (uint8_t *)&cfg_out); 6810390SAndreas.Sandberg@ARM.com} 6910390SAndreas.Sandberg@ARM.com 7010390SAndreas.Sandberg@ARM.comVirtIOBlock::Status 7110390SAndreas.Sandberg@ARM.comVirtIOBlock::read(const BlkRequest &req, VirtDescriptor *desc_chain, 7210390SAndreas.Sandberg@ARM.com size_t off_data, size_t size) 7310390SAndreas.Sandberg@ARM.com{ 7414239Schunchenhsu@google.com std::vector<uint8_t> data(size); 7510390SAndreas.Sandberg@ARM.com uint64_t sector(req.sector); 7610390SAndreas.Sandberg@ARM.com 7710390SAndreas.Sandberg@ARM.com DPRINTF(VIOBlock, "Read request starting @ sector %i (size: %i)\n", 7810390SAndreas.Sandberg@ARM.com sector, size); 7910390SAndreas.Sandberg@ARM.com 8010390SAndreas.Sandberg@ARM.com if (size % SectorSize != 0) 8110390SAndreas.Sandberg@ARM.com panic("Unexpected request/sector size relationship\n"); 8210390SAndreas.Sandberg@ARM.com 8310390SAndreas.Sandberg@ARM.com for (Addr offset = 0; offset < size; offset += SectorSize) { 8414239Schunchenhsu@google.com if (image.read(&data[offset], sector) != SectorSize) { 8510390SAndreas.Sandberg@ARM.com warn("Failed to read sector %i\n", sector); 8610390SAndreas.Sandberg@ARM.com return S_IOERR; 8710390SAndreas.Sandberg@ARM.com } 8810390SAndreas.Sandberg@ARM.com ++sector; 8910390SAndreas.Sandberg@ARM.com } 9010390SAndreas.Sandberg@ARM.com 9114239Schunchenhsu@google.com desc_chain->chainWrite(off_data, &data[0], size); 9210390SAndreas.Sandberg@ARM.com 9310390SAndreas.Sandberg@ARM.com return S_OK; 9410390SAndreas.Sandberg@ARM.com} 9510390SAndreas.Sandberg@ARM.com 9610390SAndreas.Sandberg@ARM.comVirtIOBlock::Status 9710390SAndreas.Sandberg@ARM.comVirtIOBlock::write(const BlkRequest &req, VirtDescriptor *desc_chain, 9810390SAndreas.Sandberg@ARM.com size_t off_data, size_t size) 9910390SAndreas.Sandberg@ARM.com{ 10014239Schunchenhsu@google.com std::vector<uint8_t> data(size); 10110390SAndreas.Sandberg@ARM.com uint64_t sector(req.sector); 10210390SAndreas.Sandberg@ARM.com 10310390SAndreas.Sandberg@ARM.com DPRINTF(VIOBlock, "Write request starting @ sector %i (size: %i)\n", 10410390SAndreas.Sandberg@ARM.com sector, size); 10510390SAndreas.Sandberg@ARM.com 10610390SAndreas.Sandberg@ARM.com if (size % SectorSize != 0) 10710390SAndreas.Sandberg@ARM.com panic("Unexpected request/sector size relationship\n"); 10810390SAndreas.Sandberg@ARM.com 10910390SAndreas.Sandberg@ARM.com 11014239Schunchenhsu@google.com desc_chain->chainRead(off_data, &data[0], size); 11110390SAndreas.Sandberg@ARM.com 11210390SAndreas.Sandberg@ARM.com for (Addr offset = 0; offset < size; offset += SectorSize) { 11314239Schunchenhsu@google.com if (image.write(&data[offset], sector) != SectorSize) { 11410390SAndreas.Sandberg@ARM.com warn("Failed to write sector %i\n", sector); 11510390SAndreas.Sandberg@ARM.com return S_IOERR; 11610390SAndreas.Sandberg@ARM.com } 11710390SAndreas.Sandberg@ARM.com ++sector; 11810390SAndreas.Sandberg@ARM.com } 11910390SAndreas.Sandberg@ARM.com 12010390SAndreas.Sandberg@ARM.com return S_OK; 12110390SAndreas.Sandberg@ARM.com 12210390SAndreas.Sandberg@ARM.com} 12310390SAndreas.Sandberg@ARM.com 12410390SAndreas.Sandberg@ARM.comvoid 12510390SAndreas.Sandberg@ARM.comVirtIOBlock::RequestQueue::onNotifyDescriptor(VirtDescriptor *desc) 12610390SAndreas.Sandberg@ARM.com{ 12710390SAndreas.Sandberg@ARM.com DPRINTF(VIOBlock, "Got input data descriptor (len: %i)\n", 12810390SAndreas.Sandberg@ARM.com desc->size()); 12910390SAndreas.Sandberg@ARM.com /* 13010390SAndreas.Sandberg@ARM.com * Read the request structure and do endian conversion if 13110390SAndreas.Sandberg@ARM.com * necessary. 13210390SAndreas.Sandberg@ARM.com */ 13310390SAndreas.Sandberg@ARM.com BlkRequest req; 13410390SAndreas.Sandberg@ARM.com desc->chainRead(0, (uint8_t *)&req, sizeof(req)); 13510390SAndreas.Sandberg@ARM.com req.type = htov_legacy(req.type); 13610390SAndreas.Sandberg@ARM.com req.sector = htov_legacy(req.sector); 13710390SAndreas.Sandberg@ARM.com 13810390SAndreas.Sandberg@ARM.com Status status; 13910390SAndreas.Sandberg@ARM.com const size_t data_size(desc->chainSize() 14010390SAndreas.Sandberg@ARM.com - sizeof(BlkRequest) - sizeof(Status)); 14110390SAndreas.Sandberg@ARM.com 14210390SAndreas.Sandberg@ARM.com switch (req.type) { 14310390SAndreas.Sandberg@ARM.com case T_IN: 14410390SAndreas.Sandberg@ARM.com status = parent.read(req, desc, sizeof(BlkRequest), data_size); 14510390SAndreas.Sandberg@ARM.com break; 14610390SAndreas.Sandberg@ARM.com 14710390SAndreas.Sandberg@ARM.com case T_OUT: 14810390SAndreas.Sandberg@ARM.com status = parent.write(req, desc, sizeof(BlkRequest), data_size); 14910390SAndreas.Sandberg@ARM.com break; 15010390SAndreas.Sandberg@ARM.com 15110390SAndreas.Sandberg@ARM.com case T_FLUSH: 15210390SAndreas.Sandberg@ARM.com status = S_OK; 15310390SAndreas.Sandberg@ARM.com break; 15410390SAndreas.Sandberg@ARM.com 15510390SAndreas.Sandberg@ARM.com default: 15610390SAndreas.Sandberg@ARM.com warn("Unsupported IO request: %i\n", req.type); 15710390SAndreas.Sandberg@ARM.com status = S_UNSUPP; 15810390SAndreas.Sandberg@ARM.com break; 15910390SAndreas.Sandberg@ARM.com } 16010390SAndreas.Sandberg@ARM.com 16110390SAndreas.Sandberg@ARM.com desc->chainWrite(sizeof(BlkRequest) + data_size, 16210390SAndreas.Sandberg@ARM.com &status, sizeof(status)); 16310390SAndreas.Sandberg@ARM.com 16410390SAndreas.Sandberg@ARM.com // Tell the guest that we are done with this descriptor. 16510390SAndreas.Sandberg@ARM.com produceDescriptor(desc, sizeof(BlkRequest) + data_size + sizeof(Status)); 16610390SAndreas.Sandberg@ARM.com parent.kick(); 16710390SAndreas.Sandberg@ARM.com} 16810390SAndreas.Sandberg@ARM.com 16910390SAndreas.Sandberg@ARM.comVirtIOBlock * 17010390SAndreas.Sandberg@ARM.comVirtIOBlockParams::create() 17110390SAndreas.Sandberg@ARM.com{ 17210390SAndreas.Sandberg@ARM.com return new VirtIOBlock(this); 17310390SAndreas.Sandberg@ARM.com} 174