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