qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

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 <mark.cave-ayland@ilande.co.uk>
Reviewed-by: Artyom Tarasenko <atar4qemu@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

+7 -15
+6 -14
hw/dma/sparc32_dma.c
··· 160 160 DMADeviceState *s = opaque; 161 161 uint32_t saddr; 162 162 163 - if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) { 164 - /* aliased to espdma, but we can't get there from here */ 165 - /* buggy driver if using undocumented behavior, just return 0 */ 166 - trace_sparc32_dma_mem_readl(addr, 0); 167 - return 0; 168 - } 169 163 saddr = (addr & DMA_MASK) >> 2; 170 164 trace_sparc32_dma_mem_readl(addr, s->dmaregs[saddr]); 171 165 return s->dmaregs[saddr]; ··· 177 171 DMADeviceState *s = opaque; 178 172 uint32_t saddr; 179 173 180 - if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) { 181 - /* aliased to espdma, but we can't get there from here */ 182 - trace_sparc32_dma_mem_writel(addr, 0, val); 183 - return; 184 - } 185 174 saddr = (addr & DMA_MASK) >> 2; 186 175 trace_sparc32_dma_mem_writel(addr, s->dmaregs[saddr], val); 187 176 switch (saddr) { ··· 296 285 297 286 memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s, 298 287 "espdma-mmio", DMA_SIZE); 299 - s->is_ledma = 0; 300 288 } 301 289 302 290 static void sparc32_espdma_device_realize(DeviceState *dev, Error **errp) ··· 337 325 DMADeviceState *s = SPARC32_DMA_DEVICE(obj); 338 326 339 327 memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s, 340 - "ledma-mmio", DMA_ETH_SIZE); 341 - s->is_ledma = 1; 328 + "ledma-mmio", DMA_SIZE); 342 329 } 343 330 344 331 static void sparc32_ledma_device_realize(DeviceState *dev, Error **errp) ··· 411 398 sbd = SYS_BUS_DEVICE(ledma); 412 399 memory_region_add_subregion(&s->dmamem, 0x10, 413 400 sysbus_mmio_get_region(sbd, 0)); 401 + 402 + /* Add ledma alias to handle SunOS 5.7 - Solaris 9 invalid access bug */ 403 + memory_region_init_alias(&s->ledma_alias, OBJECT(dev), "ledma-alias", 404 + sysbus_mmio_get_region(sbd, 0), 0x4, 0x4); 405 + memory_region_add_subregion(&s->dmamem, 0x20, &s->ledma_alias); 414 406 } 415 407 416 408 static void sparc32_dma_init(Object *obj)
+1 -1
include/hw/sparc/sparc32_dma.h
··· 21 21 qemu_irq irq; 22 22 void *iommu; 23 23 qemu_irq gpio[2]; 24 - uint32_t is_ledma; 25 24 }; 26 25 27 26 #define TYPE_SPARC32_ESPDMA_DEVICE "sparc32-espdma" ··· 52 51 SysBusDevice parent_obj; 53 52 54 53 MemoryRegion dmamem; 54 + MemoryRegion ledma_alias; 55 55 ESPDMADeviceState *espdma; 56 56 LEDMADeviceState *ledma; 57 57 } SPARC32DMAState;