qemu/hw/misc/vmcoreinfo.c
<<
>>
Prefs
   1/*
   2 * Virtual Machine coreinfo device
   3 *
   4 * Copyright (C) 2017 Red Hat, Inc.
   5 *
   6 * Authors: Marc-André Lureau <marcandre.lureau@redhat.com>
   7 *
   8 * This work is licensed under the terms of the GNU GPL, version 2 or later.
   9 * See the COPYING file in the top-level directory.
  10 *
  11 */
  12
  13#include "qemu/osdep.h"
  14#include "qapi/error.h"
  15#include "qemu/module.h"
  16#include "hw/nvram/fw_cfg.h"
  17#include "hw/misc/vmcoreinfo.h"
  18
  19static void fw_cfg_vmci_write(void *dev, off_t offset, size_t len)
  20{
  21    VMCoreInfoState *s = VMCOREINFO(dev);
  22
  23    s->has_vmcoreinfo = offset == 0 && len == sizeof(s->vmcoreinfo)
  24        && s->vmcoreinfo.guest_format != FW_CFG_VMCOREINFO_FORMAT_NONE;
  25}
  26
  27static void vmcoreinfo_reset(void *dev)
  28{
  29    VMCoreInfoState *s = VMCOREINFO(dev);
  30
  31    s->has_vmcoreinfo = false;
  32    memset(&s->vmcoreinfo, 0, sizeof(s->vmcoreinfo));
  33    s->vmcoreinfo.host_format = cpu_to_le16(FW_CFG_VMCOREINFO_FORMAT_ELF);
  34}
  35
  36static void vmcoreinfo_realize(DeviceState *dev, Error **errp)
  37{
  38    VMCoreInfoState *s = VMCOREINFO(dev);
  39    FWCfgState *fw_cfg = fw_cfg_find();
  40    /* for gdb script dump-guest-memory.py */
  41    static VMCoreInfoState * volatile vmcoreinfo_state G_GNUC_UNUSED;
  42
  43    /* Given that this function is executing, there is at least one VMCOREINFO
  44     * device. Check if there are several.
  45     */
  46    if (!vmcoreinfo_find()) {
  47        error_setg(errp, "at most one %s device is permitted",
  48                   VMCOREINFO_DEVICE);
  49        return;
  50    }
  51
  52    if (!fw_cfg || !fw_cfg->dma_enabled) {
  53        error_setg(errp, "%s device requires fw_cfg with DMA",
  54                   VMCOREINFO_DEVICE);
  55        return;
  56    }
  57
  58    fw_cfg_add_file_callback(fw_cfg, FW_CFG_VMCOREINFO_FILENAME,
  59                             NULL, fw_cfg_vmci_write, s,
  60                             &s->vmcoreinfo, sizeof(s->vmcoreinfo), false);
  61
  62    qemu_register_reset(vmcoreinfo_reset, dev);
  63    vmcoreinfo_state = s;
  64}
  65
  66static const VMStateDescription vmstate_vmcoreinfo = {
  67    .name = "vmcoreinfo",
  68    .version_id = 1,
  69    .minimum_version_id = 1,
  70    .fields = (VMStateField[]) {
  71        VMSTATE_BOOL(has_vmcoreinfo, VMCoreInfoState),
  72        VMSTATE_UINT16(vmcoreinfo.host_format, VMCoreInfoState),
  73        VMSTATE_UINT16(vmcoreinfo.guest_format, VMCoreInfoState),
  74        VMSTATE_UINT32(vmcoreinfo.size, VMCoreInfoState),
  75        VMSTATE_UINT64(vmcoreinfo.paddr, VMCoreInfoState),
  76        VMSTATE_END_OF_LIST()
  77    },
  78};
  79
  80static void vmcoreinfo_device_class_init(ObjectClass *klass, void *data)
  81{
  82    DeviceClass *dc = DEVICE_CLASS(klass);
  83
  84    dc->vmsd = &vmstate_vmcoreinfo;
  85    dc->realize = vmcoreinfo_realize;
  86    dc->hotpluggable = false;
  87    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
  88}
  89
  90static const TypeInfo vmcoreinfo_device_info = {
  91    .name          = VMCOREINFO_DEVICE,
  92    .parent        = TYPE_DEVICE,
  93    .instance_size = sizeof(VMCoreInfoState),
  94    .class_init    = vmcoreinfo_device_class_init,
  95};
  96
  97static void vmcoreinfo_register_types(void)
  98{
  99    type_register_static(&vmcoreinfo_device_info);
 100}
 101
 102type_init(vmcoreinfo_register_types)
 103