From d9a8e9d79ade5b82d9ba467fbcb49a9003b88e28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 7 Mar 2025 14:21:06 +0100 Subject: [PATCH 01/45] hw/virtio/virtio-mem: Convert VIRTIO_MEM_USABLE_EXTENT to runtime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use target_arch() to check at runtime which target architecture is being run. Note, since TARGET_ARM is defined for TARGET_AARCH64, we check for both ARM & AARCH64 enum values. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Pierrick Bouvier Acked-by: David Hildenbrand Reviewed-by: Michael S. Tsirkin Message-Id: <20250502214551.80401-4-philmd@linaro.org> --- hw/virtio/virtio-mem.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c index 15ba6799f2..f16445b934 100644 --- a/hw/virtio/virtio-mem.c +++ b/hw/virtio/virtio-mem.c @@ -15,6 +15,7 @@ #include "qemu/cutils.h" #include "qemu/error-report.h" #include "qemu/units.h" +#include "qemu/target-info-qapi.h" #include "system/numa.h" #include "system/system.h" #include "system/ramblock.h" @@ -170,13 +171,20 @@ static bool virtio_mem_has_shared_zeropage(RAMBlock *rb) * necessary (as the section size can change). But it's more likely that the * section size will rather get smaller and not bigger over time. */ -#if defined(TARGET_X86_64) || defined(TARGET_I386) || defined(TARGET_S390X) -#define VIRTIO_MEM_USABLE_EXTENT (2 * (128 * MiB)) -#elif defined(TARGET_ARM) -#define VIRTIO_MEM_USABLE_EXTENT (2 * (512 * MiB)) -#else -#error VIRTIO_MEM_USABLE_EXTENT not defined -#endif +static uint64_t virtio_mem_usable_extent_size(void) +{ + switch (target_arch()) { + case SYS_EMU_TARGET_I386: + case SYS_EMU_TARGET_X86_64: + case SYS_EMU_TARGET_S390X: + return 2 * 128 * MiB; + case SYS_EMU_TARGET_AARCH64: + case SYS_EMU_TARGET_ARM: + return 2 * 512 * MiB; + default: + g_assert_not_reached(); + } +} static bool virtio_mem_is_busy(void) { @@ -699,7 +707,7 @@ static void virtio_mem_resize_usable_region(VirtIOMEM *vmem, bool can_shrink) { uint64_t newsize = MIN(memory_region_size(&vmem->memdev->mr), - requested_size + VIRTIO_MEM_USABLE_EXTENT); + requested_size + virtio_mem_usable_extent_size()); /* The usable region size always has to be multiples of the block size. */ newsize = QEMU_ALIGN_UP(newsize, vmem->block_size); From 0d9468ba523431794b0d11da64a7f67b95fe3ed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 16 Apr 2025 14:29:55 +0200 Subject: [PATCH 02/45] hw/virtio/virtio-mem: Convert VIRTIO_MEM_HAS_LEGACY_GUESTS to runtime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check legacy guests support at runtime: instead of evaluating the VIRTIO_MEM_HAS_LEGACY_GUESTS definition at compile time, call target_arch() to detect which target is being run at runtime. Register virtio_mem_legacy_guests_properties[] at runtime. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Pierrick Bouvier Acked-by: David Hildenbrand Reviewed-by: Michael S. Tsirkin Message-Id: <20250502214551.80401-5-philmd@linaro.org> --- hw/virtio/virtio-mem.c | 76 ++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c index f16445b934..ae7c13e33c 100644 --- a/hw/virtio/virtio-mem.c +++ b/hw/virtio/virtio-mem.c @@ -34,13 +34,21 @@ static const VMStateDescription vmstate_virtio_mem_device_early; -/* - * We only had legacy x86 guests that did not support - * VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE. Other targets don't have legacy guests. - */ -#if defined(TARGET_X86_64) || defined(TARGET_I386) -#define VIRTIO_MEM_HAS_LEGACY_GUESTS -#endif +static bool virtio_mem_has_legacy_guests(void) +{ + /* + * We only had legacy x86 guests that did not support + * VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE. Other targets don't have + * legacy guests. + */ + switch (target_arch()) { + case SYS_EMU_TARGET_I386: + case SYS_EMU_TARGET_X86_64: + return true; + default: + return false; + } +} /* * Let's not allow blocks smaller than 1 MiB, for example, to keep the tracking @@ -144,7 +152,6 @@ static uint64_t virtio_mem_default_block_size(RAMBlock *rb) return MAX(page_size, VIRTIO_MEM_MIN_BLOCK_SIZE); } -#if defined(VIRTIO_MEM_HAS_LEGACY_GUESTS) static bool virtio_mem_has_shared_zeropage(RAMBlock *rb) { /* @@ -155,7 +162,6 @@ static bool virtio_mem_has_shared_zeropage(RAMBlock *rb) return !qemu_ram_is_shared(rb) && qemu_ram_get_fd(rb) < 0 && qemu_ram_pagesize(rb) == qemu_real_host_page_size(); } -#endif /* VIRTIO_MEM_HAS_LEGACY_GUESTS */ /* * Size the usable region bigger than the requested size if possible. Esp. @@ -983,28 +989,28 @@ static void virtio_mem_device_realize(DeviceState *dev, Error **errp) rb = vmem->memdev->mr.ram_block; page_size = qemu_ram_pagesize(rb); -#if defined(VIRTIO_MEM_HAS_LEGACY_GUESTS) - switch (vmem->unplugged_inaccessible) { - case ON_OFF_AUTO_AUTO: - if (virtio_mem_has_shared_zeropage(rb)) { - vmem->unplugged_inaccessible = ON_OFF_AUTO_OFF; - } else { - vmem->unplugged_inaccessible = ON_OFF_AUTO_ON; + if (virtio_mem_has_legacy_guests()) { + switch (vmem->unplugged_inaccessible) { + case ON_OFF_AUTO_AUTO: + if (virtio_mem_has_shared_zeropage(rb)) { + vmem->unplugged_inaccessible = ON_OFF_AUTO_OFF; + } else { + vmem->unplugged_inaccessible = ON_OFF_AUTO_ON; + } + break; + case ON_OFF_AUTO_OFF: + if (!virtio_mem_has_shared_zeropage(rb)) { + warn_report("'%s' property set to 'off' with a memdev that does" + " not support the shared zeropage.", + VIRTIO_MEM_UNPLUGGED_INACCESSIBLE_PROP); + } + break; + default: + break; } - break; - case ON_OFF_AUTO_OFF: - if (!virtio_mem_has_shared_zeropage(rb)) { - warn_report("'%s' property set to 'off' with a memdev that does" - " not support the shared zeropage.", - VIRTIO_MEM_UNPLUGGED_INACCESSIBLE_PROP); - } - break; - default: - break; + } else { + vmem->unplugged_inaccessible = ON_OFF_AUTO_ON; } -#else /* VIRTIO_MEM_HAS_LEGACY_GUESTS */ - vmem->unplugged_inaccessible = ON_OFF_AUTO_ON; -#endif /* VIRTIO_MEM_HAS_LEGACY_GUESTS */ if (vmem->dynamic_memslots && vmem->unplugged_inaccessible != ON_OFF_AUTO_ON) { @@ -1701,16 +1707,17 @@ static const Property virtio_mem_properties[] = { DEFINE_PROP_BOOL(VIRTIO_MEM_PREALLOC_PROP, VirtIOMEM, prealloc, false), DEFINE_PROP_LINK(VIRTIO_MEM_MEMDEV_PROP, VirtIOMEM, memdev, TYPE_MEMORY_BACKEND, HostMemoryBackend *), -#if defined(VIRTIO_MEM_HAS_LEGACY_GUESTS) - DEFINE_PROP_ON_OFF_AUTO(VIRTIO_MEM_UNPLUGGED_INACCESSIBLE_PROP, VirtIOMEM, - unplugged_inaccessible, ON_OFF_AUTO_ON), -#endif DEFINE_PROP_BOOL(VIRTIO_MEM_EARLY_MIGRATION_PROP, VirtIOMEM, early_migration, true), DEFINE_PROP_BOOL(VIRTIO_MEM_DYNAMIC_MEMSLOTS_PROP, VirtIOMEM, dynamic_memslots, false), }; +static const Property virtio_mem_legacy_guests_properties[] = { + DEFINE_PROP_ON_OFF_AUTO(VIRTIO_MEM_UNPLUGGED_INACCESSIBLE_PROP, VirtIOMEM, + unplugged_inaccessible, ON_OFF_AUTO_ON), +}; + static uint64_t virtio_mem_rdm_get_min_granularity(const RamDiscardManager *rdm, const MemoryRegion *mr) { @@ -1862,6 +1869,9 @@ static void virtio_mem_class_init(ObjectClass *klass, const void *data) RamDiscardManagerClass *rdmc = RAM_DISCARD_MANAGER_CLASS(klass); device_class_set_props(dc, virtio_mem_properties); + if (virtio_mem_has_legacy_guests()) { + device_class_set_props(dc, virtio_mem_legacy_guests_properties); + } dc->vmsd = &vmstate_virtio_mem; set_bit(DEVICE_CATEGORY_MISC, dc->categories); From f1ee11469318a1e5d9da16b6c6c6b51c99b3edf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 7 Mar 2025 14:51:58 +0100 Subject: [PATCH 03/45] hw/virtio: Compile virtio-mem.c once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove unused "system/ram_addr.h" header. This file doesn't use any target specific definitions anymore, compile it once by moving it to system_virtio_ss[]. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: David Hildenbrand Reviewed-by: Pierrick Bouvier Acked-by: David Hildenbrand Reviewed-by: Michael S. Tsirkin Message-Id: <20250502214551.80401-6-philmd@linaro.org> --- hw/virtio/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build index 48b9fedfa5..affd66887d 100644 --- a/hw/virtio/meson.build +++ b/hw/virtio/meson.build @@ -57,7 +57,7 @@ specific_virtio_ss.add(when: 'CONFIG_VIRTIO_BALLOON', if_true: files('virtio-bal specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_FS', if_true: files('vhost-user-fs.c')) specific_virtio_ss.add(when: 'CONFIG_VIRTIO_PMEM', if_true: files('virtio-pmem.c')) specific_virtio_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock.c')) -specific_virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c')) +system_virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c')) system_virtio_ss.add(when: 'CONFIG_VIRTIO_NSM', if_true: files('virtio-nsm.c')) system_virtio_ss.add(when: 'CONFIG_VIRTIO_NSM', if_true: [files('cbor-helpers.c'), libcbor]) system_virtio_ss.add(when: 'CONFIG_VHOST_USER_SCMI', if_true: files('vhost-user-scmi.c')) From 62ef928312a981d0e25672f72dd467f4a0c05463 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sun, 4 May 2025 18:01:35 +0200 Subject: [PATCH 04/45] hw/pci-host/raven: Simplify direct config access address decoding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use ctz instead of an open coded version and rename function to better show what it does. Signed-off-by: BALATON Zoltan Reviewed-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Message-ID: <68c038fd225463db282d0277d80cb525e0551413.1760795082.git.balaton@eik.bme.hu> Signed-off-by: Philippe Mathieu-Daudé --- hw/pci-host/raven.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/hw/pci-host/raven.c b/hw/pci-host/raven.c index f8c0be5d21..ee9058e262 100644 --- a/hw/pci-host/raven.c +++ b/hw/pci-host/raven.c @@ -72,16 +72,9 @@ struct PRePPCIState { #define PCI_IO_BASE_ADDR 0x80000000 /* Physical address on main bus */ -static inline uint32_t raven_pci_io_config(hwaddr addr) +static inline uint32_t raven_idsel_to_addr(hwaddr addr) { - int i; - - for (i = 0; i < 11; i++) { - if ((addr & (1 << (11 + i))) != 0) { - break; - } - } - return (addr & 0x7ff) | (i << 11); + return (ctz16(addr >> 11) << 11) | (addr & 0x7ff); } static void raven_pci_io_write(void *opaque, hwaddr addr, @@ -89,7 +82,7 @@ static void raven_pci_io_write(void *opaque, hwaddr addr, { PREPPCIState *s = opaque; PCIHostState *phb = PCI_HOST_BRIDGE(s); - pci_data_write(phb->bus, raven_pci_io_config(addr), val, size); + pci_data_write(phb->bus, raven_idsel_to_addr(addr), val, size); } static uint64_t raven_pci_io_read(void *opaque, hwaddr addr, @@ -97,7 +90,7 @@ static uint64_t raven_pci_io_read(void *opaque, hwaddr addr, { PREPPCIState *s = opaque; PCIHostState *phb = PCI_HOST_BRIDGE(s); - return pci_data_read(phb->bus, raven_pci_io_config(addr), size); + return pci_data_read(phb->bus, raven_idsel_to_addr(addr), size); } static const MemoryRegionOps raven_pci_io_ops = { From 046d2e21fcf6a8b0dca8555da2d5684ca8a4dd82 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sun, 4 May 2025 18:01:36 +0200 Subject: [PATCH 05/45] hw/pci-host/raven: Rename direct config access ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename memory io ops implementing PCI configuration direct access to mmcfg which describes better what these are for. Signed-off-by: BALATON Zoltan Reviewed-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Message-ID: <74fcd70106289663ea426161aada78e879995d6c.1760795082.git.balaton@eik.bme.hu> Signed-off-by: Philippe Mathieu-Daudé --- hw/pci-host/raven.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/hw/pci-host/raven.c b/hw/pci-host/raven.c index ee9058e262..e0ebc81c24 100644 --- a/hw/pci-host/raven.c +++ b/hw/pci-host/raven.c @@ -77,25 +77,24 @@ static inline uint32_t raven_idsel_to_addr(hwaddr addr) return (ctz16(addr >> 11) << 11) | (addr & 0x7ff); } -static void raven_pci_io_write(void *opaque, hwaddr addr, - uint64_t val, unsigned int size) +static void raven_mmcfg_write(void *opaque, hwaddr addr, uint64_t val, + unsigned int size) { PREPPCIState *s = opaque; PCIHostState *phb = PCI_HOST_BRIDGE(s); pci_data_write(phb->bus, raven_idsel_to_addr(addr), val, size); } -static uint64_t raven_pci_io_read(void *opaque, hwaddr addr, - unsigned int size) +static uint64_t raven_mmcfg_read(void *opaque, hwaddr addr, unsigned int size) { PREPPCIState *s = opaque; PCIHostState *phb = PCI_HOST_BRIDGE(s); return pci_data_read(phb->bus, raven_idsel_to_addr(addr), size); } -static const MemoryRegionOps raven_pci_io_ops = { - .read = raven_pci_io_read, - .write = raven_pci_io_write, +static const MemoryRegionOps raven_mmcfg_ops = { + .read = raven_mmcfg_read, + .write = raven_mmcfg_write, .endianness = DEVICE_LITTLE_ENDIAN, }; @@ -253,8 +252,8 @@ static void raven_pcihost_realizefn(DeviceState *d, Error **errp) "pci-conf-data", 4); memory_region_add_subregion(&s->pci_io, 0xcfc, &h->data_mem); - memory_region_init_io(&h->mmcfg, OBJECT(s), &raven_pci_io_ops, s, - "pciio", 0x00400000); + memory_region_init_io(&h->mmcfg, OBJECT(s), &raven_mmcfg_ops, s, + "pci-mmcfg", 0x00400000); memory_region_add_subregion(address_space_mem, 0x80800000, &h->mmcfg); memory_region_init_io(&s->pci_intack, OBJECT(s), &raven_intack_ops, s, From dcff29f4cca2090d8454aa8a6ba23511e4758ff4 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Thu, 3 Jul 2025 00:09:02 +0200 Subject: [PATCH 06/45] hw/pci-host/raven: Use correct parameter in direct access ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of passing unneeded enclosing objects to the config direct access ops that only need the bus we can pass that directly thus simplifying the functions. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-ID: <226e0756661e72a03ba363887730112a58acde85.1760795082.git.balaton@eik.bme.hu> Signed-off-by: Philippe Mathieu-Daudé --- hw/pci-host/raven.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/hw/pci-host/raven.c b/hw/pci-host/raven.c index e0ebc81c24..eacffc86d8 100644 --- a/hw/pci-host/raven.c +++ b/hw/pci-host/raven.c @@ -80,16 +80,16 @@ static inline uint32_t raven_idsel_to_addr(hwaddr addr) static void raven_mmcfg_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { - PREPPCIState *s = opaque; - PCIHostState *phb = PCI_HOST_BRIDGE(s); - pci_data_write(phb->bus, raven_idsel_to_addr(addr), val, size); + PCIBus *hbus = opaque; + + pci_data_write(hbus, raven_idsel_to_addr(addr), val, size); } static uint64_t raven_mmcfg_read(void *opaque, hwaddr addr, unsigned int size) { - PREPPCIState *s = opaque; - PCIHostState *phb = PCI_HOST_BRIDGE(s); - return pci_data_read(phb->bus, raven_idsel_to_addr(addr), size); + PCIBus *hbus = opaque; + + return pci_data_read(hbus, raven_idsel_to_addr(addr), size); } static const MemoryRegionOps raven_mmcfg_ops = { @@ -252,7 +252,7 @@ static void raven_pcihost_realizefn(DeviceState *d, Error **errp) "pci-conf-data", 4); memory_region_add_subregion(&s->pci_io, 0xcfc, &h->data_mem); - memory_region_init_io(&h->mmcfg, OBJECT(s), &raven_mmcfg_ops, s, + memory_region_init_io(&h->mmcfg, OBJECT(h), &raven_mmcfg_ops, h->bus, "pci-mmcfg", 0x00400000); memory_region_add_subregion(address_space_mem, 0x80800000, &h->mmcfg); From 2c6fab1c143059e59128b805f4e6a6796eedee43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 20 Oct 2025 23:46:21 +0200 Subject: [PATCH 07/45] hw/core: Filter machine list available for a particular target binary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Binaries can register a QOM type to filter their machines by filling their TargetInfo::machine_typename field. Commit 28502121be7 ("system/vl: Filter machine list available for a particular target binary") added the filter to machine_help_func() but missed the other places where the machine list must be filtered, such QMP 'query-machines' command used by QTests, and select_machine(). Fix that. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Pierrick Bouvier Message-Id: <20251020220941.65269-2-philmd@linaro.org> --- hw/core/machine-qmp-cmds.c | 4 +++- monitor/qemu-config-qmp.c | 3 ++- system/vl.c | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c index 51d5c230f7..28dfd3e15b 100644 --- a/hw/core/machine-qmp-cmds.c +++ b/hw/core/machine-qmp-cmds.c @@ -20,6 +20,7 @@ #include "qapi/qobject-input-visitor.h" #include "qapi/type-helpers.h" #include "qemu/uuid.h" +#include "qemu/target-info.h" #include "qemu/target-info-qapi.h" #include "qom/qom-qobject.h" #include "system/hostmem.h" @@ -94,9 +95,10 @@ CpuInfoFastList *qmp_query_cpus_fast(Error **errp) MachineInfoList *qmp_query_machines(bool has_compat_props, bool compat_props, Error **errp) { - GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false); + GSList *el, *machines; MachineInfoList *mach_list = NULL; + machines = object_class_get_list(target_machine_typename(), false); for (el = machines; el; el = el->next) { MachineClass *mc = el->data; const char *default_cpu_type = machine_class_default_cpu_type(mc); diff --git a/monitor/qemu-config-qmp.c b/monitor/qemu-config-qmp.c index 9a3b183602..8bd28fc232 100644 --- a/monitor/qemu-config-qmp.c +++ b/monitor/qemu-config-qmp.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ #include "qemu/osdep.h" +#include "qemu/target-info.h" #include "qapi/error.h" #include "qapi/qapi-commands-misc.h" #include "qobject/qlist.h" @@ -128,7 +129,7 @@ static CommandLineParameterInfoList *query_all_machine_properties(void) ObjectProperty *prop; bool is_new; - machines = object_class_get_list(TYPE_MACHINE, false); + machines = object_class_get_list(target_machine_typename(), false); assert(machines); /* Loop over all machine classes */ diff --git a/system/vl.c b/system/vl.c index 646239e4a6..a96063f990 100644 --- a/system/vl.c +++ b/system/vl.c @@ -1672,7 +1672,8 @@ static MachineClass *select_machine(QDict *qdict, Error **errp) { ERRP_GUARD(); const char *machine_type = qdict_get_try_str(qdict, "type"); - g_autoptr(GSList) machines = object_class_get_list(TYPE_MACHINE, false); + g_autoptr(GSList) machines = object_class_get_list(target_machine_typename(), + false); MachineClass *machine_class = NULL; if (machine_type) { From 42a4700bb9c6e9424b3ed12f041209e0770f971c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 4 Apr 2025 00:54:15 +0200 Subject: [PATCH 08/45] hw/core/machine: Allow dynamic registration of valid CPU types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add MachineClass::get_valid_cpu_types(), a helper that returns a dynamic list of CPU types. Since the helper takes a MachineState argument, we know the machine is created by the time we call it. Suggested-by: Pierrick Bouvier Reviewed-by: Pierrick Bouvier Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20251020220941.65269-4-philmd@linaro.org> --- hw/core/machine.c | 28 ++++++++++++++++++++++++++++ include/hw/boards.h | 4 ++++ 2 files changed, 32 insertions(+) diff --git a/hw/core/machine.c b/hw/core/machine.c index 7aec3916e8..cd2f1414a7 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -1570,6 +1570,8 @@ static bool is_cpu_type_supported(const MachineState *machine, Error **errp) */ if (mc->valid_cpu_types) { assert(mc->valid_cpu_types[0] != NULL); + assert(!mc->get_valid_cpu_types); + for (i = 0; mc->valid_cpu_types[i]; i++) { if (object_class_dynamic_cast(oc, mc->valid_cpu_types[i])) { break; @@ -1596,6 +1598,32 @@ static bool is_cpu_type_supported(const MachineState *machine, Error **errp) error_append_hint(errp, "\n"); } + return false; + } + } else if (mc->get_valid_cpu_types) { + GPtrArray *vct = mc->get_valid_cpu_types(machine); + bool valid = false; + + for (i = 0; i < vct->len; i++) { + if (object_class_dynamic_cast(oc, vct->pdata[i])) { + valid = true; + break; + } + } + + if (!valid) { + g_autofree char *requested = cpu_model_from_type(machine->cpu_type); + + error_setg(errp, "Invalid CPU model: %s", requested); + error_append_hint(errp, "The valid models are: "); + for (i = 0; i < vct->len; i++) { + g_autofree char *model = cpu_model_from_type(vct->pdata[i]); + error_append_hint(errp, "%s%s", + model, i + 1 == vct->len ? "\n" : ", "); + } + } + g_ptr_array_free(vct, true); + if (!valid) { return false; } } diff --git a/include/hw/boards.h b/include/hw/boards.h index d0a69cd490..c45272b741 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -253,6 +253,9 @@ typedef struct { * @smbios_memory_device_size: * Default size of memory device, * SMBIOS 3.1.0 "7.18 Memory Device (Type 17)" + * @get_valid_cpu_types: + * Returns a list of valid CPU types for this board. May be NULL + * if not needed. */ struct MachineClass { /*< private >*/ @@ -299,6 +302,7 @@ struct MachineClass { bool ignore_memory_transaction_failures; int numa_mem_align_shift; const char * const *valid_cpu_types; + GPtrArray *(*get_valid_cpu_types)(const MachineState *ms); strList *allowed_dynamic_sysbus_devices; bool auto_enable_numa_with_memhp; bool auto_enable_numa_with_memdev; From 6d06b1e3f6b2f906767e2faa1b781dcef2308bd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 22 Apr 2025 12:11:56 +0200 Subject: [PATCH 09/45] hw/core: Introduce MachineClass::get_default_cpu_type() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MachineClass::get_default_cpu_type() runs once the machine is created, being able to evaluate runtime checks; it returns the machine default CPU type. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Pierrick Bouvier Message-Id: <20251020221508.67413-7-philmd@linaro.org> --- hw/core/machine.c | 10 ++++++++++ include/hw/boards.h | 6 ++++++ system/vl.c | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index cd2f1414a7..cd63803000 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -1556,6 +1556,16 @@ const char *machine_class_default_cpu_type(MachineClass *mc) return mc->default_cpu_type; } +const char *machine_default_cpu_type(const MachineState *ms) +{ + MachineClass *mc = MACHINE_GET_CLASS(ms); + + if (mc->get_default_cpu_type) { + return mc->get_default_cpu_type(ms); + } + return machine_class_default_cpu_type(mc); +} + static bool is_cpu_type_supported(const MachineState *machine, Error **errp) { MachineClass *mc = MACHINE_GET_CLASS(machine); diff --git a/include/hw/boards.h b/include/hw/boards.h index c45272b741..014007920d 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -25,6 +25,11 @@ OBJECT_DECLARE_TYPE(MachineState, MachineClass, MACHINE) extern MachineState *current_machine; +/** + * machine_default_cpu_type: Return the machine default CPU type. + * @ms: Machine state + */ +const char *machine_default_cpu_type(const MachineState *ms); /** * machine_class_default_cpu_type: Return the machine default CPU type. * @mc: Machine class @@ -303,6 +308,7 @@ struct MachineClass { int numa_mem_align_shift; const char * const *valid_cpu_types; GPtrArray *(*get_valid_cpu_types)(const MachineState *ms); + const char *(*get_default_cpu_type)(const MachineState *ms); strList *allowed_dynamic_sysbus_devices; bool auto_enable_numa_with_memhp; bool auto_enable_numa_with_memdev; diff --git a/system/vl.c b/system/vl.c index a96063f990..fd98ea52d9 100644 --- a/system/vl.c +++ b/system/vl.c @@ -3817,7 +3817,7 @@ void qemu_init(int argc, char **argv) migration_object_init(); /* parse features once if machine provides default cpu_type */ - current_machine->cpu_type = machine_class_default_cpu_type(machine_class); + current_machine->cpu_type = machine_default_cpu_type(current_machine); if (cpu_option) { current_machine->cpu_type = parse_cpu_option(cpu_option); } From 0f212b0d12cc35d4600d08d4a337f4b6c243f07b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 20 Oct 2025 16:50:03 +0200 Subject: [PATCH 10/45] hw/boards: Move DEFINE_MACHINE() definition closer to its doc string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Code movement to have the DEFINE_MACHINE() definition follow its usage documentation comment. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Pierrick Bouvier Message-Id: <20251020220941.65269-3-philmd@linaro.org> --- include/hw/boards.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/include/hw/boards.h b/include/hw/boards.h index 014007920d..a214e3322a 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -506,6 +506,23 @@ struct MachineState { * DEFINE_VIRT_MACHINE_IMPL(false, major, minor, micro, _, tag) */ +#define DEFINE_MACHINE(namestr, machine_initfn) \ + static void machine_initfn##_class_init(ObjectClass *oc, const void *data) \ + { \ + MachineClass *mc = MACHINE_CLASS(oc); \ + machine_initfn(mc); \ + } \ + static const TypeInfo machine_initfn##_typeinfo = { \ + .name = MACHINE_TYPE_NAME(namestr), \ + .parent = TYPE_MACHINE, \ + .class_init = machine_initfn##_class_init, \ + }; \ + static void machine_initfn##_register_types(void) \ + { \ + type_register_static(&machine_initfn##_typeinfo); \ + } \ + type_init(machine_initfn##_register_types) + /* * Helper for dispatching different macros based on how * many __VA_ARGS__ are passed. Supports 1 to 5 variadic @@ -765,23 +782,6 @@ struct MachineState { } \ } while (0) -#define DEFINE_MACHINE(namestr, machine_initfn) \ - static void machine_initfn##_class_init(ObjectClass *oc, const void *data) \ - { \ - MachineClass *mc = MACHINE_CLASS(oc); \ - machine_initfn(mc); \ - } \ - static const TypeInfo machine_initfn##_typeinfo = { \ - .name = MACHINE_TYPE_NAME(namestr), \ - .parent = TYPE_MACHINE, \ - .class_init = machine_initfn##_class_init, \ - }; \ - static void machine_initfn##_register_types(void) \ - { \ - type_register_static(&machine_initfn##_typeinfo); \ - } \ - type_init(machine_initfn##_register_types) - extern GlobalProperty hw_compat_10_1[]; extern const size_t hw_compat_10_1_len; From ce837a4fd65dedf04abb3fac7f69c26c69dfbe9a Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Fri, 2 May 2025 01:20:33 +0200 Subject: [PATCH 11/45] hw/boards: Extend DEFINE_MACHINE macro to cover more use cases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a more general DEFINE_MACHINE_EXTENDED macro and define simpler versions with less parameters based on that. This is inspired by how the OBJECT_DEFINE macros do this in a similar way to allow using the shortened definition in more complex cases too. Signed-off-by: BALATON Zoltan Message-ID: Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Pierrick Bouvier --- include/hw/boards.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/include/hw/boards.h b/include/hw/boards.h index a214e3322a..b2964cf055 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -506,7 +506,8 @@ struct MachineState { * DEFINE_VIRT_MACHINE_IMPL(false, major, minor, micro, _, tag) */ -#define DEFINE_MACHINE(namestr, machine_initfn) \ +#define DEFINE_MACHINE_EXTENDED(namestr, PARENT_NAME, InstanceName, \ + machine_initfn, ABSTRACT, ...) \ static void machine_initfn##_class_init(ObjectClass *oc, const void *data) \ { \ MachineClass *mc = MACHINE_CLASS(oc); \ @@ -514,8 +515,11 @@ struct MachineState { } \ static const TypeInfo machine_initfn##_typeinfo = { \ .name = MACHINE_TYPE_NAME(namestr), \ - .parent = TYPE_MACHINE, \ + .parent = TYPE_##PARENT_NAME, \ .class_init = machine_initfn##_class_init, \ + .instance_size = sizeof(InstanceName), \ + .abstract = ABSTRACT, \ + .interfaces = (const InterfaceInfo[]) { __VA_ARGS__ }, \ }; \ static void machine_initfn##_register_types(void) \ { \ @@ -523,6 +527,14 @@ struct MachineState { } \ type_init(machine_initfn##_register_types) +#define DEFINE_MACHINE(namestr, machine_initfn) \ + DEFINE_MACHINE_EXTENDED(namestr, MACHINE, MachineState, machine_initfn, \ + false, { }) + +#define DEFINE_MACHINE_WITH_INTERFACES(namestr, machine_initfn, ...) \ + DEFINE_MACHINE_EXTENDED(namestr, MACHINE, MachineState, machine_initfn, \ + false, __VA_ARGS__) + /* * Helper for dispatching different macros based on how * many __VA_ARGS__ are passed. Supports 1 to 5 variadic From a4d934ea079563a38cc6ea4a556da3fb14a2b753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 24 Apr 2025 15:10:49 +0200 Subject: [PATCH 12/45] hw/boards: Introduce DEFINE_MACHINE_WITH_INTERFACE_ARRAY() macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DEFINE_MACHINE_WITH_INTERFACE_ARRAY() is similar to DEFINE_MACHINE_WITH_INTERFACES() but allows to pass an InterfaceInfo[] pointer. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Pierrick Bouvier Message-Id: <20251020220941.65269-5-philmd@linaro.org> --- include/hw/boards.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/include/hw/boards.h b/include/hw/boards.h index b2964cf055..a48ed4f86a 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -507,7 +507,7 @@ struct MachineState { */ #define DEFINE_MACHINE_EXTENDED(namestr, PARENT_NAME, InstanceName, \ - machine_initfn, ABSTRACT, ...) \ + machine_initfn, ABSTRACT, ifaces...) \ static void machine_initfn##_class_init(ObjectClass *oc, const void *data) \ { \ MachineClass *mc = MACHINE_CLASS(oc); \ @@ -519,7 +519,7 @@ struct MachineState { .class_init = machine_initfn##_class_init, \ .instance_size = sizeof(InstanceName), \ .abstract = ABSTRACT, \ - .interfaces = (const InterfaceInfo[]) { __VA_ARGS__ }, \ + .interfaces = ifaces, \ }; \ static void machine_initfn##_register_types(void) \ { \ @@ -529,11 +529,15 @@ struct MachineState { #define DEFINE_MACHINE(namestr, machine_initfn) \ DEFINE_MACHINE_EXTENDED(namestr, MACHINE, MachineState, machine_initfn, \ - false, { }) + false, NULL) + +#define DEFINE_MACHINE_WITH_INTERFACE_ARRAY(namestr, machine_initfn, ifaces...)\ + DEFINE_MACHINE_EXTENDED(namestr, MACHINE, MachineState, machine_initfn, \ + false, ifaces) #define DEFINE_MACHINE_WITH_INTERFACES(namestr, machine_initfn, ...) \ - DEFINE_MACHINE_EXTENDED(namestr, MACHINE, MachineState, machine_initfn, \ - false, __VA_ARGS__) + DEFINE_MACHINE_WITH_INTERFACE_ARRAY(namestr, machine_initfn, \ + (const InterfaceInfo[]) { __VA_ARGS__ }) /* * Helper for dispatching different macros based on how From 40eed74cc9deaa4343b31e49a6fbf7f037e8d841 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 8 Oct 2025 14:25:02 +0200 Subject: [PATCH 13/45] hw/i2c/smbus_eeprom: Add minimum write recovery time for DDR2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is needed for newer u-boot-sam460ex versions to pass the DRAM setup. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20251008122502.9DA8956F301@zero.eik.bme.hu> Signed-off-by: Philippe Mathieu-Daudé --- hw/i2c/smbus_eeprom.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/i2c/smbus_eeprom.c b/hw/i2c/smbus_eeprom.c index 0a1088fbb0..26e211b31a 100644 --- a/hw/i2c/smbus_eeprom.c +++ b/hw/i2c/smbus_eeprom.c @@ -288,6 +288,7 @@ uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t ram_size) spd[33] = 8; /* addr/cmd hold time */ spd[34] = 20; /* data input setup time */ spd[35] = 8; /* data input hold time */ + spd[36] = (type == DDR2 ? 13 << 2 : 0); /* min. write recovery time */ /* checksum */ for (i = 0; i < 63; i++) { From 270b28681e369082dc17f58eae2871b75d3e8e6c Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 15 Oct 2025 13:12:43 +0200 Subject: [PATCH 14/45] hw/ppc/e500: Check for compatible CPU type instead of aborting ungracefully MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using the ppce500 machine with an embedded CPU type that has the right MMU model, but is not part of the e500 CPU family, QEMU currently aborts ungracefully: $ ./qemu-system-ppc -machine ppce500 -cpu e200z5 -nographic qemu-system-ppc: ../qemu/hw/core/gpio.c:108: qdev_get_gpio_in_named: Assertion `n >= 0 && n < gpio_list->num_in' failed. Aborted (core dumped) The ppce500 machine expects a CPU with certain GPIO interrupt pins, so let's replace the coarse check for the MMU_BOOKE206 model with a more precise check that only allows CPUs from the e500 family. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3162 Signed-off-by: Thomas Huth Acked-by: Bernhard Beschow Reviewed-by: Harsh Prateek Bora Reviewed-by: BALATON Zoltan Message-ID: <20251015111243.1585018-1-thuth@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/ppc/e500.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 723c97fad2..3d69428f31 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -20,6 +20,7 @@ #include "qemu/guest-random.h" #include "exec/target_page.h" #include "qapi/error.h" +#include "cpu-models.h" #include "e500.h" #include "e500-ccsr.h" #include "net/net.h" @@ -942,9 +943,8 @@ void ppce500_init(MachineState *machine) env = &cpu->env; cs = CPU(cpu); - if (env->mmu_model != POWERPC_MMU_BOOKE206) { - error_report("MMU model %i not supported by this machine", - env->mmu_model); + if (!(POWERPC_CPU_GET_CLASS(cpu)->svr & POWERPC_SVR_E500)) { + error_report("This machine needs a CPU from the e500 family"); exit(1); } From 6095c7dd3b6750eaac7eee7a6327ae68af19097e Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Thu, 16 Oct 2025 14:48:10 +0200 Subject: [PATCH 15/45] hw/openrisc/openrisc_sim: Avoid buffer overflow build error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves this build breakage (which is actually a false-positive) ../hw/openrisc/openrisc_sim.c: In function ‘openrisc_sim_init’: ../hw/openrisc/openrisc_sim.c:284:45: error: ‘__builtin___snprintf_chk’ output may be truncated before the last format character [-Werror=format-truncation=] snprintf(alias, sizeof(alias), "serial%d", uart_idx); ^ In file included from /usr/include/stdio.h:964:0, from /data/qemu/include/qemu/osdep.h:114, from ../hw/openrisc/openrisc_sim.c:21: /usr/include/bits/stdio2.h:54:10: note: ‘__builtin___snprintf_chk’ output between 8 and 9 bytes into a destination of size 8 return __builtin___snprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ __glibc_objsize (__s), __fmt, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ __va_arg_pack ()); ~~~~~~~~~~~~~~~~~ by using a modern, more robust allocation pattern. Suggested-by: Peter Maydell Signed-off-by: Jan Kiszka Reviewed-by: Peter Maydell Message-ID: <298bd904-1ee9-439e-8220-7a24e0952861@siemens.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/openrisc/openrisc_sim.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c index 880c8ebbb8..b7d9cdd900 100644 --- a/hw/openrisc/openrisc_sim.c +++ b/hw/openrisc/openrisc_sim.c @@ -247,10 +247,10 @@ static void openrisc_sim_serial_init(Or1ksimState *state, hwaddr base, OpenRISCCPU *cpus[], int irq_pin, int uart_idx) { + g_autofree char *alias = g_strdup_printf("serial%d", uart_idx); void *fdt = state->fdt; char *nodename; qemu_irq serial_irq; - char alias[sizeof("serial0")]; int i; if (num_cpus > 1) { @@ -281,7 +281,6 @@ static void openrisc_sim_serial_init(Or1ksimState *state, hwaddr base, /* The /chosen node is created during fdt creation. */ qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", nodename); } - snprintf(alias, sizeof(alias), "serial%d", uart_idx); qemu_fdt_setprop_string(fdt, "/aliases", alias, nodename); g_free(nodename); From f74ce602264d05f3b17de6d431f887fa0f0d5932 Mon Sep 17 00:00:00 2001 From: Roger Pau Monne Date: Fri, 17 Oct 2025 17:51:36 +0200 Subject: [PATCH 16/45] hw/xen: pass PCI domain to xc_physdev_map_pirq_msi() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's currently impossible for passthrough devices on segment different than 0 to work correctly, as the PCI domain is not provided to xc_physdev_map_pirq_msi(), and hence it's unconditionally assumed that all devices are on segment 0. Adjust the call to xc_physdev_map_pirq_msi() to pass the PCI domain in the high 16bits of the bus parameter. On versions of Xen where this is not supported the passed segment will be ignored and assume to be 0, no worse than the current state. Signed-off-by: Roger Pau Monné Reviewed-by: Frediano Ziglio Reviewed-by: Anthony PERARD Reviewed-by: Edgar E. Iglesias Message-ID: <20251017155136.16540-1-roger.pau@citrix.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/xen/xen_pt_msi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/xen/xen_pt_msi.c b/hw/xen/xen_pt_msi.c index e9ba17317a..df15ccf0d0 100644 --- a/hw/xen/xen_pt_msi.c +++ b/hw/xen/xen_pt_msi.c @@ -138,6 +138,7 @@ static int msi_msix_setup(XenPCIPassthroughState *s, rc = xc_physdev_map_pirq_msi(xen_xc, xen_domid, XEN_PT_AUTO_ASSIGN, ppirq, PCI_DEVFN(s->real_device.dev, s->real_device.func), + ((uint32_t)s->real_device.domain << 16) | s->real_device.bus, msix_entry, table_base); if (rc) { From f66752961a5750298229b86adccd821e7785bfdf Mon Sep 17 00:00:00 2001 From: Luc Michel Date: Fri, 17 Oct 2025 18:18:00 +0200 Subject: [PATCH 17/45] hw/core/register: remove the REGISTER device type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The REGISTER class (RegisterInfo struct) is currently a QOM type inheriting from DEVICE. This class has no real purpose: - the qdev API is not used, - according to the comment preceding it, the object_initialize call is here to zero-initialize the struct. However all the effective struct attributes are then initialized explicitly. - the object is never parented. This commits drops the REGISTER QOM type completely, leaving the RegisterInfo struct as a bare C struct. The register_register_types function is left empty here because it is reused in the next commit. Reviewed-by: Alistair Francis Reviewed-by: Francisco Iglesias Reviewed-by: Edgar E. Iglesias Signed-off-by: Luc Michel Message-ID: <20251017161809.235740-2-luc.michel@amd.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/core/register.c | 18 ------------------ hw/net/can/xlnx-versal-canfd.c | 2 -- include/hw/register.h | 7 ------- 3 files changed, 27 deletions(-) diff --git a/hw/core/register.c b/hw/core/register.c index 3340df70b0..2553cb15ab 100644 --- a/hw/core/register.c +++ b/hw/core/register.c @@ -258,9 +258,6 @@ static RegisterInfoArray *register_init_block(DeviceState *owner, int index = rae[i].addr / data_size; RegisterInfo *r = &ri[index]; - /* Init the register, this will zero it. */ - object_initialize((void *)r, sizeof(*r), TYPE_REGISTER); - /* Set the properties of the register */ r->data = data + data_size * index; r->data_size = data_size; @@ -318,24 +315,9 @@ void register_finalize_block(RegisterInfoArray *r_array) g_free(r_array); } -static void register_class_init(ObjectClass *oc, const void *data) -{ - DeviceClass *dc = DEVICE_CLASS(oc); - - /* Reason: needs to be wired up to work */ - dc->user_creatable = false; -} - -static const TypeInfo register_info = { - .name = TYPE_REGISTER, - .parent = TYPE_DEVICE, - .class_init = register_class_init, - .instance_size = sizeof(RegisterInfo), -}; static void register_register_types(void) { - type_register_static(®ister_info); } type_init(register_register_types) diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c index 343348660b..99bbdd7d3f 100644 --- a/hw/net/can/xlnx-versal-canfd.c +++ b/hw/net/can/xlnx-versal-canfd.c @@ -1868,8 +1868,6 @@ static int canfd_populate_regarray(XlnxVersalCANFDState *s, int index = rae[i].addr / 4; RegisterInfo *r = &s->reg_info[index]; - object_initialize(r, sizeof(*r), TYPE_REGISTER); - *r = (RegisterInfo) { .data = &s->regs[index], .data_size = sizeof(uint32_t), diff --git a/include/hw/register.h b/include/hw/register.h index a913c52aee..4d13ea183c 100644 --- a/include/hw/register.h +++ b/include/hw/register.h @@ -75,10 +75,6 @@ struct RegisterAccessInfo { */ struct RegisterInfo { - /* */ - DeviceState parent_obj; - - /* */ void *data; int data_size; @@ -87,9 +83,6 @@ struct RegisterInfo { void *opaque; }; -#define TYPE_REGISTER "qemu-register" -DECLARE_INSTANCE_CHECKER(RegisterInfo, REGISTER, - TYPE_REGISTER) /** * This structure is used to group all of the individual registers which are From 5c6367bc1c8850f74812eeaaf87cff9911be58de Mon Sep 17 00:00:00 2001 From: Luc Michel Date: Fri, 17 Oct 2025 18:18:01 +0200 Subject: [PATCH 18/45] hw/core/register: add the REGISTER_ARRAY type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce the REGISTER_ARRAY QOM type. This type reuses the existing RegisterInfoArray struct. When `register_init_block' is called, it creates a REGISTER_ARRAY object and parents it to the calling device. This way it gets finalized when the device is. The memory region is parented to the REGISTER_ARRAY object to ensure correct finalizing order. The finalize function of the REGISTER_ARRAY type performs the necessary cleaning that used to be done by `register_finalize_block'. The latter is left empty and will be removed when all the register API users have been refactored. Reviewed-by: Alistair Francis Reviewed-by: Francisco Iglesias Reviewed-by: Edgar E. Iglesias Signed-off-by: Luc Michel Message-ID: <20251017161809.235740-3-luc.michel@amd.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/core/register.c | 26 ++++++++++++++++++++++---- include/hw/register.h | 4 ++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/hw/core/register.c b/hw/core/register.c index 2553cb15ab..1612ad174f 100644 --- a/hw/core/register.c +++ b/hw/core/register.c @@ -245,10 +245,16 @@ static RegisterInfoArray *register_init_block(DeviceState *owner, size_t data_size_bits) { const char *device_prefix = object_get_typename(OBJECT(owner)); - RegisterInfoArray *r_array = g_new0(RegisterInfoArray, 1); + Object *obj; + RegisterInfoArray *r_array; int data_size = data_size_bits >> 3; int i; + obj = object_new(TYPE_REGISTER_ARRAY); + object_property_add_child(OBJECT(owner), "reg-array[*]", obj); + object_unref(obj); + + r_array = REGISTER_ARRAY(obj); r_array->r = g_new0(RegisterInfo *, num); r_array->num_elements = num; r_array->debug = debug_enabled; @@ -267,7 +273,7 @@ static RegisterInfoArray *register_init_block(DeviceState *owner, r_array->r[i] = r; } - memory_region_init_io(&r_array->mem, OBJECT(owner), ops, r_array, + memory_region_init_io(&r_array->mem, OBJECT(r_array), ops, r_array, device_prefix, memory_size); return r_array; @@ -309,15 +315,27 @@ RegisterInfoArray *register_init_block64(DeviceState *owner, data, ops, debug_enabled, memory_size, 64); } -void register_finalize_block(RegisterInfoArray *r_array) +static void register_array_finalize(Object *obj) { + RegisterInfoArray *r_array = REGISTER_ARRAY(obj); + g_free(r_array->r); - g_free(r_array); } +void register_finalize_block(RegisterInfoArray *r_array) +{ +} + +static const TypeInfo register_array_info = { + .name = TYPE_REGISTER_ARRAY, + .parent = TYPE_OBJECT, + .instance_size = sizeof(RegisterInfoArray), + .instance_finalize = register_array_finalize, +}; static void register_register_types(void) { + type_register_static(®ister_array_info); } type_init(register_register_types) diff --git a/include/hw/register.h b/include/hw/register.h index 4d13ea183c..65c82600e0 100644 --- a/include/hw/register.h +++ b/include/hw/register.h @@ -83,6 +83,8 @@ struct RegisterInfo { void *opaque; }; +#define TYPE_REGISTER_ARRAY "qemu-register-array" +OBJECT_DECLARE_SIMPLE_TYPE(RegisterInfoArray, REGISTER_ARRAY) /** * This structure is used to group all of the individual registers which are @@ -96,6 +98,8 @@ struct RegisterInfo { */ struct RegisterInfoArray { + Object parent_obj; + MemoryRegion mem; int num_elements; From f423f7ebac82136515f3e3957a26f2482ff04ed9 Mon Sep 17 00:00:00 2001 From: Luc Michel Date: Fri, 17 Oct 2025 18:18:02 +0200 Subject: [PATCH 19/45] hw/core/register: remove the calls to `register_finalize_block' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function is now a no-op. The register array is parented to the device and get finalized when the device is. Drop all the calls to `register_finalize_block'. Drop the RegisterInfoArray reference when it is not used elsewhere in the device. Reviewed-by: Alistair Francis Reviewed-by: Francisco Iglesias Reviewed-by: Edgar E. Iglesias Signed-off-by: Luc Michel Message-ID: <20251017161809.235740-4-luc.michel@amd.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/misc/xlnx-versal-crl.c | 38 +++++++++++--------------- hw/misc/xlnx-versal-trng.c | 1 - hw/misc/xlnx-versal-xramc.c | 12 ++------ hw/misc/xlnx-zynqmp-apu-ctrl.c | 12 ++------ hw/misc/xlnx-zynqmp-crf.c | 12 ++------ hw/nvram/xlnx-bbram.c | 13 ++------- hw/nvram/xlnx-versal-efuse-ctrl.c | 1 - hw/nvram/xlnx-zynqmp-efuse.c | 8 ------ include/hw/misc/xlnx-versal-crl.h | 1 - include/hw/misc/xlnx-versal-xramc.h | 1 - include/hw/misc/xlnx-zynqmp-apu-ctrl.h | 1 - include/hw/misc/xlnx-zynqmp-crf.h | 1 - include/hw/nvram/xlnx-bbram.h | 1 - 13 files changed, 28 insertions(+), 74 deletions(-) diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c index 10e6af002b..5987f32c71 100644 --- a/hw/misc/xlnx-versal-crl.c +++ b/hw/misc/xlnx-versal-crl.c @@ -634,17 +634,17 @@ static void versal_crl_init(Object *obj) XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj); XlnxVersalCRLBase *xvcb = XLNX_VERSAL_CRL_BASE(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + RegisterInfoArray *reg_array; int i; - xvcb->reg_array = - register_init_block32(DEVICE(obj), crl_regs_info, - ARRAY_SIZE(crl_regs_info), - s->regs_info, s->regs, - &crl_ops, - XLNX_VERSAL_CRL_ERR_DEBUG, - CRL_R_MAX * 4); + reg_array = register_init_block32(DEVICE(obj), crl_regs_info, + ARRAY_SIZE(crl_regs_info), + s->regs_info, s->regs, + &crl_ops, + XLNX_VERSAL_CRL_ERR_DEBUG, + CRL_R_MAX * 4); xvcb->regs = s->regs; - sysbus_init_mmio(sbd, &xvcb->reg_array->mem); + sysbus_init_mmio(sbd, ®_array->mem); sysbus_init_irq(sbd, &s->irq); for (i = 0; i < ARRAY_SIZE(s->cfg.rpu); ++i) { @@ -688,17 +688,18 @@ static void versal2_crl_init(Object *obj) XlnxVersal2CRL *s = XLNX_VERSAL2_CRL(obj); XlnxVersalCRLBase *xvcb = XLNX_VERSAL_CRL_BASE(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + RegisterInfoArray *reg_array; size_t i; - xvcb->reg_array = register_init_block32(DEVICE(obj), versal2_crl_regs_info, - ARRAY_SIZE(versal2_crl_regs_info), - s->regs_info, s->regs, - &crl_ops, - XLNX_VERSAL_CRL_ERR_DEBUG, - VERSAL2_CRL_R_MAX * 4); + reg_array = register_init_block32(DEVICE(obj), versal2_crl_regs_info, + ARRAY_SIZE(versal2_crl_regs_info), + s->regs_info, s->regs, + &crl_ops, + XLNX_VERSAL_CRL_ERR_DEBUG, + VERSAL2_CRL_R_MAX * 4); xvcb->regs = s->regs; - sysbus_init_mmio(sbd, &xvcb->reg_array->mem); + sysbus_init_mmio(sbd, ®_array->mem); for (i = 0; i < ARRAY_SIZE(s->cfg.rpu); ++i) { object_property_add_link(obj, "rpu[*]", TYPE_ARM_CPU, @@ -750,12 +751,6 @@ static void versal2_crl_init(Object *obj) } } -static void crl_finalize(Object *obj) -{ - XlnxVersalCRLBase *s = XLNX_VERSAL_CRL_BASE(obj); - register_finalize_block(s->reg_array); -} - static const VMStateDescription vmstate_versal_crl = { .name = TYPE_XLNX_VERSAL_CRL, .version_id = 1, @@ -804,7 +799,6 @@ static const TypeInfo crl_base_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(XlnxVersalCRLBase), .class_size = sizeof(XlnxVersalCRLBaseClass), - .instance_finalize = crl_finalize, .abstract = true, }; diff --git a/hw/misc/xlnx-versal-trng.c b/hw/misc/xlnx-versal-trng.c index f34dd3ef35..2b573a45bd 100644 --- a/hw/misc/xlnx-versal-trng.c +++ b/hw/misc/xlnx-versal-trng.c @@ -627,7 +627,6 @@ static void trng_finalize(Object *obj) { XlnxVersalTRng *s = XLNX_VERSAL_TRNG(obj); - register_finalize_block(s->reg_array); g_rand_free(s->prng); s->prng = NULL; } diff --git a/hw/misc/xlnx-versal-xramc.c b/hw/misc/xlnx-versal-xramc.c index 07370b80c0..d90f3e87c7 100644 --- a/hw/misc/xlnx-versal-xramc.c +++ b/hw/misc/xlnx-versal-xramc.c @@ -190,24 +190,19 @@ static void xram_ctrl_init(Object *obj) { XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + RegisterInfoArray *reg_array; - s->reg_array = + reg_array = register_init_block32(DEVICE(obj), xram_ctrl_regs_info, ARRAY_SIZE(xram_ctrl_regs_info), s->regs_info, s->regs, &xram_ctrl_ops, XLNX_XRAM_CTRL_ERR_DEBUG, XRAM_CTRL_R_MAX * 4); - sysbus_init_mmio(sbd, &s->reg_array->mem); + sysbus_init_mmio(sbd, ®_array->mem); sysbus_init_irq(sbd, &s->irq); } -static void xram_ctrl_finalize(Object *obj) -{ - XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj); - register_finalize_block(s->reg_array); -} - static const VMStateDescription vmstate_xram_ctrl = { .name = TYPE_XLNX_XRAM_CTRL, .version_id = 1, @@ -241,7 +236,6 @@ static const TypeInfo xram_ctrl_info = { .instance_size = sizeof(XlnxXramCtrl), .class_init = xram_ctrl_class_init, .instance_init = xram_ctrl_init, - .instance_finalize = xram_ctrl_finalize, }; static void xram_ctrl_register_types(void) diff --git a/hw/misc/xlnx-zynqmp-apu-ctrl.c b/hw/misc/xlnx-zynqmp-apu-ctrl.c index e85da32d99..08777496d5 100644 --- a/hw/misc/xlnx-zynqmp-apu-ctrl.c +++ b/hw/misc/xlnx-zynqmp-apu-ctrl.c @@ -179,16 +179,17 @@ static void zynqmp_apu_handle_wfi(void *opaque, int irq, int level) static void zynqmp_apu_init(Object *obj) { XlnxZynqMPAPUCtrl *s = XLNX_ZYNQMP_APU_CTRL(obj); + RegisterInfoArray *reg_array; int i; - s->reg_array = + reg_array = register_init_block32(DEVICE(obj), zynqmp_apu_regs_info, ARRAY_SIZE(zynqmp_apu_regs_info), s->regs_info, s->regs, &zynqmp_apu_ops, XILINX_ZYNQMP_APU_ERR_DEBUG, APU_R_MAX * 4); - sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->reg_array->mem); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), ®_array->mem); sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq_imr); for (i = 0; i < APU_MAX_CPU; ++i) { @@ -208,12 +209,6 @@ static void zynqmp_apu_init(Object *obj) qdev_init_gpio_in_named(DEVICE(obj), zynqmp_apu_handle_wfi, "wfi_in", 4); } -static void zynqmp_apu_finalize(Object *obj) -{ - XlnxZynqMPAPUCtrl *s = XLNX_ZYNQMP_APU_CTRL(obj); - register_finalize_block(s->reg_array); -} - static const VMStateDescription vmstate_zynqmp_apu = { .name = TYPE_XLNX_ZYNQMP_APU_CTRL, .version_id = 1, @@ -241,7 +236,6 @@ static const TypeInfo zynqmp_apu_info = { .instance_size = sizeof(XlnxZynqMPAPUCtrl), .class_init = zynqmp_apu_class_init, .instance_init = zynqmp_apu_init, - .instance_finalize = zynqmp_apu_finalize, }; static void zynqmp_apu_register_types(void) diff --git a/hw/misc/xlnx-zynqmp-crf.c b/hw/misc/xlnx-zynqmp-crf.c index cccca0e814..d9c1bd50e4 100644 --- a/hw/misc/xlnx-zynqmp-crf.c +++ b/hw/misc/xlnx-zynqmp-crf.c @@ -211,24 +211,19 @@ static void crf_init(Object *obj) { XlnxZynqMPCRF *s = XLNX_ZYNQMP_CRF(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + RegisterInfoArray *reg_array; - s->reg_array = + reg_array = register_init_block32(DEVICE(obj), crf_regs_info, ARRAY_SIZE(crf_regs_info), s->regs_info, s->regs, &crf_ops, XLNX_ZYNQMP_CRF_ERR_DEBUG, CRF_R_MAX * 4); - sysbus_init_mmio(sbd, &s->reg_array->mem); + sysbus_init_mmio(sbd, ®_array->mem); sysbus_init_irq(sbd, &s->irq_ir); } -static void crf_finalize(Object *obj) -{ - XlnxZynqMPCRF *s = XLNX_ZYNQMP_CRF(obj); - register_finalize_block(s->reg_array); -} - static const VMStateDescription vmstate_crf = { .name = TYPE_XLNX_ZYNQMP_CRF, .version_id = 1, @@ -255,7 +250,6 @@ static const TypeInfo crf_info = { .instance_size = sizeof(XlnxZynqMPCRF), .class_init = crf_class_init, .instance_init = crf_init, - .instance_finalize = crf_finalize, }; static void crf_register_types(void) diff --git a/hw/nvram/xlnx-bbram.c b/hw/nvram/xlnx-bbram.c index 5702bb3f31..22aefbc240 100644 --- a/hw/nvram/xlnx-bbram.c +++ b/hw/nvram/xlnx-bbram.c @@ -456,8 +456,9 @@ static void bbram_ctrl_init(Object *obj) { XlnxBBRam *s = XLNX_BBRAM(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + RegisterInfoArray *reg_array; - s->reg_array = + reg_array = register_init_block32(DEVICE(obj), bbram_ctrl_regs_info, ARRAY_SIZE(bbram_ctrl_regs_info), s->regs_info, s->regs, @@ -465,17 +466,10 @@ static void bbram_ctrl_init(Object *obj) XLNX_BBRAM_ERR_DEBUG, R_MAX * 4); - sysbus_init_mmio(sbd, &s->reg_array->mem); + sysbus_init_mmio(sbd, ®_array->mem); sysbus_init_irq(sbd, &s->irq_bbram); } -static void bbram_ctrl_finalize(Object *obj) -{ - XlnxBBRam *s = XLNX_BBRAM(obj); - - register_finalize_block(s->reg_array); -} - static void bbram_prop_set_drive(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { @@ -542,7 +536,6 @@ static const TypeInfo bbram_ctrl_info = { .instance_size = sizeof(XlnxBBRam), .class_init = bbram_ctrl_class_init, .instance_init = bbram_ctrl_init, - .instance_finalize = bbram_ctrl_finalize, }; static void bbram_ctrl_register_types(void) diff --git a/hw/nvram/xlnx-versal-efuse-ctrl.c b/hw/nvram/xlnx-versal-efuse-ctrl.c index 9096219800..6f17f32a0c 100644 --- a/hw/nvram/xlnx-versal-efuse-ctrl.c +++ b/hw/nvram/xlnx-versal-efuse-ctrl.c @@ -728,7 +728,6 @@ static void efuse_ctrl_finalize(Object *obj) { XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(obj); - register_finalize_block(s->reg_array); g_free(s->extra_pg0_lock_spec); } diff --git a/hw/nvram/xlnx-zynqmp-efuse.c b/hw/nvram/xlnx-zynqmp-efuse.c index 5a218c32e8..ce35bb0cc1 100644 --- a/hw/nvram/xlnx-zynqmp-efuse.c +++ b/hw/nvram/xlnx-zynqmp-efuse.c @@ -816,13 +816,6 @@ static void zynqmp_efuse_init(Object *obj) sysbus_init_irq(sbd, &s->irq); } -static void zynqmp_efuse_finalize(Object *obj) -{ - XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(obj); - - register_finalize_block(s->reg_array); -} - static const VMStateDescription vmstate_efuse = { .name = TYPE_XLNX_ZYNQMP_EFUSE, .version_id = 1, @@ -857,7 +850,6 @@ static const TypeInfo efuse_info = { .instance_size = sizeof(XlnxZynqMPEFuse), .class_init = zynqmp_efuse_class_init, .instance_init = zynqmp_efuse_init, - .instance_finalize = zynqmp_efuse_finalize, }; static void efuse_register_types(void) diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h index f6b8694ebe..49ed500acd 100644 --- a/include/hw/misc/xlnx-versal-crl.h +++ b/include/hw/misc/xlnx-versal-crl.h @@ -533,7 +533,6 @@ REG32(VERSAL2_RST_OCM, 0x3d8) struct XlnxVersalCRLBase { SysBusDevice parent_obj; - RegisterInfoArray *reg_array; uint32_t *regs; }; diff --git a/include/hw/misc/xlnx-versal-xramc.h b/include/hw/misc/xlnx-versal-xramc.h index d3d1862676..35e4e8b91d 100644 --- a/include/hw/misc/xlnx-versal-xramc.h +++ b/include/hw/misc/xlnx-versal-xramc.h @@ -90,7 +90,6 @@ typedef struct XlnxXramCtrl { unsigned int encoded_size; } cfg; - RegisterInfoArray *reg_array; uint32_t regs[XRAM_CTRL_R_MAX]; RegisterInfo regs_info[XRAM_CTRL_R_MAX]; } XlnxXramCtrl; diff --git a/include/hw/misc/xlnx-zynqmp-apu-ctrl.h b/include/hw/misc/xlnx-zynqmp-apu-ctrl.h index c3bf3c1583..fbfe34aa7e 100644 --- a/include/hw/misc/xlnx-zynqmp-apu-ctrl.h +++ b/include/hw/misc/xlnx-zynqmp-apu-ctrl.h @@ -85,7 +85,6 @@ struct XlnxZynqMPAPUCtrl { uint8_t cpu_pwrdwn_req; uint8_t cpu_in_wfi; - RegisterInfoArray *reg_array; uint32_t regs[APU_R_MAX]; RegisterInfo regs_info[APU_R_MAX]; }; diff --git a/include/hw/misc/xlnx-zynqmp-crf.h b/include/hw/misc/xlnx-zynqmp-crf.h index 02ef0bdeee..c746ae1039 100644 --- a/include/hw/misc/xlnx-zynqmp-crf.h +++ b/include/hw/misc/xlnx-zynqmp-crf.h @@ -203,7 +203,6 @@ struct XlnxZynqMPCRF { MemoryRegion iomem; qemu_irq irq_ir; - RegisterInfoArray *reg_array; uint32_t regs[CRF_R_MAX]; RegisterInfo regs_info[CRF_R_MAX]; }; diff --git a/include/hw/nvram/xlnx-bbram.h b/include/hw/nvram/xlnx-bbram.h index 58acbe9f51..af90900bfc 100644 --- a/include/hw/nvram/xlnx-bbram.h +++ b/include/hw/nvram/xlnx-bbram.h @@ -47,7 +47,6 @@ struct XlnxBBRam { bool bbram8_wo; bool blk_ro; - RegisterInfoArray *reg_array; uint32_t regs[RMAX_XLNX_BBRAM]; RegisterInfo regs_info[RMAX_XLNX_BBRAM]; }; From 2fcb0f1f28a03bdf61259f4856b980517d1cc9d7 Mon Sep 17 00:00:00 2001 From: Luc Michel Date: Fri, 17 Oct 2025 18:18:03 +0200 Subject: [PATCH 20/45] hw/core/register: remove the `register_finalize_block' function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function is now unused. Drop it. Reviewed-by: Alistair Francis Reviewed-by: Francisco Iglesias Reviewed-by: Edgar E. Iglesias Signed-off-by: Luc Michel Message-ID: <20251017161809.235740-5-luc.michel@amd.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/core/register.c | 4 ---- include/hw/register.h | 14 -------------- 2 files changed, 18 deletions(-) diff --git a/hw/core/register.c b/hw/core/register.c index 1612ad174f..81316d4859 100644 --- a/hw/core/register.c +++ b/hw/core/register.c @@ -322,10 +322,6 @@ static void register_array_finalize(Object *obj) g_free(r_array->r); } -void register_finalize_block(RegisterInfoArray *r_array) -{ -} - static const TypeInfo register_array_info = { .name = TYPE_REGISTER_ARRAY, .parent = TYPE_OBJECT, diff --git a/include/hw/register.h b/include/hw/register.h index 65c82600e0..7b0f4c8b7a 100644 --- a/include/hw/register.h +++ b/include/hw/register.h @@ -209,18 +209,4 @@ RegisterInfoArray *register_init_block64(DeviceState *owner, bool debug_enabled, uint64_t memory_size); -/** - * This function should be called to cleanup the registers that were initialized - * when calling register_init_block32(). This function should only be called - * from the device's instance_finalize function. - * - * Any memory operations that the device performed that require cleanup (such - * as creating subregions) need to be called before calling this function. - * - * @r_array: A structure containing all of the registers, as returned by - * register_init_block32() - */ - -void register_finalize_block(RegisterInfoArray *r_array); - #endif From b7477d714005e1ed5784f6c066a4c43d55c010e5 Mon Sep 17 00:00:00 2001 From: Luc Michel Date: Fri, 17 Oct 2025 18:18:04 +0200 Subject: [PATCH 21/45] hw/net/can/xlnx-versal-canfd: refactor the banked registers logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CANFD device has several groups of registers: - the main control registers from 0x0 to 0xec - several banks of multiple registers. The number of banks is either hardcoded, or configurable using QOM properties: - Tx registers - Filter registers - Tx events registers - Rx0 registers - Rx1 registers As of now, all the registers are handled using the register API. The banked register logic results in a convoluted code to correctly allocate the register descriptors for the register API. This code bypasses the standard register API creation function (register_init_block). The resulting code leaks memory when the device is finalized. This commit introduces decoding logic for the banked registers. Those registers are quite simple in practice. Accessing them triggers no side-effect (only the filter registers need a check to catch guest invalid behaviour). Starting from the Tx events registers, they are all read-only. The main device memory region is changed to an I/O one, calling the new decoding logic when accessed. The register API memory region still overlaps all of it so for now the introduced code has no effect. The next commit will remove the register API usage for banked registers. Reviewed-by: Francisco Iglesias Reviewed-by: Edgar E. Iglesias Signed-off-by: Luc Michel Message-ID: <20251017161809.235740-6-luc.michel@amd.com> [PMD: Have canfd_decode_reg_bank() take optional @idx, types fixups] Signed-off-by: Philippe Mathieu-Daudé --- hw/net/can/xlnx-versal-canfd.c | 150 ++++++++++++++++++++++++++++++++- 1 file changed, 146 insertions(+), 4 deletions(-) diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c index 99bbdd7d3f..04f9a6d57d 100644 --- a/hw/net/can/xlnx-versal-canfd.c +++ b/hw/net/can/xlnx-versal-canfd.c @@ -1410,6 +1410,22 @@ static uint64_t canfd_srr_pre_write(RegisterInfo *reg, uint64_t val64) return s->regs[R_SOFTWARE_RESET_REGISTER]; } +static void filter_reg_write(XlnxVersalCANFDState *s, hwaddr addr, + unsigned bank_idx, uint32_t val) +{ + size_t reg_idx = addr / sizeof(uint32_t); + + if (!(s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER] & (1 << bank_idx))) { + s->regs[reg_idx] = val; + } else { + g_autofree char *path = object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter register 0x%" + HWADDR_PRIx " changed while filter %u enabled\n", + path, addr, bank_idx + 1); + } +} + static uint64_t filter_mask(RegisterInfo *reg, uint64_t val64) { XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque); @@ -1763,9 +1779,135 @@ static void xlnx_versal_canfd_ptimer_cb(void *opaque) /* No action required on the timer rollover. */ } +static bool canfd_decode_reg_bank(XlnxVersalCANFDState *s, hwaddr addr, + hwaddr first_reg, hwaddr last_reg, + size_t num_banks, unsigned *idx, + hwaddr *offset) +{ + hwaddr base = addr - first_reg; + hwaddr span = last_reg - first_reg + sizeof(uint32_t); + unsigned index = base / span; + + if (index >= num_banks) { + return false; + } + if (idx) { + *idx = index; + } + + *offset = base % span; + *offset += first_reg; + + return true; +} + +/* + * Decode the given addr into a (idx, offset) pair: + * - idx is the bank index of the register at addr, + * - offset is the register offset relative to bank 0 + * + * @return true is the decoding succeded, false otherwise + */ +static bool canfd_decode_addr(XlnxVersalCANFDState *s, hwaddr addr, + unsigned *idx, hwaddr *offset) +{ + if (addr <= A_RX_FIFO_WATERMARK_REGISTER) { + /* from 0x0 to 0xec. Handled by the register API */ + g_assert_not_reached(); + } else if (addr < A_TB_ID_REGISTER) { + /* no register in this gap */ + return false; + } else if (addr < A_AFMR_REGISTER) { + /* TX registers */ + return canfd_decode_reg_bank(s, addr, + A_TB_ID_REGISTER, A_TB_DW15_REGISTER, + s->cfg.tx_fifo, idx, offset); + } else if (addr < A_TXE_FIFO_TB_ID_REGISTER) { + /* Filter registers */ + return canfd_decode_reg_bank(s, addr, + A_AFMR_REGISTER, A_AFIR_REGISTER, + 32, idx, offset); + } else if (addr < A_RB_ID_REGISTER) { + /* TX event registers */ + return canfd_decode_reg_bank(s, addr, + A_TXE_FIFO_TB_ID_REGISTER, + A_TXE_FIFO_TB_DLC_REGISTER, + 32, idx, offset); + } else if (addr < A_RB_ID_REGISTER_1) { + /* RX0 registers */ + return canfd_decode_reg_bank(s, addr, + A_RB_ID_REGISTER, + A_RB_DW15_REGISTER, + s->cfg.rx0_fifo, idx, offset); + } else if (addr <= A_RB_DW15_REGISTER_1) { + /* RX1 registers */ + return canfd_decode_reg_bank(s, addr, + A_RB_ID_REGISTER_1, + A_RB_DW15_REGISTER_1, + s->cfg.rx1_fifo, idx, offset); + } + + /* decode error */ + return false; +} + +static uint64_t canfd_read(void *opaque, hwaddr addr, unsigned size) +{ + XlnxVersalCANFDState *s = XILINX_CANFD(opaque); + hwaddr reg_offset; + uint64_t ret; + + if (!canfd_decode_addr(s, addr, NULL, ®_offset)) { + qemu_log_mask(LOG_GUEST_ERROR, TYPE_XILINX_CANFD + ": read to unknown register at address 0x%" + HWADDR_PRIx "\n", addr); + return 0; + } + + switch (reg_offset) { + default: + ret = s->regs[addr / sizeof(uint32_t)]; + } + + return ret; +} + +static void canfd_write(void *opaque, hwaddr addr, uint64_t value, + unsigned size) +{ + XlnxVersalCANFDState *s = XILINX_CANFD(opaque); + unsigned bank_idx; + hwaddr reg_offset; + + if (!canfd_decode_addr(s, addr, &bank_idx, ®_offset)) { + qemu_log_mask(LOG_GUEST_ERROR, TYPE_XILINX_CANFD + ": write to unknown register at address 0x%" + HWADDR_PRIx "\n", addr); + return; + } + + if (addr >= A_TXE_FIFO_TB_ID_REGISTER) { + /* All registers from TX event regs to the end are read-only */ + qemu_log_mask(LOG_GUEST_ERROR, TYPE_XILINX_CANFD + ": write to read-only register at 0x%" HWADDR_PRIx "\n", + addr); + return; + } + + switch (reg_offset) { + case A_AFMR_REGISTER: + case A_AFIR_REGISTER: + filter_reg_write(s, addr, bank_idx, value); + break; + + default: + s->regs[addr / sizeof(uint32_t)] = value; + } +} + static const MemoryRegionOps canfd_ops = { - .read = register_read_memory, - .write = register_write_memory, + .read = canfd_read, + .write = canfd_write, .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 4, @@ -2018,8 +2160,8 @@ static void canfd_init(Object *obj) { XlnxVersalCANFDState *s = XILINX_CANFD(obj); - memory_region_init(&s->iomem, obj, TYPE_XILINX_CANFD, - XLNX_VERSAL_CANFD_R_MAX * 4); + memory_region_init_io(&s->iomem, obj, &canfd_ops, s, TYPE_XILINX_CANFD, + XLNX_VERSAL_CANFD_R_MAX * 4); } static const VMStateDescription vmstate_canfd = { From c11200c71575cb38f78548743555c2797d14bf96 Mon Sep 17 00:00:00 2001 From: Luc Michel Date: Fri, 17 Oct 2025 18:18:05 +0200 Subject: [PATCH 22/45] hw/net/can/xlnx-versal-canfd: remove register API usage for banked regs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we have a simple decoding logic for all the banked registers, remove the register API usage for them. This restricts the register API usage to only the base registers (from 0x0 to 0xec). This also removes all the custom code that was creating register descriptors for the register API and was leading to memory leaks when the device was finalized. Reviewed-by: Francisco Iglesias Reviewed-by: Edgar E. Iglesias Signed-off-by: Luc Michel Message-ID: <20251017161809.235740-7-luc.michel@amd.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/net/can/xlnx-versal-canfd.c | 303 ++--------------------------- include/hw/net/xlnx-versal-canfd.h | 8 - 2 files changed, 15 insertions(+), 296 deletions(-) diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c index 04f9a6d57d..5735639b85 100644 --- a/hw/net/can/xlnx-versal-canfd.c +++ b/hw/net/can/xlnx-versal-canfd.c @@ -1426,46 +1426,6 @@ static void filter_reg_write(XlnxVersalCANFDState *s, hwaddr addr, } } -static uint64_t filter_mask(RegisterInfo *reg, uint64_t val64) -{ - XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque); - uint32_t reg_idx = (reg->access->addr) / 4; - uint32_t val = val64; - uint32_t filter_offset = (reg_idx - R_AFMR_REGISTER) / 2; - - if (!(s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER] & - (1 << filter_offset))) { - s->regs[reg_idx] = val; - } else { - g_autofree char *path = object_get_canonical_path(OBJECT(s)); - - qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d not enabled\n", - path, filter_offset + 1); - } - - return s->regs[reg_idx]; -} - -static uint64_t filter_id(RegisterInfo *reg, uint64_t val64) -{ - XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque); - hwaddr reg_idx = (reg->access->addr) / 4; - uint32_t val = val64; - uint32_t filter_offset = (reg_idx - R_AFIR_REGISTER) / 2; - - if (!(s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER] & - (1 << filter_offset))) { - s->regs[reg_idx] = val; - } else { - g_autofree char *path = object_get_canonical_path(OBJECT(s)); - - qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d not enabled\n", - path, filter_offset + 1); - } - - return s->regs[reg_idx]; -} - static uint64_t canfd_tx_fifo_status_prew(RegisterInfo *reg, uint64_t val64) { XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque); @@ -1591,125 +1551,6 @@ static uint64_t canfd_write_check_prew(RegisterInfo *reg, uint64_t val64) return 0; } -static const RegisterAccessInfo canfd_tx_regs[] = { - { .name = "TB_ID_REGISTER", .addr = A_TB_ID_REGISTER, - },{ .name = "TB0_DLC_REGISTER", .addr = A_TB0_DLC_REGISTER, - },{ .name = "TB_DW0_REGISTER", .addr = A_TB_DW0_REGISTER, - },{ .name = "TB_DW1_REGISTER", .addr = A_TB_DW1_REGISTER, - },{ .name = "TB_DW2_REGISTER", .addr = A_TB_DW2_REGISTER, - },{ .name = "TB_DW3_REGISTER", .addr = A_TB_DW3_REGISTER, - },{ .name = "TB_DW4_REGISTER", .addr = A_TB_DW4_REGISTER, - },{ .name = "TB_DW5_REGISTER", .addr = A_TB_DW5_REGISTER, - },{ .name = "TB_DW6_REGISTER", .addr = A_TB_DW6_REGISTER, - },{ .name = "TB_DW7_REGISTER", .addr = A_TB_DW7_REGISTER, - },{ .name = "TB_DW8_REGISTER", .addr = A_TB_DW8_REGISTER, - },{ .name = "TB_DW9_REGISTER", .addr = A_TB_DW9_REGISTER, - },{ .name = "TB_DW10_REGISTER", .addr = A_TB_DW10_REGISTER, - },{ .name = "TB_DW11_REGISTER", .addr = A_TB_DW11_REGISTER, - },{ .name = "TB_DW12_REGISTER", .addr = A_TB_DW12_REGISTER, - },{ .name = "TB_DW13_REGISTER", .addr = A_TB_DW13_REGISTER, - },{ .name = "TB_DW14_REGISTER", .addr = A_TB_DW14_REGISTER, - },{ .name = "TB_DW15_REGISTER", .addr = A_TB_DW15_REGISTER, - } -}; - -static const RegisterAccessInfo canfd_rx0_regs[] = { - { .name = "RB_ID_REGISTER", .addr = A_RB_ID_REGISTER, - .ro = 0xffffffff, - },{ .name = "RB_DLC_REGISTER", .addr = A_RB_DLC_REGISTER, - .ro = 0xfe1fffff, - },{ .name = "RB_DW0_REGISTER", .addr = A_RB_DW0_REGISTER, - .ro = 0xffffffff, - },{ .name = "RB_DW1_REGISTER", .addr = A_RB_DW1_REGISTER, - .ro = 0xffffffff, - },{ .name = "RB_DW2_REGISTER", .addr = A_RB_DW2_REGISTER, - .ro = 0xffffffff, - },{ .name = "RB_DW3_REGISTER", .addr = A_RB_DW3_REGISTER, - .ro = 0xffffffff, - },{ .name = "RB_DW4_REGISTER", .addr = A_RB_DW4_REGISTER, - .ro = 0xffffffff, - },{ .name = "RB_DW5_REGISTER", .addr = A_RB_DW5_REGISTER, - .ro = 0xffffffff, - },{ .name = "RB_DW6_REGISTER", .addr = A_RB_DW6_REGISTER, - .ro = 0xffffffff, - },{ .name = "RB_DW7_REGISTER", .addr = A_RB_DW7_REGISTER, - .ro = 0xffffffff, - },{ .name = "RB_DW8_REGISTER", .addr = A_RB_DW8_REGISTER, - .ro = 0xffffffff, - },{ .name = "RB_DW9_REGISTER", .addr = A_RB_DW9_REGISTER, - .ro = 0xffffffff, - },{ .name = "RB_DW10_REGISTER", .addr = A_RB_DW10_REGISTER, - .ro = 0xffffffff, - },{ .name = "RB_DW11_REGISTER", .addr = A_RB_DW11_REGISTER, - .ro = 0xffffffff, - },{ .name = "RB_DW12_REGISTER", .addr = A_RB_DW12_REGISTER, - .ro = 0xffffffff, - },{ .name = "RB_DW13_REGISTER", .addr = A_RB_DW13_REGISTER, - .ro = 0xffffffff, - },{ .name = "RB_DW14_REGISTER", .addr = A_RB_DW14_REGISTER, - .ro = 0xffffffff, - },{ .name = "RB_DW15_REGISTER", .addr = A_RB_DW15_REGISTER, - .ro = 0xffffffff, - } -}; - -static const RegisterAccessInfo canfd_rx1_regs[] = { - { .name = "RB_ID_REGISTER_1", .addr = A_RB_ID_REGISTER_1, - .ro = 0xffffffff, - },{ .name = "RB_DLC_REGISTER_1", .addr = A_RB_DLC_REGISTER_1, - .ro = 0xfe1fffff, - },{ .name = "RB0_DW0_REGISTER_1", .addr = A_RB0_DW0_REGISTER_1, - .ro = 0xffffffff, - },{ .name = "RB_DW1_REGISTER_1", .addr = A_RB_DW1_REGISTER_1, - .ro = 0xffffffff, - },{ .name = "RB_DW2_REGISTER_1", .addr = A_RB_DW2_REGISTER_1, - .ro = 0xffffffff, - },{ .name = "RB_DW3_REGISTER_1", .addr = A_RB_DW3_REGISTER_1, - .ro = 0xffffffff, - },{ .name = "RB_DW4_REGISTER_1", .addr = A_RB_DW4_REGISTER_1, - .ro = 0xffffffff, - },{ .name = "RB_DW5_REGISTER_1", .addr = A_RB_DW5_REGISTER_1, - .ro = 0xffffffff, - },{ .name = "RB_DW6_REGISTER_1", .addr = A_RB_DW6_REGISTER_1, - .ro = 0xffffffff, - },{ .name = "RB_DW7_REGISTER_1", .addr = A_RB_DW7_REGISTER_1, - .ro = 0xffffffff, - },{ .name = "RB_DW8_REGISTER_1", .addr = A_RB_DW8_REGISTER_1, - .ro = 0xffffffff, - },{ .name = "RB_DW9_REGISTER_1", .addr = A_RB_DW9_REGISTER_1, - .ro = 0xffffffff, - },{ .name = "RB_DW10_REGISTER_1", .addr = A_RB_DW10_REGISTER_1, - .ro = 0xffffffff, - },{ .name = "RB_DW11_REGISTER_1", .addr = A_RB_DW11_REGISTER_1, - .ro = 0xffffffff, - },{ .name = "RB_DW12_REGISTER_1", .addr = A_RB_DW12_REGISTER_1, - .ro = 0xffffffff, - },{ .name = "RB_DW13_REGISTER_1", .addr = A_RB_DW13_REGISTER_1, - .ro = 0xffffffff, - },{ .name = "RB_DW14_REGISTER_1", .addr = A_RB_DW14_REGISTER_1, - .ro = 0xffffffff, - },{ .name = "RB_DW15_REGISTER_1", .addr = A_RB_DW15_REGISTER_1, - .ro = 0xffffffff, - } -}; - -/* Acceptance filter registers. */ -static const RegisterAccessInfo canfd_af_regs[] = { - { .name = "AFMR_REGISTER", .addr = A_AFMR_REGISTER, - .pre_write = filter_mask, - },{ .name = "AFIR_REGISTER", .addr = A_AFIR_REGISTER, - .pre_write = filter_id, - } -}; - -static const RegisterAccessInfo canfd_txe_regs[] = { - { .name = "TXE_FIFO_TB_ID_REGISTER", .addr = A_TXE_FIFO_TB_ID_REGISTER, - .ro = 0xffffffff, - },{ .name = "TXE_FIFO_TB_DLC_REGISTER", .addr = A_TXE_FIFO_TB_DLC_REGISTER, - .ro = 0xffffffff, - } -}; - static const RegisterAccessInfo canfd_regs_info[] = { { .name = "SOFTWARE_RESET_REGISTER", .addr = A_SOFTWARE_RESET_REGISTER, .pre_write = canfd_srr_pre_write, @@ -1915,6 +1756,16 @@ static const MemoryRegionOps canfd_ops = { }, }; +static const MemoryRegionOps canfd_regs_ops = { + .read = register_read_memory, + .write = register_write_memory, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + static void canfd_reset(DeviceState *dev) { XlnxVersalCANFDState *s = XILINX_CANFD(dev); @@ -1994,140 +1845,16 @@ static int xlnx_canfd_connect_to_bus(XlnxVersalCANFDState *s, return can_bus_insert_client(bus, &s->bus_client); } -#define NUM_REG_PER_AF ARRAY_SIZE(canfd_af_regs) -#define NUM_AF 32 -#define NUM_REG_PER_TXE ARRAY_SIZE(canfd_txe_regs) -#define NUM_TXE 32 - -static int canfd_populate_regarray(XlnxVersalCANFDState *s, - RegisterInfoArray *r_array, int pos, - const RegisterAccessInfo *rae, - int num_rae) -{ - int i; - - for (i = 0; i < num_rae; i++) { - int index = rae[i].addr / 4; - RegisterInfo *r = &s->reg_info[index]; - - *r = (RegisterInfo) { - .data = &s->regs[index], - .data_size = sizeof(uint32_t), - .access = &rae[i], - .opaque = OBJECT(s), - }; - - r_array->r[i + pos] = r; - } - return i + pos; -} - -static void canfd_create_rai(RegisterAccessInfo *rai_array, - const RegisterAccessInfo *canfd_regs, - int template_rai_array_sz, - int num_template_to_copy) -{ - int i; - int reg_num; - - for (reg_num = 0; reg_num < num_template_to_copy; reg_num++) { - int pos = reg_num * template_rai_array_sz; - - memcpy(rai_array + pos, canfd_regs, - template_rai_array_sz * sizeof(RegisterAccessInfo)); - - for (i = 0; i < template_rai_array_sz; i++) { - const char *name = canfd_regs[i].name; - uint64_t addr = canfd_regs[i].addr; - rai_array[i + pos].name = g_strdup_printf("%s%d", name, reg_num); - rai_array[i + pos].addr = addr + pos * 4; - } - } -} - -static RegisterInfoArray *canfd_create_regarray(XlnxVersalCANFDState *s) -{ - const char *device_prefix = object_get_typename(OBJECT(s)); - uint64_t memory_size = XLNX_VERSAL_CANFD_R_MAX * 4; - int num_regs; - int pos = 0; - RegisterInfoArray *r_array; - - num_regs = ARRAY_SIZE(canfd_regs_info) + - s->cfg.tx_fifo * NUM_REGS_PER_MSG_SPACE + - s->cfg.rx0_fifo * NUM_REGS_PER_MSG_SPACE + - NUM_AF * NUM_REG_PER_AF + - NUM_TXE * NUM_REG_PER_TXE; - - s->tx_regs = g_new0(RegisterAccessInfo, - s->cfg.tx_fifo * ARRAY_SIZE(canfd_tx_regs)); - - canfd_create_rai(s->tx_regs, canfd_tx_regs, - ARRAY_SIZE(canfd_tx_regs), s->cfg.tx_fifo); - - s->rx0_regs = g_new0(RegisterAccessInfo, - s->cfg.rx0_fifo * ARRAY_SIZE(canfd_rx0_regs)); - - canfd_create_rai(s->rx0_regs, canfd_rx0_regs, - ARRAY_SIZE(canfd_rx0_regs), s->cfg.rx0_fifo); - - s->af_regs = g_new0(RegisterAccessInfo, - NUM_AF * ARRAY_SIZE(canfd_af_regs)); - - canfd_create_rai(s->af_regs, canfd_af_regs, - ARRAY_SIZE(canfd_af_regs), NUM_AF); - - s->txe_regs = g_new0(RegisterAccessInfo, - NUM_TXE * ARRAY_SIZE(canfd_txe_regs)); - - canfd_create_rai(s->txe_regs, canfd_txe_regs, - ARRAY_SIZE(canfd_txe_regs), NUM_TXE); - - if (s->cfg.enable_rx_fifo1) { - num_regs += s->cfg.rx1_fifo * NUM_REGS_PER_MSG_SPACE; - - s->rx1_regs = g_new0(RegisterAccessInfo, - s->cfg.rx1_fifo * ARRAY_SIZE(canfd_rx1_regs)); - - canfd_create_rai(s->rx1_regs, canfd_rx1_regs, - ARRAY_SIZE(canfd_rx1_regs), s->cfg.rx1_fifo); - } - - r_array = g_new0(RegisterInfoArray, 1); - r_array->r = g_new0(RegisterInfo * , num_regs); - r_array->num_elements = num_regs; - r_array->prefix = device_prefix; - - pos = canfd_populate_regarray(s, r_array, pos, - canfd_regs_info, - ARRAY_SIZE(canfd_regs_info)); - pos = canfd_populate_regarray(s, r_array, pos, - s->tx_regs, s->cfg.tx_fifo * - NUM_REGS_PER_MSG_SPACE); - pos = canfd_populate_regarray(s, r_array, pos, - s->rx0_regs, s->cfg.rx0_fifo * - NUM_REGS_PER_MSG_SPACE); - if (s->cfg.enable_rx_fifo1) { - pos = canfd_populate_regarray(s, r_array, pos, - s->rx1_regs, s->cfg.rx1_fifo * - NUM_REGS_PER_MSG_SPACE); - } - pos = canfd_populate_regarray(s, r_array, pos, - s->af_regs, NUM_AF * NUM_REG_PER_AF); - pos = canfd_populate_regarray(s, r_array, pos, - s->txe_regs, NUM_TXE * NUM_REG_PER_TXE); - - memory_region_init_io(&r_array->mem, OBJECT(s), &canfd_ops, r_array, - device_prefix, memory_size); - return r_array; -} - static void canfd_realize(DeviceState *dev, Error **errp) { XlnxVersalCANFDState *s = XILINX_CANFD(dev); RegisterInfoArray *reg_array; - reg_array = canfd_create_regarray(s); + reg_array = register_init_block32(dev, canfd_regs_info, + ARRAY_SIZE(canfd_regs_info), s->reg_info, + s->regs, &canfd_regs_ops, false, + A_RX_FIFO_WATERMARK_REGISTER + + sizeof(uint32_t)); memory_region_add_subregion(&s->iomem, 0x00, ®_array->mem); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq_canfd_int); diff --git a/include/hw/net/xlnx-versal-canfd.h b/include/hw/net/xlnx-versal-canfd.h index ad3104dd13..396f90d6dc 100644 --- a/include/hw/net/xlnx-versal-canfd.h +++ b/include/hw/net/xlnx-versal-canfd.h @@ -54,14 +54,6 @@ typedef struct XlnxVersalCANFDState { qemu_irq irq_addr_err; RegisterInfo reg_info[XLNX_VERSAL_CANFD_R_MAX]; - RegisterAccessInfo *tx_regs; - RegisterAccessInfo *rx0_regs; - RegisterAccessInfo *rx1_regs; - RegisterAccessInfo *af_regs; - RegisterAccessInfo *txe_regs; - RegisterAccessInfo *rx_mailbox_regs; - RegisterAccessInfo *af_mask_regs_mailbox; - uint32_t regs[XLNX_VERSAL_CANFD_R_MAX]; ptimer_state *canfd_timer; From 5e7ea00c5fdcb05d189fb0a5cb8ab9f520303ee8 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 18 Oct 2025 16:04:59 +0200 Subject: [PATCH 23/45] hw/ppc/prep: Always create prep-systemio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The prep-systemio device models the system control ports of the 40p machine which is not an optional pluggable device but part of the system so it should not be disabled by -nodefaults but always created. Additionally remove some line breaks to make lines related to one device appear in one block for logical separation from other devices. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-ID: Signed-off-by: Philippe Mathieu-Daudé --- hw/ppc/prep.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index 982e40e53e..c730cb3429 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -308,6 +308,13 @@ static void ibm_40p_init(MachineState *machine) sysbus_connect_irq(pcihost, 0, qdev_get_gpio_in(i82378_dev, 15)); isa_bus = ISA_BUS(qdev_get_child_bus(i82378_dev, "isa.0")); + /* system control ports */ + isa_dev = isa_new("prep-systemio"); + dev = DEVICE(isa_dev); + qdev_prop_set_uint32(dev, "ibm-planar-id", 0xfc); + qdev_prop_set_uint32(dev, "equipment", 0xc0); + isa_realize_and_unref(isa_dev, isa_bus, &error_fatal); + /* Memory controller */ isa_dev = isa_new("rs6000-mc"); dev = DEVICE(isa_dev); @@ -333,7 +340,6 @@ static void ibm_40p_init(MachineState *machine) dev = DEVICE(isa_dev); qdev_prop_set_uint32(dev, "iobase", 0x830); qdev_prop_set_uint32(dev, "irq", 10); - if (machine->audiodev) { qdev_prop_set_string(dev, "audiodev", machine->audiodev); } @@ -344,14 +350,7 @@ static void ibm_40p_init(MachineState *machine) qdev_prop_set_uint32(dev, "config", 12); isa_realize_and_unref(isa_dev, isa_bus, &error_fatal); - isa_dev = isa_new("prep-systemio"); - dev = DEVICE(isa_dev); - qdev_prop_set_uint32(dev, "ibm-planar-id", 0xfc); - qdev_prop_set_uint32(dev, "equipment", 0xc0); - isa_realize_and_unref(isa_dev, isa_bus, &error_fatal); - - dev = DEVICE(pci_create_simple(pci_bus, PCI_DEVFN(1, 0), - "lsi53c810")); + dev = DEVICE(pci_create_simple(pci_bus, PCI_DEVFN(1, 0), "lsi53c810")); lsi53c8xx_handle_legacy_cmdline(dev); qdev_connect_gpio_out(dev, 0, qdev_get_gpio_in(i82378_dev, 13)); From be2f66e07aab5998f55d5e6e4de0a69a069759ed Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Sun, 19 Oct 2025 23:02:54 +0200 Subject: [PATCH 24/45] hw/timer/i8254: Add I/O trace events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allows to see how the guest interacts with the device. Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20251019210303.104718-2-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/timer/i8254.c | 6 ++++++ hw/timer/trace-events | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/hw/timer/i8254.c b/hw/timer/i8254.c index 4b25c487f7..7033ebf50d 100644 --- a/hw/timer/i8254.c +++ b/hw/timer/i8254.c @@ -29,6 +29,7 @@ #include "hw/timer/i8254.h" #include "hw/timer/i8254_internal.h" #include "qom/object.h" +#include "trace.h" //#define DEBUG_PIT @@ -130,6 +131,8 @@ static void pit_ioport_write(void *opaque, hwaddr addr, int channel, access; PITChannelState *s; + trace_pit_ioport_write(addr, val); + addr &= 3; if (addr == 3) { channel = val >> 6; @@ -248,6 +251,9 @@ static uint64_t pit_ioport_read(void *opaque, hwaddr addr, break; } } + + trace_pit_ioport_read(addr, ret); + return ret; } diff --git a/hw/timer/trace-events b/hw/timer/trace-events index c5b6db49f5..2bb51f95ea 100644 --- a/hw/timer/trace-events +++ b/hw/timer/trace-events @@ -49,6 +49,10 @@ cmsdk_apb_dualtimer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK A cmsdk_apb_dualtimer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB dualtimer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" cmsdk_apb_dualtimer_reset(void) "CMSDK APB dualtimer: reset" +# i8254.c +pit_ioport_read(uint8_t addr, uint32_t value) "[0x%" PRIx8 "] -> 0x%" PRIx32 +pit_ioport_write(uint8_t addr, uint32_t value) "[0x%" PRIx8 "] <- 0x%" PRIx32 + # imx_gpt.c imx_gpt_set_freq(uint32_t clksrc, uint32_t freq) "Setting clksrc %u to %u Hz" imx_gpt_read(const char *name, uint64_t value) "%s -> 0x%08" PRIx64 From 6b670b1b9616ac113392eb438642cbf6e854e3eb Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Sun, 19 Oct 2025 23:02:55 +0200 Subject: [PATCH 25/45] hw/audio/pcspk: Add I/O trace events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allows to see how the guest interacts with the device. Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20251019210303.104718-3-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/audio/pcspk.c | 10 +++++++++- hw/audio/trace-events | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index a419161b5b..f8020593b0 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -34,6 +34,7 @@ #include "hw/audio/pcspk.h" #include "qapi/error.h" #include "qom/object.h" +#include "trace.h" #define PCSPK_BUF_LEN 1792 #define PCSPK_SAMPLE_RATE 32000 @@ -137,13 +138,18 @@ static uint64_t pcspk_io_read(void *opaque, hwaddr addr, { PCSpkState *s = opaque; PITChannelInfo ch; + uint8_t val; pit_get_channel_info(s->pit, 2, &ch); s->dummy_refresh_clock ^= (1 << 4); - return ch.gate | (s->data_on << 1) | s->dummy_refresh_clock | + val = ch.gate | (s->data_on << 1) | s->dummy_refresh_clock | (ch.out << 5); + + trace_pcspk_io_read(s->iobase, val); + + return val; } static void pcspk_io_write(void *opaque, hwaddr addr, uint64_t val, @@ -152,6 +158,8 @@ static void pcspk_io_write(void *opaque, hwaddr addr, uint64_t val, PCSpkState *s = opaque; const int gate = val & 1; + trace_pcspk_io_write(s->iobase, val); + s->data_on = (val >> 1) & 1; pit_set_gate(s->pit, 2, gate); if (s->voice) { diff --git a/hw/audio/trace-events b/hw/audio/trace-events index b8ef572767..30f5921545 100644 --- a/hw/audio/trace-events +++ b/hw/audio/trace-events @@ -23,6 +23,10 @@ hda_audio_format(const char *stream, int chan, const char *fmt, int freq) "st %s hda_audio_adjust(const char *stream, int pos) "st %s, pos %d" hda_audio_overrun(const char *stream) "st %s" +# pcspk.c +pcspk_io_read(uint16_t addr, uint8_t val) "[0x%"PRIx16"] -> 0x%"PRIx8 +pcspk_io_write(uint16_t addr, uint8_t val) "[0x%"PRIx16"] <- 0x%"PRIx8 + #via-ac97.c via_ac97_codec_write(uint8_t addr, uint16_t val) "0x%x <- 0x%x" via_ac97_sgd_fetch(uint32_t curr, uint32_t addr, char stop, char eol, char flag, uint32_t len) "curr=0x%x addr=0x%x %c%c%c len=%d" From 4847c5701a33d519067c06054243434e489e337c Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Sun, 19 Oct 2025 23:02:56 +0200 Subject: [PATCH 26/45] hw/rtc/mc146818rtc: Convert CMOS_DPRINTF() into trace events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20251019210303.104718-4-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/rtc/mc146818rtc.c | 14 +++----------- hw/rtc/trace-events | 4 ++++ 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c index f9f5cf396f..61e9c0bf99 100644 --- a/hw/rtc/mc146818rtc.c +++ b/hw/rtc/mc146818rtc.c @@ -43,16 +43,10 @@ #include "qapi/error.h" #include "qapi/qapi-events-misc.h" #include "qapi/visitor.h" +#include "trace.h" -//#define DEBUG_CMOS //#define DEBUG_COALESCED -#ifdef DEBUG_CMOS -# define CMOS_DPRINTF(format, ...) printf(format, ## __VA_ARGS__) -#else -# define CMOS_DPRINTF(format, ...) do { } while (0) -#endif - #ifdef DEBUG_COALESCED # define DPRINTF_C(format, ...) printf(format, ## __VA_ARGS__) #else @@ -439,8 +433,7 @@ static void cmos_ioport_write(void *opaque, hwaddr addr, if ((addr & 1) == 0) { s->cmos_index = data & 0x7f; } else { - CMOS_DPRINTF("cmos: write index=0x%02x val=0x%02" PRIx64 "\n", - s->cmos_index, data); + trace_mc146818_rtc_ioport_write(s->cmos_index, data); switch(s->cmos_index) { case RTC_SECONDS_ALARM: case RTC_MINUTES_ALARM: @@ -726,8 +719,7 @@ static uint64_t cmos_ioport_read(void *opaque, hwaddr addr, ret = s->cmos_data[s->cmos_index]; break; } - CMOS_DPRINTF("cmos: read index=0x%02x val=0x%02x\n", - s->cmos_index, ret); + trace_mc146818_rtc_ioport_read(s->cmos_index, ret); return ret; } } diff --git a/hw/rtc/trace-events b/hw/rtc/trace-events index b9f2852d35..d2f36217cb 100644 --- a/hw/rtc/trace-events +++ b/hw/rtc/trace-events @@ -32,6 +32,10 @@ m48txx_nvram_io_write(uint64_t addr, uint64_t value) "io write addr:0x%04" PRIx6 m48txx_nvram_mem_read(uint32_t addr, uint32_t value) "mem read addr:0x%04x value:0x%02x" m48txx_nvram_mem_write(uint32_t addr, uint32_t value) "mem write addr:0x%04x value:0x%02x" +# mc146818rtc.c +mc146818_rtc_ioport_read(uint8_t addr, uint8_t value) "[0x%02" PRIx8 "] -> 0x%02" PRIx8 +mc146818_rtc_ioport_write(uint8_t addr, uint8_t value) "[0x%02" PRIx8 "] <- 0x%02" PRIx8 + # goldfish_rtc.c goldfish_rtc_read(uint64_t addr, uint64_t value) "addr 0x%02" PRIx64 " value 0x%08" PRIx64 goldfish_rtc_write(uint64_t addr, uint64_t value) "addr 0x%02" PRIx64 " value 0x%08" PRIx64 From 3006fa8d26fe8b8d9b344c9e983513cd59477cb7 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Sun, 19 Oct 2025 23:02:57 +0200 Subject: [PATCH 27/45] hw/rtc/mc146818rtc: Use ARRAY_SIZE macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoids the error-prone repetition of the array size. Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20251019210303.104718-5-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/rtc/mc146818rtc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c index 61e9c0bf99..5a89062b4c 100644 --- a/hw/rtc/mc146818rtc.c +++ b/hw/rtc/mc146818rtc.c @@ -726,13 +726,14 @@ static uint64_t cmos_ioport_read(void *opaque, hwaddr addr, void mc146818rtc_set_cmos_data(MC146818RtcState *s, int addr, int val) { - if (addr >= 0 && addr <= 127) + if (addr >= 0 && addr < ARRAY_SIZE(s->cmos_data)) { s->cmos_data[addr] = val; + } } int mc146818rtc_get_cmos_data(MC146818RtcState *s, int addr) { - assert(addr >= 0 && addr <= 127); + assert(addr >= 0 && addr < ARRAY_SIZE(s->cmos_data)); return s->cmos_data[addr]; } From f3c0c9da662b22d62532c25b7c561dd9ce6b8def Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Sun, 19 Oct 2025 23:02:58 +0200 Subject: [PATCH 28/45] hw/rtc/mc146818rtc: Assert correct usage of mc146818rtc_set_cmos_data() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The offset is never controlled by the guest, so any misuse constitutes a programming error and shouldn't be silently ignored. Fix this by using assert(). Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20251019210303.104718-6-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/rtc/mc146818rtc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c index 5a89062b4c..8631386b9f 100644 --- a/hw/rtc/mc146818rtc.c +++ b/hw/rtc/mc146818rtc.c @@ -726,9 +726,8 @@ static uint64_t cmos_ioport_read(void *opaque, hwaddr addr, void mc146818rtc_set_cmos_data(MC146818RtcState *s, int addr, int val) { - if (addr >= 0 && addr < ARRAY_SIZE(s->cmos_data)) { - s->cmos_data[addr] = val; - } + assert(addr >= 0 && addr < ARRAY_SIZE(s->cmos_data)); + s->cmos_data[addr] = val; } int mc146818rtc_get_cmos_data(MC146818RtcState *s, int addr) From dd012373a591ea52e3b9105cd5f8ba69d2303103 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Sun, 19 Oct 2025 23:02:59 +0200 Subject: [PATCH 29/45] hw/ide/ide-internal: Move dma_buf_commit() into ide "namespace" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The identifier suggests that it is a generic DMA function while it is tied to IDE. Fix this by adding an "ide_" prefix. Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20251019210303.104718-7-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/ide/ahci.c | 8 ++++---- hw/ide/core.c | 10 +++++----- hw/ide/ide-internal.h | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 1303c21cb7..14bc66fb7f 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1417,7 +1417,7 @@ static void ahci_pio_transfer(const IDEDMA *dma) } /* Update number of transferred bytes, destroy sglist */ - dma_buf_commit(s, size); + ide_dma_buf_commit(s, size); out: /* declare that we processed everything */ @@ -1482,8 +1482,8 @@ static int32_t ahci_dma_prepare_buf(const IDEDMA *dma, int32_t limit) /** * Updates the command header with a bytes-read value. - * Called via dma_buf_commit, for both DMA and PIO paths. - * sglist destruction is handled within dma_buf_commit. + * Called via ide_dma_buf_commit, for both DMA and PIO paths. + * sglist destruction is handled within ide_dma_buf_commit. */ static void ahci_commit_buf(const IDEDMA *dma, uint32_t tx_bytes) { @@ -1511,7 +1511,7 @@ static int ahci_dma_rw_buf(const IDEDMA *dma, bool is_write) } /* free sglist, update byte count */ - dma_buf_commit(s, l); + ide_dma_buf_commit(s, l); s->io_buffer_index += l; trace_ahci_dma_rw_buf(ad->hba, ad->port_no, l); diff --git a/hw/ide/core.c b/hw/ide/core.c index b14983ec54..8c380abf7c 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -827,7 +827,7 @@ static void ide_sector_read(IDEState *s) ide_sector_read_cb, s); } -void dma_buf_commit(IDEState *s, uint32_t tx_bytes) +void ide_dma_buf_commit(IDEState *s, uint32_t tx_bytes) { if (s->bus->dma->ops->commit_buf) { s->bus->dma->ops->commit_buf(s->bus->dma, tx_bytes); @@ -848,7 +848,7 @@ void ide_set_inactive(IDEState *s, bool more) void ide_dma_error(IDEState *s) { - dma_buf_commit(s, 0); + ide_dma_buf_commit(s, 0); ide_abort_command(s); ide_set_inactive(s, false); ide_bus_set_irq(s->bus); @@ -893,7 +893,7 @@ static void ide_dma_cb(void *opaque, int ret) if (ret < 0) { if (ide_handle_rw_error(s, -ret, ide_dma_cmd_to_retry(s->dma_cmd))) { s->bus->dma->aiocb = NULL; - dma_buf_commit(s, 0); + ide_dma_buf_commit(s, 0); return; } } @@ -912,7 +912,7 @@ static void ide_dma_cb(void *opaque, int ret) sector_num = ide_get_sector(s); if (n > 0) { assert(n * 512 == s->sg.size); - dma_buf_commit(s, s->sg.size); + ide_dma_buf_commit(s, s->sg.size); sector_num += n; ide_set_sector(s, sector_num); s->nsector -= n; @@ -944,7 +944,7 @@ static void ide_dma_cb(void *opaque, int ret) * Reset the Active bit and don't raise the interrupt. */ s->status = READY_STAT | SEEK_STAT; - dma_buf_commit(s, 0); + ide_dma_buf_commit(s, 0); goto eot; } diff --git a/hw/ide/ide-internal.h b/hw/ide/ide-internal.h index 0d64805da2..281d07c9d5 100644 --- a/hw/ide/ide-internal.h +++ b/hw/ide/ide-internal.h @@ -398,7 +398,7 @@ int64_t ide_get_sector(IDEState *s); void ide_set_sector(IDEState *s, int64_t sector_num); void ide_start_dma(IDEState *s, BlockCompletionFunc *cb); -void dma_buf_commit(IDEState *s, uint32_t tx_bytes); +void ide_dma_buf_commit(IDEState *s, uint32_t tx_bytes); void ide_dma_error(IDEState *s); void ide_abort_command(IDEState *s); From 2fd15a24ca3b88531d66efb203d1f7f39d8519f5 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Sun, 19 Oct 2025 23:03:00 +0200 Subject: [PATCH 30/45] hw/i386/apic: Prefer APICCommonState over DeviceState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Makes the APIC API more type-safe by resolving quite a few APIC_COMMON downcasts. Like PICCommonState, the APICCommonState is now a public typedef while staying an abstract datatype. Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20251019210303.104718-8-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/i386/kvm/apic.c | 3 +- hw/i386/vapic.c | 2 +- hw/i386/x86-cpu.c | 2 +- hw/intc/apic.c | 97 +++++++++++++------------------- hw/intc/apic_common.c | 56 +++++++----------- include/hw/i386/apic.h | 33 +++++------ include/hw/i386/apic_internal.h | 7 +-- target/i386/cpu-apic.c | 18 +++--- target/i386/cpu-dump.c | 2 +- target/i386/cpu.c | 2 +- target/i386/cpu.h | 5 +- target/i386/kvm/kvm.c | 2 +- target/i386/kvm/kvm_i386.h | 2 +- target/i386/whpx/whpx-apic.c | 3 +- target/i386/whpx/whpx-internal.h | 4 +- 15 files changed, 98 insertions(+), 140 deletions(-) diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c index 1be9bfe36e..82355f0463 100644 --- a/hw/i386/kvm/apic.c +++ b/hw/i386/kvm/apic.c @@ -60,9 +60,8 @@ static void kvm_put_apic_state(APICCommonState *s, struct kvm_lapic_state *kapic kvm_apic_set_reg(kapic, 0x3e, s->divide_conf); } -void kvm_get_apic_state(DeviceState *dev, struct kvm_lapic_state *kapic) +void kvm_get_apic_state(APICCommonState *s, struct kvm_lapic_state *kapic) { - APICCommonState *s = APIC_COMMON(dev); int i, v; if (kvm_has_x2apic_api() && s->apicbase & MSR_IA32_APICBASE_EXTD) { diff --git a/hw/i386/vapic.c b/hw/i386/vapic.c index 0c1c92c479..f1089f0a7c 100644 --- a/hw/i386/vapic.c +++ b/hw/i386/vapic.c @@ -490,7 +490,7 @@ void vapic_report_tpr_access(DeviceState *dev, CPUState *cs, target_ulong ip, } typedef struct VAPICEnableTPRReporting { - DeviceState *apic; + APICCommonState *apic; bool enable; } VAPICEnableTPRReporting; diff --git a/hw/i386/x86-cpu.c b/hw/i386/x86-cpu.c index c876e6709e..1a86a853d5 100644 --- a/hw/i386/x86-cpu.c +++ b/hw/i386/x86-cpu.c @@ -86,7 +86,7 @@ int cpu_get_pic_interrupt(CPUX86State *env) return intno; } -DeviceState *cpu_get_current_apic(void) +APICCommonState *cpu_get_current_apic(void) { if (current_cpu) { X86CPU *cpu = X86_CPU(current_cpu); diff --git a/hw/intc/apic.c b/hw/intc/apic.c index c768033856..cb35c80c75 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -181,10 +181,8 @@ static void apic_local_deliver(APICCommonState *s, int vector) } } -void apic_deliver_pic_intr(DeviceState *dev, int level) +void apic_deliver_pic_intr(APICCommonState *s, int level) { - APICCommonState *s = APIC(dev); - if (level) { apic_local_deliver(s, APIC_LVT_LINT0); } else { @@ -301,10 +299,8 @@ static void apic_deliver_irq(uint32_t dest, uint8_t dest_mode, apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, trigger_mode); } -bool is_x2apic_mode(DeviceState *dev) +bool is_x2apic_mode(APICCommonState *s) { - APICCommonState *s = APIC(dev); - return s->apicbase & MSR_IA32_APICBASE_EXTD; } @@ -388,15 +384,12 @@ static void apic_set_tpr(APICCommonState *s, uint8_t val) } } -int apic_get_highest_priority_irr(DeviceState *dev) +int apic_get_highest_priority_irr(APICCommonState *s) { - APICCommonState *s; - - if (!dev) { + if (!s) { /* no interrupts */ return -1; } - s = APIC_COMMON(dev); return get_highest_priority_int(s->irr); } @@ -458,22 +451,19 @@ static int apic_irq_pending(APICCommonState *s) static void apic_update_irq(APICCommonState *s) { CPUState *cpu; - DeviceState *dev = (DeviceState *)s; cpu = CPU(s->cpu); if (!qemu_cpu_is_self(cpu)) { cpu_interrupt(cpu, CPU_INTERRUPT_POLL); } else if (apic_irq_pending(s) > 0) { cpu_interrupt(cpu, CPU_INTERRUPT_HARD); - } else if (!apic_accept_pic_intr(dev) || !pic_get_output(isa_pic)) { + } else if (!apic_accept_pic_intr(s) || !pic_get_output(isa_pic)) { cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD); } } -void apic_poll_irq(DeviceState *dev) +void apic_poll_irq(APICCommonState *s) { - APICCommonState *s = APIC(dev); - apic_sync_vapic(s, SYNC_FROM_VAPIC); apic_update_irq(s); } @@ -516,7 +506,7 @@ static void apic_eoi(APICCommonState *s) static bool apic_match_dest(APICCommonState *apic, uint32_t dest) { - if (is_x2apic_mode(&apic->parent_obj)) { + if (is_x2apic_mode(apic)) { return apic->initial_apic_id == dest; } else { return apic->id == (uint8_t)dest; @@ -550,7 +540,7 @@ static void apic_get_broadcast_bitmask(uint32_t *deliver_bitmask, for (i = 0; i < max_apics; i++) { apic_iter = local_apics[i]; if (apic_iter) { - bool apic_in_x2apic = is_x2apic_mode(&apic_iter->parent_obj); + bool apic_in_x2apic = is_x2apic_mode(apic_iter); if (is_x2apic_broadcast && apic_in_x2apic) { apic_set_bit(deliver_bitmask, i); @@ -642,27 +632,24 @@ static void apic_startup(APICCommonState *s, int vector_num) cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI); } -void apic_sipi(DeviceState *dev) +void apic_sipi(APICCommonState *s) { - APICCommonState *s = APIC(dev); - if (!s->wait_for_sipi) return; cpu_x86_load_seg_cache_sipi(s->cpu, s->sipi_vector); s->wait_for_sipi = 0; } -static void apic_deliver(DeviceState *dev, uint32_t dest, uint8_t dest_mode, +static void apic_deliver(APICCommonState *s, uint32_t dest, uint8_t dest_mode, uint8_t delivery_mode, uint8_t vector_num, uint8_t trigger_mode, uint8_t dest_shorthand) { - APICCommonState *s = APIC(dev); APICCommonState *apic_iter; uint32_t deliver_bitmask_size = max_apic_words * sizeof(uint32_t); g_autofree uint32_t *deliver_bitmask = g_new(uint32_t, max_apic_words); uint32_t current_apic_id; - if (is_x2apic_mode(dev)) { + if (is_x2apic_mode(s)) { current_apic_id = s->initial_apic_id; } else { current_apic_id = s->id; @@ -709,18 +696,15 @@ static void apic_deliver(DeviceState *dev, uint32_t dest, uint8_t dest_mode, static bool apic_check_pic(APICCommonState *s) { - DeviceState *dev = (DeviceState *)s; - - if (!apic_accept_pic_intr(dev) || !pic_get_output(isa_pic)) { + if (!apic_accept_pic_intr(s) || !pic_get_output(isa_pic)) { return false; } - apic_deliver_pic_intr(dev, 1); + apic_deliver_pic_intr(s, 1); return true; } -int apic_get_interrupt(DeviceState *dev) +int apic_get_interrupt(APICCommonState *s) { - APICCommonState *s = APIC(dev); int intno; /* if the APIC is installed or enabled, we let the 8259 handle the @@ -752,9 +736,8 @@ int apic_get_interrupt(DeviceState *dev) return intno; } -int apic_accept_pic_intr(DeviceState *dev) +int apic_accept_pic_intr(APICCommonState *s) { - APICCommonState *s = APIC(dev); uint32_t lvt0; if (!s) @@ -788,20 +771,18 @@ static void apic_timer(void *opaque) static int apic_register_read(int index, uint64_t *value) { - DeviceState *dev; APICCommonState *s; uint32_t val; int ret = 0; - dev = cpu_get_current_apic(); - if (!dev) { + s = cpu_get_current_apic(); + if (!s) { return -1; } - s = APIC(dev); switch(index) { case 0x02: /* id */ - if (is_x2apic_mode(dev)) { + if (is_x2apic_mode(s)) { val = s->initial_apic_id; } else { val = s->id << 24; @@ -828,14 +809,14 @@ static int apic_register_read(int index, uint64_t *value) val = 0; break; case 0x0d: - if (is_x2apic_mode(dev)) { + if (is_x2apic_mode(s)) { val = s->extended_log_dest; } else { val = s->log_dest << 24; } break; case 0x0e: - if (is_x2apic_mode(dev)) { + if (is_x2apic_mode(s)) { val = 0; ret = -1; } else { @@ -902,14 +883,14 @@ static uint64_t apic_mem_read(void *opaque, hwaddr addr, unsigned size) int apic_msr_read(int index, uint64_t *val) { - DeviceState *dev; + APICCommonState *s; - dev = cpu_get_current_apic(); - if (!dev) { + s = cpu_get_current_apic(); + if (!s) { return -1; } - if (!is_x2apic_mode(dev)) { + if (!is_x2apic_mode(s)) { return -1; } @@ -943,20 +924,18 @@ static void apic_send_msi(MSIMessage *msi) static int apic_register_write(int index, uint64_t val) { - DeviceState *dev; APICCommonState *s; - dev = cpu_get_current_apic(); - if (!dev) { + s = cpu_get_current_apic(); + if (!s) { return -1; } - s = APIC(dev); trace_apic_register_write(index, val); switch(index) { case 0x02: - if (is_x2apic_mode(dev)) { + if (is_x2apic_mode(s)) { return -1; } @@ -979,14 +958,14 @@ static int apic_register_write(int index, uint64_t val) apic_eoi(s); break; case 0x0d: - if (is_x2apic_mode(dev)) { + if (is_x2apic_mode(s)) { return -1; } s->log_dest = val >> 24; break; case 0x0e: - if (is_x2apic_mode(dev)) { + if (is_x2apic_mode(s)) { return -1; } @@ -1005,20 +984,20 @@ static int apic_register_write(int index, uint64_t val) uint32_t dest; s->icr[0] = val; - if (is_x2apic_mode(dev)) { + if (is_x2apic_mode(s)) { s->icr[1] = val >> 32; dest = s->icr[1]; } else { dest = (s->icr[1] >> 24) & 0xff; } - apic_deliver(dev, dest, (s->icr[0] >> 11) & 1, + apic_deliver(s, dest, (s->icr[0] >> 11) & 1, (s->icr[0] >> 8) & 7, (s->icr[0] & 0xff), (s->icr[0] >> 15) & 1, (s->icr[0] >> 18) & 3); break; } case 0x31: - if (is_x2apic_mode(dev)) { + if (is_x2apic_mode(s)) { return -1; } @@ -1053,7 +1032,7 @@ static int apic_register_write(int index, uint64_t val) case 0x3f: { int vector = val & 0xff; - if (!is_x2apic_mode(dev)) { + if (!is_x2apic_mode(s)) { return -1; } @@ -1063,7 +1042,7 @@ static int apic_register_write(int index, uint64_t val) * - Trigger mode: 0 (Edge) * - Delivery mode: 0 (Fixed) */ - apic_deliver(dev, 0, 0, APIC_DM_FIXED, vector, 0, 1); + apic_deliver(s, 0, 0, APIC_DM_FIXED, vector, 0, 1); break; } @@ -1102,14 +1081,14 @@ static void apic_mem_write(void *opaque, hwaddr addr, uint64_t val, int apic_msr_write(int index, uint64_t val) { - DeviceState *dev; + APICCommonState *s; - dev = cpu_get_current_apic(); - if (!dev) { + s = cpu_get_current_apic(); + if (!s) { return -1; } - if (!is_x2apic_mode(dev)) { + if (!is_x2apic_mode(s)) { return -1; } diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c index 394fe02013..ec9e978b0b 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -35,12 +35,11 @@ bool apic_report_tpr_access; -int cpu_set_apic_base(DeviceState *dev, uint64_t val) +int cpu_set_apic_base(APICCommonState *s, uint64_t val) { trace_cpu_set_apic_base(val); - if (dev) { - APICCommonState *s = APIC_COMMON(dev); + if (s) { APICCommonClass *info = APIC_COMMON_GET_CLASS(s); /* Reset possibly modified xAPIC ID */ s->id = s->initial_apic_id; @@ -50,10 +49,9 @@ int cpu_set_apic_base(DeviceState *dev, uint64_t val) return 0; } -uint64_t cpu_get_apic_base(DeviceState *dev) +uint64_t cpu_get_apic_base(APICCommonState *s) { - if (dev) { - APICCommonState *s = APIC_COMMON(dev); + if (s) { trace_cpu_get_apic_base((uint64_t)s->apicbase); return s->apicbase; } else { @@ -62,52 +60,43 @@ uint64_t cpu_get_apic_base(DeviceState *dev) } } -bool cpu_is_apic_enabled(DeviceState *dev) +bool cpu_is_apic_enabled(APICCommonState *s) { - APICCommonState *s; - - if (!dev) { + if (!s) { return false; } - s = APIC_COMMON(dev); - return s->apicbase & MSR_IA32_APICBASE_ENABLE; } -void cpu_set_apic_tpr(DeviceState *dev, uint8_t val) +void cpu_set_apic_tpr(APICCommonState *s, uint8_t val) { - APICCommonState *s; APICCommonClass *info; - if (!dev) { + if (!s) { return; } - s = APIC_COMMON(dev); info = APIC_COMMON_GET_CLASS(s); info->set_tpr(s, val); } -uint8_t cpu_get_apic_tpr(DeviceState *dev) +uint8_t cpu_get_apic_tpr(APICCommonState *s) { - APICCommonState *s; APICCommonClass *info; - if (!dev) { + if (!s) { return 0; } - s = APIC_COMMON(dev); info = APIC_COMMON_GET_CLASS(s); return info->get_tpr(s); } -void apic_enable_tpr_access_reporting(DeviceState *dev, bool enable) +void apic_enable_tpr_access_reporting(APICCommonState *s, bool enable) { - APICCommonState *s = APIC_COMMON(dev); APICCommonClass *info = APIC_COMMON_GET_CLASS(s); apic_report_tpr_access = enable; @@ -116,26 +105,22 @@ void apic_enable_tpr_access_reporting(DeviceState *dev, bool enable) } } -void apic_enable_vapic(DeviceState *dev, hwaddr paddr) +void apic_enable_vapic(APICCommonState *s, hwaddr paddr) { - APICCommonState *s = APIC_COMMON(dev); APICCommonClass *info = APIC_COMMON_GET_CLASS(s); s->vapic_paddr = paddr; info->vapic_base_update(s); } -void apic_handle_tpr_access_report(DeviceState *dev, target_ulong ip, +void apic_handle_tpr_access_report(APICCommonState *s, target_ulong ip, TPRAccess access) { - APICCommonState *s = APIC_COMMON(dev); - vapic_report_tpr_access(s->vapic, CPU(s->cpu), ip, access); } -void apic_deliver_nmi(DeviceState *dev) +void apic_deliver_nmi(APICCommonState *s) { - APICCommonState *s = APIC_COMMON(dev); APICCommonClass *info = APIC_COMMON_GET_CLASS(s); info->external_nmi(s); @@ -193,16 +178,14 @@ uint32_t apic_get_current_count(APICCommonState *s) return val; } -void apic_init_reset(DeviceState *dev) +void apic_init_reset(APICCommonState *s) { - APICCommonState *s; APICCommonClass *info; int i; - if (!dev) { + if (!s) { return; } - s = APIC_COMMON(dev); s->tpr = 0; s->spurious_vec = 0xff; s->log_dest = 0; @@ -233,13 +216,12 @@ void apic_init_reset(DeviceState *dev) } } -void apic_designate_bsp(DeviceState *dev, bool bsp) +void apic_designate_bsp(APICCommonState *s, bool bsp) { - if (dev == NULL) { + if (s == NULL) { return; } - APICCommonState *s = APIC_COMMON(dev); if (bsp) { s->apicbase |= MSR_IA32_APICBASE_BSP; } else { @@ -262,7 +244,7 @@ static void apic_reset_common(DeviceState *dev) s->vapic_paddr = 0; info->vapic_base_update(s); - apic_init_reset(dev); + apic_init_reset(s); } static const VMStateDescription vmstate_apic_common; diff --git a/include/hw/i386/apic.h b/include/hw/i386/apic.h index eb606d6076..871f142888 100644 --- a/include/hw/i386/apic.h +++ b/include/hw/i386/apic.h @@ -1,28 +1,29 @@ #ifndef APIC_H #define APIC_H +typedef struct APICCommonState APICCommonState; /* apic.c */ void apic_set_max_apic_id(uint32_t max_apic_id); -int apic_accept_pic_intr(DeviceState *s); -void apic_deliver_pic_intr(DeviceState *s, int level); -void apic_deliver_nmi(DeviceState *d); -int apic_get_interrupt(DeviceState *s); -int cpu_set_apic_base(DeviceState *s, uint64_t val); -uint64_t cpu_get_apic_base(DeviceState *s); -bool cpu_is_apic_enabled(DeviceState *s); -void cpu_set_apic_tpr(DeviceState *s, uint8_t val); -uint8_t cpu_get_apic_tpr(DeviceState *s); -void apic_init_reset(DeviceState *s); -void apic_sipi(DeviceState *s); -void apic_poll_irq(DeviceState *d); -void apic_designate_bsp(DeviceState *d, bool bsp); -int apic_get_highest_priority_irr(DeviceState *dev); +int apic_accept_pic_intr(APICCommonState *s); +void apic_deliver_pic_intr(APICCommonState *s, int level); +void apic_deliver_nmi(APICCommonState *s); +int apic_get_interrupt(APICCommonState *s); +int cpu_set_apic_base(APICCommonState *s, uint64_t val); +uint64_t cpu_get_apic_base(APICCommonState *s); +bool cpu_is_apic_enabled(APICCommonState *s); +void cpu_set_apic_tpr(APICCommonState *s, uint8_t val); +uint8_t cpu_get_apic_tpr(APICCommonState *s); +void apic_init_reset(APICCommonState *s); +void apic_sipi(APICCommonState *s); +void apic_poll_irq(APICCommonState *s); +void apic_designate_bsp(APICCommonState *s, bool bsp); +int apic_get_highest_priority_irr(APICCommonState *s); int apic_msr_read(int index, uint64_t *val); int apic_msr_write(int index, uint64_t val); -bool is_x2apic_mode(DeviceState *d); +bool is_x2apic_mode(APICCommonState *s); /* pc.c */ -DeviceState *cpu_get_current_apic(void); +APICCommonState *cpu_get_current_apic(void); #endif diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h index 429278da61..4a62fdceb4 100644 --- a/include/hw/i386/apic_internal.h +++ b/include/hw/i386/apic_internal.h @@ -22,6 +22,7 @@ #define QEMU_APIC_INTERNAL_H #include "cpu.h" +#include "hw/i386/apic.h" #include "system/memory.h" #include "qemu/timer.h" #include "target/i386/cpu-qom.h" @@ -125,8 +126,6 @@ #define VAPIC_ENABLE_BIT 0 #define VAPIC_ENABLE_MASK (1 << VAPIC_ENABLE_BIT) -typedef struct APICCommonState APICCommonState; - #define TYPE_APIC_COMMON "apic-common" typedef struct APICCommonClass APICCommonClass; DECLARE_OBJ_CHECKERS(APICCommonState, APICCommonClass, @@ -203,8 +202,8 @@ typedef struct VAPICState { extern bool apic_report_tpr_access; bool apic_next_timer(APICCommonState *s, int64_t current_time); -void apic_enable_tpr_access_reporting(DeviceState *d, bool enable); -void apic_enable_vapic(DeviceState *d, hwaddr paddr); +void apic_enable_tpr_access_reporting(APICCommonState *s, bool enable); +void apic_enable_vapic(APICCommonState *s, hwaddr paddr); void vapic_report_tpr_access(DeviceState *dev, CPUState *cpu, target_ulong ip, TPRAccess access); diff --git a/target/i386/cpu-apic.c b/target/i386/cpu-apic.c index 242a05fdbe..564c1288e4 100644 --- a/target/i386/cpu-apic.c +++ b/target/i386/cpu-apic.c @@ -41,34 +41,31 @@ APICCommonClass *apic_get_class(Error **errp) void x86_cpu_apic_create(X86CPU *cpu, Error **errp) { - APICCommonState *apic; APICCommonClass *apic_class = apic_get_class(errp); if (!apic_class) { return; } - cpu->apic_state = DEVICE(object_new_with_class(OBJECT_CLASS(apic_class))); + cpu->apic_state = APIC_COMMON(object_new_with_class(OBJECT_CLASS(apic_class))); object_property_add_child(OBJECT(cpu), "lapic", OBJECT(cpu->apic_state)); object_unref(OBJECT(cpu->apic_state)); /* TODO: convert to link<> */ - apic = APIC_COMMON(cpu->apic_state); - apic->cpu = cpu; - apic->apicbase = APIC_DEFAULT_ADDRESS | MSR_IA32_APICBASE_ENABLE; + cpu->apic_state->cpu = cpu; + cpu->apic_state->apicbase = APIC_DEFAULT_ADDRESS | MSR_IA32_APICBASE_ENABLE; /* * apic_common_set_id needs to check if the CPU has x2APIC - * feature in case APIC ID >= 255, so we need to set apic->cpu + * feature in case APIC ID >= 255, so we need to set cpu->apic_state->cpu * before setting APIC ID */ - qdev_prop_set_uint32(cpu->apic_state, "id", cpu->apic_id); + qdev_prop_set_uint32(DEVICE(cpu->apic_state), "id", cpu->apic_id); } void x86_cpu_apic_realize(X86CPU *cpu, Error **errp) { - APICCommonState *apic; static bool apic_mmio_map_once; if (cpu->apic_state == NULL) { @@ -77,12 +74,11 @@ void x86_cpu_apic_realize(X86CPU *cpu, Error **errp) qdev_realize(DEVICE(cpu->apic_state), NULL, errp); /* Map APIC MMIO area */ - apic = APIC_COMMON(cpu->apic_state); if (!apic_mmio_map_once) { memory_region_add_subregion_overlap(get_system_memory(), - apic->apicbase & + cpu->apic_state->apicbase & MSR_IA32_APICBASE_BASE, - &apic->io_memory, + &cpu->apic_state->io_memory, 0x1000); apic_mmio_map_once = true; } diff --git a/target/i386/cpu-dump.c b/target/i386/cpu-dump.c index a72ed93bd2..67bf31e0ca 100644 --- a/target/i386/cpu-dump.c +++ b/target/i386/cpu-dump.c @@ -291,7 +291,7 @@ static void dump_apic_interrupt(const char *name, uint32_t *ireg_tab, void x86_cpu_dump_local_apic_state(CPUState *cs, int flags) { X86CPU *cpu = X86_CPU(cs); - APICCommonState *s = APIC_COMMON(cpu->apic_state); + APICCommonState *s = cpu->apic_state; if (!s) { qemu_printf("local apic state not available\n"); return; diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 455caff6b2..0a66e1fec9 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -8789,7 +8789,7 @@ void x86_cpu_after_reset(X86CPU *cpu) } if (cpu->apic_state) { - device_cold_reset(cpu->apic_state); + device_cold_reset(DEVICE(cpu->apic_state)); } #endif } diff --git a/target/i386/cpu.h b/target/i386/cpu.h index ce948861a7..d0da9bfe58 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -27,6 +27,7 @@ #include "exec/cpu-defs.h" #include "exec/cpu-interrupt.h" #include "exec/memop.h" +#include "hw/i386/apic.h" #include "hw/i386/topology.h" #include "qapi/qapi-types-common.h" #include "qemu/cpu-float.h" @@ -2349,7 +2350,7 @@ struct ArchCPU { /* in order to simplify APIC support, we leave this pointer to the user */ - struct DeviceState *apic_state; + APICCommonState *apic_state; struct MemoryRegion *cpu_as_root, *cpu_as_mem, *smram; Notifier machine_done; @@ -2830,7 +2831,7 @@ bool cpu_svm_has_intercept(CPUX86State *env, uint32_t type); /* apic.c */ void cpu_report_tpr_access(CPUX86State *env, TPRAccess access); -void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip, +void apic_handle_tpr_access_report(APICCommonState *s, target_ulong ip, TPRAccess access); /* Special values for X86CPUVersion: */ diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 309f043373..f7a6ef650a 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -5029,7 +5029,7 @@ static int kvm_get_mp_state(X86CPU *cpu) static int kvm_get_apic(X86CPU *cpu) { - DeviceState *apic = cpu->apic_state; + APICCommonState *apic = cpu->apic_state; struct kvm_lapic_state kapic; int ret; diff --git a/target/i386/kvm/kvm_i386.h b/target/i386/kvm/kvm_i386.h index 5f83e8850a..5c908fdd6a 100644 --- a/target/i386/kvm/kvm_i386.h +++ b/target/i386/kvm/kvm_i386.h @@ -56,7 +56,7 @@ bool kvm_has_adjust_clock_stable(void); bool kvm_has_exception_payload(void); void kvm_synchronize_all_tsc(void); -void kvm_get_apic_state(DeviceState *d, struct kvm_lapic_state *kapic); +void kvm_get_apic_state(APICCommonState *s, struct kvm_lapic_state *kapic); void kvm_put_apicbase(X86CPU *cpu, uint64_t value); bool kvm_has_x2apic_api(void); diff --git a/target/i386/whpx/whpx-apic.c b/target/i386/whpx/whpx-apic.c index e1ef6d4e6d..afcb25843b 100644 --- a/target/i386/whpx/whpx-apic.c +++ b/target/i386/whpx/whpx-apic.c @@ -151,9 +151,8 @@ static void whpx_apic_put(CPUState *cs, run_on_cpu_data data) } } -void whpx_apic_get(DeviceState *dev) +void whpx_apic_get(APICCommonState *s) { - APICCommonState *s = APIC_COMMON(dev); CPUState *cpu = CPU(s->cpu); struct whpx_lapic_state kapic; diff --git a/target/i386/whpx/whpx-internal.h b/target/i386/whpx/whpx-internal.h index 6633e9c4ca..2dcad1f565 100644 --- a/target/i386/whpx/whpx-internal.h +++ b/target/i386/whpx/whpx-internal.h @@ -5,6 +5,8 @@ #include #include +#include "hw/i386/apic.h" + typedef enum WhpxBreakpointState { WHPX_BP_CLEARED = 0, WHPX_BP_SET_PENDING, @@ -44,7 +46,7 @@ struct whpx_state { }; extern struct whpx_state whpx_global; -void whpx_apic_get(DeviceState *s); +void whpx_apic_get(APICCommonState *s); #define WHV_E_UNKNOWN_CAPABILITY 0x80370300L From 337eece9c0a4b84cd2e34ed94b55efbad9f37a6b Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Sun, 19 Oct 2025 23:03:01 +0200 Subject: [PATCH 31/45] hw/i386/apic: Ensure own APIC use in apic_msr_{read,write} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoids the `current_cpu` global and seems more robust by not "forgetting" the own APIC and then re-determining it by cpu_get_current_apic() which uses the global. Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20251019210303.104718-9-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/intc/apic.c | 10 ++-------- include/hw/i386/apic.h | 4 ++-- target/i386/hvf/hvf.c | 4 ++-- target/i386/tcg/system/misc_helper.c | 4 ++-- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/hw/intc/apic.c b/hw/intc/apic.c index cb35c80c75..ba0eda3921 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -881,11 +881,8 @@ static uint64_t apic_mem_read(void *opaque, hwaddr addr, unsigned size) return val; } -int apic_msr_read(int index, uint64_t *val) +int apic_msr_read(APICCommonState *s, int index, uint64_t *val) { - APICCommonState *s; - - s = cpu_get_current_apic(); if (!s) { return -1; } @@ -1079,11 +1076,8 @@ static void apic_mem_write(void *opaque, hwaddr addr, uint64_t val, apic_register_write(index, val); } -int apic_msr_write(int index, uint64_t val) +int apic_msr_write(APICCommonState *s, int index, uint64_t val) { - APICCommonState *s; - - s = cpu_get_current_apic(); if (!s) { return -1; } diff --git a/include/hw/i386/apic.h b/include/hw/i386/apic.h index 871f142888..6a0933f401 100644 --- a/include/hw/i386/apic.h +++ b/include/hw/i386/apic.h @@ -19,8 +19,8 @@ void apic_sipi(APICCommonState *s); void apic_poll_irq(APICCommonState *s); void apic_designate_bsp(APICCommonState *s, bool bsp); int apic_get_highest_priority_irr(APICCommonState *s); -int apic_msr_read(int index, uint64_t *val); -int apic_msr_write(int index, uint64_t val); +int apic_msr_read(APICCommonState *s, int index, uint64_t *val); +int apic_msr_write(APICCommonState *s, int index, uint64_t val); bool is_x2apic_mode(APICCommonState *s); /* pc.c */ diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index 8445cadece..33f723a76a 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -527,7 +527,7 @@ void hvf_simulate_rdmsr(CPUState *cs) int ret; int index = (uint32_t)env->regs[R_ECX] - MSR_APIC_START; - ret = apic_msr_read(index, &val); + ret = apic_msr_read(cpu->apic_state, index, &val); if (ret < 0) { x86_emul_raise_exception(env, EXCP0D_GPF, 0); } @@ -638,7 +638,7 @@ void hvf_simulate_wrmsr(CPUState *cs) int ret; int index = (uint32_t)env->regs[R_ECX] - MSR_APIC_START; - ret = apic_msr_write(index, data); + ret = apic_msr_write(cpu->apic_state, index, data); if (ret < 0) { x86_emul_raise_exception(env, EXCP0D_GPF, 0); } diff --git a/target/i386/tcg/system/misc_helper.c b/target/i386/tcg/system/misc_helper.c index 9c3f5cc99b..0c32424d36 100644 --- a/target/i386/tcg/system/misc_helper.c +++ b/target/i386/tcg/system/misc_helper.c @@ -299,7 +299,7 @@ void helper_wrmsr(CPUX86State *env) int index = (uint32_t)env->regs[R_ECX] - MSR_APIC_START; bql_lock(); - ret = apic_msr_write(index, val); + ret = apic_msr_write(env_archcpu(env)->apic_state, index, val); bql_unlock(); if (ret < 0) { goto error; @@ -477,7 +477,7 @@ void helper_rdmsr(CPUX86State *env) int index = (uint32_t)env->regs[R_ECX] - MSR_APIC_START; bql_lock(); - ret = apic_msr_read(index, &val); + ret = apic_msr_read(x86_cpu->apic_state, index, &val); bql_unlock(); if (ret < 0) { raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC()); From e2bb6f999f44f7b5835df4a52d83fc2d7b349a14 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Sun, 19 Oct 2025 23:03:02 +0200 Subject: [PATCH 32/45] hw/intc/apic: Pass APICCommonState to apic_register_{read,write} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As per the previous patch, the APIC instance is already available in apic_msr_{read,write}, so it can be passed along. It turns out that the call to cpu_get_current_apic() is only required in apic_mem_{read,write}, so it has been moved there. Longer term, cpu_get_current_apic() could be removed entirely if apic_mem_{read,write} is tied to a CPU's local address space. Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20251019210303.104718-10-shentey@gmail.com> [PMD: Move return after apic_send_msi() in apic_mem_write()] Signed-off-by: Philippe Mathieu-Daudé --- hw/intc/apic.c | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/hw/intc/apic.c b/hw/intc/apic.c index ba0eda3921..aad253af15 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -769,17 +769,11 @@ static void apic_timer(void *opaque) apic_timer_update(s, s->next_time); } -static int apic_register_read(int index, uint64_t *value) +static int apic_register_read(APICCommonState *s, int index, uint64_t *value) { - APICCommonState *s; uint32_t val; int ret = 0; - s = cpu_get_current_apic(); - if (!s) { - return -1; - } - switch(index) { case 0x02: /* id */ if (is_x2apic_mode(s)) { @@ -868,6 +862,7 @@ static int apic_register_read(int index, uint64_t *value) static uint64_t apic_mem_read(void *opaque, hwaddr addr, unsigned size) { + APICCommonState *s = cpu_get_current_apic(); uint64_t val; int index; @@ -875,8 +870,12 @@ static uint64_t apic_mem_read(void *opaque, hwaddr addr, unsigned size) return 0; } + if (!s) { + return -1; + } + index = (addr >> 4) & 0xff; - apic_register_read(index, &val); + apic_register_read(s, index, &val); return val; } @@ -891,7 +890,7 @@ int apic_msr_read(APICCommonState *s, int index, uint64_t *val) return -1; } - return apic_register_read(index, val); + return apic_register_read(s, index, val); } static void apic_send_msi(MSIMessage *msi) @@ -919,15 +918,8 @@ static void apic_send_msi(MSIMessage *msi) apic_deliver_irq(dest, dest_mode, delivery, vector, trigger_mode); } -static int apic_register_write(int index, uint64_t val) +static int apic_register_write(APICCommonState *s, int index, uint64_t val) { - APICCommonState *s; - - s = cpu_get_current_apic(); - if (!s) { - return -1; - } - trace_apic_register_write(index, val); switch(index) { @@ -1054,6 +1046,7 @@ static int apic_register_write(int index, uint64_t val) static void apic_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { + APICCommonState *s = cpu_get_current_apic(); int index = (addr >> 4) & 0xff; if (size < 4) { @@ -1073,7 +1066,11 @@ static void apic_mem_write(void *opaque, hwaddr addr, uint64_t val, return; } - apic_register_write(index, val); + if (!s) { + return; + } + + apic_register_write(s, index, val); } int apic_msr_write(APICCommonState *s, int index, uint64_t val) @@ -1086,7 +1083,7 @@ int apic_msr_write(APICCommonState *s, int index, uint64_t val) return -1; } - return apic_register_write(index, val); + return apic_register_write(s, index, val); } static void apic_pre_save(APICCommonState *s) From 0305ee82754aba1f312fb1fc6ad613219f697db7 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Sun, 19 Oct 2025 23:03:03 +0200 Subject: [PATCH 33/45] tests/qtest/ds1338: Reuse from_bcd() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit from_bcd() is a public API function which can be unit-tested. Reuse it to avoid code duplication. Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Fabiano Rosas Message-ID: <20251019210303.104718-11-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- tests/qtest/ds1338-test.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/qtest/ds1338-test.c b/tests/qtest/ds1338-test.c index d12424d27f..b8d0e65ec4 100644 --- a/tests/qtest/ds1338-test.c +++ b/tests/qtest/ds1338-test.c @@ -18,16 +18,12 @@ */ #include "qemu/osdep.h" +#include "qemu/bcd.h" #include "libqtest.h" #include "libqos/i2c.h" #define DS1338_ADDR 0x68 -static inline uint8_t bcd2bin(uint8_t x) -{ - return ((x) & 0x0f) + ((x) >> 4) * 10; -} - static void send_and_receive(void *obj, void *data, QGuestAllocator *alloc) { QI2CDevice *i2cdev = (QI2CDevice *)obj; @@ -39,9 +35,9 @@ static void send_and_receive(void *obj, void *data, QGuestAllocator *alloc) i2c_read_block(i2cdev, 0, resp, sizeof(resp)); /* check retrieved time against local time */ - g_assert_cmpuint(bcd2bin(resp[4]), == , tm_ptr->tm_mday); - g_assert_cmpuint(bcd2bin(resp[5]), == , 1 + tm_ptr->tm_mon); - g_assert_cmpuint(2000 + bcd2bin(resp[6]), == , 1900 + tm_ptr->tm_year); + g_assert_cmpuint(from_bcd(resp[4]), == , tm_ptr->tm_mday); + g_assert_cmpuint(from_bcd(resp[5]), == , 1 + tm_ptr->tm_mon); + g_assert_cmpuint(2000 + from_bcd(resp[6]), == , 1900 + tm_ptr->tm_year); } static void ds1338_register_nodes(void) From 047b721c60f592bdd6abbc69ed2f63316e061fe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 21 Oct 2025 13:02:32 +0400 Subject: [PATCH 34/45] hw/audio: improve error reports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The -audiodev argument is 'model=..', use same terminology. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20251021090317.425409-2-marcandre.lureau@redhat.com> [PMD: Fixed checkpatch.pl issues] Signed-off-by: Philippe Mathieu-Daudé --- hw/audio/soundhw.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/hw/audio/soundhw.c b/hw/audio/soundhw.c index d18fd9fa05..2a41e108c0 100644 --- a/hw/audio/soundhw.c +++ b/hw/audio/soundhw.c @@ -70,13 +70,13 @@ void show_valid_soundhw(void) struct soundhw *c; if (soundhw_count) { - printf("Valid sound card names (comma separated):\n"); - for (c = soundhw; c->name; ++c) { - printf ("%-11s %s\n", c->name, c->descr); - } + printf("Valid audio device model names:\n"); + for (c = soundhw; c->name; ++c) { + printf("%-11s %s\n", c->name, c->descr); + } } else { - printf("Machine has no user-selectable audio hardware " - "(it may or may not have always-present audio hardware).\n"); + printf("Machine has no user-selectable audio hardware " + "(it may or may not have always-present audio hardware).\n"); } } @@ -88,7 +88,7 @@ void select_soundhw(const char *name, const char *audiodev) struct soundhw *c; if (selected) { - error_report("only one -soundhw option is allowed"); + error_report("only one -audio option is allowed"); exit(1); } @@ -101,7 +101,7 @@ void select_soundhw(const char *name, const char *audiodev) } if (!c->name) { - error_report("Unknown sound card name `%s'", name); + error_report("Unknown audio device model `%s'", name); show_valid_soundhw(); exit(1); } @@ -140,4 +140,3 @@ void soundhw_init(void) c->init_pci(pci_bus, audiodev_id); } } - From 74d3a119ef642477a548360476c6b566a0fe6744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 21 Oct 2025 13:02:33 +0400 Subject: [PATCH 35/45] hw/audio: rename model list function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20251021090317.425409-3-marcandre.lureau@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/audio/soundhw.c | 4 ++-- include/hw/audio/soundhw.h | 2 +- system/vl.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/audio/soundhw.c b/hw/audio/soundhw.c index 2a41e108c0..63a6855635 100644 --- a/hw/audio/soundhw.c +++ b/hw/audio/soundhw.c @@ -65,7 +65,7 @@ void deprecated_register_soundhw(const char *name, const char *descr, soundhw_count++; } -void show_valid_soundhw(void) +void audio_print_available_models(void) { struct soundhw *c; @@ -102,7 +102,7 @@ void select_soundhw(const char *name, const char *audiodev) if (!c->name) { error_report("Unknown audio device model `%s'", name); - show_valid_soundhw(); + audio_print_available_models(); exit(1); } } diff --git a/include/hw/audio/soundhw.h b/include/hw/audio/soundhw.h index 474c5ff94e..83b3011083 100644 --- a/include/hw/audio/soundhw.h +++ b/include/hw/audio/soundhw.h @@ -7,7 +7,7 @@ void deprecated_register_soundhw(const char *name, const char *descr, int isa, const char *typename); void soundhw_init(void); -void show_valid_soundhw(void); +void audio_print_available_models(void); void select_soundhw(const char *name, const char *audiodev); #endif diff --git a/system/vl.c b/system/vl.c index fd98ea52d9..17bbc092c8 100644 --- a/system/vl.c +++ b/system/vl.c @@ -3078,7 +3078,7 @@ void qemu_init(int argc, char **argv) model = g_strdup(qdict_get_str(dict, "model")); qdict_del(dict, "model"); if (is_help_option(model)) { - show_valid_soundhw(); + audio_print_available_models(); exit(0); } } From 0347f9e0e1caaaf6fb6e7f53b5f90ced6a6ec5e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 21 Oct 2025 13:02:34 +0400 Subject: [PATCH 36/45] hw/audio: remove global pcspk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is no longer used since commit 6033b9ecd4 ("pc: remove -soundhw pcspk") Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20251021090317.425409-4-marcandre.lureau@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/audio/pcspk.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index f8020593b0..610a5b2162 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -61,7 +61,6 @@ struct PCSpkState { }; static const char *s_spk = "pcspk"; -static PCSpkState *pcspk_state; static inline void generate_samples(PCSpkState *s) { @@ -200,8 +199,6 @@ static void pcspk_realizefn(DeviceState *dev, Error **errp) if (s->card.state && AUD_register_card(s_spk, &s->card, errp)) { pcspk_audio_init(s); } - - pcspk_state = s; } static bool migrate_needed(void *opaque) @@ -237,7 +234,6 @@ static void pcspk_class_initfn(ObjectClass *klass, const void *data) set_bit(DEVICE_CATEGORY_SOUND, dc->categories); dc->vmsd = &vmstate_spk; device_class_set_props(dc, pcspk_properties); - /* Reason: realize sets global pcspk_state */ /* Reason: pit object link */ dc->user_creatable = false; } From 0c35f5bf86813f085e8a5053a90ebac0bc33e3ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 21 Oct 2025 13:02:35 +0400 Subject: [PATCH 37/45] hw/pcspk: use explicitly the required PIT types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20251021090317.425409-5-marcandre.lureau@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/audio/pcspk.c | 2 +- hw/timer/i8254_common.c | 6 ++---- include/hw/timer/i8254.h | 4 ++-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index 610a5b2162..9cf78ff55f 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -51,7 +51,7 @@ struct PCSpkState { uint8_t sample_buf[PCSPK_BUF_LEN]; QEMUSoundCard card; SWVoiceOut *voice; - void *pit; + PITCommonState *pit; unsigned int pit_count; unsigned int samples; unsigned int play_pos; diff --git a/hw/timer/i8254_common.c b/hw/timer/i8254_common.c index ad091594cd..419d4cd6e5 100644 --- a/hw/timer/i8254_common.c +++ b/hw/timer/i8254_common.c @@ -32,9 +32,8 @@ #include "migration/vmstate.h" /* val must be 0 or 1 */ -void pit_set_gate(ISADevice *dev, int channel, int val) +void pit_set_gate(PITCommonState *pit, int channel, int val) { - PITCommonState *pit = PIT_COMMON(dev); PITChannelState *s = &pit->channels[channel]; PITCommonClass *c = PIT_COMMON_GET_CLASS(pit); @@ -139,9 +138,8 @@ void pit_get_channel_info_common(PITCommonState *s, PITChannelState *sc, info->out = pit_get_out(sc, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); } -void pit_get_channel_info(ISADevice *dev, int channel, PITChannelInfo *info) +void pit_get_channel_info(PITCommonState *pit, int channel, PITChannelInfo *info) { - PITCommonState *pit = PIT_COMMON(dev); PITChannelState *s = &pit->channels[channel]; PITCommonClass *c = PIT_COMMON_GET_CLASS(pit); diff --git a/include/hw/timer/i8254.h b/include/hw/timer/i8254.h index 8402caad30..f7148d9286 100644 --- a/include/hw/timer/i8254.h +++ b/include/hw/timer/i8254.h @@ -75,7 +75,7 @@ static inline ISADevice *kvm_pit_init(ISABus *bus, int base) return d; } -void pit_set_gate(ISADevice *dev, int channel, int val); -void pit_get_channel_info(ISADevice *dev, int channel, PITChannelInfo *info); +void pit_set_gate(PITCommonState *pit, int channel, int val); +void pit_get_channel_info(PITCommonState *pit, int channel, PITChannelInfo *info); #endif /* HW_I8254_H */ From 64a013e18bbd02c26a7ca2b2c4c1a14d77058749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 21 Oct 2025 13:02:36 +0400 Subject: [PATCH 38/45] hw/pcspk: make 'pit' a class property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should be functionally equivalent. (for some reason, the device property was convert to an object instance property in commit 873b4d3f0571) Signed-off-by: Marc-André Lureau Message-ID: <20251021090317.425409-6-marcandre.lureau@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Philippe Mathieu-Daudé --- hw/audio/pcspk.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index 9cf78ff55f..7b716c08ef 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -182,11 +182,6 @@ static void pcspk_initfn(Object *obj) PCSpkState *s = PC_SPEAKER(obj); memory_region_init_io(&s->ioport, OBJECT(s), &pcspk_io_ops, s, "pcspk", 1); - - object_property_add_link(obj, "pit", TYPE_PIT_COMMON, - (Object **)&s->pit, - qdev_prop_allow_set_link_before_realize, - 0); } static void pcspk_realizefn(DeviceState *dev, Error **errp) @@ -224,6 +219,7 @@ static const Property pcspk_properties[] = { DEFINE_AUDIO_PROPERTIES(PCSpkState, card), DEFINE_PROP_UINT32("iobase", PCSpkState, iobase, 0x61), DEFINE_PROP_BOOL("migrate", PCSpkState, migrate, true), + DEFINE_PROP_LINK("pit", PCSpkState, pit, TYPE_PIT_COMMON, PITCommonState *), }; static void pcspk_class_initfn(ObjectClass *klass, const void *data) From 840c2c4ed9645fe729321a53d76c5abd3fecc67b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 21 Oct 2025 13:02:37 +0400 Subject: [PATCH 39/45] hw/pcspk: check the "pit" is set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't let the user create a "isa-pcspk" via -device yet (in theory, we could, and fallback on a lookup PIT), but we can add some safety checks that the property was correctly set nonetheless. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20251021090317.425409-7-marcandre.lureau@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/audio/pcspk.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index 7b716c08ef..54fcf632e6 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -189,6 +189,11 @@ static void pcspk_realizefn(DeviceState *dev, Error **errp) ISADevice *isadev = ISA_DEVICE(dev); PCSpkState *s = PC_SPEAKER(dev); + if (!s->pit) { + error_setg(errp, "pcspk: No \"pit\" set or available"); + return; + } + isa_register_ioport(isadev, &s->ioport, s->iobase); if (s->card.state && AUD_register_card(s_spk, &s->card, errp)) { From 55634cdf115f31ec26b66d622e6ea50354805b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 21 Oct 2025 13:03:02 +0400 Subject: [PATCH 40/45] hw/audio: replace AUD_log() usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AUD_log() is just printf(stderr, "prefix: "..), we can use error_report() or warn_report() appropriately instead. Ideally it should be converted to traces, but there are many places to convert, this is left for another day. Avoid bit-rot by using conditionals. The patch could be splitted if necessary. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20251021090317.425409-32-marcandre.lureau@redhat.com> [PMD: Fixed checkpatch.pl issues] Signed-off-by: Philippe Mathieu-Daudé --- hw/audio/ac97.c | 124 +++++++++++++++++++++++---------------------- hw/audio/adlib.c | 24 ++++----- hw/audio/cs4231a.c | 44 ++++++++-------- hw/audio/es1370.c | 24 ++++----- hw/audio/gus.c | 25 ++++----- hw/audio/pcspk.c | 2 +- hw/audio/sb16.c | 115 +++++++++++++++++++++-------------------- 7 files changed, 180 insertions(+), 178 deletions(-) diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c index eb7a847080..828333b66a 100644 --- a/hw/audio/ac97.c +++ b/hw/audio/ac97.c @@ -26,6 +26,7 @@ #include "qemu/module.h" #include "system/dma.h" #include "qom/object.h" +#include "qemu/error-report.h" #include "ac97.h" #define SOFT_VOLUME @@ -141,11 +142,12 @@ enum { BUP_LAST = 2 }; -#ifdef DEBUG_AC97 -#define dolog(...) AUD_log("ac97", __VA_ARGS__) -#else -#define dolog(...) -#endif +#define DEBUG_AC97 0 +#define dolog(fmt, ...) do { \ + if (DEBUG_AC97) { \ + error_report("ac97: " fmt, ##__VA_ARGS__); \ + } \ + } while (0) #define MKREGS(prefix, start) \ enum { \ @@ -190,7 +192,7 @@ static void fetch_bd(AC97LinkState *s, AC97BusMasterRegs *r) r->bd.addr = le32_to_cpu(*(uint32_t *) &b[0]) & ~3; r->bd.ctl_len = le32_to_cpu(*(uint32_t *) &b[4]); r->picb = r->bd.ctl_len & 0xffff; - dolog("bd %2d addr=0x%x ctl=0x%06x len=0x%x(%d bytes)\n", + dolog("bd %2d addr=0x%x ctl=0x%06x len=0x%x(%d bytes)", r->civ, r->bd.addr, r->bd.ctl_len >> 16, r->bd.ctl_len & 0xffff, (r->bd.ctl_len & 0xffff) << 1); } @@ -222,7 +224,7 @@ static void update_sr(AC97LinkState *s, AC97BusMasterRegs *r, uint32_t new_sr) r->sr = new_sr; - dolog("IOC%d LVB%d sr=0x%x event=%d level=%d\n", + dolog("IOC%d LVB%d sr=0x%x event=%d level=%d", r->sr & SR_BCIS, r->sr & SR_LVBCI, r->sr, event, level); if (!event) { @@ -231,11 +233,11 @@ static void update_sr(AC97LinkState *s, AC97BusMasterRegs *r, uint32_t new_sr) if (level) { s->glob_sta |= masks[r - s->bm_regs]; - dolog("set irq level=1\n"); + dolog("set irq level=1"); pci_irq_assert(&s->dev); } else { s->glob_sta &= ~masks[r - s->bm_regs]; - dolog("set irq level=0\n"); + dolog("set irq level=0"); pci_irq_deassert(&s->dev); } } @@ -256,14 +258,14 @@ static void voice_set_active(AC97LinkState *s, int bm_index, int on) break; default: - AUD_log("ac97", "invalid bm_index(%d) in voice_set_active", bm_index); + error_report("ac97: invalid bm_index(%d) in voice_set_active", bm_index); break; } } static void reset_bm_regs(AC97LinkState *s, AC97BusMasterRegs *r) { - dolog("reset_bm_regs\n"); + dolog("reset_bm_regs"); r->bdbar = 0; r->civ = 0; r->lvi = 0; @@ -281,7 +283,7 @@ static void reset_bm_regs(AC97LinkState *s, AC97BusMasterRegs *r) static void mixer_store(AC97LinkState *s, uint32_t i, uint16_t v) { if (i + 2 > sizeof(s->mixer_data)) { - dolog("mixer_store: index %d out of bounds %zd\n", + dolog("mixer_store: index %d out of bounds %zd", i, sizeof(s->mixer_data)); return; } @@ -295,7 +297,7 @@ static uint16_t mixer_load(AC97LinkState *s, uint32_t i) uint16_t val = 0xffff; if (i + 2 > sizeof(s->mixer_data)) { - dolog("mixer_load: index %d out of bounds %zd\n", + dolog("mixer_load: index %d out of bounds %zd", i, sizeof(s->mixer_data)); } else { val = s->mixer_data[i + 0] | (s->mixer_data[i + 1] << 8); @@ -460,7 +462,7 @@ static void mixer_reset(AC97LinkState *s) { uint8_t active[LAST_INDEX]; - dolog("mixer_reset\n"); + dolog("mixer_reset"); memset(s->mixer_data, 0, sizeof(s->mixer_data)); memset(active, 0, sizeof(active)); mixer_store(s, AC97_Reset, 0x0000); /* 6940 */ @@ -508,7 +510,7 @@ static void mixer_reset(AC97LinkState *s) static uint32_t nam_readb(void *opaque, uint32_t addr) { AC97LinkState *s = opaque; - dolog("U nam readb 0x%x\n", addr); + dolog("U nam readb 0x%x", addr); s->cas = 0; return ~0U; } @@ -523,7 +525,7 @@ static uint32_t nam_readw(void *opaque, uint32_t addr) static uint32_t nam_readl(void *opaque, uint32_t addr) { AC97LinkState *s = opaque; - dolog("U nam readl 0x%x\n", addr); + dolog("U nam readl 0x%x", addr); s->cas = 0; return ~0U; } @@ -535,7 +537,7 @@ static uint32_t nam_readl(void *opaque, uint32_t addr) static void nam_writeb(void *opaque, uint32_t addr, uint32_t val) { AC97LinkState *s = opaque; - dolog("U nam writeb 0x%x <- 0x%x\n", addr, val); + dolog("U nam writeb 0x%x <- 0x%x", addr, val); s->cas = 0; } @@ -563,10 +565,10 @@ static void nam_writew(void *opaque, uint32_t addr, uint32_t val) break; case AC97_Vendor_ID1: case AC97_Vendor_ID2: - dolog("Attempt to write vendor ID to 0x%x\n", val); + dolog("Attempt to write vendor ID to 0x%x", val); break; case AC97_Extended_Audio_ID: - dolog("Attempt to write extended audio ID to 0x%x\n", val); + dolog("Attempt to write extended audio ID to 0x%x", val); break; case AC97_Extended_Audio_Ctrl_Stat: if (!(val & EACS_VRA)) { @@ -579,36 +581,36 @@ static void nam_writew(void *opaque, uint32_t addr, uint32_t val) mixer_store(s, AC97_MIC_ADC_Rate, 0xbb80); open_voice(s, MC_INDEX, 48000); } - dolog("Setting extended audio control to 0x%x\n", val); + dolog("Setting extended audio control to 0x%x", val); mixer_store(s, AC97_Extended_Audio_Ctrl_Stat, val); break; case AC97_PCM_Front_DAC_Rate: if (mixer_load(s, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA) { mixer_store(s, addr, val); - dolog("Set front DAC rate to %d\n", val); + dolog("Set front DAC rate to %d", val); open_voice(s, PO_INDEX, val); } else { - dolog("Attempt to set front DAC rate to %d, but VRA is not set\n", + dolog("Attempt to set front DAC rate to %d, but VRA is not set", val); } break; case AC97_MIC_ADC_Rate: if (mixer_load(s, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRM) { mixer_store(s, addr, val); - dolog("Set MIC ADC rate to %d\n", val); + dolog("Set MIC ADC rate to %d", val); open_voice(s, MC_INDEX, val); } else { - dolog("Attempt to set MIC ADC rate to %d, but VRM is not set\n", + dolog("Attempt to set MIC ADC rate to %d, but VRM is not set", val); } break; case AC97_PCM_LR_ADC_Rate: if (mixer_load(s, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA) { mixer_store(s, addr, val); - dolog("Set front LR ADC rate to %d\n", val); + dolog("Set front LR ADC rate to %d", val); open_voice(s, PI_INDEX, val); } else { - dolog("Attempt to set LR ADC rate to %d, but VRA is not set\n", + dolog("Attempt to set LR ADC rate to %d, but VRA is not set", val); } break; @@ -630,7 +632,7 @@ static void nam_writew(void *opaque, uint32_t addr, uint32_t val) /* None of the features in these regs are emulated, so they are RO */ break; default: - dolog("U nam writew 0x%x <- 0x%x\n", addr, val); + dolog("U nam writew 0x%x <- 0x%x", addr, val); mixer_store(s, addr, val); break; } @@ -639,7 +641,7 @@ static void nam_writew(void *opaque, uint32_t addr, uint32_t val) static void nam_writel(void *opaque, uint32_t addr, uint32_t val) { AC97LinkState *s = opaque; - dolog("U nam writel 0x%x <- 0x%x\n", addr, val); + dolog("U nam writel 0x%x <- 0x%x", addr, val); s->cas = 0; } @@ -655,7 +657,7 @@ static uint32_t nabm_readb(void *opaque, uint32_t addr) switch (addr) { case CAS: - dolog("CAS %d\n", s->cas); + dolog("CAS %d", s->cas); val = s->cas; s->cas = 1; break; @@ -664,38 +666,38 @@ static uint32_t nabm_readb(void *opaque, uint32_t addr) case MC_CIV: r = &s->bm_regs[GET_BM(addr)]; val = r->civ; - dolog("CIV[%d] -> 0x%x\n", GET_BM(addr), val); + dolog("CIV[%d] -> 0x%x", GET_BM(addr), val); break; case PI_LVI: case PO_LVI: case MC_LVI: r = &s->bm_regs[GET_BM(addr)]; val = r->lvi; - dolog("LVI[%d] -> 0x%x\n", GET_BM(addr), val); + dolog("LVI[%d] -> 0x%x", GET_BM(addr), val); break; case PI_PIV: case PO_PIV: case MC_PIV: r = &s->bm_regs[GET_BM(addr)]; val = r->piv; - dolog("PIV[%d] -> 0x%x\n", GET_BM(addr), val); + dolog("PIV[%d] -> 0x%x", GET_BM(addr), val); break; case PI_CR: case PO_CR: case MC_CR: r = &s->bm_regs[GET_BM(addr)]; val = r->cr; - dolog("CR[%d] -> 0x%x\n", GET_BM(addr), val); + dolog("CR[%d] -> 0x%x", GET_BM(addr), val); break; case PI_SR: case PO_SR: case MC_SR: r = &s->bm_regs[GET_BM(addr)]; val = r->sr & 0xff; - dolog("SRb[%d] -> 0x%x\n", GET_BM(addr), val); + dolog("SRb[%d] -> 0x%x", GET_BM(addr), val); break; default: - dolog("U nabm readb 0x%x -> 0x%x\n", addr, val); + dolog("U nabm readb 0x%x -> 0x%x", addr, val); break; } return val; @@ -713,17 +715,17 @@ static uint32_t nabm_readw(void *opaque, uint32_t addr) case MC_SR: r = &s->bm_regs[GET_BM(addr)]; val = r->sr; - dolog("SR[%d] -> 0x%x\n", GET_BM(addr), val); + dolog("SR[%d] -> 0x%x", GET_BM(addr), val); break; case PI_PICB: case PO_PICB: case MC_PICB: r = &s->bm_regs[GET_BM(addr)]; val = r->picb; - dolog("PICB[%d] -> 0x%x\n", GET_BM(addr), val); + dolog("PICB[%d] -> 0x%x", GET_BM(addr), val); break; default: - dolog("U nabm readw 0x%x -> 0x%x\n", addr, val); + dolog("U nabm readw 0x%x -> 0x%x", addr, val); break; } return val; @@ -741,14 +743,14 @@ static uint32_t nabm_readl(void *opaque, uint32_t addr) case MC_BDBAR: r = &s->bm_regs[GET_BM(addr)]; val = r->bdbar; - dolog("BMADDR[%d] -> 0x%x\n", GET_BM(addr), val); + dolog("BMADDR[%d] -> 0x%x", GET_BM(addr), val); break; case PI_CIV: case PO_CIV: case MC_CIV: r = &s->bm_regs[GET_BM(addr)]; val = r->civ | (r->lvi << 8) | (r->sr << 16); - dolog("CIV LVI SR[%d] -> 0x%x, 0x%x, 0x%x\n", GET_BM(addr), + dolog("CIV LVI SR[%d] -> 0x%x, 0x%x, 0x%x", GET_BM(addr), r->civ, r->lvi, r->sr); break; case PI_PICB: @@ -756,19 +758,19 @@ static uint32_t nabm_readl(void *opaque, uint32_t addr) case MC_PICB: r = &s->bm_regs[GET_BM(addr)]; val = r->picb | (r->piv << 16) | (r->cr << 24); - dolog("PICB PIV CR[%d] -> 0x%x 0x%x 0x%x 0x%x\n", GET_BM(addr), + dolog("PICB PIV CR[%d] -> 0x%x 0x%x 0x%x 0x%x", GET_BM(addr), val, r->picb, r->piv, r->cr); break; case GLOB_CNT: val = s->glob_cnt; - dolog("glob_cnt -> 0x%x\n", val); + dolog("glob_cnt -> 0x%x", val); break; case GLOB_STA: val = s->glob_sta | GS_S0CR; - dolog("glob_sta -> 0x%x\n", val); + dolog("glob_sta -> 0x%x", val); break; default: - dolog("U nabm readl 0x%x -> 0x%x\n", addr, val); + dolog("U nabm readl 0x%x -> 0x%x", addr, val); break; } return val; @@ -795,7 +797,7 @@ static void nabm_writeb(void *opaque, uint32_t addr, uint32_t val) fetch_bd(s, r); } r->lvi = val % 32; - dolog("LVI[%d] <- 0x%x\n", GET_BM(addr), val); + dolog("LVI[%d] <- 0x%x", GET_BM(addr), val); break; case PI_CR: case PO_CR: @@ -816,7 +818,7 @@ static void nabm_writeb(void *opaque, uint32_t addr, uint32_t val) voice_set_active(s, r - s->bm_regs, 1); } } - dolog("CR[%d] <- 0x%x (cr 0x%x)\n", GET_BM(addr), val, r->cr); + dolog("CR[%d] <- 0x%x (cr 0x%x)", GET_BM(addr), val, r->cr); break; case PI_SR: case PO_SR: @@ -824,10 +826,10 @@ static void nabm_writeb(void *opaque, uint32_t addr, uint32_t val) r = &s->bm_regs[GET_BM(addr)]; r->sr |= val & ~(SR_RO_MASK | SR_WCLEAR_MASK); update_sr(s, r, r->sr & ~(val & SR_WCLEAR_MASK)); - dolog("SR[%d] <- 0x%x (sr 0x%x)\n", GET_BM(addr), val, r->sr); + dolog("SR[%d] <- 0x%x (sr 0x%x)", GET_BM(addr), val, r->sr); break; default: - dolog("U nabm writeb 0x%x <- 0x%x\n", addr, val); + dolog("U nabm writeb 0x%x <- 0x%x", addr, val); break; } } @@ -844,10 +846,10 @@ static void nabm_writew(void *opaque, uint32_t addr, uint32_t val) r = &s->bm_regs[GET_BM(addr)]; r->sr |= val & ~(SR_RO_MASK | SR_WCLEAR_MASK); update_sr(s, r, r->sr & ~(val & SR_WCLEAR_MASK)); - dolog("SR[%d] <- 0x%x (sr 0x%x)\n", GET_BM(addr), val, r->sr); + dolog("SR[%d] <- 0x%x (sr 0x%x)", GET_BM(addr), val, r->sr); break; default: - dolog("U nabm writew 0x%x <- 0x%x\n", addr, val); + dolog("U nabm writew 0x%x <- 0x%x", addr, val); break; } } @@ -863,22 +865,22 @@ static void nabm_writel(void *opaque, uint32_t addr, uint32_t val) case MC_BDBAR: r = &s->bm_regs[GET_BM(addr)]; r->bdbar = val & ~3; - dolog("BDBAR[%d] <- 0x%x (bdbar 0x%x)\n", GET_BM(addr), val, r->bdbar); + dolog("BDBAR[%d] <- 0x%x (bdbar 0x%x)", GET_BM(addr), val, r->bdbar); break; case GLOB_CNT: /* TODO: Handle WR or CR being set (warm/cold reset requests) */ if (!(val & (GC_WR | GC_CR))) { s->glob_cnt = val & GC_VALID_MASK; } - dolog("glob_cnt <- 0x%x (glob_cnt 0x%x)\n", val, s->glob_cnt); + dolog("glob_cnt <- 0x%x (glob_cnt 0x%x)", val, s->glob_cnt); break; case GLOB_STA: s->glob_sta &= ~(val & GS_WCLEAR_MASK); s->glob_sta |= (val & ~(GS_WCLEAR_MASK | GS_RO_MASK)) & GS_VALID_MASK; - dolog("glob_sta <- 0x%x (glob_sta 0x%x)\n", val, s->glob_sta); + dolog("glob_sta <- 0x%x (glob_sta 0x%x)", val, s->glob_sta); break; default: - dolog("U nabm writel 0x%x <- 0x%x\n", addr, val); + dolog("U nabm writel 0x%x <- 0x%x", addr, val); break; } } @@ -903,7 +905,7 @@ static int write_audio(AC97LinkState *s, AC97BusMasterRegs *r, to_copy = MIN(temp, sizeof(tmpbuf)); pci_dma_read(&s->dev, addr, tmpbuf, to_copy); copied = AUD_write(s->voice_po, tmpbuf, to_copy); - dolog("write_audio max=%x to_copy=%x copied=%x\n", + dolog("write_audio max=%x to_copy=%x copied=%x", max, to_copy, copied); if (!copied) { *stop = 1; @@ -916,7 +918,7 @@ static int write_audio(AC97LinkState *s, AC97BusMasterRegs *r, if (!temp) { if (to_copy < 4) { - dolog("whoops\n"); + dolog("whoops"); s->last_samp = 0; } else { s->last_samp = *(uint32_t *)&tmpbuf[to_copy - 4]; @@ -929,7 +931,7 @@ static int write_audio(AC97LinkState *s, AC97BusMasterRegs *r, static void write_bup(AC97LinkState *s, int elapsed) { - dolog("write_bup\n"); + dolog("write_bup"); if (!(s->bup_flag & BUP_SET)) { if (s->bup_flag & BUP_LAST) { int i; @@ -997,7 +999,7 @@ static void transfer_audio(AC97LinkState *s, int index, int elapsed) int stop = 0; if (s->invalid_freq[index]) { - AUD_log("ac97", "attempt to use voice %d with invalid frequency %d\n", + error_report("ac97: attempt to use voice %d with invalid frequency %d", index, s->invalid_freq[index]); return; } @@ -1017,12 +1019,12 @@ static void transfer_audio(AC97LinkState *s, int index, int elapsed) int temp; if (!r->bd_valid) { - dolog("invalid bd\n"); + dolog("invalid bd"); fetch_bd(s, r); } if (!r->picb) { - dolog("fresh bd %d is empty 0x%x 0x%x\n", + dolog("fresh bd %d is empty 0x%x 0x%x", r->civ, r->bd.addr, r->bd.ctl_len); if (r->civ == r->lvi) { r->sr |= SR_DCH; /* CELV? */ @@ -1059,7 +1061,7 @@ static void transfer_audio(AC97LinkState *s, int index, int elapsed) } if (r->civ == r->lvi) { - dolog("Underrun civ (%d) == lvi (%d)\n", r->civ, r->lvi); + dolog("Underrun civ (%d) == lvi (%d)", r->civ, r->lvi); new_sr |= SR_LVBCI | SR_DCH | SR_CELV; stop = 1; diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c index 1f29a7e319..772435f04c 100644 --- a/hw/audio/adlib.c +++ b/hw/audio/adlib.c @@ -29,24 +29,24 @@ #include "audio/audio.h" #include "hw/isa/isa.h" #include "hw/qdev-properties.h" +#include "qemu/error-report.h" #include "qom/object.h" -//#define DEBUG +#define DEBUG 0 #define ADLIB_KILL_TIMERS 1 #define ADLIB_DESC "Yamaha YM3812 (OPL2)" -#ifdef DEBUG +#if DEBUG #include "qemu/timer.h" #endif -#define dolog(...) AUD_log ("adlib", __VA_ARGS__) -#ifdef DEBUG -#define ldebug(...) dolog (__VA_ARGS__) -#else -#define ldebug(...) -#endif +#define ldebug(fmt, ...) do { \ + if (DEBUG) { \ + error_report("adlib: " fmt, ##__VA_ARGS__); \ + } \ + } while (0) #include "fmopl.h" #define SHIFT 1 @@ -64,7 +64,7 @@ struct AdlibState { int enabled; int active; int bufpos; -#ifdef DEBUG +#if DEBUG int64_t exp[2]; #endif int16_t *mixbuf; @@ -92,7 +92,7 @@ static void adlib_kill_timers (AdlibState *s) delta = AUD_get_elapsed_usec_out (s->voice, &s->ats); ldebug ( - "delta = %f dexp = %f expired => %d\n", + "delta = %f dexp = %f expired => %d", delta / 1000000.0, s->dexp[i] / 1000000.0, delta >= s->dexp[i] @@ -131,7 +131,7 @@ static void timer_handler (void *opaque, int c, double interval_Sec) { AdlibState *s = opaque; unsigned n = c & 1; -#ifdef DEBUG +#if DEBUG double interval; int64_t exp; #endif @@ -142,7 +142,7 @@ static void timer_handler (void *opaque, int c, double interval_Sec) } s->ticking[n] = 1; -#ifdef DEBUG +#if DEBUG interval = NANOSECONDS_PER_SECOND * interval_Sec; exp = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + interval; s->exp[n] = exp; diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c index 6dfff202ff..7931fcfec8 100644 --- a/hw/audio/cs4231a.c +++ b/hw/audio/cs4231a.c @@ -30,7 +30,7 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "qemu/module.h" -#include "qemu/timer.h" +#include "qemu/error-report.h" #include "qapi/error.h" #include "qom/object.h" @@ -43,21 +43,21 @@ More... */ -/* #define DEBUG */ +#define DEBUG 0 /* #define DEBUG_XLAW */ static struct { int aci_counter; } conf = {1}; -#ifdef DEBUG -#define dolog(...) AUD_log ("cs4231a", __VA_ARGS__) -#else -#define dolog(...) -#endif +#define dolog(fmt, ...) do { \ + if (DEBUG) { \ + error_report("cs4231a: " fmt, ##__VA_ARGS__); \ + } \ + } while (0) -#define lwarn(...) AUD_log ("cs4231a", "warning: " __VA_ARGS__) -#define lerr(...) AUD_log ("cs4231a", "error: " __VA_ARGS__) +#define lwarn(fmt, ...) warn_report("cs4231a: " fmt, ##__VA_ARGS__) +#define lerr(fmt, ...) error_report("cs4231a: " fmt, ##__VA_ARGS__) #define CS_REGS 16 #define CS_DREGS 32 @@ -284,7 +284,7 @@ static void cs_reset_voices (CSState *s, uint32_t val) as.freq = freqs[xtal][(val >> 1) & 7]; if (as.freq == -1) { - lerr ("unsupported frequency (val=%#x)\n", val); + lerr("unsupported frequency (val=0x%x)", val); goto error; } @@ -319,11 +319,11 @@ static void cs_reset_voices (CSState *s, uint32_t val) case 7: case 4: - lerr ("attempt to use reserved format value (%#x)\n", val); + lerr("attempt to use reserved format value (0x%x)", val); goto error; case 5: - lerr ("ADPCM 4 bit IMA compatible format is not supported\n"); + lerr("ADPCM 4 bit IMA compatible format is not supported"); goto error; } @@ -393,7 +393,7 @@ static uint64_t cs_read (void *opaque, hwaddr addr, unsigned size) ret = s->regs[saddr]; break; } - dolog ("read %d:%d -> %d\n", saddr, iaddr, ret); + dolog("read %d:%d -> %d", saddr, iaddr, ret); return ret; } @@ -425,7 +425,7 @@ static void cs_write (void *opaque, hwaddr addr, case RESERVED: case RESERVED_2: case RESERVED_3: - lwarn ("attempt to write %#x to reserved indirect register %d\n", + lwarn("attempt to write 0x%x to reserved indirect register %d", val, iaddr); break; @@ -439,7 +439,7 @@ static void cs_write (void *opaque, hwaddr addr, cs_reset_voices (s, val); } else { - lwarn ("[P]MCE(%#x, %#x) is not set, val=%#x\n", + lwarn("[P]MCE(0x%x, 0x%x) is not set, val=0x%x", s->regs[Index_Address], s->dregs[Alternate_Feature_Status], val); @@ -453,7 +453,7 @@ static void cs_write (void *opaque, hwaddr addr, val &= ~(1 << 5); /* D5 is reserved */ s->dregs[iaddr] = val; if (val & PPIO) { - lwarn ("PIO is not supported (%#x)\n", val); + lwarn("PIO is not supported (0x%x)", val); break; } if (val & PEN) { @@ -472,11 +472,11 @@ static void cs_write (void *opaque, hwaddr addr, break; case Error_Status_And_Initialization: - lwarn ("attempt to write to read only register %d\n", iaddr); + lwarn("attempt to write to read only register %d", iaddr); break; case MODE_And_ID: - dolog ("val=%#x\n", val); + dolog("val=0x%x", val); if (val & MODE2) s->dregs[iaddr] |= MODE2; else @@ -485,7 +485,7 @@ static void cs_write (void *opaque, hwaddr addr, case Alternate_Feature_Enable_I: if (val & TE) - lerr ("timer is not yet supported\n"); + lerr("timer is not yet supported"); s->dregs[iaddr] = val; break; @@ -499,7 +499,7 @@ static void cs_write (void *opaque, hwaddr addr, break; case Version_Chip_ID: - lwarn ("write to Version_Chip_ID register %#x\n", val); + lwarn("write to Version_Chip_ID register 0x%x", val); s->dregs[iaddr] = val; break; @@ -507,7 +507,7 @@ static void cs_write (void *opaque, hwaddr addr, s->dregs[iaddr] = val; break; } - dolog ("written value %#x to indirect register %d\n", val, iaddr); + dolog("written value 0x%x to indirect register %d", val, iaddr); break; case Status: @@ -519,7 +519,7 @@ static void cs_write (void *opaque, hwaddr addr, break; case PIO_Data: - lwarn ("attempt to write value %#x to PIO register\n", val); + lwarn("attempt to write value 0x%x to PIO register", val); break; } } diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c index a6a32a6348..6b0da0746e 100644 --- a/hw/audio/es1370.c +++ b/hw/audio/es1370.c @@ -32,7 +32,7 @@ #include "migration/vmstate.h" #include "qemu/cutils.h" #include "qemu/module.h" -#include "system/dma.h" +#include "qemu/error-report.h" #include "qom/object.h" #include "trace.h" @@ -190,7 +190,7 @@ static void print_ctl(uint32_t val) a(CDC_EN); a(SERR_DIS); #undef a - AUD_log("es1370", "ctl - PCLKDIV %d(DAC2 freq %d), freq %d,%s\n", + error_report("es1370: ctl - PCLKDIV %d(DAC2 freq %d), freq %d,%s", (val & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV, DAC2_DIVTOSR((val & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV), dac1_samplerate[(val & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL], @@ -226,7 +226,7 @@ static void print_sctl(uint32_t val) } #undef b #undef a - AUD_log("es1370", + error_report("es1370: " "%s p2_end_inc %d, p2_st_inc %d," " r1_fmt %s, p2_fmt %s, p1_fmt %s\n", buf, @@ -238,10 +238,10 @@ static void print_sctl(uint32_t val) } } -#define lwarn(...) \ +#define lwarn(fmt, ...) \ do { \ if (VERBOSE_ES1370) { \ - AUD_log("es1370: warning", __VA_ARGS__); \ + error_report("es1370: " fmt, ##__VA_ARGS__); \ } \ } while (0) @@ -502,10 +502,10 @@ static void es1370_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) break; case ES1370_REG_PHANTOM_FRAMECNT: - lwarn("writing to phantom frame count 0x%" PRIx64 "\n", val); + lwarn("writing to phantom frame count 0x%" PRIx64, val); break; case ES1370_REG_PHANTOM_FRAMEADR: - lwarn("writing to phantom frame address 0x%" PRIx64 "\n", val); + lwarn("writing to phantom frame address 0x%" PRIx64, val); break; case ES1370_REG_ADC_FRAMECNT: @@ -522,7 +522,7 @@ static void es1370_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) break; default: - lwarn("writel 0x%" PRIx64 " <- 0x%" PRIx64 "\n", addr, val); + lwarn("writel 0x%" PRIx64 " <- 0x%" PRIx64, addr, val); break; } } @@ -586,16 +586,16 @@ static uint64_t es1370_read(void *opaque, hwaddr addr, unsigned size) case ES1370_REG_PHANTOM_FRAMECNT: val = ~0U; - lwarn("reading from phantom frame count\n"); + lwarn("reading from phantom frame count"); break; case ES1370_REG_PHANTOM_FRAMEADR: val = ~0U; - lwarn("reading from phantom frame address\n"); + lwarn("reading from phantom frame address"); break; default: val = ~0U; - lwarn("readl 0x%" PRIx64 " -> 0x%x\n", addr, val); + lwarn("readl 0x%" PRIx64 " -> 0x%x", addr, val); break; } return val; @@ -677,7 +677,7 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel, * when the sample count reaches zero) or 1 for stop mode (set * interrupt and stop recording). */ - AUD_log ("es1370: warning", "non looping mode\n"); + warn_report("es1370: non looping mode"); } else { d->frame_cnt = size; diff --git a/hw/audio/gus.c b/hw/audio/gus.c index c36df0240f..91d07e0f81 100644 --- a/hw/audio/gus.c +++ b/hw/audio/gus.c @@ -32,15 +32,16 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "gusemu.h" -#include "gustate.h" +#include "qemu/error-report.h" #include "qom/object.h" -#define dolog(...) AUD_log ("audio", __VA_ARGS__) -#ifdef DEBUG -#define ldebug(...) dolog (__VA_ARGS__) -#else -#define ldebug(...) -#endif +#define DEBUG 0 + +#define ldebug(fmt, ...) do { \ + if (DEBUG) { \ + error_report("gus: " fmt, ##__VA_ARGS__); \ + } \ + } while (0) #define TYPE_GUS "gus" OBJECT_DECLARE_SIMPLE_TYPE(GUSState, GUS) @@ -154,14 +155,14 @@ int GUS_irqrequest (GUSEmuState *emu, int hwirq, int n) /* qemu_irq_lower (s->pic); */ qemu_irq_raise (s->pic); s->irqs += n; - ldebug ("irqrequest %d %d %d\n", hwirq, n, s->irqs); + ldebug("irqrequest %d %d %d", hwirq, n, s->irqs); return n; } void GUS_irqclear (GUSEmuState *emu, int hwirq) { GUSState *s = emu->opaque; - ldebug ("irqclear %d %d\n", hwirq, s->irqs); + ldebug("irqclear %d %d", hwirq, s->irqs); qemu_irq_lower (s->pic); s->irqs -= 1; #ifdef IRQ_STORM @@ -175,7 +176,7 @@ void GUS_dmarequest (GUSEmuState *emu) { GUSState *s = emu->opaque; IsaDmaClass *k = ISADMA_GET_CLASS(s->isa_dma); - ldebug ("dma request %d\n", der->gusdma); + ldebug("dma request %d", s->emu.gusdma); k->hold_DREQ(s->isa_dma, s->emu.gusdma); } @@ -186,13 +187,13 @@ static int GUS_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len) QEMU_UNINITIALIZED char tmpbuf[4096]; int pos = dma_pos, mode, left = dma_len - dma_pos; - ldebug ("read DMA %#x %d\n", dma_pos, dma_len); + ldebug("read DMA 0x%x %d", dma_pos, dma_len); mode = k->has_autoinitialization(s->isa_dma, s->emu.gusdma); while (left) { int to_copy = MIN ((size_t) left, sizeof (tmpbuf)); int copied; - ldebug ("left=%d to_copy=%d pos=%d\n", left, to_copy, pos); + ldebug("left=%d to_copy=%d pos=%d", left, to_copy, pos); copied = k->read_memory(s->isa_dma, nchan, tmpbuf, pos, to_copy); gus_dma_transferdata (&s->emu, tmpbuf, copied, left == copied); left -= copied; diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index 54fcf632e6..a719912872 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -125,7 +125,7 @@ static int pcspk_audio_init(PCSpkState *s) s->voice = AUD_open_out(&s->card, s->voice, s_spk, s, pcspk_callback, &as); if (!s->voice) { - AUD_log(s_spk, "Could not open voice\n"); + error_report("pcspk: Could not open voice"); return -1; } diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c index bac64118fe..03c82f2777 100644 --- a/hw/audio/sb16.c +++ b/hw/audio/sb16.c @@ -30,22 +30,21 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "qemu/timer.h" +#include "qemu/error-report.h" #include "qemu/host-utils.h" #include "qemu/log.h" #include "qemu/module.h" #include "qapi/error.h" #include "qom/object.h" -#define dolog(...) AUD_log ("sb16", __VA_ARGS__) - -/* #define DEBUG */ +#define DEBUG 0 /* #define DEBUG_SB16_MOST */ -#ifdef DEBUG -#define ldebug(...) dolog (__VA_ARGS__) -#else -#define ldebug(...) -#endif +#define ldebug(fmt, ...) do { \ + if (DEBUG) { \ + error_report("sb16: " fmt, ##__VA_ARGS__); \ + } \ + } while (0) static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; @@ -157,7 +156,7 @@ static int irq_of_magic (int magic) #if 0 static void log_dsp (SB16State *dsp) { - ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n", + ldebug("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d", dsp->fmt_stereo ? "Stereo" : "Mono", dsp->fmt_signed ? "Signed" : "Unsigned", dsp->fmt_bits, @@ -182,7 +181,7 @@ static void control (SB16State *s, int hold) IsaDmaClass *k = ISADMA_GET_CLASS(isa_dma); s->dma_running = hold; - ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma); + ldebug("hold %d high %d dma %d", hold, s->use_hdma, dma); if (hold) { k->hold_DREQ(isa_dma, dma); @@ -289,8 +288,8 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len) " alignment %d\n", s->block_size, s->align + 1); } - ldebug ("freq %d, stereo %d, sign %d, bits %d, " - "dma %d, auto %d, fifo %d, high %d\n", + ldebug("freq %d, stereo %d, sign %d, bits %d, " + "dma %d, auto %d, fifo %d, high %d", s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits, s->block_size, s->dma_auto, s->fifo, s->highspeed); @@ -337,8 +336,8 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len) s->block_size <<= s->fmt_stereo; } - ldebug ("freq %d, stereo %d, sign %d, bits %d, " - "dma %d, auto %d, fifo %d, high %d\n", + ldebug("freq %d, stereo %d, sign %d, bits %d, " + "dma %d, auto %d, fifo %d, high %d", s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits, s->block_size, s->dma_auto, s->fifo, s->highspeed); @@ -395,7 +394,7 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len) static inline void dsp_out_data (SB16State *s, uint8_t val) { - ldebug ("outdata %#x\n", val); + ldebug("outdata 0x%x", val); if ((size_t) s->out_data_len < sizeof (s->out_data)) { s->out_data[s->out_data_len++] = val; } @@ -407,18 +406,18 @@ static inline uint8_t dsp_get_data (SB16State *s) return s->in2_data[--s->in_index]; } else { - dolog ("buffer underflow\n"); + warn_report("sb16: buffer underflow"); return 0; } } static void command (SB16State *s, uint8_t cmd) { - ldebug ("command %#x\n", cmd); + ldebug("command 0x%x", cmd); if (cmd > 0xaf && cmd < 0xd0) { if (cmd & 8) { - qemu_log_mask(LOG_UNIMP, "ADC not yet supported (command %#x)\n", + qemu_log_mask(LOG_UNIMP, "ADC not yet supported (command 0x%x)\n", cmd); } @@ -427,7 +426,7 @@ static void command (SB16State *s, uint8_t cmd) case 12: break; default: - qemu_log_mask(LOG_GUEST_ERROR, "%#x wrong bits\n", cmd); + qemu_log_mask(LOG_GUEST_ERROR, "0x%x wrong bits\n", cmd); } s->needed_bytes = 3; } @@ -645,13 +644,13 @@ static void command (SB16State *s, uint8_t cmd) goto warn; default: - qemu_log_mask(LOG_UNIMP, "Unrecognized command %#x\n", cmd); + qemu_log_mask(LOG_UNIMP, "Unrecognized command 0x%x\n", cmd); break; } } if (!s->needed_bytes) { - ldebug ("\n"); + ldebug("!needed_bytes"); } exit: @@ -664,7 +663,7 @@ static void command (SB16State *s, uint8_t cmd) return; warn: - qemu_log_mask(LOG_UNIMP, "warning: command %#x,%d is not truly understood" + qemu_log_mask(LOG_UNIMP, "warning: command 0x%x,%d is not truly understood" " yet\n", cmd, s->needed_bytes); goto exit; @@ -687,7 +686,7 @@ static uint16_t dsp_get_hilo (SB16State *s) static void complete (SB16State *s) { int d0, d1, d2; - ldebug ("complete command %#x, in_index %d, needed_bytes %d\n", + ldebug("complete command 0x%x, in_index %d, needed_bytes %d", s->cmd, s->in_index, s->needed_bytes); if (s->cmd > 0xaf && s->cmd < 0xd0) { @@ -696,11 +695,11 @@ static void complete (SB16State *s) d0 = dsp_get_data (s); if (s->cmd & 8) { - dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n", + warn_report("sb16: ADC params cmd = 0x%x d0 = %d, d1 = %d, d2 = %d", s->cmd, d0, d1, d2); } else { - ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n", + ldebug("cmd = 0x%x d0 = %d, d1 = %d, d2 = %d", s->cmd, d0, d1, d2); dma_cmd (s, s->cmd, d0, d1 + (d2 << 8)); } @@ -711,13 +710,13 @@ static void complete (SB16State *s) s->csp_mode = dsp_get_data (s); s->csp_reg83r = 0; s->csp_reg83w = 0; - ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode); + ldebug("CSP command 0x04: mode=0x%x", s->csp_mode); break; case 0x05: s->csp_param = dsp_get_data (s); s->csp_value = dsp_get_data (s); - ldebug ("CSP command 0x05: param=%#x value=%#x\n", + ldebug("CSP command 0x05: param=0x%x value=0x%x", s->csp_param, s->csp_value); break; @@ -725,9 +724,9 @@ static void complete (SB16State *s) case 0x0e: d0 = dsp_get_data (s); d1 = dsp_get_data (s); - ldebug ("write CSP register %d <- %#x\n", d1, d0); + ldebug("write CSP register %d <- 0x%x", d1, d0); if (d1 == 0x83) { - ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0); + ldebug("0x83[%d] <- 0x%x", s->csp_reg83r, d0); s->csp_reg83[s->csp_reg83r % 4] = d0; s->csp_reg83r += 1; } @@ -738,10 +737,10 @@ static void complete (SB16State *s) case 0x0f: d0 = dsp_get_data (s); - ldebug ("read CSP register %#x -> %#x, mode=%#x\n", + ldebug("read CSP register 0x%x -> 0x%x, mode=0x%x", d0, s->csp_regs[d0], s->csp_mode); if (d0 == 0x83) { - ldebug ("0x83[%d] -> %#x\n", + ldebug("0x83[%d] -> 0x%x", s->csp_reg83w, s->csp_reg83[s->csp_reg83w % 4]); dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]); @@ -754,7 +753,7 @@ static void complete (SB16State *s) case 0x10: d0 = dsp_get_data (s); - dolog ("cmd 0x10 d0=%#x\n", d0); + warn_report("sb16: cmd 0x10 d0=0x%x", d0); break; case 0x14: @@ -763,7 +762,7 @@ static void complete (SB16State *s) case 0x40: s->time_const = dsp_get_data (s); - ldebug ("set time const %d\n", s->time_const); + ldebug("set time const %d", s->time_const); break; case 0x41: @@ -776,12 +775,12 @@ static void complete (SB16State *s) * http://homepages.cae.wisc.edu/~brodskye/sb16doc/sb16doc.html#SamplingRate */ s->freq = restrict_sampling_rate(dsp_get_hilo(s)); - ldebug ("set freq %d\n", s->freq); + ldebug("set freq %d", s->freq); break; case 0x48: s->block_size = dsp_get_lohi (s) + 1; - ldebug ("set dma block len %d\n", s->block_size); + ldebug("set dma block len %d", s->block_size); break; case 0x74: @@ -811,21 +810,21 @@ static void complete (SB16State *s) ); } } - ldebug ("mix silence %d %d %" PRId64 "\n", samples, bytes, ticks); + ldebug("mix silence %d %d %" PRId64, samples, bytes, ticks); } break; case 0xe0: d0 = dsp_get_data (s); s->out_data_len = 0; - ldebug ("E0 data = %#x\n", d0); + ldebug("E0 data = 0x%x", d0); dsp_out_data (s, ~d0); break; case 0xe2: -#ifdef DEBUG +#if DEBUG d0 = dsp_get_data (s); - dolog ("E2 = %#x\n", d0); + warn_report("sb16: E2 = 0x%x", d0); #endif break; @@ -835,7 +834,7 @@ static void complete (SB16State *s) case 0xf9: d0 = dsp_get_data (s); - ldebug ("command 0xf9 with %#x\n", d0); + ldebug("command 0xf9 with 0x%x", d0); switch (d0) { case 0x0e: dsp_out_data (s, 0xff); @@ -856,13 +855,13 @@ static void complete (SB16State *s) break; default: - qemu_log_mask(LOG_UNIMP, "complete: unrecognized command %#x\n", + qemu_log_mask(LOG_UNIMP, "complete: unrecognized command 0x%x\n", s->cmd); return; } } - ldebug ("\n"); + ldebug(""); s->cmd = -1; } @@ -926,7 +925,7 @@ static void dsp_write(void *opaque, uint32_t nport, uint32_t val) iport = nport - s->port; - ldebug ("write %#x <- %#x\n", nport, val); + ldebug("write 0x%x <- 0x%x", nport, val); switch (iport) { case 0x06: switch (val) { @@ -976,7 +975,7 @@ static void dsp_write(void *opaque, uint32_t nport, uint32_t val) } else { if (s->in_index == sizeof (s->in2_data)) { - dolog ("in data overrun\n"); + warn_report("sb16: in data overrun"); } else { s->in2_data[s->in_index++] = val; @@ -992,7 +991,7 @@ static void dsp_write(void *opaque, uint32_t nport, uint32_t val) break; default: - ldebug ("(nport=%#x, val=%#x)\n", nport, val); + ldebug("(nport=0x%x, val=0x%x)", nport, val); break; } } @@ -1016,7 +1015,7 @@ static uint32_t dsp_read(void *opaque, uint32_t nport) } else { if (s->cmd != -1) { - dolog ("empty output buffer for command %#x\n", + warn_report("sb16: empty output buffer for command 0x%x", s->cmd); } retval = s->last_read_byte; @@ -1029,7 +1028,7 @@ static uint32_t dsp_read(void *opaque, uint32_t nport) break; case 0x0d: /* timer interrupt clear */ - /* dolog ("timer interrupt clear\n"); */ + /* warn_report("sb16: timer interrupt clear"); */ retval = 0; break; @@ -1056,13 +1055,13 @@ static uint32_t dsp_read(void *opaque, uint32_t nport) } if (!ack) { - ldebug ("read %#x -> %#x\n", nport, retval); + ldebug("read 0x%x -> 0x%x", nport, retval); } return retval; error: - dolog ("warning: dsp_read %#x error\n", nport); + warn_report("sb16: dsp_read 0x%x error", nport); return 0xff; } @@ -1108,7 +1107,7 @@ static void mixer_write_datab(void *opaque, uint32_t nport, uint32_t val) SB16State *s = opaque; (void) nport; - ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val); + ldebug("mixer_write [0x%x] <- 0x%x", s->mixer_nreg, val); switch (s->mixer_nreg) { case 0x00: @@ -1118,7 +1117,7 @@ static void mixer_write_datab(void *opaque, uint32_t nport, uint32_t val) case 0x80: { int irq = irq_of_magic (val); - ldebug ("setting irq to %d (val=%#x)\n", irq, val); + ldebug("setting irq to %d (val=0x%x)", irq, val); if (irq > 0) { s->irq = irq; } @@ -1133,7 +1132,7 @@ static void mixer_write_datab(void *opaque, uint32_t nport, uint32_t val) hdma = ctz32 (val & 0xf0); if (dma != s->dma || hdma != s->hdma) { qemu_log_mask(LOG_GUEST_ERROR, "attempt to change DMA 8bit" - " %d(%d), 16bit %d(%d) (val=%#x)\n", dma, s->dma, + " %d(%d), 16bit %d(%d) (val=0x%x)\n", dma, s->dma, hdma, s->hdma, val); } #if 0 @@ -1145,12 +1144,12 @@ static void mixer_write_datab(void *opaque, uint32_t nport, uint32_t val) case 0x82: qemu_log_mask(LOG_GUEST_ERROR, "attempt to write into IRQ status" - " register (val=%#x)\n", val); + " register (val=0x%x)\n", val); return; default: if (s->mixer_nreg >= 0x80) { - ldebug ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val); + ldebug("attempt to write mixer[0x%x] <- 0x%x", s->mixer_nreg, val); } break; } @@ -1165,11 +1164,11 @@ static uint32_t mixer_read(void *opaque, uint32_t nport) (void) nport; #ifndef DEBUG_SB16_MOST if (s->mixer_nreg != 0x82) { - ldebug ("mixer_read[%#x] -> %#x\n", + ldebug("mixer_read[0x%x] -> 0x%x", s->mixer_nreg, s->mixer_regs[s->mixer_nreg]); } #else - ldebug ("mixer_read[%#x] -> %#x\n", + ldebug("mixer_read[0x%x] -> 0x%x", s->mixer_nreg, s->mixer_regs[s->mixer_nreg]); #endif return s->mixer_regs[s->mixer_nreg]; @@ -1241,7 +1240,7 @@ static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len) till = s->left_till_irq; #ifdef DEBUG_SB16_MOST - dolog ("pos:%06d %d till:%d len:%d\n", + warn_report("sb16: pos:%06d %d till:%d len:%d", dma_pos, free, till, dma_len); #endif @@ -1265,7 +1264,7 @@ static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len) } #ifdef DEBUG_SB16_MOST - ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n", + ldebug("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d", dma_pos, free, dma_len, s->left_till_irq, copy, written, s->block_size); #endif From 344c79b8ff700559dec0f871b30f09b25f0aca45 Mon Sep 17 00:00:00 2001 From: Vishal Chourasia Date: Tue, 21 Oct 2025 16:24:44 +0530 Subject: [PATCH 41/45] hw/ppc/spapr: Rename resize_hpt_err to errp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename resize_hpt_err to standard errp naming convention. Signed-off-by: Vishal Chourasia Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20251021105442.1474602-9-vishalc@linux.ibm.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/ppc/spapr.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 97ab6bebd2..e0a2e5a984 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2817,7 +2817,7 @@ static void spapr_machine_init(MachineState *machine) int i; MemoryRegion *sysmem = get_system_memory(); long load_limit, fw_size; - Error *resize_hpt_err = NULL; + Error *errp = NULL; NICInfo *nd; if (!filename) { @@ -2845,7 +2845,7 @@ static void spapr_machine_init(MachineState *machine) /* Determine capabilities to run with */ spapr_caps_init(spapr); - kvmppc_check_papr_resize_hpt(&resize_hpt_err); + kvmppc_check_papr_resize_hpt(&errp); if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) { /* * If the user explicitly requested a mode we should either @@ -2853,10 +2853,10 @@ static void spapr_machine_init(MachineState *machine) * it's not set explicitly, we reset our mode to something * that works */ - if (resize_hpt_err) { + if (errp) { spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; - error_free(resize_hpt_err); - resize_hpt_err = NULL; + error_free(errp); + errp = NULL; } else { spapr->resize_hpt = smc->resize_hpt_default; } @@ -2864,14 +2864,14 @@ static void spapr_machine_init(MachineState *machine) assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT); - if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && resize_hpt_err) { + if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && errp) { /* * User requested HPT resize, but this host can't supply it. Bail out */ - error_report_err(resize_hpt_err); + error_report_err(errp); exit(1); } - error_free(resize_hpt_err); + error_free(errp); spapr->rma_size = spapr_rma_size(spapr, &error_fatal); From 253f902d845b4ce2877b4b446c026be0dd0ea7f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 13 May 2025 12:33:29 +0100 Subject: [PATCH 42/45] qemu/target-info: Include missing 'qapi-types-common.h' header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When adding the TargetInfo::@endianness field in commit a37aec2e7d8, we neglected to include the "qapi-types-common.h" header to get the EndianMode enum definition. Fix that. Fixes: a37aec2e7d8 ("qemu/target-info: Add target_endian_mode()") Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Pierrick Bouvier Message-Id: <20251020220941.65269-10-philmd@linaro.org> --- include/qemu/target-info-impl.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/qemu/target-info-impl.h b/include/qemu/target-info-impl.h index 17887f64e2..e446585bf5 100644 --- a/include/qemu/target-info-impl.h +++ b/include/qemu/target-info-impl.h @@ -9,6 +9,7 @@ #ifndef QEMU_TARGET_INFO_IMPL_H #define QEMU_TARGET_INFO_IMPL_H +#include "qapi/qapi-types-common.h" #include "qapi/qapi-types-machine.h" typedef struct TargetInfo { From 7d82e9b56c6fad65d993a31d990fdc5792926692 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 20 Oct 2025 16:04:24 +0200 Subject: [PATCH 43/45] MAINTAINERS: Add missing machine name in the Alpha section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without a machine name here, get_maintainers.pl uses the "-----..." separator for describing what the maintainer is taking care of: $ scripts/get_maintainer.pl -f hw/alpha/dp264.c Richard Henderson (maintainer:--------------) qemu-devel@nongnu.org (open list:All patches CC here) Signed-off-by: Thomas Huth Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20251020140425.45003-1-thuth@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 667acd933c..d4e7fd965b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -671,6 +671,7 @@ F: tests/docker/dockerfiles/emsdk-wasm32-cross.docker Alpha Machines -------------- +Clipper M: Richard Henderson S: Maintained F: hw/alpha/ From ba4d0a0184cb364df98fe66d885b79427ebd0e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 21 Oct 2025 13:02:38 +0400 Subject: [PATCH 44/45] docs: update -soundhw -> -device list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (note: I wonder if pcspk was really an option when -soundhw was available, since it was not user-creatable) Signed-off-by: Marc-André Lureau Message-ID: <20251021090317.425409-8-marcandre.lureau@redhat.com> Reviewed-by: Thomas Huth Signed-off-by: Philippe Mathieu-Daudé --- docs/qdev-device-use.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/qdev-device-use.txt b/docs/qdev-device-use.txt index c98c86d828..043ae46114 100644 --- a/docs/qdev-device-use.txt +++ b/docs/qdev-device-use.txt @@ -324,8 +324,10 @@ Map from -soundhw sound card name to -device: gus -device gus,iobase=IOADDR,irq=IRQ,dma=DMA,freq=F hda -device intel-hda,msi=MSI -device hda-duplex sb16 -device sb16,iobase=IOADDR,irq=IRQ,dma=DMA,dma16=DMA16,version=V - adlib not yet available with -device - pcspk not yet available with -device + adlib -device adlib,iobase=IOADDR,freq=F + + pcspk Not available with -device, + but audiodev can be set with -machine pcspk-audiodev= For PCI devices, you can add bus=PCI-BUS,addr=DEVFN to control the PCI device address, as usual. From 274d9060664b1754a3d349af718d006ed2e70b2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 21 Oct 2025 15:11:07 +0200 Subject: [PATCH 45/45] docs: Update mentions of removed '-soundhw' command line option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `-soundhw` CLI was removed in commit 039a68373c4 ("introduce -audio as a replacement for -soundhw"). Remove outdated comments and update the document mentioning the old usage. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Marc-André Lureau Message-Id: <20251021131825.99390-2-philmd@linaro.org> --- docs/qdev-device-use.txt | 4 ++-- system/qdev-monitor.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/qdev-device-use.txt b/docs/qdev-device-use.txt index 043ae46114..fb420da2a9 100644 --- a/docs/qdev-device-use.txt +++ b/docs/qdev-device-use.txt @@ -311,9 +311,9 @@ constraints. Host and guest part of audio devices have always been separate. -The old way to define guest audio devices is -soundhw C1,... +The old way to define guest audio devices was -soundhw C1,... -The new way is to define each guest audio device separately with +The current way is to define each guest audio device separately with -device. Map from -soundhw sound card name to -device: diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c index 2ac92d0a07..ec4a2394ce 100644 --- a/system/qdev-monitor.c +++ b/system/qdev-monitor.c @@ -73,9 +73,9 @@ typedef struct QDevAlias /* Please keep this table sorted by typename. */ static const QDevAlias qdev_alias_table[] = { - { "AC97", "ac97" }, /* -soundhw name */ + { "AC97", "ac97" }, { "e1000", "e1000-82540em" }, - { "ES1370", "es1370" }, /* -soundhw name */ + { "ES1370", "es1370" }, { "ich9-ahci", "ahci" }, { "lsi53c895a", "lsi" }, { "virtio-9p-device", "virtio-9p", QEMU_ARCH_VIRTIO_MMIO },