qemu/hw/misc/pvpanic.c
<<
>>
Prefs
   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
  15#include "qemu/osdep.h"
  16#include "qapi/qmp/qobject.h"
  17#include "qapi/qmp/qjson.h"
  18#include "sysemu/sysemu.h"
  19#include "qemu/log.h"
  20
  21#include "hw/nvram/fw_cfg.h"
  22#include "hw/i386/pc.h"
  23#include "qapi-event.h"
  24
  25/* The bit of supported pv event */
  26#define PVPANIC_F_PANICKED      0
  27
  28/* The pv event value */
  29#define PVPANIC_PANICKED        (1 << PVPANIC_F_PANICKED)
  30
  31#define TYPE_ISA_PVPANIC_DEVICE    "pvpanic"
  32#define ISA_PVPANIC_DEVICE(obj)    \
  33    OBJECT_CHECK(PVPanicState, (obj), TYPE_ISA_PVPANIC_DEVICE)
  34
  35static void handle_event(int event)
  36{
  37    static bool logged;
  38
  39    if (event & ~PVPANIC_PANICKED && !logged) {
  40        qemu_log_mask(LOG_GUEST_ERROR, "pvpanic: unknown event %#x.\n", event);
  41        logged = true;
  42    }
  43
  44    if (event & PVPANIC_PANICKED) {
  45        qemu_system_guest_panicked();
  46        return;
  47    }
  48}
  49
  50#include "hw/isa/isa.h"
  51
  52typedef struct PVPanicState {
  53    ISADevice parent_obj;
  54
  55    MemoryRegion io;
  56    uint16_t ioport;
  57} PVPanicState;
  58
  59/* return supported events on read */
  60static uint64_t pvpanic_ioport_read(void *opaque, hwaddr addr, unsigned size)
  61{
  62    return PVPANIC_PANICKED;
  63}
  64
  65static void pvpanic_ioport_write(void *opaque, hwaddr addr, uint64_t val,
  66                                 unsigned size)
  67{
  68    handle_event(val);
  69}
  70
  71static const MemoryRegionOps pvpanic_ops = {
  72    .read = pvpanic_ioport_read,
  73    .write = pvpanic_ioport_write,
  74    .impl = {
  75        .min_access_size = 1,
  76        .max_access_size = 1,
  77    },
  78};
  79
  80static void pvpanic_isa_initfn(Object *obj)
  81{
  82    PVPanicState *s = ISA_PVPANIC_DEVICE(obj);
  83
  84    memory_region_init_io(&s->io, OBJECT(s), &pvpanic_ops, s, "pvpanic", 1);
  85}
  86
  87static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp)
  88{
  89    ISADevice *d = ISA_DEVICE(dev);
  90    PVPanicState *s = ISA_PVPANIC_DEVICE(dev);
  91    FWCfgState *fw_cfg = fw_cfg_find();
  92    uint16_t *pvpanic_port;
  93
  94    if (!fw_cfg) {
  95        return;
  96    }
  97
  98    pvpanic_port = g_malloc(sizeof(*pvpanic_port));
  99    *pvpanic_port = cpu_to_le16(s->ioport);
 100    fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port,
 101                    sizeof(*pvpanic_port));
 102
 103    isa_register_ioport(d, &s->io, s->ioport);
 104}
 105
 106#define PVPANIC_IOPORT_PROP "ioport"
 107
 108uint16_t pvpanic_port(void)
 109{
 110    Object *o = object_resolve_path_type("", TYPE_ISA_PVPANIC_DEVICE, NULL);
 111    if (!o) {
 112        return 0;
 113    }
 114    return object_property_get_int(o, PVPANIC_IOPORT_PROP, NULL);
 115}
 116
 117static Property pvpanic_isa_properties[] = {
 118    DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicState, ioport, 0x505),
 119    DEFINE_PROP_END_OF_LIST(),
 120};
 121
 122static void pvpanic_isa_class_init(ObjectClass *klass, void *data)
 123{
 124    DeviceClass *dc = DEVICE_CLASS(klass);
 125
 126    dc->realize = pvpanic_isa_realizefn;
 127    dc->props = pvpanic_isa_properties;
 128    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 129}
 130
 131static TypeInfo pvpanic_isa_info = {
 132    .name          = TYPE_ISA_PVPANIC_DEVICE,
 133    .parent        = TYPE_ISA_DEVICE,
 134    .instance_size = sizeof(PVPanicState),
 135    .instance_init = pvpanic_isa_initfn,
 136    .class_init    = pvpanic_isa_class_init,
 137};
 138
 139static void pvpanic_register_types(void)
 140{
 141    type_register_static(&pvpanic_isa_info);
 142}
 143
 144type_init(pvpanic_register_types)
 145