diff options
author | Laurent Vivier | 2021-03-12 22:41:44 +0100 |
---|---|---|
committer | Laurent Vivier | 2021-03-15 21:02:57 +0100 |
commit | 0791bc02b8fbf9d55626b57f45255ba1b6ea83d5 (patch) | |
tree | ac7d6fdf6f66a3843ffbb057c7facc08554cbe3a /hw | |
parent | m68k: add an interrupt controller (diff) | |
download | qemu-0791bc02b8fbf9d55626b57f45255ba1b6ea83d5.tar.gz qemu-0791bc02b8fbf9d55626b57f45255ba1b6ea83d5.tar.xz qemu-0791bc02b8fbf9d55626b57f45255ba1b6ea83d5.zip |
m68k: add a system controller
Add a system controller for the m68k-virt machine.
This controller allows the kernel to power off or reset the machine.
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20210312214145.2936082-5-laurent@vivier.eu>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/misc/Kconfig | 3 | ||||
-rw-r--r-- | hw/misc/meson.build | 3 | ||||
-rw-r--r-- | hw/misc/trace-events | 7 | ||||
-rw-r--r-- | hw/misc/virt_ctrl.c | 151 |
4 files changed, 164 insertions, 0 deletions
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index 5426b9b1a1..c71ed25820 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -183,4 +183,7 @@ config SIFIVE_U_OTP config SIFIVE_U_PRCI bool +config VIRT_CTRL + bool + source macio/Kconfig diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 7a2b0d031a..21034dc60a 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -24,6 +24,9 @@ softmmu_ss.add(when: 'CONFIG_ARM11SCU', if_true: files('arm11scu.c')) # Mac devices softmmu_ss.add(when: 'CONFIG_MOS6522', if_true: files('mos6522.c')) +# virt devices +softmmu_ss.add(when: 'CONFIG_VIRT_CTRL', if_true: files('virt_ctrl.c')) + # RISC-V devices softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_DMC', if_true: files('mchp_pfsoc_dmc.c')) softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_IOSCB', if_true: files('mchp_pfsoc_ioscb.c')) diff --git a/hw/misc/trace-events b/hw/misc/trace-events index b87d0b4c90..3d44978cca 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -255,3 +255,10 @@ pca955x_gpio_change(const char *description, unsigned id, unsigned prev_state, u bcm2835_cprman_read(uint64_t offset, uint64_t value) "offset:0x%" PRIx64 " value:0x%" PRIx64 bcm2835_cprman_write(uint64_t offset, uint64_t value) "offset:0x%" PRIx64 " value:0x%" PRIx64 bcm2835_cprman_write_invalid_magic(uint64_t offset, uint64_t value) "offset:0x%" PRIx64 " value:0x%" PRIx64 + +# virt_ctrl.c +virt_ctrl_read(void *dev, unsigned int addr, unsigned int size, uint64_t value) "ctrl: %p reg: 0x%02x size: %d value: 0x%"PRIx64 +virt_ctrl_write(void *dev, unsigned int addr, unsigned int size, uint64_t value) "ctrl: %p reg: 0x%02x size: %d value: 0x%"PRIx64 +virt_ctrl_reset(void *dev) "ctrl: %p" +virt_ctrl_realize(void *dev) "ctrl: %p" +virt_ctrl_instance_init(void *dev) "ctrl: %p" diff --git a/hw/misc/virt_ctrl.c b/hw/misc/virt_ctrl.c new file mode 100644 index 0000000000..2ea01bd7a1 --- /dev/null +++ b/hw/misc/virt_ctrl.c @@ -0,0 +1,151 @@ +/* + * SPDX-License-Identifer: GPL-2.0-or-later + * + * Virt system Controller + */ + +#include "qemu/osdep.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/sysbus.h" +#include "migration/vmstate.h" +#include "qemu/log.h" +#include "trace.h" +#include "sysemu/runstate.h" +#include "hw/misc/virt_ctrl.h" + +enum { + REG_FEATURES = 0x00, + REG_CMD = 0x04, +}; + +#define FEAT_POWER_CTRL 0x00000001 + +enum { + CMD_NOOP, + CMD_RESET, + CMD_HALT, + CMD_PANIC, +}; + +static uint64_t virt_ctrl_read(void *opaque, hwaddr addr, unsigned size) +{ + VirtCtrlState *s = opaque; + uint64_t value = 0; + + switch (addr) { + case REG_FEATURES: + value = FEAT_POWER_CTRL; + break; + default: + qemu_log_mask(LOG_UNIMP, + "%s: unimplemented register read 0x%02"HWADDR_PRIx"\n", + __func__, addr); + break; + } + + trace_virt_ctrl_write(s, addr, size, value); + + return value; +} + +static void virt_ctrl_write(void *opaque, hwaddr addr, uint64_t value, + unsigned size) +{ + VirtCtrlState *s = opaque; + + trace_virt_ctrl_write(s, addr, size, value); + + switch (addr) { + case REG_CMD: + switch (value) { + case CMD_NOOP: + break; + case CMD_RESET: + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + break; + case CMD_HALT: + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + break; + case CMD_PANIC: + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC); + break; + } + break; + default: + qemu_log_mask(LOG_UNIMP, + "%s: unimplemented register write 0x%02"HWADDR_PRIx"\n", + __func__, addr); + break; + } +} + +static const MemoryRegionOps virt_ctrl_ops = { + .read = virt_ctrl_read, + .write = virt_ctrl_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid.max_access_size = 4, + .impl.max_access_size = 4, +}; + +static void virt_ctrl_reset(DeviceState *dev) +{ + VirtCtrlState *s = VIRT_CTRL(dev); + + trace_virt_ctrl_reset(s); +} + +static void virt_ctrl_realize(DeviceState *dev, Error **errp) +{ + VirtCtrlState *s = VIRT_CTRL(dev); + + trace_virt_ctrl_instance_init(s); + + memory_region_init_io(&s->iomem, OBJECT(s), &virt_ctrl_ops, s, + "virt-ctrl", 0x100); +} + +static const VMStateDescription vmstate_virt_ctrl = { + .name = "virt-ctrl", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(irq_enabled, VirtCtrlState), + VMSTATE_END_OF_LIST() + } +}; + +static void virt_ctrl_instance_init(Object *obj) +{ + SysBusDevice *dev = SYS_BUS_DEVICE(obj); + VirtCtrlState *s = VIRT_CTRL(obj); + + trace_virt_ctrl_instance_init(s); + + sysbus_init_mmio(dev, &s->iomem); + sysbus_init_irq(dev, &s->irq); +} + +static void virt_ctrl_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->reset = virt_ctrl_reset; + dc->realize = virt_ctrl_realize; + dc->vmsd = &vmstate_virt_ctrl; +} + +static const TypeInfo virt_ctrl_info = { + .name = TYPE_VIRT_CTRL, + .parent = TYPE_SYS_BUS_DEVICE, + .class_init = virt_ctrl_class_init, + .instance_init = virt_ctrl_instance_init, + .instance_size = sizeof(VirtCtrlState), +}; + +static void virt_ctrl_register_types(void) +{ + type_register_static(&virt_ctrl_info); +} + +type_init(virt_ctrl_register_types) |