xref: /qemu/hw/misc/pvpanic.c (revision a27bd6c779badb8d76e4430d810ef710a1b98f4e)
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 "sysemu/sysemu.h"
17eec3d2adSHu Tao #include "qemu/log.h"
180b8fa32fSMarkus Armbruster #include "qemu/module.h"
19eec3d2adSHu Tao 
2010a584b2SHu Tao #include "hw/nvram/fw_cfg.h"
21*a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
220d5d8a3aSPhilippe Mathieu-Daudé #include "hw/misc/pvpanic.h"
2310a584b2SHu Tao 
24eec3d2adSHu Tao /* The bit of supported pv event */
25eec3d2adSHu Tao #define PVPANIC_F_PANICKED      0
26eec3d2adSHu Tao 
27eec3d2adSHu Tao /* The pv event value */
28eec3d2adSHu Tao #define PVPANIC_PANICKED        (1 << PVPANIC_F_PANICKED)
29eec3d2adSHu Tao 
30eec3d2adSHu Tao #define ISA_PVPANIC_DEVICE(obj)    \
310d5d8a3aSPhilippe Mathieu-Daudé     OBJECT_CHECK(PVPanicState, (obj), TYPE_PVPANIC)
32eec3d2adSHu Tao 
33eec3d2adSHu Tao static void handle_event(int event)
34eec3d2adSHu Tao {
35eec3d2adSHu Tao     static bool logged;
36eec3d2adSHu Tao 
37eec3d2adSHu Tao     if (event & ~PVPANIC_PANICKED && !logged) {
38eec3d2adSHu Tao         qemu_log_mask(LOG_GUEST_ERROR, "pvpanic: unknown event %#x.\n", event);
39eec3d2adSHu Tao         logged = true;
40eec3d2adSHu Tao     }
41eec3d2adSHu Tao 
42eec3d2adSHu Tao     if (event & PVPANIC_PANICKED) {
43c86f106bSAnton Nefedov         qemu_system_guest_panicked(NULL);
44eec3d2adSHu Tao         return;
45eec3d2adSHu Tao     }
46eec3d2adSHu Tao }
47eec3d2adSHu Tao 
48eec3d2adSHu Tao #include "hw/isa/isa.h"
49eec3d2adSHu Tao 
50eec3d2adSHu Tao typedef struct PVPanicState {
51eec3d2adSHu Tao     ISADevice parent_obj;
52eec3d2adSHu Tao 
53eec3d2adSHu Tao     MemoryRegion io;
54eec3d2adSHu Tao     uint16_t ioport;
55eec3d2adSHu Tao } PVPanicState;
56eec3d2adSHu Tao 
57eec3d2adSHu Tao /* return supported events on read */
58eec3d2adSHu Tao static uint64_t pvpanic_ioport_read(void *opaque, hwaddr addr, unsigned size)
59eec3d2adSHu Tao {
60eec3d2adSHu Tao     return PVPANIC_PANICKED;
61eec3d2adSHu Tao }
62eec3d2adSHu Tao 
63eec3d2adSHu Tao static void pvpanic_ioport_write(void *opaque, hwaddr addr, uint64_t val,
64eec3d2adSHu Tao                                  unsigned size)
65eec3d2adSHu Tao {
66eec3d2adSHu Tao     handle_event(val);
67eec3d2adSHu Tao }
68eec3d2adSHu Tao 
69eec3d2adSHu Tao static const MemoryRegionOps pvpanic_ops = {
70eec3d2adSHu Tao     .read = pvpanic_ioport_read,
71eec3d2adSHu Tao     .write = pvpanic_ioport_write,
72eec3d2adSHu Tao     .impl = {
73eec3d2adSHu Tao         .min_access_size = 1,
74eec3d2adSHu Tao         .max_access_size = 1,
75eec3d2adSHu Tao     },
76eec3d2adSHu Tao };
77eec3d2adSHu Tao 
78db895a1eSAndreas Färber static void pvpanic_isa_initfn(Object *obj)
79eec3d2adSHu Tao {
80db895a1eSAndreas Färber     PVPanicState *s = ISA_PVPANIC_DEVICE(obj);
81db895a1eSAndreas Färber 
823c161542SPaolo Bonzini     memory_region_init_io(&s->io, OBJECT(s), &pvpanic_ops, s, "pvpanic", 1);
83db895a1eSAndreas Färber }
84db895a1eSAndreas Färber 
85db895a1eSAndreas Färber static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp)
86db895a1eSAndreas Färber {
87db895a1eSAndreas Färber     ISADevice *d = ISA_DEVICE(dev);
88eec3d2adSHu Tao     PVPanicState *s = ISA_PVPANIC_DEVICE(dev);
89a5d3f640SMarcel Apfelbaum     FWCfgState *fw_cfg = fw_cfg_find();
90a5d3f640SMarcel Apfelbaum     uint16_t *pvpanic_port;
91a5d3f640SMarcel Apfelbaum 
92a5d3f640SMarcel Apfelbaum     if (!fw_cfg) {
93a5d3f640SMarcel Apfelbaum         return;
94a5d3f640SMarcel Apfelbaum     }
95a5d3f640SMarcel Apfelbaum 
96a5d3f640SMarcel Apfelbaum     pvpanic_port = g_malloc(sizeof(*pvpanic_port));
97a5d3f640SMarcel Apfelbaum     *pvpanic_port = cpu_to_le16(s->ioport);
98a5d3f640SMarcel Apfelbaum     fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port,
99a5d3f640SMarcel Apfelbaum                     sizeof(*pvpanic_port));
100eec3d2adSHu Tao 
101db895a1eSAndreas Färber     isa_register_ioport(d, &s->io, s->ioport);
102eec3d2adSHu Tao }
103eec3d2adSHu Tao 
104eec3d2adSHu Tao static Property pvpanic_isa_properties[] = {
105309cd62dSMichael S. Tsirkin     DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicState, ioport, 0x505),
106eec3d2adSHu Tao     DEFINE_PROP_END_OF_LIST(),
107eec3d2adSHu Tao };
108eec3d2adSHu Tao 
109eec3d2adSHu Tao static void pvpanic_isa_class_init(ObjectClass *klass, void *data)
110eec3d2adSHu Tao {
111eec3d2adSHu Tao     DeviceClass *dc = DEVICE_CLASS(klass);
112eec3d2adSHu Tao 
113db895a1eSAndreas Färber     dc->realize = pvpanic_isa_realizefn;
114eec3d2adSHu Tao     dc->props = pvpanic_isa_properties;
115a5d3f640SMarcel Apfelbaum     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
116eec3d2adSHu Tao }
117eec3d2adSHu Tao 
118eec3d2adSHu Tao static TypeInfo pvpanic_isa_info = {
1190d5d8a3aSPhilippe Mathieu-Daudé     .name          = TYPE_PVPANIC,
120eec3d2adSHu Tao     .parent        = TYPE_ISA_DEVICE,
121eec3d2adSHu Tao     .instance_size = sizeof(PVPanicState),
122db895a1eSAndreas Färber     .instance_init = pvpanic_isa_initfn,
123eec3d2adSHu Tao     .class_init    = pvpanic_isa_class_init,
124eec3d2adSHu Tao };
125eec3d2adSHu Tao 
126eec3d2adSHu Tao static void pvpanic_register_types(void)
127eec3d2adSHu Tao {
128eec3d2adSHu Tao     type_register_static(&pvpanic_isa_info);
129eec3d2adSHu Tao }
130eec3d2adSHu Tao 
131eec3d2adSHu Tao type_init(pvpanic_register_types)
132