Re: [Qemu-devel] Re: [PATCH] sparc32: ledma extra registers
On Mon, Dec 20, 2010 at 6:33 PM, Bob Breuer breu...@mc.net wrote: Artyom Tarasenko wrote: On Sun, Dec 19, 2010 at 8:37 PM, Bob Breuer breu...@mc.net wrote: Andreas Färber wrote: Am 18.12.2010 um 19:53 schrieb Blue Swirl: On Sat, Dec 18, 2010 at 5:09 PM, Bob Breuer breu...@mc.net wrote: ledma has 0x20 bytes of registers according to OBP, and at least Solaris9 reads the 5th register which is beyond what we've mapped. So let's setup a flag (inspired by a previous patch from Blue Swirl) to identify ledma from espdma, and map another 16 bytes of registers which return 0. Signed-off-by: Bob Breuer breu...@mc.net I'm not familar with that part of code but... diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c index e78f025..56be8c8 100644 --- a/hw/sparc32_dma.c +++ b/hw/sparc32_dma.c @@ -165,6 +169,9 @@ static uint32_t dma_mem_readl(void *opaque, target_phys_addr_t addr) DMAState *s = opaque; uint32_t saddr; + if (s-is_ledma (addr DMA_MAX_REG_OFFSET)) { + return 0; /* extra mystery register(s) */ Wouldn't it be a good idea to trace these mystery reads... + } saddr = (addr DMA_MASK) 2; trace_sparc32_dma_mem_readl(addr, s-dmaregs[saddr]); return s-dmaregs[saddr]; @@ -175,6 +182,9 @@ static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) DMAState *s = opaque; uint32_t saddr; + if (s-is_ledma (addr DMA_MAX_REG_OFFSET)) { + return; /* extra mystery register(s) */ ...and writes? We return just before the tracepoints fire. Ok, I'll put together a patch to add the trace calls just before the returns. How about I also call it undocumented instead of mystery. None of the BSD's or Linux know about or use anything beyond the 4 registers. I'd use aliased instead of mystery. On a real SS-5: ok 78400020 20 spacel@ . a4240050 ok 7840 20 spacel@ . a4240050 ok 78400024 20 spacel@ . fc004000 ok 7844 20 spacel@ . fc004000 Verified that it also aliases on an SS-20. Addresses 0x7840002x are aliases for 0x784x. As well as 0x7840004x. And so on up to ok 787fffe4 20 spacel@ . fc004000 7884 20 spacel@ . 0 Or a real SS-20 ef040 is aliased up to ef37fffe0 Fwiw I think it's a bug in the later Solaris versions: http://tyom.blogspot.com/2010/10/bug-in-all-solaris-versions-after-57.html On the bare metal it works because of address aliasing. If you want to emulate the hw precisely, the Blue's generic aliasing patch can be used here. The question is though do we want to do a generic aliasing for all the SBUS devices, or just in the single case(es) where we know is necessary. On the other hand Solaris seems to be fine with a 0 stub too. I'll send a patch to update the comments. If it's accessing a wrong register because of a bug, then it may not matter what value is returned. I think the value is important, but the tests show that 0 is fine. -- Regards, Artyom Tarasenko solaris/sparc under qemu blog: http://tyom.blogspot.com/
Re: [Qemu-devel] Re: [PATCH] sparc32: ledma extra registers
On Sun, Dec 19, 2010 at 8:37 PM, Bob Breuer breu...@mc.net wrote: Andreas Färber wrote: Am 18.12.2010 um 19:53 schrieb Blue Swirl: On Sat, Dec 18, 2010 at 5:09 PM, Bob Breuer breu...@mc.net wrote: ledma has 0x20 bytes of registers according to OBP, and at least Solaris9 reads the 5th register which is beyond what we've mapped. So let's setup a flag (inspired by a previous patch from Blue Swirl) to identify ledma from espdma, and map another 16 bytes of registers which return 0. Signed-off-by: Bob Breuer breu...@mc.net I'm not familar with that part of code but... diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c index e78f025..56be8c8 100644 --- a/hw/sparc32_dma.c +++ b/hw/sparc32_dma.c @@ -165,6 +169,9 @@ static uint32_t dma_mem_readl(void *opaque, target_phys_addr_t addr) DMAState *s = opaque; uint32_t saddr; + if (s-is_ledma (addr DMA_MAX_REG_OFFSET)) { + return 0; /* extra mystery register(s) */ Wouldn't it be a good idea to trace these mystery reads... + } saddr = (addr DMA_MASK) 2; trace_sparc32_dma_mem_readl(addr, s-dmaregs[saddr]); return s-dmaregs[saddr]; @@ -175,6 +182,9 @@ static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) DMAState *s = opaque; uint32_t saddr; + if (s-is_ledma (addr DMA_MAX_REG_OFFSET)) { + return; /* extra mystery register(s) */ ...and writes? We return just before the tracepoints fire. Ok, I'll put together a patch to add the trace calls just before the returns. How about I also call it undocumented instead of mystery. None of the BSD's or Linux know about or use anything beyond the 4 registers. I'd use aliased instead of mystery. On a real SS-5: ok 78400020 20 spacel@ . a4240050 ok 7840 20 spacel@ . a4240050 ok 78400024 20 spacel@ . fc004000 ok 7844 20 spacel@ . fc004000 Addresses 0x7840002x are aliases for 0x784x. As well as 0x7840004x. And so on up to ok 787fffe4 20 spacel@ . fc004000 7884 20 spacel@ . 0 Or a real SS-20 ef040 is aliased up to ef37fffe0 Fwiw I think it's a bug in the later Solaris versions: http://tyom.blogspot.com/2010/10/bug-in-all-solaris-versions-after-57.html On the bare metal it works because of address aliasing. If you want to emulate the hw precisely, the Blue's generic aliasing patch can be used here. The question is though do we want to do a generic aliasing for all the SBUS devices, or just in the single case(es) where we know is necessary. On the other hand Solaris seems to be fine with a 0 stub too. -- Regards, Artyom Tarasenko solaris/sparc under qemu blog: http://tyom.blogspot.com/
Re: [Qemu-devel] Re: [PATCH] sparc32: ledma extra registers
Artyom Tarasenko wrote: On Sun, Dec 19, 2010 at 8:37 PM, Bob Breuer breu...@mc.net wrote: Andreas Färber wrote: Am 18.12.2010 um 19:53 schrieb Blue Swirl: On Sat, Dec 18, 2010 at 5:09 PM, Bob Breuer breu...@mc.net wrote: ledma has 0x20 bytes of registers according to OBP, and at least Solaris9 reads the 5th register which is beyond what we've mapped. So let's setup a flag (inspired by a previous patch from Blue Swirl) to identify ledma from espdma, and map another 16 bytes of registers which return 0. Signed-off-by: Bob Breuer breu...@mc.net I'm not familar with that part of code but... diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c index e78f025..56be8c8 100644 --- a/hw/sparc32_dma.c +++ b/hw/sparc32_dma.c @@ -165,6 +169,9 @@ static uint32_t dma_mem_readl(void *opaque, target_phys_addr_t addr) DMAState *s = opaque; uint32_t saddr; +if (s-is_ledma (addr DMA_MAX_REG_OFFSET)) { +return 0; /* extra mystery register(s) */ Wouldn't it be a good idea to trace these mystery reads... +} saddr = (addr DMA_MASK) 2; trace_sparc32_dma_mem_readl(addr, s-dmaregs[saddr]); return s-dmaregs[saddr]; @@ -175,6 +182,9 @@ static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) DMAState *s = opaque; uint32_t saddr; +if (s-is_ledma (addr DMA_MAX_REG_OFFSET)) { +return; /* extra mystery register(s) */ ...and writes? We return just before the tracepoints fire. Ok, I'll put together a patch to add the trace calls just before the returns. How about I also call it undocumented instead of mystery. None of the BSD's or Linux know about or use anything beyond the 4 registers. I'd use aliased instead of mystery. On a real SS-5: ok 78400020 20 spacel@ . a4240050 ok 7840 20 spacel@ . a4240050 ok 78400024 20 spacel@ . fc004000 ok 7844 20 spacel@ . fc004000 Verified that it also aliases on an SS-20. Addresses 0x7840002x are aliases for 0x784x. As well as 0x7840004x. And so on up to ok 787fffe4 20 spacel@ . fc004000 7884 20 spacel@ . 0 Or a real SS-20 ef040 is aliased up to ef37fffe0 Fwiw I think it's a bug in the later Solaris versions: http://tyom.blogspot.com/2010/10/bug-in-all-solaris-versions-after-57.html On the bare metal it works because of address aliasing. If you want to emulate the hw precisely, the Blue's generic aliasing patch can be used here. The question is though do we want to do a generic aliasing for all the SBUS devices, or just in the single case(es) where we know is necessary. On the other hand Solaris seems to be fine with a 0 stub too. I'll send a patch to update the comments. If it's accessing a wrong register because of a bug, then it may not matter what value is returned. Bob
Re: [Qemu-devel] Re: [PATCH] sparc32: ledma extra registers
Andreas Färber wrote: Am 18.12.2010 um 19:53 schrieb Blue Swirl: On Sat, Dec 18, 2010 at 5:09 PM, Bob Breuer breu...@mc.net wrote: ledma has 0x20 bytes of registers according to OBP, and at least Solaris9 reads the 5th register which is beyond what we've mapped. So let's setup a flag (inspired by a previous patch from Blue Swirl) to identify ledma from espdma, and map another 16 bytes of registers which return 0. Signed-off-by: Bob Breuer breu...@mc.net I'm not familar with that part of code but... diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c index e78f025..56be8c8 100644 --- a/hw/sparc32_dma.c +++ b/hw/sparc32_dma.c @@ -165,6 +169,9 @@ static uint32_t dma_mem_readl(void *opaque, target_phys_addr_t addr) DMAState *s = opaque; uint32_t saddr; +if (s-is_ledma (addr DMA_MAX_REG_OFFSET)) { +return 0; /* extra mystery register(s) */ Wouldn't it be a good idea to trace these mystery reads... +} saddr = (addr DMA_MASK) 2; trace_sparc32_dma_mem_readl(addr, s-dmaregs[saddr]); return s-dmaregs[saddr]; @@ -175,6 +182,9 @@ static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) DMAState *s = opaque; uint32_t saddr; +if (s-is_ledma (addr DMA_MAX_REG_OFFSET)) { +return; /* extra mystery register(s) */ ...and writes? We return just before the tracepoints fire. Ok, I'll put together a patch to add the trace calls just before the returns. How about I also call it undocumented instead of mystery. None of the BSD's or Linux know about or use anything beyond the 4 registers. Blue, do you know of a mirror for the documents at http://wikis.sun.com/display/FOSSdocs/Home ? The pdfs there seem to have gone missing, and maybe there might be something in the macio documentation. Bob
[Qemu-devel] Re: [PATCH] sparc32: ledma extra registers
Thanks, applied. On Sat, Dec 18, 2010 at 5:09 PM, Bob Breuer breu...@mc.net wrote: ledma has 0x20 bytes of registers according to OBP, and at least Solaris9 reads the 5th register which is beyond what we've mapped. So let's setup a flag (inspired by a previous patch from Blue Swirl) to identify ledma from espdma, and map another 16 bytes of registers which return 0. Signed-off-by: Bob Breuer breu...@mc.net --- hw/sparc32_dma.c | 15 ++- hw/sun4m.c | 16 +--- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c index e78f025..56be8c8 100644 --- a/hw/sparc32_dma.c +++ b/hw/sparc32_dma.c @@ -44,6 +44,9 @@ /* We need the mask, because one instance of the device is not page aligned (ledma, start address 0x0010) */ #define DMA_MASK (DMA_SIZE - 1) +/* ledma has more than 4 registers, Solaris reads the 5th one */ +#define DMA_ETH_SIZE (8 * sizeof(uint32_t)) +#define DMA_MAX_REG_OFFSET (2 * DMA_SIZE - 1) #define DMA_VER 0xa000 #define DMA_INTR 1 @@ -65,6 +68,7 @@ struct DMAState { qemu_irq irq; void *iommu; qemu_irq gpio[2]; + uint32_t is_ledma; }; enum { @@ -165,6 +169,9 @@ static uint32_t dma_mem_readl(void *opaque, target_phys_addr_t addr) DMAState *s = opaque; uint32_t saddr; + if (s-is_ledma (addr DMA_MAX_REG_OFFSET)) { + return 0; /* extra mystery register(s) */ + } saddr = (addr DMA_MASK) 2; trace_sparc32_dma_mem_readl(addr, s-dmaregs[saddr]); return s-dmaregs[saddr]; @@ -175,6 +182,9 @@ static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) DMAState *s = opaque; uint32_t saddr; + if (s-is_ledma (addr DMA_MAX_REG_OFFSET)) { + return; /* extra mystery register(s) */ + } saddr = (addr DMA_MASK) 2; trace_sparc32_dma_mem_writel(addr, s-dmaregs[saddr], val); switch (saddr) { @@ -254,12 +264,14 @@ static int sparc32_dma_init1(SysBusDevice *dev) { DMAState *s = FROM_SYSBUS(DMAState, dev); int dma_io_memory; + int reg_size; sysbus_init_irq(dev, s-irq); dma_io_memory = cpu_register_io_memory(dma_mem_read, dma_mem_write, s, DEVICE_NATIVE_ENDIAN); - sysbus_init_mmio(dev, DMA_SIZE, dma_io_memory); + reg_size = s-is_ledma ? DMA_ETH_SIZE : DMA_SIZE; + sysbus_init_mmio(dev, reg_size, dma_io_memory); qdev_init_gpio_in(dev-qdev, dma_set_irq, 1); qdev_init_gpio_out(dev-qdev, s-gpio, 2); @@ -275,6 +287,7 @@ static SysBusDeviceInfo sparc32_dma_info = { .qdev.reset = dma_reset, .qdev.props = (Property[]) { DEFINE_PROP_PTR(iommu_opaque, DMAState, iommu), + DEFINE_PROP_UINT32(is_ledma, DMAState, is_ledma, 0), DEFINE_PROP_END_OF_LIST(), } }; diff --git a/hw/sun4m.c b/hw/sun4m.c index 4795b3f..30e8a21 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -378,13 +378,14 @@ static void *iommu_init(target_phys_addr_t addr, uint32_t version, qemu_irq irq) } static void *sparc32_dma_init(target_phys_addr_t daddr, qemu_irq parent_irq, - void *iommu, qemu_irq *dev_irq) + void *iommu, qemu_irq *dev_irq, int is_ledma) { DeviceState *dev; SysBusDevice *s; dev = qdev_create(NULL, sparc32_dma); qdev_prop_set_ptr(dev, iommu_opaque, iommu); + qdev_prop_set_uint32(dev, is_ledma, is_ledma); qdev_init_nofail(dev); s = sysbus_from_qdev(dev); sysbus_connect_irq(s, 0, parent_irq); @@ -862,10 +863,10 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size, } espdma = sparc32_dma_init(hwdef-dma_base, slavio_irq[18], - iommu, espdma_irq); + iommu, espdma_irq, 0); ledma = sparc32_dma_init(hwdef-dma_base + 16ULL, - slavio_irq[16], iommu, ledma_irq); + slavio_irq[16], iommu, ledma_irq, 1); if (graphic_depth != 8 graphic_depth != 24) { fprintf(stderr, qemu: Unsupported depth: %d\n, graphic_depth); @@ -1524,10 +1525,11 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size, sbi_irq[0]); espdma = sparc32_dma_init(hwdef-espdma_base, sbi_irq[3], - iounits[0], espdma_irq); + iounits[0], espdma_irq, 0); + /* should be lebuffer instead */ ledma = sparc32_dma_init(hwdef-ledma_base, sbi_irq[4], - iounits[0], ledma_irq); + iounits[0], ledma_irq, 0); if (graphic_depth != 8 graphic_depth != 24) { fprintf(stderr, qemu: Unsupported depth: %d\n, graphic_depth); @@ -1707,10 +1709,10 @@ static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, ram_addr_t RAM_size,
Re: [Qemu-devel] Re: [PATCH] sparc32: ledma extra registers
Am 18.12.2010 um 19:53 schrieb Blue Swirl: On Sat, Dec 18, 2010 at 5:09 PM, Bob Breuer breu...@mc.net wrote: ledma has 0x20 bytes of registers according to OBP, and at least Solaris9 reads the 5th register which is beyond what we've mapped. So let's setup a flag (inspired by a previous patch from Blue Swirl) to identify ledma from espdma, and map another 16 bytes of registers which return 0. Signed-off-by: Bob Breuer breu...@mc.net I'm not familar with that part of code but... diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c index e78f025..56be8c8 100644 --- a/hw/sparc32_dma.c +++ b/hw/sparc32_dma.c @@ -165,6 +169,9 @@ static uint32_t dma_mem_readl(void *opaque, target_phys_addr_t addr) DMAState *s = opaque; uint32_t saddr; +if (s-is_ledma (addr DMA_MAX_REG_OFFSET)) { +return 0; /* extra mystery register(s) */ Wouldn't it be a good idea to trace these mystery reads... +} saddr = (addr DMA_MASK) 2; trace_sparc32_dma_mem_readl(addr, s-dmaregs[saddr]); return s-dmaregs[saddr]; @@ -175,6 +182,9 @@ static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) DMAState *s = opaque; uint32_t saddr; +if (s-is_ledma (addr DMA_MAX_REG_OFFSET)) { +return; /* extra mystery register(s) */ ...and writes? We return just before the tracepoints fire. Andreas +} saddr = (addr DMA_MASK) 2; trace_sparc32_dma_mem_writel(addr, s-dmaregs[saddr], val); switch (saddr) {