[Qemu-devel] [PATCH qemu v2 REPOST] pci: Initialize pci_dev->name before use
This moves pci_dev->name initialization earlier so pci_dev->bus_master_as could get a name instead of an empty string. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Alexey Kardashevskiy --- Changes: v2: * fixed mistype in the commit log * added "rb" --- hw/pci/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 1e6fb88eba..05c5f75ef0 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1020,6 +1020,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, pci_dev->devfn = devfn; pci_dev->requester_id_cache = pci_req_id_cache_get(pci_dev); +pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); memory_region_init(&pci_dev->bus_master_container_region, OBJECT(pci_dev), "bus master container", UINT64_MAX); @@ -1029,7 +1030,6 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, if (qdev_hotplug) { pci_init_bus_master(pci_dev); } -pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); pci_dev->irq_state = 0; pci_config_alloc(pci_dev); -- 2.11.0
Re: [Qemu-devel] host physical address width issues/questions for x86_64
On Fri, Oct 13, 2017 at 11:14:03AM -0600, Alex Williamson wrote: > On Fri, 13 Oct 2017 18:01:44 +0100 > "Dr. David Alan Gilbert" wrote: > > > * Prasad Singamsetty (prasad.singamse...@oracle.com) wrote: > > > Hi, > > > > > > I am new to the alias. I have some questions on this subject > > > and seek some clarifications from the experts in the team. > > > I ran into a couple of issues when I tried with large configuration > > > ( >= 1TB memory, > 255 CPUs) for x86_64 guest machine. > > > > > > 1. QEMU uses the default value of 40 (TCG_PHYS_ADDR_BITS) for address > > >width if user has not specified phys-bits or host-phys-bits=true > > >property. The default value is obviously not sufficient and > > >causing guest kernel to crash if configured with >= 1TB > > >memory. Depending on the linux kernel version in the guest the > > >panic was in different code paths. The workaround is for the > > >user to specify the phys-bits property or set the property > > >host-phys-bits=true. > > > > > >QUESTIONS: > ... > > > 2. host_address_width in DMAR table structure > > > > > >In this case, the default value is set to 39 > > >(VTD_HOST_ADDRESS_WIDTH - 1). With interrupt remapping > > >enabled for the intel iommu and the guest is configured > > >with > 255 cpus and >= 1TB memory, the guest kernel hangs > > >during boot up. This need to be fixed. > > > > > >QUESTION: > > >The question here again is can we fix this to use the > > >real address width from the host as the default? > > > > I don't know DMAR stuff; chatting to Alex (cc'd) it does sound > > like that's an ommission that should be fixed. > > [CC +Peter] > > On physical hardware VT-d supports either 39 or 48 bit address widths > and generally you'd expect a sufficiently capable IOMMU to be matched > with the CPU. Seems QEMU has only implemented a lower bit width and > it should probably be forcing phys bits of the VM to 39 to match until > the extended width can be implemented. Thanks, > > Alex There were patches that tried to enable 48 bits GAW but it was not accepted somehow: https://lists.gnu.org/archive/html/qemu-devel/2016-12/msg01886.html Would this help in any way? Thanks, -- Peter Xu
Re: [Qemu-devel] [PATCH qemu v2] pci: Initialize pci_dev->name before use
On Sun, Oct 15, 2017 at 02:24:17PM +1100, Alexey Kardashevskiy wrote: > On 03/10/17 13:10, Alexey Kardashevskiy wrote: > > On 15/09/17 16:35, Alexey Kardashevskiy wrote: > >> This moves pci_dev->name initialization earlier so > >> pci_dev->bus_master_as could get a name instead of an empty string. > >> > >> Signed-off-by: Alexey Kardashevskiy > >> Reviewed-by: Philippe Mathieu-Daudé > > > > Ping? > > Ping? Pls repost while you CC me. Thanks! > > > > > > >> --- > >> Changes: > >> v2: > >> * fixed mistype in the commit log > >> * added "rb" > >> --- > >> hw/pci/pci.c | 2 +- > >> 1 file changed, 1 insertion(+), 1 deletion(-) > >> > >> diff --git a/hw/pci/pci.c b/hw/pci/pci.c > >> index 21e203b056..353195d154 100644 > >> --- a/hw/pci/pci.c > >> +++ b/hw/pci/pci.c > >> @@ -1020,6 +1020,7 @@ static PCIDevice *do_pci_register_device(PCIDevice > >> *pci_dev, PCIBus *bus, > >> > >> pci_dev->devfn = devfn; > >> pci_dev->requester_id_cache = pci_req_id_cache_get(pci_dev); > >> +pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); > >> > >> memory_region_init(&pci_dev->bus_master_container_region, > >> OBJECT(pci_dev), > >> "bus master container", UINT64_MAX); > >> @@ -1029,7 +1030,6 @@ static PCIDevice *do_pci_register_device(PCIDevice > >> *pci_dev, PCIBus *bus, > >> if (qdev_hotplug) { > >> pci_init_bus_master(pci_dev); > >> } > >> -pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); > >> pci_dev->irq_state = 0; > >> pci_config_alloc(pci_dev); > >> > >> > > > > > > > -- > Alexey
[Qemu-devel] [PULL 25/26] pc: remove useless hot_add_cpu initialisation
From: Laurent Vivier Since 4458fb3a79 (pc: Eliminate pc_default_machine_options()), hot_add_cpu is set in pc_machine_class_init(), so we don't need to set it in pc_q35_machine_options(), pc_i440fx_machine_options() and xenfv_machine_options(), except to clear it in pc_i440fx_1_4_machine_opt(). Signed-off-by: Laurent Vivier Reviewed-by: Igor Mammedov Reviewed-by: Eduardo Habkost Acked-by: Anthony PERARD Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/pc_piix.c | 2 -- hw/i386/pc_q35.c | 1 - 2 files changed, 3 deletions(-) diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 9dbcbcd..f79d5cb 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -426,7 +426,6 @@ static void pc_i440fx_machine_options(MachineClass *m) { m->family = "pc_piix"; m->desc = "Standard PC (i440FX + PIIX, 1996)"; -m->hot_add_cpu = pc_hot_add_cpu; m->default_machine_opts = "firmware=bios-256k.bin"; m->default_display = "std"; } @@ -1125,7 +1124,6 @@ static void xenfv_machine_options(MachineClass *m) m->desc = "Xen Fully-virtualized PC"; m->max_cpus = HVM_MAX_VCPUS; m->default_machine_opts = "accel=xen"; -m->hot_add_cpu = pc_hot_add_cpu; } DEFINE_PC_MACHINE(xenfv, "xenfv", pc_xen_hvm_init, diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 6c4ec4b..da3ea60 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -295,7 +295,6 @@ static void pc_q35_machine_options(MachineClass *m) { m->family = "pc_q35"; m->desc = "Standard PC (Q35 + ICH9, 2009)"; -m->hot_add_cpu = pc_hot_add_cpu; m->units_per_default_bus = 1; m->default_machine_opts = "firmware=bios-256k.bin"; m->default_display = "std"; -- MST
[Qemu-devel] [PULL 24/26] isapc: Remove unnecessary migration compatibility code
From: Eduardo Habkost We don't touch isapc when we change guest ABI and add new entries to PC_COMPAT_* or new PCMachineClass compat flags. This means isapc never guaranteed guest ABI and cross-QEMU-version live migration compatibility. There's no point in keeping code for kvm-pv-eoi and APIC ID compatibility in pc_init_isa(). Signed-off-by: Eduardo Habkost Reviewed-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/pc_piix.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 1a56465..9dbcbcd 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -378,8 +378,6 @@ static void pc_compat_0_13(MachineState *machine) static void pc_init_isa(MachineState *machine) { -x86_cpu_change_kvm_default("kvm-pv-eoi", NULL); -enable_compat_apic_id_mode(); pc_init1(machine, TYPE_I440FX_PCI_HOST_BRIDGE, TYPE_I440FX_PCI_DEVICE); } -- MST
Re: [Qemu-devel] [PATCH qemu v2] pci: Initialize pci_dev->name before use
On 15/10/17 14:31, Michael S. Tsirkin wrote: > On Sun, Oct 15, 2017 at 02:24:17PM +1100, Alexey Kardashevskiy wrote: >> On 03/10/17 13:10, Alexey Kardashevskiy wrote: >>> On 15/09/17 16:35, Alexey Kardashevskiy wrote: This moves pci_dev->name initialization earlier so pci_dev->bus_master_as could get a name instead of an empty string. Signed-off-by: Alexey Kardashevskiy Reviewed-by: Philippe Mathieu-Daudé >>> >>> Ping? >> >> Ping? > > I can't find v2 in either qemu or my personal mailbox. Few weeks ago qemu-devel@ list admins were playing with list-id, may be that's why it missed your inbox. It hit patchwork though: https://patchwork.ozlabs.org/patch/814085/ > >> >>> >>> --- Changes: v2: * fixed mistype in the commit log * added "rb" --- hw/pci/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 21e203b056..353195d154 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1020,6 +1020,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, pci_dev->devfn = devfn; pci_dev->requester_id_cache = pci_req_id_cache_get(pci_dev); +pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); memory_region_init(&pci_dev->bus_master_container_region, OBJECT(pci_dev), "bus master container", UINT64_MAX); @@ -1029,7 +1030,6 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, if (qdev_hotplug) { pci_init_bus_master(pci_dev); } -pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); pci_dev->irq_state = 0; pci_config_alloc(pci_dev); >>> >>> >> >> >> -- >> Alexey -- Alexey
Re: [Qemu-devel] [PATCH qemu v2] pci: Initialize pci_dev->name before use
On Sun, Oct 15, 2017 at 02:24:17PM +1100, Alexey Kardashevskiy wrote: > On 03/10/17 13:10, Alexey Kardashevskiy wrote: > > On 15/09/17 16:35, Alexey Kardashevskiy wrote: > >> This moves pci_dev->name initialization earlier so > >> pci_dev->bus_master_as could get a name instead of an empty string. > >> > >> Signed-off-by: Alexey Kardashevskiy > >> Reviewed-by: Philippe Mathieu-Daudé > > > > Ping? > > Ping? I can't find v2 in either qemu or my personal mailbox. > > > > > > >> --- > >> Changes: > >> v2: > >> * fixed mistype in the commit log > >> * added "rb" > >> --- > >> hw/pci/pci.c | 2 +- > >> 1 file changed, 1 insertion(+), 1 deletion(-) > >> > >> diff --git a/hw/pci/pci.c b/hw/pci/pci.c > >> index 21e203b056..353195d154 100644 > >> --- a/hw/pci/pci.c > >> +++ b/hw/pci/pci.c > >> @@ -1020,6 +1020,7 @@ static PCIDevice *do_pci_register_device(PCIDevice > >> *pci_dev, PCIBus *bus, > >> > >> pci_dev->devfn = devfn; > >> pci_dev->requester_id_cache = pci_req_id_cache_get(pci_dev); > >> +pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); > >> > >> memory_region_init(&pci_dev->bus_master_container_region, > >> OBJECT(pci_dev), > >> "bus master container", UINT64_MAX); > >> @@ -1029,7 +1030,6 @@ static PCIDevice *do_pci_register_device(PCIDevice > >> *pci_dev, PCIBus *bus, > >> if (qdev_hotplug) { > >> pci_init_bus_master(pci_dev); > >> } > >> -pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); > >> pci_dev->irq_state = 0; > >> pci_config_alloc(pci_dev); > >> > >> > > > > > > > -- > Alexey
[Qemu-devel] [PULL 19/26] xen/pt: Mark TYPE_XEN_PT_DEVICE as hybrid
From: Eduardo Habkost xen-pt doesn't set the is_express field, but is supposed to be able to handle PCI Express devices too. Mark it as hybrid. Suggested-by: Jan Beulich Signed-off-by: Eduardo Habkost Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/xen/xen_pt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c index 01df341..9bba717 100644 --- a/hw/xen/xen_pt.c +++ b/hw/xen/xen_pt.c @@ -966,6 +966,7 @@ static const TypeInfo xen_pci_passthrough_info = { .class_init = xen_pci_passthrough_class_init, .interfaces = (InterfaceInfo[]) { { INTERFACE_CONVENTIONAL_PCI_DEVICE }, +{ INTERFACE_PCIE_DEVICE }, { }, }, }; -- MST
[Qemu-devel] [PULL 18/26] pci: Add INTERFACE_CONVENTIONAL_PCI_DEVICE to Conventional PCI devices
From: Eduardo Habkost Add INTERFACE_CONVENTIONAL_PCI_DEVICE to all direct subtypes of TYPE_PCI_DEVICE, except: 1) The ones that already have INTERFACE_PCIE_DEVICE set: * base-xhci * e1000e * nvme * pvscsi * vfio-pci * virtio-pci * vmxnet3 2) base-pci-bridge Not all PCI bridges are Conventional PCI devices, so INTERFACE_CONVENTIONAL_PCI_DEVICE is added only to the subtypes that are actually Conventional PCI: * dec-21154-p2p-bridge * i82801b11-bridge * pbm-bridge * pci-bridge The direct subtypes of base-pci-bridge not touched by this patch are: * xilinx-pcie-root: Already marked as PCIe-only. * pcie-pci-bridge: Already marked as PCIe-only. * pcie-port: all non-abstract subtypes of pcie-port are already marked as PCIe-only devices. 3) megasas-base Not all megasas devices are Conventional PCI devices, so the interface names are added to the subclasses registered by megasas_register_types(), according to information in the megasas_devices[] array. "megasas-gen2" already implements INTERFACE_PCIE_DEVICE, so add INTERFACE_CONVENTIONAL_PCI_DEVICE only to "megasas". Acked-by: Alberto Garcia Acked-by: John Snow Acked-by: Anthony PERARD Signed-off-by: Eduardo Habkost Reviewed-by: David Gibson Acked-by: David Gibson Reviewed-by: Marcel Apfelbaum Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/piix4.c | 1 + hw/audio/ac97.c | 4 hw/audio/es1370.c | 4 hw/audio/intel-hda.c| 4 hw/char/serial-pci.c| 12 hw/display/cirrus_vga.c | 4 hw/display/qxl.c| 4 hw/display/sm501.c | 4 hw/display/vga-pci.c| 4 hw/display/vmware_vga.c | 4 hw/i2c/smbus_ich9.c | 4 hw/i386/amd_iommu.c | 4 hw/i386/kvm/pci-assign.c| 4 hw/i386/pc_piix.c | 4 hw/i386/xen/xen_platform.c | 4 hw/i386/xen/xen_pvdevice.c | 4 hw/ide/ich.c| 4 hw/ide/pci.c| 4 hw/ipack/tpci200.c | 4 hw/isa/i82378.c | 4 hw/isa/lpc_ich9.c | 1 + hw/isa/piix4.c | 4 hw/isa/vt82c686.c | 16 hw/mips/gt64xxx_pci.c | 4 hw/misc/edu.c | 5 + hw/misc/ivshmem.c | 4 hw/misc/macio/macio.c | 4 hw/misc/pci-testdev.c | 4 hw/net/e1000.c | 4 hw/net/eepro100.c | 4 hw/net/ne2000.c | 4 hw/net/pcnet-pci.c | 4 hw/net/rocker/rocker.c | 4 hw/net/rtl8139.c| 4 hw/net/sungem.c | 4 hw/net/sunhme.c | 4 hw/pci-bridge/dec.c | 8 hw/pci-bridge/i82801b11.c | 4 hw/pci-bridge/pci_bridge_dev.c | 1 + hw/pci-bridge/pci_expander_bridge.c | 8 hw/pci-host/apb.c | 8 hw/pci-host/bonito.c| 4 hw/pci-host/gpex.c | 4 hw/pci-host/grackle.c | 4 hw/pci-host/piix.c | 8 hw/pci-host/ppce500.c | 4 hw/pci-host/prep.c | 4 hw/pci-host/q35.c | 4 hw/pci-host/uninorth.c | 16 hw/pci-host/versatile.c | 4 hw/ppc/ppc4xx_pci.c | 4 hw/scsi/esp-pci.c | 4 hw/scsi/lsi53c895a.c| 4 hw/scsi/megasas.c | 4 hw/scsi/mptsas.c| 4 hw/sd/sdhci.c | 4 hw/sh4/sh_pci.c | 4 hw/sparc64/sun4u.c | 4 hw/usb/hcd-ehci-pci.c | 4 hw/usb/hcd-ohci.c | 4 hw/usb/hcd-uhci.c | 4 hw/vfio/pci-quirks.c| 4 hw/watchdog/wdt_i6300esb.c | 4 hw/xen/xen_pt.c | 4 64 files changed, 296 insertions(+) diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index f4fd590..a0fb1ce 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -718,6 +718,7 @@ static const TypeInfo piix4_pm_info = { .interfaces = (InterfaceInfo[]) { { TYPE_HOTPLUG_HANDLER }, { TYPE_ACPI_DEVICE_IF }, +{ INTERFACE_CONVENTIONAL_PCI_DEVICE }, { } } }; diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c index 959c786..337402e 100644 --- a/hw/audio/ac97.c +++ b/hw/audio/ac97.c @@ -1431,6 +1431,10 @@ static const TypeInfo ac97_info = { .parent= TY
[Qemu-devel] [PULL 22/26] virtio: fix descriptor counting in virtqueue_pop
From: Wolfgang Bumiller While changing the s/g list allocation, commit 3b3b0628 also changed the descriptor counting to count iovec entries as split by cpu_physical_memory_map(). Previously only the actual descriptor entries were counted and the split into the iovec happened afterwards in virtqueue_map(). Count the entries again instead to avoid erroneous "Looped descriptor" errors. Reported-by: Hans Middelhoek Link: https://forum.proxmox.com/threads/vm-crash-with-memory-hotplug.35904/ Fixes: 3b3b0628217e ("virtio: slim down allocation of VirtQueueElements") Signed-off-by: Wolfgang Bumiller Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 311929e..5884ce3 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -834,7 +834,7 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz) int64_t len; VirtIODevice *vdev = vq->vdev; VirtQueueElement *elem = NULL; -unsigned out_num, in_num; +unsigned out_num, in_num, elem_entries; hwaddr addr[VIRTQUEUE_MAX_SIZE]; struct iovec iov[VIRTQUEUE_MAX_SIZE]; VRingDesc desc; @@ -852,7 +852,7 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz) smp_rmb(); /* When we start there are none of either input nor output. */ -out_num = in_num = 0; +out_num = in_num = elem_entries = 0; max = vq->vring.num; @@ -922,7 +922,7 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz) } /* If we've got too many, that implies a descriptor loop. */ -if ((in_num + out_num) > max) { +if (++elem_entries > max) { virtio_error(vdev, "Looped descriptor"); goto err_undo_map; } -- MST
[Qemu-devel] [PULL 23/26] virtio-pci: Replace modern_as with direct access to modern_bar
From: Alexey Kardashevskiy The modern bar is accessed now via yet another address space created just for that purpose and it does not really need FlatView and dispatch tree as it has a single memory region so it is just a waste of memory. Things get even worse when there are dozens or hundreds of virtio-pci devices - since these address spaces are global, changing any of them triggers rebuilding all address spaces. This replaces indirect accesses to the modern BAR with a simple lookup and direct calls to memory_region_dispatch_read/write. This is expected to save lots of memory at boot time after applying: [Qemu-devel] [PULL 00/32] Misc changes for 2017-09-22 Signed-off-by: Alexey Kardashevskiy Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.h | 17 +++- hw/virtio/virtio-pci.c | 75 +- 2 files changed, 54 insertions(+), 38 deletions(-) diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index 69f5959..12d3a90 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -155,15 +155,18 @@ typedef struct VirtIOPCIQueue { struct VirtIOPCIProxy { PCIDevice pci_dev; MemoryRegion bar; -VirtIOPCIRegion common; -VirtIOPCIRegion isr; -VirtIOPCIRegion device; -VirtIOPCIRegion notify; -VirtIOPCIRegion notify_pio; +union { +struct { +VirtIOPCIRegion common; +VirtIOPCIRegion isr; +VirtIOPCIRegion device; +VirtIOPCIRegion notify; +VirtIOPCIRegion notify_pio; +}; +VirtIOPCIRegion regs[5]; +}; MemoryRegion modern_bar; MemoryRegion io_bar; -MemoryRegion modern_cfg; -AddressSpace modern_as; uint32_t legacy_io_bar_idx; uint32_t msix_bar_idx; uint32_t modern_io_bar_idx; diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 6c60aa0..e92837c 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -491,6 +491,24 @@ static const MemoryRegionOps virtio_pci_config_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; +static MemoryRegion *virtio_address_space_lookup(VirtIOPCIProxy *proxy, + hwaddr *off, int len) +{ +int i; +VirtIOPCIRegion *reg; + +for (i = 0; i < ARRAY_SIZE(proxy->regs); ++i) { +reg = &proxy->regs[i]; +if (*off >= reg->offset && +*off + len <= reg->offset + reg->size) { +*off -= reg->offset; +return ®->mr; +} +} + +return NULL; +} + /* Below are generic functions to do memcpy from/to an address space, * without byteswaps, with input validation. * @@ -504,63 +522,72 @@ static const MemoryRegionOps virtio_pci_config_ops = { * Note: host pointer must be aligned. */ static -void virtio_address_space_write(AddressSpace *as, hwaddr addr, +void virtio_address_space_write(VirtIOPCIProxy *proxy, hwaddr addr, const uint8_t *buf, int len) { -uint32_t val; +uint64_t val; +MemoryRegion *mr; /* address_space_* APIs assume an aligned address. * As address is under guest control, handle illegal values. */ addr &= ~(len - 1); +mr = virtio_address_space_lookup(proxy, &addr, len); +if (!mr) { +return; +} + /* Make sure caller aligned buf properly */ assert(!(((uintptr_t)buf) & (len - 1))); switch (len) { case 1: val = pci_get_byte(buf); -address_space_stb(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL); break; case 2: -val = pci_get_word(buf); -address_space_stw_le(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL); +val = cpu_to_le16(pci_get_word(buf)); break; case 4: -val = pci_get_long(buf); -address_space_stl_le(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL); +val = cpu_to_le32(pci_get_long(buf)); break; default: /* As length is under guest control, handle illegal values. */ -break; +return; } +memory_region_dispatch_write(mr, addr, val, len, MEMTXATTRS_UNSPECIFIED); } static void -virtio_address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len) +virtio_address_space_read(VirtIOPCIProxy *proxy, hwaddr addr, + uint8_t *buf, int len) { -uint32_t val; +uint64_t val; +MemoryRegion *mr; /* address_space_* APIs assume an aligned address. * As address is under guest control, handle illegal values. */ addr &= ~(len - 1); +mr = virtio_address_space_lookup(proxy, &addr, len); +if (!mr) { +return; +} + /* Make sure caller aligned buf properly */ assert(!(((uintptr_t)buf) & (len - 1))); +memory_region_dispatch_read(mr, addr, &val, len, MEMTXATTRS_UNSPECIFIED); switch (len) { case 1: -val = address_space_ldub(as, addr, MEMTXATTRS_U
[Qemu-devel] [PULL 16/26] pci: Add interface names to hybrid PCI devices
From: Eduardo Habkost The following devices support both PCI Express and Conventional PCI, by including special code to handle the QEMU_PCI_CAP_EXPRESS flag and/or conditional pcie_endpoint_cap_init() calls: * vfio-pci (is_express=1, but legacy PCI handled by vfio_populate_device()) * vmxnet3 (is_express=0, but PCIe handled by vmxnet3_realize()) * pvscsi (is_express=0, but PCIe handled by pvscsi_realize()) * virtio-pci (is_express=0, but PCIe handled by virtio_pci_dc_realize(), and additional legacy PCI code at virtio_pci_realize()) * base-xhci (is_express=1, but pcie_endpoint_cap_init() call is conditional on pci_bus_is_express(dev->bus) * Note that xhci does not clear QEMU_PCI_CAP_EXPRESS like the other hybrid devices Cc: Dmitry Fleytman Cc: Jason Wang Cc: Paolo Bonzini Cc: Gerd Hoffmann Cc: Alex Williamson Cc: "Michael S. Tsirkin" Signed-off-by: Eduardo Habkost Reviewed-by: David Gibson Reviewed-by: Marcel Apfelbaum Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/net/vmxnet3.c | 5 + hw/scsi/vmw_pvscsi.c | 2 ++ hw/usb/hcd-xhci.c | 5 + hw/vfio/pci.c | 5 + hw/virtio/virtio-pci.c | 5 + 5 files changed, 22 insertions(+) diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index b43b58b..8c4bae5 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -2653,6 +2653,11 @@ static const TypeInfo vmxnet3_info = { .instance_size = sizeof(VMXNET3State), .class_init= vmxnet3_class_init, .instance_init = vmxnet3_instance_init, +.interfaces = (InterfaceInfo[]) { +{ INTERFACE_PCIE_DEVICE }, +{ INTERFACE_CONVENTIONAL_PCI_DEVICE }, +{ } +}, }; static void vmxnet3_register_types(void) diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c index d807915..d564e5c 100644 --- a/hw/scsi/vmw_pvscsi.c +++ b/hw/scsi/vmw_pvscsi.c @@ -1302,6 +1302,8 @@ static const TypeInfo pvscsi_info = { .class_init= pvscsi_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_HOTPLUG_HANDLER }, +{ INTERFACE_PCIE_DEVICE }, +{ INTERFACE_CONVENTIONAL_PCI_DEVICE }, { } } }; diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index d75c085..af3a9d8 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -3670,6 +3670,11 @@ static const TypeInfo xhci_info = { .instance_size = sizeof(XHCIState), .class_init= xhci_class_init, .abstract = true, +.interfaces = (InterfaceInfo[]) { +{ INTERFACE_PCIE_DEVICE }, +{ INTERFACE_CONVENTIONAL_PCI_DEVICE }, +{ } +}, }; static void qemu_xhci_class_init(ObjectClass *klass, void *data) diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 9e86db7..c977ee3 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -3036,6 +3036,11 @@ static const TypeInfo vfio_pci_dev_info = { .class_init = vfio_pci_dev_class_init, .instance_init = vfio_instance_init, .instance_finalize = vfio_instance_finalize, +.interfaces = (InterfaceInfo[]) { +{ INTERFACE_PCIE_DEVICE }, +{ INTERFACE_CONVENTIONAL_PCI_DEVICE }, +{ } +}, }; static void register_vfio_pci_dev_type(void) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index f825a68..6c60aa0 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1904,6 +1904,11 @@ static const TypeInfo virtio_pci_info = { .class_init= virtio_pci_class_init, .class_size= sizeof(VirtioPCIClass), .abstract = true, +.interfaces = (InterfaceInfo[]) { +{ INTERFACE_PCIE_DEVICE }, +{ INTERFACE_CONVENTIONAL_PCI_DEVICE }, +{ } +}, }; /* virtio-blk-pci */ -- MST
[Qemu-devel] [PULL 20/26] pci: Validate interfaces on base_class_init
From: Eduardo Habkost Make sure we don't forget to add the Conventional PCI or PCI Express interface names on PCI device classes in the future. Signed-off-by: Eduardo Habkost Revieed-by: David Gibson Reviewed-by: Marcel Apfelbaum Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/pci/pci.c | 12 1 file changed, 12 insertions(+) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 1b08e18..5ed3c8d 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -2547,6 +2547,17 @@ static void pci_device_class_init(ObjectClass *klass, void *data) pc->realize = pci_default_realize; } +static void pci_device_class_base_init(ObjectClass *klass, void *data) +{ +if (!object_class_is_abstract(klass)) { +ObjectClass *conventional = +object_class_dynamic_cast(klass, INTERFACE_CONVENTIONAL_PCI_DEVICE); +ObjectClass *pcie = +object_class_dynamic_cast(klass, INTERFACE_PCIE_DEVICE); +assert(conventional || pcie); +} +} + AddressSpace *pci_device_iommu_address_space(PCIDevice *dev) { PCIBus *bus = PCI_BUS(dev->bus); @@ -2671,6 +2682,7 @@ static const TypeInfo pci_device_type_info = { .abstract = true, .class_size = sizeof(PCIDeviceClass), .class_init = pci_device_class_init, +.class_base_init = pci_device_class_base_init, }; static void pci_register_types(void) -- MST
[Qemu-devel] [PULL 14/26] PCI: PCIe access should always be little endian
From: Matt Redfearn PCIe busses are always little endian, so set the endianness of the memory region to little endian rather than native such that operations work as expected on big endian targets. Signed-off-by: Matt Redfearn Reviewed-by: Marcel Apfelbaum Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/pci/pcie_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/pci/pcie_host.c b/hw/pci/pcie_host.c index dcebf57..553db56 100644 --- a/hw/pci/pcie_host.c +++ b/hw/pci/pcie_host.c @@ -81,7 +81,7 @@ static uint64_t pcie_mmcfg_data_read(void *opaque, static const MemoryRegionOps pcie_mmcfg_ops = { .read = pcie_mmcfg_data_read, .write = pcie_mmcfg_data_write, -.endianness = DEVICE_NATIVE_ENDIAN, +.endianness = DEVICE_LITTLE_ENDIAN, }; static void pcie_host_init(Object *obj) -- MST
[Qemu-devel] [PULL 21/26] hw/gen_pcie_root_port: make IO RO 0 on IO disabled
From: Marcel Apfelbaum IO_LIMIT and IO_BASE registers should not be writable if gen_pcie_root_port's io-reserve property is set to 0. The COMMAND register should have the IO flag read only. Signed-off-by: Marcel Apfelbaum Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/pci-bridge/gen_pcie_root_port.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/hw/pci-bridge/gen_pcie_root_port.c b/hw/pci-bridge/gen_pcie_root_port.c index ed03ffc..ad4e6aa 100644 --- a/hw/pci-bridge/gen_pcie_root_port.c +++ b/hw/pci-bridge/gen_pcie_root_port.c @@ -85,6 +85,13 @@ static void gen_rp_realize(DeviceState *dev, Error **errp) rpc->parent_class.exit(d); return; } + +if (!grp->io_reserve) { +pci_word_test_and_clear_mask(d->wmask + PCI_COMMAND, + PCI_COMMAND_IO); +d->wmask[PCI_IO_BASE] = 0; +d->wmask[PCI_IO_LIMIT] = 0; +} } static const VMStateDescription vmstate_rp_dev = { -- MST
[Qemu-devel] [PULL 15/26] pci: conventional-pci-device and pci-express-device interfaces
From: Eduardo Habkost Those two interfaces will be used to indicate which device types support Conventional PCI or PCI Express buses. Management software will be able to use the qom-list-types QMP command to query that information. Signed-off-by: Eduardo Habkost Reviewed-by: David Gibson Reviewed-by: Marcel Apfelbaum Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/pci/pci.h | 6 ++ hw/pci/pci.c | 12 2 files changed, 18 insertions(+) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index aa7ef9c..8d02a0a 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -198,6 +198,12 @@ enum { #define PCI_DEVICE_GET_CLASS(obj) \ OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE) +/* Implemented by devices that can be plugged on PCI Express buses */ +#define INTERFACE_PCIE_DEVICE "pci-express-device" + +/* Implemented by devices that can be plugged on Conventional PCI buses */ +#define INTERFACE_CONVENTIONAL_PCI_DEVICE "conventional-pci-device" + typedef struct PCIINTxRoute { enum { PCI_INTX_ENABLED, diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 1e6fb88..1b08e18 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -170,6 +170,16 @@ static const TypeInfo pci_bus_info = { .class_init = pci_bus_class_init, }; +static const TypeInfo pcie_interface_info = { +.name = INTERFACE_PCIE_DEVICE, +.parent= TYPE_INTERFACE, +}; + +static const TypeInfo conventional_pci_interface_info = { +.name = INTERFACE_CONVENTIONAL_PCI_DEVICE, +.parent= TYPE_INTERFACE, +}; + static const TypeInfo pcie_bus_info = { .name = TYPE_PCIE_BUS, .parent = TYPE_PCI_BUS, @@ -2667,6 +2677,8 @@ static void pci_register_types(void) { type_register_static(&pci_bus_info); type_register_static(&pcie_bus_info); +type_register_static(&conventional_pci_interface_info); +type_register_static(&pcie_interface_info); type_register_static(&pci_device_type_info); } -- MST
[Qemu-devel] [PULL 11/26] pci: allow 32-bit PCI IO accesses to pass through the PCI bridge
From: Mark Cave-Ayland Whilst the underlying PCI bridge implementation supports 32-bit PCI IO accesses, unfortunately they are truncated at the legacy 64K limit. Signed-off-by: Mark Cave-Ayland Reviewed-by: Richard Henderson Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/pci/pci_bridge.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c index 17feae5..a47d257 100644 --- a/hw/pci/pci_bridge.c +++ b/hw/pci/pci_bridge.c @@ -379,7 +379,8 @@ void pci_bridge_initfn(PCIDevice *dev, const char *typename) sec_bus->address_space_mem = &br->address_space_mem; memory_region_init(&br->address_space_mem, OBJECT(br), "pci_bridge_pci", UINT64_MAX); sec_bus->address_space_io = &br->address_space_io; -memory_region_init(&br->address_space_io, OBJECT(br), "pci_bridge_io", 65536); +memory_region_init(&br->address_space_io, OBJECT(br), "pci_bridge_io", + UINT32_MAX); br->windows = pci_bridge_region_init(br); QLIST_INIT(&sec_bus->child); QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling); -- MST
[Qemu-devel] [PULL 17/26] pci: Add INTERFACE_PCIE_DEVICE to all PCIe devices
From: Eduardo Habkost Change all devices that set is_express=1 to implement INTERFACE_PCIE_DEVICE. Cc: Keith Busch Cc: Kevin Wolf Cc: Max Reitz Cc: Dmitry Fleytman Cc: Jason Wang Cc: "Michael S. Tsirkin" Cc: Marcel Apfelbaum Cc: Paul Burton Cc: Paolo Bonzini Cc: Hannes Reinecke Cc: qemu-bl...@nongnu.org Reviewed-by: Alistair Francis Signed-off-by: Eduardo Habkost Reviewed-by: David Gibson Reviewed-by: Marcel Apfelbaum Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/block/nvme.c| 4 hw/net/e1000e.c| 4 hw/pci-bridge/pcie_pci_bridge.c| 1 + hw/pci-bridge/pcie_root_port.c | 4 hw/pci-bridge/xio3130_downstream.c | 4 hw/pci-bridge/xio3130_upstream.c | 4 hw/pci-host/xilinx-pcie.c | 4 hw/scsi/megasas.c | 6 ++ 8 files changed, 31 insertions(+) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 9aa3269..441e21e 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -1110,6 +1110,10 @@ static const TypeInfo nvme_info = { .instance_size = sizeof(NvmeCtrl), .class_init= nvme_class_init, .instance_init = nvme_instance_init, +.interfaces = (InterfaceInfo[]) { +{ INTERFACE_PCIE_DEVICE }, +{ } +}, }; static void nvme_register_types(void) diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c index 744f0f3..f1af279 100644 --- a/hw/net/e1000e.c +++ b/hw/net/e1000e.c @@ -710,6 +710,10 @@ static const TypeInfo e1000e_info = { .instance_size = sizeof(E1000EState), .class_init = e1000e_class_init, .instance_init = e1000e_instance_init, +.interfaces = (InterfaceInfo[]) { +{ INTERFACE_PCIE_DEVICE }, +{ } +}, }; static void e1000e_register_types(void) diff --git a/hw/pci-bridge/pcie_pci_bridge.c b/hw/pci-bridge/pcie_pci_bridge.c index da562fe..a4d827c 100644 --- a/hw/pci-bridge/pcie_pci_bridge.c +++ b/hw/pci-bridge/pcie_pci_bridge.c @@ -192,6 +192,7 @@ static const TypeInfo pcie_pci_bridge_info = { .class_init = pcie_pci_bridge_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_HOTPLUG_HANDLER }, +{ INTERFACE_PCIE_DEVICE }, { }, } }; diff --git a/hw/pci-bridge/pcie_root_port.c b/hw/pci-bridge/pcie_root_port.c index 4d588cb..9b6e4ce 100644 --- a/hw/pci-bridge/pcie_root_port.c +++ b/hw/pci-bridge/pcie_root_port.c @@ -161,6 +161,10 @@ static const TypeInfo rp_info = { .class_init= rp_class_init, .abstract = true, .class_size = sizeof(PCIERootPortClass), +.interfaces = (InterfaceInfo[]) { +{ INTERFACE_PCIE_DEVICE }, +{ } +}, }; static void rp_register_types(void) diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c index 5a882b0..1e09d2a 100644 --- a/hw/pci-bridge/xio3130_downstream.c +++ b/hw/pci-bridge/xio3130_downstream.c @@ -196,6 +196,10 @@ static const TypeInfo xio3130_downstream_info = { .name = "xio3130-downstream", .parent= TYPE_PCIE_SLOT, .class_init= xio3130_downstream_class_init, +.interfaces = (InterfaceInfo[]) { +{ INTERFACE_PCIE_DEVICE }, +{ } +}, }; static void xio3130_downstream_register_types(void) diff --git a/hw/pci-bridge/xio3130_upstream.c b/hw/pci-bridge/xio3130_upstream.c index a052224..227997c 100644 --- a/hw/pci-bridge/xio3130_upstream.c +++ b/hw/pci-bridge/xio3130_upstream.c @@ -166,6 +166,10 @@ static const TypeInfo xio3130_upstream_info = { .name = "x3130-upstream", .parent= TYPE_PCIE_PORT, .class_init= xio3130_upstream_class_init, +.interfaces = (InterfaceInfo[]) { +{ INTERFACE_PCIE_DEVICE }, +{ } +}, }; static void xio3130_upstream_register_types(void) diff --git a/hw/pci-host/xilinx-pcie.c b/hw/pci-host/xilinx-pcie.c index 4613dda..7659253 100644 --- a/hw/pci-host/xilinx-pcie.c +++ b/hw/pci-host/xilinx-pcie.c @@ -317,6 +317,10 @@ static const TypeInfo xilinx_pcie_root_info = { .parent = TYPE_PCI_BRIDGE, .instance_size = sizeof(XilinxPCIERoot), .class_init = xilinx_pcie_root_class_init, +.interfaces = (InterfaceInfo[]) { +{ INTERFACE_PCIE_DEVICE }, +{ } +}, }; static void xilinx_pcie_register(void) diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 0db68aa..535ee26 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -2451,6 +2451,7 @@ typedef struct MegasasInfo { int osts; const VMStateDescription *vmsd; Property *props; +InterfaceInfo *interfaces; } MegasasInfo; static struct MegasasInfo megasas_devices[] = { @@ -2480,6 +2481,10 @@ static struct MegasasInfo megasas_devices[] = { .is_express = true, .vmsd = &vmstate_megasas_gen2, .props = megasas_properties_gen2, +.interfaces = (InterfaceInfo[]) { +{ INTERFACE_PCIE_DEVICE }, +{ } +}, } }; @
[Qemu-devel] [PULL 09/26] MAINTAINERS: add Dump maintainers
From: Marc-André Lureau Proposing myself, since I have some familiarity with the code now. Signed-off-by: Marc-André Lureau Acked-by: Laszlo Ersek Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- MAINTAINERS | 11 +++ 1 file changed, 11 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 772ac20..9cff973 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1317,6 +1317,17 @@ S: Maintained F: device_tree.c F: include/sysemu/device_tree.h +Dump +S: Supported +M: Marc-André Lureau +F: dump.c +F: hw/misc/vmcoreinfo.c +F: include/hw/misc/vmcoreinfo.h +F: include/sysemu/dump-arch.h +F: include/sysemu/dump.h +F: scripts/dump-guest-memory.py +F: stubs/dump.c + Error reporting M: Markus Armbruster S: Supported -- MST
[Qemu-devel] [PULL 12/26] hw/pci-bridge/pcie_pci_bridge: properly handle MSI unavailability case
From: Aleksandr Bezzubikov QEMU with the pcie-pci-bridge device crashes if the guest board doesn't support MSI, e.g. 'qemu-system-ppc64 -M prep -device pcie-pci-bridge'. This is caused by wrong pcie-pci-bridge instantiation error handling. This patch fixes this issue by falling back to legacy INTx if MSI is not available. Also set the bridge's 'msi' property default value to 'auto' in order to trigger errors only when user explicitly set msi=on. Reported-by: Eduardo Habkost Signed-off-by: Aleksandr Bezzubikov Reviewed-by: Marcel Apfelbaum Tested-by: Thomas Huth Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/pci-bridge/pcie_pci_bridge.c | 24 ++-- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/hw/pci-bridge/pcie_pci_bridge.c b/hw/pci-bridge/pcie_pci_bridge.c index 9aa5cc3..da562fe 100644 --- a/hw/pci-bridge/pcie_pci_bridge.c +++ b/hw/pci-bridge/pcie_pci_bridge.c @@ -65,10 +65,18 @@ static void pcie_pci_bridge_realize(PCIDevice *d, Error **errp) goto aer_error; } +Error *local_err = NULL; if (pcie_br->msi != ON_OFF_AUTO_OFF) { -rc = msi_init(d, 0, 1, true, true, errp); +rc = msi_init(d, 0, 1, true, true, &local_err); if (rc < 0) { -goto msi_error; +assert(rc == -ENOTSUP); +if (pcie_br->msi != ON_OFF_AUTO_ON) { +error_free(local_err); +} else { +/* failed to satisfy user's explicit request for MSI */ +error_propagate(errp, local_err); +goto msi_error; +} } } pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY | @@ -81,7 +89,7 @@ aer_error: pm_error: pcie_cap_exit(d); cap_error: -shpc_free(d); +shpc_cleanup(d, &pcie_br->shpc_bar); error: pci_bridge_exitfn(d); } @@ -98,7 +106,9 @@ static void pcie_pci_bridge_reset(DeviceState *qdev) { PCIDevice *d = PCI_DEVICE(qdev); pci_bridge_reset(qdev); -msi_reset(d); +if (msi_present(d)) { +msi_reset(d); +} shpc_reset(d); } @@ -106,12 +116,14 @@ static void pcie_pci_bridge_write_config(PCIDevice *d, uint32_t address, uint32_t val, int len) { pci_bridge_write_config(d, address, val, len); -msi_write_config(d, address, val, len); +if (msi_present(d)) { +msi_write_config(d, address, val, len); +} shpc_cap_write_config(d, address, val, len); } static Property pcie_pci_bridge_dev_properties[] = { -DEFINE_PROP_ON_OFF_AUTO("msi", PCIEPCIBridge, msi, ON_OFF_AUTO_ON), +DEFINE_PROP_ON_OFF_AUTO("msi", PCIEPCIBridge, msi, ON_OFF_AUTO_AUTO), DEFINE_PROP_END_OF_LIST(), }; -- MST
[Qemu-devel] [PULL 13/26] virtio/pci/migration: Convert to VMState
From: "Dr. David Alan Gilbert" Convert the 'modern_state' part of virtio-pci to modern migration macros. Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 108 + 1 file changed, 27 insertions(+), 81 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 8b0d6b6..f825a68 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -88,77 +88,19 @@ static void virtio_pci_save_config(DeviceState *d, QEMUFile *f) qemu_put_be16(f, vdev->config_vector); } -static void virtio_pci_load_modern_queue_state(VirtIOPCIQueue *vq, - QEMUFile *f) -{ -vq->num = qemu_get_be16(f); -vq->enabled = qemu_get_be16(f); -vq->desc[0] = qemu_get_be32(f); -vq->desc[1] = qemu_get_be32(f); -vq->avail[0] = qemu_get_be32(f); -vq->avail[1] = qemu_get_be32(f); -vq->used[0] = qemu_get_be32(f); -vq->used[1] = qemu_get_be32(f); -} - -static bool virtio_pci_has_extra_state(DeviceState *d) -{ -VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); - -return proxy->flags & VIRTIO_PCI_FLAG_MIGRATE_EXTRA; -} - -static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size, - VMStateField *field) -{ -VirtIOPCIProxy *proxy = pv; -int i; - -proxy->dfselect = qemu_get_be32(f); -proxy->gfselect = qemu_get_be32(f); -proxy->guest_features[0] = qemu_get_be32(f); -proxy->guest_features[1] = qemu_get_be32(f); -for (i = 0; i < VIRTIO_QUEUE_MAX; i++) { -virtio_pci_load_modern_queue_state(&proxy->vqs[i], f); -} - -return 0; -} - -static void virtio_pci_save_modern_queue_state(VirtIOPCIQueue *vq, - QEMUFile *f) -{ -qemu_put_be16(f, vq->num); -qemu_put_be16(f, vq->enabled); -qemu_put_be32(f, vq->desc[0]); -qemu_put_be32(f, vq->desc[1]); -qemu_put_be32(f, vq->avail[0]); -qemu_put_be32(f, vq->avail[1]); -qemu_put_be32(f, vq->used[0]); -qemu_put_be32(f, vq->used[1]); -} - -static int put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size, - VMStateField *field, QJSON *vmdesc) -{ -VirtIOPCIProxy *proxy = pv; -int i; - -qemu_put_be32(f, proxy->dfselect); -qemu_put_be32(f, proxy->gfselect); -qemu_put_be32(f, proxy->guest_features[0]); -qemu_put_be32(f, proxy->guest_features[1]); -for (i = 0; i < VIRTIO_QUEUE_MAX; i++) { -virtio_pci_save_modern_queue_state(&proxy->vqs[i], f); +static const VMStateDescription vmstate_virtio_pci_modern_queue_state = { +.name = "virtio_pci/modern_queue_state", +.version_id = 1, +.minimum_version_id = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT16(num, VirtIOPCIQueue), +VMSTATE_UNUSED(1), /* enabled was stored as be16 */ +VMSTATE_BOOL(enabled, VirtIOPCIQueue), +VMSTATE_UINT32_ARRAY(desc, VirtIOPCIQueue, 2), +VMSTATE_UINT32_ARRAY(avail, VirtIOPCIQueue, 2), +VMSTATE_UINT32_ARRAY(used, VirtIOPCIQueue, 2), +VMSTATE_END_OF_LIST() } - -return 0; -} - -static const VMStateInfo vmstate_info_virtio_pci_modern_state = { -.name = "virtqueue_state", -.get = get_virtio_pci_modern_state, -.put = put_virtio_pci_modern_state, }; static bool virtio_pci_modern_state_needed(void *opaque) @@ -168,21 +110,18 @@ static bool virtio_pci_modern_state_needed(void *opaque) return virtio_pci_modern(proxy); } -static const VMStateDescription vmstate_virtio_pci_modern_state = { +static const VMStateDescription vmstate_virtio_pci_modern_state_sub = { .name = "virtio_pci/modern_state", .version_id = 1, .minimum_version_id = 1, .needed = &virtio_pci_modern_state_needed, .fields = (VMStateField[]) { -{ -.name = "modern_state", -.version_id = 0, -.field_exists = NULL, -.size = 0, -.info = &vmstate_info_virtio_pci_modern_state, -.flags= VMS_SINGLE, -.offset = 0, -}, +VMSTATE_UINT32(dfselect, VirtIOPCIProxy), +VMSTATE_UINT32(gfselect, VirtIOPCIProxy), +VMSTATE_UINT32_ARRAY(guest_features, VirtIOPCIProxy, 2), +VMSTATE_STRUCT_ARRAY(vqs, VirtIOPCIProxy, VIRTIO_QUEUE_MAX, 0, + vmstate_virtio_pci_modern_queue_state, + VirtIOPCIQueue), VMSTATE_END_OF_LIST() } }; @@ -196,11 +135,18 @@ static const VMStateDescription vmstate_virtio_pci = { VMSTATE_END_OF_LIST() }, .subsections = (const VMStateDescription*[]) { -&vmstate_virtio_pci_modern_state, +&vmstate_virtio_pci_modern_state_sub, NULL } }; +static bool virtio_pci_has_extra_state(DeviceState *d) +{ +Vir
Re: [Qemu-devel] [PATCH qemu v2] pci: Initialize pci_dev->name before use
On 03/10/17 13:10, Alexey Kardashevskiy wrote: > On 15/09/17 16:35, Alexey Kardashevskiy wrote: >> This moves pci_dev->name initialization earlier so >> pci_dev->bus_master_as could get a name instead of an empty string. >> >> Signed-off-by: Alexey Kardashevskiy >> Reviewed-by: Philippe Mathieu-Daudé > > Ping? Ping? > > >> --- >> Changes: >> v2: >> * fixed mistype in the commit log >> * added "rb" >> --- >> hw/pci/pci.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/hw/pci/pci.c b/hw/pci/pci.c >> index 21e203b056..353195d154 100644 >> --- a/hw/pci/pci.c >> +++ b/hw/pci/pci.c >> @@ -1020,6 +1020,7 @@ static PCIDevice *do_pci_register_device(PCIDevice >> *pci_dev, PCIBus *bus, >> >> pci_dev->devfn = devfn; >> pci_dev->requester_id_cache = pci_req_id_cache_get(pci_dev); >> +pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); >> >> memory_region_init(&pci_dev->bus_master_container_region, >> OBJECT(pci_dev), >> "bus master container", UINT64_MAX); >> @@ -1029,7 +1030,6 @@ static PCIDevice *do_pci_register_device(PCIDevice >> *pci_dev, PCIBus *bus, >> if (qdev_hotplug) { >> pci_init_bus_master(pci_dev); >> } >> -pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); >> pci_dev->irq_state = 0; >> pci_config_alloc(pci_dev); >> >> > > -- Alexey
[Qemu-devel] [PULL 03/26] fw_cfg: add write callback
From: Marc-André Lureau Reintroduce the write callback that was removed when write support was removed in commit 023e3148567ac898c7258138f8e86c3c2bb40d07. Contrary to the previous callback implementation, the write_cb callback is called whenever a write happened, so handlers must be ready to handle partial write as necessary. Signed-off-by: Marc-André Lureau Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/nvram/fw_cfg.h | 3 +++ hw/acpi/vmgenid.c | 2 +- hw/core/loader.c | 2 +- hw/i386/acpi-build.c | 2 +- hw/isa/lpc_ich9.c | 4 ++-- hw/nvram/fw_cfg.c | 14 ++ 6 files changed, 18 insertions(+), 9 deletions(-) diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h index f50d068..7ccbae5 100644 --- a/include/hw/nvram/fw_cfg.h +++ b/include/hw/nvram/fw_cfg.h @@ -45,6 +45,7 @@ typedef struct FWCfgDmaAccess { } QEMU_PACKED FWCfgDmaAccess; typedef void (*FWCfgCallback)(void *opaque); +typedef void (*FWCfgWriteCallback)(void *opaque, off_t start, size_t len); struct FWCfgState { /*< private >*/ @@ -183,6 +184,7 @@ void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data, * @s: fw_cfg device being modified * @filename: name of new fw_cfg file item * @select_cb: callback function when selecting + * @write_cb: callback function after a write * @callback_opaque: argument to be passed into callback function * @data: pointer to start of item data * @len: size of item data @@ -202,6 +204,7 @@ void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data, */ void fw_cfg_add_file_callback(FWCfgState *s, const char *filename, FWCfgCallback select_cb, + FWCfgWriteCallback write_cb, void *callback_opaque, void *data, size_t len, bool read_only); diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c index 2876d8a..105044f 100644 --- a/hw/acpi/vmgenid.c +++ b/hw/acpi/vmgenid.c @@ -124,7 +124,7 @@ void vmgenid_add_fw_cfg(VmGenIdState *vms, FWCfgState *s, GArray *guid) fw_cfg_add_file(s, VMGENID_GUID_FW_CFG_FILE, guid->data, VMGENID_FW_CFG_SIZE); /* Create a read-write fw_cfg file for Address */ -fw_cfg_add_file_callback(s, VMGENID_ADDR_FW_CFG_FILE, NULL, NULL, +fw_cfg_add_file_callback(s, VMGENID_ADDR_FW_CFG_FILE, NULL, NULL, NULL, vms->vmgenid_addr_le, ARRAY_SIZE(vms->vmgenid_addr_le), false); } diff --git a/hw/core/loader.c b/hw/core/loader.c index 4593061..91669d6 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -1023,7 +1023,7 @@ MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len, } fw_cfg_add_file_callback(fw_cfg, fw_file_name, - fw_callback, callback_opaque, + fw_callback, NULL, callback_opaque, data, rom->datasize, read_only); } return mr; diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 2af37a9..73519ab 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2911,7 +2911,7 @@ void acpi_setup(void) build_state->rsdp = g_memdup(tables.rsdp->data, rsdp_size); fw_cfg_add_file_callback(pcms->fw_cfg, ACPI_BUILD_RSDP_FILE, - acpi_build_update, build_state, + acpi_build_update, NULL, build_state, build_state->rsdp, rsdp_size, true); build_state->rsdp_mr = NULL; } else { diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index ac8416d..de8fbb7 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -402,12 +402,12 @@ void ich9_lpc_pm_init(PCIDevice *lpc_pci, bool smm_enabled) * just link them into fw_cfg here. */ fw_cfg_add_file_callback(fw_cfg, "etc/smi/requested-features", - NULL, NULL, + NULL, NULL, NULL, lpc->smi_guest_features_le, sizeof lpc->smi_guest_features_le, false); fw_cfg_add_file_callback(fw_cfg, "etc/smi/features-ok", - smi_features_ok_callback, lpc, + smi_features_ok_callback, NULL, lpc, &lpc->smi_features_ok, sizeof lpc->smi_features_ok, true); diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index e3bd626..753ac0e 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -56,6 +56,7 @@ struct FWCfgEntry { uint8_t *data; void *callback_opaque; FWCfgCallback select_cb; +FWCfgWriteCallback write_cb; }; #define JPG_FILE 0 @@ -370,6 +371,8 @@ st
[Qemu-devel] [PULL 07/26] kdump: set vmcoreinfo location
From: Marc-André Lureau kdump header provides offset and size of the vmcoreinfo content, append it if available (skip the ELF note header). crash-7.1.9 was the first version that started looking in the vmcoreinfo data for phys_base instead of in the kdump_sub_header. Signed-off-by: Marc-André Lureau Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- dump.c | 24 1 file changed, 24 insertions(+) diff --git a/dump.c b/dump.c index 5674512..d4a8c94 100644 --- a/dump.c +++ b/dump.c @@ -857,6 +857,18 @@ static void create_header32(DumpState *s, Error **errp) kh->dump_level = cpu_to_dump32(s, DUMP_LEVEL); offset_note = DISKDUMP_HEADER_BLOCKS * block_size + size; +if (s->guest_note && +note_name_equal(s, s->guest_note, "VMCOREINFO")) { +uint64_t hsize, name_size, size_vmcoreinfo_desc, offset_vmcoreinfo; + +get_note_sizes(s, s->guest_note, + &hsize, &name_size, &size_vmcoreinfo_desc); +offset_vmcoreinfo = offset_note + s->note_size - s->guest_note_size + +(DIV_ROUND_UP(hsize, 4) + DIV_ROUND_UP(name_size, 4)) * 4; +kh->offset_vmcoreinfo = cpu_to_dump64(s, offset_vmcoreinfo); +kh->size_vmcoreinfo = cpu_to_dump32(s, size_vmcoreinfo_desc); +} + kh->offset_note = cpu_to_dump64(s, offset_note); kh->note_size = cpu_to_dump32(s, s->note_size); @@ -957,6 +969,18 @@ static void create_header64(DumpState *s, Error **errp) kh->dump_level = cpu_to_dump32(s, DUMP_LEVEL); offset_note = DISKDUMP_HEADER_BLOCKS * block_size + size; +if (s->guest_note && +note_name_equal(s, s->guest_note, "VMCOREINFO")) { +uint64_t hsize, name_size, size_vmcoreinfo_desc, offset_vmcoreinfo; + +get_note_sizes(s, s->guest_note, + &hsize, &name_size, &size_vmcoreinfo_desc); +offset_vmcoreinfo = offset_note + s->note_size - s->guest_note_size + +(DIV_ROUND_UP(hsize, 4) + DIV_ROUND_UP(name_size, 4)) * 4; +kh->offset_vmcoreinfo = cpu_to_dump64(s, offset_vmcoreinfo); +kh->size_vmcoreinfo = cpu_to_dump64(s, size_vmcoreinfo_desc); +} + kh->offset_note = cpu_to_dump64(s, offset_note); kh->note_size = cpu_to_dump64(s, s->note_size); -- MST
[Qemu-devel] [PULL 08/26] scripts/dump-guest-memory.py: add vmcoreinfo
From: Marc-André Lureau Add a vmcoreinfo ELF note in the dump if vmcoreinfo device has the memory location details. Signed-off-by: Marc-André Lureau Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- scripts/dump-guest-memory.py | 61 1 file changed, 61 insertions(+) diff --git a/scripts/dump-guest-memory.py b/scripts/dump-guest-memory.py index f7c6635..69dd5ef 100644 --- a/scripts/dump-guest-memory.py +++ b/scripts/dump-guest-memory.py @@ -14,6 +14,7 @@ the COPYING file in the top-level directory. """ import ctypes +import struct UINTPTR_T = gdb.lookup_type("uintptr_t") @@ -45,6 +46,17 @@ EM_S390 = 22 EM_AARCH = 183 EM_X86_64 = 62 +VMCOREINFO_FORMAT_ELF = 1 + +def le16_to_cpu(val): +return struct.unpack(" 1 << 20: +print('warning: invalid vmcoreinfo size') +return +# now get the full note +note = get_arch_note(self.endianness, + header.n_namesz - 1, header.n_descsz) +ctypes.memmove(ctypes.pointer(note), vmcoreinfo, ctypes.sizeof(note)) + +self.notes.append(note) +self.segments[0].p_filesz += ctypes.sizeof(note) +self.segments[0].p_memsz += ctypes.sizeof(note) + def add_segment(self, p_type, p_paddr, p_size): """Adds a segment to the elf.""" @@ -505,6 +536,35 @@ shape and this command should mostly work.""" cur += chunk_size left -= chunk_size +def phys_memory_read(self, addr, size): +qemu_core = gdb.inferiors()[0] +for block in self.guest_phys_blocks: +if block["target_start"] <= addr \ + and addr + size <= block["target_end"]: +haddr = block["host_addr"] + (addr - block["target_start"]) +return qemu_core.read_memory(haddr, size) +return None + +def add_vmcoreinfo(self): +if not gdb.parse_and_eval("vmcoreinfo_find()") \ + or not gdb.parse_and_eval("vmcoreinfo_find()->has_vmcoreinfo"): +return + +fmt = gdb.parse_and_eval("vmcoreinfo_find()->vmcoreinfo.guest_format") +addr = gdb.parse_and_eval("vmcoreinfo_find()->vmcoreinfo.paddr") +size = gdb.parse_and_eval("vmcoreinfo_find()->vmcoreinfo.size") + +fmt = le16_to_cpu(fmt) +addr = le64_to_cpu(addr) +size = le32_to_cpu(size) + +if fmt != VMCOREINFO_FORMAT_ELF: +return + +vmcoreinfo = self.phys_memory_read(addr, size) +if vmcoreinfo: +self.elf.add_vmcoreinfo_note(vmcoreinfo.tobytes()) + def invoke(self, args, from_tty): """Handles command invocation from gdb.""" @@ -518,6 +578,7 @@ shape and this command should mostly work.""" self.elf = ELF(argv[1]) self.guest_phys_blocks = get_guest_phys_blocks() +self.add_vmcoreinfo() with open(argv[0], "wb") as vmcore: self.dump_init(vmcore) -- MST
[Qemu-devel] [PULL 26/26] tests/pxe: Test more NICs when running in SPEED=slow mode
From: Thomas Huth The pxe-test is a very good test to excercise NICs, thus we should use it to test all NICs that can be used by the BIOS for booting via network. However, to avoid that the default testing time increases too much, the additional NICs are only tested in the "make check SPEED=slow" mode. The virtio-net NIC on ppc64 is now also only tested in slow mode, since the test on ppc64 is really quite slow and we've got test coverage for virtio-net in big endian mode now on s390x, too. Signed-off-by: Thomas Huth Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/pxe-test.c | 31 +-- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/tests/pxe-test.c b/tests/pxe-test.c index 0d70afc..937f29e 100644 --- a/tests/pxe-test.c +++ b/tests/pxe-test.c @@ -1,11 +1,12 @@ /* * PXE test cases. * - * Copyright (c) 2016 Red Hat Inc. + * Copyright (c) 2016, 2017 Red Hat Inc. * * Authors: * Michael S. Tsirkin , * Victor Kaplansky + * Thomas Huth * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. @@ -36,14 +37,14 @@ static void test_pxe_one(const char *params, bool ipv6) g_free(args); } -static void test_pxe_e1000(void) +static void test_pxe_ipv4(gconstpointer data) { -test_pxe_one("-device e1000,netdev=" NETNAME, false); -} +const char *model = data; +char *dev_arg; -static void test_pxe_virtio_pci(void) -{ -test_pxe_one("-device virtio-net-pci,netdev=" NETNAME, false); +dev_arg = g_strdup_printf("-device %s,netdev=" NETNAME, model); +test_pxe_one(dev_arg, false); +g_free(dev_arg); } static void test_pxe_spapr_vlan(void) @@ -68,11 +69,21 @@ int main(int argc, char *argv[]) g_test_init(&argc, &argv, NULL); if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { -qtest_add_func("pxe/e1000", test_pxe_e1000); -qtest_add_func("pxe/virtio", test_pxe_virtio_pci); +qtest_add_data_func("pxe/e1000", "e1000", test_pxe_ipv4); +qtest_add_data_func("pxe/virtio", "virtio-net-pci", test_pxe_ipv4); +if (g_test_slow()) { +qtest_add_data_func("pxe/ne2000", "ne2k_pci", test_pxe_ipv4); +qtest_add_data_func("pxe/eepro100", "i82550", test_pxe_ipv4); +qtest_add_data_func("pxe/pcnet", "pcnet", test_pxe_ipv4); +qtest_add_data_func("pxe/rtl8139", "rtl8139", test_pxe_ipv4); +qtest_add_data_func("pxe/vmxnet3", "vmxnet3", test_pxe_ipv4); +} } else if (strcmp(arch, "ppc64") == 0) { -qtest_add_func("pxe/virtio", test_pxe_virtio_pci); qtest_add_func("pxe/spapr-vlan", test_pxe_spapr_vlan); +if (g_test_slow()) { +qtest_add_data_func("pxe/virtio", "virtio-net-pci", test_pxe_ipv4); +qtest_add_data_func("pxe/e1000", "e1000", test_pxe_ipv4); +} } else if (g_str_equal(arch, "s390x")) { qtest_add_func("pxe/virtio-ccw", test_pxe_virtio_ccw); } -- MST
[Qemu-devel] [PULL 06/26] dump: update phys_base header field based on VMCOREINFO content
From: Marc-André Lureau If the guest note is VMCOREINFO, try to get phys_base from it. Signed-off-by: Marc-André Lureau Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- docs/specs/vmcoreinfo.txt | 8 +++ dump.c| 56 +-- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/docs/specs/vmcoreinfo.txt b/docs/specs/vmcoreinfo.txt index 2868a77..8212610 100644 --- a/docs/specs/vmcoreinfo.txt +++ b/docs/specs/vmcoreinfo.txt @@ -39,3 +39,11 @@ qemu dumps. The note format/class must be of the target bitness and the size must be less than 1Mb. + +If the ELF note name is "VMCOREINFO", it is expected to be the Linux +vmcoreinfo note (see Documentation/ABI/testing/sysfs-kernel-vmcoreinfo +in Linux source). In this case, qemu dump code will read the content +as a key=value text file, looking for "NUMBER(phys_base)" key +value. The value is expected to be more accurate than architecture +guess of the value. This is useful for KASLR-enabled guest with +ancient tools not handling the VMCOREINFO note. diff --git a/dump.c b/dump.c index 1479f1f..5674512 100644 --- a/dump.c +++ b/dump.c @@ -779,6 +779,23 @@ static void get_note_sizes(DumpState *s, const void *note, } } +static bool note_name_equal(DumpState *s, +const uint8_t *note, const char *name) +{ +int len = strlen(name) + 1; +uint64_t head_size, name_size; + +get_note_sizes(s, note, &head_size, &name_size, NULL); +head_size = ROUND_UP(head_size, 4); + +if (name_size != len || +memcmp(note + head_size, "VMCOREINFO", len)) { +return false; +} + +return true; +} + /* write common header, sub header and elf note to vmcore */ static void create_header32(DumpState *s, Error **errp) { @@ -1553,6 +1570,39 @@ static int64_t dump_calculate_size(DumpState *s) return total; } +static void vmcoreinfo_update_phys_base(DumpState *s) +{ +uint64_t size, note_head_size, name_size, phys_base; +char **lines; +uint8_t *vmci; +size_t i; + +if (!note_name_equal(s, s->guest_note, "VMCOREINFO")) { +return; +} + +get_note_sizes(s, s->guest_note, ¬e_head_size, &name_size, &size); +note_head_size = ROUND_UP(note_head_size, 4); + +vmci = s->guest_note + note_head_size + ROUND_UP(name_size, 4); +*(vmci + size) = '\0'; + +lines = g_strsplit((char *)vmci, "\n", -1); +for (i = 0; lines[i]; i++) { +if (g_str_has_prefix(lines[i], "NUMBER(phys_base)=")) { +if (qemu_strtou64(lines[i] + 18, NULL, 16, + &phys_base) < 0) { +warn_report("Failed to read NUMBER(phys_base)="); +} else { +s->dump_info.phys_base = phys_base; +} +break; +} +} + +g_strfreev(lines); +} + static void dump_init(DumpState *s, int fd, bool has_format, DumpGuestMemoryFormat format, bool paging, bool has_filter, int64_t begin, int64_t length, Error **errp) @@ -1636,8 +1686,9 @@ static void dump_init(DumpState *s, int fd, bool has_format, } /* - * The goal of this block is to copy the guest note out of - * the guest. Failure to do so is not fatal for dumping. + * The goal of this block is to (a) update the previously guessed + * phys_base, (b) copy the guest note out of the guest. + * Failure to do so is not fatal for dumping. */ if (vmci) { uint64_t addr, note_head_size, name_size, desc_size; @@ -1670,6 +1721,7 @@ static void dump_init(DumpState *s, int fd, bool has_format, g_free(s->guest_note); s->guest_note = NULL; } else { +vmcoreinfo_update_phys_base(s); s->note_size += s->guest_note_size; } } -- MST
[Qemu-devel] [PULL 05/26] dump: add guest ELF note
From: Marc-André Lureau Read the guest ELF PT_NOTE from guest memory when fw_cfg etc/vmcoreinfo entry provides the location, and write it as an additional note in the dump. Signed-off-by: Marc-André Lureau Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/sysemu/dump.h | 2 + dump.c| 107 ++ 2 files changed, 109 insertions(+) diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h index 2672a15..df43bd0 100644 --- a/include/sysemu/dump.h +++ b/include/sysemu/dump.h @@ -192,6 +192,8 @@ typedef struct DumpState { * this could be used to calculate * how much work we have * finished. */ +uint8_t *guest_note; /* ELF note content */ +size_t guest_note_size; } DumpState; uint16_t cpu_to_dump16(DumpState *s, uint16_t val); diff --git a/dump.c b/dump.c index 7ebcf55..1479f1f 100644 --- a/dump.c +++ b/dump.c @@ -25,6 +25,8 @@ #include "qapi/qmp/qerror.h" #include "qmp-commands.h" #include "qapi-event.h" +#include "qemu/error-report.h" +#include "hw/misc/vmcoreinfo.h" #include #ifdef CONFIG_LZO @@ -37,6 +39,13 @@ #define ELF_MACHINE_UNAME "Unknown" #endif +#define MAX_GUEST_NOTE_SIZE (1 << 20) /* 1MB should be enough */ + +#define ELF_NOTE_SIZE(hdr_size, name_size, desc_size) \ +((DIV_ROUND_UP((hdr_size), 4) + \ + DIV_ROUND_UP((name_size), 4) +\ + DIV_ROUND_UP((desc_size), 4)) * 4) + uint16_t cpu_to_dump16(DumpState *s, uint16_t val) { if (s->dump_info.d_endian == ELFDATA2LSB) { @@ -75,6 +84,8 @@ static int dump_cleanup(DumpState *s) guest_phys_blocks_free(&s->guest_phys_blocks); memory_mapping_list_free(&s->list); close(s->fd); +g_free(s->guest_note); +s->guest_note = NULL; if (s->resume) { if (s->detached) { qemu_mutex_lock_iothread(); @@ -234,6 +245,19 @@ static inline int cpu_index(CPUState *cpu) return cpu->cpu_index + 1; } +static void write_guest_note(WriteCoreDumpFunction f, DumpState *s, + Error **errp) +{ +int ret; + +if (s->guest_note) { +ret = f(s->guest_note, s->guest_note_size, s); +if (ret < 0) { +error_setg(errp, "dump: failed to write guest note"); +} +} +} + static void write_elf64_notes(WriteCoreDumpFunction f, DumpState *s, Error **errp) { @@ -257,6 +281,8 @@ static void write_elf64_notes(WriteCoreDumpFunction f, DumpState *s, return; } } + +write_guest_note(f, s, errp); } static void write_elf32_note(DumpState *s, Error **errp) @@ -302,6 +328,8 @@ static void write_elf32_notes(WriteCoreDumpFunction f, DumpState *s, return; } } + +write_guest_note(f, s, errp); } static void write_elf_section(DumpState *s, int type, Error **errp) @@ -713,6 +741,44 @@ static int buf_write_note(const void *buf, size_t size, void *opaque) return 0; } +/* + * This function retrieves various sizes from an elf header. + * + * @note has to be a valid ELF note. The return sizes are unmodified + * (not padded or rounded up to be multiple of 4). + */ +static void get_note_sizes(DumpState *s, const void *note, + uint64_t *note_head_size, + uint64_t *name_size, + uint64_t *desc_size) +{ +uint64_t note_head_sz; +uint64_t name_sz; +uint64_t desc_sz; + +if (s->dump_info.d_class == ELFCLASS64) { +const Elf64_Nhdr *hdr = note; +note_head_sz = sizeof(Elf64_Nhdr); +name_sz = tswap64(hdr->n_namesz); +desc_sz = tswap64(hdr->n_descsz); +} else { +const Elf32_Nhdr *hdr = note; +note_head_sz = sizeof(Elf32_Nhdr); +name_sz = tswap32(hdr->n_namesz); +desc_sz = tswap32(hdr->n_descsz); +} + +if (note_head_size) { +*note_head_size = note_head_sz; +} +if (name_size) { +*name_size = name_sz; +} +if (desc_size) { +*desc_size = desc_sz; +} +} + /* write common header, sub header and elf note to vmcore */ static void create_header32(DumpState *s, Error **errp) { @@ -1491,6 +1557,7 @@ static void dump_init(DumpState *s, int fd, bool has_format, DumpGuestMemoryFormat format, bool paging, bool has_filter, int64_t begin, int64_t length, Error **errp) { +VMCoreInfoState *vmci = vmcoreinfo_find(); CPUState *cpu; int nr_cpus; Error *err = NULL; @@ -1568,6 +1635,46 @@ static void dump_init(DumpState *s, int fd, bool has_format, goto cleanup; } +/* + * The goal of this block is to copy the guest note out of + * the guest. Failure to do so is not fatal for dumping. + */ +if (vmci) { +uint64_
[Qemu-devel] [PULL 01/26] xio3130_downstream: Report error if pcie_chassis_add_slot() failed
From: Eduardo Habkost On commit f8cd1b02 ("pci: Convert to realize"), no error_set*() call was added for the pcie_chassis_add_slot() error case. pcie_chassis_add_slot() errors get ignored, making QEMU crash later. e.g.: $ qemu-system-x86_64 -device ioh3420 -device xio3130-downstream qemu-system-x86_64: memory.c:2166: memory_region_del_subregion: Assertion `subregion->container == mr' failed. Aborted (core dumped) Fix it by reporting the error using error_setg(). Fixes: f8cd1b0201c41d88bb97dcafb80348a0e88d8805 Signed-off-by: Eduardo Habkost Reviewed-by: Marcel Apfelbaum Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/pci-bridge/xio3130_downstream.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c index e706f36..5a882b0 100644 --- a/hw/pci-bridge/xio3130_downstream.c +++ b/hw/pci-bridge/xio3130_downstream.c @@ -94,6 +94,7 @@ static void xio3130_downstream_realize(PCIDevice *d, Error **errp) pcie_chassis_create(s->chassis); rc = pcie_chassis_add_slot(s); if (rc < 0) { +error_setg(errp, "Can't add chassis slot, error %d", rc); goto err_pcie_cap; } -- MST
[Qemu-devel] [PULL 10/26] virtio/vhost: reset dev->log after syncing
From: Felipe Franciosi vhost_log_put() is called to decomission the dirty log between qemu and a vhost device when stopping the device. Such a call can happen from migration_completion(). Present code sets dev->log_size to zero too early in vhost_log_put(), causing the sync check to always return false. As a consequence, the last pass on the dirty bitmap never happens at the end of migration. If a vhost device was busy (writing to guest memory) until the last moments before vhost_virtqueue_stop(), this error will result in guest memory corruption (at least) following migrations. Signed-off-by: Felipe Franciosi Acked-by: Jason Wang Reviewed-by: Marc-André Lureau Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 5fd69f0..ddc42f0 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -375,8 +375,6 @@ static void vhost_log_put(struct vhost_dev *dev, bool sync) if (!log) { return; } -dev->log = NULL; -dev->log_size = 0; --log->refcnt; if (log->refcnt == 0) { @@ -396,6 +394,9 @@ static void vhost_log_put(struct vhost_dev *dev, bool sync) g_free(log); } + +dev->log = NULL; +dev->log_size = 0; } static bool vhost_dev_log_is_shared(struct vhost_dev *dev) -- MST
[Qemu-devel] [PULL 02/26] pci: Set err to errp directly rather than through error_propagate()
From: Mao Zhongyi ioh3420_interrupts_init() pass error message to local_err, then propagate it to errp by error_propagate(), which is not necessary. So eliminate it and pass errp directly instead of local_err. Cc: "Michael S. Tsirkin" Cc: Marcel Apfelbaum Signed-off-by: Mao Zhongyi Reviewed-by: Eric Blake Reviewed-by: Marcel Apfelbaum Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Stefan Hajnoczi Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/pci-bridge/ioh3420.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hw/pci-bridge/ioh3420.c b/hw/pci-bridge/ioh3420.c index da4e5bd..5f56a2f 100644 --- a/hw/pci-bridge/ioh3420.c +++ b/hw/pci-bridge/ioh3420.c @@ -64,15 +64,13 @@ static uint8_t ioh3420_aer_vector(const PCIDevice *d) static int ioh3420_interrupts_init(PCIDevice *d, Error **errp) { int rc; -Error *local_err = NULL; rc = msi_init(d, IOH_EP_MSI_OFFSET, IOH_EP_MSI_NR_VECTOR, IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT, IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT, - &local_err); + errp); if (rc < 0) { assert(rc == -ENOTSUP); -error_propagate(errp, local_err); } return rc; -- MST
[Qemu-devel] [PULL 04/26] hw/misc: add vmcoreinfo device
From: Marc-André Lureau See docs/specs/vmcoreinfo.txt for details. "etc/vmcoreinfo" fw_cfg entry is added when using "-device vmcoreinfo". Signed-off-by: Marc-André Lureau Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- docs/specs/vmcoreinfo.txt| 41 +++ include/hw/misc/vmcoreinfo.h | 46 + hw/misc/vmcoreinfo.c | 96 hw/misc/Makefile.objs| 1 + 4 files changed, 184 insertions(+) create mode 100644 docs/specs/vmcoreinfo.txt create mode 100644 include/hw/misc/vmcoreinfo.h create mode 100644 hw/misc/vmcoreinfo.c diff --git a/docs/specs/vmcoreinfo.txt b/docs/specs/vmcoreinfo.txt new file mode 100644 index 000..2868a77 --- /dev/null +++ b/docs/specs/vmcoreinfo.txt @@ -0,0 +1,41 @@ += +VMCoreInfo device += + +The `-device vmcoreinfo` will create a fw_cfg entry for a guest to +store dump details. + +etc/vmcoreinfo +** + +A guest may use this fw_cfg entry to add information details to qemu +dumps. + +The entry of 16 bytes has the following layout, in little-endian:: + +#define VMCOREINFO_FORMAT_NONE 0x0 +#define VMCOREINFO_FORMAT_ELF 0x1 + +struct FWCfgVMCoreInfo { +uint16_t host_format; /* formats host supports */ +uint16_t guest_format; /* format guest supplies */ +uint32_t size; /* size of vmcoreinfo region */ +uint64_t paddr;/* physical address of vmcoreinfo region */ +}; + +Only full write (of 16 bytes) are considered valid for further +processing of entry values. + +A write of 0 in guest_format will disable further processing of +vmcoreinfo entry values & content. + +Format & content + + +As of qemu 2.11, only VMCOREINFO_FORMAT_ELF is supported. + +The entry gives location and size of an ELF note that is appended in +qemu dumps. + +The note format/class must be of the target bitness and the size must +be less than 1Mb. diff --git a/include/hw/misc/vmcoreinfo.h b/include/hw/misc/vmcoreinfo.h new file mode 100644 index 000..c3aa856 --- /dev/null +++ b/include/hw/misc/vmcoreinfo.h @@ -0,0 +1,46 @@ +/* + * Virtual Machine coreinfo device + * + * Copyright (C) 2017 Red Hat, Inc. + * + * Authors: Marc-André Lureau + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ +#ifndef VMCOREINFO_H +#define VMCOREINFO_H + +#include "hw/qdev.h" + +#define VMCOREINFO_DEVICE "vmcoreinfo" +#define VMCOREINFO(obj) OBJECT_CHECK(VMCoreInfoState, (obj), VMCOREINFO_DEVICE) + +#define VMCOREINFO_FORMAT_NONE 0x0 +#define VMCOREINFO_FORMAT_ELF 0x1 + +/* all fields are little-endian */ +typedef struct FWCfgVMCoreInfo { +uint16_t host_format; /* set on reset */ +uint16_t guest_format; +uint32_t size; +uint64_t paddr; +} QEMU_PACKED FWCfgVMCoreInfo; + +typedef struct VMCoreInfoState { +DeviceClass parent_obj; + +bool has_vmcoreinfo; +FWCfgVMCoreInfo vmcoreinfo; +} VMCoreInfoState; + +/* returns NULL unless there is exactly one device */ +static inline VMCoreInfoState *vmcoreinfo_find(void) +{ +Object *o = object_resolve_path_type("", VMCOREINFO_DEVICE, NULL); + +return o ? VMCOREINFO(o) : NULL; +} + +#endif diff --git a/hw/misc/vmcoreinfo.c b/hw/misc/vmcoreinfo.c new file mode 100644 index 000..a618e12 --- /dev/null +++ b/hw/misc/vmcoreinfo.c @@ -0,0 +1,96 @@ +/* + * Virtual Machine coreinfo device + * + * Copyright (C) 2017 Red Hat, Inc. + * + * Authors: Marc-André Lureau + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/nvram/fw_cfg.h" +#include "hw/misc/vmcoreinfo.h" + +static void fw_cfg_vmci_write(void *dev, off_t offset, size_t len) +{ +VMCoreInfoState *s = VMCOREINFO(dev); + +s->has_vmcoreinfo = offset == 0 && len == sizeof(s->vmcoreinfo) +&& s->vmcoreinfo.guest_format != VMCOREINFO_FORMAT_NONE; +} + +static void vmcoreinfo_reset(void *dev) +{ +VMCoreInfoState *s = VMCOREINFO(dev); + +s->has_vmcoreinfo = false; +memset(&s->vmcoreinfo, 0, sizeof(s->vmcoreinfo)); +s->vmcoreinfo.host_format = cpu_to_le16(VMCOREINFO_FORMAT_ELF); +} + +static void vmcoreinfo_realize(DeviceState *dev, Error **errp) +{ +VMCoreInfoState *s = VMCOREINFO(dev); +FWCfgState *fw_cfg = fw_cfg_find(); + +/* Given that this function is executing, there is at least one VMCOREINFO + * device. Check if there are several. + */ +if (!vmcoreinfo_find()) { +error_setg(errp, "at most one %s device is permitted", + VMCOREINFO_DEVICE); +return; +} + +if (!fw_cfg || !fw_cfg->dma_enabled) { +error_setg(errp, "%s device requires fw_cfg with DMA", + VMCOREINFO_DEVICE); +return; +} + +fw_cfg_add_file_
[Qemu-devel] [PULL 00/26] pc, pci, virtio: fixes, features
The following changes since commit f90ea7ba7c5ae7010ee0ce062207ae42530f57d6: Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20171012' into staging (2017-10-12 17:06:50 +0100) are available in the git repository at: git://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git tags/for_upstream for you to fetch changes up to ab06ec43577177a442e8e5ca28d0154efe4ff60f: tests/pxe: Test more NICs when running in SPEED=slow mode (2017-10-15 05:54:44 +0300) pc, pci, virtio: fixes, features A bunch of fixes all over the place. A new vmcore device - the user interface around it is still somewhat controversial, but I feel most of the code is fine, suggestions can be addressed by adding patches on top. Signed-off-by: Michael S. Tsirkin Aleksandr Bezzubikov (1): hw/pci-bridge/pcie_pci_bridge: properly handle MSI unavailability case Alexey Kardashevskiy (1): virtio-pci: Replace modern_as with direct access to modern_bar Dr. David Alan Gilbert (1): virtio/pci/migration: Convert to VMState Eduardo Habkost (8): xio3130_downstream: Report error if pcie_chassis_add_slot() failed pci: conventional-pci-device and pci-express-device interfaces pci: Add interface names to hybrid PCI devices pci: Add INTERFACE_PCIE_DEVICE to all PCIe devices pci: Add INTERFACE_CONVENTIONAL_PCI_DEVICE to Conventional PCI devices xen/pt: Mark TYPE_XEN_PT_DEVICE as hybrid pci: Validate interfaces on base_class_init isapc: Remove unnecessary migration compatibility code Felipe Franciosi (1): virtio/vhost: reset dev->log after syncing Laurent Vivier (1): pc: remove useless hot_add_cpu initialisation Mao Zhongyi (1): pci: Set err to errp directly rather than through error_propagate() Marc-André Lureau (7): fw_cfg: add write callback hw/misc: add vmcoreinfo device dump: add guest ELF note dump: update phys_base header field based on VMCOREINFO content kdump: set vmcoreinfo location scripts/dump-guest-memory.py: add vmcoreinfo MAINTAINERS: add Dump maintainers Marcel Apfelbaum (1): hw/gen_pcie_root_port: make IO RO 0 on IO disabled Mark Cave-Ayland (1): pci: allow 32-bit PCI IO accesses to pass through the PCI bridge Matt Redfearn (1): PCI: PCIe access should always be little endian Thomas Huth (1): tests/pxe: Test more NICs when running in SPEED=slow mode Wolfgang Bumiller (1): virtio: fix descriptor counting in virtqueue_pop docs/specs/vmcoreinfo.txt | 49 ++ hw/virtio/virtio-pci.h | 17 ++-- include/hw/misc/vmcoreinfo.h| 46 + include/hw/nvram/fw_cfg.h | 3 + include/hw/pci/pci.h| 6 ++ include/sysemu/dump.h | 2 + dump.c | 183 +++ hw/acpi/piix4.c | 1 + hw/acpi/vmgenid.c | 2 +- hw/audio/ac97.c | 4 + hw/audio/es1370.c | 4 + hw/audio/intel-hda.c| 4 + hw/block/nvme.c | 4 + hw/char/serial-pci.c| 12 +++ hw/core/loader.c| 2 +- hw/display/cirrus_vga.c | 4 + hw/display/qxl.c| 4 + hw/display/sm501.c | 4 + hw/display/vga-pci.c| 4 + hw/display/vmware_vga.c | 4 + hw/i2c/smbus_ich9.c | 4 + hw/i386/acpi-build.c| 2 +- hw/i386/amd_iommu.c | 4 + hw/i386/kvm/pci-assign.c| 4 + hw/i386/pc_piix.c | 8 +- hw/i386/pc_q35.c| 1 - hw/i386/xen/xen_platform.c | 4 + hw/i386/xen/xen_pvdevice.c | 4 + hw/ide/ich.c| 4 + hw/ide/pci.c| 4 + hw/ipack/tpci200.c | 4 + hw/isa/i82378.c | 4 + hw/isa/lpc_ich9.c | 5 +- hw/isa/piix4.c | 4 + hw/isa/vt82c686.c | 16 +++ hw/mips/gt64xxx_pci.c | 4 + hw/misc/edu.c | 5 + hw/misc/ivshmem.c | 4 + hw/misc/macio/macio.c | 4 + hw/misc/pci-testdev.c | 4 + hw/misc/vmcoreinfo.c| 96 ++ hw/net/e1000.c | 4 + hw/net/e1000e.c | 4 + hw/net/eepro100.c | 4 + hw/net/ne2000.c | 4 + hw/net/pcnet-pci.c | 4 + hw/net/rocker/rocker.c | 4 + hw/net/rtl8139.c| 4 + hw/net/sungem.c | 4 + hw/net/sunhme.c | 4 + hw/net/vmxnet3.c
Re: [Qemu-devel] [PATCHv2 00/13] sun4m: sparc32_dma tidy-ups
Hi, This series failed build test on s390x host. Please find the details below. Type: series Message-id: 1508004545-28578-1-git-send-email-mark.cave-ayl...@ilande.co.uk Subject: [Qemu-devel] [PATCHv2 00/13] sun4m: sparc32_dma tidy-ups === TEST SCRIPT BEGIN === #!/bin/bash # Testing script will be invoked under the git checkout with # HEAD pointing to a commit that has the patches applied on top of "base" # branch set -e echo "=== ENV ===" env echo "=== PACKAGES ===" rpm -qa echo "=== TEST BEGIN ===" CC=$HOME/bin/cc INSTALL=$PWD/install BUILD=$PWD/build echo -n "Using CC: " realpath $CC mkdir -p $BUILD $INSTALL SRC=$PWD cd $BUILD $SRC/configure --cc=$CC --prefix=$INSTALL make -j4 # XXX: we need reliable clean up # make check -j4 V=1 make install === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 From https://github.com/patchew-project/qemu - [tag update] patchew/1507816448-86665-1-git-send-email-pbonz...@redhat.com -> patchew/1507816448-86665-1-git-send-email-pbonz...@redhat.com - [tag update] patchew/1507930220-17461-1-git-send-email-c...@braap.org -> patchew/1507930220-17461-1-git-send-email-c...@braap.org * [new tag] patchew/1508004545-28578-1-git-send-email-mark.cave-ayl...@ilande.co.uk -> patchew/1508004545-28578-1-git-send-email-mark.cave-ayl...@ilande.co.uk - [tag update] patchew/20171013054842.32120-1...@weilnetz.de -> patchew/20171013054842.32120-1...@weilnetz.de - [tag update] patchew/20171013162438.32458-1-alex.ben...@linaro.org -> patchew/20171013162438.32458-1-alex.ben...@linaro.org Switched to a new branch 'test' 750844c sparc32_dma: add len to esp/le DMA memory tracing ba7ab63 sparc32_dma: remove is_ledma hack and replace with memory region alias cf74bfb sparc32_dma: introduce new SPARC32_DMA type container object 1a9feba sparc32_dma: make lance device child of ledma device 86b3305 lance: move TYPE_LANCE and SysBusPCNetState from lance.c to sun4m.h c5ae1c6 sparc32_dma: make esp device child of espdma device 420993a esp: move TYPE_ESP and SysBusESPState from esp.c to esp.h 236dbd4 sparc32_dma: use object link instead of qdev property to pass IOMMU reference 5165f56 sun4m_iommu: move TYPE_SUN4M_IOMMU declaration to sun4m.h 850a150 sun4m: move DMA device wiring from sparc32_dma_init() to sun4m_hw_init() 4ba0c4c sparc32_dma: move type declarations from sparc32_dma.c to sparc32_dma.h 553bbce sparc32_dma: split esp and le into separate DMA devices dd74a83 sparc32_dma: rename SPARC32_DMA type to SPARC32_DMA_DEVICE === OUTPUT BEGIN === === ENV === XDG_SESSION_ID=45931 SHELL=/bin/sh USER=fam PATCHEW=/home/fam/patchew/patchew-cli -s http://patchew.org --nodebug PATH=/usr/bin:/bin PWD=/var/tmp/patchew-tester-tmp-0zvctjo5/src LANG=en_US.UTF-8 HOME=/home/fam SHLVL=2 LOGNAME=fam DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1012/bus XDG_RUNTIME_DIR=/run/user/1012 _=/usr/bin/env === PACKAGES === gpg-pubkey-873529b8-54e386ff xz-libs-5.2.2-2.fc24.s390x libxshmfence-1.2-3.fc24.s390x giflib-4.1.6-15.fc24.s390x trousers-lib-0.3.13-6.fc24.s390x ncurses-base-6.0-6.20160709.fc25.noarch gmp-6.1.1-1.fc25.s390x libidn-1.33-1.fc25.s390x slang-2.3.0-7.fc25.s390x pkgconfig-0.29.1-1.fc25.s390x alsa-lib-1.1.1-2.fc25.s390x yum-metadata-parser-1.1.4-17.fc25.s390x python3-slip-dbus-0.6.4-4.fc25.noarch python2-cssselect-0.9.2-1.fc25.noarch createrepo_c-libs-0.10.0-6.fc25.s390x initscripts-9.69-1.fc25.s390x parted-3.2-21.fc25.s390x flex-2.6.0-3.fc25.s390x colord-libs-1.3.4-1.fc25.s390x python-osbs-client-0.33-3.fc25.noarch perl-Pod-Simple-3.35-1.fc25.noarch python2-simplejson-3.10.0-1.fc25.s390x brltty-5.4-2.fc25.s390x librados2-10.2.4-2.fc25.s390x tcp_wrappers-7.6-83.fc25.s390x libcephfs_jni1-10.2.4-2.fc25.s390x nettle-devel-3.3-1.fc25.s390x bzip2-devel-1.0.6-21.fc25.s390x libuuid-2.28.2-2.fc25.s390x python3-dnf-1.1.10-6.fc25.noarch texlive-kpathsea-doc-svn41139-33.fc25.1.noarch openssh-7.4p1-4.fc25.s390x texlive-kpathsea-bin-svn40473-33.20160520.fc25.1.s390x texlive-graphics-svn41015-33.fc25.1.noarch texlive-dvipdfmx-def-svn40328-33.fc25.1.noarch texlive-mfware-svn40768-33.fc25.1.noarch texlive-texlive-scripts-svn41433-33.fc25.1.noarch texlive-euro-svn22191.1.1-33.fc25.1.noarch texlive-etex-svn37057.0-33.fc25.1.noarch texlive-iftex-svn29654.0.2-33.fc25.1.noarch texlive-palatino-svn31835.0-33.fc25.1.noarch texlive-texlive-docindex-svn41430-33.fc25.1.noarch texlive-xunicode-svn30466.0.981-33.fc25.1.noarch texlive-koma-script-svn41508-33.fc25.1.noarch texlive-pst-grad-svn15878.1.06-33.fc25.1.noarch texlive-pst-blur-svn15878.2.0-33.fc25.1.noarch texlive-jknapltx-svn19440.0-33.fc25.1.noarch texinfo-6.1-4.fc25.s390x openssl-devel-1.0.2k-1.fc25.s390x jansson-2.10-2.fc25.s390x fedora-repos-25-4.noarch perl-Errno-1.25-387.fc25.s390x acl-2.2.52-13.fc25.s390x systemd-pam-231-17.fc25.s390x NetworkManager-libnm-1.4.4-5.fc25.s390x poppler-0.45.0-5.fc25.s390x ccache-3.3.4-1.fc25.s390x valgrind-3.12.0-9.fc25.s390x perl-open-1.10-387.fc25.noarch libgcc-6.4.1-1.fc25.s390x libs
Re: [Qemu-devel] [PATCH v6 2/7] hw/misc: add vmcoreinfo device
On Tue, Oct 10, 2017 at 03:01:10PM -0300, Eduardo Habkost wrote: > On Tue, Oct 10, 2017 at 04:06:28PM +0100, Daniel P. Berrange wrote: > > On Tue, Oct 10, 2017 at 05:00:18PM +0200, Marc-André Lureau wrote: > > > Hi > > > > > > On Tue, Oct 10, 2017 at 10:31 AM, Daniel P. Berrange > > > wrote: > > > > On Tue, Oct 10, 2017 at 12:44:26AM +0300, Michael S. Tsirkin wrote: > > > >> On Mon, Oct 09, 2017 at 02:02:18PM +0100, Daniel P. Berrange wrote: > > > >> > On Mon, Oct 09, 2017 at 02:43:44PM +0200, Igor Mammedov wrote: > > > >> > > On Mon, 9 Oct 2017 12:03:36 +0100 > > > >> > > "Daniel P. Berrange" wrote: > > > >> > > > > > >> > > > On Mon, Sep 11, 2017 at 06:59:24PM +0200, Marc-André Lureau > > > >> > > > wrote: > > > >> > > > > See docs/specs/vmcoreinfo.txt for details. > > > >> > > > > > > > >> > > > > "etc/vmcoreinfo" fw_cfg entry is added when using "-device > > > >> > > > > vmcoreinfo". > > > >> > > > > > > >> > > > I'm wondering if you considered just adding the entry to fw_cfg > > > >> > > > by > > > >> > > > default, without requiring any -device arg ? Unless I'm > > > >> > > > misunderstanding, > > > >> > > > this doesn't feel like a device to me - its just a well known > > > >> > > > bucket > > > >> > > > in fw_cfg IIUC ? Obviously its existance would need to be tied > > > >> > > > to > > > >> > > > the latest machine type for ABI reasons though. The benefit of > > > >> > > > this > > > >> > > > is that it would "just work" without us having to plumb it > > > >> > > > through to > > > >> > > > all the downstream applications that use QEMU for mgmt guest > > > >> > > > (OpenStack, > > > >> > > > oVirt, GNOME Boxes, virt-manager, and countless other mgmt apps). > > > >> > > it follows model set by pvpanic device, it's easier to manage from > > > >> > > migration > > > >> > > POV, one could use it even for old machine types with new qemu > > > >> > > (just by adding > > > >> > > device, it makes instance not backwards migratable to old qemu but > > > >> > > should work > > > >> > > for forward migration) and if user doesn't need it, device could > > > >> > > be just omitted > > > >> > > from CLI. > > > >> > > > > >> > Sure but it means that in effect no one will have this functionality > > > >> > enabled > > > >> > for several years. pvpanic has been around a long time and I rarely > > > >> > see it > > > >> > present in configured guests :-( > > > >> > > > > >> > > > > >> > Regards, > > > >> > Daniel > > > >> > > > >> libvirt runs with -nodefaults, right? I'd argue pretty strongly > > > >> -nodefaults > > > >> shouldn't add optional devices anyway. > > > > > > > > This isn't really adding a device though is it - it is just a well known > > > > location in fw_cfg to receive data. > > > > > > Enabling the device on some configurations by default can be done as a > > > follow-up patch. Can we get this series reviewed & merged? > > > > The problem with the -device approach + turning it on by default is that > > there > > is no way to turn it off again if you don't want it. eg there's way to undo > > an implicit '-device foo' except via -nodefaults, but since libvirt uses > > that > > already it would negate the effect of enabling it by default > > unconditionally. > > It's still possible to add a -machine option that can > enable/disable automatic creation of the device. > > > But I also don't see why it needs to be implemented using -device > if it's not really a device. A boolean machine or fw_cfg > property is good enough for that. Device imho is a combination of guest/host interface and state. > > > > Your previous approach of "-global fw_cfg.vmcoreinfo=on" is nicer in this > > respect, as you can trivially turn it on/off, overriding the default state > > in both directions. > > Both "-global fw_cfg.vmcoreinfo=on|off" and > "-machine vmcoreinfo=on|off" sound good enough to me. I can live with the second option if people really want it. I'd like to see some way to add these things without adding to the mess that is the pc initialization but oh well. > -- > Eduardo
Re: [Qemu-devel] [PATCH v6 2/7] hw/misc: add vmcoreinfo device
On Tue, Oct 10, 2017 at 03:01:10PM -0300, Eduardo Habkost wrote: > On Tue, Oct 10, 2017 at 04:06:28PM +0100, Daniel P. Berrange wrote: > > On Tue, Oct 10, 2017 at 05:00:18PM +0200, Marc-André Lureau wrote: > > > Hi > > > > > > On Tue, Oct 10, 2017 at 10:31 AM, Daniel P. Berrange > > > wrote: > > > > On Tue, Oct 10, 2017 at 12:44:26AM +0300, Michael S. Tsirkin wrote: > > > >> On Mon, Oct 09, 2017 at 02:02:18PM +0100, Daniel P. Berrange wrote: > > > >> > On Mon, Oct 09, 2017 at 02:43:44PM +0200, Igor Mammedov wrote: > > > >> > > On Mon, 9 Oct 2017 12:03:36 +0100 > > > >> > > "Daniel P. Berrange" wrote: > > > >> > > > > > >> > > > On Mon, Sep 11, 2017 at 06:59:24PM +0200, Marc-André Lureau > > > >> > > > wrote: > > > >> > > > > See docs/specs/vmcoreinfo.txt for details. > > > >> > > > > > > > >> > > > > "etc/vmcoreinfo" fw_cfg entry is added when using "-device > > > >> > > > > vmcoreinfo". > > > >> > > > > > > >> > > > I'm wondering if you considered just adding the entry to fw_cfg > > > >> > > > by > > > >> > > > default, without requiring any -device arg ? Unless I'm > > > >> > > > misunderstanding, > > > >> > > > this doesn't feel like a device to me - its just a well known > > > >> > > > bucket > > > >> > > > in fw_cfg IIUC ? Obviously its existance would need to be tied > > > >> > > > to > > > >> > > > the latest machine type for ABI reasons though. The benefit of > > > >> > > > this > > > >> > > > is that it would "just work" without us having to plumb it > > > >> > > > through to > > > >> > > > all the downstream applications that use QEMU for mgmt guest > > > >> > > > (OpenStack, > > > >> > > > oVirt, GNOME Boxes, virt-manager, and countless other mgmt apps). > > > >> > > it follows model set by pvpanic device, it's easier to manage from > > > >> > > migration > > > >> > > POV, one could use it even for old machine types with new qemu > > > >> > > (just by adding > > > >> > > device, it makes instance not backwards migratable to old qemu but > > > >> > > should work > > > >> > > for forward migration) and if user doesn't need it, device could > > > >> > > be just omitted > > > >> > > from CLI. > > > >> > > > > >> > Sure but it means that in effect no one will have this functionality > > > >> > enabled > > > >> > for several years. pvpanic has been around a long time and I rarely > > > >> > see it > > > >> > present in configured guests :-( > > > >> > > > > >> > > > > >> > Regards, > > > >> > Daniel > > > >> > > > >> libvirt runs with -nodefaults, right? I'd argue pretty strongly > > > >> -nodefaults > > > >> shouldn't add optional devices anyway. > > > > > > > > This isn't really adding a device though is it - it is just a well known > > > > location in fw_cfg to receive data. > > > > > > Enabling the device on some configurations by default can be done as a > > > follow-up patch. Can we get this series reviewed & merged? > > > > The problem with the -device approach + turning it on by default is that > > there > > is no way to turn it off again if you don't want it. eg there's way to undo > > an implicit '-device foo' except via -nodefaults, but since libvirt uses > > that > > already it would negate the effect of enabling it by default > > unconditionally. > > It's still possible to add a -machine option that can > enable/disable automatic creation of the device. > > But I also don't see why it needs to be implemented using -device > if it's not really a device. A boolean machine or fw_cfg > property is good enough for that. It certainly feels like a device. It has state (that needs to be migrated), it has a host/guest interface. > > > > Your previous approach of "-global fw_cfg.vmcoreinfo=on" is nicer in this > > respect, as you can trivially turn it on/off, overriding the default state > > in both directions. > > Both "-global fw_cfg.vmcoreinfo=on|off" and > "-machine vmcoreinfo=on|off" sound good enough to me. Certainly not a fw cfg flag. Can be a machine flag I guess but then we'd have to open-code each such device. And don't forget auto - this is what Daniel asks for. I don't necessarily see this device as so special and think a generic interface to control what goes into the machine would be better (e.g. look how you use hacky -global to control fw cfg options, it only works if there's a single one), but if everyone thinks otherwise and agrees we should have it in there by default, and a property to disable, fine. Can be a patch on top though. > -- > Eduardo
Re: [Qemu-devel] [PATCH] spapr_cpu_core: instantiate CPUs separately
On Fri, Oct 13, 2017 at 01:31:44PM +0200, Greg Kurz wrote: > The current code assumes that only the CPU core object holds a > reference on each individual CPU object, and happily frees their > allocated memory when the core is unrealized. This is dangerous > as some other code can legitimely keep a pointer to a CPU if it > calls object_ref(), but it would end up with a dangling pointer. > > Let's allocate all CPUs with object_new() and let QOM frees them > when their reference count reaches zero. This greatly simplify the > code as we don't have to fiddle with the instance size anymore. > > Signed-off-by: Greg Kurz So, I'm pretty sure my first drafts of the core stuff did things this waym and it got nacked, for QOM lifetime reasons that I never really understood. > --- > v2: - mention code simplification in changelog > - use PowerPCCPU * and Object * instead of void * > --- > hw/ppc/spapr.c | 11 +++ > hw/ppc/spapr_cpu_core.c | 19 +++ > include/hw/ppc/spapr_cpu_core.h |2 +- > 3 files changed, 11 insertions(+), 21 deletions(-) > > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > index fd9813bde82f..d9555a3677be 100644 > --- a/hw/ppc/spapr.c > +++ b/hw/ppc/spapr.c > @@ -3153,12 +3153,10 @@ void spapr_core_release(DeviceState *dev) > > if (smc->pre_2_10_has_unused_icps) { > sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); > -sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(cc)); > -size_t size = object_type_get_instance_size(scc->cpu_type); > int i; > > for (i = 0; i < cc->nr_threads; i++) { > -CPUState *cs = CPU(sc->threads + i * size); > +CPUState *cs = CPU(sc->threads[i]); > > pre_2_10_vmstate_register_dummy_icp(cs->cpu_index); > } > @@ -3204,7 +3202,7 @@ static void spapr_core_plug(HotplugHandler > *hotplug_dev, DeviceState *dev, > sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); > sPAPRCPUCore *core = SPAPR_CPU_CORE(OBJECT(dev)); > CPUCore *cc = CPU_CORE(dev); > -CPUState *cs = CPU(core->threads); > +CPUState *cs = CPU(core->threads[0]); > sPAPRDRConnector *drc; > Error *local_err = NULL; > int smt = kvmppc_smt_threads(); > @@ -3249,15 +3247,12 @@ static void spapr_core_plug(HotplugHandler > *hotplug_dev, DeviceState *dev, > core_slot->cpu = OBJECT(dev); > > if (smc->pre_2_10_has_unused_icps) { > -sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(cc)); > -size_t size = object_type_get_instance_size(scc->cpu_type); > int i; > > for (i = 0; i < cc->nr_threads; i++) { > sPAPRCPUCore *sc = SPAPR_CPU_CORE(dev); > -void *obj = sc->threads + i * size; > > -cs = CPU(obj); > +cs = CPU(sc->threads[i]); > pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index); > } > } > diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c > index 3a4c17401226..588f9b45714a 100644 > --- a/hw/ppc/spapr_cpu_core.c > +++ b/hw/ppc/spapr_cpu_core.c > @@ -79,13 +79,11 @@ const char *spapr_get_cpu_core_type(const char *cpu_type) > static void spapr_cpu_core_unrealizefn(DeviceState *dev, Error **errp) > { > sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); > -sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev)); > -size_t size = object_type_get_instance_size(scc->cpu_type); > CPUCore *cc = CPU_CORE(dev); > int i; > > for (i = 0; i < cc->nr_threads; i++) { > -void *obj = sc->threads + i * size; > +Object *obj = OBJECT(sc->threads[i]); > DeviceState *dev = DEVICE(obj); > CPUState *cs = CPU(dev); > PowerPCCPU *cpu = POWERPC_CPU(cs); > @@ -146,9 +144,8 @@ static void spapr_cpu_core_realize(DeviceState *dev, > Error **errp) > sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); > sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev)); > CPUCore *cc = CPU_CORE(OBJECT(dev)); > -size_t size; > Error *local_err = NULL; > -void *obj; > +Object *obj; > int i, j; > > if (!spapr) { > @@ -156,18 +153,16 @@ static void spapr_cpu_core_realize(DeviceState *dev, > Error **errp) > return; > } > > -size = object_type_get_instance_size(scc->cpu_type); > -sc->threads = g_malloc0(size * cc->nr_threads); > +sc->threads = g_new(PowerPCCPU *, cc->nr_threads); > for (i = 0; i < cc->nr_threads; i++) { > char id[32]; > CPUState *cs; > PowerPCCPU *cpu; > > -obj = sc->threads + i * size; > +obj = object_new(scc->cpu_type); > > -object_initialize(obj, size, scc->cpu_type); > cs = CPU(obj); > -cpu = POWERPC_CPU(cs); > +cpu = sc->threads[i] = POWERPC_CPU(obj); > cs->cpu_index = cc->core_id + i; > cpu->vcpu_id = (cc->core_id * spapr->vsmt / smp_threads) + i; >
[Qemu-devel] [PATCH v4 7/8] nbd/client: prepare nbd_receive_reply for structured reply
From: Vladimir Sementsov-Ogievskiy In following patch nbd_receive_reply will be used both for simple and structured reply header receiving. NBDReply is altered into union of simple reply header and structured reply chunk header, simple error translation moved to block/nbd-client to be consistent with further structured reply error translation. Signed-off-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Eric Blake --- include/block/nbd.h | 30 --- block/nbd-client.c | 8 ++-- nbd/client.c| 104 +--- nbd/trace-events| 3 +- 4 files changed, 113 insertions(+), 32 deletions(-) diff --git a/include/block/nbd.h b/include/block/nbd.h index 225e9575e4..2ee1578420 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -57,12 +57,6 @@ struct NBDRequest { }; typedef struct NBDRequest NBDRequest; -struct NBDReply { -uint64_t handle; -uint32_t error; -}; -typedef struct NBDReply NBDReply; - typedef struct NBDSimpleReply { uint32_t magic; /* NBD_SIMPLE_REPLY_MAGIC */ uint32_t error; @@ -78,6 +72,20 @@ typedef struct NBDStructuredReplyChunk { uint32_t length; /* length of payload */ } QEMU_PACKED NBDStructuredReplyChunk; +typedef union NBDReply { +NBDSimpleReply simple; +NBDStructuredReplyChunk structured; +struct { +/* @magic and @handle fields have the same offset and size both in + * simple reply and structured reply chunk, so let them be accessible + * without ".simple." or ".structured." specification + */ +uint32_t magic; +uint32_t _skip; +uint64_t handle; +} QEMU_PACKED; +} NBDReply; + /* Header of NBD_REPLY_TYPE_OFFSET_DATA, complete NBD_REPLY_TYPE_OFFSET_HOLE */ typedef struct NBDStructuredRead { NBDStructuredReplyChunk h; @@ -256,4 +264,14 @@ void nbd_client_put(NBDClient *client); void nbd_server_start(SocketAddress *addr, const char *tls_creds, Error **errp); +static inline bool nbd_reply_is_simple(NBDReply *reply) +{ +return reply->magic == NBD_SIMPLE_REPLY_MAGIC; +} + +static inline bool nbd_reply_is_structured(NBDReply *reply) +{ +return reply->magic == NBD_STRUCTURED_REPLY_MAGIC; +} + #endif diff --git a/block/nbd-client.c b/block/nbd-client.c index c0683c3c83..58493b7ac4 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -92,7 +92,9 @@ static coroutine_fn void nbd_read_reply_entry(void *opaque) i = HANDLE_TO_INDEX(s, s->reply.handle); if (i >= MAX_NBD_REQUESTS || !s->requests[i].coroutine || -!s->requests[i].receiving) { +!s->requests[i].receiving || +nbd_reply_is_structured(&s->reply)) +{ break; } @@ -194,8 +196,8 @@ static int nbd_co_receive_reply(NBDClientSession *s, ret = -EIO; } else { assert(s->reply.handle == handle); -ret = -s->reply.error; -if (qiov && s->reply.error == 0) { +ret = -nbd_errno_to_system_errno(s->reply.simple.error); +if (qiov && ret == 0) { if (qio_channel_readv_all(s->ioc, qiov->iov, qiov->niov, NULL) < 0) { ret = -EIO; diff --git a/nbd/client.c b/nbd/client.c index 9d335fcaba..eeb23ae934 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -907,6 +907,57 @@ int nbd_send_request(QIOChannel *ioc, NBDRequest *request) return nbd_write(ioc, buf, sizeof(buf), NULL); } +/* nbd_receive_simple_reply + * Read simple reply except magic field (which should be already read). + * Payload is not read (payload is possible for CMD_READ, but here we even + * don't know whether it take place or not). + */ +static int nbd_receive_simple_reply(QIOChannel *ioc, NBDSimpleReply *reply, +Error **errp) +{ +int ret; + +assert(reply->magic == NBD_SIMPLE_REPLY_MAGIC); + +ret = nbd_read(ioc, (uint8_t *)reply + sizeof(reply->magic), + sizeof(*reply) - sizeof(reply->magic), errp); +if (ret < 0) { +return ret; +} + +be32_to_cpus(&reply->error); +be64_to_cpus(&reply->handle); + +return 0; +} + +/* nbd_receive_structured_reply_chunk + * Read structured reply chunk except magic field (which should be already + * read). + * Payload is not read. + */ +static int nbd_receive_structured_reply_chunk(QIOChannel *ioc, + NBDStructuredReplyChunk *chunk, + Error **errp) +{ +int ret; + +assert(chunk->magic == NBD_STRUCTURED_REPLY_MAGIC); + +ret = nbd_read(ioc, (uint8_t *)chunk + sizeof(chunk->magic), + sizeof(*chunk) - sizeof(chunk->magic), errp); +if (ret < 0) { +return ret; +} + +be16_to_cpus(&chunk->flags); +be16_to_cpus(&chunk->type); +be64_to_cpus(&chunk->handle); +be32_to_cpus(&chunk->length); + +return 0; +} + /
[Qemu-devel] [PATCH v4 6/8] nbd/client: refactor nbd_receive_starttls
From: Vladimir Sementsov-Ogievskiy Split out nbd_request_simple_option to be reused for structured reply option. Signed-off-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Eric Blake --- v4: reduce redundant traces, typo fix in commit message --- nbd/client.c | 69 ++-- nbd/trace-events | 4 +--- 2 files changed, 48 insertions(+), 25 deletions(-) diff --git a/nbd/client.c b/nbd/client.c index 50f36b511e..9d335fcaba 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -508,35 +508,60 @@ static int nbd_receive_query_exports(QIOChannel *ioc, } } +/* nbd_request_simple_option: Send an option request, and parse the reply + * return 1 for successful negotiation, + *0 if operation is unsupported, + *-1 with errp set for any other error + */ +static int nbd_request_simple_option(QIOChannel *ioc, int opt, Error **errp) +{ +nbd_opt_reply reply; + +if (nbd_send_option_request(ioc, opt, 0, NULL, errp) < 0) { +return -1; +} + +if (nbd_receive_option_reply(ioc, opt, &reply, errp) < 0) { +return -1; +} + +if (reply.length != 0) { +error_setg(errp, "Option %d ('%s') response length is %" PRIu32 + " (it should be zero)", opt, nbd_opt_lookup(opt), + reply.length); +nbd_send_opt_abort(ioc); +return -1; +} + +if (reply.type == NBD_REP_ERR_UNSUP) { +return 0; +} + +if (reply.type != NBD_REP_ACK) { +error_setg(errp, "Server rejected request for option %d (%s) " + "with reply %" PRIx32 " (%s)", opt, nbd_opt_lookup(opt), + reply.type, nbd_rep_lookup(reply.type)); +nbd_send_opt_abort(ioc); +return -1; +} + +return 1; +} + static QIOChannel *nbd_receive_starttls(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, const char *hostname, Error **errp) { -nbd_opt_reply reply; +int ret; QIOChannelTLS *tioc; struct NBDTLSHandshakeData data = { 0 }; -trace_nbd_receive_starttls_request(); -if (nbd_send_option_request(ioc, NBD_OPT_STARTTLS, 0, NULL, errp) < 0) { -return NULL; -} - -trace_nbd_receive_starttls_reply(); -if (nbd_receive_option_reply(ioc, NBD_OPT_STARTTLS, &reply, errp) < 0) { -return NULL; -} - -if (reply.type != NBD_REP_ACK) { -error_setg(errp, "Server rejected request to start TLS %" PRIx32, - reply.type); -nbd_send_opt_abort(ioc); -return NULL; -} - -if (reply.length != 0) { -error_setg(errp, "Start TLS response was not zero %" PRIu32, - reply.length); -nbd_send_opt_abort(ioc); +ret = nbd_request_simple_option(ioc, NBD_OPT_STARTTLS, errp); +if (ret <= 0) { +if (ret == 0) { +error_setg(errp, "Server don't support STARTTLS option"); +nbd_send_opt_abort(ioc); +} return NULL; } diff --git a/nbd/trace-events b/nbd/trace-events index 880f211c07..39b723d1d8 100644 --- a/nbd/trace-events +++ b/nbd/trace-events @@ -8,9 +8,7 @@ nbd_opt_go_info_unknown(int info, const char *name) "Ignoring unknown info %d (% nbd_opt_go_info_block_size(uint32_t minimum, uint32_t preferred, uint32_t maximum) "Block sizes are 0x%" PRIx32 ", 0x%" PRIx32 ", 0x%" PRIx32 nbd_receive_query_exports_start(const char *wantname) "Querying export list for '%s'" nbd_receive_query_exports_success(const char *wantname) "Found desired export name '%s'" -nbd_receive_starttls_request(void) "Requesting TLS from server" -nbd_receive_starttls_reply(void) "Getting TLS reply from server" -nbd_receive_starttls_new_client(void) "TLS request approved, setting up TLS" +nbd_receive_starttls_new_client(void) "Setting up TLS" nbd_receive_starttls_tls_handshake(void) "Starting TLS handshake" nbd_receive_negotiate(void *tlscreds, const char *hostname) "Receiving negotiation tlscreds=%p hostname=%s" nbd_receive_negotiate_magic(uint64_t magic) "Magic is 0x%" PRIx64 -- 2.13.6
[Qemu-devel] [PATCH v4 4/8] nbd: Minimal structured read for server
From: Vladimir Sementsov-Ogievskiy Minimal implementation of structured read: one structured reply chunk, no segmentation. Minimal structured error implementation: no text message. Support DF flag, but just ignore it, as there is no segmentation any way. Signed-off-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Eric Blake --- v4: better _DF flag handling, convert errno to wire format, add comments and tracing, rework structured error for less churn when adding text message later, don't kill connection on redundant client option --- nbd/server.c | 106 +-- nbd/trace-events | 2 ++ 2 files changed, 98 insertions(+), 10 deletions(-) diff --git a/nbd/server.c b/nbd/server.c index efb6003364..23dc6be708 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -100,6 +100,8 @@ struct NBDClient { QTAILQ_ENTRY(NBDClient) next; int nb_requests; bool closing; + +bool structured_reply; }; /* That's all folks */ @@ -762,6 +764,23 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags, return ret; } break; + +case NBD_OPT_STRUCTURED_REPLY: +if (client->structured_reply) { +ret = nbd_negotiate_send_rep_err( +client->ioc, NBD_REP_ERR_INVALID, option, errp, +"structured reply already negotiated"); +} else { +ret = nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, + option, errp); +} +if (ret < 0) { +return ret; +} +client->structured_reply = true; +myflags |= NBD_CMD_FLAG_DF; +break; + default: if (nbd_drop(client->ioc, length, errp) < 0) { return -EIO; @@ -1236,6 +1255,59 @@ static int nbd_co_send_simple_reply(NBDClient *client, return nbd_co_send_iov(client, iov, len ? 2 : 1, errp); } +static inline void set_be_chunk(NBDStructuredReplyChunk *chunk, uint16_t flags, +uint16_t type, uint64_t handle, uint32_t length) +{ +stl_be_p(&chunk->magic, NBD_STRUCTURED_REPLY_MAGIC); +stw_be_p(&chunk->flags, flags); +stw_be_p(&chunk->type, type); +stq_be_p(&chunk->handle, handle); +stl_be_p(&chunk->length, length); +} + +static int coroutine_fn nbd_co_send_structured_read(NBDClient *client, +uint64_t handle, +uint64_t offset, +void *data, +size_t size, +Error **errp) +{ +NBDStructuredRead chunk; +struct iovec iov[] = { +{.iov_base = &chunk, .iov_len = sizeof(chunk)}, +{.iov_base = data, .iov_len = size} +}; + +trace_nbd_co_send_structured_read(handle, offset, data, size); +set_be_chunk(&chunk.h, NBD_REPLY_FLAG_DONE, NBD_REPLY_TYPE_OFFSET_DATA, + handle, sizeof(chunk) - sizeof(chunk.h) + size); +stq_be_p(&chunk.offset, offset); + +return nbd_co_send_iov(client, iov, 2, errp); +} + +static int coroutine_fn nbd_co_send_structured_error(NBDClient *client, + uint64_t handle, + uint32_t error, + Error **errp) +{ +NBDStructuredError chunk; +int nbd_err = system_errno_to_nbd_errno(error); +struct iovec iov[] = { +{.iov_base = &chunk, .iov_len = sizeof(chunk)}, +/* FIXME: Support human-readable error message */ +}; + +assert(nbd_err); +trace_nbd_co_send_structured_error(handle, nbd_err); +set_be_chunk(&chunk.h, NBD_REPLY_FLAG_DONE, NBD_REPLY_TYPE_ERROR, handle, + sizeof(chunk) - sizeof(chunk.h)); +stl_be_p(&chunk.error, nbd_err); +stw_be_p(&chunk.message_length, 0); + +return nbd_co_send_iov(client, iov, 1, errp); +} + /* nbd_co_receive_request * Collect a client request. Return 0 if request looks valid, -EIO to drop * connection right away, and any other negative value to report an error to @@ -1246,6 +1318,7 @@ static int nbd_co_receive_request(NBDRequestData *req, NBDRequest *request, Error **errp) { NBDClient *client = req->client; +int valid_flags; g_assert(qemu_in_coroutine()); assert(client->recv_coroutine == qemu_coroutine_self()); @@ -1307,13 +1380,15 @@ static int nbd_co_receive_request(NBDRequestData *req, NBDRequest *request, (uint64_t)client->exp->size); return request->type == NBD_CMD_WRITE ? -ENOSPC : -EINVAL; } -if (request->flags & ~(NBD_CMD_
[Qemu-devel] [PATCH v4 3/8] nbd: Expose constants and structs for structured read
Upcoming patches will implement the NBD structured reply extension [1] for both client and server roles. Declare the constants, structs, and lookup routines that will be valuable whether the server or client code is backported in isolation. This includes moving one constant from an internal header to the public header, as part of the structured read processing will be done in block/nbd-client.c rather than nbd/client.c. [1]https://github.com/NetworkBlockDevice/nbd/blob/extension-structured-reply/doc/proto.md Based on patches from Vladimir Sementsov-Ogievskiy. Signed-off-by: Eric Blake --- include/block/nbd.h | 41 + nbd/nbd-internal.h | 2 +- nbd/common.c| 27 +++ nbd/server.c| 2 ++ 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/include/block/nbd.h b/include/block/nbd.h index dc62b5cd19..225e9575e4 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -69,6 +69,28 @@ typedef struct NBDSimpleReply { uint64_t handle; } QEMU_PACKED NBDSimpleReply; +/* Header of all structured replies */ +typedef struct NBDStructuredReplyChunk { +uint32_t magic; /* NBD_STRUCTURED_REPLY_MAGIC */ +uint16_t flags; /* combination of NBD_REPLY_FLAG_* */ +uint16_t type; /* NBD_REPLY_TYPE_* */ +uint64_t handle; /* request handle */ +uint32_t length; /* length of payload */ +} QEMU_PACKED NBDStructuredReplyChunk; + +/* Header of NBD_REPLY_TYPE_OFFSET_DATA, complete NBD_REPLY_TYPE_OFFSET_HOLE */ +typedef struct NBDStructuredRead { +NBDStructuredReplyChunk h; +uint64_t offset; +} QEMU_PACKED NBDStructuredRead; + +/* Header of all NBD_REPLY_TYPE_ERROR* errors */ +typedef struct NBDStructuredError { +NBDStructuredReplyChunk h; +uint32_t error; +uint16_t message_length; +} QEMU_PACKED NBDStructuredError; + /* Transmission (export) flags: sent from server to client during handshake, but describe what will happen during transmission */ #define NBD_FLAG_HAS_FLAGS (1 << 0) /* Flags are there */ @@ -79,6 +101,7 @@ typedef struct NBDSimpleReply { rotational media */ #define NBD_FLAG_SEND_TRIM (1 << 5) /* Send TRIM (discard) */ #define NBD_FLAG_SEND_WRITE_ZEROES (1 << 6) /* Send WRITE_ZEROES */ +#define NBD_FLAG_SEND_DF (1 << 7) /* Send DF (Do not Fragment) */ /* New-style handshake (global) flags, sent from server to client, and control what will happen during handshake phase. */ @@ -125,6 +148,7 @@ typedef struct NBDSimpleReply { /* Request flags, sent from client to server during transmission phase */ #define NBD_CMD_FLAG_FUA(1 << 0) /* 'force unit access' during write */ #define NBD_CMD_FLAG_NO_HOLE(1 << 1) /* don't punch hole on zero run */ +#define NBD_CMD_FLAG_DF (1 << 2) /* don't fragment structured read */ /* Supported request types */ enum { @@ -149,6 +173,22 @@ enum { * aren't overflowing some other buffer. */ #define NBD_MAX_NAME_SIZE 256 +/* Two types of reply structures */ +#define NBD_SIMPLE_REPLY_MAGIC 0x67446698 +#define NBD_STRUCTURED_REPLY_MAGIC 0x668e33ef + +/* Structured reply flags */ +#define NBD_REPLY_FLAG_DONE (1 << 0) /* This reply-chunk is last */ + +/* Structured reply types */ +#define NBD_REPLY_ERR(value) ((1 << 15) | (value)) + +#define NBD_REPLY_TYPE_NONE 0 +#define NBD_REPLY_TYPE_OFFSET_DATA 1 +#define NBD_REPLY_TYPE_OFFSET_HOLE 2 +#define NBD_REPLY_TYPE_ERROR NBD_REPLY_ERR(1) +#define NBD_REPLY_TYPE_ERROR_OFFSET NBD_REPLY_ERR(2) + /* NBD errors are based on errno numbers, so there is a 1:1 mapping, * but only a limited set of errno values is specified in the protocol. * Everything else is squashed to EINVAL. @@ -159,6 +199,7 @@ enum { #define NBD_ENOMEM 12 #define NBD_EINVAL 22 #define NBD_ENOSPC 28 +#define NBD_EOVERFLOW 75 #define NBD_ESHUTDOWN 108 /* Details collected by NBD_OPT_EXPORT_NAME and NBD_OPT_GO */ diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h index df6c8b2f24..4f24d6e57d 100644 --- a/nbd/nbd-internal.h +++ b/nbd/nbd-internal.h @@ -47,7 +47,6 @@ #define NBD_OLDSTYLE_NEGOTIATE_SIZE (8 + 8 + 8 + 4 + 124) #define NBD_REQUEST_MAGIC 0x25609513 -#define NBD_SIMPLE_REPLY_MAGIC 0x67446698 #define NBD_OPTS_MAGIC 0x49484156454F5054LL #define NBD_CLIENT_MAGIC0x420281861253LL #define NBD_REP_MAGIC 0x0003e889045565a9LL @@ -114,6 +113,7 @@ const char *nbd_opt_lookup(uint32_t opt); const char *nbd_rep_lookup(uint32_t rep); const char *nbd_info_lookup(uint16_t info); const char *nbd_cmd_lookup(uint16_t info); +const char *nbd_reply_type_lookup(uint16_t type); const char *nbd_err_lookup(int err); int nbd_drop(QIOChannel *ioc, size_t size, Error **errp); diff --git a/nbd/common.c b/nbd/common.c index 593904f148..6047d71748 100644 --- a/nbd/common.c +++ b/nbd/common.c @@ -151,6 +151,28 @@ const c
[Qemu-devel] [PATCH v4 8/8] nbd: Move nbd_read() to common header
An upcoming change to block/nbd-client.c will want to read the tail of a structured reply chunk directly from the wire. Move this function to make it easier. Based on a patch from Vladimir Sementsov-Ogievskiy. Signed-off-by: Eric Blake --- include/block/nbd.h | 10 ++ nbd/nbd-internal.h | 9 - 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/include/block/nbd.h b/include/block/nbd.h index 2ee1578420..da6e305dd5 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -264,6 +264,16 @@ void nbd_client_put(NBDClient *client); void nbd_server_start(SocketAddress *addr, const char *tls_creds, Error **errp); + +/* nbd_read + * Reads @size bytes from @ioc. Returns 0 on success. + */ +static inline int nbd_read(QIOChannel *ioc, void *buffer, size_t size, + Error **errp) +{ +return qio_channel_read_all(ioc, buffer, size, errp) < 0 ? -EIO : 0; +} + static inline bool nbd_reply_is_simple(NBDReply *reply) { return reply->magic == NBD_SIMPLE_REPLY_MAGIC; diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h index 4f24d6e57d..b64eb1cc9b 100644 --- a/nbd/nbd-internal.h +++ b/nbd/nbd-internal.h @@ -82,15 +82,6 @@ static inline int nbd_read_eof(QIOChannel *ioc, void *buffer, size_t size, return ret; } -/* nbd_read - * Reads @size bytes from @ioc. Returns 0 on success. - */ -static inline int nbd_read(QIOChannel *ioc, void *buffer, size_t size, - Error **errp) -{ -return qio_channel_read_all(ioc, buffer, size, errp) < 0 ? -EIO : 0; -} - /* nbd_write * Writes @size bytes to @ioc. Returns 0 on success. */ -- 2.13.6
[Qemu-devel] [PATCH v4 2/8] nbd: Move nbd_errno_to_system_errno() to public header
This is needed in preparation for structured reply handling, as we will be performing the translation from NBD error to system errno value higher in the stack at block/nbd-client.c. --- include/block/nbd.h | 13 + nbd/nbd-internal.h | 12 nbd/client.c| 32 nbd/common.c| 34 ++ nbd/trace-events| 4 +++- 5 files changed, 50 insertions(+), 45 deletions(-) diff --git a/include/block/nbd.h b/include/block/nbd.h index a6df5ce8b5..dc62b5cd19 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -149,6 +149,18 @@ enum { * aren't overflowing some other buffer. */ #define NBD_MAX_NAME_SIZE 256 +/* NBD errors are based on errno numbers, so there is a 1:1 mapping, + * but only a limited set of errno values is specified in the protocol. + * Everything else is squashed to EINVAL. + */ +#define NBD_SUCCESS0 +#define NBD_EPERM 1 +#define NBD_EIO5 +#define NBD_ENOMEM 12 +#define NBD_EINVAL 22 +#define NBD_ENOSPC 28 +#define NBD_ESHUTDOWN 108 + /* Details collected by NBD_OPT_EXPORT_NAME and NBD_OPT_GO */ struct NBDExportInfo { /* Set by client before nbd_receive_negotiate() */ @@ -172,6 +184,7 @@ int nbd_send_request(QIOChannel *ioc, NBDRequest *request); int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp); int nbd_client(int fd); int nbd_disconnect(int fd); +int nbd_errno_to_system_errno(int err); typedef struct NBDExport NBDExport; typedef struct NBDClient NBDClient; diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h index 4bfe5be884..df6c8b2f24 100644 --- a/nbd/nbd-internal.h +++ b/nbd/nbd-internal.h @@ -64,18 +64,6 @@ #define NBD_SET_TIMEOUT _IO(0xab, 9) #define NBD_SET_FLAGS _IO(0xab, 10) -/* NBD errors are based on errno numbers, so there is a 1:1 mapping, - * but only a limited set of errno values is specified in the protocol. - * Everything else is squashed to EINVAL. - */ -#define NBD_SUCCESS0 -#define NBD_EPERM 1 -#define NBD_EIO5 -#define NBD_ENOMEM 12 -#define NBD_EINVAL 22 -#define NBD_ENOSPC 28 -#define NBD_ESHUTDOWN 108 - /* nbd_read_eof * Tries to read @size bytes from @ioc. * Returns 1 on success diff --git a/nbd/client.c b/nbd/client.c index 59d7c9d49f..50f36b511e 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -22,38 +22,6 @@ #include "trace.h" #include "nbd-internal.h" -static int nbd_errno_to_system_errno(int err) -{ -int ret; -switch (err) { -case NBD_SUCCESS: -ret = 0; -break; -case NBD_EPERM: -ret = EPERM; -break; -case NBD_EIO: -ret = EIO; -break; -case NBD_ENOMEM: -ret = ENOMEM; -break; -case NBD_ENOSPC: -ret = ENOSPC; -break; -case NBD_ESHUTDOWN: -ret = ESHUTDOWN; -break; -default: -trace_nbd_unknown_error(err); -/* fallthrough */ -case NBD_EINVAL: -ret = EINVAL; -break; -} -return ret; -} - /* Definitions for opaque data types */ static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports); diff --git a/nbd/common.c b/nbd/common.c index 7456021f7e..593904f148 100644 --- a/nbd/common.c +++ b/nbd/common.c @@ -18,6 +18,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" +#include "trace.h" #include "nbd-internal.h" /* Discard length bytes from channel. Return -errno on failure and 0 on @@ -171,3 +172,36 @@ const char *nbd_err_lookup(int err) return ""; } } + + +int nbd_errno_to_system_errno(int err) +{ +int ret; +switch (err) { +case NBD_SUCCESS: +ret = 0; +break; +case NBD_EPERM: +ret = EPERM; +break; +case NBD_EIO: +ret = EIO; +break; +case NBD_ENOMEM: +ret = ENOMEM; +break; +case NBD_ENOSPC: +ret = ENOSPC; +break; +case NBD_ESHUTDOWN: +ret = ESHUTDOWN; +break; +default: +trace_nbd_unknown_error(err); +/* fallthrough */ +case NBD_EINVAL: +ret = EINVAL; +break; +} +return ret; +} diff --git a/nbd/trace-events b/nbd/trace-events index 9a72f458b2..d3b702dd9a 100644 --- a/nbd/trace-events +++ b/nbd/trace-events @@ -1,5 +1,4 @@ # nbd/client.c -nbd_unknown_error(int err) "Squashing unexpected error %d to EINVAL" nbd_send_option_request(uint32_t opt, const char *name, uint32_t len) "Sending option request %" PRIu32" (%s), len %" PRIu32 nbd_receive_option_reply(uint32_t option, const char *optname, uint32_t type, const char *typename, uint32_t length) "Received option reply 0x%" PRIx32" (%s), type 0x%" PRIx32" (%s), len %" PRIu32 nbd_reply_err_unsup(uint32_t option, const char *name) "server doesn't understand request 0x%" PRIx32 " (%s), attempting fallback" @@ -31,6 +30,9 @@ nbd_client_clear_socket(void) "Clearing NBD socket" nbd_send_request(uint64_t from, u
[Qemu-devel] [PATCH v4 5/8] nbd/server: Include human-readable message in structured errors
The NBD spec permits including a human-readable error string if structured replies are in force, so we might as well send the client the message that we logged on any error. Signed-off-by: Eric Blake --- nbd/server.c | 22 -- nbd/trace-events | 2 +- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/nbd/server.c b/nbd/server.c index 23dc6be708..8085d79076 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1289,23 +1289,25 @@ static int coroutine_fn nbd_co_send_structured_read(NBDClient *client, static int coroutine_fn nbd_co_send_structured_error(NBDClient *client, uint64_t handle, uint32_t error, + char *msg, Error **errp) { NBDStructuredError chunk; int nbd_err = system_errno_to_nbd_errno(error); struct iovec iov[] = { {.iov_base = &chunk, .iov_len = sizeof(chunk)}, -/* FIXME: Support human-readable error message */ +{.iov_base = msg, .iov_len = strlen(msg)}, }; assert(nbd_err); -trace_nbd_co_send_structured_error(handle, nbd_err); +trace_nbd_co_send_structured_error(handle, nbd_err, + nbd_err_lookup(nbd_err), msg); set_be_chunk(&chunk.h, NBD_REPLY_FLAG_DONE, NBD_REPLY_TYPE_ERROR, handle, sizeof(chunk) - sizeof(chunk.h)); stl_be_p(&chunk.error, nbd_err); -stw_be_p(&chunk.message_length, 0); +stw_be_p(&chunk.message_length, iov[1].iov_len); -return nbd_co_send_iov(client, iov, 1, errp); +return nbd_co_send_iov(client, iov, 1 + !!iov[1].iov_len, errp); } /* nbd_co_receive_request @@ -1406,6 +1408,7 @@ static coroutine_fn void nbd_trip(void *opaque) int flags; int reply_data_len = 0; Error *local_err = NULL; +char *msg = NULL; trace_nbd_trip(); if (client->closing) { @@ -1521,14 +1524,20 @@ reply: if (local_err) { /* If we get here, local_err was not a fatal error, and should be sent * to the client. */ +assert(ret < 0); +msg = g_strdup(error_get_pretty(local_err)); error_report_err(local_err); local_err = NULL; } -if (client->structured_reply && request.type == NBD_CMD_READ) { +if (client->structured_reply && +(ret < 0 || request.type == NBD_CMD_READ)) { if (ret < 0) { +if (!msg) { +msg = g_strdup(""); +} ret = nbd_co_send_structured_error(req->client, request.handle, - -ret, &local_err); + -ret, msg, &local_err); } else { ret = nbd_co_send_structured_read(req->client, request.handle, request.from, req->data, @@ -1539,6 +1548,7 @@ reply: ret < 0 ? -ret : 0, req->data, reply_data_len, &local_err); } +g_free(msg); if (ret < 0) { error_prepend(&local_err, "Failed to send reply: "); goto disconnect; diff --git a/nbd/trace-events b/nbd/trace-events index 15a9294445..880f211c07 100644 --- a/nbd/trace-events +++ b/nbd/trace-events @@ -57,7 +57,7 @@ nbd_blk_aio_attached(const char *name, void *ctx) "Export %s: Attaching clients nbd_blk_aio_detach(const char *name, void *ctx) "Export %s: Detaching clients from AIO context %p\n" nbd_co_send_simple_reply(uint64_t handle, uint32_t error, const char *errname, int len) "Send simple reply: handle = %" PRIu64 ", error = %" PRIu32 " (%s), len = %d" nbd_co_send_structured_read(uint64_t handle, uint64_t offset, void *data, size_t size) "Send structured read data reply: handle = %" PRIu64 ", offset = %" PRIu64 ", data = %p, len = %zu" -nbd_co_send_structured_error(uint64_t handle, int err) "Send structured error reply: handle = %" PRIu64 ", error = %d" +nbd_co_send_structured_error(uint64_t handle, int err, const char *errname, const char *msg) "Send structured error reply: handle = %" PRIu64 ", error = %d (%s), msg = '%s'" nbd_co_receive_request_decode_type(uint64_t handle, uint16_t type, const char *name) "Decoding type: handle = %" PRIu64 ", type = %" PRIu16 " (%s)" nbd_co_receive_request_payload_received(uint64_t handle, uint32_t len) "Payload received: handle = %" PRIu64 ", len = %" PRIu32 nbd_co_receive_request_cmd_write(uint32_t len) "Reading %" PRIu32 " byte(s)" -- 2.13.6
[Qemu-devel] [PATCH v4 0/8] nbd mimimal structured read
As mentioned in my review of Vladimir's v3 of this series [1], I had enough tweaks during my review that it's easier to repost things for another round of discussion, adding some of my patches in between his. I did not include his 13/13 "nbd: Minimal structured read for client", where I had a lot of comments, and suggest that Vladimir is in the best position to rebase that patch on top of this v4 series (post it as a 9/8, if desired). [1] https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg02755.html Based-on: <20171015004033.3248-1-ebl...@redhat.com> ([PULL 0/9] NBD patches through 14 Oct) Eric Blake (5): nbd: Include error names in trace messages nbd: Move nbd_errno_to_system_errno() to public header nbd: Expose constants and structs for structured read nbd/server: Include human-readable message in structured errors nbd: Move nbd_read() to common header Vladimir Sementsov-Ogievskiy (3): nbd: Minimal structured read for server nbd/client: refactor nbd_receive_starttls nbd/client: prepare nbd_receive_reply for structured reply include/block/nbd.h | 94 ++-- nbd/nbd-internal.h | 24 +-- block/nbd-client.c | 8 ++- nbd/client.c| 204 +--- nbd/common.c| 84 ++ nbd/server.c| 121 --- nbd/trace-events| 15 ++-- 7 files changed, 427 insertions(+), 123 deletions(-) -- 2.13.6
[Qemu-devel] [PATCH v4 1/8] nbd: Include error names in trace messages
NBD errors were originally sent over the wire based on Linux errno values; but not all the world is Linux, and not all platforms share the same values. Since a number isn't very easy to decipher on all platforms, update the trace messages to include the name of NBD errors being sent/received over the wire. Tweak the trace messages to be at the point where we are using the NBD error, not the translation to the host errno values. Signed-off-by: Eric Blake --- nbd/nbd-internal.h | 1 + nbd/client.c | 3 ++- nbd/common.c | 23 +++ nbd/server.c | 3 ++- nbd/trace-events | 4 ++-- 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h index 11a130d050..4bfe5be884 100644 --- a/nbd/nbd-internal.h +++ b/nbd/nbd-internal.h @@ -126,6 +126,7 @@ const char *nbd_opt_lookup(uint32_t opt); const char *nbd_rep_lookup(uint32_t rep); const char *nbd_info_lookup(uint16_t info); const char *nbd_cmd_lookup(uint16_t info); +const char *nbd_err_lookup(int err); int nbd_drop(QIOChannel *ioc, size_t size, Error **errp); diff --git a/nbd/client.c b/nbd/client.c index cd5a2c80ac..59d7c9d49f 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -940,6 +940,8 @@ int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp) reply->error = ldl_be_p(buf + 4); reply->handle = ldq_be_p(buf + 8); +trace_nbd_receive_reply(magic, reply->error, nbd_err_lookup(reply->error), +reply->handle); reply->error = nbd_errno_to_system_errno(reply->error); if (reply->error == ESHUTDOWN) { @@ -947,7 +949,6 @@ int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp) error_setg(errp, "server shutting down"); return -EINVAL; } -trace_nbd_receive_reply(magic, reply->error, reply->handle); if (magic != NBD_SIMPLE_REPLY_MAGIC) { error_setg(errp, "invalid magic (got 0x%" PRIx32 ")", magic); diff --git a/nbd/common.c b/nbd/common.c index 59a5316be9..7456021f7e 100644 --- a/nbd/common.c +++ b/nbd/common.c @@ -148,3 +148,26 @@ const char *nbd_cmd_lookup(uint16_t cmd) return ""; } } + + +const char *nbd_err_lookup(int err) +{ +switch (err) { +case NBD_SUCCESS: +return "success"; +case NBD_EPERM: +return "EPERM"; +case NBD_EIO: +return "EIO"; +case NBD_ENOMEM: +return "ENOMEM"; +case NBD_EINVAL: +return "EINVAL"; +case NBD_ENOSPC: +return "ENOSPC"; +case NBD_ESHUTDOWN: +return "ESHUTDOWN"; +default: +return ""; +} +} diff --git a/nbd/server.c b/nbd/server.c index 3df3548d6d..459e00c553 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1227,7 +1227,8 @@ static int nbd_co_send_simple_reply(NBDClient *client, {.iov_base = data, .iov_len = len} }; -trace_nbd_co_send_simple_reply(handle, nbd_err, len); +trace_nbd_co_send_simple_reply(handle, nbd_err, nbd_err_lookup(nbd_err), + len); set_be_simple_reply(&reply, nbd_err, handle); return nbd_co_send_iov(client, iov, len ? 2 : 1, errp); diff --git a/nbd/trace-events b/nbd/trace-events index e27614f050..9a72f458b2 100644 --- a/nbd/trace-events +++ b/nbd/trace-events @@ -29,7 +29,7 @@ nbd_client_loop_ret(int ret, const char *error) "NBD loop returned %d: %s" nbd_client_clear_queue(void) "Clearing NBD queue" nbd_client_clear_socket(void) "Clearing NBD socket" nbd_send_request(uint64_t from, uint32_t len, uint64_t handle, uint16_t flags, uint16_t type, const char *name) "Sending request to server: { .from = %" PRIu64", .len = %" PRIu32 ", .handle = %" PRIu64 ", .flags = 0x%" PRIx16 ", .type = %" PRIu16 " (%s) }" -nbd_receive_reply(uint32_t magic, int32_t error, uint64_t handle) "Got reply: { magic = 0x%" PRIx32 ", .error = % " PRId32 ", handle = %" PRIu64" }" +nbd_receive_reply(uint32_t magic, int32_t error, const char *errname, uint64_t handle) "Got reply: { magic = 0x%" PRIx32 ", .error = % " PRId32 " (%s), handle = %" PRIu64" }" # nbd/server.c nbd_negotiate_send_rep_len(uint32_t opt, const char *optname, uint32_t type, const char *typename, uint32_t len) "Reply opt=0x%" PRIx32 " (%s), type=0x%" PRIx32 " (%s), len=%" PRIu32 @@ -53,7 +53,7 @@ nbd_negotiate_success(void) "Negotiation succeeded" nbd_receive_request(uint32_t magic, uint16_t flags, uint16_t type, uint64_t from, uint32_t len) "Got request: { magic = 0x%" PRIx32 ", .flags = 0x%" PRIx16 ", .type = 0x%" PRIx16 ", from = %" PRIu64 ", len = %" PRIu32 " }" nbd_blk_aio_attached(const char *name, void *ctx) "Export %s: Attaching clients to AIO context %p\n" nbd_blk_aio_detach(const char *name, void *ctx) "Export %s: Detaching clients from AIO context %p\n" -nbd_co_send_simple_reply(uint64_t handle, uint32_t error, int len) "Send simple reply: handle = %" PRIu64 ", error = %" PRIu32 ", len = %d" +nbd_co_send_simple_reply(uint64_t handle, uint32_t error, cons
[Qemu-devel] [PULL 8/9] nbd/server: simplify reply transmission
From: Vladimir Sementsov-Ogievskiy Send qiov via qio_channel_writev_all instead of calling nbd_write twice with a cork. Signed-off-by: Vladimir Sementsov-Ogievskiy Message-Id: <20171012095319.136610-8-vsement...@virtuozzo.com> [eblake: rebase to tweaks earlier in series] Signed-off-by: Eric Blake --- nbd/server.c | 49 - 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/nbd/server.c b/nbd/server.c index 3fcc3d3c7c..3df3548d6d 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1188,6 +1188,23 @@ void nbd_export_close_all(void) } } +static int coroutine_fn nbd_co_send_iov(NBDClient *client, struct iovec *iov, +unsigned niov, Error **errp) +{ +int ret; + +g_assert(qemu_in_coroutine()); +qemu_co_mutex_lock(&client->send_lock); +client->send_coroutine = qemu_coroutine_self(); + +ret = qio_channel_writev_all(client->ioc, iov, niov, errp) < 0 ? -EIO : 0; + +client->send_coroutine = NULL; +qemu_co_mutex_unlock(&client->send_lock); + +return ret; +} + static inline void set_be_simple_reply(NBDSimpleReply *reply, uint64_t error, uint64_t handle) { @@ -1203,35 +1220,17 @@ static int nbd_co_send_simple_reply(NBDClient *client, size_t len, Error **errp) { -NBDSimpleReply simple_reply; +NBDSimpleReply reply; int nbd_err = system_errno_to_nbd_errno(error); -int ret; - -g_assert(qemu_in_coroutine()); +struct iovec iov[] = { +{.iov_base = &reply, .iov_len = sizeof(reply)}, +{.iov_base = data, .iov_len = len} +}; trace_nbd_co_send_simple_reply(handle, nbd_err, len); -set_be_simple_reply(&simple_reply, nbd_err, handle); +set_be_simple_reply(&reply, nbd_err, handle); -qemu_co_mutex_lock(&client->send_lock); -client->send_coroutine = qemu_coroutine_self(); - -if (!len) { -ret = nbd_write(client->ioc, &simple_reply, sizeof(simple_reply), errp); -} else { -qio_channel_set_cork(client->ioc, true); -ret = nbd_write(client->ioc, &simple_reply, sizeof(simple_reply), errp); -if (ret == 0) { -ret = nbd_write(client->ioc, data, len, errp); -if (ret < 0) { -ret = -EIO; -} -} -qio_channel_set_cork(client->ioc, false); -} - -client->send_coroutine = NULL; -qemu_co_mutex_unlock(&client->send_lock); -return ret; +return nbd_co_send_iov(client, iov, len ? 2 : 1, errp); } /* nbd_co_receive_request -- 2.13.6
[Qemu-devel] [PULL 9/9] nbd: header constants indenting
From: Vladimir Sementsov-Ogievskiy Prepare indenting for the following commit. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake Message-Id: <20171012095319.136610-9-vsement...@virtuozzo.com> Signed-off-by: Eric Blake --- include/block/nbd.h | 15 --- nbd/nbd-internal.h | 32 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/include/block/nbd.h b/include/block/nbd.h index 49008980f4..a6df5ce8b5 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -71,13 +71,14 @@ typedef struct NBDSimpleReply { /* Transmission (export) flags: sent from server to client during handshake, but describe what will happen during transmission */ -#define NBD_FLAG_HAS_FLAGS (1 << 0)/* Flags are there */ -#define NBD_FLAG_READ_ONLY (1 << 1)/* Device is read-only */ -#define NBD_FLAG_SEND_FLUSH (1 << 2)/* Send FLUSH */ -#define NBD_FLAG_SEND_FUA (1 << 3)/* Send FUA (Force Unit Access) */ -#define NBD_FLAG_ROTATIONAL (1 << 4)/* Use elevator algorithm - rotational media */ -#define NBD_FLAG_SEND_TRIM (1 << 5)/* Send TRIM (discard) */ -#define NBD_FLAG_SEND_WRITE_ZEROES (1 << 6) /* Send WRITE_ZEROES */ +#define NBD_FLAG_HAS_FLAGS (1 << 0) /* Flags are there */ +#define NBD_FLAG_READ_ONLY (1 << 1) /* Device is read-only */ +#define NBD_FLAG_SEND_FLUSH(1 << 2) /* Send FLUSH */ +#define NBD_FLAG_SEND_FUA (1 << 3) /* Send FUA (Force Unit Access) */ +#define NBD_FLAG_ROTATIONAL(1 << 4) /* Use elevator algorithm - + rotational media */ +#define NBD_FLAG_SEND_TRIM (1 << 5) /* Send TRIM (discard) */ +#define NBD_FLAG_SEND_WRITE_ZEROES (1 << 6) /* Send WRITE_ZEROES */ /* New-style handshake (global) flags, sent from server to client, and control what will happen during handshake phase. */ diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h index 2d6663de23..11a130d050 100644 --- a/nbd/nbd-internal.h +++ b/nbd/nbd-internal.h @@ -46,23 +46,23 @@ /* Size of oldstyle negotiation */ #define NBD_OLDSTYLE_NEGOTIATE_SIZE (8 + 8 + 8 + 4 + 124) -#define NBD_REQUEST_MAGIC 0x25609513 -#define NBD_SIMPLE_REPLY_MAGIC 0x67446698 -#define NBD_OPTS_MAGIC 0x49484156454F5054LL -#define NBD_CLIENT_MAGIC0x420281861253LL -#define NBD_REP_MAGIC 0x0003e889045565a9LL +#define NBD_REQUEST_MAGIC 0x25609513 +#define NBD_SIMPLE_REPLY_MAGIC 0x67446698 +#define NBD_OPTS_MAGIC 0x49484156454F5054LL +#define NBD_CLIENT_MAGIC0x420281861253LL +#define NBD_REP_MAGIC 0x0003e889045565a9LL -#define NBD_SET_SOCK_IO(0xab, 0) -#define NBD_SET_BLKSIZE _IO(0xab, 1) -#define NBD_SET_SIZE_IO(0xab, 2) -#define NBD_DO_IT _IO(0xab, 3) -#define NBD_CLEAR_SOCK _IO(0xab, 4) -#define NBD_CLEAR_QUE _IO(0xab, 5) -#define NBD_PRINT_DEBUG _IO(0xab, 6) -#define NBD_SET_SIZE_BLOCKS _IO(0xab, 7) -#define NBD_DISCONNECT _IO(0xab, 8) -#define NBD_SET_TIMEOUT _IO(0xab, 9) -#define NBD_SET_FLAGS _IO(0xab, 10) +#define NBD_SET_SOCK_IO(0xab, 0) +#define NBD_SET_BLKSIZE _IO(0xab, 1) +#define NBD_SET_SIZE_IO(0xab, 2) +#define NBD_DO_IT _IO(0xab, 3) +#define NBD_CLEAR_SOCK _IO(0xab, 4) +#define NBD_CLEAR_QUE _IO(0xab, 5) +#define NBD_PRINT_DEBUG _IO(0xab, 6) +#define NBD_SET_SIZE_BLOCKS _IO(0xab, 7) +#define NBD_DISCONNECT _IO(0xab, 8) +#define NBD_SET_TIMEOUT _IO(0xab, 9) +#define NBD_SET_FLAGS _IO(0xab, 10) /* NBD errors are based on errno numbers, so there is a 1:1 mapping, * but only a limited set of errno values is specified in the protocol. -- 2.13.6
[Qemu-devel] [PULL 6/9] nbd/server: do not use NBDReply structure
From: Vladimir Sementsov-Ogievskiy NBDReply structure will be upgraded in future patches to handle both simple and structured replies and will be used only in the client Signed-off-by: Vladimir Sementsov-Ogievskiy Message-Id: <20171012095319.136610-6-vsement...@virtuozzo.com> [eblake: rebase to tweaks earlier in series] Signed-off-by: Eric Blake --- nbd/server.c | 36 +++- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/nbd/server.c b/nbd/server.c index 4f765ba992..06aeadcfbb 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1196,18 +1196,20 @@ static inline void set_be_simple_reply(NBDSimpleReply *reply, uint64_t error, stq_be_p(&reply->handle, handle); } -static int nbd_co_send_simple_reply(NBDRequestData *req, NBDReply *reply, +static int nbd_co_send_simple_reply(NBDRequestData *req, +uint64_t handle, +uint32_t error, int len, Error **errp) { NBDClient *client = req->client; NBDSimpleReply simple_reply; -int nbd_err = system_errno_to_nbd_errno(reply->error); +int nbd_err = system_errno_to_nbd_errno(error); int ret; g_assert(qemu_in_coroutine()); -trace_nbd_co_send_simple_reply(reply->handle, nbd_err, len); -set_be_simple_reply(&simple_reply, nbd_err, reply->handle); +trace_nbd_co_send_simple_reply(handle, nbd_err, len); +set_be_simple_reply(&simple_reply, nbd_err, handle); qemu_co_mutex_lock(&client->send_lock); client->send_coroutine = qemu_coroutine_self(); @@ -1322,7 +1324,6 @@ static coroutine_fn void nbd_trip(void *opaque) NBDExport *exp = client->exp; NBDRequestData *req; NBDRequest request = { 0 };/* GCC thinks it can be used uninitialized */ -NBDReply reply; int ret; int flags; int reply_data_len = 0; @@ -1342,11 +1343,7 @@ static coroutine_fn void nbd_trip(void *opaque) goto disconnect; } -reply.handle = request.handle; -reply.error = 0; - if (ret < 0) { -reply.error = -ret; goto reply; } @@ -1365,7 +1362,6 @@ static coroutine_fn void nbd_trip(void *opaque) ret = blk_co_flush(exp->blk); if (ret < 0) { error_setg_errno(&local_err, -ret, "flush failed"); -reply.error = -ret; break; } } @@ -1374,7 +1370,6 @@ static coroutine_fn void nbd_trip(void *opaque) req->data, request.len); if (ret < 0) { error_setg_errno(&local_err, -ret, "reading from file failed"); -reply.error = -ret; break; } @@ -1383,7 +1378,7 @@ static coroutine_fn void nbd_trip(void *opaque) break; case NBD_CMD_WRITE: if (exp->nbdflags & NBD_FLAG_READ_ONLY) { -reply.error = EROFS; +ret = -EROFS; break; } @@ -1395,14 +1390,13 @@ static coroutine_fn void nbd_trip(void *opaque) req->data, request.len, flags); if (ret < 0) { error_setg_errno(&local_err, -ret, "writing to file failed"); -reply.error = -ret; } break; case NBD_CMD_WRITE_ZEROES: if (exp->nbdflags & NBD_FLAG_READ_ONLY) { error_setg(&local_err, "Server is read-only, return error"); -reply.error = EROFS; +ret = -EROFS; break; } @@ -1417,7 +1411,6 @@ static coroutine_fn void nbd_trip(void *opaque) request.len, flags); if (ret < 0) { error_setg_errno(&local_err, -ret, "writing to file failed"); -reply.error = -ret; } break; @@ -1429,7 +1422,6 @@ static coroutine_fn void nbd_trip(void *opaque) ret = blk_co_flush(exp->blk); if (ret < 0) { error_setg_errno(&local_err, -ret, "flush failed"); -reply.error = -ret; } break; @@ -1438,25 +1430,27 @@ static coroutine_fn void nbd_trip(void *opaque) request.len); if (ret < 0) { error_setg_errno(&local_err, -ret, "discard failed"); -reply.error = -ret; } break; default: error_setg(&local_err, "invalid request type (%" PRIu32 ") received", request.type); -reply.error = EINVAL; +ret = -EINVAL; } reply: if (local_err) { -/* If we are here local_err is not fatal error, already stored in - * reply.error */ +/* If we get here, local_err was not a fatal error, and should be sent + * to the client. */ error_report_err(local_err); local_err = NULL; } -if (nbd_co_send_simple_reply(req, &reply, reply_data_len, &local_err) < 0) { +if (nbd_co_send_simple_reply(req, request.handle, +
[Qemu-devel] [PULL 7/9] nbd/server: refactor nbd_co_send_simple_reply parameters
From: Vladimir Sementsov-Ogievskiy Pass client and buffer (*data) parameters directly, to make the function consistent with further structured reply sending functions. Signed-off-by: Vladimir Sementsov-Ogievskiy Message-Id: <20171012095319.136610-7-vsement...@virtuozzo.com> Signed-off-by: Eric Blake --- nbd/server.c | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/nbd/server.c b/nbd/server.c index 06aeadcfbb..3fcc3d3c7c 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1196,12 +1196,13 @@ static inline void set_be_simple_reply(NBDSimpleReply *reply, uint64_t error, stq_be_p(&reply->handle, handle); } -static int nbd_co_send_simple_reply(NBDRequestData *req, +static int nbd_co_send_simple_reply(NBDClient *client, uint64_t handle, uint32_t error, -int len, Error **errp) +void *data, +size_t len, +Error **errp) { -NBDClient *client = req->client; NBDSimpleReply simple_reply; int nbd_err = system_errno_to_nbd_errno(error); int ret; @@ -1220,7 +1221,7 @@ static int nbd_co_send_simple_reply(NBDRequestData *req, qio_channel_set_cork(client->ioc, true); ret = nbd_write(client->ioc, &simple_reply, sizeof(simple_reply), errp); if (ret == 0) { -ret = nbd_write(client->ioc, req->data, len, errp); +ret = nbd_write(client->ioc, data, len, errp); if (ret < 0) { ret = -EIO; } @@ -1447,9 +1448,9 @@ reply: local_err = NULL; } -if (nbd_co_send_simple_reply(req, request.handle, +if (nbd_co_send_simple_reply(req->client, request.handle, ret < 0 ? -ret : 0, - reply_data_len, &local_err) < 0) + req->data, reply_data_len, &local_err) < 0) { error_prepend(&local_err, "Failed to send reply: "); goto disconnect; -- 2.13.6
[Qemu-devel] [PULL 4/9] nbd: rename some simple-request related objects to be _simple_
From: Vladimir Sementsov-Ogievskiy To be consistent when their _structured_ analogs will be introduced. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake Message-Id: <20171012095319.136610-4-vsement...@virtuozzo.com> [eblake: also tweak trace message contents] Signed-off-by: Eric Blake --- nbd/nbd-internal.h | 2 +- nbd/client.c | 4 ++-- nbd/server.c | 12 ++-- nbd/trace-events | 2 +- tests/qemu-iotests/nbd-fault-injector.py | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h index 8a609a227f..2d6663de23 100644 --- a/nbd/nbd-internal.h +++ b/nbd/nbd-internal.h @@ -47,7 +47,7 @@ #define NBD_OLDSTYLE_NEGOTIATE_SIZE (8 + 8 + 8 + 4 + 124) #define NBD_REQUEST_MAGIC 0x25609513 -#define NBD_REPLY_MAGIC 0x67446698 +#define NBD_SIMPLE_REPLY_MAGIC 0x67446698 #define NBD_OPTS_MAGIC 0x49484156454F5054LL #define NBD_CLIENT_MAGIC0x420281861253LL #define NBD_REP_MAGIC 0x0003e889045565a9LL diff --git a/nbd/client.c b/nbd/client.c index 68a0bc1ffc..cd5a2c80ac 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -931,7 +931,7 @@ int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp) } /* Reply - [ 0 .. 3]magic (NBD_REPLY_MAGIC) + [ 0 .. 3]magic (NBD_SIMPLE_REPLY_MAGIC) [ 4 .. 7]error (0 == no error) [ 7 .. 15]handle */ @@ -949,7 +949,7 @@ int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp) } trace_nbd_receive_reply(magic, reply->error, reply->handle); -if (magic != NBD_REPLY_MAGIC) { +if (magic != NBD_SIMPLE_REPLY_MAGIC) { error_setg(errp, "invalid magic (got 0x%" PRIx32 ")", magic); return -EINVAL; } diff --git a/nbd/server.c b/nbd/server.c index b74cc6ab7e..ea2f0fa476 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -911,11 +911,11 @@ static int nbd_send_reply(QIOChannel *ioc, NBDReply *reply, Error **errp) trace_nbd_send_reply(reply->error, reply->handle); /* Reply - [ 0 .. 3]magic (NBD_REPLY_MAGIC) + [ 0 .. 3]magic (NBD_SIMPLE_REPLY_MAGIC) [ 4 .. 7]error (0 == no error) [ 7 .. 15]handle */ -stl_be_p(buf, NBD_REPLY_MAGIC); +stl_be_p(buf, NBD_SIMPLE_REPLY_MAGIC); stl_be_p(buf + 4, reply->error); stq_be_p(buf + 8, reply->handle); @@ -1208,15 +1208,15 @@ void nbd_export_close_all(void) } } -static int nbd_co_send_reply(NBDRequestData *req, NBDReply *reply, int len, - Error **errp) +static int nbd_co_send_simple_reply(NBDRequestData *req, NBDReply *reply, +int len, Error **errp) { NBDClient *client = req->client; int ret; g_assert(qemu_in_coroutine()); -trace_nbd_co_send_reply(reply->handle, reply->error, len); +trace_nbd_co_send_simple_reply(reply->handle, reply->error, len); qemu_co_mutex_lock(&client->send_lock); client->send_coroutine = qemu_coroutine_self(); @@ -1465,7 +1465,7 @@ reply: local_err = NULL; } -if (nbd_co_send_reply(req, &reply, reply_data_len, &local_err) < 0) { +if (nbd_co_send_simple_reply(req, &reply, reply_data_len, &local_err) < 0) { error_prepend(&local_err, "Failed to send reply: "); goto disconnect; } diff --git a/nbd/trace-events b/nbd/trace-events index 48a4f27682..4d6f86c2d4 100644 --- a/nbd/trace-events +++ b/nbd/trace-events @@ -54,7 +54,7 @@ nbd_receive_request(uint32_t magic, uint16_t flags, uint16_t type, uint64_t from nbd_send_reply(int32_t error, uint64_t handle) "Sending response to client: { .error = %" PRId32 ", handle = %" PRIu64 " }" nbd_blk_aio_attached(const char *name, void *ctx) "Export %s: Attaching clients to AIO context %p\n" nbd_blk_aio_detach(const char *name, void *ctx) "Export %s: Detaching clients from AIO context %p\n" -nbd_co_send_reply(uint64_t handle, uint32_t error, int len) "Send reply: handle = %" PRIu64 ", error = %" PRIu32 ", len = %d" +nbd_co_send_simple_reply(uint64_t handle, uint32_t error, int len) "Send simple reply: handle = %" PRIu64 ", error = %" PRIu32 ", len = %d" nbd_co_receive_request_decode_type(uint64_t handle, uint16_t type, const char *name) "Decoding type: handle = %" PRIu64 ", type = %" PRIu16 " (%s)" nbd_co_receive_request_payload_received(uint64_t handle, uint32_t len) "Payload received: handle = %" PRIu64 ", len = %" PRIu32 nbd_co_receive_request_cmd_write(uint32_t len) "Reading %" PRIu32 " byte(s)" diff --git a/tests/qemu-iotests/nbd-fault-injector.py b/tests/qemu-iotests/nbd-fault-injector.py index 1c10dcb51c..8a04d979aa 100755 --- a/tests/qemu-iotests/nbd-fault-injector.py +++ b/tests/qemu-iotests/nbd-fault-injector.py @@ -56,7 +56,7 @@ NBD_CMD_READ = 0 NBD_CMD_WRITE = 1 NBD_CMD_DISC = 2 NBD_
[Qemu-devel] [PULL 2/9] block/nbd-client: assert qiov len once in nbd_co_request
From: Vladimir Sementsov-Ogievskiy Also improve the assertion: check that qiov is NULL for other commands than CMD_READ and CMD_WRITE. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake Message-Id: <20171012095319.136610-2-vsement...@virtuozzo.com> Signed-off-by: Eric Blake --- block/nbd-client.c | 10 ++ 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/block/nbd-client.c b/block/nbd-client.c index 72651dcdb1..ddf273a6a4 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -156,7 +156,6 @@ static int nbd_co_send_request(BlockDriverState *bs, qio_channel_set_cork(s->ioc, true); rc = nbd_send_request(s->ioc, request); if (rc >= 0 && !s->quit) { -assert(request->len == iov_size(qiov->iov, qiov->niov)); if (qio_channel_writev_all(s->ioc, qiov->iov, qiov->niov, NULL) < 0) { rc = -EIO; @@ -197,7 +196,6 @@ static int nbd_co_receive_reply(NBDClientSession *s, assert(s->reply.handle == request->handle); ret = -s->reply.error; if (qiov && s->reply.error == 0) { -assert(request->len == iov_size(qiov->iov, qiov->niov)); if (qio_channel_readv_all(s->ioc, qiov->iov, qiov->niov, NULL) < 0) { ret = -EIO; @@ -231,8 +229,12 @@ static int nbd_co_request(BlockDriverState *bs, NBDClientSession *client = nbd_get_client_session(bs); int ret; -assert(!qiov || request->type == NBD_CMD_WRITE || - request->type == NBD_CMD_READ); +if (qiov) { +assert(request->type == NBD_CMD_WRITE || request->type == NBD_CMD_READ); +assert(request->len == iov_size(qiov->iov, qiov->niov)); +} else { +assert(request->type != NBD_CMD_WRITE && request->type != NBD_CMD_READ); +} ret = nbd_co_send_request(bs, request, request->type == NBD_CMD_WRITE ? qiov : NULL); if (ret < 0) { -- 2.13.6
[Qemu-devel] [PULL 5/9] nbd/server: structurize simple reply header sending
From: Vladimir Sementsov-Ogievskiy Use packed structure instead of pointer arithmetics. Also, merge two redundant traces into one. Signed-off-by: Vladimir Sementsov-Ogievskiy Message-Id: <20171012095319.136610-5-vsement...@virtuozzo.com> [eblake: tweak and mention impact on traces, fix errp usage] Signed-off-by: Eric Blake --- include/block/nbd.h | 6 ++ nbd/server.c| 37 ++--- nbd/trace-events| 1 - 3 files changed, 20 insertions(+), 24 deletions(-) diff --git a/include/block/nbd.h b/include/block/nbd.h index 707fd37575..49008980f4 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -63,6 +63,12 @@ struct NBDReply { }; typedef struct NBDReply NBDReply; +typedef struct NBDSimpleReply { +uint32_t magic; /* NBD_SIMPLE_REPLY_MAGIC */ +uint32_t error; +uint64_t handle; +} QEMU_PACKED NBDSimpleReply; + /* Transmission (export) flags: sent from server to client during handshake, but describe what will happen during transmission */ #define NBD_FLAG_HAS_FLAGS (1 << 0)/* Flags are there */ diff --git a/nbd/server.c b/nbd/server.c index ea2f0fa476..4f765ba992 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -902,26 +902,6 @@ static int nbd_receive_request(QIOChannel *ioc, NBDRequest *request, return 0; } -static int nbd_send_reply(QIOChannel *ioc, NBDReply *reply, Error **errp) -{ -uint8_t buf[NBD_REPLY_SIZE]; - -reply->error = system_errno_to_nbd_errno(reply->error); - -trace_nbd_send_reply(reply->error, reply->handle); - -/* Reply - [ 0 .. 3]magic (NBD_SIMPLE_REPLY_MAGIC) - [ 4 .. 7]error (0 == no error) - [ 7 .. 15]handle - */ -stl_be_p(buf, NBD_SIMPLE_REPLY_MAGIC); -stl_be_p(buf + 4, reply->error); -stq_be_p(buf + 8, reply->handle); - -return nbd_write(ioc, buf, sizeof(buf), errp); -} - #define MAX_NBD_REQUESTS 16 void nbd_client_get(NBDClient *client) @@ -1208,24 +1188,35 @@ void nbd_export_close_all(void) } } +static inline void set_be_simple_reply(NBDSimpleReply *reply, uint64_t error, + uint64_t handle) +{ +stl_be_p(&reply->magic, NBD_SIMPLE_REPLY_MAGIC); +stl_be_p(&reply->error, error); +stq_be_p(&reply->handle, handle); +} + static int nbd_co_send_simple_reply(NBDRequestData *req, NBDReply *reply, int len, Error **errp) { NBDClient *client = req->client; +NBDSimpleReply simple_reply; +int nbd_err = system_errno_to_nbd_errno(reply->error); int ret; g_assert(qemu_in_coroutine()); -trace_nbd_co_send_simple_reply(reply->handle, reply->error, len); +trace_nbd_co_send_simple_reply(reply->handle, nbd_err, len); +set_be_simple_reply(&simple_reply, nbd_err, reply->handle); qemu_co_mutex_lock(&client->send_lock); client->send_coroutine = qemu_coroutine_self(); if (!len) { -ret = nbd_send_reply(client->ioc, reply, errp); +ret = nbd_write(client->ioc, &simple_reply, sizeof(simple_reply), errp); } else { qio_channel_set_cork(client->ioc, true); -ret = nbd_send_reply(client->ioc, reply, errp); +ret = nbd_write(client->ioc, &simple_reply, sizeof(simple_reply), errp); if (ret == 0) { ret = nbd_write(client->ioc, req->data, len, errp); if (ret < 0) { diff --git a/nbd/trace-events b/nbd/trace-events index 4d6f86c2d4..e27614f050 100644 --- a/nbd/trace-events +++ b/nbd/trace-events @@ -51,7 +51,6 @@ nbd_negotiate_old_style(uint64_t size, unsigned flags) "advertising size %" PRIu nbd_negotiate_new_style_size_flags(uint64_t size, unsigned flags) "advertising size %" PRIu64 " and flags 0x%x" nbd_negotiate_success(void) "Negotiation succeeded" nbd_receive_request(uint32_t magic, uint16_t flags, uint16_t type, uint64_t from, uint32_t len) "Got request: { magic = 0x%" PRIx32 ", .flags = 0x%" PRIx16 ", .type = 0x%" PRIx16 ", from = %" PRIu64 ", len = %" PRIu32 " }" -nbd_send_reply(int32_t error, uint64_t handle) "Sending response to client: { .error = %" PRId32 ", handle = %" PRIu64 " }" nbd_blk_aio_attached(const char *name, void *ctx) "Export %s: Attaching clients to AIO context %p\n" nbd_blk_aio_detach(const char *name, void *ctx) "Export %s: Detaching clients from AIO context %p\n" nbd_co_send_simple_reply(uint64_t handle, uint32_t error, int len) "Send simple reply: handle = %" PRIu64 ", error = %" PRIu32 ", len = %d" -- 2.13.6
[Qemu-devel] [PULL 3/9] block/nbd-client: refactor nbd_co_receive_reply
From: Vladimir Sementsov-Ogievskiy Pass handle parameter directly, as the whole request isn't needed. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake Message-Id: <20171012095319.136610-3-vsement...@virtuozzo.com> Signed-off-by: Eric Blake --- block/nbd-client.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/block/nbd-client.c b/block/nbd-client.c index ddf273a6a4..c0683c3c83 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -180,11 +180,11 @@ err: } static int nbd_co_receive_reply(NBDClientSession *s, -NBDRequest *request, +uint64_t handle, QEMUIOVector *qiov) { int ret; -int i = HANDLE_TO_INDEX(s, request->handle); +int i = HANDLE_TO_INDEX(s, handle); /* Wait until we're woken up by nbd_read_reply_entry. */ s->requests[i].receiving = true; @@ -193,7 +193,7 @@ static int nbd_co_receive_reply(NBDClientSession *s, if (!s->ioc || s->quit) { ret = -EIO; } else { -assert(s->reply.handle == request->handle); +assert(s->reply.handle == handle); ret = -s->reply.error; if (qiov && s->reply.error == 0) { if (qio_channel_readv_all(s->ioc, qiov->iov, qiov->niov, @@ -241,7 +241,7 @@ static int nbd_co_request(BlockDriverState *bs, return ret; } -return nbd_co_receive_reply(client, request, +return nbd_co_receive_reply(client, request->handle, request->type == NBD_CMD_READ ? qiov : NULL); } -- 2.13.6
[Qemu-devel] [PULL 0/9] NBD patches through 14 Oct
The following changes since commit f90ea7ba7c5ae7010ee0ce062207ae42530f57d6: Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20171012' into staging (2017-10-12 17:06:50 +0100) are available in the git repository at: git://repo.or.cz/qemu/ericb.git tags/pull-nbd-2017-10-14 for you to fetch changes up to 92652b124336f5c08c7eb4616af202ea910dd3ea: nbd: header constants indenting (2017-10-13 09:27:38 -0500) nbd patches for 2017-10-14 - Marc-André Lureau - NBD: use g_new() family of functions - Vladimir Sementsov-Ogievskiy - first half of 00/13 nbd minimal structured read Marc-André Lureau (1): NBD: use g_new() family of functions Vladimir Sementsov-Ogievskiy (8): block/nbd-client: assert qiov len once in nbd_co_request block/nbd-client: refactor nbd_co_receive_reply nbd: rename some simple-request related objects to be _simple_ nbd/server: structurize simple reply header sending nbd/server: do not use NBDReply structure nbd/server: refactor nbd_co_send_simple_reply parameters nbd/server: simplify reply transmission nbd: header constants indenting include/block/nbd.h | 21 --- nbd/nbd-internal.h | 32 +- block/nbd-client.c | 18 +++--- nbd/client.c | 4 +- nbd/server.c | 101 +-- nbd/trace-events | 3 +- tests/qemu-iotests/nbd-fault-injector.py | 4 +- 7 files changed, 88 insertions(+), 95 deletions(-) -- 2.13.6
[Qemu-devel] [PULL 1/9] NBD: use g_new() family of functions
From: Marc-André Lureau Signed-off-by: Marc-André Lureau Message-Id: <20171006235023.11952-22-f4...@amsat.org> Signed-off-by: Eric Blake --- nbd/server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nbd/server.c b/nbd/server.c index 993ade30bb..b74cc6ab7e 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1047,7 +1047,7 @@ NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size, { AioContext *ctx; BlockBackend *blk; -NBDExport *exp = g_malloc0(sizeof(NBDExport)); +NBDExport *exp = g_new0(NBDExport, 1); uint64_t perm; int ret; @@ -1539,7 +1539,7 @@ void nbd_client_new(NBDExport *exp, NBDClient *client; Coroutine *co; -client = g_malloc0(sizeof(NBDClient)); +client = g_new0(NBDClient, 1); client->refcount = 1; client->exp = exp; client->tlscreds = tlscreds; -- 2.13.6
Re: [Qemu-devel] [RFC QEMU PATCH v3 00/10] Implement vNVDIMM for Xen HVM guest
On Fri, Oct 13, 2017 at 03:53:26PM +0800, Haozhong Zhang wrote: > On 10/12/17 17:45 +0200, Paolo Bonzini wrote: > > On 12/10/2017 14:45, Haozhong Zhang wrote: > > > Basically, QEMU builds two ROMs for guest, /rom@etc/acpi/tables and > > > /rom@etc/table-loader. The former is unstructured to guest, and > > > contains all data of guest ACPI. The latter is a BIOSLinkerLoader > > > organized as a set of commands, which direct the guest (e.g., SeaBIOS > > > on KVM/QEMU) to relocate data in the former file, recalculate checksum > > > of specified area, and fill guest address in specified ACPI field. > > > > > > One part of my patches is to implement a mechanism to tell Xen which > > > part of ACPI data is a table (NFIT), and which part defines a > > > namespace device and what the device name is. I can add two new loader > > > commands for them respectively. > > > > > > Because they just provide information and SeaBIOS in non-xen > > > environment ignores unrecognized commands, they will not break SeaBIOS > > > in non-xen environment. > > > > > > On QEMU side, most Xen-specific hacks in ACPI builder could be > > > dropped, and replaced by adding the new loader commands (though they > > > may be used only by Xen). > > > > > > On Xen side, a fw_cfg driver and a BIOSLinkerLoader command executor > > > are needed in, perhaps, hvmloader. > > > > If Xen has to parse BIOSLinkerLoader, it can use the existing commands > > to process a reduced set of ACPI tables. In other words, > > etc/acpi/tables would only include the NFIT, the SSDT with namespace > > devices, and the XSDT. etc/acpi/rsdp would include the RSDP table as usual. > > > > hvmloader can then: > > > > 1) allocate some memory for where the XSDT will go > > > > 2) process the BIOSLinkerLoader like SeaBIOS would do > > > > 3) find the RSDP in low memory, since the loader script must have placed > > it there. If it cannot find it, allocate some low memory, fill it with > > the RSDP header and revision, and and jump to step 6 > > > > 4) If it found QEMU's RSDP, use it to find QEMU's XSDT > > > > 5) Copy ACPI table pointers from QEMU to hvmloader's RSDT and/or XSDT. > > > > 6) build hvmloader tables and link them into the RSDT and/or XSDT as usual. > > > > 7) overwrite the RSDP in low memory with a pointer to hvmloader's own > > RSDT and/or XSDT, and updated the checksums > > > > QEMU's XSDT remains there somewhere in memory, unused but harmless. > > > > It can work for plan tables which do not contain AML. > > However, for a namespace device, Xen needs to know its name in order > to detect the potential name conflict with those used in Xen built > ACPI. Xen does not (and is not going to) introduce an AML parser, so > it cannot get those device names from QEMU built ACPI by its own. > > The idea of either this patch series or the new BIOSLinkerLoader > command is to let QEMU tell Xen where the definition body of a > namespace device (i.e. that part within the outmost "Device(NAME)") is > and what the device name is. Xen, after the name conflict check, can > re-package the definition body in a namespace device (w/ minimal AML > builder code added in Xen) and then in SSDT. > > > Haozhong You most likely can do this without a new command. You can use something similiar to build_append_named_dword in combination with BIOS_LINKER_LOADER_COMMAND_ADD_POINTER like vm gen id does. -- MST
Re: [Qemu-devel] [RFC QEMU PATCH v3 00/10] Implement vNVDIMM for Xen HVM guest
On Fri, Oct 13, 2017 at 03:46:39PM -0700, Stefano Stabellini wrote: > On Fri, 13 Oct 2017, Jan Beulich wrote: > > >>> On 13.10.17 at 13:13, wrote: > > > To Jan, Andrew, Stefano and Anthony, > > > > > > what do you think about allowing QEMU to build the entire guest ACPI > > > and letting SeaBIOS to load it? ACPI builder code in hvmloader is > > > still there and just bypassed in this case. > > > > Well, if that can be made work in a non-quirky way and without > > loss of functionality, I'd probably be fine. I do think, however, > > that there's a reason this is being handled in hvmloader right now. > > And not to discourage you, just as a clarification, you'll also need to > consider backward compatibility: unless the tables are identical, I > imagine we'll have to keep using the old tables for already installed > virtual machines. Maybe you can handle this using machine type versioning. Installed guests would use the old type. -- MST
Re: [Qemu-devel] [PATCHv3 00/13] sun4m: sparc32_dma tidy-ups
Hi, This series seems to have some coding style problems. See output below for more information: Type: series Message-id: 1508006342-5304-1-git-send-email-mark.cave-ayl...@ilande.co.uk Subject: [Qemu-devel] [PATCHv3 00/13] sun4m: sparc32_dma tidy-ups === TEST SCRIPT BEGIN === #!/bin/bash BASE=base n=1 total=$(git log --oneline $BASE.. | wc -l) failed=0 git config --local diff.renamelimit 0 git config --local diff.renames True commits="$(git log --format=%H --reverse $BASE..)" for c in $commits; do echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..." if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then failed=1 echo fi n=$((n+1)) done exit $failed === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 Switched to a new branch 'test' 49376f2097 sparc32_dma: add len to esp/le DMA memory tracing d1747b9946 sparc32_dma: remove is_ledma hack and replace with memory region alias aff708b794 sparc32_dma: introduce new SPARC32_DMA type container object c1d8e324e2 sparc32_dma: make lance device child of ledma device 89f91116dd lance: move TYPE_LANCE and SysBusPCNetState from lance.c to sun4m.h dead665d1d sparc32_dma: make esp device child of espdma device 1afaa63bbd esp: move TYPE_ESP and SysBusESPState from esp.c to esp.h 9e05523632 sparc32_dma: use object link instead of qdev property to pass IOMMU reference 80b9835896 sun4m_iommu: move TYPE_SUN4M_IOMMU declaration to sun4m.h 66a36aaa11 sun4m: move DMA device wiring from sparc32_dma_init() to sun4m_hw_init() d2fd9ca3eb sparc32_dma: move type declarations from sparc32_dma.c to sparc32_dma.h 74c5135edf sparc32_dma: split esp and le into separate DMA devices cc07b7035d sparc32_dma: rename SPARC32_DMA type to SPARC32_DMA_DEVICE === OUTPUT BEGIN === Checking PATCH 1/13: sparc32_dma: rename SPARC32_DMA type to SPARC32_DMA_DEVICE... Checking PATCH 2/13: sparc32_dma: split esp and le into separate DMA devices... Checking PATCH 3/13: sparc32_dma: move type declarations from sparc32_dma.c to sparc32_dma.h... Checking PATCH 4/13: sun4m: move DMA device wiring from sparc32_dma_init() to sun4m_hw_init()... ERROR: spaces required around that '*' (ctx:WxV) #51: FILE: hw/sparc/sun4m.c:824: +qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS]; ^ total: 1 errors, 0 warnings, 66 lines checked Your patch has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. Checking PATCH 5/13: sun4m_iommu: move TYPE_SUN4M_IOMMU declaration to sun4m.h... Checking PATCH 6/13: sparc32_dma: use object link instead of qdev property to pass IOMMU reference... Checking PATCH 7/13: esp: move TYPE_ESP and SysBusESPState from esp.c to esp.h... Checking PATCH 8/13: sparc32_dma: make esp device child of espdma device... Checking PATCH 9/13: lance: move TYPE_LANCE and SysBusPCNetState from lance.c to sun4m.h... Checking PATCH 10/13: sparc32_dma: make lance device child of ledma device... Checking PATCH 11/13: sparc32_dma: introduce new SPARC32_DMA type container object... Checking PATCH 12/13: sparc32_dma: remove is_ledma hack and replace with memory region alias... Checking PATCH 13/13: sparc32_dma: add len to esp/le DMA memory tracing... === OUTPUT END === Test command exited with code: 1 --- Email generated automatically by Patchew [http://patchew.org/]. Please send your feedback to patchew-de...@freelists.org
[Qemu-devel] [PATCHv3 08/13] sparc32_dma: make esp device child of espdma device
This makes it possible to reference the esp device from the espdma device as required, and by wiring up the device ourselves in sun4m.c we can drop use of the esp_init() function. Signed-off-by: Mark Cave-Ayland --- hw/dma/sparc32_dma.c | 26 ++ hw/sparc/sun4m.c | 19 --- include/hw/sparc/sparc32_dma.h |3 +++ 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index c56a2ba..6009b94 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -298,11 +298,37 @@ static void sparc32_espdma_device_init(Object *obj) s->is_ledma = 0; } +static void sparc32_espdma_device_realize(DeviceState *dev, Error **errp) +{ +DeviceState *d; +SysBusESPState *sysbus; +ESPState *esp; + +d = qdev_create(NULL, TYPE_ESP); +object_property_add_child(OBJECT(dev), "esp", OBJECT(d), errp); +sysbus = ESP_STATE(d); +esp = &sysbus->esp; +esp->dma_memory_read = espdma_memory_read; +esp->dma_memory_write = espdma_memory_write; +esp->dma_opaque = SPARC32_DMA_DEVICE(dev); +sysbus->it_shift = 2; +esp->dma_enabled = 1; +qdev_init_nofail(d); +} + +static void sparc32_espdma_device_class_init(ObjectClass *klass, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(klass); + +dc->realize = sparc32_espdma_device_realize; +} + static const TypeInfo sparc32_espdma_device_info = { .name = TYPE_SPARC32_ESPDMA_DEVICE, .parent= TYPE_SPARC32_DMA_DEVICE, .instance_size = sizeof(ESPDMADeviceState), .instance_init = sparc32_espdma_device_init, +.class_init= sparc32_espdma_device_class_init, }; static void sparc32_ledma_device_init(Object *obj) diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 12d36b5..4626c85 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -819,10 +819,9 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, const char *cpu_model = machine->cpu_model; unsigned int i; void *iommu, *nvram; -DeviceState *espdma, *ledma; +DeviceState *espdma, *esp, *ledma; SysBusDevice *sbd; qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS]; -qemu_irq esp_reset, dma_enable; qemu_irq fdc_tc; unsigned long kernel_size; DriveInfo *fd[MAX_FD]; @@ -884,6 +883,13 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, sbd = SYS_BUS_DEVICE(espdma); sysbus_connect_irq(sbd, 0, slavio_irq[18]); +esp = DEVICE(object_resolve_path_component(OBJECT(espdma), "esp")); +sbd = SYS_BUS_DEVICE(esp); +sysbus_mmio_map(sbd, 0, hwdef->esp_base); +sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(espdma, 0)); +qdev_connect_gpio_out(espdma, 0, qdev_get_gpio_in(esp, 0)); +qdev_connect_gpio_out(espdma, 1, qdev_get_gpio_in(esp, 1)); + ledma = sparc32_dma_init(hwdef->dma_base + 16ULL, iommu, 1); sbd = SYS_BUS_DEVICE(ledma); sysbus_connect_irq(sbd, 0, slavio_irq[16]); @@ -970,15 +976,6 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, slavio_misc_init(hwdef->slavio_base, hwdef->aux1_base, hwdef->aux2_base, slavio_irq[30], fdc_tc); -esp_init(hwdef->esp_base, 2, - espdma_memory_read, espdma_memory_write, - espdma, - qdev_get_gpio_in(espdma, 0), - &esp_reset, &dma_enable); - -qdev_connect_gpio_out(espdma, 0, esp_reset); -qdev_connect_gpio_out(espdma, 1, dma_enable); - if (hwdef->cs_base) { sysbus_create_simple("SUNW,CS4231", hwdef->cs_base, slavio_irq[5]); diff --git a/include/hw/sparc/sparc32_dma.h b/include/hw/sparc/sparc32_dma.h index df7491d..365160f 100644 --- a/include/hw/sparc/sparc32_dma.h +++ b/include/hw/sparc/sparc32_dma.h @@ -2,6 +2,7 @@ #define SPARC32_DMA_H #include "hw/sysbus.h" +#include "hw/scsi/esp.h" #define DMA_REGS 4 @@ -28,6 +29,8 @@ struct DMADeviceState { typedef struct ESPDMADeviceState { DMADeviceState parent_obj; + +SysBusESPState *esp; } ESPDMADeviceState; #define TYPE_SPARC32_LEDMA_DEVICE "sparc32-ledma" -- 1.7.10.4
[Qemu-devel] [PATCHv3 11/13] sparc32_dma: introduce new SPARC32_DMA type container object
Create a new SPARC32_DMA container object (including an appropriate container memory region) and add instances of the SPARC32_ESPDMA_DEVICE and SPARC32_LEDMA_DEVICE as child objects. The benefit is that most of the gpio wiring complexity between esp/espdma and lance/ledma is now hidden within the SPARC32_DMA realize function. Since the sun4m IOMMU is already QOMified we can find a reference to it using object_resolve_path_type() allowing us to completely remove all external references to the iommu pointer. Finally we rework sun4m's sparc32_dma_init() to invoke the new SPARC32_DMA object and wire up the remaining board memory regions/IRQs. Signed-off-by: Mark Cave-Ayland --- hw/dma/sparc32_dma.c | 70 hw/sparc/sun4m.c | 66 ++--- include/hw/sparc/sparc32_dma.h | 12 +++ 3 files changed, 114 insertions(+), 34 deletions(-) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index d507ca3..ba62927 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -29,6 +29,7 @@ #include "hw/hw.h" #include "hw/sparc/sparc32_dma.h" #include "hw/sysbus.h" +#include "qapi/error.h" #include "trace.h" /* @@ -368,11 +369,80 @@ static const TypeInfo sparc32_ledma_device_info = { .class_init= sparc32_ledma_device_class_init, }; +static void sparc32_dma_realize(DeviceState *dev, Error **errp) +{ +SPARC32DMAState *s = SPARC32_DMA(dev); +DeviceState *espdma, *esp, *ledma, *lance; +SysBusDevice *sbd; +Object *iommu; + +iommu = object_resolve_path_type("", TYPE_SUN4M_IOMMU, NULL); +if (!iommu) { +error_setg(errp, "unable to locate sun4m IOMMU device"); +return; +} + +espdma = qdev_create(NULL, TYPE_SPARC32_ESPDMA_DEVICE); +object_property_set_link(OBJECT(espdma), iommu, "iommu", errp); +object_property_add_child(OBJECT(s), "espdma", OBJECT(espdma), errp); +qdev_init_nofail(espdma); + +esp = DEVICE(object_resolve_path_component(OBJECT(espdma), "esp")); +sbd = SYS_BUS_DEVICE(esp); +sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(espdma, 0)); +qdev_connect_gpio_out(espdma, 0, qdev_get_gpio_in(esp, 0)); +qdev_connect_gpio_out(espdma, 1, qdev_get_gpio_in(esp, 1)); + +sbd = SYS_BUS_DEVICE(espdma); +memory_region_add_subregion(&s->dmamem, 0x0, +sysbus_mmio_get_region(sbd, 0)); + +ledma = qdev_create(NULL, TYPE_SPARC32_LEDMA_DEVICE); +object_property_set_link(OBJECT(ledma), iommu, "iommu", errp); +object_property_add_child(OBJECT(s), "ledma", OBJECT(ledma), errp); +qdev_init_nofail(ledma); + +lance = DEVICE(object_resolve_path_component(OBJECT(ledma), "lance")); +sbd = SYS_BUS_DEVICE(lance); +sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(ledma, 0)); +qdev_connect_gpio_out(ledma, 0, qdev_get_gpio_in(lance, 0)); + +sbd = SYS_BUS_DEVICE(ledma); +memory_region_add_subregion(&s->dmamem, 0x10, +sysbus_mmio_get_region(sbd, 0)); +} + +static void sparc32_dma_init(Object *obj) +{ +SPARC32DMAState *s = SPARC32_DMA(obj); +SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + +memory_region_init(&s->dmamem, OBJECT(s), "dma", DMA_SIZE + DMA_ETH_SIZE); +sysbus_init_mmio(sbd, &s->dmamem); +} + +static void sparc32_dma_class_init(ObjectClass *klass, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(klass); + +dc->realize = sparc32_dma_realize; +} + +static const TypeInfo sparc32_dma_info = { +.name = TYPE_SPARC32_DMA, +.parent= TYPE_SYS_BUS_DEVICE, +.instance_size = sizeof(SPARC32DMAState), +.instance_init = sparc32_dma_init, +.class_init= sparc32_dma_class_init, +}; + + static void sparc32_dma_register_types(void) { type_register_static(&sparc32_dma_device_info); type_register_static(&sparc32_espdma_device_info); type_register_static(&sparc32_ledma_device_info); +type_register_static(&sparc32_dma_info); } type_init(sparc32_dma_register_types) diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index ae486a4..5017ae5 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -307,18 +307,36 @@ static void *iommu_init(hwaddr addr, uint32_t version, qemu_irq irq) return s; } -static void *sparc32_dma_init(hwaddr daddr, void *iommu, int is_ledma) +static void *sparc32_dma_init(hwaddr dma_base, + hwaddr esp_base, qemu_irq espdma_irq, + hwaddr le_base, qemu_irq ledma_irq) { -DeviceState *dev; -SysBusDevice *s; +DeviceState *dma; +ESPDMADeviceState *espdma; +LEDMADeviceState *ledma; +SysBusESPState *esp; +SysBusPCNetState *lance; -dev = qdev_create(NULL, is_ledma ? "sparc32-ledma" : "sparc32-espdma"); -object_property_set_link(OBJECT(dev), OBJECT(iommu), "iommu", &error_abort); -qdev_init_nofail(dev); -s = SYS_BUS_DEVICE(dev); -sysbus_mmio_map(s, 0, da
[Qemu-devel] [PATCHv3 13/13] sparc32_dma: add len to esp/le DMA memory tracing
This is surprisingly useful when trying to debug DMA issues. Signed-off-by: Mark Cave-Ayland --- hw/dma/sparc32_dma.c |8 hw/dma/trace-events |8 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index bb7d70a..fbb072a 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -73,7 +73,7 @@ void ledma_memory_read(void *opaque, hwaddr addr, int i; addr |= s->dmaregs[3]; -trace_ledma_memory_read(addr); +trace_ledma_memory_read(addr, len); if (do_bswap) { sparc_iommu_memory_read(s->iommu, addr, buf, len); } else { @@ -94,7 +94,7 @@ void ledma_memory_write(void *opaque, hwaddr addr, uint16_t tmp_buf[32]; addr |= s->dmaregs[3]; -trace_ledma_memory_write(addr); +trace_ledma_memory_write(addr, len); if (do_bswap) { sparc_iommu_memory_write(s->iommu, addr, buf, len); } else { @@ -139,7 +139,7 @@ void espdma_memory_read(void *opaque, uint8_t *buf, int len) { DMADeviceState *s = opaque; -trace_espdma_memory_read(s->dmaregs[1]); +trace_espdma_memory_read(s->dmaregs[1], len); sparc_iommu_memory_read(s->iommu, s->dmaregs[1], buf, len); s->dmaregs[1] += len; } @@ -148,7 +148,7 @@ void espdma_memory_write(void *opaque, uint8_t *buf, int len) { DMADeviceState *s = opaque; -trace_espdma_memory_write(s->dmaregs[1]); +trace_espdma_memory_write(s->dmaregs[1], len); sparc_iommu_memory_write(s->iommu, s->dmaregs[1], buf, len); s->dmaregs[1] += len; } diff --git a/hw/dma/trace-events b/hw/dma/trace-events index 428469a..6b367f0 100644 --- a/hw/dma/trace-events +++ b/hw/dma/trace-events @@ -7,12 +7,12 @@ rc4030_read(uint64_t addr, uint32_t ret) "read reg[0x%"PRIx64"] = 0x%x" rc4030_write(uint64_t addr, uint32_t val) "write reg[0x%"PRIx64"] = 0x%x" # hw/dma/sparc32_dma.c -ledma_memory_read(uint64_t addr) "DMA read addr 0x%"PRIx64 -ledma_memory_write(uint64_t addr) "DMA write addr 0x%"PRIx64 +ledma_memory_read(uint64_t addr, int len) "DMA read addr 0x%"PRIx64 " len %d" +ledma_memory_write(uint64_t addr, int len) "DMA write addr 0x%"PRIx64 " len %d" sparc32_dma_set_irq_raise(void) "Raise IRQ" sparc32_dma_set_irq_lower(void) "Lower IRQ" -espdma_memory_read(uint32_t addr) "DMA read addr 0x%08x" -espdma_memory_write(uint32_t addr) "DMA write addr 0x%08x" +espdma_memory_read(uint32_t addr, int len) "DMA read addr 0x%08x len %d" +espdma_memory_write(uint32_t addr, int len) "DMA write addr 0x%08x len %d" sparc32_dma_mem_readl(uint64_t addr, uint32_t ret) "read dmareg 0x%"PRIx64": 0x%08x" sparc32_dma_mem_writel(uint64_t addr, uint32_t old, uint32_t val) "write dmareg 0x%"PRIx64": 0x%08x -> 0x%08x" sparc32_dma_enable_raise(void) "Raise DMA enable" -- 1.7.10.4
[Qemu-devel] [PATCHv3 09/13] lance: move TYPE_LANCE and SysBusPCNetState from lance.c to sun4m.h
This enables them to be used outside of lance.c. Signed-off-by: Mark Cave-Ayland CC: Jason Wang --- hw/net/lance.c |9 - include/hw/sparc/sun4m.h | 13 + 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/hw/net/lance.c b/hw/net/lance.c index 92b0c68..ef7747d 100644 --- a/hw/net/lance.c +++ b/hw/net/lance.c @@ -45,15 +45,6 @@ #include "trace.h" #include "sysemu/sysemu.h" -#define TYPE_LANCE "lance" -#define SYSBUS_PCNET(obj) \ -OBJECT_CHECK(SysBusPCNetState, (obj), TYPE_LANCE) - -typedef struct { -SysBusDevice parent_obj; - -PCNetState state; -} SysBusPCNetState; static void parent_lance_reset(void *opaque, int irq, int level) { diff --git a/include/hw/sparc/sun4m.h b/include/hw/sparc/sun4m.h index 1f1cf91..a4f5f09 100644 --- a/include/hw/sparc/sun4m.h +++ b/include/hw/sparc/sun4m.h @@ -5,6 +5,8 @@ #include "exec/hwaddr.h" #include "qapi/qmp/types.h" #include "hw/sysbus.h" +#include "net/net.h" +#include "hw/net/pcnet.h" /* Devices used by sparc32 system. */ @@ -40,6 +42,17 @@ static inline void sparc_iommu_memory_write(void *opaque, sparc_iommu_memory_rw(opaque, addr, buf, len, 1); } +/* lance.c */ +#define TYPE_LANCE "lance" +#define SYSBUS_PCNET(obj) \ +OBJECT_CHECK(SysBusPCNetState, (obj), TYPE_LANCE) + +typedef struct { +SysBusDevice parent_obj; + +PCNetState state; +} SysBusPCNetState; + /* sparc32_dma.c */ #include "hw/sparc/sparc32_dma.h" -- 1.7.10.4
[Qemu-devel] [PATCHv3 10/13] sparc32_dma: make lance device child of ledma device
This makes it possible to reference the lance device from the ledma device as required. Signed-off-by: Mark Cave-Ayland --- hw/dma/sparc32_dma.c | 23 ++- hw/sparc/sun4m.c | 31 +++ include/hw/sparc/sparc32_dma.h |3 +++ 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index 6009b94..d507ca3 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -28,7 +28,6 @@ #include "qemu/osdep.h" #include "hw/hw.h" #include "hw/sparc/sparc32_dma.h" -#include "hw/sparc/sun4m.h" #include "hw/sysbus.h" #include "trace.h" @@ -340,11 +339,33 @@ static void sparc32_ledma_device_init(Object *obj) s->is_ledma = 1; } +static void sparc32_ledma_device_realize(DeviceState *dev, Error **errp) +{ +DeviceState *d; +NICInfo *nd = &nd_table[0]; + +qemu_check_nic_model(nd, "lance"); + +d = qdev_create(NULL, "lance"); +object_property_add_child(OBJECT(dev), "lance", OBJECT(d), errp); +qdev_set_nic_properties(d, nd); +qdev_prop_set_ptr(d, "dma", dev); +qdev_init_nofail(d); +} + +static void sparc32_ledma_device_class_init(ObjectClass *klass, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(klass); + +dc->realize = sparc32_ledma_device_realize; +} + static const TypeInfo sparc32_ledma_device_info = { .name = TYPE_SPARC32_LEDMA_DEVICE, .parent= TYPE_SPARC32_DMA_DEVICE, .instance_size = sizeof(LEDMADeviceState), .instance_init = sparc32_ledma_device_init, +.class_init= sparc32_ledma_device_class_init, }; static void sparc32_dma_register_types(void) diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 4626c85..ae486a4 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -321,26 +321,6 @@ static void *sparc32_dma_init(hwaddr daddr, void *iommu, int is_ledma) return s; } -static void lance_init(NICInfo *nd, hwaddr leaddr, - void *dma_opaque, qemu_irq irq) -{ -DeviceState *dev; -SysBusDevice *s; -qemu_irq reset; - -qemu_check_nic_model(&nd_table[0], "lance"); - -dev = qdev_create(NULL, "lance"); -qdev_set_nic_properties(dev, nd); -qdev_prop_set_ptr(dev, "dma", dma_opaque); -qdev_init_nofail(dev); -s = SYS_BUS_DEVICE(dev); -sysbus_mmio_map(s, 0, leaddr); -sysbus_connect_irq(s, 0, irq); -reset = qdev_get_gpio_in(dev, 0); -qdev_connect_gpio_out(dma_opaque, 0, reset); -} - static DeviceState *slavio_intctl_init(hwaddr addr, hwaddr addrg, qemu_irq **parent_irq) @@ -819,7 +799,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, const char *cpu_model = machine->cpu_model; unsigned int i; void *iommu, *nvram; -DeviceState *espdma, *esp, *ledma; +DeviceState *espdma, *esp, *ledma, *lance; SysBusDevice *sbd; qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS]; qemu_irq fdc_tc; @@ -894,6 +874,12 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, sbd = SYS_BUS_DEVICE(ledma); sysbus_connect_irq(sbd, 0, slavio_irq[16]); +lance = DEVICE(object_resolve_path_component(OBJECT(ledma), "lance")); +sbd = SYS_BUS_DEVICE(lance); +sysbus_mmio_map(sbd, 0, hwdef->le_base); +sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(ledma, 0)); +qdev_connect_gpio_out(ledma, 0, qdev_get_gpio_in(lance, 0)); + if (graphic_depth != 8 && graphic_depth != 24) { error_report("Unsupported depth: %d", graphic_depth); exit (1); @@ -945,9 +931,6 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, empty_slot_init(hwdef->sx_base, 0x2000); } -lance_init(&nd_table[0], hwdef->le_base, ledma, - qdev_get_gpio_in(ledma, 0)); - nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x2000, 1968, 8); slavio_timer_init_all(hwdef->counter_base, slavio_irq[19], slavio_cpu_irq, smp_cpus); diff --git a/include/hw/sparc/sparc32_dma.h b/include/hw/sparc/sparc32_dma.h index 365160f..5f39c28 100644 --- a/include/hw/sparc/sparc32_dma.h +++ b/include/hw/sparc/sparc32_dma.h @@ -3,6 +3,7 @@ #include "hw/sysbus.h" #include "hw/scsi/esp.h" +#include "hw/sparc/sun4m.h" #define DMA_REGS 4 @@ -39,6 +40,8 @@ typedef struct ESPDMADeviceState { typedef struct LEDMADeviceState { DMADeviceState parent_obj; + +SysBusPCNetState *lance; } LEDMADeviceState; /* sparc32_dma.c */ -- 1.7.10.4
[Qemu-devel] [PATCHv3 12/13] sparc32_dma: remove is_ledma hack and replace with memory region alias
This hack originated from before the memory region API was introduced, and increased the size of the ledma DMA device to capture incorrect accesses beyond the end of the ledma device. A full analysis can be found on Artyom's blog at http://tyom.blogspot.co.uk/2010/10/bug-in-all-solaris-versions-after-57.html. With the memory API we can now simply alias the incorrect access onto its intended destination allowing us to remove the hack. Signed-off-by: Mark Cave-Ayland --- hw/dma/sparc32_dma.c | 20 ++-- include/hw/sparc/sparc32_dma.h |2 +- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index ba62927..bb7d70a 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -159,12 +159,6 @@ static uint64_t dma_mem_read(void *opaque, hwaddr addr, DMADeviceState *s = opaque; uint32_t saddr; -if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) { -/* aliased to espdma, but we can't get there from here */ -/* buggy driver if using undocumented behavior, just return 0 */ -trace_sparc32_dma_mem_readl(addr, 0); -return 0; -} saddr = (addr & DMA_MASK) >> 2; trace_sparc32_dma_mem_readl(addr, s->dmaregs[saddr]); return s->dmaregs[saddr]; @@ -176,11 +170,6 @@ static void dma_mem_write(void *opaque, hwaddr addr, DMADeviceState *s = opaque; uint32_t saddr; -if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) { -/* aliased to espdma, but we can't get there from here */ -trace_sparc32_dma_mem_writel(addr, 0, val); -return; -} saddr = (addr & DMA_MASK) >> 2; trace_sparc32_dma_mem_writel(addr, s->dmaregs[saddr], val); switch (saddr) { @@ -295,7 +284,6 @@ static void sparc32_espdma_device_init(Object *obj) memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s, "espdma-mmio", DMA_SIZE); -s->is_ledma = 0; } static void sparc32_espdma_device_realize(DeviceState *dev, Error **errp) @@ -336,8 +324,7 @@ static void sparc32_ledma_device_init(Object *obj) DMADeviceState *s = SPARC32_DMA_DEVICE(obj); memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s, - "ledma-mmio", DMA_ETH_SIZE); -s->is_ledma = 1; + "ledma-mmio", DMA_SIZE); } static void sparc32_ledma_device_realize(DeviceState *dev, Error **errp) @@ -410,6 +397,11 @@ static void sparc32_dma_realize(DeviceState *dev, Error **errp) sbd = SYS_BUS_DEVICE(ledma); memory_region_add_subregion(&s->dmamem, 0x10, sysbus_mmio_get_region(sbd, 0)); + +/* Add ledma alias to handle SunOS 5.7 - Solaris 9 invalid access bug */ +memory_region_init_alias(&s->ledma_alias, OBJECT(dev), "ledma-alias", + sysbus_mmio_get_region(sbd, 0), 0x4, 0x4); +memory_region_add_subregion(&s->dmamem, 0x20, &s->ledma_alias); } static void sparc32_dma_init(Object *obj) diff --git a/include/hw/sparc/sparc32_dma.h b/include/hw/sparc/sparc32_dma.h index e52cd1d..f78180f 100644 --- a/include/hw/sparc/sparc32_dma.h +++ b/include/hw/sparc/sparc32_dma.h @@ -21,7 +21,6 @@ struct DMADeviceState { qemu_irq irq; void *iommu; qemu_irq gpio[2]; -uint32_t is_ledma; }; #define TYPE_SPARC32_ESPDMA_DEVICE "sparc32-espdma" @@ -52,6 +51,7 @@ typedef struct SPARC32DMAState { SysBusDevice parent_obj; MemoryRegion dmamem; +MemoryRegion ledma_alias; ESPDMADeviceState *espdma; LEDMADeviceState *ledma; } SPARC32DMAState; -- 1.7.10.4
[Qemu-devel] [PATCHv3 01/13] sparc32_dma: rename SPARC32_DMA type to SPARC32_DMA_DEVICE
Also update the function names to match as appropriate. While we're here rename the type from sparc32_dma to sparc32-dma in order to match the current QOM convention. Signed-off-by: Mark Cave-Ayland --- hw/dma/sparc32_dma.c | 67 +- hw/sparc/sun4m.c |2 +- 2 files changed, 35 insertions(+), 34 deletions(-) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index eb491b5..a8d31c1 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -61,12 +61,13 @@ /* XXX SCSI and ethernet should have different read-only bit masks */ #define DMA_CSR_RO_MASK 0xfe07 -#define TYPE_SPARC32_DMA "sparc32_dma" -#define SPARC32_DMA(obj) OBJECT_CHECK(DMAState, (obj), TYPE_SPARC32_DMA) +#define TYPE_SPARC32_DMA_DEVICE "sparc32-dma-device" +#define SPARC32_DMA_DEVICE(obj) OBJECT_CHECK(DMADeviceState, (obj), \ + TYPE_SPARC32_DMA_DEVICE) -typedef struct DMAState DMAState; +typedef struct DMADeviceState DMADeviceState; -struct DMAState { +struct DMADeviceState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -86,7 +87,7 @@ enum { void ledma_memory_read(void *opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap) { -DMAState *s = opaque; +DMADeviceState *s = opaque; int i; addr |= s->dmaregs[3]; @@ -106,7 +107,7 @@ void ledma_memory_read(void *opaque, hwaddr addr, void ledma_memory_write(void *opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap) { -DMAState *s = opaque; +DMADeviceState *s = opaque; int l, i; uint16_t tmp_buf[32]; @@ -134,7 +135,7 @@ void ledma_memory_write(void *opaque, hwaddr addr, static void dma_set_irq(void *opaque, int irq, int level) { -DMAState *s = opaque; +DMADeviceState *s = opaque; if (level) { s->dmaregs[0] |= DMA_INTR; if (s->dmaregs[0] & DMA_INTREN) { @@ -154,7 +155,7 @@ static void dma_set_irq(void *opaque, int irq, int level) void espdma_memory_read(void *opaque, uint8_t *buf, int len) { -DMAState *s = opaque; +DMADeviceState *s = opaque; trace_espdma_memory_read(s->dmaregs[1]); sparc_iommu_memory_read(s->iommu, s->dmaregs[1], buf, len); @@ -163,7 +164,7 @@ void espdma_memory_read(void *opaque, uint8_t *buf, int len) void espdma_memory_write(void *opaque, uint8_t *buf, int len) { -DMAState *s = opaque; +DMADeviceState *s = opaque; trace_espdma_memory_write(s->dmaregs[1]); sparc_iommu_memory_write(s->iommu, s->dmaregs[1], buf, len); @@ -173,7 +174,7 @@ void espdma_memory_write(void *opaque, uint8_t *buf, int len) static uint64_t dma_mem_read(void *opaque, hwaddr addr, unsigned size) { -DMAState *s = opaque; +DMADeviceState *s = opaque; uint32_t saddr; if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) { @@ -190,7 +191,7 @@ static uint64_t dma_mem_read(void *opaque, hwaddr addr, static void dma_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { -DMAState *s = opaque; +DMADeviceState *s = opaque; uint32_t saddr; if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) { @@ -252,28 +253,28 @@ static const MemoryRegionOps dma_mem_ops = { }, }; -static void dma_reset(DeviceState *d) +static void sparc32_dma_device_reset(DeviceState *d) { -DMAState *s = SPARC32_DMA(d); +DMADeviceState *s = SPARC32_DMA_DEVICE(d); memset(s->dmaregs, 0, DMA_SIZE); s->dmaregs[0] = DMA_VER; } -static const VMStateDescription vmstate_dma = { +static const VMStateDescription vmstate_sparc32_dma_device = { .name ="sparc32_dma", .version_id = 2, .minimum_version_id = 2, .fields = (VMStateField[]) { -VMSTATE_UINT32_ARRAY(dmaregs, DMAState, DMA_REGS), +VMSTATE_UINT32_ARRAY(dmaregs, DMADeviceState, DMA_REGS), VMSTATE_END_OF_LIST() } }; -static void sparc32_dma_init(Object *obj) +static void sparc32_dma_device_init(Object *obj) { DeviceState *dev = DEVICE(obj); -DMAState *s = SPARC32_DMA(obj); +DMADeviceState *s = SPARC32_DMA_DEVICE(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); sysbus_init_irq(sbd, &s->irq); @@ -284,9 +285,9 @@ static void sparc32_dma_init(Object *obj) qdev_init_gpio_out(dev, s->gpio, 2); } -static void sparc32_dma_realize(DeviceState *dev, Error **errp) +static void sparc32_dma_device_realize(DeviceState *dev, Error **errp) { -DMAState *s = SPARC32_DMA(dev); +DMADeviceState *s = SPARC32_DMA_DEVICE(dev); int reg_size; reg_size = s->is_ledma ? DMA_ETH_SIZE : DMA_SIZE; @@ -294,35 +295,35 @@ static void sparc32_dma_realize(DeviceState *dev, Error **errp) "dma", reg_size); } -static Property sparc32_dma_properties[] = { -DEFINE_PROP_PTR("iommu_opaque", DMAState, iommu), -DEFINE_PROP_UINT32("is_ledma", DMAState, is_ledma, 0
[Qemu-devel] [PATCHv3 07/13] esp: move TYPE_ESP and SysBusESPState from esp.c to esp.h
This enables them to be used outside of esp.c. Signed-off-by: Mark Cave-Ayland CC: Paolo Bonzini --- hw/scsi/esp.c | 13 - include/hw/scsi/esp.h | 14 ++ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 22c2d91..ee586e7 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -592,19 +592,6 @@ const VMStateDescription vmstate_esp = { } }; -#define TYPE_ESP "esp" -#define ESP_STATE(obj) OBJECT_CHECK(SysBusESPState, (obj), TYPE_ESP) - -typedef struct { -/*< private >*/ -SysBusDevice parent_obj; -/*< public >*/ - -MemoryRegion iomem; -uint32_t it_shift; -ESPState esp; -} SysBusESPState; - static void sysbus_esp_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h index d2c4886..3b160f8 100644 --- a/include/hw/scsi/esp.h +++ b/include/hw/scsi/esp.h @@ -2,6 +2,7 @@ #define QEMU_HW_ESP_H #include "hw/scsi/scsi.h" +#include "hw/sysbus.h" /* esp.c */ #define ESP_MAX_DEVS 7 @@ -52,6 +53,19 @@ struct ESPState { void (*dma_cb)(ESPState *s); }; +#define TYPE_ESP "esp" +#define ESP_STATE(obj) OBJECT_CHECK(SysBusESPState, (obj), TYPE_ESP) + +typedef struct { +/*< private >*/ +SysBusDevice parent_obj; +/*< public >*/ + +MemoryRegion iomem; +uint32_t it_shift; +ESPState esp; +} SysBusESPState; + #define ESP_TCLO 0x0 #define ESP_TCMID 0x1 #define ESP_FIFO 0x2 -- 1.7.10.4
[Qemu-devel] [PATCHv3 05/13] sun4m_iommu: move TYPE_SUN4M_IOMMU declaration to sun4m.h
This is in preparation to allow the type to be used elsewhere. Signed-off-by: Mark Cave-Ayland --- hw/dma/sun4m_iommu.c | 14 -- include/hw/sparc/sun4m.h | 16 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/hw/dma/sun4m_iommu.c b/hw/dma/sun4m_iommu.c index 335ef63..840064b 100644 --- a/hw/dma/sun4m_iommu.c +++ b/hw/dma/sun4m_iommu.c @@ -36,7 +36,6 @@ * http://mediacast.sun.com/users/Barton808/media/Sun4M_SystemArchitecture_edited2.pdf */ -#define IOMMU_NREGS (4*4096/4) #define IOMMU_CTRL (0x >> 2) #define IOMMU_CTRL_IMPL 0xf000 /* Implementation */ #define IOMMU_CTRL_VERS 0x0f00 /* Version */ @@ -128,19 +127,6 @@ #define IOMMU_PAGE_SIZE (1 << IOMMU_PAGE_SHIFT) #define IOMMU_PAGE_MASK ~(IOMMU_PAGE_SIZE - 1) -#define TYPE_SUN4M_IOMMU "iommu" -#define SUN4M_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4M_IOMMU) - -typedef struct IOMMUState { -SysBusDevice parent_obj; - -MemoryRegion iomem; -uint32_t regs[IOMMU_NREGS]; -hwaddr iostart; -qemu_irq irq; -uint32_t version; -} IOMMUState; - static uint64_t iommu_mem_read(void *opaque, hwaddr addr, unsigned size) { diff --git a/include/hw/sparc/sun4m.h b/include/hw/sparc/sun4m.h index 580d87b..1f1cf91 100644 --- a/include/hw/sparc/sun4m.h +++ b/include/hw/sparc/sun4m.h @@ -4,10 +4,26 @@ #include "qemu-common.h" #include "exec/hwaddr.h" #include "qapi/qmp/types.h" +#include "hw/sysbus.h" /* Devices used by sparc32 system. */ /* iommu.c */ +#define TYPE_SUN4M_IOMMU "iommu" +#define SUN4M_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4M_IOMMU) + +#define IOMMU_NREGS (4 * 4096 / 4) + +typedef struct IOMMUState { +SysBusDevice parent_obj; + +MemoryRegion iomem; +uint32_t regs[IOMMU_NREGS]; +hwaddr iostart; +qemu_irq irq; +uint32_t version; +} IOMMUState; + void sparc_iommu_memory_rw(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write); static inline void sparc_iommu_memory_read(void *opaque, -- 1.7.10.4
[Qemu-devel] [PATCHv3 02/13] sparc32_dma: split esp and le into separate DMA devices
Due to slight differences in behaviour accessing the registers for the esp and le devices, create two separate SPARC32_DMA_DEVICE types and update the sun4m machine to use. Note that by using different device types we already know the size of the register block and the value of is_ledma at init time, allowing us to drop the SPARC32_DMA_DEVICE realize function and the is_ledma device property. Signed-off-by: Mark Cave-Ayland --- hw/dma/sparc32_dma.c | 63 -- hw/sparc/sun4m.c |3 +-- 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index a8d31c1..e4ff4a8 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -78,6 +78,22 @@ struct DMADeviceState { uint32_t is_ledma; }; +#define TYPE_SPARC32_ESPDMA_DEVICE "sparc32-espdma" +#define SPARC32_ESPDMA_DEVICE(obj) OBJECT_CHECK(ESPDMADeviceState, (obj), \ +TYPE_SPARC32_ESPDMA_DEVICE) + +typedef struct ESPDMADeviceState { +DMADeviceState parent_obj; +} ESPDMADeviceState; + +#define TYPE_SPARC32_LEDMA_DEVICE "sparc32-ledma" +#define SPARC32_LEDMA_DEVICE(obj) OBJECT_CHECK(LEDMADeviceState, (obj), \ + TYPE_SPARC32_LEDMA_DEVICE) + +typedef struct LEDMADeviceState { +DMADeviceState parent_obj; +} LEDMADeviceState; + enum { GPIO_RESET = 0, GPIO_DMA, @@ -285,19 +301,8 @@ static void sparc32_dma_device_init(Object *obj) qdev_init_gpio_out(dev, s->gpio, 2); } -static void sparc32_dma_device_realize(DeviceState *dev, Error **errp) -{ -DMADeviceState *s = SPARC32_DMA_DEVICE(dev); -int reg_size; - -reg_size = s->is_ledma ? DMA_ETH_SIZE : DMA_SIZE; -memory_region_init_io(&s->iomem, OBJECT(dev), &dma_mem_ops, s, - "dma", reg_size); -} - static Property sparc32_dma_device_properties[] = { DEFINE_PROP_PTR("iommu_opaque", DMADeviceState, iommu), -DEFINE_PROP_UINT32("is_ledma", DMADeviceState, is_ledma, 0), DEFINE_PROP_END_OF_LIST(), }; @@ -308,7 +313,6 @@ static void sparc32_dma_device_class_init(ObjectClass *klass, void *data) dc->reset = sparc32_dma_device_reset; dc->vmsd = &vmstate_sparc32_dma_device; dc->props = sparc32_dma_device_properties; -dc->realize = sparc32_dma_device_realize; /* Reason: pointer property "iommu_opaque" */ dc->user_creatable = false; } @@ -316,14 +320,49 @@ static void sparc32_dma_device_class_init(ObjectClass *klass, void *data) static const TypeInfo sparc32_dma_device_info = { .name = TYPE_SPARC32_DMA_DEVICE, .parent= TYPE_SYS_BUS_DEVICE, +.abstract = true, .instance_size = sizeof(DMADeviceState), .instance_init = sparc32_dma_device_init, .class_init= sparc32_dma_device_class_init, }; +static void sparc32_espdma_device_init(Object *obj) +{ +DMADeviceState *s = SPARC32_DMA_DEVICE(obj); + +memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s, + "espdma-mmio", DMA_SIZE); +s->is_ledma = 0; +} + +static const TypeInfo sparc32_espdma_device_info = { +.name = TYPE_SPARC32_ESPDMA_DEVICE, +.parent= TYPE_SPARC32_DMA_DEVICE, +.instance_size = sizeof(ESPDMADeviceState), +.instance_init = sparc32_espdma_device_init, +}; + +static void sparc32_ledma_device_init(Object *obj) +{ +DMADeviceState *s = SPARC32_DMA_DEVICE(obj); + +memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s, + "ledma-mmio", DMA_ETH_SIZE); +s->is_ledma = 1; +} + +static const TypeInfo sparc32_ledma_device_info = { +.name = TYPE_SPARC32_LEDMA_DEVICE, +.parent= TYPE_SPARC32_DMA_DEVICE, +.instance_size = sizeof(LEDMADeviceState), +.instance_init = sparc32_ledma_device_init, +}; + static void sparc32_dma_register_types(void) { type_register_static(&sparc32_dma_device_info); +type_register_static(&sparc32_espdma_device_info); +type_register_static(&sparc32_ledma_device_info); } type_init(sparc32_dma_register_types) diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 82c553c..88a9752 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -313,9 +313,8 @@ static void *sparc32_dma_init(hwaddr daddr, qemu_irq parent_irq, DeviceState *dev; SysBusDevice *s; -dev = qdev_create(NULL, "sparc32-dma-device"); +dev = qdev_create(NULL, is_ledma ? "sparc32-ledma" : "sparc32-espdma"); qdev_prop_set_ptr(dev, "iommu_opaque", iommu); -qdev_prop_set_uint32(dev, "is_ledma", is_ledma); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); sysbus_connect_irq(s, 0, parent_irq); -- 1.7.10.4
[Qemu-devel] [PATCHv3 06/13] sparc32_dma: use object link instead of qdev property to pass IOMMU reference
This enables us to remove the last remaining (opaque) qdev property. Whilst we are here, also update iommu_init() to use TYPE_SUN4M_IOMMU instead of a hardcoded string. Signed-off-by: Mark Cave-Ayland --- hw/dma/sparc32_dma.c | 13 + hw/sparc/sun4m.c |4 ++-- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index ae8fa06..c56a2ba 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -263,24 +263,21 @@ static void sparc32_dma_device_init(Object *obj) sysbus_init_mmio(sbd, &s->iomem); +object_property_add_link(OBJECT(dev), "iommu", TYPE_SUN4M_IOMMU, + (Object **) &s->iommu, + qdev_prop_allow_set_link_before_realize, + 0, NULL); + qdev_init_gpio_in(dev, dma_set_irq, 1); qdev_init_gpio_out(dev, s->gpio, 2); } -static Property sparc32_dma_device_properties[] = { -DEFINE_PROP_PTR("iommu_opaque", DMADeviceState, iommu), -DEFINE_PROP_END_OF_LIST(), -}; - static void sparc32_dma_device_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->reset = sparc32_dma_device_reset; dc->vmsd = &vmstate_sparc32_dma_device; -dc->props = sparc32_dma_device_properties; -/* Reason: pointer property "iommu_opaque" */ -dc->user_creatable = false; } static const TypeInfo sparc32_dma_device_info = { diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 4f2ed4b..12d36b5 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -297,7 +297,7 @@ static void *iommu_init(hwaddr addr, uint32_t version, qemu_irq irq) DeviceState *dev; SysBusDevice *s; -dev = qdev_create(NULL, "iommu"); +dev = qdev_create(NULL, TYPE_SUN4M_IOMMU); qdev_prop_set_uint32(dev, "version", version); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); @@ -313,7 +313,7 @@ static void *sparc32_dma_init(hwaddr daddr, void *iommu, int is_ledma) SysBusDevice *s; dev = qdev_create(NULL, is_ledma ? "sparc32-ledma" : "sparc32-espdma"); -qdev_prop_set_ptr(dev, "iommu_opaque", iommu); +object_property_set_link(OBJECT(dev), OBJECT(iommu), "iommu", &error_abort); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); sysbus_mmio_map(s, 0, daddr); -- 1.7.10.4
[Qemu-devel] [PATCHv3 00/13] sun4m: sparc32_dma tidy-ups
This patchset aims to tidy-up the sparc32_dma code by improving the modelling of the espdma/ledma devices using both QOM and the memory API which didn't exist when the code was first written. The result is that it is now possible to remove both the iommu_opaque and is_ledma workarounds from the code, and the code for wiring up the espdma/ledma and respective devices is also a lot more readable. Signed-off-by: Mark Cave-Ayland v3: - Add missing sysbus.h include to esp.h in patch 7 v2: - Make esp/lance devices children of espdma/ledma devices respectively - Add len parameter to ledma/espdma tracepoints Mark Cave-Ayland (13): sparc32_dma: rename SPARC32_DMA type to SPARC32_DMA_DEVICE sparc32_dma: split esp and le into separate DMA devices sparc32_dma: move type declarations from sparc32_dma.c to sparc32_dma.h sun4m: move DMA device wiring from sparc32_dma_init() to sun4m_hw_init() sun4m_iommu: move TYPE_SUN4M_IOMMU declaration to sun4m.h sparc32_dma: use object link instead of qdev property to pass IOMMU reference esp: move TYPE_ESP and SysBusESPState from esp.c to esp.h sparc32_dma: make esp device child of espdma device lance: move TYPE_LANCE and SysBusPCNetState from lance.c to sun4m.h sparc32_dma: make lance device child of ledma device sparc32_dma: introduce new SPARC32_DMA type container object sparc32_dma: remove is_ledma hack and replace with memory region alias sparc32_dma: add len to esp/le DMA memory tracing hw/dma/sparc32_dma.c | 236 +--- hw/dma/sun4m_iommu.c | 14 --- hw/dma/trace-events|8 +- hw/net/lance.c |9 -- hw/scsi/esp.c | 13 --- hw/sparc/sun4m.c | 82 ++ include/hw/scsi/esp.h | 14 +++ include/hw/sparc/sparc32_dma.h | 55 ++ include/hw/sparc/sun4m.h | 29 + 9 files changed, 307 insertions(+), 153 deletions(-) -- 1.7.10.4
[Qemu-devel] [PATCHv3 04/13] sun4m: move DMA device wiring from sparc32_dma_init() to sun4m_hw_init()
By using the sysbus interface it is possible to wire up the esp/le devices to the sun4m DMA controller directly during sun4m_hw_init() instead of passing qemu_irqs into the sparc32_dma_init() function. This is an intermediate step to allow further reorganisation as more logic is moved into the relevant SPARC32 DMA devices; there will be a final refactoring of sparc32_dma_init() once this work is complete. Signed-off-by: Mark Cave-Ayland --- hw/sparc/sun4m.c | 29 - 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 88a9752..4f2ed4b 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -307,8 +307,7 @@ static void *iommu_init(hwaddr addr, uint32_t version, qemu_irq irq) return s; } -static void *sparc32_dma_init(hwaddr daddr, qemu_irq parent_irq, - void *iommu, qemu_irq *dev_irq, int is_ledma) +static void *sparc32_dma_init(hwaddr daddr, void *iommu, int is_ledma) { DeviceState *dev; SysBusDevice *s; @@ -317,8 +316,6 @@ static void *sparc32_dma_init(hwaddr daddr, qemu_irq parent_irq, qdev_prop_set_ptr(dev, "iommu_opaque", iommu); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); -sysbus_connect_irq(s, 0, parent_irq); -*dev_irq = qdev_get_gpio_in(dev, 0); sysbus_mmio_map(s, 0, daddr); return s; @@ -821,9 +818,10 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, DeviceState *slavio_intctl; const char *cpu_model = machine->cpu_model; unsigned int i; -void *iommu, *espdma, *ledma, *nvram; -qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS], -espdma_irq, ledma_irq; +void *iommu, *nvram; +DeviceState *espdma, *ledma; +SysBusDevice *sbd; +qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS]; qemu_irq esp_reset, dma_enable; qemu_irq fdc_tc; unsigned long kernel_size; @@ -882,11 +880,13 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, empty_slot_init(hwdef->iommu_pad_base,hwdef->iommu_pad_len); } -espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[18], - iommu, &espdma_irq, 0); +espdma = sparc32_dma_init(hwdef->dma_base, iommu, 0); +sbd = SYS_BUS_DEVICE(espdma); +sysbus_connect_irq(sbd, 0, slavio_irq[18]); -ledma = sparc32_dma_init(hwdef->dma_base + 16ULL, - slavio_irq[16], iommu, &ledma_irq, 1); +ledma = sparc32_dma_init(hwdef->dma_base + 16ULL, iommu, 1); +sbd = SYS_BUS_DEVICE(ledma); +sysbus_connect_irq(sbd, 0, slavio_irq[16]); if (graphic_depth != 8 && graphic_depth != 24) { error_report("Unsupported depth: %d", graphic_depth); @@ -939,7 +939,8 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, empty_slot_init(hwdef->sx_base, 0x2000); } -lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq); +lance_init(&nd_table[0], hwdef->le_base, ledma, + qdev_get_gpio_in(ledma, 0)); nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x2000, 1968, 8); @@ -971,7 +972,9 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, esp_init(hwdef->esp_base, 2, espdma_memory_read, espdma_memory_write, - espdma, espdma_irq, &esp_reset, &dma_enable); + espdma, + qdev_get_gpio_in(espdma, 0), + &esp_reset, &dma_enable); qdev_connect_gpio_out(espdma, 0, esp_reset); qdev_connect_gpio_out(espdma, 1, dma_enable); -- 1.7.10.4
[Qemu-devel] [PATCHv3 03/13] sparc32_dma: move type declarations from sparc32_dma.c to sparc32_dma.h
Signed-off-by: Mark Cave-Ayland --- hw/dma/sparc32_dma.c | 34 -- include/hw/sparc/sparc32_dma.h | 37 + 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index e4ff4a8..ae8fa06 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -40,7 +40,6 @@ * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/DMA2.txt */ -#define DMA_REGS 4 #define DMA_SIZE (4 * sizeof(uint32_t)) /* We need the mask, because one instance of the device is not page aligned (ledma, start address 0x0010) */ @@ -61,39 +60,6 @@ /* XXX SCSI and ethernet should have different read-only bit masks */ #define DMA_CSR_RO_MASK 0xfe07 -#define TYPE_SPARC32_DMA_DEVICE "sparc32-dma-device" -#define SPARC32_DMA_DEVICE(obj) OBJECT_CHECK(DMADeviceState, (obj), \ - TYPE_SPARC32_DMA_DEVICE) - -typedef struct DMADeviceState DMADeviceState; - -struct DMADeviceState { -SysBusDevice parent_obj; - -MemoryRegion iomem; -uint32_t dmaregs[DMA_REGS]; -qemu_irq irq; -void *iommu; -qemu_irq gpio[2]; -uint32_t is_ledma; -}; - -#define TYPE_SPARC32_ESPDMA_DEVICE "sparc32-espdma" -#define SPARC32_ESPDMA_DEVICE(obj) OBJECT_CHECK(ESPDMADeviceState, (obj), \ -TYPE_SPARC32_ESPDMA_DEVICE) - -typedef struct ESPDMADeviceState { -DMADeviceState parent_obj; -} ESPDMADeviceState; - -#define TYPE_SPARC32_LEDMA_DEVICE "sparc32-ledma" -#define SPARC32_LEDMA_DEVICE(obj) OBJECT_CHECK(LEDMADeviceState, (obj), \ - TYPE_SPARC32_LEDMA_DEVICE) - -typedef struct LEDMADeviceState { -DMADeviceState parent_obj; -} LEDMADeviceState; - enum { GPIO_RESET = 0, GPIO_DMA, diff --git a/include/hw/sparc/sparc32_dma.h b/include/hw/sparc/sparc32_dma.h index 9497b13..df7491d 100644 --- a/include/hw/sparc/sparc32_dma.h +++ b/include/hw/sparc/sparc32_dma.h @@ -1,6 +1,43 @@ #ifndef SPARC32_DMA_H #define SPARC32_DMA_H +#include "hw/sysbus.h" + +#define DMA_REGS 4 + +#define TYPE_SPARC32_DMA_DEVICE "sparc32-dma-device" +#define SPARC32_DMA_DEVICE(obj) OBJECT_CHECK(DMADeviceState, (obj), \ + TYPE_SPARC32_DMA_DEVICE) + +typedef struct DMADeviceState DMADeviceState; + +struct DMADeviceState { +SysBusDevice parent_obj; + +MemoryRegion iomem; +uint32_t dmaregs[DMA_REGS]; +qemu_irq irq; +void *iommu; +qemu_irq gpio[2]; +uint32_t is_ledma; +}; + +#define TYPE_SPARC32_ESPDMA_DEVICE "sparc32-espdma" +#define SPARC32_ESPDMA_DEVICE(obj) OBJECT_CHECK(ESPDMADeviceState, (obj), \ +TYPE_SPARC32_ESPDMA_DEVICE) + +typedef struct ESPDMADeviceState { +DMADeviceState parent_obj; +} ESPDMADeviceState; + +#define TYPE_SPARC32_LEDMA_DEVICE "sparc32-ledma" +#define SPARC32_LEDMA_DEVICE(obj) OBJECT_CHECK(LEDMADeviceState, (obj), \ + TYPE_SPARC32_LEDMA_DEVICE) + +typedef struct LEDMADeviceState { +DMADeviceState parent_obj; +} LEDMADeviceState; + /* sparc32_dma.c */ void ledma_memory_read(void *opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap); -- 1.7.10.4
Re: [Qemu-devel] [PATCHv2 00/13] sun4m: sparc32_dma tidy-ups
Hi, This series failed automatic build test. Please find the testing commands and their output below. If you have docker installed, you can probably reproduce it locally. Type: series Message-id: 1508004545-28578-1-git-send-email-mark.cave-ayl...@ilande.co.uk Subject: [Qemu-devel] [PATCHv2 00/13] sun4m: sparc32_dma tidy-ups === TEST SCRIPT BEGIN === #!/bin/bash set -e git submodule update --init dtc # Let docker tests dump environment info export SHOW_ENV=1 export J=8 time make docker-test-quick@centos6 time make docker-test-build@min-glib time make docker-test-mingw@fedora time make docker-test-block@fedora === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 From https://github.com/patchew-project/qemu t [tag update] patchew/1507816448-86665-1-git-send-email-pbonz...@redhat.com -> patchew/1507816448-86665-1-git-send-email-pbonz...@redhat.com t [tag update] patchew/1507930220-17461-1-git-send-email-c...@braap.org -> patchew/1507930220-17461-1-git-send-email-c...@braap.org * [new tag] patchew/1508004545-28578-1-git-send-email-mark.cave-ayl...@ilande.co.uk -> patchew/1508004545-28578-1-git-send-email-mark.cave-ayl...@ilande.co.uk t [tag update]patchew/20171013054842.32120-1...@weilnetz.de -> patchew/20171013054842.32120-1...@weilnetz.de t [tag update] patchew/20171013162438.32458-1-alex.ben...@linaro.org -> patchew/20171013162438.32458-1-alex.ben...@linaro.org Switched to a new branch 'test' 750844c42d sparc32_dma: add len to esp/le DMA memory tracing ba7ab63f8e sparc32_dma: remove is_ledma hack and replace with memory region alias cf74bfb2aa sparc32_dma: introduce new SPARC32_DMA type container object 1a9feba778 sparc32_dma: make lance device child of ledma device 86b3305848 lance: move TYPE_LANCE and SysBusPCNetState from lance.c to sun4m.h c5ae1c6011 sparc32_dma: make esp device child of espdma device 420993a6ce esp: move TYPE_ESP and SysBusESPState from esp.c to esp.h 236dbd4516 sparc32_dma: use object link instead of qdev property to pass IOMMU reference 5165f5669a sun4m_iommu: move TYPE_SUN4M_IOMMU declaration to sun4m.h 850a150983 sun4m: move DMA device wiring from sparc32_dma_init() to sun4m_hw_init() 4ba0c4c9f1 sparc32_dma: move type declarations from sparc32_dma.c to sparc32_dma.h 553bbcee17 sparc32_dma: split esp and le into separate DMA devices dd74a83295 sparc32_dma: rename SPARC32_DMA type to SPARC32_DMA_DEVICE === OUTPUT BEGIN === Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc' Cloning into '/var/tmp/patchew-tester-tmp-4z0wtpem/src/dtc'... Submodule path 'dtc': checked out '558cd81bdd432769b59bff01240c44f82cfb1a9d' BUILD centos6 make[1]: Entering directory '/var/tmp/patchew-tester-tmp-4z0wtpem/src' GEN docker-src.2017-10-14-14.23.58.20533/qemu.tar COPYRUNNER RUN test-quick in qemu:centos6 Packages installed: SDL-devel-1.2.14-7.el6_7.1.x86_64 bison-2.4.1-5.el6.x86_64 bzip2-devel-1.0.5-7.el6_0.x86_64 ccache-3.1.6-2.el6.x86_64 csnappy-devel-0-6.20150729gitd7bc683.el6.x86_64 flex-2.5.35-9.el6.x86_64 gcc-4.4.7-18.el6.x86_64 gettext-0.17-18.el6.x86_64 git-1.7.1-9.el6_9.x86_64 glib2-devel-2.28.8-9.el6.x86_64 libepoxy-devel-1.2-3.el6.x86_64 libfdt-devel-1.4.0-1.el6.x86_64 librdmacm-devel-1.0.21-0.el6.x86_64 lzo-devel-2.03-3.1.el6_5.1.x86_64 make-3.81-23.el6.x86_64 mesa-libEGL-devel-11.0.7-4.el6.x86_64 mesa-libgbm-devel-11.0.7-4.el6.x86_64 package g++ is not installed pixman-devel-0.32.8-1.el6.x86_64 spice-glib-devel-0.26-8.el6.x86_64 spice-server-devel-0.12.4-16.el6.x86_64 tar-1.23-15.el6_8.x86_64 vte-devel-0.25.1-9.el6.x86_64 xen-devel-4.6.6-2.el6.x86_64 zlib-devel-1.2.3-29.el6.x86_64 Environment variables: PACKAGES=bison bzip2-devel ccache csnappy-devel flex g++ gcc gettext git glib2-devel libepoxy-devel libfdt-devel librdmacm-devel lzo-devel make mesa-libEGL-devel mesa-libgbm-devel pixman-devel SDL-devel spice-glib-devel spice-server-devel tar vte-devel xen-devel zlib-devel HOSTNAME=2430be8c8daf TERM=xterm MAKEFLAGS= -j8 J=8 CCACHE_DIR=/var/tmp/ccache EXTRA_CONFIGURE_OPTS= V= SHOW_ENV=1 PATH=/usr/lib/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PWD=/ TARGET_LIST= SHLVL=1 HOME=/root TEST_DIR=/tmp/qemu-test FEATURES= dtc DEBUG= _=/usr/bin/env Configure options: --enable-werror --target-list=x86_64-softmmu,aarch64-softmmu --prefix=/tmp/qemu-test/install No C++ compiler available; disabling C++ specific optional code Install prefix/tmp/qemu-test/install BIOS directory/tmp/qemu-test/install/share/qemu firmware path /tmp/qemu-test/install/share/qemu-firmware binary directory /tmp/qemu-test/install/bin library directory /tmp/qemu-test/install/lib module directory /tmp/qemu-test/install/lib/qemu libexec directory /tmp/qemu-test/install/libexec include directory /tmp/qemu-test/install/include config directory /tmp/q
Re: [Qemu-devel] [PATCHv2 00/13] sun4m: sparc32_dma tidy-ups
Hi, This series seems to have some coding style problems. See output below for more information: Type: series Message-id: 1508004545-28578-1-git-send-email-mark.cave-ayl...@ilande.co.uk Subject: [Qemu-devel] [PATCHv2 00/13] sun4m: sparc32_dma tidy-ups === TEST SCRIPT BEGIN === #!/bin/bash BASE=base n=1 total=$(git log --oneline $BASE.. | wc -l) failed=0 git config --local diff.renamelimit 0 git config --local diff.renames True commits="$(git log --format=%H --reverse $BASE..)" for c in $commits; do echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..." if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then failed=1 echo fi n=$((n+1)) done exit $failed === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 Switched to a new branch 'test' 750844c42d sparc32_dma: add len to esp/le DMA memory tracing ba7ab63f8e sparc32_dma: remove is_ledma hack and replace with memory region alias cf74bfb2aa sparc32_dma: introduce new SPARC32_DMA type container object 1a9feba778 sparc32_dma: make lance device child of ledma device 86b3305848 lance: move TYPE_LANCE and SysBusPCNetState from lance.c to sun4m.h c5ae1c6011 sparc32_dma: make esp device child of espdma device 420993a6ce esp: move TYPE_ESP and SysBusESPState from esp.c to esp.h 236dbd4516 sparc32_dma: use object link instead of qdev property to pass IOMMU reference 5165f5669a sun4m_iommu: move TYPE_SUN4M_IOMMU declaration to sun4m.h 850a150983 sun4m: move DMA device wiring from sparc32_dma_init() to sun4m_hw_init() 4ba0c4c9f1 sparc32_dma: move type declarations from sparc32_dma.c to sparc32_dma.h 553bbcee17 sparc32_dma: split esp and le into separate DMA devices dd74a83295 sparc32_dma: rename SPARC32_DMA type to SPARC32_DMA_DEVICE === OUTPUT BEGIN === Checking PATCH 1/13: sparc32_dma: rename SPARC32_DMA type to SPARC32_DMA_DEVICE... Checking PATCH 2/13: sparc32_dma: split esp and le into separate DMA devices... Checking PATCH 3/13: sparc32_dma: move type declarations from sparc32_dma.c to sparc32_dma.h... Checking PATCH 4/13: sun4m: move DMA device wiring from sparc32_dma_init() to sun4m_hw_init()... ERROR: spaces required around that '*' (ctx:WxV) #51: FILE: hw/sparc/sun4m.c:824: +qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS]; ^ total: 1 errors, 0 warnings, 66 lines checked Your patch has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. Checking PATCH 5/13: sun4m_iommu: move TYPE_SUN4M_IOMMU declaration to sun4m.h... Checking PATCH 6/13: sparc32_dma: use object link instead of qdev property to pass IOMMU reference... Checking PATCH 7/13: esp: move TYPE_ESP and SysBusESPState from esp.c to esp.h... Checking PATCH 8/13: sparc32_dma: make esp device child of espdma device... Checking PATCH 9/13: lance: move TYPE_LANCE and SysBusPCNetState from lance.c to sun4m.h... Checking PATCH 10/13: sparc32_dma: make lance device child of ledma device... Checking PATCH 11/13: sparc32_dma: introduce new SPARC32_DMA type container object... Checking PATCH 12/13: sparc32_dma: remove is_ledma hack and replace with memory region alias... Checking PATCH 13/13: sparc32_dma: add len to esp/le DMA memory tracing... === OUTPUT END === Test command exited with code: 1 --- Email generated automatically by Patchew [http://patchew.org/]. Please send your feedback to patchew-de...@freelists.org
[Qemu-devel] [PATCH 1/3] sun4m: implement IOMMU translation using IOMMU memory region
Signed-off-by: Mark Cave-Ayland --- hw/dma/sun4m_iommu.c | 62 ++ include/hw/sparc/sun4m.h |5 2 files changed, 67 insertions(+) diff --git a/hw/dma/sun4m_iommu.c b/hw/dma/sun4m_iommu.c index 840064b..ce21a22 100644 --- a/hw/dma/sun4m_iommu.c +++ b/hw/dma/sun4m_iommu.c @@ -278,6 +278,49 @@ static void iommu_bad_addr(IOMMUState *s, hwaddr addr, qemu_irq_raise(s->irq); } +/* Called from RCU critical section */ +static IOMMUTLBEntry sun4m_translate_iommu(IOMMUMemoryRegion *iommu, + hwaddr addr, + IOMMUAccessFlags flags) +{ +IOMMUState *is = container_of(iommu, IOMMUState, iommu); +hwaddr page, pa; +int is_write = (flags & IOMMU_WO) ? 1 : 0; +uint32_t pte; +IOMMUTLBEntry ret = { +.target_as = &address_space_memory, +.iova = 0, +.translated_addr = 0, +.addr_mask = ~(hwaddr)0, +.perm = IOMMU_NONE, +}; + +page = addr & IOMMU_PAGE_MASK; +pte = iommu_page_get_flags(is, page); +if (!(pte & IOPTE_VALID)) { +iommu_bad_addr(is, page, is_write); +return ret; +} + +pa = iommu_translate_pa(addr, pte); +if (is_write && !(pte & IOPTE_WRITE)) { +iommu_bad_addr(is, page, is_write); +return ret; +} + +if (pte & IOPTE_WRITE) { +ret.perm = IOMMU_RW; +} else { +ret.perm = IOMMU_RO; +} + +ret.iova = page; +ret.translated_addr = pa; +ret.addr_mask = ~IOMMU_PAGE_MASK; + +return ret; +} + void sparc_iommu_memory_rw(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write) { @@ -340,6 +383,11 @@ static void iommu_init(Object *obj) IOMMUState *s = SUN4M_IOMMU(obj); SysBusDevice *dev = SYS_BUS_DEVICE(obj); +memory_region_init_iommu(&s->iommu, sizeof(s->iommu), + TYPE_SUN4M_IOMMU_MEMORY_REGION, OBJECT(dev), + "iommu-sun4m", UINT64_MAX); +address_space_init(&s->iommu_as, MEMORY_REGION(&s->iommu), "iommu-as"); + sysbus_init_irq(dev, &s->irq); memory_region_init_io(&s->iomem, obj, &iommu_mem_ops, s, "iommu", @@ -369,9 +417,23 @@ static const TypeInfo iommu_info = { .class_init= iommu_class_init, }; +static void sun4m_iommu_memory_region_class_init(ObjectClass *klass, void *data) +{ +IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass); + +imrc->translate = sun4m_translate_iommu; +} + +static const TypeInfo sun4m_iommu_memory_region_info = { +.parent = TYPE_IOMMU_MEMORY_REGION, +.name = TYPE_SUN4M_IOMMU_MEMORY_REGION, +.class_init = sun4m_iommu_memory_region_class_init, +}; + static void iommu_register_types(void) { type_register_static(&iommu_info); +type_register_static(&sun4m_iommu_memory_region_info); } type_init(iommu_register_types) diff --git a/include/hw/sparc/sun4m.h b/include/hw/sparc/sun4m.h index a4f5f09..0548bac 100644 --- a/include/hw/sparc/sun4m.h +++ b/include/hw/sparc/sun4m.h @@ -14,11 +14,16 @@ #define TYPE_SUN4M_IOMMU "iommu" #define SUN4M_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4M_IOMMU) +#define TYPE_SUN4M_IOMMU_MEMORY_REGION "sun4m-iommu-memory-region" + #define IOMMU_NREGS (4 * 4096 / 4) typedef struct IOMMUState { SysBusDevice parent_obj; +AddressSpace iommu_as; +IOMMUMemoryRegion iommu; + MemoryRegion iomem; uint32_t regs[IOMMU_NREGS]; hwaddr iostart; -- 1.7.10.4
[Qemu-devel] [PATCH 2/3] sparc32_dma: switch over to using IOMMU memory region and DMA API
Signed-off-by: Mark Cave-Ayland --- hw/dma/sparc32_dma.c | 17 +++-- 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index fbb072a..5438831 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -29,6 +29,7 @@ #include "hw/hw.h" #include "hw/sparc/sparc32_dma.h" #include "hw/sysbus.h" +#include "sysemu/dma.h" #include "qapi/error.h" #include "trace.h" @@ -70,16 +71,17 @@ void ledma_memory_read(void *opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap) { DMADeviceState *s = opaque; +IOMMUState *is = (IOMMUState *)s->iommu; int i; addr |= s->dmaregs[3]; trace_ledma_memory_read(addr, len); if (do_bswap) { -sparc_iommu_memory_read(s->iommu, addr, buf, len); +dma_memory_read(&is->iommu_as, addr, buf, len); } else { addr &= ~1; len &= ~1; -sparc_iommu_memory_read(s->iommu, addr, buf, len); +dma_memory_read(&is->iommu_as, addr, buf, len); for(i = 0; i < len; i += 2) { bswap16s((uint16_t *)(buf + i)); } @@ -90,13 +92,14 @@ void ledma_memory_write(void *opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap) { DMADeviceState *s = opaque; +IOMMUState *is = (IOMMUState *)s->iommu; int l, i; uint16_t tmp_buf[32]; addr |= s->dmaregs[3]; trace_ledma_memory_write(addr, len); if (do_bswap) { -sparc_iommu_memory_write(s->iommu, addr, buf, len); +dma_memory_write(&is->iommu_as, addr, buf, len); } else { addr &= ~1; len &= ~1; @@ -107,7 +110,7 @@ void ledma_memory_write(void *opaque, hwaddr addr, for(i = 0; i < l; i += 2) { tmp_buf[i >> 1] = bswap16(*(uint16_t *)(buf + i)); } -sparc_iommu_memory_write(s->iommu, addr, (uint8_t *)tmp_buf, l); +dma_memory_write(&is->iommu_as, addr, tmp_buf, l); len -= l; buf += l; addr += l; @@ -138,18 +141,20 @@ static void dma_set_irq(void *opaque, int irq, int level) void espdma_memory_read(void *opaque, uint8_t *buf, int len) { DMADeviceState *s = opaque; +IOMMUState *is = (IOMMUState *)s->iommu; trace_espdma_memory_read(s->dmaregs[1], len); -sparc_iommu_memory_read(s->iommu, s->dmaregs[1], buf, len); +dma_memory_read(&is->iommu_as, s->dmaregs[1], buf, len); s->dmaregs[1] += len; } void espdma_memory_write(void *opaque, uint8_t *buf, int len) { DMADeviceState *s = opaque; +IOMMUState *is = (IOMMUState *)s->iommu; trace_espdma_memory_write(s->dmaregs[1], len); -sparc_iommu_memory_write(s->iommu, s->dmaregs[1], buf, len); +dma_memory_write(&is->iommu_as, s->dmaregs[1], buf, len); s->dmaregs[1] += len; } -- 1.7.10.4
[Qemu-devel] [PATCH 3/3] sun4m_iommu: remove legacy sparc_iommu_memory_rw() function
With the switch to the IOMMU memory region and DMA API, this is no longer required. Signed-off-by: Mark Cave-Ayland --- hw/dma/sun4m_iommu.c | 33 - include/hw/sparc/sun4m.h | 16 2 files changed, 49 deletions(-) diff --git a/hw/dma/sun4m_iommu.c b/hw/dma/sun4m_iommu.c index ce21a22..30a05e8 100644 --- a/hw/dma/sun4m_iommu.c +++ b/hw/dma/sun4m_iommu.c @@ -321,39 +321,6 @@ static IOMMUTLBEntry sun4m_translate_iommu(IOMMUMemoryRegion *iommu, return ret; } -void sparc_iommu_memory_rw(void *opaque, hwaddr addr, - uint8_t *buf, int len, int is_write) -{ -int l; -uint32_t flags; -hwaddr page, phys_addr; - -while (len > 0) { -page = addr & IOMMU_PAGE_MASK; -l = (page + IOMMU_PAGE_SIZE) - addr; -if (l > len) -l = len; -flags = iommu_page_get_flags(opaque, page); -if (!(flags & IOPTE_VALID)) { -iommu_bad_addr(opaque, page, is_write); -return; -} -phys_addr = iommu_translate_pa(addr, flags); -if (is_write) { -if (!(flags & IOPTE_WRITE)) { -iommu_bad_addr(opaque, page, is_write); -return; -} -cpu_physical_memory_write(phys_addr, buf, l); -} else { -cpu_physical_memory_read(phys_addr, buf, l); -} -len -= l; -buf += l; -addr += l; -} -} - static const VMStateDescription vmstate_iommu = { .name ="iommu", .version_id = 2, diff --git a/include/hw/sparc/sun4m.h b/include/hw/sparc/sun4m.h index 0548bac..662f86e 100644 --- a/include/hw/sparc/sun4m.h +++ b/include/hw/sparc/sun4m.h @@ -31,22 +31,6 @@ typedef struct IOMMUState { uint32_t version; } IOMMUState; -void sparc_iommu_memory_rw(void *opaque, hwaddr addr, - uint8_t *buf, int len, int is_write); -static inline void sparc_iommu_memory_read(void *opaque, - hwaddr addr, - uint8_t *buf, int len) -{ -sparc_iommu_memory_rw(opaque, addr, buf, len, 0); -} - -static inline void sparc_iommu_memory_write(void *opaque, -hwaddr addr, -uint8_t *buf, int len) -{ -sparc_iommu_memory_rw(opaque, addr, buf, len, 1); -} - /* lance.c */ #define TYPE_LANCE "lance" #define SYSBUS_PCNET(obj) \ -- 1.7.10.4
[Qemu-devel] [PATCH 0/3] sun4m: implement memory region IOMMU translation and DMA API
The original sun4m IOMMU/DMA code dates from before the introduction of the QEMU memory region API (in particular IOMMU memory regions) and the DMA API. This patchset removes these sun4m-specific implementations and replaces them with the more up-to-date QEMU APIs instead. Signed-off-by: Mark Cave-Ayland Based-on: 1508004545-28578-1-git-send-email-mark.cave-ayl...@ilande.co.uk ([PATCHv2 00/13] sun4m: sparc32_dma tidy-ups) Mark Cave-Ayland (3): sun4m: implement IOMMU translation using IOMMU memory region sparc32_dma: switch over to using IOMMU memory region and DMA API sun4m_iommu: remove legacy sparc_iommu_memory_rw() function hw/dma/sparc32_dma.c | 17 + hw/dma/sun4m_iommu.c | 87 ++ include/hw/sparc/sun4m.h | 21 +++ 3 files changed, 74 insertions(+), 51 deletions(-) -- 1.7.10.4
[Qemu-devel] [PATCHv2 12/13] sparc32_dma: remove is_ledma hack and replace with memory region alias
This hack originated from before the memory region API was introduced, and increased the size of the ledma DMA device to capture incorrect accesses beyond the end of the ledma device. A full analysis can be found on Artyom's blog at http://tyom.blogspot.co.uk/2010/10/bug-in-all-solaris-versions-after-57.html. With the memory API we can now simply alias the incorrect access onto its intended destination allowing us to remove the hack. Signed-off-by: Mark Cave-Ayland --- hw/dma/sparc32_dma.c | 20 ++-- include/hw/sparc/sparc32_dma.h |2 +- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index ba62927..bb7d70a 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -159,12 +159,6 @@ static uint64_t dma_mem_read(void *opaque, hwaddr addr, DMADeviceState *s = opaque; uint32_t saddr; -if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) { -/* aliased to espdma, but we can't get there from here */ -/* buggy driver if using undocumented behavior, just return 0 */ -trace_sparc32_dma_mem_readl(addr, 0); -return 0; -} saddr = (addr & DMA_MASK) >> 2; trace_sparc32_dma_mem_readl(addr, s->dmaregs[saddr]); return s->dmaregs[saddr]; @@ -176,11 +170,6 @@ static void dma_mem_write(void *opaque, hwaddr addr, DMADeviceState *s = opaque; uint32_t saddr; -if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) { -/* aliased to espdma, but we can't get there from here */ -trace_sparc32_dma_mem_writel(addr, 0, val); -return; -} saddr = (addr & DMA_MASK) >> 2; trace_sparc32_dma_mem_writel(addr, s->dmaregs[saddr], val); switch (saddr) { @@ -295,7 +284,6 @@ static void sparc32_espdma_device_init(Object *obj) memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s, "espdma-mmio", DMA_SIZE); -s->is_ledma = 0; } static void sparc32_espdma_device_realize(DeviceState *dev, Error **errp) @@ -336,8 +324,7 @@ static void sparc32_ledma_device_init(Object *obj) DMADeviceState *s = SPARC32_DMA_DEVICE(obj); memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s, - "ledma-mmio", DMA_ETH_SIZE); -s->is_ledma = 1; + "ledma-mmio", DMA_SIZE); } static void sparc32_ledma_device_realize(DeviceState *dev, Error **errp) @@ -410,6 +397,11 @@ static void sparc32_dma_realize(DeviceState *dev, Error **errp) sbd = SYS_BUS_DEVICE(ledma); memory_region_add_subregion(&s->dmamem, 0x10, sysbus_mmio_get_region(sbd, 0)); + +/* Add ledma alias to handle SunOS 5.7 - Solaris 9 invalid access bug */ +memory_region_init_alias(&s->ledma_alias, OBJECT(dev), "ledma-alias", + sysbus_mmio_get_region(sbd, 0), 0x4, 0x4); +memory_region_add_subregion(&s->dmamem, 0x20, &s->ledma_alias); } static void sparc32_dma_init(Object *obj) diff --git a/include/hw/sparc/sparc32_dma.h b/include/hw/sparc/sparc32_dma.h index e52cd1d..f78180f 100644 --- a/include/hw/sparc/sparc32_dma.h +++ b/include/hw/sparc/sparc32_dma.h @@ -21,7 +21,6 @@ struct DMADeviceState { qemu_irq irq; void *iommu; qemu_irq gpio[2]; -uint32_t is_ledma; }; #define TYPE_SPARC32_ESPDMA_DEVICE "sparc32-espdma" @@ -52,6 +51,7 @@ typedef struct SPARC32DMAState { SysBusDevice parent_obj; MemoryRegion dmamem; +MemoryRegion ledma_alias; ESPDMADeviceState *espdma; LEDMADeviceState *ledma; } SPARC32DMAState; -- 1.7.10.4
[Qemu-devel] [PATCHv2 10/13] sparc32_dma: make lance device child of ledma device
This makes it possible to reference the lance device from the ledma device as required. Signed-off-by: Mark Cave-Ayland --- hw/dma/sparc32_dma.c | 23 ++- hw/sparc/sun4m.c | 31 +++ include/hw/sparc/sparc32_dma.h |3 +++ 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index 6009b94..d507ca3 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -28,7 +28,6 @@ #include "qemu/osdep.h" #include "hw/hw.h" #include "hw/sparc/sparc32_dma.h" -#include "hw/sparc/sun4m.h" #include "hw/sysbus.h" #include "trace.h" @@ -340,11 +339,33 @@ static void sparc32_ledma_device_init(Object *obj) s->is_ledma = 1; } +static void sparc32_ledma_device_realize(DeviceState *dev, Error **errp) +{ +DeviceState *d; +NICInfo *nd = &nd_table[0]; + +qemu_check_nic_model(nd, "lance"); + +d = qdev_create(NULL, "lance"); +object_property_add_child(OBJECT(dev), "lance", OBJECT(d), errp); +qdev_set_nic_properties(d, nd); +qdev_prop_set_ptr(d, "dma", dev); +qdev_init_nofail(d); +} + +static void sparc32_ledma_device_class_init(ObjectClass *klass, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(klass); + +dc->realize = sparc32_ledma_device_realize; +} + static const TypeInfo sparc32_ledma_device_info = { .name = TYPE_SPARC32_LEDMA_DEVICE, .parent= TYPE_SPARC32_DMA_DEVICE, .instance_size = sizeof(LEDMADeviceState), .instance_init = sparc32_ledma_device_init, +.class_init= sparc32_ledma_device_class_init, }; static void sparc32_dma_register_types(void) diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 4626c85..ae486a4 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -321,26 +321,6 @@ static void *sparc32_dma_init(hwaddr daddr, void *iommu, int is_ledma) return s; } -static void lance_init(NICInfo *nd, hwaddr leaddr, - void *dma_opaque, qemu_irq irq) -{ -DeviceState *dev; -SysBusDevice *s; -qemu_irq reset; - -qemu_check_nic_model(&nd_table[0], "lance"); - -dev = qdev_create(NULL, "lance"); -qdev_set_nic_properties(dev, nd); -qdev_prop_set_ptr(dev, "dma", dma_opaque); -qdev_init_nofail(dev); -s = SYS_BUS_DEVICE(dev); -sysbus_mmio_map(s, 0, leaddr); -sysbus_connect_irq(s, 0, irq); -reset = qdev_get_gpio_in(dev, 0); -qdev_connect_gpio_out(dma_opaque, 0, reset); -} - static DeviceState *slavio_intctl_init(hwaddr addr, hwaddr addrg, qemu_irq **parent_irq) @@ -819,7 +799,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, const char *cpu_model = machine->cpu_model; unsigned int i; void *iommu, *nvram; -DeviceState *espdma, *esp, *ledma; +DeviceState *espdma, *esp, *ledma, *lance; SysBusDevice *sbd; qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS]; qemu_irq fdc_tc; @@ -894,6 +874,12 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, sbd = SYS_BUS_DEVICE(ledma); sysbus_connect_irq(sbd, 0, slavio_irq[16]); +lance = DEVICE(object_resolve_path_component(OBJECT(ledma), "lance")); +sbd = SYS_BUS_DEVICE(lance); +sysbus_mmio_map(sbd, 0, hwdef->le_base); +sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(ledma, 0)); +qdev_connect_gpio_out(ledma, 0, qdev_get_gpio_in(lance, 0)); + if (graphic_depth != 8 && graphic_depth != 24) { error_report("Unsupported depth: %d", graphic_depth); exit (1); @@ -945,9 +931,6 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, empty_slot_init(hwdef->sx_base, 0x2000); } -lance_init(&nd_table[0], hwdef->le_base, ledma, - qdev_get_gpio_in(ledma, 0)); - nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x2000, 1968, 8); slavio_timer_init_all(hwdef->counter_base, slavio_irq[19], slavio_cpu_irq, smp_cpus); diff --git a/include/hw/sparc/sparc32_dma.h b/include/hw/sparc/sparc32_dma.h index 365160f..5f39c28 100644 --- a/include/hw/sparc/sparc32_dma.h +++ b/include/hw/sparc/sparc32_dma.h @@ -3,6 +3,7 @@ #include "hw/sysbus.h" #include "hw/scsi/esp.h" +#include "hw/sparc/sun4m.h" #define DMA_REGS 4 @@ -39,6 +40,8 @@ typedef struct ESPDMADeviceState { typedef struct LEDMADeviceState { DMADeviceState parent_obj; + +SysBusPCNetState *lance; } LEDMADeviceState; /* sparc32_dma.c */ -- 1.7.10.4
[Qemu-devel] [PATCHv2 09/13] lance: move TYPE_LANCE and SysBusPCNetState from lance.c to sun4m.h
This enables them to be used outside of lance.c. Signed-off-by: Mark Cave-Ayland CC: Jason Wang --- hw/net/lance.c |9 - include/hw/sparc/sun4m.h | 13 + 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/hw/net/lance.c b/hw/net/lance.c index 92b0c68..ef7747d 100644 --- a/hw/net/lance.c +++ b/hw/net/lance.c @@ -45,15 +45,6 @@ #include "trace.h" #include "sysemu/sysemu.h" -#define TYPE_LANCE "lance" -#define SYSBUS_PCNET(obj) \ -OBJECT_CHECK(SysBusPCNetState, (obj), TYPE_LANCE) - -typedef struct { -SysBusDevice parent_obj; - -PCNetState state; -} SysBusPCNetState; static void parent_lance_reset(void *opaque, int irq, int level) { diff --git a/include/hw/sparc/sun4m.h b/include/hw/sparc/sun4m.h index 1f1cf91..a4f5f09 100644 --- a/include/hw/sparc/sun4m.h +++ b/include/hw/sparc/sun4m.h @@ -5,6 +5,8 @@ #include "exec/hwaddr.h" #include "qapi/qmp/types.h" #include "hw/sysbus.h" +#include "net/net.h" +#include "hw/net/pcnet.h" /* Devices used by sparc32 system. */ @@ -40,6 +42,17 @@ static inline void sparc_iommu_memory_write(void *opaque, sparc_iommu_memory_rw(opaque, addr, buf, len, 1); } +/* lance.c */ +#define TYPE_LANCE "lance" +#define SYSBUS_PCNET(obj) \ +OBJECT_CHECK(SysBusPCNetState, (obj), TYPE_LANCE) + +typedef struct { +SysBusDevice parent_obj; + +PCNetState state; +} SysBusPCNetState; + /* sparc32_dma.c */ #include "hw/sparc/sparc32_dma.h" -- 1.7.10.4
[Qemu-devel] [PATCHv2 08/13] sparc32_dma: make esp device child of espdma device
This makes it possible to reference the esp device from the espdma device as required, and by wiring up the device ourselves in sun4m.c we can drop use of the esp_init() function. Signed-off-by: Mark Cave-Ayland --- hw/dma/sparc32_dma.c | 26 ++ hw/sparc/sun4m.c | 19 --- include/hw/sparc/sparc32_dma.h |3 +++ 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index c56a2ba..6009b94 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -298,11 +298,37 @@ static void sparc32_espdma_device_init(Object *obj) s->is_ledma = 0; } +static void sparc32_espdma_device_realize(DeviceState *dev, Error **errp) +{ +DeviceState *d; +SysBusESPState *sysbus; +ESPState *esp; + +d = qdev_create(NULL, TYPE_ESP); +object_property_add_child(OBJECT(dev), "esp", OBJECT(d), errp); +sysbus = ESP_STATE(d); +esp = &sysbus->esp; +esp->dma_memory_read = espdma_memory_read; +esp->dma_memory_write = espdma_memory_write; +esp->dma_opaque = SPARC32_DMA_DEVICE(dev); +sysbus->it_shift = 2; +esp->dma_enabled = 1; +qdev_init_nofail(d); +} + +static void sparc32_espdma_device_class_init(ObjectClass *klass, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(klass); + +dc->realize = sparc32_espdma_device_realize; +} + static const TypeInfo sparc32_espdma_device_info = { .name = TYPE_SPARC32_ESPDMA_DEVICE, .parent= TYPE_SPARC32_DMA_DEVICE, .instance_size = sizeof(ESPDMADeviceState), .instance_init = sparc32_espdma_device_init, +.class_init= sparc32_espdma_device_class_init, }; static void sparc32_ledma_device_init(Object *obj) diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 12d36b5..4626c85 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -819,10 +819,9 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, const char *cpu_model = machine->cpu_model; unsigned int i; void *iommu, *nvram; -DeviceState *espdma, *ledma; +DeviceState *espdma, *esp, *ledma; SysBusDevice *sbd; qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS]; -qemu_irq esp_reset, dma_enable; qemu_irq fdc_tc; unsigned long kernel_size; DriveInfo *fd[MAX_FD]; @@ -884,6 +883,13 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, sbd = SYS_BUS_DEVICE(espdma); sysbus_connect_irq(sbd, 0, slavio_irq[18]); +esp = DEVICE(object_resolve_path_component(OBJECT(espdma), "esp")); +sbd = SYS_BUS_DEVICE(esp); +sysbus_mmio_map(sbd, 0, hwdef->esp_base); +sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(espdma, 0)); +qdev_connect_gpio_out(espdma, 0, qdev_get_gpio_in(esp, 0)); +qdev_connect_gpio_out(espdma, 1, qdev_get_gpio_in(esp, 1)); + ledma = sparc32_dma_init(hwdef->dma_base + 16ULL, iommu, 1); sbd = SYS_BUS_DEVICE(ledma); sysbus_connect_irq(sbd, 0, slavio_irq[16]); @@ -970,15 +976,6 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, slavio_misc_init(hwdef->slavio_base, hwdef->aux1_base, hwdef->aux2_base, slavio_irq[30], fdc_tc); -esp_init(hwdef->esp_base, 2, - espdma_memory_read, espdma_memory_write, - espdma, - qdev_get_gpio_in(espdma, 0), - &esp_reset, &dma_enable); - -qdev_connect_gpio_out(espdma, 0, esp_reset); -qdev_connect_gpio_out(espdma, 1, dma_enable); - if (hwdef->cs_base) { sysbus_create_simple("SUNW,CS4231", hwdef->cs_base, slavio_irq[5]); diff --git a/include/hw/sparc/sparc32_dma.h b/include/hw/sparc/sparc32_dma.h index df7491d..365160f 100644 --- a/include/hw/sparc/sparc32_dma.h +++ b/include/hw/sparc/sparc32_dma.h @@ -2,6 +2,7 @@ #define SPARC32_DMA_H #include "hw/sysbus.h" +#include "hw/scsi/esp.h" #define DMA_REGS 4 @@ -28,6 +29,8 @@ struct DMADeviceState { typedef struct ESPDMADeviceState { DMADeviceState parent_obj; + +SysBusESPState *esp; } ESPDMADeviceState; #define TYPE_SPARC32_LEDMA_DEVICE "sparc32-ledma" -- 1.7.10.4
[Qemu-devel] [PATCHv2 05/13] sun4m_iommu: move TYPE_SUN4M_IOMMU declaration to sun4m.h
This is in preparation to allow the type to be used elsewhere. Signed-off-by: Mark Cave-Ayland --- hw/dma/sun4m_iommu.c | 14 -- include/hw/sparc/sun4m.h | 16 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/hw/dma/sun4m_iommu.c b/hw/dma/sun4m_iommu.c index 335ef63..840064b 100644 --- a/hw/dma/sun4m_iommu.c +++ b/hw/dma/sun4m_iommu.c @@ -36,7 +36,6 @@ * http://mediacast.sun.com/users/Barton808/media/Sun4M_SystemArchitecture_edited2.pdf */ -#define IOMMU_NREGS (4*4096/4) #define IOMMU_CTRL (0x >> 2) #define IOMMU_CTRL_IMPL 0xf000 /* Implementation */ #define IOMMU_CTRL_VERS 0x0f00 /* Version */ @@ -128,19 +127,6 @@ #define IOMMU_PAGE_SIZE (1 << IOMMU_PAGE_SHIFT) #define IOMMU_PAGE_MASK ~(IOMMU_PAGE_SIZE - 1) -#define TYPE_SUN4M_IOMMU "iommu" -#define SUN4M_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4M_IOMMU) - -typedef struct IOMMUState { -SysBusDevice parent_obj; - -MemoryRegion iomem; -uint32_t regs[IOMMU_NREGS]; -hwaddr iostart; -qemu_irq irq; -uint32_t version; -} IOMMUState; - static uint64_t iommu_mem_read(void *opaque, hwaddr addr, unsigned size) { diff --git a/include/hw/sparc/sun4m.h b/include/hw/sparc/sun4m.h index 580d87b..1f1cf91 100644 --- a/include/hw/sparc/sun4m.h +++ b/include/hw/sparc/sun4m.h @@ -4,10 +4,26 @@ #include "qemu-common.h" #include "exec/hwaddr.h" #include "qapi/qmp/types.h" +#include "hw/sysbus.h" /* Devices used by sparc32 system. */ /* iommu.c */ +#define TYPE_SUN4M_IOMMU "iommu" +#define SUN4M_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4M_IOMMU) + +#define IOMMU_NREGS (4 * 4096 / 4) + +typedef struct IOMMUState { +SysBusDevice parent_obj; + +MemoryRegion iomem; +uint32_t regs[IOMMU_NREGS]; +hwaddr iostart; +qemu_irq irq; +uint32_t version; +} IOMMUState; + void sparc_iommu_memory_rw(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write); static inline void sparc_iommu_memory_read(void *opaque, -- 1.7.10.4
[Qemu-devel] [PATCHv2 13/13] sparc32_dma: add len to esp/le DMA memory tracing
This is surprisingly useful when trying to debug DMA issues. Signed-off-by: Mark Cave-Ayland --- hw/dma/sparc32_dma.c |8 hw/dma/trace-events |8 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index bb7d70a..fbb072a 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -73,7 +73,7 @@ void ledma_memory_read(void *opaque, hwaddr addr, int i; addr |= s->dmaregs[3]; -trace_ledma_memory_read(addr); +trace_ledma_memory_read(addr, len); if (do_bswap) { sparc_iommu_memory_read(s->iommu, addr, buf, len); } else { @@ -94,7 +94,7 @@ void ledma_memory_write(void *opaque, hwaddr addr, uint16_t tmp_buf[32]; addr |= s->dmaregs[3]; -trace_ledma_memory_write(addr); +trace_ledma_memory_write(addr, len); if (do_bswap) { sparc_iommu_memory_write(s->iommu, addr, buf, len); } else { @@ -139,7 +139,7 @@ void espdma_memory_read(void *opaque, uint8_t *buf, int len) { DMADeviceState *s = opaque; -trace_espdma_memory_read(s->dmaregs[1]); +trace_espdma_memory_read(s->dmaregs[1], len); sparc_iommu_memory_read(s->iommu, s->dmaregs[1], buf, len); s->dmaregs[1] += len; } @@ -148,7 +148,7 @@ void espdma_memory_write(void *opaque, uint8_t *buf, int len) { DMADeviceState *s = opaque; -trace_espdma_memory_write(s->dmaregs[1]); +trace_espdma_memory_write(s->dmaregs[1], len); sparc_iommu_memory_write(s->iommu, s->dmaregs[1], buf, len); s->dmaregs[1] += len; } diff --git a/hw/dma/trace-events b/hw/dma/trace-events index 428469a..6b367f0 100644 --- a/hw/dma/trace-events +++ b/hw/dma/trace-events @@ -7,12 +7,12 @@ rc4030_read(uint64_t addr, uint32_t ret) "read reg[0x%"PRIx64"] = 0x%x" rc4030_write(uint64_t addr, uint32_t val) "write reg[0x%"PRIx64"] = 0x%x" # hw/dma/sparc32_dma.c -ledma_memory_read(uint64_t addr) "DMA read addr 0x%"PRIx64 -ledma_memory_write(uint64_t addr) "DMA write addr 0x%"PRIx64 +ledma_memory_read(uint64_t addr, int len) "DMA read addr 0x%"PRIx64 " len %d" +ledma_memory_write(uint64_t addr, int len) "DMA write addr 0x%"PRIx64 " len %d" sparc32_dma_set_irq_raise(void) "Raise IRQ" sparc32_dma_set_irq_lower(void) "Lower IRQ" -espdma_memory_read(uint32_t addr) "DMA read addr 0x%08x" -espdma_memory_write(uint32_t addr) "DMA write addr 0x%08x" +espdma_memory_read(uint32_t addr, int len) "DMA read addr 0x%08x len %d" +espdma_memory_write(uint32_t addr, int len) "DMA write addr 0x%08x len %d" sparc32_dma_mem_readl(uint64_t addr, uint32_t ret) "read dmareg 0x%"PRIx64": 0x%08x" sparc32_dma_mem_writel(uint64_t addr, uint32_t old, uint32_t val) "write dmareg 0x%"PRIx64": 0x%08x -> 0x%08x" sparc32_dma_enable_raise(void) "Raise DMA enable" -- 1.7.10.4
[Qemu-devel] [PATCHv2 11/13] sparc32_dma: introduce new SPARC32_DMA type container object
Create a new SPARC32_DMA container object (including an appropriate container memory region) and add instances of the SPARC32_ESPDMA_DEVICE and SPARC32_LEDMA_DEVICE as child objects. The benefit is that most of the gpio wiring complexity between esp/espdma and lance/ledma is now hidden within the SPARC32_DMA realize function. Since the sun4m IOMMU is already QOMified we can find a reference to it using object_resolve_path_type() allowing us to completely remove all external references to the iommu pointer. Finally we rework sun4m's sparc32_dma_init() to invoke the new SPARC32_DMA object and wire up the remaining board memory regions/IRQs. Signed-off-by: Mark Cave-Ayland --- hw/dma/sparc32_dma.c | 70 hw/sparc/sun4m.c | 66 ++--- include/hw/sparc/sparc32_dma.h | 12 +++ 3 files changed, 114 insertions(+), 34 deletions(-) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index d507ca3..ba62927 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -29,6 +29,7 @@ #include "hw/hw.h" #include "hw/sparc/sparc32_dma.h" #include "hw/sysbus.h" +#include "qapi/error.h" #include "trace.h" /* @@ -368,11 +369,80 @@ static const TypeInfo sparc32_ledma_device_info = { .class_init= sparc32_ledma_device_class_init, }; +static void sparc32_dma_realize(DeviceState *dev, Error **errp) +{ +SPARC32DMAState *s = SPARC32_DMA(dev); +DeviceState *espdma, *esp, *ledma, *lance; +SysBusDevice *sbd; +Object *iommu; + +iommu = object_resolve_path_type("", TYPE_SUN4M_IOMMU, NULL); +if (!iommu) { +error_setg(errp, "unable to locate sun4m IOMMU device"); +return; +} + +espdma = qdev_create(NULL, TYPE_SPARC32_ESPDMA_DEVICE); +object_property_set_link(OBJECT(espdma), iommu, "iommu", errp); +object_property_add_child(OBJECT(s), "espdma", OBJECT(espdma), errp); +qdev_init_nofail(espdma); + +esp = DEVICE(object_resolve_path_component(OBJECT(espdma), "esp")); +sbd = SYS_BUS_DEVICE(esp); +sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(espdma, 0)); +qdev_connect_gpio_out(espdma, 0, qdev_get_gpio_in(esp, 0)); +qdev_connect_gpio_out(espdma, 1, qdev_get_gpio_in(esp, 1)); + +sbd = SYS_BUS_DEVICE(espdma); +memory_region_add_subregion(&s->dmamem, 0x0, +sysbus_mmio_get_region(sbd, 0)); + +ledma = qdev_create(NULL, TYPE_SPARC32_LEDMA_DEVICE); +object_property_set_link(OBJECT(ledma), iommu, "iommu", errp); +object_property_add_child(OBJECT(s), "ledma", OBJECT(ledma), errp); +qdev_init_nofail(ledma); + +lance = DEVICE(object_resolve_path_component(OBJECT(ledma), "lance")); +sbd = SYS_BUS_DEVICE(lance); +sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(ledma, 0)); +qdev_connect_gpio_out(ledma, 0, qdev_get_gpio_in(lance, 0)); + +sbd = SYS_BUS_DEVICE(ledma); +memory_region_add_subregion(&s->dmamem, 0x10, +sysbus_mmio_get_region(sbd, 0)); +} + +static void sparc32_dma_init(Object *obj) +{ +SPARC32DMAState *s = SPARC32_DMA(obj); +SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + +memory_region_init(&s->dmamem, OBJECT(s), "dma", DMA_SIZE + DMA_ETH_SIZE); +sysbus_init_mmio(sbd, &s->dmamem); +} + +static void sparc32_dma_class_init(ObjectClass *klass, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(klass); + +dc->realize = sparc32_dma_realize; +} + +static const TypeInfo sparc32_dma_info = { +.name = TYPE_SPARC32_DMA, +.parent= TYPE_SYS_BUS_DEVICE, +.instance_size = sizeof(SPARC32DMAState), +.instance_init = sparc32_dma_init, +.class_init= sparc32_dma_class_init, +}; + + static void sparc32_dma_register_types(void) { type_register_static(&sparc32_dma_device_info); type_register_static(&sparc32_espdma_device_info); type_register_static(&sparc32_ledma_device_info); +type_register_static(&sparc32_dma_info); } type_init(sparc32_dma_register_types) diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index ae486a4..5017ae5 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -307,18 +307,36 @@ static void *iommu_init(hwaddr addr, uint32_t version, qemu_irq irq) return s; } -static void *sparc32_dma_init(hwaddr daddr, void *iommu, int is_ledma) +static void *sparc32_dma_init(hwaddr dma_base, + hwaddr esp_base, qemu_irq espdma_irq, + hwaddr le_base, qemu_irq ledma_irq) { -DeviceState *dev; -SysBusDevice *s; +DeviceState *dma; +ESPDMADeviceState *espdma; +LEDMADeviceState *ledma; +SysBusESPState *esp; +SysBusPCNetState *lance; -dev = qdev_create(NULL, is_ledma ? "sparc32-ledma" : "sparc32-espdma"); -object_property_set_link(OBJECT(dev), OBJECT(iommu), "iommu", &error_abort); -qdev_init_nofail(dev); -s = SYS_BUS_DEVICE(dev); -sysbus_mmio_map(s, 0, da
[Qemu-devel] [PATCHv2 03/13] sparc32_dma: move type declarations from sparc32_dma.c to sparc32_dma.h
Signed-off-by: Mark Cave-Ayland --- hw/dma/sparc32_dma.c | 34 -- include/hw/sparc/sparc32_dma.h | 37 + 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index e4ff4a8..ae8fa06 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -40,7 +40,6 @@ * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/DMA2.txt */ -#define DMA_REGS 4 #define DMA_SIZE (4 * sizeof(uint32_t)) /* We need the mask, because one instance of the device is not page aligned (ledma, start address 0x0010) */ @@ -61,39 +60,6 @@ /* XXX SCSI and ethernet should have different read-only bit masks */ #define DMA_CSR_RO_MASK 0xfe07 -#define TYPE_SPARC32_DMA_DEVICE "sparc32-dma-device" -#define SPARC32_DMA_DEVICE(obj) OBJECT_CHECK(DMADeviceState, (obj), \ - TYPE_SPARC32_DMA_DEVICE) - -typedef struct DMADeviceState DMADeviceState; - -struct DMADeviceState { -SysBusDevice parent_obj; - -MemoryRegion iomem; -uint32_t dmaregs[DMA_REGS]; -qemu_irq irq; -void *iommu; -qemu_irq gpio[2]; -uint32_t is_ledma; -}; - -#define TYPE_SPARC32_ESPDMA_DEVICE "sparc32-espdma" -#define SPARC32_ESPDMA_DEVICE(obj) OBJECT_CHECK(ESPDMADeviceState, (obj), \ -TYPE_SPARC32_ESPDMA_DEVICE) - -typedef struct ESPDMADeviceState { -DMADeviceState parent_obj; -} ESPDMADeviceState; - -#define TYPE_SPARC32_LEDMA_DEVICE "sparc32-ledma" -#define SPARC32_LEDMA_DEVICE(obj) OBJECT_CHECK(LEDMADeviceState, (obj), \ - TYPE_SPARC32_LEDMA_DEVICE) - -typedef struct LEDMADeviceState { -DMADeviceState parent_obj; -} LEDMADeviceState; - enum { GPIO_RESET = 0, GPIO_DMA, diff --git a/include/hw/sparc/sparc32_dma.h b/include/hw/sparc/sparc32_dma.h index 9497b13..df7491d 100644 --- a/include/hw/sparc/sparc32_dma.h +++ b/include/hw/sparc/sparc32_dma.h @@ -1,6 +1,43 @@ #ifndef SPARC32_DMA_H #define SPARC32_DMA_H +#include "hw/sysbus.h" + +#define DMA_REGS 4 + +#define TYPE_SPARC32_DMA_DEVICE "sparc32-dma-device" +#define SPARC32_DMA_DEVICE(obj) OBJECT_CHECK(DMADeviceState, (obj), \ + TYPE_SPARC32_DMA_DEVICE) + +typedef struct DMADeviceState DMADeviceState; + +struct DMADeviceState { +SysBusDevice parent_obj; + +MemoryRegion iomem; +uint32_t dmaregs[DMA_REGS]; +qemu_irq irq; +void *iommu; +qemu_irq gpio[2]; +uint32_t is_ledma; +}; + +#define TYPE_SPARC32_ESPDMA_DEVICE "sparc32-espdma" +#define SPARC32_ESPDMA_DEVICE(obj) OBJECT_CHECK(ESPDMADeviceState, (obj), \ +TYPE_SPARC32_ESPDMA_DEVICE) + +typedef struct ESPDMADeviceState { +DMADeviceState parent_obj; +} ESPDMADeviceState; + +#define TYPE_SPARC32_LEDMA_DEVICE "sparc32-ledma" +#define SPARC32_LEDMA_DEVICE(obj) OBJECT_CHECK(LEDMADeviceState, (obj), \ + TYPE_SPARC32_LEDMA_DEVICE) + +typedef struct LEDMADeviceState { +DMADeviceState parent_obj; +} LEDMADeviceState; + /* sparc32_dma.c */ void ledma_memory_read(void *opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap); -- 1.7.10.4
[Qemu-devel] [PATCHv2 01/13] sparc32_dma: rename SPARC32_DMA type to SPARC32_DMA_DEVICE
Also update the function names to match as appropriate. While we're here rename the type from sparc32_dma to sparc32-dma in order to match the current QOM convention. Signed-off-by: Mark Cave-Ayland --- hw/dma/sparc32_dma.c | 67 +- hw/sparc/sun4m.c |2 +- 2 files changed, 35 insertions(+), 34 deletions(-) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index eb491b5..a8d31c1 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -61,12 +61,13 @@ /* XXX SCSI and ethernet should have different read-only bit masks */ #define DMA_CSR_RO_MASK 0xfe07 -#define TYPE_SPARC32_DMA "sparc32_dma" -#define SPARC32_DMA(obj) OBJECT_CHECK(DMAState, (obj), TYPE_SPARC32_DMA) +#define TYPE_SPARC32_DMA_DEVICE "sparc32-dma-device" +#define SPARC32_DMA_DEVICE(obj) OBJECT_CHECK(DMADeviceState, (obj), \ + TYPE_SPARC32_DMA_DEVICE) -typedef struct DMAState DMAState; +typedef struct DMADeviceState DMADeviceState; -struct DMAState { +struct DMADeviceState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -86,7 +87,7 @@ enum { void ledma_memory_read(void *opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap) { -DMAState *s = opaque; +DMADeviceState *s = opaque; int i; addr |= s->dmaregs[3]; @@ -106,7 +107,7 @@ void ledma_memory_read(void *opaque, hwaddr addr, void ledma_memory_write(void *opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap) { -DMAState *s = opaque; +DMADeviceState *s = opaque; int l, i; uint16_t tmp_buf[32]; @@ -134,7 +135,7 @@ void ledma_memory_write(void *opaque, hwaddr addr, static void dma_set_irq(void *opaque, int irq, int level) { -DMAState *s = opaque; +DMADeviceState *s = opaque; if (level) { s->dmaregs[0] |= DMA_INTR; if (s->dmaregs[0] & DMA_INTREN) { @@ -154,7 +155,7 @@ static void dma_set_irq(void *opaque, int irq, int level) void espdma_memory_read(void *opaque, uint8_t *buf, int len) { -DMAState *s = opaque; +DMADeviceState *s = opaque; trace_espdma_memory_read(s->dmaregs[1]); sparc_iommu_memory_read(s->iommu, s->dmaregs[1], buf, len); @@ -163,7 +164,7 @@ void espdma_memory_read(void *opaque, uint8_t *buf, int len) void espdma_memory_write(void *opaque, uint8_t *buf, int len) { -DMAState *s = opaque; +DMADeviceState *s = opaque; trace_espdma_memory_write(s->dmaregs[1]); sparc_iommu_memory_write(s->iommu, s->dmaregs[1], buf, len); @@ -173,7 +174,7 @@ void espdma_memory_write(void *opaque, uint8_t *buf, int len) static uint64_t dma_mem_read(void *opaque, hwaddr addr, unsigned size) { -DMAState *s = opaque; +DMADeviceState *s = opaque; uint32_t saddr; if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) { @@ -190,7 +191,7 @@ static uint64_t dma_mem_read(void *opaque, hwaddr addr, static void dma_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { -DMAState *s = opaque; +DMADeviceState *s = opaque; uint32_t saddr; if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) { @@ -252,28 +253,28 @@ static const MemoryRegionOps dma_mem_ops = { }, }; -static void dma_reset(DeviceState *d) +static void sparc32_dma_device_reset(DeviceState *d) { -DMAState *s = SPARC32_DMA(d); +DMADeviceState *s = SPARC32_DMA_DEVICE(d); memset(s->dmaregs, 0, DMA_SIZE); s->dmaregs[0] = DMA_VER; } -static const VMStateDescription vmstate_dma = { +static const VMStateDescription vmstate_sparc32_dma_device = { .name ="sparc32_dma", .version_id = 2, .minimum_version_id = 2, .fields = (VMStateField[]) { -VMSTATE_UINT32_ARRAY(dmaregs, DMAState, DMA_REGS), +VMSTATE_UINT32_ARRAY(dmaregs, DMADeviceState, DMA_REGS), VMSTATE_END_OF_LIST() } }; -static void sparc32_dma_init(Object *obj) +static void sparc32_dma_device_init(Object *obj) { DeviceState *dev = DEVICE(obj); -DMAState *s = SPARC32_DMA(obj); +DMADeviceState *s = SPARC32_DMA_DEVICE(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); sysbus_init_irq(sbd, &s->irq); @@ -284,9 +285,9 @@ static void sparc32_dma_init(Object *obj) qdev_init_gpio_out(dev, s->gpio, 2); } -static void sparc32_dma_realize(DeviceState *dev, Error **errp) +static void sparc32_dma_device_realize(DeviceState *dev, Error **errp) { -DMAState *s = SPARC32_DMA(dev); +DMADeviceState *s = SPARC32_DMA_DEVICE(dev); int reg_size; reg_size = s->is_ledma ? DMA_ETH_SIZE : DMA_SIZE; @@ -294,35 +295,35 @@ static void sparc32_dma_realize(DeviceState *dev, Error **errp) "dma", reg_size); } -static Property sparc32_dma_properties[] = { -DEFINE_PROP_PTR("iommu_opaque", DMAState, iommu), -DEFINE_PROP_UINT32("is_ledma", DMAState, is_ledma, 0
[Qemu-devel] [PATCHv2 07/13] esp: move TYPE_ESP and SysBusESPState from esp.c to esp.h
This enables them to be used outside of esp.c. Signed-off-by: Mark Cave-Ayland CC: Paolo Bonzini --- hw/scsi/esp.c | 13 - include/hw/scsi/esp.h | 13 + 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 22c2d91..ee586e7 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -592,19 +592,6 @@ const VMStateDescription vmstate_esp = { } }; -#define TYPE_ESP "esp" -#define ESP_STATE(obj) OBJECT_CHECK(SysBusESPState, (obj), TYPE_ESP) - -typedef struct { -/*< private >*/ -SysBusDevice parent_obj; -/*< public >*/ - -MemoryRegion iomem; -uint32_t it_shift; -ESPState esp; -} SysBusESPState; - static void sysbus_esp_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h index d2c4886..a79d3f2 100644 --- a/include/hw/scsi/esp.h +++ b/include/hw/scsi/esp.h @@ -52,6 +52,19 @@ struct ESPState { void (*dma_cb)(ESPState *s); }; +#define TYPE_ESP "esp" +#define ESP_STATE(obj) OBJECT_CHECK(SysBusESPState, (obj), TYPE_ESP) + +typedef struct { +/*< private >*/ +SysBusDevice parent_obj; +/*< public >*/ + +MemoryRegion iomem; +uint32_t it_shift; +ESPState esp; +} SysBusESPState; + #define ESP_TCLO 0x0 #define ESP_TCMID 0x1 #define ESP_FIFO 0x2 -- 1.7.10.4
[Qemu-devel] [PATCHv2 06/13] sparc32_dma: use object link instead of qdev property to pass IOMMU reference
This enables us to remove the last remaining (opaque) qdev property. Whilst we are here, also update iommu_init() to use TYPE_SUN4M_IOMMU instead of a hardcoded string. Signed-off-by: Mark Cave-Ayland --- hw/dma/sparc32_dma.c | 13 + hw/sparc/sun4m.c |4 ++-- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index ae8fa06..c56a2ba 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -263,24 +263,21 @@ static void sparc32_dma_device_init(Object *obj) sysbus_init_mmio(sbd, &s->iomem); +object_property_add_link(OBJECT(dev), "iommu", TYPE_SUN4M_IOMMU, + (Object **) &s->iommu, + qdev_prop_allow_set_link_before_realize, + 0, NULL); + qdev_init_gpio_in(dev, dma_set_irq, 1); qdev_init_gpio_out(dev, s->gpio, 2); } -static Property sparc32_dma_device_properties[] = { -DEFINE_PROP_PTR("iommu_opaque", DMADeviceState, iommu), -DEFINE_PROP_END_OF_LIST(), -}; - static void sparc32_dma_device_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->reset = sparc32_dma_device_reset; dc->vmsd = &vmstate_sparc32_dma_device; -dc->props = sparc32_dma_device_properties; -/* Reason: pointer property "iommu_opaque" */ -dc->user_creatable = false; } static const TypeInfo sparc32_dma_device_info = { diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 4f2ed4b..12d36b5 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -297,7 +297,7 @@ static void *iommu_init(hwaddr addr, uint32_t version, qemu_irq irq) DeviceState *dev; SysBusDevice *s; -dev = qdev_create(NULL, "iommu"); +dev = qdev_create(NULL, TYPE_SUN4M_IOMMU); qdev_prop_set_uint32(dev, "version", version); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); @@ -313,7 +313,7 @@ static void *sparc32_dma_init(hwaddr daddr, void *iommu, int is_ledma) SysBusDevice *s; dev = qdev_create(NULL, is_ledma ? "sparc32-ledma" : "sparc32-espdma"); -qdev_prop_set_ptr(dev, "iommu_opaque", iommu); +object_property_set_link(OBJECT(dev), OBJECT(iommu), "iommu", &error_abort); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); sysbus_mmio_map(s, 0, daddr); -- 1.7.10.4
[Qemu-devel] [PATCHv2 02/13] sparc32_dma: split esp and le into separate DMA devices
Due to slight differences in behaviour accessing the registers for the esp and le devices, create two separate SPARC32_DMA_DEVICE types and update the sun4m machine to use. Note that by using different device types we already know the size of the register block and the value of is_ledma at init time, allowing us to drop the SPARC32_DMA_DEVICE realize function and the is_ledma device property. Signed-off-by: Mark Cave-Ayland --- hw/dma/sparc32_dma.c | 63 -- hw/sparc/sun4m.c |3 +-- 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index a8d31c1..e4ff4a8 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -78,6 +78,22 @@ struct DMADeviceState { uint32_t is_ledma; }; +#define TYPE_SPARC32_ESPDMA_DEVICE "sparc32-espdma" +#define SPARC32_ESPDMA_DEVICE(obj) OBJECT_CHECK(ESPDMADeviceState, (obj), \ +TYPE_SPARC32_ESPDMA_DEVICE) + +typedef struct ESPDMADeviceState { +DMADeviceState parent_obj; +} ESPDMADeviceState; + +#define TYPE_SPARC32_LEDMA_DEVICE "sparc32-ledma" +#define SPARC32_LEDMA_DEVICE(obj) OBJECT_CHECK(LEDMADeviceState, (obj), \ + TYPE_SPARC32_LEDMA_DEVICE) + +typedef struct LEDMADeviceState { +DMADeviceState parent_obj; +} LEDMADeviceState; + enum { GPIO_RESET = 0, GPIO_DMA, @@ -285,19 +301,8 @@ static void sparc32_dma_device_init(Object *obj) qdev_init_gpio_out(dev, s->gpio, 2); } -static void sparc32_dma_device_realize(DeviceState *dev, Error **errp) -{ -DMADeviceState *s = SPARC32_DMA_DEVICE(dev); -int reg_size; - -reg_size = s->is_ledma ? DMA_ETH_SIZE : DMA_SIZE; -memory_region_init_io(&s->iomem, OBJECT(dev), &dma_mem_ops, s, - "dma", reg_size); -} - static Property sparc32_dma_device_properties[] = { DEFINE_PROP_PTR("iommu_opaque", DMADeviceState, iommu), -DEFINE_PROP_UINT32("is_ledma", DMADeviceState, is_ledma, 0), DEFINE_PROP_END_OF_LIST(), }; @@ -308,7 +313,6 @@ static void sparc32_dma_device_class_init(ObjectClass *klass, void *data) dc->reset = sparc32_dma_device_reset; dc->vmsd = &vmstate_sparc32_dma_device; dc->props = sparc32_dma_device_properties; -dc->realize = sparc32_dma_device_realize; /* Reason: pointer property "iommu_opaque" */ dc->user_creatable = false; } @@ -316,14 +320,49 @@ static void sparc32_dma_device_class_init(ObjectClass *klass, void *data) static const TypeInfo sparc32_dma_device_info = { .name = TYPE_SPARC32_DMA_DEVICE, .parent= TYPE_SYS_BUS_DEVICE, +.abstract = true, .instance_size = sizeof(DMADeviceState), .instance_init = sparc32_dma_device_init, .class_init= sparc32_dma_device_class_init, }; +static void sparc32_espdma_device_init(Object *obj) +{ +DMADeviceState *s = SPARC32_DMA_DEVICE(obj); + +memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s, + "espdma-mmio", DMA_SIZE); +s->is_ledma = 0; +} + +static const TypeInfo sparc32_espdma_device_info = { +.name = TYPE_SPARC32_ESPDMA_DEVICE, +.parent= TYPE_SPARC32_DMA_DEVICE, +.instance_size = sizeof(ESPDMADeviceState), +.instance_init = sparc32_espdma_device_init, +}; + +static void sparc32_ledma_device_init(Object *obj) +{ +DMADeviceState *s = SPARC32_DMA_DEVICE(obj); + +memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s, + "ledma-mmio", DMA_ETH_SIZE); +s->is_ledma = 1; +} + +static const TypeInfo sparc32_ledma_device_info = { +.name = TYPE_SPARC32_LEDMA_DEVICE, +.parent= TYPE_SPARC32_DMA_DEVICE, +.instance_size = sizeof(LEDMADeviceState), +.instance_init = sparc32_ledma_device_init, +}; + static void sparc32_dma_register_types(void) { type_register_static(&sparc32_dma_device_info); +type_register_static(&sparc32_espdma_device_info); +type_register_static(&sparc32_ledma_device_info); } type_init(sparc32_dma_register_types) diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 82c553c..88a9752 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -313,9 +313,8 @@ static void *sparc32_dma_init(hwaddr daddr, qemu_irq parent_irq, DeviceState *dev; SysBusDevice *s; -dev = qdev_create(NULL, "sparc32-dma-device"); +dev = qdev_create(NULL, is_ledma ? "sparc32-ledma" : "sparc32-espdma"); qdev_prop_set_ptr(dev, "iommu_opaque", iommu); -qdev_prop_set_uint32(dev, "is_ledma", is_ledma); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); sysbus_connect_irq(s, 0, parent_irq); -- 1.7.10.4
[Qemu-devel] [PATCHv2 00/13] sun4m: sparc32_dma tidy-ups
This patchset aims to tidy-up the sparc32_dma code by improving the modelling of the espdma/ledma devices using both QOM and the memory API which didn't exist when the code was first written. The result is that it is now possible to remove both the iommu_opaque and is_ledma workarounds from the code, and the code for wiring up the espdma/ledma and respective devices is also a lot more readable. Signed-off-by: Mark Cave-Ayland v2: - Make esp/lance devices children of espdma/ledma devices respectively - Add len parameter to ledma/espdma tracepoints Mark Cave-Ayland (13): sparc32_dma: rename SPARC32_DMA type to SPARC32_DMA_DEVICE sparc32_dma: split esp and le into separate DMA devices sparc32_dma: move type declarations from sparc32_dma.c to sparc32_dma.h sun4m: move DMA device wiring from sparc32_dma_init() to sun4m_hw_init() sun4m_iommu: move TYPE_SUN4M_IOMMU declaration to sun4m.h sparc32_dma: use object link instead of qdev property to pass IOMMU reference esp: move TYPE_ESP and SysBusESPState from esp.c to esp.h sparc32_dma: make esp device child of espdma device lance: move TYPE_LANCE and SysBusPCNetState from lance.c to sun4m.h sparc32_dma: make lance device child of ledma device sparc32_dma: introduce new SPARC32_DMA type container object sparc32_dma: remove is_ledma hack and replace with memory region alias sparc32_dma: add len to esp/le DMA memory tracing hw/dma/sparc32_dma.c | 236 +--- hw/dma/sun4m_iommu.c | 14 --- hw/dma/trace-events|8 +- hw/net/lance.c |9 -- hw/scsi/esp.c | 13 --- hw/sparc/sun4m.c | 82 ++ include/hw/scsi/esp.h | 13 +++ include/hw/sparc/sparc32_dma.h | 55 ++ include/hw/sparc/sun4m.h | 29 + 9 files changed, 306 insertions(+), 153 deletions(-) -- 1.7.10.4
[Qemu-devel] [PATCHv2 04/13] sun4m: move DMA device wiring from sparc32_dma_init() to sun4m_hw_init()
By using the sysbus interface it is possible to wire up the esp/le devices to the sun4m DMA controller directly during sun4m_hw_init() instead of passing qemu_irqs into the sparc32_dma_init() function. This is an intermediate step to allow further reorganisation as more logic is moved into the relevant SPARC32 DMA devices; there will be a final refactoring of sparc32_dma_init() once this work is complete. Signed-off-by: Mark Cave-Ayland --- hw/sparc/sun4m.c | 29 - 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 88a9752..4f2ed4b 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -307,8 +307,7 @@ static void *iommu_init(hwaddr addr, uint32_t version, qemu_irq irq) return s; } -static void *sparc32_dma_init(hwaddr daddr, qemu_irq parent_irq, - void *iommu, qemu_irq *dev_irq, int is_ledma) +static void *sparc32_dma_init(hwaddr daddr, void *iommu, int is_ledma) { DeviceState *dev; SysBusDevice *s; @@ -317,8 +316,6 @@ static void *sparc32_dma_init(hwaddr daddr, qemu_irq parent_irq, qdev_prop_set_ptr(dev, "iommu_opaque", iommu); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); -sysbus_connect_irq(s, 0, parent_irq); -*dev_irq = qdev_get_gpio_in(dev, 0); sysbus_mmio_map(s, 0, daddr); return s; @@ -821,9 +818,10 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, DeviceState *slavio_intctl; const char *cpu_model = machine->cpu_model; unsigned int i; -void *iommu, *espdma, *ledma, *nvram; -qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS], -espdma_irq, ledma_irq; +void *iommu, *nvram; +DeviceState *espdma, *ledma; +SysBusDevice *sbd; +qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS]; qemu_irq esp_reset, dma_enable; qemu_irq fdc_tc; unsigned long kernel_size; @@ -882,11 +880,13 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, empty_slot_init(hwdef->iommu_pad_base,hwdef->iommu_pad_len); } -espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[18], - iommu, &espdma_irq, 0); +espdma = sparc32_dma_init(hwdef->dma_base, iommu, 0); +sbd = SYS_BUS_DEVICE(espdma); +sysbus_connect_irq(sbd, 0, slavio_irq[18]); -ledma = sparc32_dma_init(hwdef->dma_base + 16ULL, - slavio_irq[16], iommu, &ledma_irq, 1); +ledma = sparc32_dma_init(hwdef->dma_base + 16ULL, iommu, 1); +sbd = SYS_BUS_DEVICE(ledma); +sysbus_connect_irq(sbd, 0, slavio_irq[16]); if (graphic_depth != 8 && graphic_depth != 24) { error_report("Unsupported depth: %d", graphic_depth); @@ -939,7 +939,8 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, empty_slot_init(hwdef->sx_base, 0x2000); } -lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq); +lance_init(&nd_table[0], hwdef->le_base, ledma, + qdev_get_gpio_in(ledma, 0)); nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x2000, 1968, 8); @@ -971,7 +972,9 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, esp_init(hwdef->esp_base, 2, espdma_memory_read, espdma_memory_write, - espdma, espdma_irq, &esp_reset, &dma_enable); + espdma, + qdev_get_gpio_in(espdma, 0), + &esp_reset, &dma_enable); qdev_connect_gpio_out(espdma, 0, esp_reset); qdev_connect_gpio_out(espdma, 1, dma_enable); -- 1.7.10.4
Re: [Qemu-devel] [PATCH 0/8] sun4m : sparc32_dma tidy-ups
On 10/10/17 09:21, Artyom Tarasenko wrote: > On Mon, Oct 9, 2017 at 11:06 PM, Mark Cave-Ayland > wrote: >> This patchset aims to tidy-up the sparc32_dma code by improving the >> modelling of the espdma/ledma devices using both QOM and the memory >> API which didn't exist when the code was first written. >> >> The result is that it is now possible to remove both the iommu_opaque >> and is_ledma workarounds from the code. >> >> Signed-off-by: Mark Cave-Ayland > > Reviewed-by: Artyom Tarasenko With some further experimentation I've found that making the esp/le devices children of their respective espdma/ledma devices makes things a lot cleaner. I've also got another related patch to update the espdma/ledma tracepoints to log the DMA transaction length, so I'll submit a v2 of this with the additional changes shortly. ATB, Mark.
Re: [Qemu-devel] QEMU without X11 support
On 14 October 2017 at 17:38, Philippe Mathieu-Daudé wrote: >>> Hello, is it possible to run (or rebuild modifying build flags) QEMU >>> without support for X11 window system integration? >> >> ./configure --disable-gtk --disable-sdl --disable-opengl > > Is there some interest in adding a simpler --disable-x11 option? We don't directly link to X11, so it wouldn't fit with our other options. The --disable-foo options aren't very often necessary -- only if your build environment has support for linking against foo but for some reason you don't want it linked in. thanks -- PMM
Re: [Qemu-devel] [PATCH] tco: add trace events
Hi Paolo, On 10/12/2017 10:54 AM, Paolo Bonzini wrote: > Add trace events to the PCH watchdog timer, it can be useful to see how > the guest is using it. > > Signed-off-by: Paolo Bonzini > --- > hw/acpi/tco.c| 11 +-- > hw/acpi/trace-events | 4 > 2 files changed, 13 insertions(+), 2 deletions(-) > > diff --git a/hw/acpi/tco.c b/hw/acpi/tco.c > index 05b9d7b..0032db4 100644 > --- a/hw/acpi/tco.c > +++ b/hw/acpi/tco.c > @@ -12,6 +12,7 @@ > #include "hw/i386/ich9.h" > > #include "hw/acpi/tco.h" > +#include "trace.h" > > //#define DEBUG > > @@ -41,8 +42,11 @@ enum { > > static inline void tco_timer_reload(TCOIORegs *tr) > { > -tr->expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + > -((int64_t)(tr->tco.tmr & TCO_TMR_MASK) * TCO_TICK_NSEC); > +int ticks = tr->tco.tmr & TCO_TMR_MASK; > +int64_t nsec = (int64_t)ticks * TCO_TICK_NSEC; > + > +trace_tco_timer_reload(ticks, nsec / 100); I'd use SCALE_MS here. > +tr->expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + nsec; > timer_mod(tr->tco_timer, tr->expire_time); > } > > @@ -59,6 +63,9 @@ static void tco_timer_expired(void *opaque) > ICH9LPCState *lpc = container_of(pm, ICH9LPCState, pm); > uint32_t gcs = pci_get_long(lpc->chip_config + ICH9_CC_GCS); > > +trace_tco_timer_expired(tr->timeouts_no, > + lpc->pin_strap.spkr_hi, > + !!(gcs & ICH9_CC_GCS_NO_REBOOT)); > tr->tco.rld = 0; > tr->tco.sts1 |= TCO_TIMEOUT; > if (++tr->timeouts_no == 2) { > diff --git a/hw/acpi/trace-events b/hw/acpi/trace-events > index e3b41e9..df0024f 100644 > --- a/hw/acpi/trace-events > +++ b/hw/acpi/trace-events > @@ -30,3 +30,7 @@ cpuhp_acpi_ejecting_invalid_cpu(uint32_t idx) "0x%"PRIx32 > cpuhp_acpi_ejecting_cpu(uint32_t idx) "0x%"PRIx32 > cpuhp_acpi_write_ost_ev(uint32_t slot, uint32_t ev) "idx[0x%"PRIx32"] OST > EVENT: 0x%"PRIx32 > cpuhp_acpi_write_ost_status(uint32_t slot, uint32_t st) "idx[0x%"PRIx32"] > OST STATUS: 0x%"PRIx32 > + > +# hw/acpi/tco.c > +tco_timer_reload(int ticks, int msec) "ticks=%d (%d ms)" > +tco_timer_expired(int timeouts_no, bool strap, bool no_reboot) > "timeouts_no=%d no_reboot=%d/%d" Changing tabs by spaces to satisfy checkpatch: Reviewed-by: Philippe Mathieu-Daudé
Re: [Qemu-devel] [PATCH v2] oslib-posix: Fix compiler warning and some data types
Hi Stefan, On 10/13/2017 02:48 AM, Stefan Weil wrote: > diff --git a/util/oslib-posix.c b/util/oslib-posix.c > index 80086c549f..beef148c96 100644 > --- a/util/oslib-posix.c > +++ b/util/oslib-posix.c > @@ -59,8 +59,8 @@ > > struct MemsetThread { > char *addr; > -uint64_t numpages; > -uint64_t hpagesize; > +size_t numpages; > +size_t hpagesize; > QemuThread pgthread; > sigjmp_buf env; > }; > @@ -301,11 +301,7 @@ static void sigbus_handler(int signal) > static void *do_touch_pages(void *arg) > { > MemsetThread *memset_args = (MemsetThread *)arg; > -char *addr = memset_args->addr; > -uint64_t numpages = memset_args->numpages; > -uint64_t hpagesize = memset_args->hpagesize; > sigset_t set, oldset; > -int i = 0; > > /* unblock SIGBUS */ > sigemptyset(&set); > @@ -315,6 +311,10 @@ static void *do_touch_pages(void *arg) > if (sigsetjmp(memset_args->env, 1)) { > memset_thread_failed = true; > } else { > +volatile char *addr = memset_args->addr; > +size_t numpages = memset_args->numpages; > +size_t hpagesize = memset_args->hpagesize; > +size_t i; > for (i = 0; i < numpages; i++) { > /* > * Read & write back the same value, so we don't > @@ -328,7 +328,7 @@ static void *do_touch_pages(void *arg) > * don't need to write at all so we don't cause > * wear on the storage backing the region... > */ > -*(volatile char *)addr = *addr; > +*addr = *addr; I personally prefer the other form which is mostly self-explicit when reviewing this code. Declaring addr non volatile and using volatile cast here: Reviewed-by: Philippe Mathieu-Daudé > addr += hpagesize; > } > } > @@ -351,7 +351,8 @@ static inline int get_memset_num_threads(int smp_cpus) > static bool touch_all_pages(char *area, size_t hpagesize, size_t numpages, > int smp_cpus) > { > -uint64_t numpages_per_thread, size_per_thread; > +size_t numpages_per_thread; > +size_t size_per_thread; > char *addr = area; > int i = 0; > >
Re: [Qemu-devel] QEMU without X11 support
>> Hello, is it possible to run (or rebuild modifying build flags) QEMU >> without support for X11 window system integration? > > ./configure --disable-gtk --disable-sdl --disable-opengl Is there some interest in adding a simpler --disable-x11 option?
Re: [Qemu-devel] [PATCH] futex: add missing header guards
Cc: trivial On 10/13/2017 06:30 PM, Emilio G. Cota wrote: > The header file was introduced by fbcc3e5 ("qemu-thread: optimize QemuLockCnt > with futexes on Linux", 2017-01-16) without header guards. Add them. > > Signed-off-by: Emilio G. Cota Reviewed-by: Philippe Mathieu-Daudé > --- > include/qemu/futex.h | 5 + > 1 file changed, 5 insertions(+) > > diff --git a/include/qemu/futex.h b/include/qemu/futex.h > index bb7dc9e..91ae889 100644 > --- a/include/qemu/futex.h > +++ b/include/qemu/futex.h > @@ -11,6 +11,9 @@ > * > */ > > +#ifndef QEMU_FUTEX_H > +#define QEMU_FUTEX_H > + > #include > #include > > @@ -34,3 +37,5 @@ static inline void qemu_futex_wait(void *f, unsigned val) > } > } > } > + > +#endif /* QEMU_FUTEX_H */ >
Re: [Qemu-devel] [PATCH 2/4] multiboot: load any machine type of ELF
On 14 October 2017 at 00:21, Eduardo Habkost wrote: > I don't believe the spec restricts that, but I don't see why it > would be useful to load an ELF file that doesn't match the target > architecture (e.g. loading non-x86 ELF files on a x86 machine > like PC). Agreed. If we have non i386 boards that want to use multiboot we should probably move the common code out of hw/i386... thanks -- PMM