xref: /qemu/hw/misc/vmcoreinfo.c (revision e4ea952f)
16e43353fSMarc-André Lureau /*
26e43353fSMarc-André Lureau  * Virtual Machine coreinfo device
36e43353fSMarc-André Lureau  *
46e43353fSMarc-André Lureau  * Copyright (C) 2017 Red Hat, Inc.
56e43353fSMarc-André Lureau  *
66e43353fSMarc-André Lureau  * Authors: Marc-André Lureau <marcandre.lureau@redhat.com>
76e43353fSMarc-André Lureau  *
86e43353fSMarc-André Lureau  * This work is licensed under the terms of the GNU GPL, version 2 or later.
96e43353fSMarc-André Lureau  * See the COPYING file in the top-level directory.
106e43353fSMarc-André Lureau  *
116e43353fSMarc-André Lureau  */
120b8fa32fSMarkus Armbruster 
136e43353fSMarc-André Lureau #include "qemu/osdep.h"
146e43353fSMarc-André Lureau #include "qapi/error.h"
150b8fa32fSMarkus Armbruster #include "qemu/module.h"
1671e8a915SMarkus Armbruster #include "sysemu/reset.h"
176e43353fSMarc-André Lureau #include "hw/nvram/fw_cfg.h"
18d6454270SMarkus Armbruster #include "migration/vmstate.h"
196e43353fSMarc-André Lureau #include "hw/misc/vmcoreinfo.h"
206e43353fSMarc-André Lureau 
fw_cfg_vmci_write(void * dev,off_t offset,size_t len)216e43353fSMarc-André Lureau static void fw_cfg_vmci_write(void *dev, off_t offset, size_t len)
226e43353fSMarc-André Lureau {
236e43353fSMarc-André Lureau     VMCoreInfoState *s = VMCOREINFO(dev);
246e43353fSMarc-André Lureau 
256e43353fSMarc-André Lureau     s->has_vmcoreinfo = offset == 0 && len == sizeof(s->vmcoreinfo)
265be5df72SMarc-André Lureau         && s->vmcoreinfo.guest_format != FW_CFG_VMCOREINFO_FORMAT_NONE;
276e43353fSMarc-André Lureau }
286e43353fSMarc-André Lureau 
vmcoreinfo_reset(void * dev)296e43353fSMarc-André Lureau static void vmcoreinfo_reset(void *dev)
306e43353fSMarc-André Lureau {
316e43353fSMarc-André Lureau     VMCoreInfoState *s = VMCOREINFO(dev);
326e43353fSMarc-André Lureau 
336e43353fSMarc-André Lureau     s->has_vmcoreinfo = false;
346e43353fSMarc-André Lureau     memset(&s->vmcoreinfo, 0, sizeof(s->vmcoreinfo));
355be5df72SMarc-André Lureau     s->vmcoreinfo.host_format = cpu_to_le16(FW_CFG_VMCOREINFO_FORMAT_ELF);
366e43353fSMarc-André Lureau }
376e43353fSMarc-André Lureau 
vmcoreinfo_realize(DeviceState * dev,Error ** errp)386e43353fSMarc-André Lureau static void vmcoreinfo_realize(DeviceState *dev, Error **errp)
396e43353fSMarc-André Lureau {
406e43353fSMarc-André Lureau     VMCoreInfoState *s = VMCOREINFO(dev);
416e43353fSMarc-André Lureau     FWCfgState *fw_cfg = fw_cfg_find();
42c3b1642bSMarc-André Lureau     /* for gdb script dump-guest-memory.py */
43c3b1642bSMarc-André Lureau     static VMCoreInfoState * volatile vmcoreinfo_state G_GNUC_UNUSED;
446e43353fSMarc-André Lureau 
456e43353fSMarc-André Lureau     /* Given that this function is executing, there is at least one VMCOREINFO
466e43353fSMarc-André Lureau      * device. Check if there are several.
476e43353fSMarc-André Lureau      */
486e43353fSMarc-André Lureau     if (!vmcoreinfo_find()) {
496e43353fSMarc-André Lureau         error_setg(errp, "at most one %s device is permitted",
506e43353fSMarc-André Lureau                    VMCOREINFO_DEVICE);
516e43353fSMarc-André Lureau         return;
526e43353fSMarc-André Lureau     }
536e43353fSMarc-André Lureau 
546e43353fSMarc-André Lureau     if (!fw_cfg || !fw_cfg->dma_enabled) {
556e43353fSMarc-André Lureau         error_setg(errp, "%s device requires fw_cfg with DMA",
566e43353fSMarc-André Lureau                    VMCOREINFO_DEVICE);
576e43353fSMarc-André Lureau         return;
586e43353fSMarc-André Lureau     }
596e43353fSMarc-André Lureau 
605be5df72SMarc-André Lureau     fw_cfg_add_file_callback(fw_cfg, FW_CFG_VMCOREINFO_FILENAME,
616e43353fSMarc-André Lureau                              NULL, fw_cfg_vmci_write, s,
626e43353fSMarc-André Lureau                              &s->vmcoreinfo, sizeof(s->vmcoreinfo), false);
636e43353fSMarc-André Lureau 
6488552b16SPhilippe Mathieu-Daudé     /*
6588552b16SPhilippe Mathieu-Daudé      * This device requires to register a global reset because it is
6688552b16SPhilippe Mathieu-Daudé      * not plugged to a bus (which, as its QOM parent, would reset it).
6788552b16SPhilippe Mathieu-Daudé      */
686e43353fSMarc-André Lureau     qemu_register_reset(vmcoreinfo_reset, dev);
69c3b1642bSMarc-André Lureau     vmcoreinfo_state = s;
706e43353fSMarc-André Lureau }
716e43353fSMarc-André Lureau 
726e43353fSMarc-André Lureau static const VMStateDescription vmstate_vmcoreinfo = {
736e43353fSMarc-André Lureau     .name = "vmcoreinfo",
746e43353fSMarc-André Lureau     .version_id = 1,
756e43353fSMarc-André Lureau     .minimum_version_id = 1,
76*e4ea952fSRichard Henderson     .fields = (const VMStateField[]) {
776e43353fSMarc-André Lureau         VMSTATE_BOOL(has_vmcoreinfo, VMCoreInfoState),
786e43353fSMarc-André Lureau         VMSTATE_UINT16(vmcoreinfo.host_format, VMCoreInfoState),
796e43353fSMarc-André Lureau         VMSTATE_UINT16(vmcoreinfo.guest_format, VMCoreInfoState),
806e43353fSMarc-André Lureau         VMSTATE_UINT32(vmcoreinfo.size, VMCoreInfoState),
816e43353fSMarc-André Lureau         VMSTATE_UINT64(vmcoreinfo.paddr, VMCoreInfoState),
826e43353fSMarc-André Lureau         VMSTATE_END_OF_LIST()
836e43353fSMarc-André Lureau     },
846e43353fSMarc-André Lureau };
856e43353fSMarc-André Lureau 
vmcoreinfo_device_class_init(ObjectClass * klass,void * data)866e43353fSMarc-André Lureau static void vmcoreinfo_device_class_init(ObjectClass *klass, void *data)
876e43353fSMarc-André Lureau {
886e43353fSMarc-André Lureau     DeviceClass *dc = DEVICE_CLASS(klass);
896e43353fSMarc-André Lureau 
906e43353fSMarc-André Lureau     dc->vmsd = &vmstate_vmcoreinfo;
916e43353fSMarc-André Lureau     dc->realize = vmcoreinfo_realize;
926e43353fSMarc-André Lureau     dc->hotpluggable = false;
93b948bb55SMarc-André Lureau     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
946e43353fSMarc-André Lureau }
956e43353fSMarc-André Lureau 
966e43353fSMarc-André Lureau static const TypeInfo vmcoreinfo_device_info = {
976e43353fSMarc-André Lureau     .name          = VMCOREINFO_DEVICE,
986e43353fSMarc-André Lureau     .parent        = TYPE_DEVICE,
996e43353fSMarc-André Lureau     .instance_size = sizeof(VMCoreInfoState),
1006e43353fSMarc-André Lureau     .class_init    = vmcoreinfo_device_class_init,
1016e43353fSMarc-André Lureau };
1026e43353fSMarc-André Lureau 
vmcoreinfo_register_types(void)1036e43353fSMarc-André Lureau static void vmcoreinfo_register_types(void)
1046e43353fSMarc-André Lureau {
1056e43353fSMarc-André Lureau     type_register_static(&vmcoreinfo_device_info);
1066e43353fSMarc-André Lureau }
1076e43353fSMarc-André Lureau 
1086e43353fSMarc-André Lureau type_init(vmcoreinfo_register_types)
109