xref: /qemu/hw/misc/pvpanic.c (revision db1015e92e04835c9eb50c29625fe566d1202dbd)
1eec3d2adSHu Tao /*
2eec3d2adSHu Tao  * QEMU simulated pvpanic device.
3eec3d2adSHu Tao  *
4eec3d2adSHu Tao  * Copyright Fujitsu, Corp. 2013
5eec3d2adSHu Tao  *
6eec3d2adSHu Tao  * Authors:
7eec3d2adSHu Tao  *     Wen Congyang <wency@cn.fujitsu.com>
8eec3d2adSHu Tao  *     Hu Tao <hutao@cn.fujitsu.com>
9eec3d2adSHu Tao  *
10eec3d2adSHu Tao  * This work is licensed under the terms of the GNU GPL, version 2 or later.
11eec3d2adSHu Tao  * See the COPYING file in the top-level directory.
12eec3d2adSHu Tao  *
13eec3d2adSHu Tao  */
14eec3d2adSHu Tao 
150d1c9782SPeter Maydell #include "qemu/osdep.h"
16eec3d2adSHu Tao #include "qemu/log.h"
170b8fa32fSMarkus Armbruster #include "qemu/module.h"
1854d31236SMarkus Armbruster #include "sysemu/runstate.h"
19eec3d2adSHu Tao 
2010a584b2SHu Tao #include "hw/nvram/fw_cfg.h"
21a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
220d5d8a3aSPhilippe Mathieu-Daudé #include "hw/misc/pvpanic.h"
23*db1015e9SEduardo Habkost #include "qom/object.h"
2410a584b2SHu Tao 
257dc58deeSzhenwei pi /* The bit of supported pv event, TODO: include uapi header and remove this */
26eec3d2adSHu Tao #define PVPANIC_F_PANICKED      0
277dc58deeSzhenwei pi #define PVPANIC_F_CRASHLOADED   1
28eec3d2adSHu Tao 
29eec3d2adSHu Tao /* The pv event value */
30eec3d2adSHu Tao #define PVPANIC_PANICKED        (1 << PVPANIC_F_PANICKED)
317dc58deeSzhenwei pi #define PVPANIC_CRASHLOADED     (1 << PVPANIC_F_CRASHLOADED)
32eec3d2adSHu Tao 
33*db1015e9SEduardo Habkost typedef struct PVPanicState PVPanicState;
34eec3d2adSHu Tao #define ISA_PVPANIC_DEVICE(obj)    \
350d5d8a3aSPhilippe Mathieu-Daudé     OBJECT_CHECK(PVPanicState, (obj), TYPE_PVPANIC)
36eec3d2adSHu Tao 
37eec3d2adSHu Tao static void handle_event(int event)
38eec3d2adSHu Tao {
39eec3d2adSHu Tao     static bool logged;
40eec3d2adSHu Tao 
417dc58deeSzhenwei pi     if (event & ~(PVPANIC_PANICKED | PVPANIC_CRASHLOADED) && !logged) {
42eec3d2adSHu Tao         qemu_log_mask(LOG_GUEST_ERROR, "pvpanic: unknown event %#x.\n", event);
43eec3d2adSHu Tao         logged = true;
44eec3d2adSHu Tao     }
45eec3d2adSHu Tao 
46eec3d2adSHu Tao     if (event & PVPANIC_PANICKED) {
47c86f106bSAnton Nefedov         qemu_system_guest_panicked(NULL);
48eec3d2adSHu Tao         return;
49eec3d2adSHu Tao     }
507dc58deeSzhenwei pi 
517dc58deeSzhenwei pi     if (event & PVPANIC_CRASHLOADED) {
527dc58deeSzhenwei pi         qemu_system_guest_crashloaded(NULL);
537dc58deeSzhenwei pi         return;
547dc58deeSzhenwei pi     }
55eec3d2adSHu Tao }
56eec3d2adSHu Tao 
57eec3d2adSHu Tao #include "hw/isa/isa.h"
58eec3d2adSHu Tao 
59*db1015e9SEduardo Habkost struct PVPanicState {
60eec3d2adSHu Tao     ISADevice parent_obj;
61eec3d2adSHu Tao 
62eec3d2adSHu Tao     MemoryRegion io;
63eec3d2adSHu Tao     uint16_t ioport;
64*db1015e9SEduardo Habkost };
65eec3d2adSHu Tao 
66eec3d2adSHu Tao /* return supported events on read */
67eec3d2adSHu Tao static uint64_t pvpanic_ioport_read(void *opaque, hwaddr addr, unsigned size)
68eec3d2adSHu Tao {
69eec3d2adSHu Tao     return PVPANIC_PANICKED;
70eec3d2adSHu Tao }
71eec3d2adSHu Tao 
72eec3d2adSHu Tao static void pvpanic_ioport_write(void *opaque, hwaddr addr, uint64_t val,
73eec3d2adSHu Tao                                  unsigned size)
74eec3d2adSHu Tao {
75eec3d2adSHu Tao     handle_event(val);
76eec3d2adSHu Tao }
77eec3d2adSHu Tao 
78eec3d2adSHu Tao static const MemoryRegionOps pvpanic_ops = {
79eec3d2adSHu Tao     .read = pvpanic_ioport_read,
80eec3d2adSHu Tao     .write = pvpanic_ioport_write,
81eec3d2adSHu Tao     .impl = {
82eec3d2adSHu Tao         .min_access_size = 1,
83eec3d2adSHu Tao         .max_access_size = 1,
84eec3d2adSHu Tao     },
85eec3d2adSHu Tao };
86eec3d2adSHu Tao 
87db895a1eSAndreas Färber static void pvpanic_isa_initfn(Object *obj)
88eec3d2adSHu Tao {
89db895a1eSAndreas Färber     PVPanicState *s = ISA_PVPANIC_DEVICE(obj);
90db895a1eSAndreas Färber 
913c161542SPaolo Bonzini     memory_region_init_io(&s->io, OBJECT(s), &pvpanic_ops, s, "pvpanic", 1);
92db895a1eSAndreas Färber }
93db895a1eSAndreas Färber 
94db895a1eSAndreas Färber static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp)
95db895a1eSAndreas Färber {
96db895a1eSAndreas Färber     ISADevice *d = ISA_DEVICE(dev);
97eec3d2adSHu Tao     PVPanicState *s = ISA_PVPANIC_DEVICE(dev);
98a5d3f640SMarcel Apfelbaum     FWCfgState *fw_cfg = fw_cfg_find();
99a5d3f640SMarcel Apfelbaum     uint16_t *pvpanic_port;
100a5d3f640SMarcel Apfelbaum 
101a5d3f640SMarcel Apfelbaum     if (!fw_cfg) {
102a5d3f640SMarcel Apfelbaum         return;
103a5d3f640SMarcel Apfelbaum     }
104a5d3f640SMarcel Apfelbaum 
105a5d3f640SMarcel Apfelbaum     pvpanic_port = g_malloc(sizeof(*pvpanic_port));
106a5d3f640SMarcel Apfelbaum     *pvpanic_port = cpu_to_le16(s->ioport);
107a5d3f640SMarcel Apfelbaum     fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port,
108a5d3f640SMarcel Apfelbaum                     sizeof(*pvpanic_port));
109eec3d2adSHu Tao 
110db895a1eSAndreas Färber     isa_register_ioport(d, &s->io, s->ioport);
111eec3d2adSHu Tao }
112eec3d2adSHu Tao 
113eec3d2adSHu Tao static Property pvpanic_isa_properties[] = {
114309cd62dSMichael S. Tsirkin     DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicState, ioport, 0x505),
115eec3d2adSHu Tao     DEFINE_PROP_END_OF_LIST(),
116eec3d2adSHu Tao };
117eec3d2adSHu Tao 
118eec3d2adSHu Tao static void pvpanic_isa_class_init(ObjectClass *klass, void *data)
119eec3d2adSHu Tao {
120eec3d2adSHu Tao     DeviceClass *dc = DEVICE_CLASS(klass);
121eec3d2adSHu Tao 
122db895a1eSAndreas Färber     dc->realize = pvpanic_isa_realizefn;
1234f67d30bSMarc-André Lureau     device_class_set_props(dc, pvpanic_isa_properties);
124a5d3f640SMarcel Apfelbaum     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
125eec3d2adSHu Tao }
126eec3d2adSHu Tao 
127eec3d2adSHu Tao static TypeInfo pvpanic_isa_info = {
1280d5d8a3aSPhilippe Mathieu-Daudé     .name          = TYPE_PVPANIC,
129eec3d2adSHu Tao     .parent        = TYPE_ISA_DEVICE,
130eec3d2adSHu Tao     .instance_size = sizeof(PVPanicState),
131db895a1eSAndreas Färber     .instance_init = pvpanic_isa_initfn,
132eec3d2adSHu Tao     .class_init    = pvpanic_isa_class_init,
133eec3d2adSHu Tao };
134eec3d2adSHu Tao 
135eec3d2adSHu Tao static void pvpanic_register_types(void)
136eec3d2adSHu Tao {
137eec3d2adSHu Tao     type_register_static(&pvpanic_isa_info);
138eec3d2adSHu Tao }
139eec3d2adSHu Tao 
140eec3d2adSHu Tao type_init(pvpanic_register_types)
141