1 /* 2 * SPDX-License-Identifer: GPL-2.0-or-later 3 * 4 * Virt system Controller 5 */ 6 7 #include "qemu/osdep.h" 8 #include "hw/irq.h" 9 #include "hw/qdev-properties.h" 10 #include "hw/sysbus.h" 11 #include "migration/vmstate.h" 12 #include "qemu/log.h" 13 #include "trace.h" 14 #include "sysemu/runstate.h" 15 #include "hw/misc/virt_ctrl.h" 16 17 enum { 18 REG_FEATURES = 0x00, 19 REG_CMD = 0x04, 20 }; 21 22 #define FEAT_POWER_CTRL 0x00000001 23 24 enum { 25 CMD_NOOP, 26 CMD_RESET, 27 CMD_HALT, 28 CMD_PANIC, 29 }; 30 31 static uint64_t virt_ctrl_read(void *opaque, hwaddr addr, unsigned size) 32 { 33 VirtCtrlState *s = opaque; 34 uint64_t value = 0; 35 36 switch (addr) { 37 case REG_FEATURES: 38 value = FEAT_POWER_CTRL; 39 break; 40 default: 41 qemu_log_mask(LOG_UNIMP, 42 "%s: unimplemented register read 0x%02"HWADDR_PRIx"\n", 43 __func__, addr); 44 break; 45 } 46 47 trace_virt_ctrl_write(s, addr, size, value); 48 49 return value; 50 } 51 52 static void virt_ctrl_write(void *opaque, hwaddr addr, uint64_t value, 53 unsigned size) 54 { 55 VirtCtrlState *s = opaque; 56 57 trace_virt_ctrl_write(s, addr, size, value); 58 59 switch (addr) { 60 case REG_CMD: 61 switch (value) { 62 case CMD_NOOP: 63 break; 64 case CMD_RESET: 65 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 66 break; 67 case CMD_HALT: 68 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); 69 break; 70 case CMD_PANIC: 71 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC); 72 break; 73 } 74 break; 75 default: 76 qemu_log_mask(LOG_UNIMP, 77 "%s: unimplemented register write 0x%02"HWADDR_PRIx"\n", 78 __func__, addr); 79 break; 80 } 81 } 82 83 static const MemoryRegionOps virt_ctrl_ops = { 84 .read = virt_ctrl_read, 85 .write = virt_ctrl_write, 86 .endianness = DEVICE_NATIVE_ENDIAN, 87 .valid.max_access_size = 4, 88 .impl.max_access_size = 4, 89 }; 90 91 static void virt_ctrl_reset(DeviceState *dev) 92 { 93 VirtCtrlState *s = VIRT_CTRL(dev); 94 95 trace_virt_ctrl_reset(s); 96 } 97 98 static void virt_ctrl_realize(DeviceState *dev, Error **errp) 99 { 100 VirtCtrlState *s = VIRT_CTRL(dev); 101 102 trace_virt_ctrl_instance_init(s); 103 104 memory_region_init_io(&s->iomem, OBJECT(s), &virt_ctrl_ops, s, 105 "virt-ctrl", 0x100); 106 } 107 108 static const VMStateDescription vmstate_virt_ctrl = { 109 .name = "virt-ctrl", 110 .version_id = 1, 111 .minimum_version_id = 1, 112 .fields = (VMStateField[]) { 113 VMSTATE_UINT32(irq_enabled, VirtCtrlState), 114 VMSTATE_END_OF_LIST() 115 } 116 }; 117 118 static void virt_ctrl_instance_init(Object *obj) 119 { 120 SysBusDevice *dev = SYS_BUS_DEVICE(obj); 121 VirtCtrlState *s = VIRT_CTRL(obj); 122 123 trace_virt_ctrl_instance_init(s); 124 125 sysbus_init_mmio(dev, &s->iomem); 126 sysbus_init_irq(dev, &s->irq); 127 } 128 129 static void virt_ctrl_class_init(ObjectClass *oc, void *data) 130 { 131 DeviceClass *dc = DEVICE_CLASS(oc); 132 133 dc->reset = virt_ctrl_reset; 134 dc->realize = virt_ctrl_realize; 135 dc->vmsd = &vmstate_virt_ctrl; 136 } 137 138 static const TypeInfo virt_ctrl_info = { 139 .name = TYPE_VIRT_CTRL, 140 .parent = TYPE_SYS_BUS_DEVICE, 141 .class_init = virt_ctrl_class_init, 142 .instance_init = virt_ctrl_instance_init, 143 .instance_size = sizeof(VirtCtrlState), 144 }; 145 146 static void virt_ctrl_register_types(void) 147 { 148 type_register_static(&virt_ctrl_info); 149 } 150 151 type_init(virt_ctrl_register_types) 152