qemu-ppc
[Top][All Lists]
Advanced

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

Re: [PATCH 4/6] ppc/pegasos2: Access MV64361 registers via their memory


From: David Gibson
Subject: Re: [PATCH 4/6] ppc/pegasos2: Access MV64361 registers via their memory region
Date: Fri, 15 Oct 2021 14:18:42 +1100

On Thu, Oct 14, 2021 at 09:50:19PM +0200, BALATON Zoltan wrote:
> Instead of relying on the mapped address of the MV64361 registers
> access them via their memory region. This is not a problem at reset
> time when these registers are mapped at the default address but the
> guest could change this later and then the RTAS calls accessing PCI
> config registers could fail. None of the guests actually do this so
> this only avoids a theoretical problem not seen in practice.
> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>

Applied, thanks.

> ---
>  hw/pci-host/mv64361.c |   1 +
>  hw/ppc/pegasos2.c     | 117 ++++++++++++++++++++----------------------
>  2 files changed, 56 insertions(+), 62 deletions(-)
> 
> diff --git a/hw/pci-host/mv64361.c b/hw/pci-host/mv64361.c
> index 92b0f5d047..00b3ff7d90 100644
> --- a/hw/pci-host/mv64361.c
> +++ b/hw/pci-host/mv64361.c
> @@ -869,6 +869,7 @@ static void mv64361_realize(DeviceState *dev, Error 
> **errp)
>      s->base_addr_enable = 0x1fffff;
>      memory_region_init_io(&s->regs, OBJECT(s), &mv64361_ops, s,
>                            TYPE_MV64361, 0x10000);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->regs);
>      for (i = 0; i < 2; i++) {
>          g_autofree char *name = g_strdup_printf("pcihost%d", i);
>          object_initialize_child(OBJECT(dev), name, &s->pci[i],
> diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
> index a9e3625f56..a861bf16b8 100644
> --- a/hw/ppc/pegasos2.c
> +++ b/hw/ppc/pegasos2.c
> @@ -205,56 +205,49 @@ static void pegasos2_init(MachineState *machine)
>      }
>  }
>  
> -static uint32_t pegasos2_pci_config_read(AddressSpace *as, int bus,
> +static uint32_t pegasos2_mv_reg_read(Pegasos2MachineState *pm,
> +                                     uint32_t addr, uint32_t len)
> +{
> +    MemoryRegion *r = sysbus_mmio_get_region(SYS_BUS_DEVICE(pm->mv), 0);
> +    uint64_t val = 0xffffffffULL;
> +    memory_region_dispatch_read(r, addr, &val, size_memop(len) | MO_LE,
> +                                MEMTXATTRS_UNSPECIFIED);
> +    return val;
> +}
> +
> +static void pegasos2_mv_reg_write(Pegasos2MachineState *pm, uint32_t addr,
> +                                  uint32_t len, uint32_t val)
> +{
> +    MemoryRegion *r = sysbus_mmio_get_region(SYS_BUS_DEVICE(pm->mv), 0);
> +    memory_region_dispatch_write(r, addr, val, size_memop(len) | MO_LE,
> +                                 MEMTXATTRS_UNSPECIFIED);
> +}
> +
> +static uint32_t pegasos2_pci_config_read(Pegasos2MachineState *pm, int bus,
>                                           uint32_t addr, uint32_t len)
>  {
> -    hwaddr pcicfg = (bus ? 0xf1000c78 : 0xf1000cf8);
> -    uint32_t val = 0xffffffff;
> -
> -    stl_le_phys(as, pcicfg, addr | BIT(31));
> -    switch (len) {
> -    case 4:
> -        val = ldl_le_phys(as, pcicfg + 4);
> -        break;
> -    case 2:
> -        val = lduw_le_phys(as, pcicfg + 4);
> -        break;
> -    case 1:
> -        val = ldub_phys(as, pcicfg + 4);
> -        break;
> -    default:
> -        qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid length\n", __func__);
> -        break;
> +    hwaddr pcicfg = bus ? 0xc78 : 0xcf8;
> +    uint64_t val = 0xffffffffULL;
> +
> +    if (len <= 4) {
> +        pegasos2_mv_reg_write(pm, pcicfg, 4, addr | BIT(31));
> +        val = pegasos2_mv_reg_read(pm, pcicfg + 4, len);
>      }
>      return val;
>  }
>  
> -static void pegasos2_pci_config_write(AddressSpace *as, int bus, uint32_t 
> addr,
> -                                      uint32_t len, uint32_t val)
> +static void pegasos2_pci_config_write(Pegasos2MachineState *pm, int bus,
> +                                      uint32_t addr, uint32_t len, uint32_t 
> val)
>  {
> -    hwaddr pcicfg = (bus ? 0xf1000c78 : 0xf1000cf8);
> -
> -    stl_le_phys(as, pcicfg, addr | BIT(31));
> -    switch (len) {
> -    case 4:
> -        stl_le_phys(as, pcicfg + 4, val);
> -        break;
> -    case 2:
> -        stw_le_phys(as, pcicfg + 4, val);
> -        break;
> -    case 1:
> -        stb_phys(as, pcicfg + 4, val);
> -        break;
> -    default:
> -        qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid length\n", __func__);
> -        break;
> -    }
> +    hwaddr pcicfg = bus ? 0xc78 : 0xcf8;
> +
> +    pegasos2_mv_reg_write(pm, pcicfg, 4, addr | BIT(31));
> +    pegasos2_mv_reg_write(pm, pcicfg + 4, len, val);
>  }
>  
>  static void pegasos2_machine_reset(MachineState *machine)
>  {
>      Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine);
> -    AddressSpace *as = CPU(pm->cpu)->as;
>      void *fdt;
>      uint64_t d[2];
>      int sz;
> @@ -265,51 +258,51 @@ static void pegasos2_machine_reset(MachineState 
> *machine)
>      }
>  
>      /* Otherwise, set up devices that board firmware would normally do */
> -    stl_le_phys(as, 0xf1000000, 0x28020ff);
> -    stl_le_phys(as, 0xf1000278, 0xa31fc);
> -    stl_le_phys(as, 0xf100f300, 0x11ff0400);
> -    stl_le_phys(as, 0xf100f10c, 0x80000000);
> -    stl_le_phys(as, 0xf100001c, 0x8000000);
> -    pegasos2_pci_config_write(as, 0, PCI_COMMAND, 2, PCI_COMMAND_IO |
> +    pegasos2_mv_reg_write(pm, 0, 4, 0x28020ff);
> +    pegasos2_mv_reg_write(pm, 0x278, 4, 0xa31fc);
> +    pegasos2_mv_reg_write(pm, 0xf300, 4, 0x11ff0400);
> +    pegasos2_mv_reg_write(pm, 0xf10c, 4, 0x80000000);
> +    pegasos2_mv_reg_write(pm, 0x1c, 4, 0x8000000);
> +    pegasos2_pci_config_write(pm, 0, PCI_COMMAND, 2, PCI_COMMAND_IO |
>                                PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
> -    pegasos2_pci_config_write(as, 1, PCI_COMMAND, 2, PCI_COMMAND_IO |
> +    pegasos2_pci_config_write(pm, 1, PCI_COMMAND, 2, PCI_COMMAND_IO |
>                                PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
>  
> -    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 0) << 8) |
> +    pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 0) << 8) |
>                                PCI_INTERRUPT_LINE, 2, 0x9);
> -    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 0) << 8) |
> +    pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 0) << 8) |
>                                0x50, 1, 0x2);
>  
> -    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) |
> +    pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 1) << 8) |
>                                PCI_INTERRUPT_LINE, 2, 0x109);
> -    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) |
> +    pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 1) << 8) |
>                                PCI_CLASS_PROG, 1, 0xf);
> -    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) |
> +    pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 1) << 8) |
>                                0x40, 1, 0xb);
> -    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) |
> +    pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 1) << 8) |
>                                0x50, 4, 0x17171717);
> -    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) |
> +    pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 1) << 8) |
>                                PCI_COMMAND, 2, 0x87);
>  
> -    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 2) << 8) |
> +    pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 2) << 8) |
>                                PCI_INTERRUPT_LINE, 2, 0x409);
>  
> -    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 3) << 8) |
> +    pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 3) << 8) |
>                                PCI_INTERRUPT_LINE, 2, 0x409);
>  
> -    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 4) << 8) |
> +    pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 4) << 8) |
>                                PCI_INTERRUPT_LINE, 2, 0x9);
> -    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 4) << 8) |
> +    pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 4) << 8) |
>                                0x48, 4, 0xf00);
> -    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 4) << 8) |
> +    pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 4) << 8) |
>                                0x40, 4, 0x558020);
> -    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 4) << 8) |
> +    pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 4) << 8) |
>                                0x90, 4, 0xd00);
>  
> -    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 5) << 8) |
> +    pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 5) << 8) |
>                                PCI_INTERRUPT_LINE, 2, 0x309);
>  
> -    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 6) << 8) |
> +    pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 6) << 8) |
>                                PCI_INTERRUPT_LINE, 2, 0x309);
>  
>      /* Device tree and VOF set up */
> @@ -404,7 +397,7 @@ static target_ulong pegasos2_rtas(PowerPCCPU *cpu, 
> Pegasos2MachineState *pm,
>          }
>          addr = ldl_be_phys(as, args);
>          len = ldl_be_phys(as, args + 4);
> -        val = pegasos2_pci_config_read(as, !(addr >> 24),
> +        val = pegasos2_pci_config_read(pm, !(addr >> 24),
>                                         addr & 0x0fffffff, len);
>          stl_be_phys(as, rets, 0);
>          stl_be_phys(as, rets + 4, val);
> @@ -421,7 +414,7 @@ static target_ulong pegasos2_rtas(PowerPCCPU *cpu, 
> Pegasos2MachineState *pm,
>          addr = ldl_be_phys(as, args);
>          len = ldl_be_phys(as, args + 4);
>          val = ldl_be_phys(as, args + 8);
> -        pegasos2_pci_config_write(as, !(addr >> 24),
> +        pegasos2_pci_config_write(pm, !(addr >> 24),
>                                    addr & 0x0fffffff, len, val);
>          stl_be_phys(as, rets, 0);
>          return H_SUCCESS;

-- 
David Gibson                    | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
                                | _way_ _around_!
http://www.ozlabs.org/~dgibson

Attachment: signature.asc
Description: PGP signature


reply via email to

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