Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 1 | /* |
| 2 | * QEMU simulated pvpanic device. |
| 3 | * |
| 4 | * Copyright Fujitsu, Corp. 2013 |
| 5 | * |
| 6 | * Authors: |
| 7 | * Wen Congyang <wency@cn.fujitsu.com> |
| 8 | * Hu Tao <hutao@cn.fujitsu.com> |
| 9 | * |
| 10 | * This work is licensed under the terms of the GNU GPL, version 2 or later. |
| 11 | * See the COPYING file in the top-level directory. |
| 12 | * |
| 13 | */ |
| 14 | |
Peter Maydell | 0d1c978 | 2016-01-26 18:17:17 +0000 | [diff] [blame] | 15 | #include "qemu/osdep.h" |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 16 | #include "qemu/log.h" |
Markus Armbruster | 0b8fa32 | 2019-05-23 16:35:07 +0200 | [diff] [blame] | 17 | #include "qemu/module.h" |
Markus Armbruster | 54d3123 | 2019-08-12 07:23:59 +0200 | [diff] [blame] | 18 | #include "sysemu/runstate.h" |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 19 | |
Hu Tao | 10a584b | 2013-04-26 11:24:44 +0800 | [diff] [blame] | 20 | #include "hw/nvram/fw_cfg.h" |
Markus Armbruster | a27bd6c | 2019-08-12 07:23:51 +0200 | [diff] [blame] | 21 | #include "hw/qdev-properties.h" |
Philippe Mathieu-Daudé | 0d5d8a3 | 2017-10-17 13:44:23 -0300 | [diff] [blame] | 22 | #include "hw/misc/pvpanic.h" |
Eduardo Habkost | db1015e | 2020-09-03 16:43:22 -0400 | [diff] [blame] | 23 | #include "qom/object.h" |
Hu Tao | 10a584b | 2013-04-26 11:24:44 +0800 | [diff] [blame] | 24 | |
zhenwei pi | 7dc58de | 2020-01-14 10:31:02 +0800 | [diff] [blame] | 25 | /* The bit of supported pv event, TODO: include uapi header and remove this */ |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 26 | #define PVPANIC_F_PANICKED 0 |
zhenwei pi | 7dc58de | 2020-01-14 10:31:02 +0800 | [diff] [blame] | 27 | #define PVPANIC_F_CRASHLOADED 1 |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 28 | |
| 29 | /* The pv event value */ |
| 30 | #define PVPANIC_PANICKED (1 << PVPANIC_F_PANICKED) |
zhenwei pi | 7dc58de | 2020-01-14 10:31:02 +0800 | [diff] [blame] | 31 | #define PVPANIC_CRASHLOADED (1 << PVPANIC_F_CRASHLOADED) |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 32 | |
Eduardo Habkost | db1015e | 2020-09-03 16:43:22 -0400 | [diff] [blame] | 33 | typedef struct PVPanicState PVPanicState; |
Eduardo Habkost | 8110fa1 | 2020-08-31 17:07:33 -0400 | [diff] [blame] | 34 | DECLARE_INSTANCE_CHECKER(PVPanicState, ISA_PVPANIC_DEVICE, |
| 35 | TYPE_PVPANIC) |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 36 | |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 37 | static void handle_event(int event) |
| 38 | { |
| 39 | static bool logged; |
| 40 | |
zhenwei pi | 7dc58de | 2020-01-14 10:31:02 +0800 | [diff] [blame] | 41 | if (event & ~(PVPANIC_PANICKED | PVPANIC_CRASHLOADED) && !logged) { |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 42 | qemu_log_mask(LOG_GUEST_ERROR, "pvpanic: unknown event %#x.\n", event); |
| 43 | logged = true; |
| 44 | } |
| 45 | |
| 46 | if (event & PVPANIC_PANICKED) { |
Anton Nefedov | c86f106 | 2017-02-14 09:25:23 +0300 | [diff] [blame] | 47 | qemu_system_guest_panicked(NULL); |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 48 | return; |
| 49 | } |
zhenwei pi | 7dc58de | 2020-01-14 10:31:02 +0800 | [diff] [blame] | 50 | |
| 51 | if (event & PVPANIC_CRASHLOADED) { |
| 52 | qemu_system_guest_crashloaded(NULL); |
| 53 | return; |
| 54 | } |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 55 | } |
| 56 | |
| 57 | #include "hw/isa/isa.h" |
| 58 | |
Eduardo Habkost | db1015e | 2020-09-03 16:43:22 -0400 | [diff] [blame] | 59 | struct PVPanicState { |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 60 | ISADevice parent_obj; |
| 61 | |
| 62 | MemoryRegion io; |
| 63 | uint16_t ioport; |
Eduardo Habkost | db1015e | 2020-09-03 16:43:22 -0400 | [diff] [blame] | 64 | }; |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 65 | |
| 66 | /* return supported events on read */ |
| 67 | static uint64_t pvpanic_ioport_read(void *opaque, hwaddr addr, unsigned size) |
| 68 | { |
| 69 | return PVPANIC_PANICKED; |
| 70 | } |
| 71 | |
| 72 | static void pvpanic_ioport_write(void *opaque, hwaddr addr, uint64_t val, |
| 73 | unsigned size) |
| 74 | { |
| 75 | handle_event(val); |
| 76 | } |
| 77 | |
| 78 | static const MemoryRegionOps pvpanic_ops = { |
| 79 | .read = pvpanic_ioport_read, |
| 80 | .write = pvpanic_ioport_write, |
| 81 | .impl = { |
| 82 | .min_access_size = 1, |
| 83 | .max_access_size = 1, |
| 84 | }, |
| 85 | }; |
| 86 | |
Andreas Färber | db895a1 | 2012-11-25 02:37:14 +0100 | [diff] [blame] | 87 | static void pvpanic_isa_initfn(Object *obj) |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 88 | { |
Andreas Färber | db895a1 | 2012-11-25 02:37:14 +0100 | [diff] [blame] | 89 | PVPanicState *s = ISA_PVPANIC_DEVICE(obj); |
| 90 | |
Paolo Bonzini | 3c16154 | 2013-06-06 21:25:08 -0400 | [diff] [blame] | 91 | memory_region_init_io(&s->io, OBJECT(s), &pvpanic_ops, s, "pvpanic", 1); |
Andreas Färber | db895a1 | 2012-11-25 02:37:14 +0100 | [diff] [blame] | 92 | } |
| 93 | |
| 94 | static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp) |
| 95 | { |
| 96 | ISADevice *d = ISA_DEVICE(dev); |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 97 | PVPanicState *s = ISA_PVPANIC_DEVICE(dev); |
Marcel Apfelbaum | a5d3f64 | 2013-08-11 18:10:43 +0300 | [diff] [blame] | 98 | FWCfgState *fw_cfg = fw_cfg_find(); |
| 99 | uint16_t *pvpanic_port; |
| 100 | |
| 101 | if (!fw_cfg) { |
| 102 | return; |
| 103 | } |
| 104 | |
| 105 | pvpanic_port = g_malloc(sizeof(*pvpanic_port)); |
| 106 | *pvpanic_port = cpu_to_le16(s->ioport); |
| 107 | fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port, |
| 108 | sizeof(*pvpanic_port)); |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 109 | |
Andreas Färber | db895a1 | 2012-11-25 02:37:14 +0100 | [diff] [blame] | 110 | isa_register_ioport(d, &s->io, s->ioport); |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 111 | } |
| 112 | |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 113 | static Property pvpanic_isa_properties[] = { |
Michael S. Tsirkin | 309cd62 | 2013-07-24 18:56:12 +0300 | [diff] [blame] | 114 | DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicState, ioport, 0x505), |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 115 | DEFINE_PROP_END_OF_LIST(), |
| 116 | }; |
| 117 | |
| 118 | static void pvpanic_isa_class_init(ObjectClass *klass, void *data) |
| 119 | { |
| 120 | DeviceClass *dc = DEVICE_CLASS(klass); |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 121 | |
Andreas Färber | db895a1 | 2012-11-25 02:37:14 +0100 | [diff] [blame] | 122 | dc->realize = pvpanic_isa_realizefn; |
Marc-André Lureau | 4f67d30 | 2020-01-10 19:30:32 +0400 | [diff] [blame] | 123 | device_class_set_props(dc, pvpanic_isa_properties); |
Marcel Apfelbaum | a5d3f64 | 2013-08-11 18:10:43 +0300 | [diff] [blame] | 124 | set_bit(DEVICE_CATEGORY_MISC, dc->categories); |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 125 | } |
| 126 | |
| 127 | static TypeInfo pvpanic_isa_info = { |
Philippe Mathieu-Daudé | 0d5d8a3 | 2017-10-17 13:44:23 -0300 | [diff] [blame] | 128 | .name = TYPE_PVPANIC, |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 129 | .parent = TYPE_ISA_DEVICE, |
| 130 | .instance_size = sizeof(PVPanicState), |
Andreas Färber | db895a1 | 2012-11-25 02:37:14 +0100 | [diff] [blame] | 131 | .instance_init = pvpanic_isa_initfn, |
Hu Tao | eec3d2a | 2013-04-26 11:24:42 +0800 | [diff] [blame] | 132 | .class_init = pvpanic_isa_class_init, |
| 133 | }; |
| 134 | |
| 135 | static void pvpanic_register_types(void) |
| 136 | { |
| 137 | type_register_static(&pvpanic_isa_info); |
| 138 | } |
| 139 | |
| 140 | type_init(pvpanic_register_types) |