blob: 945707a6a6bfac796d95b778208f89a11b4deeb1 [file] [log] [blame]
// Copyright 2018 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 "garnet/bin/guest/vmm/device/test_with_device.h"
#include "garnet/bin/guest/vmm/device/config.h"
#include "garnet/bin/guest/vmm/device/virtio_queue.h"
zx_status_t TestWithDevice::LaunchDevice(
const std::string& url, size_t phys_mem_size,
fuchsia::guest::device::StartInfo* start_info,
std::unique_ptr<component::testing::EnvironmentServices> env_services) {
if (!env_services) {
env_services = CreateServices();
}
// Create test environment.
enclosing_environment_ =
CreateNewEnclosingEnvironment("realm:" + url, std::move(env_services));
bool started = WaitForEnclosingEnvToStart(enclosing_environment_.get());
if (!started) {
return ZX_ERR_TIMED_OUT;
}
// Create device process.
fuchsia::sys::LaunchInfo launch_info{
.url = url,
.directory_request = services.NewRequest(),
};
component_controller_ =
enclosing_environment_->CreateComponent(std::move(launch_info));
// Setup device interrupt event.
zx_status_t status = zx::event::create(0, &event_);
if (status != ZX_OK) {
return status;
}
status =
event_.duplicate(ZX_RIGHT_TRANSFER | ZX_RIGHT_SIGNAL, &start_info->event);
if (status != ZX_OK) {
return status;
}
// Setup guest physical memory.
zx::vmo vmo;
status = zx::vmo::create(phys_mem_size, ZX_VMO_NON_RESIZABLE, &vmo);
if (status != ZX_OK) {
FXL_LOG(ERROR) << "Failed to create VMO " << status;
return status;
}
status = vmo.duplicate(ZX_RIGHT_TRANSFER | ZX_RIGHTS_IO | ZX_RIGHT_MAP,
&start_info->vmo);
if (status != ZX_OK) {
FXL_LOG(ERROR) << "Failed to duplicate VMO " << status;
return status;
}
return phys_mem_.Init(std::move(vmo));
}
zx_status_t TestWithDevice::WaitOnInterrupt() {
zx::time deadline = zx::deadline_after(zx::sec(10));
zx_signals_t signals = VirtioQueue::InterruptAction::TRY_INTERRUPT
<< kDeviceInterruptShift;
zx_signals_t pending;
zx_status_t status = event_.wait_one(signals, deadline, &pending);
if (status != ZX_OK) {
return status;
}
if (!(pending & signals)) {
return ZX_ERR_BAD_STATE;
}
return event_.signal(pending, 0);
}