Skip to content
Snippets Groups Projects
Commit 0791bc02 authored by Laurent Vivier's avatar Laurent Vivier
Browse files

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: default avatarLaurent Vivier <laurent@vivier.eu>
Reviewed-by: default avatarRichard Henderson <richard.henderson@linaro.org>
Reviewed-by: default avatarPhilippe Mathieu-Daudé <f4bug@amsat.org>
Tested-by: default avatarPhilippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20210312214145.2936082-5-laurent@vivier.eu>
parent 2fde99ee
No related branches found
No related tags found
No related merge requests found
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.
......@@ -183,4 +183,7 @@ config SIFIVE_U_OTP
config SIFIVE_U_PRCI
bool
config VIRT_CTRL
bool
source macio/Kconfig
......@@ -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'))
......
......@@ -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"
/*
* 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)
/*
* 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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment