blob: ca1183f8eda449ce3ab857cb48f1a5befe7815c0 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/virtualization/bin/vmm/controller/virtio_block.h"
#include <lib/sys/cpp/service_directory.h>
#include "src/virtualization/bin/vmm/device/block.h"
static constexpr char kVirtioBlockUrl[] =
"fuchsia-pkg://fuchsia.com/virtio_block#meta/virtio_block.cmx";
static bool read_only(fuchsia::virtualization::BlockMode mode) {
return mode == fuchsia::virtualization::BlockMode::READ_ONLY;
}
VirtioBlock::VirtioBlock(const PhysMem& phys_mem, fuchsia::virtualization::BlockMode mode)
: VirtioComponentDevice(
phys_mem,
// From Virtio 1.0, Section 5.2.5.2: Devices SHOULD always offer
// VIRTIO_BLK_F_FLUSH.
//
// VIRTIO_BLK_F_BLK_SIZE is required by Zircon guests.
VIRTIO_BLK_F_FLUSH | VIRTIO_BLK_F_BLK_SIZE | (read_only(mode) ? VIRTIO_BLK_F_RO : 0),
fit::bind_member(this, &VirtioBlock::ConfigureQueue),
fit::bind_member(this, &VirtioBlock::Ready)),
mode_(mode) {}
zx_status_t VirtioBlock::Start(const zx::guest& guest, const std::string& id,
fuchsia::virtualization::BlockFormat format,
fuchsia::io::FileHandle file, fuchsia::sys::Launcher* launcher,
async_dispatcher_t* dispatcher) {
fuchsia::sys::LaunchInfo launch_info;
launch_info.url = kVirtioBlockUrl;
auto services = sys::ServiceDirectory::CreateWithRequest(&launch_info.directory_request);
launcher->CreateComponent(std::move(launch_info), controller_.NewRequest());
services->Connect(block_.NewRequest());
fuchsia::virtualization::hardware::StartInfo start_info;
zx_status_t status = PrepStart(guest, dispatcher, &start_info);
if (status != ZX_OK) {
return status;
}
uint64_t size;
status = block_->Start(std::move(start_info), id, mode_, format, std::move(file), &size);
if (status != ZX_OK) {
return status;
} else if (size % kBlockSectorSize != 0) {
FX_LOGS(ERROR) << "Virtio block device must be aligned to block sector size: " << id
<< " has size " << size << ".";
return ZX_ERR_INVALID_ARGS;
}
std::lock_guard<std::mutex> lock(device_config_.mutex);
config_.capacity = size / kBlockSectorSize;
config_.blk_size = kBlockSectorSize;
return ZX_OK;
}
zx_status_t VirtioBlock::ConfigureQueue(uint16_t queue, uint16_t size, zx_gpaddr_t desc,
zx_gpaddr_t avail, zx_gpaddr_t used) {
return block_->ConfigureQueue(queue, size, desc, avail, used);
}
zx_status_t VirtioBlock::Ready(uint32_t negotiated_features) {
return block_->Ready(negotiated_features);
}