blob: f5eb34c2180823a46ffdaaf4174544e0a84658f9 [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_balloon.h"
#include <lib/sys/cpp/service_directory.h>
#include <lib/syslog/cpp/macros.h>
static constexpr char kVirtioBalloonUrl[] =
"fuchsia-pkg://fuchsia.com/virtio_balloon#meta/virtio_balloon.cmx";
VirtioBalloon::VirtioBalloon(const PhysMem& phys_mem)
: VirtioComponentDevice(phys_mem, VIRTIO_BALLOON_F_STATS_VQ | VIRTIO_BALLOON_F_DEFLATE_ON_OOM,
fit::bind_member(this, &VirtioBalloon::ConfigureQueue),
fit::bind_member(this, &VirtioBalloon::Ready)) {}
zx_status_t VirtioBalloon::AddPublicService(sys::ComponentContext* context) {
return context->outgoing()->AddPublicService(bindings_.GetHandler(this));
}
zx_status_t VirtioBalloon::Start(const zx::guest& guest, fuchsia::sys::Launcher* launcher,
async_dispatcher_t* dispatcher) {
fuchsia::sys::LaunchInfo launch_info;
launch_info.url = kVirtioBalloonUrl;
auto services = sys::ServiceDirectory::CreateWithRequest(&launch_info.directory_request);
launcher->CreateComponent(std::move(launch_info), controller_.NewRequest());
services->Connect(balloon_.NewRequest());
services->Connect(stats_.NewRequest());
fuchsia::virtualization::hardware::StartInfo start_info;
zx_status_t status = PrepStart(guest, dispatcher, &start_info);
if (status != ZX_OK) {
return status;
}
return balloon_->Start(std::move(start_info));
}
zx_status_t VirtioBalloon::ConfigureQueue(uint16_t queue, uint16_t size, zx_gpaddr_t desc,
zx_gpaddr_t avail, zx_gpaddr_t used) {
return balloon_->ConfigureQueue(queue, size, desc, avail, used);
}
zx_status_t VirtioBalloon::Ready(uint32_t negotiated_features) {
return balloon_->Ready(negotiated_features);
}
void VirtioBalloon::GetNumPages(GetNumPagesCallback callback) {
uint32_t actual;
{
std::lock_guard<std::mutex> lock(device_config_.mutex);
actual = config_.actual;
}
callback(actual);
}
void VirtioBalloon::RequestNumPages(uint32_t num_pages) {
{
std::lock_guard<std::mutex> lock(device_config_.mutex);
config_.num_pages = num_pages;
}
// Send a config change interrupt to the guest.
zx_status_t status = Interrupt(VirtioQueue::SET_CONFIG | VirtioQueue::TRY_INTERRUPT);
if (status != ZX_OK) {
FX_LOGS(ERROR) << "Failed to generate configuration interrupt " << status;
}
}
void VirtioBalloon::GetMemStats(GetMemStatsCallback callback) {
stats_->GetMemStats(std::move(callback));
}