20
#include "qemu/osdep.h"
21
#include "qapi/error.h"
24
#include "qemu/module.h"
26
#include "migration/vmstate.h"
28
#include "hw/misc/mips_cpc.h"
29
#include "hw/qdev-properties.h"
31
static inline uint64_t cpc_vp_run_mask(MIPSCPCState *cpc)
33
return (1ULL << cpc->num_vp) - 1;
36
static void mips_cpu_reset_async_work(CPUState *cs, run_on_cpu_data data)
38
MIPSCPCState *cpc = (MIPSCPCState *) data.host_ptr;
42
cpc->vp_running |= 1ULL << cs->cpu_index;
45
static void cpc_run_vp(MIPSCPCState *cpc, uint64_t vp_run)
47
CPUState *cs = first_cpu;
50
uint64_t i = 1ULL << cs->cpu_index;
51
if (i & vp_run & ~cpc->vp_running) {
57
async_safe_run_on_cpu(cs, mips_cpu_reset_async_work,
58
RUN_ON_CPU_HOST_PTR(cpc));
63
static void cpc_stop_vp(MIPSCPCState *cpc, uint64_t vp_stop)
65
CPUState *cs = first_cpu;
68
uint64_t i = 1ULL << cs->cpu_index;
69
if (i & vp_stop & cpc->vp_running) {
70
cpu_interrupt(cs, CPU_INTERRUPT_HALT);
71
cpc->vp_running &= ~i;
76
static void cpc_write(void *opaque, hwaddr offset, uint64_t data,
79
MIPSCPCState *s = opaque;
82
case CPC_CL_BASE_OFS + CPC_VP_RUN_OFS:
83
case CPC_CO_BASE_OFS + CPC_VP_RUN_OFS:
84
cpc_run_vp(s, data & cpc_vp_run_mask(s));
86
case CPC_CL_BASE_OFS + CPC_VP_STOP_OFS:
87
case CPC_CO_BASE_OFS + CPC_VP_STOP_OFS:
88
cpc_stop_vp(s, data & cpc_vp_run_mask(s));
91
qemu_log_mask(LOG_UNIMP,
92
"%s: Bad offset 0x%x\n", __func__, (int)offset);
99
static uint64_t cpc_read(void *opaque, hwaddr offset, unsigned size)
101
MIPSCPCState *s = opaque;
104
case CPC_CL_BASE_OFS + CPC_VP_RUNNING_OFS:
105
case CPC_CO_BASE_OFS + CPC_VP_RUNNING_OFS:
106
return s->vp_running;
108
qemu_log_mask(LOG_UNIMP,
109
"%s: Bad offset 0x%x\n", __func__, (int)offset);
114
static const MemoryRegionOps cpc_ops = {
117
.endianness = DEVICE_NATIVE_ENDIAN,
119
.max_access_size = 8,
123
static void mips_cpc_init(Object *obj)
125
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
126
MIPSCPCState *s = MIPS_CPC(obj);
128
memory_region_init_io(&s->mr, OBJECT(s), &cpc_ops, s, "mips-cpc",
130
sysbus_init_mmio(sbd, &s->mr);
133
static void mips_cpc_realize(DeviceState *dev, Error **errp)
135
MIPSCPCState *s = MIPS_CPC(dev);
137
if (s->vp_start_running > cpc_vp_run_mask(s)) {
139
"incorrect vp_start_running 0x%" PRIx64 " for num_vp = %d",
140
s->vp_running, s->num_vp);
145
static void mips_cpc_reset(DeviceState *dev)
147
MIPSCPCState *s = MIPS_CPC(dev);
153
cpc_run_vp(s, s->vp_start_running);
156
static const VMStateDescription vmstate_mips_cpc = {
159
.minimum_version_id = 0,
160
.fields = (const VMStateField[]) {
161
VMSTATE_UINT64(vp_running, MIPSCPCState),
162
VMSTATE_END_OF_LIST()
166
static Property mips_cpc_properties[] = {
167
DEFINE_PROP_UINT32("num-vp", MIPSCPCState, num_vp, 0x1),
168
DEFINE_PROP_UINT64("vp-start-running", MIPSCPCState, vp_start_running, 0x1),
169
DEFINE_PROP_END_OF_LIST(),
172
static void mips_cpc_class_init(ObjectClass *klass, void *data)
174
DeviceClass *dc = DEVICE_CLASS(klass);
176
dc->realize = mips_cpc_realize;
177
dc->reset = mips_cpc_reset;
178
dc->vmsd = &vmstate_mips_cpc;
179
device_class_set_props(dc, mips_cpc_properties);
182
static const TypeInfo mips_cpc_info = {
183
.name = TYPE_MIPS_CPC,
184
.parent = TYPE_SYS_BUS_DEVICE,
185
.instance_size = sizeof(MIPSCPCState),
186
.instance_init = mips_cpc_init,
187
.class_init = mips_cpc_class_init,
190
static void mips_cpc_register_types(void)
192
type_register_static(&mips_cpc_info);
195
type_init(mips_cpc_register_types)