qemu/balloon.c
<<
>>
Prefs
   1/*
   2 * Generic Balloon handlers and management
   3 *
   4 * Copyright (c) 2003-2008 Fabrice Bellard
   5 * Copyright (C) 2011 Red Hat, Inc.
   6 * Copyright (C) 2011 Amit Shah <amit.shah@redhat.com>
   7 *
   8 * Permission is hereby granted, free of charge, to any person obtaining a copy
   9 * of this software and associated documentation files (the "Software"), to deal
  10 * in the Software without restriction, including without limitation the rights
  11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12 * copies of the Software, and to permit persons to whom the Software is
  13 * furnished to do so, subject to the following conditions:
  14 *
  15 * The above copyright notice and this permission notice shall be included in
  16 * all copies or substantial portions of the Software.
  17 *
  18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24 * THE SOFTWARE.
  25 */
  26
  27#include "monitor/monitor.h"
  28#include "exec/cpu-common.h"
  29#include "sysemu/kvm.h"
  30#include "sysemu/balloon.h"
  31#include "trace.h"
  32#include "qmp-commands.h"
  33#include "qapi/qmp/qjson.h"
  34
  35static QEMUBalloonEvent *balloon_event_fn;
  36static QEMUBalloonStatus *balloon_stat_fn;
  37static void *balloon_opaque;
  38
  39int qemu_add_balloon_handler(QEMUBalloonEvent *event_func,
  40                             QEMUBalloonStatus *stat_func, void *opaque)
  41{
  42    if (balloon_event_fn || balloon_stat_fn || balloon_opaque) {
  43        /* We're already registered one balloon handler.  How many can
  44         * a guest really have?
  45         */
  46        error_report("Another balloon device already registered");
  47        return -1;
  48    }
  49    balloon_event_fn = event_func;
  50    balloon_stat_fn = stat_func;
  51    balloon_opaque = opaque;
  52    return 0;
  53}
  54
  55void qemu_remove_balloon_handler(void *opaque)
  56{
  57    if (balloon_opaque != opaque) {
  58        return;
  59    }
  60    balloon_event_fn = NULL;
  61    balloon_stat_fn = NULL;
  62    balloon_opaque = NULL;
  63}
  64
  65static int qemu_balloon(ram_addr_t target)
  66{
  67    if (!balloon_event_fn) {
  68        return 0;
  69    }
  70    trace_balloon_event(balloon_opaque, target);
  71    balloon_event_fn(balloon_opaque, target);
  72    return 1;
  73}
  74
  75static int qemu_balloon_status(BalloonInfo *info)
  76{
  77    if (!balloon_stat_fn) {
  78        return 0;
  79    }
  80    balloon_stat_fn(balloon_opaque, info);
  81    return 1;
  82}
  83
  84void qemu_balloon_changed(int64_t actual)
  85{
  86    QObject *data;
  87
  88    data = qobject_from_jsonf("{ 'actual': %" PRId64 " }",
  89                              actual);
  90
  91    monitor_protocol_event(QEVENT_BALLOON_CHANGE, data);
  92
  93    qobject_decref(data);
  94}
  95
  96
  97BalloonInfo *qmp_query_balloon(Error **errp)
  98{
  99    BalloonInfo *info;
 100
 101    if (kvm_enabled() && !kvm_has_sync_mmu()) {
 102        error_set(errp, QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
 103        return NULL;
 104    }
 105
 106    info = g_malloc0(sizeof(*info));
 107
 108    if (qemu_balloon_status(info) == 0) {
 109        error_set(errp, QERR_DEVICE_NOT_ACTIVE, "balloon");
 110        qapi_free_BalloonInfo(info);
 111        return NULL;
 112    }
 113
 114    return info;
 115}
 116
 117void qmp_balloon(int64_t value, Error **errp)
 118{
 119    if (kvm_enabled() && !kvm_has_sync_mmu()) {
 120        error_set(errp, QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
 121        return;
 122    }
 123
 124    if (value <= 0) {
 125        error_set(errp, QERR_INVALID_PARAMETER_VALUE, "target", "a size");
 126        return;
 127    }
 128    
 129    if (qemu_balloon(value) == 0) {
 130        error_set(errp, QERR_DEVICE_NOT_ACTIVE, "balloon");
 131    }
 132}
 133