cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

qmp-cmds.c (9395B)


      1/*
      2 * QEMU Management Protocol commands
      3 *
      4 * Copyright IBM, Corp. 2011
      5 *
      6 * Authors:
      7 *  Anthony Liguori   <aliguori@us.ibm.com>
      8 *
      9 * This work is licensed under the terms of the GNU GPL, version 2.  See
     10 * the COPYING file in the top-level directory.
     11 *
     12 * Contributions after 2012-01-13 are licensed under the terms of the
     13 * GNU GPL, version 2 or (at your option) any later version.
     14 */
     15
     16#include "qemu/osdep.h"
     17#include "qemu-common.h"
     18#include "qemu/cutils.h"
     19#include "qemu/option.h"
     20#include "monitor/monitor.h"
     21#include "sysemu/sysemu.h"
     22#include "qemu/config-file.h"
     23#include "qemu/uuid.h"
     24#include "chardev/char.h"
     25#include "ui/qemu-spice.h"
     26#include "ui/console.h"
     27#include "sysemu/kvm.h"
     28#include "sysemu/runstate.h"
     29#include "sysemu/runstate-action.h"
     30#include "sysemu/blockdev.h"
     31#include "sysemu/block-backend.h"
     32#include "qapi/error.h"
     33#include "qapi/qapi-commands-acpi.h"
     34#include "qapi/qapi-commands-block.h"
     35#include "qapi/qapi-commands-control.h"
     36#include "qapi/qapi-commands-machine.h"
     37#include "qapi/qapi-commands-misc.h"
     38#include "qapi/qapi-commands-ui.h"
     39#include "qapi/qmp/qerror.h"
     40#include "hw/mem/memory-device.h"
     41#include "hw/acpi/acpi_dev_interface.h"
     42
     43NameInfo *qmp_query_name(Error **errp)
     44{
     45    NameInfo *info = g_malloc0(sizeof(*info));
     46
     47    if (qemu_name) {
     48        info->has_name = true;
     49        info->name = g_strdup(qemu_name);
     50    }
     51
     52    return info;
     53}
     54
     55KvmInfo *qmp_query_kvm(Error **errp)
     56{
     57    KvmInfo *info = g_malloc0(sizeof(*info));
     58
     59    info->enabled = kvm_enabled();
     60    info->present = accel_find("kvm");
     61
     62    return info;
     63}
     64
     65UuidInfo *qmp_query_uuid(Error **errp)
     66{
     67    UuidInfo *info = g_malloc0(sizeof(*info));
     68
     69    info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid);
     70    return info;
     71}
     72
     73void qmp_quit(Error **errp)
     74{
     75    shutdown_action = SHUTDOWN_ACTION_POWEROFF;
     76    qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT);
     77}
     78
     79void qmp_stop(Error **errp)
     80{
     81    /* if there is a dump in background, we should wait until the dump
     82     * finished */
     83    if (dump_in_progress()) {
     84        error_setg(errp, "There is a dump in process, please wait.");
     85        return;
     86    }
     87
     88    if (runstate_check(RUN_STATE_INMIGRATE)) {
     89        autostart = 0;
     90    } else {
     91        vm_stop(RUN_STATE_PAUSED);
     92    }
     93}
     94
     95void qmp_system_reset(Error **errp)
     96{
     97    qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP_SYSTEM_RESET);
     98}
     99
    100void qmp_system_powerdown(Error **errp)
    101{
    102    qemu_system_powerdown_request();
    103}
    104
    105void qmp_cont(Error **errp)
    106{
    107    BlockBackend *blk;
    108    BlockJob *job;
    109    Error *local_err = NULL;
    110
    111    /* if there is a dump in background, we should wait until the dump
    112     * finished */
    113    if (dump_in_progress()) {
    114        error_setg(errp, "There is a dump in process, please wait.");
    115        return;
    116    }
    117
    118    if (runstate_needs_reset()) {
    119        error_setg(errp, "Resetting the Virtual Machine is required");
    120        return;
    121    } else if (runstate_check(RUN_STATE_SUSPENDED)) {
    122        return;
    123    } else if (runstate_check(RUN_STATE_FINISH_MIGRATE)) {
    124        error_setg(errp, "Migration is not finalized yet");
    125        return;
    126    }
    127
    128    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
    129        blk_iostatus_reset(blk);
    130    }
    131
    132    for (job = block_job_next(NULL); job; job = block_job_next(job)) {
    133        block_job_iostatus_reset(job);
    134    }
    135
    136    /* Continuing after completed migration. Images have been inactivated to
    137     * allow the destination to take control. Need to get control back now.
    138     *
    139     * If there are no inactive block nodes (e.g. because the VM was just
    140     * paused rather than completing a migration), bdrv_inactivate_all() simply
    141     * doesn't do anything. */
    142    bdrv_invalidate_cache_all(&local_err);
    143    if (local_err) {
    144        error_propagate(errp, local_err);
    145        return;
    146    }
    147
    148    if (runstate_check(RUN_STATE_INMIGRATE)) {
    149        autostart = 1;
    150    } else {
    151        vm_start();
    152    }
    153}
    154
    155void qmp_system_wakeup(Error **errp)
    156{
    157    if (!qemu_wakeup_suspend_enabled()) {
    158        error_setg(errp,
    159                   "wake-up from suspend is not supported by this guest");
    160        return;
    161    }
    162
    163    qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, errp);
    164}
    165
    166void qmp_set_password(const char *protocol, const char *password,
    167                      bool has_connected, const char *connected, Error **errp)
    168{
    169    int disconnect_if_connected = 0;
    170    int fail_if_connected = 0;
    171    int rc;
    172
    173    if (has_connected) {
    174        if (strcmp(connected, "fail") == 0) {
    175            fail_if_connected = 1;
    176        } else if (strcmp(connected, "disconnect") == 0) {
    177            disconnect_if_connected = 1;
    178        } else if (strcmp(connected, "keep") == 0) {
    179            /* nothing */
    180        } else {
    181            error_setg(errp, QERR_INVALID_PARAMETER, "connected");
    182            return;
    183        }
    184    }
    185
    186    if (strcmp(protocol, "spice") == 0) {
    187        if (!qemu_using_spice(errp)) {
    188            return;
    189        }
    190        rc = qemu_spice.set_passwd(password, fail_if_connected,
    191                                   disconnect_if_connected);
    192    } else if (strcmp(protocol, "vnc") == 0) {
    193        if (fail_if_connected || disconnect_if_connected) {
    194            /* vnc supports "connected=keep" only */
    195            error_setg(errp, QERR_INVALID_PARAMETER, "connected");
    196            return;
    197        }
    198        /* Note that setting an empty password will not disable login through
    199         * this interface. */
    200        rc = vnc_display_password(NULL, password);
    201    } else {
    202        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "protocol",
    203                   "'vnc' or 'spice'");
    204        return;
    205    }
    206
    207    if (rc != 0) {
    208        error_setg(errp, "Could not set password");
    209    }
    210}
    211
    212void qmp_expire_password(const char *protocol, const char *whenstr,
    213                         Error **errp)
    214{
    215    time_t when;
    216    int rc;
    217
    218    if (strcmp(whenstr, "now") == 0) {
    219        when = 0;
    220    } else if (strcmp(whenstr, "never") == 0) {
    221        when = TIME_MAX;
    222    } else if (whenstr[0] == '+') {
    223        when = time(NULL) + strtoull(whenstr+1, NULL, 10);
    224    } else {
    225        when = strtoull(whenstr, NULL, 10);
    226    }
    227
    228    if (strcmp(protocol, "spice") == 0) {
    229        if (!qemu_using_spice(errp)) {
    230            return;
    231        }
    232        rc = qemu_spice.set_pw_expire(when);
    233    } else if (strcmp(protocol, "vnc") == 0) {
    234        rc = vnc_display_pw_expire(NULL, when);
    235    } else {
    236        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "protocol",
    237                   "'vnc' or 'spice'");
    238        return;
    239    }
    240
    241    if (rc != 0) {
    242        error_setg(errp, "Could not set password expire time");
    243    }
    244}
    245
    246#ifdef CONFIG_VNC
    247void qmp_change_vnc_password(const char *password, Error **errp)
    248{
    249    if (vnc_display_password(NULL, password) < 0) {
    250        error_setg(errp, "Could not set password");
    251    }
    252}
    253#endif
    254
    255void qmp_add_client(const char *protocol, const char *fdname,
    256                    bool has_skipauth, bool skipauth, bool has_tls, bool tls,
    257                    Error **errp)
    258{
    259    Chardev *s;
    260    int fd;
    261
    262    fd = monitor_get_fd(monitor_cur(), fdname, errp);
    263    if (fd < 0) {
    264        return;
    265    }
    266
    267    if (strcmp(protocol, "spice") == 0) {
    268        if (!qemu_using_spice(errp)) {
    269            close(fd);
    270            return;
    271        }
    272        skipauth = has_skipauth ? skipauth : false;
    273        tls = has_tls ? tls : false;
    274        if (qemu_spice.display_add_client(fd, skipauth, tls) < 0) {
    275            error_setg(errp, "spice failed to add client");
    276            close(fd);
    277        }
    278        return;
    279#ifdef CONFIG_VNC
    280    } else if (strcmp(protocol, "vnc") == 0) {
    281        skipauth = has_skipauth ? skipauth : false;
    282        vnc_display_add_client(NULL, fd, skipauth);
    283        return;
    284#endif
    285    } else if ((s = qemu_chr_find(protocol)) != NULL) {
    286        if (qemu_chr_add_client(s, fd) < 0) {
    287            error_setg(errp, "failed to add client");
    288            close(fd);
    289            return;
    290        }
    291        return;
    292    }
    293
    294    error_setg(errp, "protocol '%s' is invalid", protocol);
    295    close(fd);
    296}
    297
    298
    299MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
    300{
    301    return qmp_memory_device_list();
    302}
    303
    304ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp)
    305{
    306    bool ambig;
    307    ACPIOSTInfoList *head = NULL;
    308    ACPIOSTInfoList **prev = &head;
    309    Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, &ambig);
    310
    311    if (obj) {
    312        AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj);
    313        AcpiDeviceIf *adev = ACPI_DEVICE_IF(obj);
    314
    315        adevc->ospm_status(adev, &prev);
    316    } else {
    317        error_setg(errp, "command is not supported, missing ACPI device");
    318    }
    319
    320    return head;
    321}
    322
    323MemoryInfo *qmp_query_memory_size_summary(Error **errp)
    324{
    325    MemoryInfo *mem_info = g_malloc0(sizeof(MemoryInfo));
    326    MachineState *ms = MACHINE(qdev_get_machine());
    327
    328    mem_info->base_memory = ms->ram_size;
    329
    330    mem_info->plugged_memory = get_plugged_memory_size();
    331    mem_info->has_plugged_memory =
    332        mem_info->plugged_memory != (uint64_t)-1;
    333
    334    return mem_info;
    335}
    336
    337void qmp_display_reload(DisplayReloadOptions *arg, Error **errp)
    338{
    339    switch (arg->type) {
    340    case DISPLAY_RELOAD_TYPE_VNC:
    341#ifdef CONFIG_VNC
    342        if (arg->u.vnc.has_tls_certs && arg->u.vnc.tls_certs) {
    343            vnc_display_reload_certs(NULL, errp);
    344        }
    345#else
    346        error_setg(errp, "vnc is invalid, missing 'CONFIG_VNC'");
    347#endif
    348        break;
    349    default:
    350        abort();
    351    }
    352}