qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] sh4: Remove bad memory alias 'sh_pci.isa'


From: Guenter Roeck
Subject: Re: [PATCH] sh4: Remove bad memory alias 'sh_pci.isa'
Date: Tue, 18 Feb 2020 09:49:38 -0800
User-agent: Mutt/1.9.4 (2018-02-28)

On Tue, Feb 18, 2020 at 04:33:49PM +0000, Peter Maydell wrote:
> On Mon, 17 Feb 2020 at 20:38, Guenter Roeck <address@hidden> wrote:
> >
> > The memory alias sh_pci.isa is located at address 0x0000 with
> > a length of 0x40000. This results in the following memory tree.
> >
> > FlatView #1
> >  AS "memory", root: system
> >  AS "cpu-memory-0", root: system
> >  AS "sh_pci_host", root: bus master container
> >  Root memory region: system
> >   0000000000000000-000000000000ffff (prio 0, i/o): io
> >   0000000000010000-0000000000ffffff (prio 0, i/o): r2d.flash 
> > @0000000000010000
> >
> > The alias overlaps with flash memory. As result, flash memory can
> > not be accessed. Removing the alias fixes the problem. With this patch,
> > the memory tree is as follows, and flash is detected as expected.
> >
> > FlatView #1
> >  AS "memory", root: system
> >  AS "cpu-memory-0", root: system
> >  AS "sh_pci_host", root: bus master container
> >  Root memory region: system
> >   0000000000000000-0000000000ffffff (prio 0, i/o): r2d.flash
> >
> > After this patch has been applied, access to PCI, ATA, and USB is still
> > working, and no negative impact has ben observed.
> >
> > Signed-off-by: Guenter Roeck <address@hidden>
> > ---
> >  hw/sh4/sh_pci.c | 2 --
> >  1 file changed, 2 deletions(-)
> >
> > diff --git a/hw/sh4/sh_pci.c b/hw/sh4/sh_pci.c
> > index 71afd23b67..4ced54f1a5 100644
> > --- a/hw/sh4/sh_pci.c
> > +++ b/hw/sh4/sh_pci.c
> > @@ -143,8 +143,6 @@ static void sh_pci_device_realize(DeviceState *dev, 
> > Error **errp)
> >                            "sh_pci", 0x224);
> >      memory_region_init_alias(&s->memconfig_a7, OBJECT(s), "sh_pci.2",
> >                               &s->memconfig_p4, 0, 0x224);
> > -    memory_region_init_alias(&s->isa, OBJECT(s), "sh_pci.isa",
> > -                             get_system_io(), 0, 0x40000);
> >      sysbus_init_mmio(sbd, &s->memconfig_p4);
> >      sysbus_init_mmio(sbd, &s->memconfig_a7);
> >      s->iobr = 0xfe240000;
> > --
> 
> This change doesn't look correct. This removes the init of the alias MR,
> but we continue to use it in other parts of the code -- we will
> add it to the system memory at 0xfe240000 and we will remap it
> at different addresses when the guest writes to the 0x1c8 "IO space
> base" register.
> 
> This alias is for the ISA I/O region bridge; the code initially
> maps it at a non-zero address:
>     s->iobr = 0xfe240000;
>     memory_region_add_subregion(get_system_memory(), s->iobr, &s->isa);
> so it's not entirely clear how it ends up at 0. You could try
> sticking a printf into sh_pci_reg_write() to see if we end
> up taking that code path to modify the address for it, which
> is the most plausible reason for it to be at 0, I think.
> 

Yes, that is what happens.

###### sh_pci_reg_write(addr=0x1c8, val=0x0, size=4)

> I think the problem here is that our implementation of the
> IO space base register is simply completely wrong.
> 
> Conveniently, the SSH7751R "user's manual: hardware" seems to
> still be downloadable from Renesas at
> https://www.renesas.com/br/en/document/hw-manual?hwLayerShowFlg=true&prdLayerId=1057&layerName=SH7751R&coronrService=document-prd-search&hwDocUrl=%2Fpt-br%2Fdoc%2Fproducts%2Fmpumcu%2F001%2Fr01uh0457ej0401_sh7751.pdf&hashKey=a503c1946f0bcc913aaf89f48dd15b53
> -- hopefully that URL
> works for others and not just me.
> 
> Section 22.3.7 and in particular figure 22.3 are clear
> about how this is supposed to work: there is a window
> at 0xfe240000 in the system register space for PCI I/O
> space. When the CPU makes an access into that area,
> the PCI controller calculates the PCI address to use
> by combining bits 0..17 of the system address with the
> bits 31..18 value that the guest has put into the PCIIOBR.
> That is, writing to the PCIIOBR changes which section of
> the IO address space is visible in the 0xfe240000 window.
> Instead what QEMU's implementation does is move the
> window to whatever value the guest writes to the PCIIOBR
> register -- so if the guest writes 0 we put the window at
> 0 in system address space.
> 
> I think the correct fix would be to have the handling of
> PCIIOBR call memory_region_set_alias_offset() (thus updating
> where this alias window points within the system IO space),
> rather than doing the del/add subregion calls.
> 
Like this ?

--- a/hw/sh4/sh_pci.c
+++ b/hw/sh4/sh_pci.c
@@ -67,12 +67,7 @@ static void sh_pci_reg_write (void *p, hwaddr addr, uint64_t 
val,
         pcic->mbr = val & 0xff000001;
         break;
     case 0x1c8:
-        if ((val & 0xfffc0000) != (pcic->iobr & 0xfffc0000)) {
-            memory_region_del_subregion(get_system_memory(), &pcic->isa);
-            pcic->iobr = val & 0xfffc0001;
-            memory_region_add_subregion(get_system_memory(),
-                                        pcic->iobr & 0xfffc0000, &pcic->isa);
-        }
+        memory_region_set_alias_offset(&pcic->isa, val & 0xfffc0000);
         break;

This works for me as well. Please let me know if it is correct (especially
the mask), and I'll resubmit.

Thanks,
Guenter



reply via email to

[Prev in Thread] Current Thread [Next in Thread]