xref: /qemu/hw/misc/vmcoreinfo.c (revision 06b40d250ecfa1633209c2e431a7a38acfd03a98)
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"
1632cad1ffSPhilippe Mathieu-Daudé #include "system/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 * opaque,off_t offset,size_t len)21924e1be1SPhilippe Mathieu-Daudé static void fw_cfg_vmci_write(void *opaque, off_t offset, size_t len)
226e43353fSMarc-André Lureau {
23924e1be1SPhilippe Mathieu-Daudé     VMCoreInfoState *s = opaque;
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_hold(Object * obj,ResetType type)29b7700c9fSPhilippe Mathieu-Daudé static void vmcoreinfo_reset_hold(Object *obj, ResetType type)
306e43353fSMarc-André Lureau {
31b7700c9fSPhilippe Mathieu-Daudé     VMCoreInfoState *s = VMCOREINFO(obj);
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",
50b2d4e9f3SPhilippe Mathieu-Daudé                    TYPE_VMCOREINFO);
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",
56b2d4e9f3SPhilippe Mathieu-Daudé                    TYPE_VMCOREINFO);
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é      */
68b7700c9fSPhilippe Mathieu-Daudé     qemu_register_resettable(OBJECT(s));
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,
76e4ea952fSRichard 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,const void * data)86*12d1a768SPhilippe Mathieu-Daudé static void vmcoreinfo_device_class_init(ObjectClass *klass, const void *data)
876e43353fSMarc-André Lureau {
886e43353fSMarc-André Lureau     DeviceClass *dc = DEVICE_CLASS(klass);
89b7700c9fSPhilippe Mathieu-Daudé     ResettableClass *rc = RESETTABLE_CLASS(klass);
906e43353fSMarc-André Lureau 
916e43353fSMarc-André Lureau     dc->vmsd = &vmstate_vmcoreinfo;
926e43353fSMarc-André Lureau     dc->realize = vmcoreinfo_realize;
936e43353fSMarc-André Lureau     dc->hotpluggable = false;
94b948bb55SMarc-André Lureau     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
95b7700c9fSPhilippe Mathieu-Daudé     rc->phases.hold = vmcoreinfo_reset_hold;
966e43353fSMarc-André Lureau }
976e43353fSMarc-André Lureau 
983154922cSPhilippe Mathieu-Daudé static const TypeInfo vmcoreinfo_types[] = {
993154922cSPhilippe Mathieu-Daudé     {
100b2d4e9f3SPhilippe Mathieu-Daudé         .name           = TYPE_VMCOREINFO,
1016e43353fSMarc-André Lureau         .parent         = TYPE_DEVICE,
1026e43353fSMarc-André Lureau         .instance_size  = sizeof(VMCoreInfoState),
1036e43353fSMarc-André Lureau         .class_init     = vmcoreinfo_device_class_init,
1043154922cSPhilippe Mathieu-Daudé     }
1056e43353fSMarc-André Lureau };
1066e43353fSMarc-André Lureau 
1073154922cSPhilippe Mathieu-Daudé DEFINE_TYPES(vmcoreinfo_types)
108