1b4a12dfcSJiaxun Yang /* SPDX-License-Identifier: GPL-2.0-or-later */ 2b4a12dfcSJiaxun Yang /* 3b4a12dfcSJiaxun Yang * Loongson ipi interrupt support 4b4a12dfcSJiaxun Yang * 5b4a12dfcSJiaxun Yang * Copyright (C) 2021 Loongson Technology Corporation Limited 6b4a12dfcSJiaxun Yang */ 7b4a12dfcSJiaxun Yang 8b4a12dfcSJiaxun Yang #include "qemu/osdep.h" 9b4a12dfcSJiaxun Yang #include "hw/boards.h" 10b4a12dfcSJiaxun Yang #include "hw/sysbus.h" 11b4a12dfcSJiaxun Yang #include "hw/intc/loongson_ipi.h" 12b4a12dfcSJiaxun Yang #include "hw/irq.h" 13b4a12dfcSJiaxun Yang #include "hw/qdev-properties.h" 14b4a12dfcSJiaxun Yang #include "qapi/error.h" 15b4a12dfcSJiaxun Yang #include "qemu/log.h" 16b4a12dfcSJiaxun Yang #include "exec/address-spaces.h" 172465c89fSBibo Mao #include "exec/memory.h" 18b4a12dfcSJiaxun Yang #include "migration/vmstate.h" 1991d0b151SJiaxun Yang #ifdef TARGET_LOONGARCH64 20b4a12dfcSJiaxun Yang #include "target/loongarch/cpu.h" 2191d0b151SJiaxun Yang #endif 2291d0b151SJiaxun Yang #ifdef TARGET_MIPS 2391d0b151SJiaxun Yang #include "target/mips/cpu.h" 2491d0b151SJiaxun Yang #endif 25b4a12dfcSJiaxun Yang #include "trace.h" 26b4a12dfcSJiaxun Yang 2749eba52aSJiaxun Yang static MemTxResult loongson_ipi_core_readl(void *opaque, hwaddr addr, 28b4a12dfcSJiaxun Yang uint64_t *data, 29b4a12dfcSJiaxun Yang unsigned size, MemTxAttrs attrs) 30b4a12dfcSJiaxun Yang { 3149eba52aSJiaxun Yang IPICore *s = opaque; 32b4a12dfcSJiaxun Yang uint64_t ret = 0; 33b4a12dfcSJiaxun Yang int index = 0; 34b4a12dfcSJiaxun Yang 35b4a12dfcSJiaxun Yang addr &= 0xff; 36b4a12dfcSJiaxun Yang switch (addr) { 37b4a12dfcSJiaxun Yang case CORE_STATUS_OFF: 38b4a12dfcSJiaxun Yang ret = s->status; 39b4a12dfcSJiaxun Yang break; 40b4a12dfcSJiaxun Yang case CORE_EN_OFF: 41b4a12dfcSJiaxun Yang ret = s->en; 42b4a12dfcSJiaxun Yang break; 43b4a12dfcSJiaxun Yang case CORE_SET_OFF: 44b4a12dfcSJiaxun Yang ret = 0; 45b4a12dfcSJiaxun Yang break; 46b4a12dfcSJiaxun Yang case CORE_CLEAR_OFF: 47b4a12dfcSJiaxun Yang ret = 0; 48b4a12dfcSJiaxun Yang break; 49b4a12dfcSJiaxun Yang case CORE_BUF_20 ... CORE_BUF_38 + 4: 50b4a12dfcSJiaxun Yang index = (addr - CORE_BUF_20) >> 2; 51b4a12dfcSJiaxun Yang ret = s->buf[index]; 52b4a12dfcSJiaxun Yang break; 53b4a12dfcSJiaxun Yang default: 54b4a12dfcSJiaxun Yang qemu_log_mask(LOG_UNIMP, "invalid read: %x", (uint32_t)addr); 55b4a12dfcSJiaxun Yang break; 56b4a12dfcSJiaxun Yang } 57b4a12dfcSJiaxun Yang 58b4a12dfcSJiaxun Yang trace_loongson_ipi_read(size, (uint64_t)addr, ret); 59b4a12dfcSJiaxun Yang *data = ret; 60b4a12dfcSJiaxun Yang return MEMTX_OK; 61b4a12dfcSJiaxun Yang } 62b4a12dfcSJiaxun Yang 6349eba52aSJiaxun Yang static MemTxResult loongson_ipi_iocsr_readl(void *opaque, hwaddr addr, 6449eba52aSJiaxun Yang uint64_t *data, 6549eba52aSJiaxun Yang unsigned size, MemTxAttrs attrs) 6649eba52aSJiaxun Yang { 6740a0815eSBibo Mao LoongsonIPIState *ipi = opaque; 6849eba52aSJiaxun Yang IPICore *s; 6949eba52aSJiaxun Yang 7049eba52aSJiaxun Yang if (attrs.requester_id >= ipi->num_cpu) { 7149eba52aSJiaxun Yang return MEMTX_DECODE_ERROR; 7249eba52aSJiaxun Yang } 7349eba52aSJiaxun Yang 7449eba52aSJiaxun Yang s = &ipi->cpu[attrs.requester_id]; 7549eba52aSJiaxun Yang return loongson_ipi_core_readl(s, addr, data, size, attrs); 7649eba52aSJiaxun Yang } 7749eba52aSJiaxun Yang 7891d0b151SJiaxun Yang static AddressSpace *get_cpu_iocsr_as(CPUState *cpu) 7991d0b151SJiaxun Yang { 8091d0b151SJiaxun Yang #ifdef TARGET_LOONGARCH64 8191d0b151SJiaxun Yang return LOONGARCH_CPU(cpu)->env.address_space_iocsr; 8291d0b151SJiaxun Yang #endif 8391d0b151SJiaxun Yang #ifdef TARGET_MIPS 8491d0b151SJiaxun Yang if (ase_lcsr_available(&MIPS_CPU(cpu)->env)) { 8591d0b151SJiaxun Yang return &MIPS_CPU(cpu)->env.iocsr.as; 8691d0b151SJiaxun Yang } 8791d0b151SJiaxun Yang #endif 8891d0b151SJiaxun Yang return NULL; 8991d0b151SJiaxun Yang } 9091d0b151SJiaxun Yang 9191d0b151SJiaxun Yang static MemTxResult send_ipi_data(CPUState *cpu, uint64_t val, hwaddr addr, 92b4a12dfcSJiaxun Yang MemTxAttrs attrs) 93b4a12dfcSJiaxun Yang { 94b4a12dfcSJiaxun Yang int i, mask = 0, data = 0; 9591d0b151SJiaxun Yang AddressSpace *iocsr_as = get_cpu_iocsr_as(cpu); 9691d0b151SJiaxun Yang 9791d0b151SJiaxun Yang if (!iocsr_as) { 9891d0b151SJiaxun Yang return MEMTX_DECODE_ERROR; 9991d0b151SJiaxun Yang } 100b4a12dfcSJiaxun Yang 101b4a12dfcSJiaxun Yang /* 102b4a12dfcSJiaxun Yang * bit 27-30 is mask for byte writing, 103b4a12dfcSJiaxun Yang * if the mask is 0, we need not to do anything. 104b4a12dfcSJiaxun Yang */ 105b4a12dfcSJiaxun Yang if ((val >> 27) & 0xf) { 1062465c89fSBibo Mao data = address_space_ldl_le(iocsr_as, addr, attrs, NULL); 107b4a12dfcSJiaxun Yang for (i = 0; i < 4; i++) { 108b4a12dfcSJiaxun Yang /* get mask for byte writing */ 109b4a12dfcSJiaxun Yang if (val & (0x1 << (27 + i))) { 110b4a12dfcSJiaxun Yang mask |= 0xff << (i * 8); 111b4a12dfcSJiaxun Yang } 112b4a12dfcSJiaxun Yang } 113b4a12dfcSJiaxun Yang } 114b4a12dfcSJiaxun Yang 115b4a12dfcSJiaxun Yang data &= mask; 116b4a12dfcSJiaxun Yang data |= (val >> 32) & ~mask; 1172465c89fSBibo Mao address_space_stl_le(iocsr_as, addr, data, attrs, NULL); 11891d0b151SJiaxun Yang 11991d0b151SJiaxun Yang return MEMTX_OK; 120b4a12dfcSJiaxun Yang } 121b4a12dfcSJiaxun Yang 122b4a12dfcSJiaxun Yang static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs) 123b4a12dfcSJiaxun Yang { 124b4a12dfcSJiaxun Yang uint32_t cpuid; 125b4a12dfcSJiaxun Yang hwaddr addr; 126b4a12dfcSJiaxun Yang CPUState *cs; 127b4a12dfcSJiaxun Yang 128b4a12dfcSJiaxun Yang cpuid = extract32(val, 16, 10); 12903ca348bSJiaxun Yang cs = cpu_by_arch_id(cpuid); 130b4a12dfcSJiaxun Yang if (cs == NULL) { 131b4a12dfcSJiaxun Yang return MEMTX_DECODE_ERROR; 132b4a12dfcSJiaxun Yang } 133b4a12dfcSJiaxun Yang 134b4a12dfcSJiaxun Yang /* override requester_id */ 135b4a12dfcSJiaxun Yang addr = SMP_IPI_MAILBOX + CORE_BUF_20 + (val & 0x1c); 136b4a12dfcSJiaxun Yang attrs.requester_id = cs->cpu_index; 13791d0b151SJiaxun Yang return send_ipi_data(cs, val, addr, attrs); 138b4a12dfcSJiaxun Yang } 139b4a12dfcSJiaxun Yang 140b4a12dfcSJiaxun Yang static MemTxResult any_send(uint64_t val, MemTxAttrs attrs) 141b4a12dfcSJiaxun Yang { 142b4a12dfcSJiaxun Yang uint32_t cpuid; 143b4a12dfcSJiaxun Yang hwaddr addr; 144b4a12dfcSJiaxun Yang CPUState *cs; 145b4a12dfcSJiaxun Yang 146b4a12dfcSJiaxun Yang cpuid = extract32(val, 16, 10); 14703ca348bSJiaxun Yang cs = cpu_by_arch_id(cpuid); 148b4a12dfcSJiaxun Yang if (cs == NULL) { 149b4a12dfcSJiaxun Yang return MEMTX_DECODE_ERROR; 150b4a12dfcSJiaxun Yang } 151b4a12dfcSJiaxun Yang 152b4a12dfcSJiaxun Yang /* override requester_id */ 153b4a12dfcSJiaxun Yang addr = val & 0xffff; 154b4a12dfcSJiaxun Yang attrs.requester_id = cs->cpu_index; 15591d0b151SJiaxun Yang return send_ipi_data(cs, val, addr, attrs); 156b4a12dfcSJiaxun Yang } 157b4a12dfcSJiaxun Yang 15849eba52aSJiaxun Yang static MemTxResult loongson_ipi_core_writel(void *opaque, hwaddr addr, 15949eba52aSJiaxun Yang uint64_t val, unsigned size, 16049eba52aSJiaxun Yang MemTxAttrs attrs) 161b4a12dfcSJiaxun Yang { 16249eba52aSJiaxun Yang IPICore *s = opaque; 16340a0815eSBibo Mao LoongsonIPIState *ipi = s->ipi; 164b4a12dfcSJiaxun Yang int index = 0; 165b4a12dfcSJiaxun Yang uint32_t cpuid; 166b4a12dfcSJiaxun Yang uint8_t vector; 167b4a12dfcSJiaxun Yang CPUState *cs; 168b4a12dfcSJiaxun Yang 169b4a12dfcSJiaxun Yang addr &= 0xff; 170b4a12dfcSJiaxun Yang trace_loongson_ipi_write(size, (uint64_t)addr, val); 171b4a12dfcSJiaxun Yang switch (addr) { 172b4a12dfcSJiaxun Yang case CORE_STATUS_OFF: 173b4a12dfcSJiaxun Yang qemu_log_mask(LOG_GUEST_ERROR, "can not be written"); 174b4a12dfcSJiaxun Yang break; 175b4a12dfcSJiaxun Yang case CORE_EN_OFF: 176b4a12dfcSJiaxun Yang s->en = val; 177b4a12dfcSJiaxun Yang break; 178b4a12dfcSJiaxun Yang case CORE_SET_OFF: 179b4a12dfcSJiaxun Yang s->status |= val; 180b4a12dfcSJiaxun Yang if (s->status != 0 && (s->status & s->en) != 0) { 181b4a12dfcSJiaxun Yang qemu_irq_raise(s->irq); 182b4a12dfcSJiaxun Yang } 183b4a12dfcSJiaxun Yang break; 184b4a12dfcSJiaxun Yang case CORE_CLEAR_OFF: 185b4a12dfcSJiaxun Yang s->status &= ~val; 186b4a12dfcSJiaxun Yang if (s->status == 0 && s->en != 0) { 187b4a12dfcSJiaxun Yang qemu_irq_lower(s->irq); 188b4a12dfcSJiaxun Yang } 189b4a12dfcSJiaxun Yang break; 190b4a12dfcSJiaxun Yang case CORE_BUF_20 ... CORE_BUF_38 + 4: 191b4a12dfcSJiaxun Yang index = (addr - CORE_BUF_20) >> 2; 192b4a12dfcSJiaxun Yang s->buf[index] = val; 193b4a12dfcSJiaxun Yang break; 194b4a12dfcSJiaxun Yang case IOCSR_IPI_SEND: 195b4a12dfcSJiaxun Yang cpuid = extract32(val, 16, 10); 196b4a12dfcSJiaxun Yang /* IPI status vector */ 197b4a12dfcSJiaxun Yang vector = extract8(val, 0, 5); 19803ca348bSJiaxun Yang cs = cpu_by_arch_id(cpuid); 19949eba52aSJiaxun Yang if (cs == NULL || cs->cpu_index >= ipi->num_cpu) { 200b4a12dfcSJiaxun Yang return MEMTX_DECODE_ERROR; 201b4a12dfcSJiaxun Yang } 20249eba52aSJiaxun Yang loongson_ipi_core_writel(&ipi->cpu[cs->cpu_index], CORE_SET_OFF, 20349eba52aSJiaxun Yang BIT(vector), 4, attrs); 204b4a12dfcSJiaxun Yang break; 205b4a12dfcSJiaxun Yang default: 206b4a12dfcSJiaxun Yang qemu_log_mask(LOG_UNIMP, "invalid write: %x", (uint32_t)addr); 207b4a12dfcSJiaxun Yang break; 208b4a12dfcSJiaxun Yang } 209b4a12dfcSJiaxun Yang 210b4a12dfcSJiaxun Yang return MEMTX_OK; 211b4a12dfcSJiaxun Yang } 212b4a12dfcSJiaxun Yang 21349eba52aSJiaxun Yang static MemTxResult loongson_ipi_iocsr_writel(void *opaque, hwaddr addr, 21449eba52aSJiaxun Yang uint64_t val, unsigned size, 21549eba52aSJiaxun Yang MemTxAttrs attrs) 21649eba52aSJiaxun Yang { 21740a0815eSBibo Mao LoongsonIPIState *ipi = opaque; 21849eba52aSJiaxun Yang IPICore *s; 21949eba52aSJiaxun Yang 22049eba52aSJiaxun Yang if (attrs.requester_id >= ipi->num_cpu) { 22149eba52aSJiaxun Yang return MEMTX_DECODE_ERROR; 22249eba52aSJiaxun Yang } 22349eba52aSJiaxun Yang 22449eba52aSJiaxun Yang s = &ipi->cpu[attrs.requester_id]; 22549eba52aSJiaxun Yang return loongson_ipi_core_writel(s, addr, val, size, attrs); 22649eba52aSJiaxun Yang } 22749eba52aSJiaxun Yang 22849eba52aSJiaxun Yang static const MemoryRegionOps loongson_ipi_core_ops = { 22949eba52aSJiaxun Yang .read_with_attrs = loongson_ipi_core_readl, 23049eba52aSJiaxun Yang .write_with_attrs = loongson_ipi_core_writel, 23149eba52aSJiaxun Yang .impl.min_access_size = 4, 23249eba52aSJiaxun Yang .impl.max_access_size = 4, 23349eba52aSJiaxun Yang .valid.min_access_size = 4, 23449eba52aSJiaxun Yang .valid.max_access_size = 8, 23549eba52aSJiaxun Yang .endianness = DEVICE_LITTLE_ENDIAN, 23649eba52aSJiaxun Yang }; 23749eba52aSJiaxun Yang 23849eba52aSJiaxun Yang static const MemoryRegionOps loongson_ipi_iocsr_ops = { 23949eba52aSJiaxun Yang .read_with_attrs = loongson_ipi_iocsr_readl, 24049eba52aSJiaxun Yang .write_with_attrs = loongson_ipi_iocsr_writel, 241b4a12dfcSJiaxun Yang .impl.min_access_size = 4, 242b4a12dfcSJiaxun Yang .impl.max_access_size = 4, 243b4a12dfcSJiaxun Yang .valid.min_access_size = 4, 244b4a12dfcSJiaxun Yang .valid.max_access_size = 8, 245b4a12dfcSJiaxun Yang .endianness = DEVICE_LITTLE_ENDIAN, 246b4a12dfcSJiaxun Yang }; 247b4a12dfcSJiaxun Yang 248b4a12dfcSJiaxun Yang /* mail send and any send only support writeq */ 249b4a12dfcSJiaxun Yang static MemTxResult loongson_ipi_writeq(void *opaque, hwaddr addr, uint64_t val, 250b4a12dfcSJiaxun Yang unsigned size, MemTxAttrs attrs) 251b4a12dfcSJiaxun Yang { 252b4a12dfcSJiaxun Yang MemTxResult ret = MEMTX_OK; 253b4a12dfcSJiaxun Yang 254b4a12dfcSJiaxun Yang addr &= 0xfff; 255b4a12dfcSJiaxun Yang switch (addr) { 256b4a12dfcSJiaxun Yang case MAIL_SEND_OFFSET: 257b4a12dfcSJiaxun Yang ret = mail_send(val, attrs); 258b4a12dfcSJiaxun Yang break; 259b4a12dfcSJiaxun Yang case ANY_SEND_OFFSET: 260b4a12dfcSJiaxun Yang ret = any_send(val, attrs); 261b4a12dfcSJiaxun Yang break; 262b4a12dfcSJiaxun Yang default: 263b4a12dfcSJiaxun Yang break; 264b4a12dfcSJiaxun Yang } 265b4a12dfcSJiaxun Yang 266b4a12dfcSJiaxun Yang return ret; 267b4a12dfcSJiaxun Yang } 268b4a12dfcSJiaxun Yang 269b4a12dfcSJiaxun Yang static const MemoryRegionOps loongson_ipi64_ops = { 270b4a12dfcSJiaxun Yang .write_with_attrs = loongson_ipi_writeq, 271b4a12dfcSJiaxun Yang .impl.min_access_size = 8, 272b4a12dfcSJiaxun Yang .impl.max_access_size = 8, 273b4a12dfcSJiaxun Yang .valid.min_access_size = 8, 274b4a12dfcSJiaxun Yang .valid.max_access_size = 8, 275b4a12dfcSJiaxun Yang .endianness = DEVICE_LITTLE_ENDIAN, 276b4a12dfcSJiaxun Yang }; 277b4a12dfcSJiaxun Yang 278530e6dafSBibo Mao static void loongson_ipi_common_realize(DeviceState *dev, Error **errp) 279b4a12dfcSJiaxun Yang { 28040a0815eSBibo Mao LoongsonIPIState *s = LOONGSON_IPI(dev); 281b4a12dfcSJiaxun Yang SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 282b4a12dfcSJiaxun Yang int i; 283b4a12dfcSJiaxun Yang 284b4a12dfcSJiaxun Yang if (s->num_cpu == 0) { 285b4a12dfcSJiaxun Yang error_setg(errp, "num-cpu must be at least 1"); 286b4a12dfcSJiaxun Yang return; 287b4a12dfcSJiaxun Yang } 288b4a12dfcSJiaxun Yang 28949eba52aSJiaxun Yang memory_region_init_io(&s->ipi_iocsr_mem, OBJECT(dev), 29049eba52aSJiaxun Yang &loongson_ipi_iocsr_ops, 291b4a12dfcSJiaxun Yang s, "loongson_ipi_iocsr", 0x48); 292b4a12dfcSJiaxun Yang 293b4a12dfcSJiaxun Yang /* loongson_ipi_iocsr performs re-entrant IO through ipi_send */ 294b4a12dfcSJiaxun Yang s->ipi_iocsr_mem.disable_reentrancy_guard = true; 295b4a12dfcSJiaxun Yang 296b4a12dfcSJiaxun Yang sysbus_init_mmio(sbd, &s->ipi_iocsr_mem); 297b4a12dfcSJiaxun Yang 298b4a12dfcSJiaxun Yang memory_region_init_io(&s->ipi64_iocsr_mem, OBJECT(dev), 299b4a12dfcSJiaxun Yang &loongson_ipi64_ops, 300b4a12dfcSJiaxun Yang s, "loongson_ipi64_iocsr", 0x118); 301b4a12dfcSJiaxun Yang sysbus_init_mmio(sbd, &s->ipi64_iocsr_mem); 302b4a12dfcSJiaxun Yang 303b4a12dfcSJiaxun Yang s->cpu = g_new0(IPICore, s->num_cpu); 304b4a12dfcSJiaxun Yang for (i = 0; i < s->num_cpu; i++) { 30549eba52aSJiaxun Yang s->cpu[i].ipi = s; 30649eba52aSJiaxun Yang 307b4a12dfcSJiaxun Yang qdev_init_gpio_out(dev, &s->cpu[i].irq, 1); 308b4a12dfcSJiaxun Yang } 309b4a12dfcSJiaxun Yang } 310b4a12dfcSJiaxun Yang 311530e6dafSBibo Mao static void loongson_ipi_realize(DeviceState *dev, Error **errp) 312530e6dafSBibo Mao { 313530e6dafSBibo Mao LoongsonIPIState *s = LOONGSON_IPI(dev); 314530e6dafSBibo Mao SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 315530e6dafSBibo Mao Error *local_err = NULL; 316530e6dafSBibo Mao 317530e6dafSBibo Mao loongson_ipi_common_realize(dev, &local_err); 318530e6dafSBibo Mao if (local_err) { 319530e6dafSBibo Mao error_propagate(errp, local_err); 320530e6dafSBibo Mao return; 321530e6dafSBibo Mao } 322530e6dafSBibo Mao 323*a022e0deSBibo Mao s->ipi_mmio_mem = g_new0(MemoryRegion, s->num_cpu); 324530e6dafSBibo Mao for (unsigned i = 0; i < s->num_cpu; i++) { 325530e6dafSBibo Mao g_autofree char *name = g_strdup_printf("loongson_ipi_cpu%d_mmio", i); 326*a022e0deSBibo Mao memory_region_init_io(&s->ipi_mmio_mem[i], OBJECT(dev), 327530e6dafSBibo Mao &loongson_ipi_core_ops, &s->cpu[i], name, 0x48); 328*a022e0deSBibo Mao sysbus_init_mmio(sbd, &s->ipi_mmio_mem[i]); 329530e6dafSBibo Mao } 330530e6dafSBibo Mao } 331530e6dafSBibo Mao 332530e6dafSBibo Mao static void loongson_ipi_common_unrealize(DeviceState *dev) 3330c2086bcSPhilippe Mathieu-Daudé { 33440a0815eSBibo Mao LoongsonIPIState *s = LOONGSON_IPI(dev); 3350c2086bcSPhilippe Mathieu-Daudé 3360c2086bcSPhilippe Mathieu-Daudé g_free(s->cpu); 3370c2086bcSPhilippe Mathieu-Daudé } 3380c2086bcSPhilippe Mathieu-Daudé 339530e6dafSBibo Mao static void loongson_ipi_unrealize(DeviceState *dev) 340530e6dafSBibo Mao { 341*a022e0deSBibo Mao LoongsonIPIState *s = LOONGSON_IPI(dev); 342*a022e0deSBibo Mao 343*a022e0deSBibo Mao g_free(s->ipi_mmio_mem); 344*a022e0deSBibo Mao 345530e6dafSBibo Mao loongson_ipi_common_unrealize(dev); 346530e6dafSBibo Mao } 347530e6dafSBibo Mao 348b4a12dfcSJiaxun Yang static const VMStateDescription vmstate_ipi_core = { 349b4a12dfcSJiaxun Yang .name = "ipi-single", 350b4a12dfcSJiaxun Yang .version_id = 2, 351b4a12dfcSJiaxun Yang .minimum_version_id = 2, 352b4a12dfcSJiaxun Yang .fields = (const VMStateField[]) { 353b4a12dfcSJiaxun Yang VMSTATE_UINT32(status, IPICore), 354b4a12dfcSJiaxun Yang VMSTATE_UINT32(en, IPICore), 355b4a12dfcSJiaxun Yang VMSTATE_UINT32(set, IPICore), 356b4a12dfcSJiaxun Yang VMSTATE_UINT32(clear, IPICore), 357b4a12dfcSJiaxun Yang VMSTATE_UINT32_ARRAY(buf, IPICore, IPI_MBX_NUM * 2), 358b4a12dfcSJiaxun Yang VMSTATE_END_OF_LIST() 359b4a12dfcSJiaxun Yang } 360b4a12dfcSJiaxun Yang }; 361b4a12dfcSJiaxun Yang 362b4a12dfcSJiaxun Yang static const VMStateDescription vmstate_loongson_ipi = { 363b4a12dfcSJiaxun Yang .name = TYPE_LOONGSON_IPI, 364b4a12dfcSJiaxun Yang .version_id = 2, 365b4a12dfcSJiaxun Yang .minimum_version_id = 2, 366b4a12dfcSJiaxun Yang .fields = (const VMStateField[]) { 36740a0815eSBibo Mao VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongsonIPIState, num_cpu, 368b4a12dfcSJiaxun Yang vmstate_ipi_core, IPICore), 369b4a12dfcSJiaxun Yang VMSTATE_END_OF_LIST() 370b4a12dfcSJiaxun Yang } 371b4a12dfcSJiaxun Yang }; 372b4a12dfcSJiaxun Yang 373b4a12dfcSJiaxun Yang static Property ipi_properties[] = { 37440a0815eSBibo Mao DEFINE_PROP_UINT32("num-cpu", LoongsonIPIState, num_cpu, 1), 375b4a12dfcSJiaxun Yang DEFINE_PROP_END_OF_LIST(), 376b4a12dfcSJiaxun Yang }; 377b4a12dfcSJiaxun Yang 378b4a12dfcSJiaxun Yang static void loongson_ipi_class_init(ObjectClass *klass, void *data) 379b4a12dfcSJiaxun Yang { 380b4a12dfcSJiaxun Yang DeviceClass *dc = DEVICE_CLASS(klass); 3817e555781SBibo Mao LoongsonIPIClass *lic = LOONGSON_IPI_CLASS(klass); 382b4a12dfcSJiaxun Yang 3837e555781SBibo Mao device_class_set_parent_realize(dc, loongson_ipi_realize, 3847e555781SBibo Mao &lic->parent_realize); 3857e555781SBibo Mao device_class_set_parent_unrealize(dc, loongson_ipi_unrealize, 3867e555781SBibo Mao &lic->parent_unrealize); 387b4a12dfcSJiaxun Yang device_class_set_props(dc, ipi_properties); 388b4a12dfcSJiaxun Yang dc->vmsd = &vmstate_loongson_ipi; 389b4a12dfcSJiaxun Yang } 390b4a12dfcSJiaxun Yang 39113e8ec6cSPhilippe Mathieu-Daudé static const TypeInfo loongson_ipi_types[] = { 39213e8ec6cSPhilippe Mathieu-Daudé { 393b4a12dfcSJiaxun Yang .name = TYPE_LOONGSON_IPI, 3947e555781SBibo Mao .parent = TYPE_LOONGSON_IPI_COMMON, 39540a0815eSBibo Mao .instance_size = sizeof(LoongsonIPIState), 3967e555781SBibo Mao .class_size = sizeof(LoongsonIPIClass), 397b4a12dfcSJiaxun Yang .class_init = loongson_ipi_class_init, 39813e8ec6cSPhilippe Mathieu-Daudé } 399b4a12dfcSJiaxun Yang }; 400b4a12dfcSJiaxun Yang 40113e8ec6cSPhilippe Mathieu-Daudé DEFINE_TYPES(loongson_ipi_types) 402