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