2012-10-11 16:41:02 +02:00
|
|
|
/*
|
|
|
|
* \brief Block interface
|
|
|
|
* \author Markus Partheymueller
|
2013-06-16 22:46:04 +02:00
|
|
|
* \author Alexander Boettcher
|
2012-10-11 16:41:02 +02:00
|
|
|
* \date 2012-09-15
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2012 Intel Corporation
|
2018-03-18 10:31:09 +01:00
|
|
|
* Copyright (C) 2013-2018 Genode Labs GmbH
|
2012-10-11 16:41:02 +02:00
|
|
|
*
|
2014-01-10 22:58:28 +01:00
|
|
|
* This file is distributed under the terms of the GNU General Public License
|
|
|
|
* version 2.
|
2012-10-11 16:41:02 +02:00
|
|
|
*
|
|
|
|
* The code is partially based on the Vancouver VMM, which is distributed
|
|
|
|
* under the terms of the GNU General Public License version 2.
|
|
|
|
*
|
|
|
|
* Modifications by Intel Corporation are contributed under the terms and
|
|
|
|
* conditions of the GNU General Public License version 2.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Genode includes */
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
#include <base/log.h>
|
2012-10-11 16:41:02 +02:00
|
|
|
#include <block_session/connection.h>
|
2013-06-16 22:46:04 +02:00
|
|
|
#include <base/heap.h>
|
2012-10-11 16:41:02 +02:00
|
|
|
|
2013-08-20 21:24:52 +02:00
|
|
|
/* VMM utility includes */
|
|
|
|
#include <vmm/utcb_guard.h>
|
|
|
|
|
2012-10-11 16:41:02 +02:00
|
|
|
/* local includes */
|
2014-05-17 00:57:41 +02:00
|
|
|
#include "disk.h"
|
2012-10-11 16:41:02 +02:00
|
|
|
|
2019-01-21 10:48:39 +01:00
|
|
|
static Genode::Heap * disk_heap(Genode::Ram_allocator *ram = nullptr,
|
2017-01-03 11:41:42 +01:00
|
|
|
Genode::Region_map *rm = nullptr)
|
2013-06-16 22:46:04 +02:00
|
|
|
{
|
2017-01-03 11:41:42 +01:00
|
|
|
static Genode::Heap heap(ram, rm);
|
2015-09-06 11:24:42 +02:00
|
|
|
return &heap;
|
|
|
|
}
|
2017-01-03 11:41:42 +01:00
|
|
|
static Genode::Heap * disk_heap_msg(Genode::Env &env)
|
|
|
|
{
|
|
|
|
static Genode::Heap heap(&env.ram(), &env.rm(), 4096);
|
2015-09-06 11:24:42 +02:00
|
|
|
return &heap;
|
|
|
|
}
|
2017-01-03 11:41:42 +01:00
|
|
|
static Genode::Heap * disk_heap_avl(Genode::Env &env)
|
|
|
|
{
|
|
|
|
static Genode::Heap heap(&env.ram(), &env.rm(), 4096);
|
2013-06-16 22:46:04 +02:00
|
|
|
return &heap;
|
|
|
|
}
|
2012-10-11 16:41:02 +02:00
|
|
|
|
|
|
|
|
2017-01-03 11:41:42 +01:00
|
|
|
Seoul::Disk::Disk(Genode::Env &env, Synced_motherboard &mb,
|
|
|
|
char * backing_store_base, Genode::size_t backing_store_size)
|
2012-10-11 16:41:02 +02:00
|
|
|
:
|
2017-01-03 11:41:42 +01:00
|
|
|
_env(env),
|
2013-08-20 21:24:52 +02:00
|
|
|
_motherboard(mb),
|
|
|
|
_backing_store_base(backing_store_base),
|
|
|
|
_backing_store_size(backing_store_size),
|
2017-01-03 11:41:42 +01:00
|
|
|
_tslab_msg(disk_heap_msg(env)),
|
|
|
|
_tslab_avl(disk_heap_avl(env))
|
2012-10-11 16:41:02 +02:00
|
|
|
{
|
2017-01-03 11:41:42 +01:00
|
|
|
/* initialize disk heap */
|
|
|
|
disk_heap(&env.ram(), &env.rm());
|
|
|
|
|
2012-10-11 16:41:02 +02:00
|
|
|
/* initialize struct with 0 size */
|
|
|
|
for (int i=0; i < MAX_DISKS; i++) {
|
2019-04-03 16:05:10 +02:00
|
|
|
_diskcon[i].info.block_size = 0;
|
2012-10-11 16:41:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-03 11:41:42 +01:00
|
|
|
void Seoul::Disk::register_host_operations(Motherboard &motherboard)
|
2013-05-16 23:32:27 +02:00
|
|
|
{
|
|
|
|
motherboard.bus_disk.add(this, receive_static<MessageDisk>);
|
|
|
|
}
|
|
|
|
|
2017-01-03 11:41:42 +01:00
|
|
|
void Seoul::Disk_signal::_signal() { _obj.handle_disk(_id); }
|
2013-05-16 23:32:27 +02:00
|
|
|
|
2017-01-03 11:41:42 +01:00
|
|
|
void Seoul::Disk::handle_disk(unsigned disknr)
|
2013-06-16 22:46:04 +02:00
|
|
|
{
|
|
|
|
Block::Session::Tx::Source *source = _diskcon[disknr].blk_con->tx();
|
|
|
|
|
|
|
|
while (source->ack_avail())
|
|
|
|
{
|
|
|
|
Block::Packet_descriptor packet = source->get_acked_packet();
|
2018-03-18 10:31:09 +01:00
|
|
|
char * const source_addr = source->packet_content(packet);
|
2013-06-16 22:46:04 +02:00
|
|
|
|
|
|
|
/* find the corresponding MessageDisk object */
|
2018-03-18 10:31:09 +01:00
|
|
|
Avl_entry * obj = lookup_and_remove(_lookup_msg, source_addr);
|
|
|
|
if (!obj) {
|
|
|
|
Genode::warning("unknown MessageDisk object - drop ack of block session ", (void *)source_addr);
|
|
|
|
continue;
|
2013-06-16 22:46:04 +02:00
|
|
|
}
|
|
|
|
/* got the MessageDisk object */
|
|
|
|
MessageDisk * msg = obj->msg();
|
|
|
|
/* delete helper object */
|
|
|
|
destroy(&_tslab_avl, obj);
|
|
|
|
|
|
|
|
/* go ahead and tell VMM about new block event */
|
|
|
|
if (!packet.succeeded() ||
|
|
|
|
!(packet.operation() == Block::Packet_descriptor::Opcode::READ ||
|
|
|
|
packet.operation() == Block::Packet_descriptor::Opcode::WRITE)) {
|
|
|
|
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::warning("getting block failed");
|
2013-06-16 22:46:04 +02:00
|
|
|
|
|
|
|
MessageDiskCommit mdc(disknr, msg->usertag,
|
|
|
|
MessageDisk::DISK_STATUS_DEVICE);
|
|
|
|
_motherboard()->bus_diskcommit.send(mdc);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (packet.operation() == Block::Packet_descriptor::Opcode::READ) {
|
2019-04-03 16:05:10 +02:00
|
|
|
|
2013-06-16 22:46:04 +02:00
|
|
|
unsigned long long sector = msg->sector;
|
2019-04-03 16:05:10 +02:00
|
|
|
sector = (sector-packet.block_number())
|
|
|
|
* _diskcon[disknr].info.block_size;
|
2013-06-16 22:46:04 +02:00
|
|
|
|
2018-03-18 10:31:09 +01:00
|
|
|
bool const ok = check_dma_descriptors(msg,
|
|
|
|
[&](char * const dma_addr, unsigned i)
|
|
|
|
{
|
|
|
|
size_t const bytecount = msg->dma[i].bytecount;
|
|
|
|
|
|
|
|
if (bytecount > packet.size() ||
|
|
|
|
sector > packet.size() ||
|
|
|
|
sector + bytecount > packet.size() ||
|
|
|
|
source_addr > source->packet_content(packet) + packet.size() - sector - bytecount ||
|
|
|
|
_backing_store_base + _backing_store_size - bytecount < dma_addr)
|
|
|
|
return false;
|
2013-06-16 22:46:04 +02:00
|
|
|
|
2018-03-18 10:31:09 +01:00
|
|
|
memcpy(dma_addr, source_addr + sector, bytecount);
|
|
|
|
sector += bytecount;
|
|
|
|
return true;
|
|
|
|
});
|
2013-06-16 22:46:04 +02:00
|
|
|
|
2018-03-18 10:31:09 +01:00
|
|
|
if (!ok)
|
|
|
|
Genode::warning("DMA bounds violation during read");
|
2013-06-16 22:46:04 +02:00
|
|
|
|
2015-09-06 11:24:42 +02:00
|
|
|
destroy(disk_heap(), msg->dma);
|
2018-03-18 10:31:09 +01:00
|
|
|
msg->dma = nullptr;
|
2013-06-16 22:46:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
MessageDiskCommit mdc (disknr, msg->usertag, MessageDisk::DISK_OK);
|
|
|
|
_motherboard()->bus_diskcommit.send(mdc);
|
|
|
|
}
|
|
|
|
|
2018-03-18 10:31:09 +01:00
|
|
|
{
|
|
|
|
Genode::Lock::Guard lock_guard(_alloc_lock);
|
|
|
|
source->release_packet(packet);
|
|
|
|
}
|
2013-06-16 22:46:04 +02:00
|
|
|
destroy(&_tslab_msg, msg);
|
|
|
|
}
|
2018-03-18 10:31:09 +01:00
|
|
|
|
|
|
|
/* restart disk operations suspended due to out of memory by alloc_packet */
|
|
|
|
check_restart();
|
2012-10-11 16:41:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-03 11:41:42 +01:00
|
|
|
bool Seoul::Disk::receive(MessageDisk &msg)
|
2012-10-11 16:41:02 +02:00
|
|
|
{
|
2016-03-08 16:59:43 +01:00
|
|
|
static Vmm::Utcb_guard::Utcb_backup utcb_backup;
|
2013-08-20 21:24:52 +02:00
|
|
|
Vmm::Utcb_guard guard(utcb_backup);
|
2012-10-11 16:41:02 +02:00
|
|
|
|
|
|
|
if (msg.disknr >= MAX_DISKS)
|
|
|
|
Logging::panic("You configured more disks than supported.\n");
|
|
|
|
|
2018-03-18 10:31:09 +01:00
|
|
|
struct disk_session &disk = _diskcon[msg.disknr];
|
2012-10-11 16:41:02 +02:00
|
|
|
|
2019-04-03 16:05:10 +02:00
|
|
|
if (!disk.info.block_size) {
|
2018-03-18 10:31:09 +01:00
|
|
|
Genode::String<16> label("VirtualDisk ", msg.disknr);
|
|
|
|
/*
|
|
|
|
* If we receive a message for this disk the first time, create the
|
|
|
|
* structure for it.
|
|
|
|
*/
|
2012-10-11 16:41:02 +02:00
|
|
|
try {
|
2013-06-16 22:46:04 +02:00
|
|
|
Genode::Allocator_avl * block_alloc =
|
2017-01-03 11:41:42 +01:00
|
|
|
new (disk_heap()) Genode::Allocator_avl(disk_heap());
|
2013-06-16 22:46:04 +02:00
|
|
|
|
2018-03-18 10:31:09 +01:00
|
|
|
disk.blk_con =
|
2017-01-03 11:41:42 +01:00
|
|
|
new (disk_heap()) Block::Connection(_env, block_alloc,
|
|
|
|
4*512*1024,
|
|
|
|
label.string());
|
2018-03-18 10:31:09 +01:00
|
|
|
disk.signal =
|
2017-01-03 11:41:42 +01:00
|
|
|
new (disk_heap()) Seoul::Disk_signal(_env.ep(), *this,
|
2018-03-18 10:31:09 +01:00
|
|
|
*disk.blk_con, msg.disknr);
|
2012-10-11 16:41:02 +02:00
|
|
|
} catch (...) {
|
|
|
|
/* there is none. */
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-04-03 16:05:10 +02:00
|
|
|
disk.info = disk.blk_con->info();
|
2012-10-11 16:41:02 +02:00
|
|
|
}
|
|
|
|
|
2013-06-16 22:46:04 +02:00
|
|
|
msg.error = MessageDisk::DISK_OK;
|
|
|
|
|
2012-10-11 16:41:02 +02:00
|
|
|
switch (msg.type) {
|
|
|
|
case MessageDisk::DISK_GET_PARAMS:
|
2018-03-18 10:31:09 +01:00
|
|
|
{
|
|
|
|
Genode::String<16> label("VirtualDisk ", msg.disknr);
|
|
|
|
|
2019-04-03 16:05:10 +02:00
|
|
|
msg.params->flags = DiskParameter::FLAG_HARDDISK;
|
|
|
|
msg.params->sectors = disk.info.block_count;
|
|
|
|
msg.params->sectorsize = disk.info.block_size;
|
|
|
|
msg.params->maxrequestcount = disk.info.block_count;
|
2018-03-18 10:31:09 +01:00
|
|
|
memcpy(msg.params->name, label.string(), label.length());
|
|
|
|
|
2012-10-11 16:41:02 +02:00
|
|
|
return true;
|
2018-03-18 10:31:09 +01:00
|
|
|
}
|
2012-10-11 16:41:02 +02:00
|
|
|
case MessageDisk::DISK_WRITE:
|
2018-03-18 10:31:09 +01:00
|
|
|
/* don't write on read only medium */
|
2019-04-03 16:05:10 +02:00
|
|
|
if (!disk.info.writeable) {
|
2018-03-18 10:31:09 +01:00
|
|
|
MessageDiskCommit ro(msg.disknr, msg.usertag,
|
|
|
|
MessageDisk::DISK_STATUS_DEVICE);
|
|
|
|
_motherboard()->bus_diskcommit.send(ro);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case MessageDisk::DISK_READ:
|
|
|
|
/* read and write handling */
|
|
|
|
return execute(msg.type == MessageDisk::DISK_WRITE, disk, msg);
|
|
|
|
default:
|
|
|
|
Logging::printf("Got MessageDisk type %x\n", msg.type);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2012-10-11 16:41:02 +02:00
|
|
|
|
2018-03-18 10:31:09 +01:00
|
|
|
void Seoul::Disk::check_restart()
|
|
|
|
{
|
|
|
|
bool restarted = true;
|
2012-10-11 16:41:02 +02:00
|
|
|
|
2018-03-18 10:31:09 +01:00
|
|
|
while (restarted) {
|
|
|
|
Avl_entry * obj = lookup_and_remove(_restart_msg);
|
|
|
|
if (!obj)
|
|
|
|
return;
|
2012-10-11 16:41:02 +02:00
|
|
|
|
2018-03-18 10:31:09 +01:00
|
|
|
MessageDisk * const msg = obj->msg();
|
|
|
|
struct disk_session const &disk = _diskcon[msg->disknr];
|
2012-10-11 16:41:02 +02:00
|
|
|
|
2018-03-18 10:31:09 +01:00
|
|
|
restarted = restart(disk, msg);
|
|
|
|
|
|
|
|
if (restarted) {
|
|
|
|
destroy(&_tslab_avl, obj);
|
|
|
|
} else {
|
|
|
|
Genode::Lock::Guard lock_guard(_alloc_lock);
|
|
|
|
_restart_msg.insert(obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Seoul::Disk::restart(struct disk_session const &disk,
|
|
|
|
MessageDisk * const msg)
|
|
|
|
{
|
|
|
|
Block::Session::Tx::Source * const source = disk.blk_con->tx();
|
|
|
|
|
2019-04-03 16:05:10 +02:00
|
|
|
unsigned long const total = DmaDescriptor::sum_length(msg->dmacount, msg->dma);
|
|
|
|
unsigned long const blk_size = disk.info.block_size;
|
|
|
|
unsigned long const blocks = total/blk_size + ((total%blk_size) ? 1 : 0);
|
|
|
|
bool const write = msg->type == MessageDisk::DISK_WRITE;
|
2012-10-11 16:41:02 +02:00
|
|
|
|
2018-03-18 10:31:09 +01:00
|
|
|
Block::Packet_descriptor packet;
|
2012-10-11 16:41:02 +02:00
|
|
|
|
2018-03-18 10:31:09 +01:00
|
|
|
try {
|
|
|
|
Genode::Lock::Guard lock_guard(_alloc_lock);
|
2012-10-11 16:41:02 +02:00
|
|
|
|
2018-03-18 10:31:09 +01:00
|
|
|
packet = Block::Packet_descriptor(
|
2019-04-04 18:25:54 +02:00
|
|
|
disk.blk_con->alloc_packet(blocks * blk_size),
|
2018-03-18 10:31:09 +01:00
|
|
|
(write) ? Block::Packet_descriptor::WRITE
|
|
|
|
: Block::Packet_descriptor::READ,
|
|
|
|
msg->sector, blocks);
|
2012-10-11 16:41:02 +02:00
|
|
|
|
2018-03-18 10:31:09 +01:00
|
|
|
char * source_addr = source->packet_content(packet);
|
|
|
|
_lookup_msg.insert(new (&_tslab_avl) Avl_entry(source_addr, msg));
|
|
|
|
|
|
|
|
} catch (...) { return false; }
|
|
|
|
|
|
|
|
/* read */
|
|
|
|
if (!write) {
|
|
|
|
source->submit_packet(packet);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* write */
|
|
|
|
char * source_addr = source->packet_content(packet);
|
|
|
|
source_addr += (msg->sector - packet.block_number()) * blk_size;
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < msg->dmacount; i++) {
|
|
|
|
char * const dma_addr = _backing_store_base +
|
|
|
|
msg->dma[i].byteoffset +
|
|
|
|
msg->physoffset;
|
|
|
|
|
|
|
|
memcpy(source_addr, dma_addr, msg->dma[i].bytecount);
|
|
|
|
source_addr += msg->dma[i].bytecount;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* free up DMA descriptors of write */
|
|
|
|
destroy(disk_heap(), msg->dma);
|
|
|
|
msg->dma = nullptr;
|
|
|
|
|
|
|
|
source->submit_packet(packet);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Seoul::Disk::execute(bool const write, struct disk_session const &disk,
|
|
|
|
MessageDisk const &msg)
|
|
|
|
{
|
|
|
|
unsigned long long const sector = msg.sector;
|
2019-04-03 16:05:10 +02:00
|
|
|
unsigned long const total = DmaDescriptor::sum_length(msg.dmacount, msg.dma);
|
|
|
|
unsigned long const blk_size = disk.info.block_size;
|
2018-03-18 10:31:09 +01:00
|
|
|
unsigned long const blocks = total/blk_size + ((total%blk_size) ? 1 : 0);
|
|
|
|
|
|
|
|
Block::Session::Tx::Source * const source = disk.blk_con->tx();
|
|
|
|
Block::Packet_descriptor packet;
|
|
|
|
|
|
|
|
/* msg copy required for acknowledgements */
|
|
|
|
MessageDisk * const msg_cpy = new (&_tslab_msg) MessageDisk(msg);
|
|
|
|
char * source_addr = nullptr;
|
|
|
|
|
|
|
|
try {
|
|
|
|
Genode::Lock::Guard lock_guard(_alloc_lock);
|
|
|
|
|
|
|
|
packet = Block::Packet_descriptor(
|
2019-04-04 18:25:54 +02:00
|
|
|
disk.blk_con->alloc_packet(blocks * blk_size),
|
2018-03-18 10:31:09 +01:00
|
|
|
(write) ? Block::Packet_descriptor::WRITE
|
|
|
|
: Block::Packet_descriptor::READ,
|
|
|
|
sector, blocks);
|
|
|
|
|
|
|
|
source_addr = source->packet_content(packet);
|
|
|
|
|
|
|
|
_lookup_msg.insert(new (&_tslab_avl) Avl_entry(source_addr, msg_cpy));
|
|
|
|
} catch (Block::Session::Tx::Source::Packet_alloc_failed) {
|
|
|
|
/* msg_cpy object will be used/freed below by copy_dma_descriptors */
|
|
|
|
} catch (...) {
|
|
|
|
if (msg_cpy)
|
|
|
|
destroy(&_tslab_msg, msg_cpy);
|
|
|
|
|
|
|
|
Logging::printf("could not allocate disk block elements - "
|
|
|
|
"write=%u blocks=%lu\n", write, blocks);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy DMA descriptors ever for read requests and for deferred write
|
|
|
|
* requests. The descriptors can be changed by the guest at any time.
|
|
|
|
*/
|
|
|
|
bool const copy_dma_descriptors = !source_addr || !write;
|
|
|
|
|
|
|
|
/* invalid packet allocation or read request */
|
|
|
|
if (copy_dma_descriptors) {
|
|
|
|
msg_cpy->dma = new (disk_heap()) DmaDescriptor[msg_cpy->dmacount];
|
|
|
|
for (unsigned i = 0; i < msg_cpy->dmacount; i++)
|
|
|
|
memcpy(msg_cpy->dma + i, msg.dma + i, sizeof(DmaDescriptor));
|
|
|
|
|
|
|
|
/* validate DMA descriptors */
|
|
|
|
bool const ok = check_dma_descriptors(msg_cpy,
|
|
|
|
[&](char * const dma_addr, unsigned i)
|
|
|
|
{
|
|
|
|
if (!write)
|
|
|
|
/* evaluated during receive */
|
|
|
|
return true;
|
|
|
|
|
|
|
|
size_t const bytecount = msg_cpy->dma[i].bytecount;
|
|
|
|
|
|
|
|
if (bytecount > packet.size() ||
|
|
|
|
source_addr > source->packet_content(packet) + packet.size() - bytecount ||
|
|
|
|
_backing_store_base + _backing_store_size - bytecount < dma_addr)
|
2013-06-16 22:46:04 +02:00
|
|
|
return false;
|
2012-10-11 16:41:02 +02:00
|
|
|
|
2018-03-18 10:31:09 +01:00
|
|
|
return true;
|
|
|
|
});
|
|
|
|
|
|
|
|
if (ok) {
|
|
|
|
/* DMA descriptors look good - go ahead with disk request */
|
|
|
|
|
|
|
|
if (source_addr)
|
|
|
|
/* valid packet for read request */
|
|
|
|
source->submit_packet(packet);
|
|
|
|
else {
|
|
|
|
/* failed packet allocation, restart at later point in time */
|
|
|
|
Genode::Lock::Guard lock_guard(_alloc_lock);
|
|
|
|
_restart_msg.insert(new (&_tslab_avl) Avl_entry(source_addr,
|
|
|
|
msg_cpy));
|
2012-10-11 16:41:02 +02:00
|
|
|
}
|
2018-03-18 10:31:09 +01:00
|
|
|
return true;
|
|
|
|
}
|
2012-10-11 16:41:02 +02:00
|
|
|
|
2018-03-18 10:31:09 +01:00
|
|
|
/* DMA descriptors look bad - free resources */
|
|
|
|
destroy(disk_heap(), msg_cpy->dma);
|
|
|
|
destroy(&_tslab_msg, msg_cpy);
|
|
|
|
if (source_addr) {
|
|
|
|
Genode::Lock::Guard lock_guard(_alloc_lock);
|
|
|
|
source->release_packet(packet);
|
2012-10-11 16:41:02 +02:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-03-18 10:31:09 +01:00
|
|
|
/* valid packet allocation for write request */
|
|
|
|
source_addr += (sector - packet.block_number()) * blk_size;
|
2012-10-11 16:41:02 +02:00
|
|
|
|
2018-03-18 10:31:09 +01:00
|
|
|
bool const ok = check_dma_descriptors(msg_cpy,
|
|
|
|
[&](char * const dma_addr, unsigned i)
|
|
|
|
{
|
|
|
|
/* read bytecount from guest memory once and don't evaluate again */
|
|
|
|
size_t const bytecount = msg.dma[i].bytecount;
|
|
|
|
|
|
|
|
if (bytecount > packet.size() ||
|
|
|
|
source_addr > source->packet_content(packet) + packet.size() - bytecount ||
|
|
|
|
_backing_store_base + _backing_store_size - bytecount < dma_addr)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
memcpy(source_addr, dma_addr, bytecount);
|
|
|
|
source_addr += bytecount;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
|
|
|
|
if (ok) {
|
|
|
|
/* don't needed anymore + protect us to use it again */
|
|
|
|
msg_cpy->dma = nullptr;
|
|
|
|
source->submit_packet(packet);
|
|
|
|
} else {
|
|
|
|
destroy(&_tslab_msg, msg_cpy);
|
|
|
|
|
|
|
|
Genode::Lock::Guard lock_guard(_alloc_lock);
|
|
|
|
source->release_packet(packet);
|
|
|
|
}
|
|
|
|
return ok;
|
2012-10-11 16:41:02 +02:00
|
|
|
}
|