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>
This commit is contained in:
Laurent Vivier 2021-03-12 22:41:44 +01:00
parent 2fde99ee31
commit 0791bc02b8
6 changed files with 212 additions and 0 deletions

26
docs/specs/virt-ctlr.txt Normal file
View file

@ -0,0 +1,26 @@
Virtual System Controller
=========================
This device is a simple interface defined for the pure virtual machine with no
hardware reference implementation to allow the guest kernel to send command
to the host hypervisor.
The specification can evolve, the current state is defined as below.
This is a MMIO mapped device using 256 bytes.
Two 32bit registers are defined:
1- the features register (read-only, address 0x00)
This register allows the device to report features supported by the
controller.
The only feature supported for the moment is power control (0x01).
2- the command register (write-only, address 0x04)
This register allows the kernel to send the commands to the hypervisor.
The implemented commands are part of the power control feature and
are reset (1), halt (2) and panic (3).
A basic command, no-op (0), is always present and can be used to test the
register access. This command has no effect.

View file

@ -183,4 +183,7 @@ config SIFIVE_U_OTP
config SIFIVE_U_PRCI
bool
config VIRT_CTRL
bool
source macio/Kconfig

View file

@ -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'))

View file

@ -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"

151
hw/misc/virt_ctrl.c Normal file
View file

@ -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)

View file

@ -0,0 +1,22 @@
/*
* SPDX-License-Identifer: GPL-2.0-or-later
*
* Virt system Controller
*/
#ifndef VIRT_CTRL_H
#define VIRT_CTRL_H
#define TYPE_VIRT_CTRL "virt-ctrl"
OBJECT_DECLARE_SIMPLE_TYPE(VirtCtrlState, VIRT_CTRL)
struct VirtCtrlState {
SysBusDevice parent_obj;
MemoryRegion iomem;
qemu_irq irq;
uint32_t irq_enabled;
};
#endif