virtio: add driver for the virtio balloon device
* how-to for qemu: command line option: -balloon virtio
* in the monitor view
- to switch the vm size to 500MB: balloon 500
- to display balloon info: info balloon
This commit is contained in:
committed by
Adrien Destugues
parent
2284eb4875
commit
fe11711026
@@ -7,4 +7,6 @@ KernelAddon virtio :
|
|||||||
VirtioDevice.cpp
|
VirtioDevice.cpp
|
||||||
VirtioModule.cpp
|
VirtioModule.cpp
|
||||||
VirtioQueue.cpp
|
VirtioQueue.cpp
|
||||||
|
VirtioBalloonDevice.cpp
|
||||||
|
virtio_balloon.cpp
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -0,0 +1,258 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018, Jérôme Duval, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "VirtioBalloonPrivate.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <util/AutoLock.h>
|
||||||
|
|
||||||
|
#include "virtio_balloon.h"
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
get_feature_name(uint32 feature)
|
||||||
|
{
|
||||||
|
switch (feature) {
|
||||||
|
case VIRTIO_BALLOON_F_MUST_TELL_HOST:
|
||||||
|
return "must tell host";
|
||||||
|
case VIRTIO_BALLOON_F_STATS_VQ:
|
||||||
|
return "stats vq";
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VirtioBalloonDevice::VirtioBalloonDevice(device_node* node)
|
||||||
|
:
|
||||||
|
fNode(node),
|
||||||
|
fVirtio(NULL),
|
||||||
|
fVirtioDevice(NULL),
|
||||||
|
fStatus(B_NO_INIT),
|
||||||
|
fDesiredSize(0),
|
||||||
|
fActualSize(0)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
B_INITIALIZE_SPINLOCK(&fInterruptLock);
|
||||||
|
fQueueCondition.Init(this, "virtio balloon transfer");
|
||||||
|
fConfigCondition.Init(this, "virtio balloon config");
|
||||||
|
|
||||||
|
get_memory_map(fBuffer, sizeof(fBuffer), &fEntry, 1);
|
||||||
|
|
||||||
|
// get the Virtio device from our parent's parent
|
||||||
|
device_node* parent = gDeviceManager->get_parent_node(node);
|
||||||
|
device_node* virtioParent = gDeviceManager->get_parent_node(parent);
|
||||||
|
gDeviceManager->put_node(parent);
|
||||||
|
|
||||||
|
gDeviceManager->get_driver(virtioParent, (driver_module_info**)&fVirtio,
|
||||||
|
(void**)&fVirtioDevice);
|
||||||
|
gDeviceManager->put_node(virtioParent);
|
||||||
|
|
||||||
|
fVirtio->negotiate_features(fVirtioDevice,
|
||||||
|
0, &fFeatures, &get_feature_name);
|
||||||
|
|
||||||
|
fStatus = fVirtio->alloc_queues(fVirtioDevice, 2, fVirtioQueues);
|
||||||
|
if (fStatus != B_OK) {
|
||||||
|
ERROR("queue allocation failed (%s)\n", strerror(fStatus));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fStatus = fVirtio->setup_interrupt(fVirtioDevice, _ConfigCallback, this);
|
||||||
|
if (fStatus != B_OK) {
|
||||||
|
ERROR("interrupt setup failed (%s)\n", strerror(fStatus));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fStatus = fVirtio->queue_setup_interrupt(fVirtioQueues[0],
|
||||||
|
_QueueCallback, fVirtioQueues[0]);
|
||||||
|
if (fStatus != B_OK) {
|
||||||
|
ERROR("queue interrupt setup failed (%s)\n", strerror(fStatus));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fStatus = fVirtio->queue_setup_interrupt(fVirtioQueues[1],
|
||||||
|
_QueueCallback, fVirtioQueues[1]);
|
||||||
|
if (fStatus != B_OK) {
|
||||||
|
ERROR("queue interrupt setup failed (%s)\n", strerror(fStatus));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fThread = spawn_kernel_thread(&_ThreadEntry, "virtio balloon thread",
|
||||||
|
B_NORMAL_PRIORITY, this);
|
||||||
|
if (fThread < 0) {
|
||||||
|
fStatus = fThread;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resume_thread(fThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VirtioBalloonDevice::~VirtioBalloonDevice()
|
||||||
|
{
|
||||||
|
fRunning = false;
|
||||||
|
if (fThread >= 0) {
|
||||||
|
int32 result;
|
||||||
|
wait_for_thread(fThread, &result);
|
||||||
|
fThread = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
VirtioBalloonDevice::InitCheck()
|
||||||
|
{
|
||||||
|
return fStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
VirtioBalloonDevice::_ThreadEntry(void* data)
|
||||||
|
{
|
||||||
|
VirtioBalloonDevice* device = (VirtioBalloonDevice*)data;
|
||||||
|
return device->_Thread();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
VirtioBalloonDevice::_Thread()
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
while (fRunning) {
|
||||||
|
if (fDesiredSize == fActualSize) {
|
||||||
|
TRACE("waiting for a config change\n");
|
||||||
|
ConditionVariableEntry configConditionEntry;
|
||||||
|
fConfigCondition.Add(&configConditionEntry);
|
||||||
|
status_t result = configConditionEntry.Wait(B_CAN_INTERRUPT);
|
||||||
|
if (result != B_OK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fDesiredSize = _DesiredSize();
|
||||||
|
TRACE("finished waiting: requested %" B_PRIu32 " instead of %" B_PRIu32
|
||||||
|
"\n", fDesiredSize, fActualSize);
|
||||||
|
}
|
||||||
|
::virtio_queue queue;
|
||||||
|
if (fDesiredSize > fActualSize) {
|
||||||
|
int32 count = min_c(PAGES_COUNT, fDesiredSize - fActualSize);
|
||||||
|
TRACE("allocating %" B_PRIu32 " pages\n", count);
|
||||||
|
queue = fVirtioQueues[0];
|
||||||
|
|
||||||
|
vm_page_reservation reservation;
|
||||||
|
vm_page_reserve_pages(&reservation, count, VM_PRIORITY_SYSTEM);
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
//TRACE("allocating page %" B_PRIu32 " pages\n", i);
|
||||||
|
vm_page* page = vm_page_allocate_page(&reservation,
|
||||||
|
PAGE_STATE_WIRED);
|
||||||
|
if (page == NULL) {
|
||||||
|
TRACE("allocating failed\n");
|
||||||
|
count = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PageInfo* info = new PageInfo;
|
||||||
|
info->page = page;
|
||||||
|
fBuffer[i] = (phys_addr_t)page->physical_page_number
|
||||||
|
>> (PAGE_SHIFT - VIRTIO_BALLOON_PFN_SHIFT);
|
||||||
|
fPages.Add(info);
|
||||||
|
}
|
||||||
|
fEntry.size = count * sizeof(uint32);
|
||||||
|
fActualSize += count;
|
||||||
|
} else {
|
||||||
|
int32 count = min_c(PAGES_COUNT, fActualSize - fDesiredSize);
|
||||||
|
TRACE("freeing %" B_PRIu32 " pages\n", count);
|
||||||
|
queue = fVirtioQueues[1];
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
PageInfo* info = fPages.RemoveHead();
|
||||||
|
if (info == NULL) {
|
||||||
|
TRACE("remove failed\n");
|
||||||
|
count = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vm_page* page = info->page;
|
||||||
|
fBuffer[i] = (phys_addr_t)page->physical_page_number
|
||||||
|
>> (PAGE_SHIFT - VIRTIO_BALLOON_PFN_SHIFT);
|
||||||
|
vm_page_free(NULL, page);
|
||||||
|
}
|
||||||
|
fEntry.size = count * sizeof(uint32);
|
||||||
|
fActualSize -= count;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionVariableEntry queueConditionEntry;
|
||||||
|
fQueueCondition.Add(&queueConditionEntry);
|
||||||
|
|
||||||
|
// alloc or release
|
||||||
|
TRACE("queue request\n");
|
||||||
|
status_t result = fVirtio->queue_request(queue, &fEntry, NULL,
|
||||||
|
queue);
|
||||||
|
if (result != B_OK) {
|
||||||
|
ERROR("queueing failed (%s)\n", strerror(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (fVirtio->queue_dequeue(queue, NULL) == NULL) {
|
||||||
|
TRACE("wait for response\n");
|
||||||
|
queueConditionEntry.Wait(B_CAN_INTERRUPT);
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("update size\n");
|
||||||
|
_UpdateSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
VirtioBalloonDevice::_ConfigCallback(void* driverCookie)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
VirtioBalloonDevice* device = (VirtioBalloonDevice*)driverCookie;
|
||||||
|
|
||||||
|
SpinLocker locker(device->fInterruptLock);
|
||||||
|
device->fConfigCondition.NotifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
VirtioBalloonDevice::_QueueCallback(void* driverCookie, void* cookie)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
VirtioBalloonDevice* device = (VirtioBalloonDevice*)driverCookie;
|
||||||
|
|
||||||
|
SpinLocker locker(device->fInterruptLock);
|
||||||
|
device->fQueueCondition.NotifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
VirtioBalloonDevice::_DesiredSize()
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
uint32 desiredSize;
|
||||||
|
|
||||||
|
status_t status = fVirtio->read_device_config(fVirtioDevice,
|
||||||
|
offsetof(struct virtio_balloon_config, num_pages),
|
||||||
|
&desiredSize, sizeof(desiredSize));
|
||||||
|
if (status != B_OK)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return B_LENDIAN_TO_HOST_INT32(desiredSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
VirtioBalloonDevice::_UpdateSize()
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
TRACE("_UpdateSize %u\n", fActualSize);
|
||||||
|
uint32 actualSize = B_HOST_TO_LENDIAN_INT32(fActualSize);
|
||||||
|
return fVirtio->write_device_config(fVirtioDevice,
|
||||||
|
offsetof(struct virtio_balloon_config, actual),
|
||||||
|
&actualSize, sizeof(actualSize));
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018, Jérôme Duval, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef VIRTIO_BALLOON_PRIVATE_H
|
||||||
|
#define VIRTIO_BALLOON_PRIVATE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <condition_variable.h>
|
||||||
|
#include <lock.h>
|
||||||
|
#include <virtio.h>
|
||||||
|
#include <vm/vm_page.h>
|
||||||
|
|
||||||
|
|
||||||
|
//#define TRACE_VIRTIO_BALLOON
|
||||||
|
#ifdef TRACE_VIRTIO_BALLOON
|
||||||
|
# define TRACE(x...) dprintf("virtio_balloon: " x)
|
||||||
|
#else
|
||||||
|
# define TRACE(x...) ;
|
||||||
|
#endif
|
||||||
|
#define ERROR(x...) dprintf("\33[33mvirtio_rng:\33[0m " x)
|
||||||
|
#define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
|
||||||
|
|
||||||
|
|
||||||
|
extern device_manager_info* gDeviceManager;
|
||||||
|
|
||||||
|
|
||||||
|
#define PAGES_COUNT 256
|
||||||
|
|
||||||
|
|
||||||
|
struct PageInfo : DoublyLinkedListLinkImpl<PageInfo> {
|
||||||
|
vm_page *page;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef DoublyLinkedList<PageInfo> PageInfoList;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class VirtioBalloonDevice {
|
||||||
|
public:
|
||||||
|
VirtioBalloonDevice(device_node* node);
|
||||||
|
~VirtioBalloonDevice();
|
||||||
|
|
||||||
|
status_t InitCheck();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void _ConfigCallback(void* driverCookie);
|
||||||
|
static void _QueueCallback(void* driverCookie,
|
||||||
|
void *cookie);
|
||||||
|
|
||||||
|
static int32 _ThreadEntry(void *data);
|
||||||
|
int32 _Thread();
|
||||||
|
|
||||||
|
uint32 _DesiredSize();
|
||||||
|
status_t _UpdateSize();
|
||||||
|
|
||||||
|
device_node* fNode;
|
||||||
|
|
||||||
|
virtio_device_interface* fVirtio;
|
||||||
|
virtio_device* fVirtioDevice;
|
||||||
|
|
||||||
|
status_t fStatus;
|
||||||
|
uint32 fFeatures;
|
||||||
|
::virtio_queue fVirtioQueues[2];
|
||||||
|
|
||||||
|
physical_entry fEntry;
|
||||||
|
uint32 fBuffer[PAGES_COUNT];
|
||||||
|
|
||||||
|
thread_id fThread;
|
||||||
|
uint32 fDesiredSize;
|
||||||
|
uint32 fActualSize;
|
||||||
|
|
||||||
|
spinlock fInterruptLock;
|
||||||
|
ConditionVariable fQueueCondition;
|
||||||
|
ConditionVariable fConfigCondition;
|
||||||
|
bool fRunning;
|
||||||
|
|
||||||
|
PageInfoList fPages;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VIRTIO_BALLOON_PRIVATE_H
|
||||||
@@ -315,9 +315,16 @@ module_dependency module_dependencies[] = {
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern struct driver_module_info sVirtioBalloonDriver;
|
||||||
|
extern struct driver_module_info sVirtioBalloonDeviceInterface;
|
||||||
|
|
||||||
|
|
||||||
module_info *modules[] = {
|
module_info *modules[] = {
|
||||||
(module_info *)&virtio_for_controller_module,
|
(module_info *)&virtio_for_controller_module,
|
||||||
(module_info *)&virtio_device_module,
|
(module_info *)&virtio_device_module,
|
||||||
|
(module_info *)&sVirtioBalloonDriver,
|
||||||
|
(module_info *)&sVirtioBalloonDeviceInterface,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018, Jérôme Duval, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "VirtioBalloonPrivate.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define VIRTIO_BALLOON_CONTROLLER_PRETTY_NAME "Virtio Balloon Device"
|
||||||
|
|
||||||
|
#define VIRTIO_BALLOON_DRIVER_MODULE_NAME "drivers/misc/virtio_balloon/driver_v1"
|
||||||
|
#define VIRTIO_BALLOON_DEVICE_MODULE_NAME "drivers/misc/virtio_balloon/device_v1"
|
||||||
|
|
||||||
|
|
||||||
|
extern device_manager_info *gDeviceManager;
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Device module interface
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
virtio_balloon_init_device(device_node *node, void **_cookie)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
VirtioBalloonDevice *device = new(std::nothrow)
|
||||||
|
VirtioBalloonDevice(node);
|
||||||
|
if (device == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
status_t status = device->InitCheck();
|
||||||
|
if (status < B_OK) {
|
||||||
|
delete device;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
*_cookie = device;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
virtio_balloon_uninit_device(void *cookie)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
VirtioBalloonDevice *device = (VirtioBalloonDevice*)cookie;
|
||||||
|
|
||||||
|
delete device;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Driver module interface
|
||||||
|
|
||||||
|
|
||||||
|
static float
|
||||||
|
virtio_balloon_supports_device(device_node *parent)
|
||||||
|
{
|
||||||
|
const char *bus;
|
||||||
|
uint16 deviceType;
|
||||||
|
|
||||||
|
// make sure parent is really the Virtio bus manager
|
||||||
|
if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (strcmp(bus, "virtio"))
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
// check whether it's really a Virtio Entropy Device
|
||||||
|
if (gDeviceManager->get_attr_uint16(parent, VIRTIO_DEVICE_TYPE_ITEM,
|
||||||
|
&deviceType, true) != B_OK || deviceType != VIRTIO_DEVICE_ID_BALLOON)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
TRACE("Virtio Balloon device found!\n");
|
||||||
|
|
||||||
|
return 0.6f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
virtio_balloon_register_device(device_node *parent)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
device_attr attrs[] = {
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
return gDeviceManager->register_node(parent, VIRTIO_BALLOON_DRIVER_MODULE_NAME,
|
||||||
|
attrs, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
virtio_balloon_init_driver(device_node *node, void **_cookie)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
*_cookie = node;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
virtio_balloon_register_child_devices(void *cookie)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
device_node *node = (device_node *)cookie;
|
||||||
|
|
||||||
|
device_attr attrs[] = {
|
||||||
|
{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
|
||||||
|
{ string: VIRTIO_BALLOON_CONTROLLER_PRETTY_NAME }},
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
return gDeviceManager->register_node(node,
|
||||||
|
VIRTIO_BALLOON_DEVICE_MODULE_NAME, attrs, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
std_ops(int32 op, ...)
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case B_MODULE_INIT:
|
||||||
|
case B_MODULE_UNINIT:
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
driver_module_info sVirtioBalloonDeviceInterface = {
|
||||||
|
{
|
||||||
|
VIRTIO_BALLOON_DEVICE_MODULE_NAME,
|
||||||
|
0,
|
||||||
|
std_ops
|
||||||
|
},
|
||||||
|
NULL, // supported devices
|
||||||
|
NULL, // register node
|
||||||
|
virtio_balloon_init_device,
|
||||||
|
virtio_balloon_uninit_device,
|
||||||
|
NULL, // register child devices
|
||||||
|
NULL, // rescan
|
||||||
|
NULL // bus_removed
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
driver_module_info sVirtioBalloonDriver = {
|
||||||
|
{
|
||||||
|
VIRTIO_BALLOON_DRIVER_MODULE_NAME,
|
||||||
|
0,
|
||||||
|
std_ops
|
||||||
|
},
|
||||||
|
virtio_balloon_supports_device,
|
||||||
|
virtio_balloon_register_device,
|
||||||
|
virtio_balloon_init_driver,
|
||||||
|
NULL, // uninit_driver,
|
||||||
|
virtio_balloon_register_child_devices,
|
||||||
|
NULL, // rescan
|
||||||
|
NULL, // device_removed
|
||||||
|
};
|
||||||
|
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/*-
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* This header is BSD licensed so anyone can use the definitions to implement
|
||||||
|
* compatible drivers/servers.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of IBM nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _VIRTIO_BALLOON_H
|
||||||
|
#define _VIRTIO_BALLOON_H
|
||||||
|
|
||||||
|
/* Feature bits. */
|
||||||
|
#define VIRTIO_BALLOON_F_MUST_TELL_HOST 0x1 /* Tell before reclaiming pages */
|
||||||
|
#define VIRTIO_BALLOON_F_STATS_VQ 0x2 /* Memory stats virtqueue */
|
||||||
|
|
||||||
|
/* Size of a PFN in the balloon interface. */
|
||||||
|
#define VIRTIO_BALLOON_PFN_SHIFT 12
|
||||||
|
|
||||||
|
struct virtio_balloon_config {
|
||||||
|
/* Number of pages host wants Guest to give up. */
|
||||||
|
uint32_t num_pages;
|
||||||
|
|
||||||
|
/* Number of pages we've actually got in balloon. */
|
||||||
|
uint32_t actual;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VIRTIO_BALLOON_S_SWAP_IN 0 /* Amount of memory swapped in */
|
||||||
|
#define VIRTIO_BALLOON_S_SWAP_OUT 1 /* Amount of memory swapped out */
|
||||||
|
#define VIRTIO_BALLOON_S_MAJFLT 2 /* Number of major faults */
|
||||||
|
#define VIRTIO_BALLOON_S_MINFLT 3 /* Number of minor faults */
|
||||||
|
#define VIRTIO_BALLOON_S_MEMFREE 4 /* Total amount of free memory */
|
||||||
|
#define VIRTIO_BALLOON_S_MEMTOT 5 /* Total amount of memory */
|
||||||
|
#define VIRTIO_BALLOON_S_NR 6
|
||||||
|
|
||||||
|
struct virtio_balloon_stat {
|
||||||
|
uint16_t tag;
|
||||||
|
uint64_t val;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#endif /* _VIRTIO_BALLOON_H */
|
||||||
Reference in New Issue
Block a user