diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2024-08-07 00:33:51 +1000 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2024-08-07 00:33:51 +1000 |
commit | f4bb895a3bb08d9bf6b04937555eff14225772e4 (patch) | |
tree | 11e49b527d3ef9fe0479206b7d7a2a7c158b3c54 | |
parent | c659b7b3b4925f8cef486a3ee64e911519495782 (diff) | |
parent | 7e7085da1f86655cb9c892e14328cc07fe552717 (diff) |
Merge tag 'hw-misc-20240806' of https://github.com/philmd/qemu into staging
Misc HW & UI patches
- Replace Loongson IPI with LoongArch IPI on LoongArch Virt machine (Bibo)
- SD card: Do not abort when reading DAT lines on invalid cmd state (Phil)
- SDHCI: Reset @data_count index on invalid ADMA transfers (Phil)
- Don't decrement PFlash counter below 0 (Peter)
- Explicit a 8bit truncate on IDE ATAPI (Peter)
- Silent Coverity warning in ISA FDC (Peter)
- Remove dead code in PCI IDE bmdma_prepare_buf (Peter)
- Improve OpenGL and related display error messages (Peter)
- Set PCI base address register write mask on GC64120 host bridge (Phil)
- List PCIe Root Port and PCIe-to-PCI bridge in QEMU PCI IDs list (George)
# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmayMloACgkQ4+MsLN6t
# wN6SFQ//S0WvrFNsCeHphsbPETNwHL72j2XdX9xnt9UJZoBhFitOTCzo/EpNQHJe
# dFxCAfef9Nc9WDumyWsb7hE6IGjn/wPpVUnOnoWZZAilA6LK01J0mxgDXNRUf8ES
# iRo5x1Zd3oNBcKA9oqCuALkapXYypKCwSlRgvc42ekdYXHG95pFbJv9MmWIYy6Vn
# 0+hBWv3+Xegv7oFH4UsbjY844vsFcjupvrEm10bcH/zeYhEWVvXRylyfAQS8ww+U
# TYWj9g1i+Cfz+QxKyXovlS21ogieckiTYlr4yM7Ze7fD3Tyj5Q3KRfjC9tD0HoNb
# hjTSojfzk9m93/c5nASL7ChbjisJWqewH5J0eVLSMkqDRUsbFbsryJ4bDXIQNSYD
# HTko32P5obrDQO6l8rr6zuk1Y8lKBd0cY4fGlynXzsitp7duAqWJeMbD0s0duASW
# pqGITK/F/hKHJC6RVDaiFoyGHEa+wm4K6YqfwSFy0EOb5qYq0/d0MAEzTXPB1K1S
# mFMF6+Yk7ZfOnYwSDTDGf5hnmSvSLLdY+Ne94g9gLvuIRWCvc5rrjfBzAbnOfeif
# EMpFbofkMys5p7kxGUZhkJpRQiRjB11fZl9bplyhjGpPgQrq+E/j0G3Uc7jtkOUO
# sjB/4iA7RFvCe47EWqN3WR+rf462EGk2MD+Ebxd9FLsiciFvk1Y=
# =jOxG
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 07 Aug 2024 12:25:30 AM AEST
# gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
# gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full]
* tag 'hw-misc-20240806' of https://github.com/philmd/qemu: (28 commits)
docs/specs/pci-ids: Fix markup
docs/specs/pci-ids: Add missing devices
hw/pci-host/gt64120: Reset config registers during RESET phase
hw/pci-host/gt64120: Set PCI base address register write mask
ui/console: Note in '-display help' that some backends support suboptions
system/vl.c: Expand OpenGL related errors
hw/display/virtio-gpu: Improve "opengl is not available" error message
hw/ide/pci: Remove dead code from bmdma_prepare_buf()
hw/block/fdc-isa: Assert that isa_fdc_get_drive_max_chs() found something
hw/ide/atapi: Be explicit that assigning to s->lcyl truncates
hw/block/pflash_cfi01: Don't decrement pfl->counter below 0
hw/sd/sdhci: Reset @data_count index on invalid ADMA transfers
hw/sd/sdcard: Do not abort when reading DAT lines on invalid cmd state
hw/sd/sdcard: Explicit dummy byte value
hw/intc/loongson_ipi: Restrict to MIPS
hw/loongarch/virt: Replace Loongson IPI with LoongArch IPI
hw/intc/loongarch_ipi: Add loongarch IPI support
hw/intc/loongson_ipi: Move common code to loongson_ipi_common.c
hw/intc/loongson_ipi: Expose loongson_ipi_core_read/write helpers
hw/intc/loongson_ipi: Add LoongsonIPICommonClass::cpu_by_arch_id handler
...
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r-- | MAINTAINERS | 6 | ||||
-rw-r--r-- | docs/specs/pci-ids.rst | 8 | ||||
-rw-r--r-- | hw/block/fdc-isa.c | 2 | ||||
-rw-r--r-- | hw/block/pflash_cfi01.c | 1 | ||||
-rw-r--r-- | hw/display/virtio-gpu-gl.c | 8 | ||||
-rw-r--r-- | hw/ide/atapi.c | 2 | ||||
-rw-r--r-- | hw/ide/pci.c | 7 | ||||
-rw-r--r-- | hw/intc/Kconfig | 8 | ||||
-rw-r--r-- | hw/intc/loongarch_ipi.c | 68 | ||||
-rw-r--r-- | hw/intc/loongson_ipi.c | 340 | ||||
-rw-r--r-- | hw/intc/loongson_ipi_common.c | 347 | ||||
-rw-r--r-- | hw/intc/meson.build | 2 | ||||
-rw-r--r-- | hw/loongarch/Kconfig | 2 | ||||
-rw-r--r-- | hw/loongarch/virt.c | 4 | ||||
-rw-r--r-- | hw/pci-host/gt64120.c | 23 | ||||
-rw-r--r-- | hw/sd/sd.c | 16 | ||||
-rw-r--r-- | hw/sd/sdhci.c | 1 | ||||
-rw-r--r-- | include/hw/intc/loongarch_ipi.h | 25 | ||||
-rw-r--r-- | include/hw/intc/loongson_ipi.h | 51 | ||||
-rw-r--r-- | include/hw/intc/loongson_ipi_common.h | 74 | ||||
-rw-r--r-- | include/hw/loongarch/virt.h | 1 | ||||
-rw-r--r-- | system/vl.c | 5 | ||||
-rw-r--r-- | ui/console.c | 5 |
23 files changed, 635 insertions, 371 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index e34c2bd4cd..74a85360fd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1250,9 +1250,9 @@ F: configs/devices/loongarch64-softmmu/default.mak F: hw/loongarch/ F: include/hw/loongarch/virt.h F: include/hw/intc/loongarch_*.h -F: include/hw/intc/loongson_ipi.h +F: include/hw/intc/loongson_ipi_common.h F: hw/intc/loongarch_*.c -F: hw/intc/loongson_ipi.c +F: hw/intc/loongson_ipi_common.c F: include/hw/pci-host/ls7a.h F: hw/rtc/ls7a_rtc.c F: gdb-xml/loongarch*.xml @@ -1386,11 +1386,13 @@ Loongson-3 virtual platforms M: Huacai Chen <chenhuacai@kernel.org> R: Jiaxun Yang <jiaxun.yang@flygoat.com> S: Maintained +F: hw/intc/loongson_ipi_common.c F: hw/intc/loongson_ipi.c F: hw/intc/loongson_liointc.c F: hw/mips/loongson3_bootp.c F: hw/mips/loongson3_bootp.h F: hw/mips/loongson3_virt.c +F: include/hw/intc/loongson_ipi_common.h F: include/hw/intc/loongson_ipi.h F: include/hw/intc/loongson_liointc.h F: tests/avocado/machine_mips_loongson3v.py diff --git a/docs/specs/pci-ids.rst b/docs/specs/pci-ids.rst index c0a3dec2e7..328ab31fe8 100644 --- a/docs/specs/pci-ids.rst +++ b/docs/specs/pci-ids.rst @@ -77,13 +77,17 @@ PCI devices (other than virtio): 1b36:0008 PCIe host bridge 1b36:0009 - PCI Expander Bridge (-device pxb) + PCI Expander Bridge (``-device pxb``) 1b36:000a PCI-PCI bridge (multiseat) 1b36:000b - PCIe Expander Bridge (-device pxb-pcie) + PCIe Expander Bridge (``-device pxb-pcie``) +1b36:000c + PCIe Root Port (``-device pcie-root-port``) 1b36:000d PCI xhci usb host adapter +1b36:000e + PCIe-to-PCI bridge (``-device pcie-pci-bridge``) 1b36:000f mdpy (mdev sample device), ``linux/samples/vfio-mdev/mdpy.c`` 1b36:0010 diff --git a/hw/block/fdc-isa.c b/hw/block/fdc-isa.c index e43dc532af..796835f57b 100644 --- a/hw/block/fdc-isa.c +++ b/hw/block/fdc-isa.c @@ -147,6 +147,8 @@ static void isa_fdc_get_drive_max_chs(FloppyDriveType type, uint8_t *maxc, *maxs = fdf->last_sect; } } + /* fd_formats must contain at least one entry per FloppyDriveType */ + assert(*maxc); (*maxc)--; } diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c index c8f1cf5a87..2f3d1dd509 100644 --- a/hw/block/pflash_cfi01.c +++ b/hw/block/pflash_cfi01.c @@ -614,6 +614,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset, if (!pfl->counter) { trace_pflash_write(pfl->name, "block write finished"); pfl->wcycle++; + break; } pfl->counter--; diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c index 952820a425..29d20b0132 100644 --- a/hw/display/virtio-gpu-gl.c +++ b/hw/display/virtio-gpu-gl.c @@ -106,6 +106,7 @@ static void virtio_gpu_gl_reset(VirtIODevice *vdev) static void virtio_gpu_gl_device_realize(DeviceState *qdev, Error **errp) { + ERRP_GUARD(); VirtIOGPU *g = VIRTIO_GPU(qdev); #if HOST_BIG_ENDIAN @@ -119,7 +120,12 @@ static void virtio_gpu_gl_device_realize(DeviceState *qdev, Error **errp) } if (!display_opengl) { - error_setg(errp, "opengl is not available"); + error_setg(errp, + "The display backend does not have OpenGL support enabled"); + error_append_hint(errp, + "It can be enabled with '-display BACKEND,gl=on' " + "where BACKEND is the name of the display backend " + "to use.\n"); return; } diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c index fcb6cca157..e82959dc2d 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c @@ -265,7 +265,7 @@ void ide_atapi_cmd_reply_end(IDEState *s) byte_count_limit--; size = byte_count_limit; } - s->lcyl = size; + s->lcyl = size & 0xff; s->hcyl = size >> 8; s->elementary_transfer_size = size; /* we cannot transmit more than one sector at a time */ diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 4675d079a1..a008fe7316 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -237,7 +237,7 @@ static int32_t bmdma_prepare_buf(const IDEDMA *dma, int32_t limit) /* end of table (with a fail safe of one page) */ if (bm->cur_prd_last || (bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE) { - return s->sg.size; + break; } pci_dma_read(pci_dev, bm->cur_addr, &prd, 8); bm->cur_addr += 8; @@ -266,10 +266,7 @@ static int32_t bmdma_prepare_buf(const IDEDMA *dma, int32_t limit) s->io_buffer_size += l; } } - - qemu_sglist_destroy(&s->sg); - s->io_buffer_size = 0; - return -1; + return s->sg.size; } /* return 0 if buffer completed */ diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig index 58b6d3a710..dd405bdb5d 100644 --- a/hw/intc/Kconfig +++ b/hw/intc/Kconfig @@ -87,8 +87,16 @@ config GOLDFISH_PIC config M68K_IRQC bool +config LOONGSON_IPI_COMMON + bool + config LOONGSON_IPI bool + select LOONGSON_IPI_COMMON + +config LOONGARCH_IPI + bool + select LOONGSON_IPI_COMMON config LOONGARCH_PCH_PIC bool diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c new file mode 100644 index 0000000000..2ae1a42c46 --- /dev/null +++ b/hw/intc/loongarch_ipi.c @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * LoongArch IPI interrupt support + * + * Copyright (C) 2024 Loongson Technology Corporation Limited + */ + +#include "qemu/osdep.h" +#include "hw/boards.h" +#include "hw/intc/loongarch_ipi.h" +#include "target/loongarch/cpu.h" + +static AddressSpace *get_iocsr_as(CPUState *cpu) +{ + return LOONGARCH_CPU(cpu)->env.address_space_iocsr; +} + +static int archid_cmp(const void *a, const void *b) +{ + CPUArchId *archid_a = (CPUArchId *)a; + CPUArchId *archid_b = (CPUArchId *)b; + + return archid_a->arch_id - archid_b->arch_id; +} + +static CPUArchId *find_cpu_by_archid(MachineState *ms, uint32_t id) +{ + CPUArchId apic_id, *found_cpu; + + apic_id.arch_id = id; + found_cpu = bsearch(&apic_id, ms->possible_cpus->cpus, + ms->possible_cpus->len, + sizeof(*ms->possible_cpus->cpus), + archid_cmp); + + return found_cpu; +} + +static CPUState *loongarch_cpu_by_arch_id(int64_t arch_id) +{ + MachineState *machine = MACHINE(qdev_get_machine()); + CPUArchId *archid; + + archid = find_cpu_by_archid(machine, arch_id); + if (archid) { + return CPU(archid->cpu); + } + + return NULL; +} + +static void loongarch_ipi_class_init(ObjectClass *klass, void *data) +{ + LoongsonIPICommonClass *licc = LOONGSON_IPI_COMMON_CLASS(klass); + + licc->get_iocsr_as = get_iocsr_as; + licc->cpu_by_arch_id = loongarch_cpu_by_arch_id; +} + +static const TypeInfo loongarch_ipi_types[] = { + { + .name = TYPE_LOONGARCH_IPI, + .parent = TYPE_LOONGSON_IPI_COMMON, + .class_init = loongarch_ipi_class_init, + } +}; + +DEFINE_TYPES(loongarch_ipi_types) diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c index 682cec96f3..8382ceca67 100644 --- a/hw/intc/loongson_ipi.c +++ b/hw/intc/loongson_ipi.c @@ -16,213 +16,16 @@ #include "exec/address-spaces.h" #include "exec/memory.h" #include "migration/vmstate.h" -#ifdef TARGET_LOONGARCH64 -#include "target/loongarch/cpu.h" -#endif -#ifdef TARGET_MIPS #include "target/mips/cpu.h" -#endif #include "trace.h" -static MemTxResult loongson_ipi_core_readl(void *opaque, hwaddr addr, - uint64_t *data, - unsigned size, MemTxAttrs attrs) +static AddressSpace *get_iocsr_as(CPUState *cpu) { - IPICore *s = opaque; - uint64_t ret = 0; - int index = 0; - - addr &= 0xff; - switch (addr) { - case CORE_STATUS_OFF: - ret = s->status; - break; - case CORE_EN_OFF: - ret = s->en; - break; - case CORE_SET_OFF: - ret = 0; - break; - case CORE_CLEAR_OFF: - ret = 0; - break; - case CORE_BUF_20 ... CORE_BUF_38 + 4: - index = (addr - CORE_BUF_20) >> 2; - ret = s->buf[index]; - break; - default: - qemu_log_mask(LOG_UNIMP, "invalid read: %x", (uint32_t)addr); - break; - } - - trace_loongson_ipi_read(size, (uint64_t)addr, ret); - *data = ret; - return MEMTX_OK; -} - -static MemTxResult loongson_ipi_iocsr_readl(void *opaque, hwaddr addr, - uint64_t *data, - unsigned size, MemTxAttrs attrs) -{ - LoongsonIPI *ipi = opaque; - IPICore *s; - - if (attrs.requester_id >= ipi->num_cpu) { - return MEMTX_DECODE_ERROR; - } - - s = &ipi->cpu[attrs.requester_id]; - return loongson_ipi_core_readl(s, addr, data, size, attrs); -} - -static AddressSpace *get_cpu_iocsr_as(CPUState *cpu) -{ -#ifdef TARGET_LOONGARCH64 - return LOONGARCH_CPU(cpu)->env.address_space_iocsr; -#endif -#ifdef TARGET_MIPS if (ase_lcsr_available(&MIPS_CPU(cpu)->env)) { return &MIPS_CPU(cpu)->env.iocsr.as; } -#endif - return NULL; -} - -static MemTxResult send_ipi_data(CPUState *cpu, uint64_t val, hwaddr addr, - MemTxAttrs attrs) -{ - int i, mask = 0, data = 0; - AddressSpace *iocsr_as = get_cpu_iocsr_as(cpu); - - if (!iocsr_as) { - return MEMTX_DECODE_ERROR; - } - - /* - * bit 27-30 is mask for byte writing, - * if the mask is 0, we need not to do anything. - */ - if ((val >> 27) & 0xf) { - data = address_space_ldl_le(iocsr_as, addr, attrs, NULL); - for (i = 0; i < 4; i++) { - /* get mask for byte writing */ - if (val & (0x1 << (27 + i))) { - mask |= 0xff << (i * 8); - } - } - } - - data &= mask; - data |= (val >> 32) & ~mask; - address_space_stl_le(iocsr_as, addr, data, attrs, NULL); - - return MEMTX_OK; -} - -static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs) -{ - uint32_t cpuid; - hwaddr addr; - CPUState *cs; - - cpuid = extract32(val, 16, 10); - cs = cpu_by_arch_id(cpuid); - if (cs == NULL) { - return MEMTX_DECODE_ERROR; - } - - /* override requester_id */ - addr = SMP_IPI_MAILBOX + CORE_BUF_20 + (val & 0x1c); - attrs.requester_id = cs->cpu_index; - return send_ipi_data(cs, val, addr, attrs); -} - -static MemTxResult any_send(uint64_t val, MemTxAttrs attrs) -{ - uint32_t cpuid; - hwaddr addr; - CPUState *cs; - - cpuid = extract32(val, 16, 10); - cs = cpu_by_arch_id(cpuid); - if (cs == NULL) { - return MEMTX_DECODE_ERROR; - } - - /* override requester_id */ - addr = val & 0xffff; - attrs.requester_id = cs->cpu_index; - return send_ipi_data(cs, val, addr, attrs); -} - -static MemTxResult loongson_ipi_core_writel(void *opaque, hwaddr addr, - uint64_t val, unsigned size, - MemTxAttrs attrs) -{ - IPICore *s = opaque; - LoongsonIPI *ipi = s->ipi; - int index = 0; - uint32_t cpuid; - uint8_t vector; - CPUState *cs; - - addr &= 0xff; - trace_loongson_ipi_write(size, (uint64_t)addr, val); - switch (addr) { - case CORE_STATUS_OFF: - qemu_log_mask(LOG_GUEST_ERROR, "can not be written"); - break; - case CORE_EN_OFF: - s->en = val; - break; - case CORE_SET_OFF: - s->status |= val; - if (s->status != 0 && (s->status & s->en) != 0) { - qemu_irq_raise(s->irq); - } - break; - case CORE_CLEAR_OFF: - s->status &= ~val; - if (s->status == 0 && s->en != 0) { - qemu_irq_lower(s->irq); - } - break; - case CORE_BUF_20 ... CORE_BUF_38 + 4: - index = (addr - CORE_BUF_20) >> 2; - s->buf[index] = val; - break; - case IOCSR_IPI_SEND: - cpuid = extract32(val, 16, 10); - /* IPI status vector */ - vector = extract8(val, 0, 5); - cs = cpu_by_arch_id(cpuid); - if (cs == NULL || cs->cpu_index >= ipi->num_cpu) { - return MEMTX_DECODE_ERROR; - } - loongson_ipi_core_writel(&ipi->cpu[cs->cpu_index], CORE_SET_OFF, - BIT(vector), 4, attrs); - break; - default: - qemu_log_mask(LOG_UNIMP, "invalid write: %x", (uint32_t)addr); - break; - } - - return MEMTX_OK; -} - -static MemTxResult loongson_ipi_iocsr_writel(void *opaque, hwaddr addr, - uint64_t val, unsigned size, - MemTxAttrs attrs) -{ - LoongsonIPI *ipi = opaque; - IPICore *s; - - if (attrs.requester_id >= ipi->num_cpu) { - return MEMTX_DECODE_ERROR; - } - s = &ipi->cpu[attrs.requester_id]; - return loongson_ipi_core_writel(s, addr, val, size, attrs); + return NULL; } static const MemoryRegionOps loongson_ipi_core_ops = { @@ -235,141 +38,60 @@ static const MemoryRegionOps loongson_ipi_core_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static const MemoryRegionOps loongson_ipi_iocsr_ops = { - .read_with_attrs = loongson_ipi_iocsr_readl, - .write_with_attrs = loongson_ipi_iocsr_writel, - .impl.min_access_size = 4, - .impl.max_access_size = 4, - .valid.min_access_size = 4, - .valid.max_access_size = 8, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -/* mail send and any send only support writeq */ -static MemTxResult loongson_ipi_writeq(void *opaque, hwaddr addr, uint64_t val, - unsigned size, MemTxAttrs attrs) -{ - MemTxResult ret = MEMTX_OK; - - addr &= 0xfff; - switch (addr) { - case MAIL_SEND_OFFSET: - ret = mail_send(val, attrs); - break; - case ANY_SEND_OFFSET: - ret = any_send(val, attrs); - break; - default: - break; - } - - return ret; -} - -static const MemoryRegionOps loongson_ipi64_ops = { - .write_with_attrs = loongson_ipi_writeq, - .impl.min_access_size = 8, - .impl.max_access_size = 8, - .valid.min_access_size = 8, - .valid.max_access_size = 8, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - static void loongson_ipi_realize(DeviceState *dev, Error **errp) { - LoongsonIPI *s = LOONGSON_IPI(dev); + LoongsonIPICommonState *sc = LOONGSON_IPI_COMMON(dev); + LoongsonIPIState *s = LOONGSON_IPI(dev); + LoongsonIPIClass *lic = LOONGSON_IPI_GET_CLASS(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - int i; - - if (s->num_cpu == 0) { - error_setg(errp, "num-cpu must be at least 1"); - return; - } - - memory_region_init_io(&s->ipi_iocsr_mem, OBJECT(dev), - &loongson_ipi_iocsr_ops, - s, "loongson_ipi_iocsr", 0x48); - - /* loongson_ipi_iocsr performs re-entrant IO through ipi_send */ - s->ipi_iocsr_mem.disable_reentrancy_guard = true; - - sysbus_init_mmio(sbd, &s->ipi_iocsr_mem); - - memory_region_init_io(&s->ipi64_iocsr_mem, OBJECT(dev), - &loongson_ipi64_ops, - s, "loongson_ipi64_iocsr", 0x118); - sysbus_init_mmio(sbd, &s->ipi64_iocsr_mem); + Error *local_err = NULL; - s->cpu = g_new0(IPICore, s->num_cpu); - if (s->cpu == NULL) { - error_setg(errp, "Memory allocation for IPICore faile"); + lic->parent_realize(dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); return; } - for (i = 0; i < s->num_cpu; i++) { - s->cpu[i].ipi = s; - s->cpu[i].ipi_mmio_mem = g_new0(MemoryRegion, 1); + s->ipi_mmio_mem = g_new0(MemoryRegion, sc->num_cpu); + for (unsigned i = 0; i < sc->num_cpu; i++) { g_autofree char *name = g_strdup_printf("loongson_ipi_cpu%d_mmio", i); - memory_region_init_io(s->cpu[i].ipi_mmio_mem, OBJECT(dev), - &loongson_ipi_core_ops, &s->cpu[i], name, 0x48); - sysbus_init_mmio(sbd, s->cpu[i].ipi_mmio_mem); - qdev_init_gpio_out(dev, &s->cpu[i].irq, 1); + memory_region_init_io(&s->ipi_mmio_mem[i], OBJECT(dev), + &loongson_ipi_core_ops, &sc->cpu[i], name, 0x48); + sysbus_init_mmio(sbd, &s->ipi_mmio_mem[i]); } } static void loongson_ipi_unrealize(DeviceState *dev) { - LoongsonIPI *s = LOONGSON_IPI(dev); + LoongsonIPIState *s = LOONGSON_IPI(dev); + LoongsonIPIClass *k = LOONGSON_IPI_GET_CLASS(dev); - g_free(s->cpu); -} - -static const VMStateDescription vmstate_ipi_core = { - .name = "ipi-single", - .version_id = 2, - .minimum_version_id = 2, - .fields = (const VMStateField[]) { - VMSTATE_UINT32(status, IPICore), - VMSTATE_UINT32(en, IPICore), - VMSTATE_UINT32(set, IPICore), - VMSTATE_UINT32(clear, IPICore), - VMSTATE_UINT32_ARRAY(buf, IPICore, IPI_MBX_NUM * 2), - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription vmstate_loongson_ipi = { - .name = TYPE_LOONGSON_IPI, - .version_id = 2, - .minimum_version_id = 2, - .fields = (const VMStateField[]) { - VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongsonIPI, num_cpu, - vmstate_ipi_core, IPICore), - VMSTATE_END_OF_LIST() - } -}; + g_free(s->ipi_mmio_mem); -static Property ipi_properties[] = { - DEFINE_PROP_UINT32("num-cpu", LoongsonIPI, num_cpu, 1), - DEFINE_PROP_END_OF_LIST(), -}; + k->parent_unrealize(dev); +} static void loongson_ipi_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = loongson_ipi_realize; - dc->unrealize = loongson_ipi_unrealize; - device_class_set_props(dc, ipi_properties); - dc->vmsd = &vmstate_loongson_ipi; + LoongsonIPIClass *lic = LOONGSON_IPI_CLASS(klass); + LoongsonIPICommonClass *licc = LOONGSON_IPI_COMMON_CLASS(klass); + + device_class_set_parent_realize(dc, loongson_ipi_realize, + &lic->parent_realize); + device_class_set_parent_unrealize(dc, loongson_ipi_unrealize, + &lic->parent_unrealize); + licc->get_iocsr_as = get_iocsr_as; + licc->cpu_by_arch_id = cpu_by_arch_id; } static const TypeInfo loongson_ipi_types[] = { { .name = TYPE_LOONGSON_IPI, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(LoongsonIPI), + .parent = TYPE_LOONGSON_IPI_COMMON, + .instance_size = sizeof(LoongsonIPIState), + .class_size = sizeof(LoongsonIPIClass), .class_init = loongson_ipi_class_init, } }; diff --git a/hw/intc/loongson_ipi_common.c b/hw/intc/loongson_ipi_common.c new file mode 100644 index 0000000000..a6ce0181f6 --- /dev/null +++ b/hw/intc/loongson_ipi_common.c @@ -0,0 +1,347 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Loongson IPI interrupt common support + * + * Copyright (C) 2021 Loongson Technology Corporation Limited + */ + +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "hw/intc/loongson_ipi_common.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "qapi/error.h" +#include "qemu/log.h" +#include "migration/vmstate.h" +#include "trace.h" + +MemTxResult loongson_ipi_core_readl(void *opaque, hwaddr addr, uint64_t *data, + unsigned size, MemTxAttrs attrs) +{ + IPICore *s = opaque; + uint64_t ret = 0; + int index = 0; + + addr &= 0xff; + switch (addr) { + case CORE_STATUS_OFF: + ret = s->status; + break; + case CORE_EN_OFF: + ret = s->en; + break; + case CORE_SET_OFF: + ret = 0; + break; + case CORE_CLEAR_OFF: + ret = 0; + break; + case CORE_BUF_20 ... CORE_BUF_38 + 4: + index = (addr - CORE_BUF_20) >> 2; + ret = s->buf[index]; + break; + default: + qemu_log_mask(LOG_UNIMP, "invalid read: %x", (uint32_t)addr); + break; + } + + trace_loongson_ipi_read(size, (uint64_t)addr, ret); + *data = ret; + + return MEMTX_OK; +} + +static MemTxResult loongson_ipi_iocsr_readl(void *opaque, hwaddr addr, + uint64_t *data, unsigned size, + MemTxAttrs attrs) +{ + LoongsonIPICommonState *ipi = opaque; + IPICore *s; + + if (attrs.requester_id >= ipi->num_cpu) { + return MEMTX_DECODE_ERROR; + } + + s = &ipi->cpu[attrs.requester_id]; + return loongson_ipi_core_readl(s, addr, data, size, attrs); +} + +static MemTxResult send_ipi_data(LoongsonIPICommonState *ipi, CPUState *cpu, + uint64_t val, hwaddr addr, MemTxAttrs attrs) +{ + LoongsonIPICommonClass *licc = LOONGSON_IPI_COMMON_GET_CLASS(ipi); + int i, mask = 0, data = 0; + AddressSpace *iocsr_as = licc->get_iocsr_as(cpu); + + if (!iocsr_as) { + return MEMTX_DECODE_ERROR; + } + + /* + * bit 27-30 is mask for byte writing, + * if the mask is 0, we need not to do anything. + */ + if ((val >> 27) & 0xf) { + data = address_space_ldl_le(iocsr_as, addr, attrs, NULL); + for (i = 0; i < 4; i++) { + /* get mask for byte writing */ + if (val & (0x1 << (27 + i))) { + mask |= 0xff << (i * 8); + } + } + } + + data &= mask; + data |= (val >> 32) & ~mask; + address_space_stl_le(iocsr_as, addr, data, attrs, NULL); + + return MEMTX_OK; +} + +static MemTxResult mail_send(LoongsonIPICommonState *ipi, + uint64_t val, MemTxAttrs attrs) +{ + LoongsonIPICommonClass *licc = LOONGSON_IPI_COMMON_GET_CLASS(ipi); + uint32_t cpuid; + hwaddr addr; + CPUState *cs; + + cpuid = extract32(val, 16, 10); + cs = licc->cpu_by_arch_id(cpuid); + if (cs == NULL) { + return MEMTX_DECODE_ERROR; + } + + /* override requester_id */ + addr = SMP_IPI_MAILBOX + CORE_BUF_20 + (val & 0x1c); + attrs.requester_id = cs->cpu_index; + return send_ipi_data(ipi, cs, val, addr, attrs); +} + +static MemTxResult any_send(LoongsonIPICommonState *ipi, + uint64_t val, MemTxAttrs attrs) +{ + LoongsonIPICommonClass *licc = LOONGSON_IPI_COMMON_GET_CLASS(ipi); + uint32_t cpuid; + hwaddr addr; + CPUState *cs; + + cpuid = extract32(val, 16, 10); + cs = licc->cpu_by_arch_id(cpuid); + if (cs == NULL) { + return MEMTX_DECODE_ERROR; + } + + /* override requester_id */ + addr = val & 0xffff; + attrs.requester_id = cs->cpu_index; + return send_ipi_data(ipi, cs, val, addr, attrs); +} + +MemTxResult loongson_ipi_core_writel(void *opaque, hwaddr addr, uint64_t val, + unsigned size, MemTxAttrs attrs) +{ + IPICore *s = opaque; + LoongsonIPICommonState *ipi = s->ipi; + LoongsonIPICommonClass *licc = LOONGSON_IPI_COMMON_GET_CLASS(ipi); + int index = 0; + uint32_t cpuid; + uint8_t vector; + CPUState *cs; + + addr &= 0xff; + trace_loongson_ipi_write(size, (uint64_t)addr, val); + switch (addr) { + case CORE_STATUS_OFF: + qemu_log_mask(LOG_GUEST_ERROR, "can not be written"); + break; + case CORE_EN_OFF: + s->en = val; + break; + case CORE_SET_OFF: + s->status |= val; + if (s->status != 0 && (s->status & s->en) != 0) { + qemu_irq_raise(s->irq); + } + break; + case CORE_CLEAR_OFF: + s->status &= ~val; + if (s->status == 0 && s->en != 0) { + qemu_irq_lower(s->irq); + } + break; + case CORE_BUF_20 ... CORE_BUF_38 + 4: + index = (addr - CORE_BUF_20) >> 2; + s->buf[index] = val; + break; + case IOCSR_IPI_SEND: + cpuid = extract32(val, 16, 10); + /* IPI status vector */ + vector = extract8(val, 0, 5); + cs = licc->cpu_by_arch_id(cpuid); + if (cs == NULL || cs->cpu_index >= ipi->num_cpu) { + return MEMTX_DECODE_ERROR; + } + loongson_ipi_core_writel(&ipi->cpu[cs->cpu_index], CORE_SET_OFF, + BIT(vector), 4, attrs); + break; + default: + qemu_log_mask(LOG_UNIMP, "invalid write: %x", (uint32_t)addr); + break; + } + + return MEMTX_OK; +} + +static MemTxResult loongson_ipi_iocsr_writel(void *opaque, hwaddr addr, + uint64_t val, unsigned size, + MemTxAttrs attrs) +{ + LoongsonIPICommonState *ipi = opaque; + IPICore *s; + + if (attrs.requester_id >= ipi->num_cpu) { + return MEMTX_DECODE_ERROR; + } + + s = &ipi->cpu[attrs.requester_id]; + return loongson_ipi_core_writel(s, addr, val, size, attrs); +} + +static const MemoryRegionOps loongson_ipi_iocsr_ops = { + .read_with_attrs = loongson_ipi_iocsr_readl, + .write_with_attrs = loongson_ipi_iocsr_writel, + .impl.min_access_size = 4, + .impl.max_access_size = 4, + .valid.min_access_size = 4, + .valid.max_access_size = 8, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +/* mail send and any send only support writeq */ +static MemTxResult loongson_ipi_writeq(void *opaque, hwaddr addr, uint64_t val, + unsigned size, MemTxAttrs attrs) +{ + LoongsonIPICommonState *ipi = opaque; + MemTxResult ret = MEMTX_OK; + + addr &= 0xfff; + switch (addr) { + case MAIL_SEND_OFFSET: + ret = mail_send(ipi, val, attrs); + break; + case ANY_SEND_OFFSET: + ret = any_send(ipi, val, attrs); + break; + default: + break; + } + + return ret; +} + +static const MemoryRegionOps loongson_ipi64_ops = { + .write_with_attrs = loongson_ipi_writeq, + .impl.min_access_size = 8, + .impl.max_access_size = 8, + .valid.min_access_size = 8, + .valid.max_access_size = 8, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void loongson_ipi_common_realize(DeviceState *dev, Error **errp) +{ + LoongsonIPICommonState *s = LOONGSON_IPI_COMMON(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + int i; + + if (s->num_cpu == 0) { + error_setg(errp, "num-cpu must be at least 1"); + return; + } + + memory_region_init_io(&s->ipi_iocsr_mem, OBJECT(dev), + &loongson_ipi_iocsr_ops, + s, "loongson_ipi_iocsr", 0x48); + + /* loongson_ipi_iocsr performs re-entrant IO through ipi_send */ + s->ipi_iocsr_mem.disable_reentrancy_guard = true; + + sysbus_init_mmio(sbd, &s->ipi_iocsr_mem); + + memory_region_init_io(&s->ipi64_iocsr_mem, OBJECT(dev), + &loongson_ipi64_ops, + s, "loongson_ipi64_iocsr", 0x118); + sysbus_init_mmio(sbd, &s->ipi64_iocsr_mem); + + s->cpu = g_new0(IPICore, s->num_cpu); + for (i = 0; i < s->num_cpu; i++) { + s->cpu[i].ipi = s; + + qdev_init_gpio_out(dev, &s->cpu[i].irq, 1); + } +} + +static void loongson_ipi_common_unrealize(DeviceState *dev) +{ + LoongsonIPICommonState *s = LOONGSON_IPI_COMMON(dev); + + g_free(s->cpu); +} + +static const VMStateDescription vmstate_ipi_core = { + .name = "ipi-single", + .version_id = 2, + .minimum_version_id = 2, + .fields = (const VMStateField[]) { + VMSTATE_UINT32(status, IPICore), + VMSTATE_UINT32(en, IPICore), + VMSTATE_UINT32(set, IPICore), + VMSTATE_UINT32(clear, IPICore), + VMSTATE_UINT32_ARRAY(buf, IPICore, IPI_MBX_NUM * 2), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_loongson_ipi_common = { + .name = "loongson_ipi", + .version_id = 2, + .minimum_version_id = 2, + .fields = (const VMStateField[]) { + VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongsonIPICommonState, + num_cpu, vmstate_ipi_core, + IPICore), + VMSTATE_END_OF_LIST() + } +}; + +static Property ipi_common_properties[] = { + DEFINE_PROP_UINT32("num-cpu", LoongsonIPICommonState, num_cpu, 1), + DEFINE_PROP_END_OF_LIST(), +}; + +static void loongson_ipi_common_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + LoongsonIPICommonClass *licc = LOONGSON_IPI_COMMON_CLASS(klass); + + device_class_set_parent_realize(dc, loongson_ipi_common_realize, + &licc->parent_realize); + device_class_set_parent_unrealize(dc, loongson_ipi_common_unrealize, + &licc->parent_unrealize); + device_class_set_props(dc, ipi_common_properties); + dc->vmsd = &vmstate_loongson_ipi_common; +} + +static const TypeInfo loongarch_ipi_common_types[] = { + { + .name = TYPE_LOONGSON_IPI_COMMON, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(LoongsonIPICommonState), + .class_size = sizeof(LoongsonIPICommonClass), + .class_init = loongson_ipi_common_class_init, + .abstract = true, + } +}; + +DEFINE_TYPES(loongarch_ipi_common_types) diff --git a/hw/intc/meson.build b/hw/intc/meson.build index afd1aa51ee..f4d81eb8e4 100644 --- a/hw/intc/meson.build +++ b/hw/intc/meson.build @@ -69,7 +69,9 @@ specific_ss.add(when: 'CONFIG_XIVE', if_true: files('xive.c')) specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XIVE'], if_true: files('spapr_xive_kvm.c')) specific_ss.add(when: 'CONFIG_M68K_IRQC', if_true: files('m68k_irqc.c')) +specific_ss.add(when: 'CONFIG_LOONGSON_IPI_COMMON', if_true: files('loongson_ipi_common.c')) specific_ss.add(when: 'CONFIG_LOONGSON_IPI', if_true: files('loongson_ipi.c')) +specific_ss.add(when: 'CONFIG_LOONGARCH_IPI', if_true: files('loongarch_ipi.c')) specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: files('loongarch_pch_pic.c')) specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: files('loongarch_pch_msi.c')) specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI', if_true: files('loongarch_extioi.c')) diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig index 89be737726..0de713a439 100644 --- a/hw/loongarch/Kconfig +++ b/hw/loongarch/Kconfig @@ -12,7 +12,7 @@ config LOONGARCH_VIRT select SERIAL select VIRTIO_PCI select PLATFORM_BUS - select LOONGSON_IPI + select LOONGARCH_IPI select LOONGARCH_PCH_PIC select LOONGARCH_PCH_MSI select LOONGARCH_EXTIOI diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index e592b1b6b7..29040422aa 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -23,7 +23,7 @@ #include "net/net.h" #include "hw/loader.h" #include "elf.h" -#include "hw/intc/loongson_ipi.h" +#include "hw/intc/loongarch_ipi.h" #include "hw/intc/loongarch_extioi.h" #include "hw/intc/loongarch_pch_pic.h" #include "hw/intc/loongarch_pch_msi.h" @@ -788,7 +788,7 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms) */ /* Create IPI device */ - ipi = qdev_new(TYPE_LOONGSON_IPI); + ipi = qdev_new(TYPE_LOONGARCH_IPI); qdev_prop_set_uint32(ipi, "num-cpu", ms->smp.cpus); sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal); diff --git a/hw/pci-host/gt64120.c b/hw/pci-host/gt64120.c index e02efc9e2e..33607dfbec 100644 --- a/hw/pci-host/gt64120.c +++ b/hw/pci-host/gt64120.c @@ -1,6 +1,8 @@ /* * QEMU GT64120 PCI host * + * (Datasheet GT-64120 Rev 1.4 from Sep 14, 1999) + * * Copyright (c) 2006,2007 Aurelien Jarno * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -1213,17 +1215,34 @@ static void gt64120_realize(DeviceState *dev, Error **errp) static void gt64120_pci_realize(PCIDevice *d, Error **errp) { - /* FIXME: Malta specific hw assumptions ahead */ + /* Values from chapter 17.16 "PCI Configuration" */ + + pci_set_long(d->wmask + PCI_BASE_ADDRESS_0, 0xfffff008); /* SCS[1:0] */ + pci_set_long(d->wmask + PCI_BASE_ADDRESS_1, 0xfffff008); /* SCS[3:2] */ + pci_set_long(d->wmask + PCI_BASE_ADDRESS_2, 0xfffff008); /* CS[2:0] */ + pci_set_long(d->wmask + PCI_BASE_ADDRESS_3, 0xfffff008); /* CS[3], BootCS */ + pci_set_long(d->wmask + PCI_BASE_ADDRESS_4, 0xfffff000); /* ISD MMIO */ + pci_set_long(d->wmask + PCI_BASE_ADDRESS_5, 0xfffff001); /* ISD I/O */ +} + +static void gt64120_pci_reset_hold(Object *obj, ResetType type) +{ + PCIDevice *d = PCI_DEVICE(obj); + + /* Values from chapter 17.16 "PCI Configuration" */ + pci_set_word(d->config + PCI_COMMAND, 0); pci_set_word(d->config + PCI_STATUS, PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM); pci_config_set_prog_interface(d->config, 0); + pci_set_long(d->config + PCI_BASE_ADDRESS_0, 0x00000008); pci_set_long(d->config + PCI_BASE_ADDRESS_1, 0x01000008); pci_set_long(d->config + PCI_BASE_ADDRESS_2, 0x1c000000); pci_set_long(d->config + PCI_BASE_ADDRESS_3, 0x1f000000); pci_set_long(d->config + PCI_BASE_ADDRESS_4, 0x14000000); pci_set_long(d->config + PCI_BASE_ADDRESS_5, 0x14000001); + pci_set_byte(d->config + 0x3d, 0x01); } @@ -1231,7 +1250,9 @@ static void gt64120_pci_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); + ResettableClass *rc = RESETTABLE_CLASS(klass); + rc->phases.hold = gt64120_pci_reset_hold; k->realize = gt64120_pci_realize; k->vendor_id = PCI_VENDOR_ID_MARVELL; k->device_id = PCI_DEVICE_ID_MARVELL_GT6412X; diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 07cb97d88c..a140a32ccd 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -2478,20 +2478,22 @@ void sd_write_byte(SDState *sd, uint8_t value) uint8_t sd_read_byte(SDState *sd) { /* TODO: Append CRCs */ + const uint8_t dummy_byte = 0x00; uint8_t ret; uint32_t io_len; if (!sd->blk || !blk_is_inserted(sd->blk) || !sd->enable) - return 0x00; + return dummy_byte; if (sd->state != sd_sendingdata_state) { qemu_log_mask(LOG_GUEST_ERROR, "%s: not in Sending-Data state\n", __func__); - return 0x00; + return dummy_byte; } - if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION)) - return 0x00; + if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION)) { + return dummy_byte; + } io_len = sd_blk_len(sd); @@ -2517,7 +2519,7 @@ uint8_t sd_read_byte(SDState *sd) if (sd->data_offset == 0) { if (!address_in_range(sd, "READ_MULTIPLE_BLOCK", sd->data_start, io_len)) { - return 0x00; + return dummy_byte; } sd_blk_read(sd, sd->data_start, io_len); } @@ -2538,7 +2540,9 @@ uint8_t sd_read_byte(SDState *sd) break; default: - g_assert_not_reached(); + qemu_log_mask(LOG_GUEST_ERROR, "%s: DAT read illegal for command %s\n", + __func__, sd->last_cmd_name); + return dummy_byte; } return ret; diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index d02c3e3963..8293d83556 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -846,6 +846,7 @@ static void sdhci_do_adma(SDHCIState *s) } } if (res != MEMTX_OK) { + s->data_count = 0; if (s->errintstsen & SDHC_EISEN_ADMAERR) { trace_sdhci_error("Set ADMA error flag"); s->errintsts |= SDHC_EIS_ADMAERR; diff --git a/include/hw/intc/loongarch_ipi.h b/include/hw/intc/loongarch_ipi.h new file mode 100644 index 0000000000..276b3040a3 --- /dev/null +++ b/include/hw/intc/loongarch_ipi.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * LoongArch IPI interrupt header files + * + * Copyright (C) 2024 Loongson Technology Corporation Limited + */ + +#ifndef HW_LOONGARCH_IPI_H +#define HW_LOONGARCH_IPI_H + +#include "qom/object.h" +#include "hw/intc/loongson_ipi_common.h" + +#define TYPE_LOONGARCH_IPI "loongarch_ipi" +OBJECT_DECLARE_TYPE(LoongarchIPIState, LoongarchIPIClass, LOONGARCH_IPI) + +struct LoongarchIPIState { + LoongsonIPICommonState parent_obj; +}; + +struct LoongarchIPIClass { + LoongsonIPICommonClass parent_class; +}; + +#endif diff --git a/include/hw/intc/loongson_ipi.h b/include/hw/intc/loongson_ipi.h index 3f795edbf3..4e517cc8dc 100644 --- a/include/hw/intc/loongson_ipi.h +++ b/include/hw/intc/loongson_ipi.h @@ -8,49 +8,24 @@ #ifndef HW_LOONGSON_IPI_H #define HW_LOONGSON_IPI_H +#include "qom/object.h" +#include "hw/intc/loongson_ipi_common.h" #include "hw/sysbus.h" -/* Mainy used by iocsr read and write */ -#define SMP_IPI_MAILBOX 0x1000ULL -#define CORE_STATUS_OFF 0x0 -#define CORE_EN_OFF 0x4 -#define CORE_SET_OFF 0x8 -#define CORE_CLEAR_OFF 0xc -#define CORE_BUF_20 0x20 -#define CORE_BUF_28 0x28 -#define CORE_BUF_30 0x30 -#define CORE_BUF_38 0x38 -#define IOCSR_IPI_SEND 0x40 -#define IOCSR_MAIL_SEND 0x48 -#define IOCSR_ANY_SEND 0x158 - -#define MAIL_SEND_ADDR (SMP_IPI_MAILBOX + IOCSR_MAIL_SEND) -#define MAIL_SEND_OFFSET 0 -#define ANY_SEND_OFFSET (IOCSR_ANY_SEND - IOCSR_MAIL_SEND) - -#define IPI_MBX_NUM 4 - #define TYPE_LOONGSON_IPI "loongson_ipi" -OBJECT_DECLARE_SIMPLE_TYPE(LoongsonIPI, LOONGSON_IPI) +OBJECT_DECLARE_TYPE(LoongsonIPIState, LoongsonIPIClass, LOONGSON_IPI) + +struct LoongsonIPIClass { + LoongsonIPICommonClass parent_class; + + DeviceRealize parent_realize; + DeviceUnrealize parent_unrealize; +}; + +struct LoongsonIPIState { + LoongsonIPICommonState parent_obj; -typedef struct IPICore { - LoongsonIPI *ipi; MemoryRegion *ipi_mmio_mem; - uint32_t status; - uint32_t en; - uint32_t set; - uint32_t clear; - /* 64bit buf divide into 2 32bit buf */ - uint32_t buf[IPI_MBX_NUM * 2]; - qemu_irq irq; -} IPICore; - -struct LoongsonIPI { - SysBusDevice parent_obj; - MemoryRegion ipi_iocsr_mem; - MemoryRegion ipi64_iocsr_mem; - uint32_t num_cpu; - IPICore *cpu; }; #endif diff --git a/include/hw/intc/loongson_ipi_common.h b/include/hw/intc/loongson_ipi_common.h new file mode 100644 index 0000000000..df9d9c5168 --- /dev/null +++ b/include/hw/intc/loongson_ipi_common.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Loongson ipi interrupt header files + * + * Copyright (C) 2021 Loongson Technology Corporation Limited + */ + +#ifndef HW_LOONGSON_IPI_COMMON_H +#define HW_LOONGSON_IPI_COMMON_H + +#include "qom/object.h" +#include "hw/sysbus.h" +#include "exec/memattrs.h" + +#define IPI_MBX_NUM 4 + +#define TYPE_LOONGSON_IPI_COMMON "loongson_ipi_common" +OBJECT_DECLARE_TYPE(LoongsonIPICommonState, + LoongsonIPICommonClass, LOONGSON_IPI_COMMON) + +typedef struct IPICore { + LoongsonIPICommonState *ipi; + uint32_t status; + uint32_t en; + uint32_t set; + uint32_t clear; + /* 64bit buf divide into 2 32-bit buf */ + uint32_t buf[IPI_MBX_NUM * 2]; + qemu_irq irq; +} IPICore; + +struct LoongsonIPICommonState { + SysBusDevice parent_obj; + + MemoryRegion ipi_iocsr_mem; + MemoryRegion ipi64_iocsr_mem; + uint32_t num_cpu; + IPICore *cpu; +}; + +struct LoongsonIPICommonClass { + SysBusDeviceClass parent_class; + + DeviceRealize parent_realize; + DeviceUnrealize parent_unrealize; + AddressSpace *(*get_iocsr_as)(CPUState *cpu); + CPUState *(*cpu_by_arch_id)(int64_t id); +}; + +MemTxResult loongson_ipi_core_readl(void *opaque, hwaddr addr, uint64_t *data, + unsigned size, MemTxAttrs attrs); +MemTxResult loongson_ipi_core_writel(void *opaque, hwaddr addr, uint64_t val, + unsigned size, MemTxAttrs attrs); + +/* Mainy used by iocsr read and write */ +#define SMP_IPI_MAILBOX 0x1000ULL + +#define CORE_STATUS_OFF 0x0 +#define CORE_EN_OFF 0x4 +#define CORE_SET_OFF 0x8 +#define CORE_CLEAR_OFF 0xc +#define CORE_BUF_20 0x20 +#define CORE_BUF_28 0x28 +#define CORE_BUF_30 0x30 +#define CORE_BUF_38 0x38 +#define IOCSR_IPI_SEND 0x40 +#define IOCSR_MAIL_SEND 0x48 +#define IOCSR_ANY_SEND 0x158 + +#define MAIL_SEND_ADDR (SMP_IPI_MAILBOX + IOCSR_MAIL_SEND) +#define MAIL_SEND_OFFSET 0 +#define ANY_SEND_OFFSET (IOCSR_ANY_SEND - IOCSR_MAIL_SEND) + +#endif diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h index 603c1cebdb..c373e48f27 100644 --- a/include/hw/loongarch/virt.h +++ b/include/hw/loongarch/virt.h @@ -11,7 +11,6 @@ #include "target/loongarch/cpu.h" #include "hw/boards.h" #include "qemu/queue.h" -#include "hw/intc/loongson_ipi.h" #include "hw/block/flash.h" #include "hw/loongarch/boot.h" diff --git a/system/vl.c b/system/vl.c index 9e8f16f155..41d53d2456 100644 --- a/system/vl.c +++ b/system/vl.c @@ -1973,9 +1973,10 @@ static void qemu_create_early_backends(void) if (dpy.has_gl && dpy.gl != DISPLAYGL_MODE_OFF && display_opengl == 0) { #if defined(CONFIG_OPENGL) - error_report("OpenGL is not supported by the display"); + error_report("OpenGL is not supported by display backend '%s'", + DisplayType_str(dpy.type)); #else - error_report("OpenGL support is disabled"); + error_report("OpenGL support was not enabled in this build of QEMU"); #endif exit(1); } diff --git a/ui/console.c b/ui/console.c index e8f0083af7..105a0e2c70 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1632,4 +1632,9 @@ void qemu_display_help(void) printf("%s\n", DisplayType_str(dpys[idx]->type)); } } + printf("\n" + "Some display backends support suboptions, which can be set with\n" + " -display backend,option=value,option=value...\n" + "For a short list of the suboptions for each display, see the " + "top-level -help output; more detail is in the documentation.\n"); } |