All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 04/15] ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs
  2017-08-20 17:23 [Qemu-devel] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
                   ` (5 preceding siblings ...)
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 11/15] ppc: Add 460EX embedded CPU BALATON Zoltan
@ 2017-08-20 17:23 ` BALATON Zoltan
  2017-08-21  4:18   ` David Gibson
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 09/15] hw/ide: Emulate SiI3112 SATA controller BALATON Zoltan
                   ` (8 subsequent siblings)
  15 siblings, 1 reply; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-20 17:23 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: Alexander Graf, David Gibson, Francois Revol, Gerd Hoffmann

Some PPC SoCs have an EHCI with OHCI companion USB controller. Add a
new type for this similar to types used for other embedded SoCs.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/usb/hcd-ehci-sysbus.c | 25 +++++++++++++++++++++++++
 hw/usb/hcd-ehci.h        |  1 +
 2 files changed, 26 insertions(+)

diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
index 6c20604..3b83beb 100644
--- a/hw/usb/hcd-ehci-sysbus.c
+++ b/hw/usb/hcd-ehci-sysbus.c
@@ -142,6 +142,30 @@ static const TypeInfo ehci_tegra2_type_info = {
     .class_init    = ehci_tegra2_class_init,
 };
 
+static void ehci_ppc4xx_init(Object *o)
+{
+    EHCISysBusState *s = SYS_BUS_EHCI(o);
+
+    s->ehci.companion_enable = true;
+}
+
+static void ehci_ppc4xx_class_init(ObjectClass *oc, void *data)
+{
+    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    sec->capsbase = 0x0;
+    sec->opregbase = 0x10;
+    set_bit(DEVICE_CATEGORY_USB, dc->categories);
+}
+
+static const TypeInfo ehci_ppc4xx_type_info = {
+    .name          = TYPE_PPC4xx_EHCI,
+    .parent        = TYPE_SYS_BUS_EHCI,
+    .class_init    = ehci_ppc4xx_class_init,
+    .instance_init = ehci_ppc4xx_init,
+};
+
 /*
  * Faraday FUSBH200 USB 2.0 EHCI
  */
@@ -224,6 +248,7 @@ static void ehci_sysbus_register_types(void)
     type_register_static(&ehci_xlnx_type_info);
     type_register_static(&ehci_exynos4210_type_info);
     type_register_static(&ehci_tegra2_type_info);
+    type_register_static(&ehci_ppc4xx_type_info);
     type_register_static(&ehci_fusbh200_type_info);
 }
 
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
index 821f1de..0bc364b 100644
--- a/hw/usb/hcd-ehci.h
+++ b/hw/usb/hcd-ehci.h
@@ -344,6 +344,7 @@ typedef struct EHCIPCIState {
 #define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb"
 #define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb"
 #define TYPE_TEGRA2_EHCI "tegra2-ehci-usb"
+#define TYPE_PPC4xx_EHCI "ppc4xx-ehci-usb"
 #define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb"
 
 #define SYS_BUS_EHCI(obj) \
-- 
2.7.6

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Qemu-devel] [PATCH 12/15] ppc4xx: Export ECB and PLB emulation
  2017-08-20 17:23 [Qemu-devel] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
                   ` (2 preceding siblings ...)
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 02/15] ppc4xx: Make MAL emulation more generic BALATON Zoltan
@ 2017-08-20 17:23 ` BALATON Zoltan
  2017-08-23  2:30   ` David Gibson
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 05/15] ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file BALATON Zoltan
                   ` (11 subsequent siblings)
  15 siblings, 1 reply; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-20 17:23 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

Make these device models available outside ppc405_uc.c for reuse in
460EX emulation. They are left in their current place for now because
they are used mostly unchanged and I'm not sure these correctly model
the components in 440 SoCs (but they seem to be good enough). These
functions could be moved in a subsequent clean up series when this is
confirmed.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/ppc/ppc405.h    | 3 +++
 hw/ppc/ppc405_uc.c | 4 ++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index a9ffc87..7ed25cf 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -59,6 +59,9 @@ struct ppc4xx_bd_info_t {
 ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
                                 uint32_t flags);
 
+void ppc4xx_plb_init(CPUPPCState *env);
+void ppc405_ebc_init(CPUPPCState *env);
+
 CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
                         MemoryRegion ram_memories[4],
                         hwaddr ram_bases[4],
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 8f44cb4..e621d0a 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -174,7 +174,7 @@ static void ppc4xx_plb_reset (void *opaque)
     plb->besr = 0x00000000;
 }
 
-static void ppc4xx_plb_init(CPUPPCState *env)
+void ppc4xx_plb_init(CPUPPCState *env)
 {
     ppc4xx_plb_t *plb;
 
@@ -585,7 +585,7 @@ static void ebc_reset (void *opaque)
     ebc->cfg = 0x80400000;
 }
 
-static void ppc405_ebc_init(CPUPPCState *env)
+void ppc405_ebc_init(CPUPPCState *env)
 {
     ppc4xx_ebc_t *ebc;
 
-- 
2.7.6

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Qemu-devel] [PATCH 02/15] ppc4xx: Make MAL emulation more generic
  2017-08-20 17:23 [Qemu-devel] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 07/15] ppc4xx_i2c: Move to hw/i2c BALATON Zoltan
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 06/15] ppc4xx_i2c: QOMify BALATON Zoltan
@ 2017-08-20 17:23 ` BALATON Zoltan
  2017-08-21 10:40   ` David Gibson
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 12/15] ppc4xx: Export ECB and PLB emulation BALATON Zoltan
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-20 17:23 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

Allow MAL with more RX and TX channels as found in newer versions.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/ppc405_uc.c      |   2 +-
 hw/ppc/ppc4xx_devs.c    | 171 +++++++++++++++++++-----------------------------
 include/hw/ppc/ppc4xx.h |   3 +-
 3 files changed, 70 insertions(+), 106 deletions(-)

diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 3c74402..03856d5 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -2281,7 +2281,7 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
     mal_irqs[1] = pic[12];
     mal_irqs[2] = pic[13];
     mal_irqs[3] = pic[14];
-    ppc405_mal_init(env, mal_irqs);
+    ppc4xx_mal_init(env, 4, 2, mal_irqs);
     /* Ethernet */
     /* Uses pic[9], pic[15], pic[17] */
     /* CPU control */
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 8e4f78e..6e1cc09 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -737,6 +737,7 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
 
 /*****************************************************************************/
 /* MAL */
+
 enum {
     MAL0_CFG      = 0x180,
     MAL0_ESR      = 0x181,
@@ -750,17 +751,13 @@ enum {
     MAL0_RXEOBISR = 0x192,
     MAL0_RXDEIR   = 0x193,
     MAL0_TXCTP0R  = 0x1A0,
-    MAL0_TXCTP1R  = 0x1A1,
-    MAL0_TXCTP2R  = 0x1A2,
-    MAL0_TXCTP3R  = 0x1A3,
     MAL0_RXCTP0R  = 0x1C0,
-    MAL0_RXCTP1R  = 0x1C1,
     MAL0_RCBS0    = 0x1E0,
     MAL0_RCBS1    = 0x1E1,
 };
 
-typedef struct ppc40x_mal_t ppc40x_mal_t;
-struct ppc40x_mal_t {
+typedef struct ppc4xx_mal_t ppc4xx_mal_t;
+struct ppc4xx_mal_t {
     qemu_irq irqs[4];
     uint32_t cfg;
     uint32_t esr;
@@ -773,16 +770,32 @@ struct ppc40x_mal_t {
     uint32_t rxcarr;
     uint32_t rxeobisr;
     uint32_t rxdeir;
-    uint32_t txctpr[4];
-    uint32_t rxctpr[2];
-    uint32_t rcbs[2];
+    uint32_t *txctpr;
+    uint32_t *rxctpr;
+    uint32_t *rcbs;
+    uint8_t  txcnum;
+    uint8_t  rxcnum;
 };
 
-static void ppc40x_mal_reset(void *opaque);
+static void ppc4xx_mal_reset(void *opaque)
+{
+    ppc4xx_mal_t *mal;
+
+    mal = opaque;
+    mal->cfg = 0x0007C000;
+    mal->esr = 0x00000000;
+    mal->ier = 0x00000000;
+    mal->rxcasr = 0x00000000;
+    mal->rxdeir = 0x00000000;
+    mal->rxeobisr = 0x00000000;
+    mal->txcasr = 0x00000000;
+    mal->txdeir = 0x00000000;
+    mal->txeobisr = 0x00000000;
+}
 
 static uint32_t dcr_read_mal(void *opaque, int dcrn)
 {
-    ppc40x_mal_t *mal;
+    ppc4xx_mal_t *mal;
     uint32_t ret;
 
     mal = opaque;
@@ -820,48 +833,32 @@ static uint32_t dcr_read_mal(void *opaque, int dcrn)
     case MAL0_RXDEIR:
         ret = mal->rxdeir;
         break;
-    case MAL0_TXCTP0R:
-        ret = mal->txctpr[0];
-        break;
-    case MAL0_TXCTP1R:
-        ret = mal->txctpr[1];
-        break;
-    case MAL0_TXCTP2R:
-        ret = mal->txctpr[2];
-        break;
-    case MAL0_TXCTP3R:
-        ret = mal->txctpr[3];
-        break;
-    case MAL0_RXCTP0R:
-        ret = mal->rxctpr[0];
-        break;
-    case MAL0_RXCTP1R:
-        ret = mal->rxctpr[1];
-        break;
-    case MAL0_RCBS0:
-        ret = mal->rcbs[0];
-        break;
-    case MAL0_RCBS1:
-        ret = mal->rcbs[1];
-        break;
     default:
         ret = 0;
         break;
     }
+    if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
+        ret = mal->txctpr[dcrn - MAL0_TXCTP0R];
+    }
+    if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
+        ret = mal->rxctpr[dcrn - MAL0_RXCTP0R];
+    }
+    if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
+        ret = mal->rcbs[dcrn - MAL0_RCBS0];
+    }
 
     return ret;
 }
 
 static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
 {
-    ppc40x_mal_t *mal;
-    int idx;
+    ppc4xx_mal_t *mal;
 
     mal = opaque;
     switch (dcrn) {
     case MAL0_CFG:
         if (val & 0x80000000) {
-            ppc40x_mal_reset(mal);
+            ppc4xx_mal_reset(mal);
         }
         mal->cfg = val & 0x00FFC087;
         break;
@@ -900,65 +897,35 @@ static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
         /* Read/clear */
         mal->rxdeir &= ~val;
         break;
-    case MAL0_TXCTP0R:
-        idx = 0;
-        goto update_tx_ptr;
-    case MAL0_TXCTP1R:
-        idx = 1;
-        goto update_tx_ptr;
-    case MAL0_TXCTP2R:
-        idx = 2;
-        goto update_tx_ptr;
-    case MAL0_TXCTP3R:
-        idx = 3;
-    update_tx_ptr:
-        mal->txctpr[idx] = val;
-        break;
-    case MAL0_RXCTP0R:
-        idx = 0;
-        goto update_rx_ptr;
-    case MAL0_RXCTP1R:
-        idx = 1;
-    update_rx_ptr:
-        mal->rxctpr[idx] = val;
-        break;
-    case MAL0_RCBS0:
-        idx = 0;
-        goto update_rx_size;
-    case MAL0_RCBS1:
-        idx = 1;
-    update_rx_size:
-        mal->rcbs[idx] = val & 0x000000FF;
-        break;
+    }
+    if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
+        mal->txctpr[dcrn - MAL0_TXCTP0R] = val;
+    }
+    if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
+        mal->rxctpr[dcrn - MAL0_RXCTP0R] = val;
+    }
+    if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
+        mal->rcbs[dcrn - MAL0_RCBS0] = val & 0x000000FF;
     }
 }
 
-static void ppc40x_mal_reset(void *opaque)
-{
-    ppc40x_mal_t *mal;
-
-    mal = opaque;
-    mal->cfg = 0x0007C000;
-    mal->esr = 0x00000000;
-    mal->ier = 0x00000000;
-    mal->rxcasr = 0x00000000;
-    mal->rxdeir = 0x00000000;
-    mal->rxeobisr = 0x00000000;
-    mal->txcasr = 0x00000000;
-    mal->txdeir = 0x00000000;
-    mal->txeobisr = 0x00000000;
-}
-
-void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
+void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
+                     qemu_irq irqs[4])
 {
-    ppc40x_mal_t *mal;
+    ppc4xx_mal_t *mal;
     int i;
 
-    mal = g_malloc0(sizeof(ppc40x_mal_t));
+    assert(txcnum <= 32 && rxcnum <= 32);
+    mal = g_malloc0(sizeof(*mal));
+    mal->txcnum = txcnum;
+    mal->rxcnum = rxcnum;
+    mal->txctpr = g_new0(uint32_t, txcnum);
+    mal->rxctpr = g_new0(uint32_t, rxcnum);
+    mal->rcbs = g_new0(uint32_t, rxcnum);
     for (i = 0; i < 4; i++) {
         mal->irqs[i] = irqs[i];
     }
-    qemu_register_reset(&ppc40x_mal_reset, mal);
+    qemu_register_reset(&ppc4xx_mal_reset, mal);
     ppc_dcr_register(env, MAL0_CFG,
                      mal, &dcr_read_mal, &dcr_write_mal);
     ppc_dcr_register(env, MAL0_ESR,
@@ -981,20 +948,16 @@ void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
                      mal, &dcr_read_mal, &dcr_write_mal);
     ppc_dcr_register(env, MAL0_RXDEIR,
                      mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP0R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP1R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP2R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP3R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCTP0R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCTP1R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RCBS0,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RCBS1,
-                     mal, &dcr_read_mal, &dcr_write_mal);
+    for (i = 0; i < txcnum; i++) {
+        ppc_dcr_register(env, MAL0_TXCTP0R + i,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+    }
+    for (i = 0; i < rxcnum; i++) {
+        ppc_dcr_register(env, MAL0_RXCTP0R + i,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+    }
+    for (i = 0; i < rxcnum; i++) {
+        ppc_dcr_register(env, MAL0_RCBS0 + i,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+    }
 }
diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
index db50cfa..cb0bb55 100644
--- a/include/hw/ppc/ppc4xx.h
+++ b/include/hw/ppc/ppc4xx.h
@@ -53,7 +53,8 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
                         hwaddr *ram_sizes,
                         int do_init);
 
-void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4]);
+void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
+                     qemu_irq irqs[4]);
 
 #define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost"
 
-- 
2.7.6

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Qemu-devel] [PATCH 06/15] ppc4xx_i2c: QOMify
  2017-08-20 17:23 [Qemu-devel] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 07/15] ppc4xx_i2c: Move to hw/i2c BALATON Zoltan
@ 2017-08-20 17:23 ` BALATON Zoltan
  2017-08-21 10:50   ` David Gibson
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 02/15] ppc4xx: Make MAL emulation more generic BALATON Zoltan
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-20 17:23 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/ppc/ppc405.h             |   2 -
 hw/ppc/ppc405_uc.c          |   5 +-
 hw/ppc/ppc4xx_i2c.c         | 154 ++++++++++++++------------------------------
 include/hw/i2c/ppc4xx_i2c.h |  61 ++++++++++++++++++
 4 files changed, 113 insertions(+), 109 deletions(-)
 create mode 100644 include/hw/i2c/ppc4xx_i2c.h

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 61ec739..a9ffc87 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -59,8 +59,6 @@ struct ppc4xx_bd_info_t {
 ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
                                 uint32_t flags);
 
-void ppc405_i2c_init(hwaddr base, qemu_irq irq);
-
 CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
                         MemoryRegion ram_memories[4],
                         hwaddr ram_bases[4],
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 3925e4c..8f44cb4 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -28,6 +28,7 @@
 #include "hw/hw.h"
 #include "hw/ppc/ppc.h"
 #include "hw/boards.h"
+#include "hw/i2c/ppc4xx_i2c.h"
 #include "ppc405.h"
 #include "hw/char/serial.h"
 #include "qemu/timer.h"
@@ -1663,7 +1664,7 @@ CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
                        DEVICE_BIG_ENDIAN);
     }
     /* IIC controller */
-    ppc405_i2c_init(0xef600500, pic[2]);
+    sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500, pic[2]);
     /* GPIO */
     ppc405_gpio_init(0xef600700);
     /* CPU control */
@@ -2010,7 +2011,7 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
     dma_irqs[3] = pic[8];
     ppc405_dma_init(env, dma_irqs);
     /* IIC controller */
-    ppc405_i2c_init(0xef600500, pic[2]);
+    sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500, pic[2]);
     /* GPIO */
     ppc405_gpio_init(0xef600700);
     /* Serial ports */
diff --git a/hw/ppc/ppc4xx_i2c.c b/hw/ppc/ppc4xx_i2c.c
index 15f2dea..5a6bde9 100644
--- a/hw/ppc/ppc4xx_i2c.c
+++ b/hw/ppc/ppc4xx_i2c.c
@@ -27,42 +27,20 @@
 #include "qemu-common.h"
 #include "cpu.h"
 #include "hw/hw.h"
-#include "exec/address-spaces.h"
-#include "hw/ppc/ppc.h"
-#include "ppc405.h"
+#include "hw/i2c/ppc4xx_i2c.h"
 
 /*#define DEBUG_I2C*/
 
-typedef struct ppc4xx_i2c_t ppc4xx_i2c_t;
-struct ppc4xx_i2c_t {
-    qemu_irq irq;
-    MemoryRegion iomem;
-    uint8_t mdata;
-    uint8_t lmadr;
-    uint8_t hmadr;
-    uint8_t cntl;
-    uint8_t mdcntl;
-    uint8_t sts;
-    uint8_t extsts;
-    uint8_t sdata;
-    uint8_t lsadr;
-    uint8_t hsadr;
-    uint8_t clkdiv;
-    uint8_t intrmsk;
-    uint8_t xfrcnt;
-    uint8_t xtcntlss;
-    uint8_t directcntl;
-};
+#define PPC4xx_I2C_MEM_SIZE 0x11
 
-static uint32_t ppc4xx_i2c_readb(void *opaque, hwaddr addr)
+static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size)
 {
-    ppc4xx_i2c_t *i2c;
-    uint32_t ret;
+    PPC4xxI2CState *i2c = PPC4xx_I2C(opaque);
+    uint64_t ret;
 
 #ifdef DEBUG_I2C
     printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
 #endif
-    i2c = opaque;
     switch (addr) {
     case 0x00:
         /*i2c_readbyte(&i2c->mdata);*/
@@ -115,22 +93,20 @@ static uint32_t ppc4xx_i2c_readb(void *opaque, hwaddr addr)
         break;
     }
 #ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__, addr, ret);
+    printf("%s: addr " TARGET_FMT_plx " %02" PRIx64 "\n", __func__, addr, ret);
 #endif
 
     return ret;
 }
 
-static void ppc4xx_i2c_writeb(void *opaque,
-                              hwaddr addr, uint32_t value)
+static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
+                              unsigned int size)
 {
-    ppc4xx_i2c_t *i2c;
-
+    PPC4xxI2CState *i2c = opaque;
 #ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx64 "\n",
+           __func__, addr, value);
 #endif
-    i2c = opaque;
     switch (addr) {
     case 0x00:
         i2c->mdata = value;
@@ -181,71 +157,20 @@ static void ppc4xx_i2c_writeb(void *opaque,
     }
 }
 
-static uint32_t ppc4xx_i2c_readw(void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    ret = ppc4xx_i2c_readb(opaque, addr) << 8;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 1);
-
-    return ret;
-}
-
-static void ppc4xx_i2c_writew(void *opaque,
-                              hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    ppc4xx_i2c_writeb(opaque, addr, value >> 8);
-    ppc4xx_i2c_writeb(opaque, addr + 1, value);
-}
-
-static uint32_t ppc4xx_i2c_readl(void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    ret = ppc4xx_i2c_readb(opaque, addr) << 24;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 3);
-
-    return ret;
-}
-
-static void ppc4xx_i2c_writel(void *opaque,
-                              hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    ppc4xx_i2c_writeb(opaque, addr, value >> 24);
-    ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16);
-    ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8);
-    ppc4xx_i2c_writeb(opaque, addr + 3, value);
-}
-
-static const MemoryRegionOps i2c_ops = {
-    .old_mmio = {
-        .read = { ppc4xx_i2c_readb, ppc4xx_i2c_readw, ppc4xx_i2c_readl, },
-        .write = { ppc4xx_i2c_writeb, ppc4xx_i2c_writew, ppc4xx_i2c_writel, },
-    },
+static const MemoryRegionOps ppc4xx_i2c_ops = {
+    .read = ppc4xx_i2c_readb,
+    .write = ppc4xx_i2c_writeb,
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 4,
+    .impl.min_access_size = 1,
+    .impl.max_access_size = 1,
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void ppc4xx_i2c_reset(void *opaque)
+static void ppc4xx_i2c_reset(DeviceState *s)
 {
-    ppc4xx_i2c_t *i2c;
+    PPC4xxI2CState *i2c = PPC4xx_I2C(s);
 
-    i2c = opaque;
     i2c->mdata = 0x00;
     i2c->sdata = 0x00;
     i2c->cntl = 0x00;
@@ -257,16 +182,35 @@ static void ppc4xx_i2c_reset(void *opaque)
     i2c->directcntl = 0x0F;
 }
 
-void ppc405_i2c_init(hwaddr base, qemu_irq irq)
+static void ppc4xx_i2c_init(Object *o)
 {
-    ppc4xx_i2c_t *i2c;
+    PPC4xxI2CState *s = PPC4xx_I2C(o);
 
-    i2c = g_malloc0(sizeof(ppc4xx_i2c_t));
-    i2c->irq = irq;
-#ifdef DEBUG_I2C
-    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
-#endif
-    memory_region_init_io(&i2c->iomem, NULL, &i2c_ops, i2c, "i2c", 0x011);
-    memory_region_add_subregion(get_system_memory(), base, &i2c->iomem);
-    qemu_register_reset(ppc4xx_i2c_reset, i2c);
+    memory_region_init_io(&s->iomem, OBJECT(s), &ppc4xx_i2c_ops, s,
+                          TYPE_PPC4xx_I2C, PPC4xx_I2C_MEM_SIZE);
+    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
+    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
+    s->bus = i2c_init_bus(DEVICE(s), "i2c");
 }
+
+static void ppc4xx_i2c_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->reset = ppc4xx_i2c_reset;
+}
+
+static const TypeInfo ppc4xx_i2c_type_info = {
+    .name = TYPE_PPC4xx_I2C,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PPC4xxI2CState),
+    .instance_init = ppc4xx_i2c_init,
+    .class_init = ppc4xx_i2c_class_init,
+};
+
+static void ppc4xx_i2c_register_types(void)
+{
+    type_register_static(&ppc4xx_i2c_type_info);
+}
+
+type_init(ppc4xx_i2c_register_types)
diff --git a/include/hw/i2c/ppc4xx_i2c.h b/include/hw/i2c/ppc4xx_i2c.h
new file mode 100644
index 0000000..e53042f
--- /dev/null
+++ b/include/hw/i2c/ppc4xx_i2c.h
@@ -0,0 +1,61 @@
+/*
+ * PPC4xx I2C controller emulation
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef PPC4XX_I2C_H
+#define PPC4XX_I2C_H
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "hw/sysbus.h"
+#include "hw/i2c/i2c.h"
+
+#define TYPE_PPC4xx_I2C "ppc4xx-i2c"
+#define PPC4xx_I2C(obj) OBJECT_CHECK(PPC4xxI2CState, (obj), TYPE_PPC4xx_I2C)
+
+typedef struct PPC4xxI2CState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+
+    /*< public >*/
+    I2CBus *bus;
+    qemu_irq irq;
+    MemoryRegion iomem;
+    uint8_t mdata;
+    uint8_t lmadr;
+    uint8_t hmadr;
+    uint8_t cntl;
+    uint8_t mdcntl;
+    uint8_t sts;
+    uint8_t extsts;
+    uint8_t sdata;
+    uint8_t lsadr;
+    uint8_t hsadr;
+    uint8_t clkdiv;
+    uint8_t intrmsk;
+    uint8_t xfrcnt;
+    uint8_t xtcntlss;
+    uint8_t directcntl;
+} PPC4xxI2CState;
+
+#endif /* PPC4XX_I2C_H */
-- 
2.7.6

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Qemu-devel] [PATCH 11/15] ppc: Add 460EX embedded CPU
  2017-08-20 17:23 [Qemu-devel] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
                   ` (4 preceding siblings ...)
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 05/15] ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file BALATON Zoltan
@ 2017-08-20 17:23 ` BALATON Zoltan
  2017-08-23  2:28   ` David Gibson
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 04/15] ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs BALATON Zoltan
                   ` (9 subsequent siblings)
  15 siblings, 1 reply; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-20 17:23 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

Despite its name it is a 440 core CPU

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
---
 target/ppc/cpu-models.c     |  3 +++
 target/ppc/cpu-models.h     |  1 +
 target/ppc/translate_init.c | 38 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 42 insertions(+)

diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
index 4d3e635..7c368fc 100644
--- a/target/ppc/cpu-models.c
+++ b/target/ppc/cpu-models.c
@@ -348,6 +348,8 @@
                 "PowerPC 440 EPb")
     POWERPC_DEF("440EPX",        CPU_POWERPC_440EPX,                 440EP,
                 "PowerPC 440 EPX")
+    POWERPC_DEF("460EXb",        CPU_POWERPC_460EXb,                 460EX,
+                "PowerPC 460 EXb")
 #if defined(TODO_USER_ONLY)
     POWERPC_DEF("440GPb",        CPU_POWERPC_440GPb,                 440GP,
                 "PowerPC 440 GPb")
@@ -1238,6 +1240,7 @@ PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "440GP", "440GPc" },
     { "440GR", "440GRa" },
     { "440GX", "440GXf" },
+    { "460EX", "460EXb" },
 
     { "RCPU", "MPC5xx" },
     /* MPC5xx microcontrollers */
diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h
index b563c45..92f99c0 100644
--- a/target/ppc/cpu-models.h
+++ b/target/ppc/cpu-models.h
@@ -241,6 +241,7 @@ enum {
     CPU_POWERPC_440SP              = 0x53221850,
     CPU_POWERPC_440SP2             = 0x53221891,
     CPU_POWERPC_440SPE             = 0x53421890,
+    CPU_POWERPC_460EXb             = 0x130218A4, /* called 460 but 440 core */
     /* PowerPC 460 family */
 #if 0
     /* Generic PowerPC 464 */
diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c
index 8fb407e..1e0d566 100644
--- a/target/ppc/translate_init.c
+++ b/target/ppc/translate_init.c
@@ -3832,6 +3832,44 @@ POWERPC_FAMILY(440EP)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
 }
 
+POWERPC_FAMILY(460EX)(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    dc->desc = "PowerPC 460 EX";
+    pcc->init_proc = init_proc_440EP;
+    pcc->check_pow = check_pow_nocheck;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
+                       PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |
+                       PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
+                       PPC_FLOAT_STFIWX |
+                       PPC_DCR | PPC_DCRX | PPC_WRTEE | PPC_RFMCI |
+                       PPC_CACHE | PPC_CACHE_ICBI |
+                       PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
+                       PPC_MEM_TLBSYNC | PPC_MFTB |
+                       PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
+                       PPC_440_SPEC;
+    pcc->msr_mask = (1ull << MSR_POW) |
+                    (1ull << MSR_CE) |
+                    (1ull << MSR_EE) |
+                    (1ull << MSR_PR) |
+                    (1ull << MSR_FP) |
+                    (1ull << MSR_ME) |
+                    (1ull << MSR_FE0) |
+                    (1ull << MSR_DWE) |
+                    (1ull << MSR_DE) |
+                    (1ull << MSR_FE1) |
+                    (1ull << MSR_IR) |
+                    (1ull << MSR_DR);
+    pcc->mmu_model = POWERPC_MMU_BOOKE;
+    pcc->excp_model = POWERPC_EXCP_BOOKE;
+    pcc->bus_model = PPC_FLAGS_INPUT_BookE;
+    pcc->bfd_mach = bfd_mach_ppc_403;
+    pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DWE |
+                 POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
+}
+
 static void init_proc_440GP(CPUPPCState *env)
 {
     /* Time base */
-- 
2.7.6

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Qemu-devel] [PATCH 13/15] ppc4xx: Add more PLB registers
  2017-08-20 17:23 [Qemu-devel] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
                   ` (7 preceding siblings ...)
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 09/15] hw/ide: Emulate SiI3112 SATA controller BALATON Zoltan
@ 2017-08-20 17:23 ` BALATON Zoltan
  2017-08-20 21:58   ` Philippe Mathieu-Daudé
  2017-08-23  2:39   ` David Gibson
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 03/15] ohci: Allow sysbus version to be used as a companion BALATON Zoltan
                   ` (6 subsequent siblings)
  15 siblings, 2 replies; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-20 17:23 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

These registers are present in 440 SoCs (and maybe in others too) and
U-Boot accesses them when printing register info. We don't emulate
these but add them to avoid crashing when they are read or written.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/ppc/ppc405_uc.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index e621d0a..8e58065 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -105,9 +105,12 @@ ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
 /*****************************************************************************/
 /* Peripheral local bus arbitrer */
 enum {
-    PLB0_BESR = 0x084,
-    PLB0_BEAR = 0x086,
-    PLB0_ACR  = 0x087,
+    PLB3A0_ACR = 0x077,
+    PLB4A0_ACR = 0x081,
+    PLB0_BESR  = 0x084,
+    PLB0_BEAR  = 0x086,
+    PLB0_ACR   = 0x087,
+    PLB4A1_ACR = 0x089,
 };
 
 typedef struct ppc4xx_plb_t ppc4xx_plb_t;
@@ -179,9 +182,12 @@ void ppc4xx_plb_init(CPUPPCState *env)
     ppc4xx_plb_t *plb;
 
     plb = g_malloc0(sizeof(ppc4xx_plb_t));
+    ppc_dcr_register(env, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
+    ppc_dcr_register(env, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
     ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
     ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
     ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
+    ppc_dcr_register(env, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb);
     qemu_register_reset(ppc4xx_plb_reset, plb);
 }
 
-- 
2.7.6

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Qemu-devel] [PATCH 08/15] ppc4xx_i2c: Implement basic I2C functions
  2017-08-20 17:23 [Qemu-devel] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
                   ` (13 preceding siblings ...)
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 15/15] ppc: Add aCube Sam460ex board BALATON Zoltan
@ 2017-08-20 17:23 ` BALATON Zoltan
  2017-08-27 12:34 ` [Qemu-devel] [Qemu-ppc] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
  15 siblings, 0 replies; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-20 17:23 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

Enough to please U-Boot and make it able to detect SDRAM SPD EEPROMs

Signed-off-by: François Revol <revol@free.fr>
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/i2c/ppc4xx_i2c.c         | 210 ++++++++++++++++++++++++++++++++++++++------
 include/hw/i2c/ppc4xx_i2c.h |   3 +
 2 files changed, 184 insertions(+), 29 deletions(-)

diff --git a/hw/i2c/ppc4xx_i2c.c b/hw/i2c/ppc4xx_i2c.c
index 5a6bde9..63c4020 100644
--- a/hw/i2c/ppc4xx_i2c.c
+++ b/hw/i2c/ppc4xx_i2c.c
@@ -2,6 +2,8 @@
  * PPC4xx I2C controller emulation
  *
  * Copyright (c) 2007 Jocelyn Mayer
+ * Copyright (c) 2012 François Revol
+ * Copyright (c) 2016 BALATON Zoltan
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -25,26 +27,128 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "qemu-common.h"
+#include "qemu/log.h"
 #include "cpu.h"
 #include "hw/hw.h"
 #include "hw/i2c/ppc4xx_i2c.h"
 
 /*#define DEBUG_I2C*/
 
-#define PPC4xx_I2C_MEM_SIZE 0x11
+#ifdef DEBUG_I2C
+#define DPRINTF(fmt, args...) printf("[%s]%s: " fmt, TYPE_PPC4xx_I2C, \
+                                     __func__, ##args);
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+#define PPC4xx_I2C_MEM_SIZE 0x12
+
+#define IIC_CNTL_PT         (1 << 0)
+#define IIC_CNTL_READ       (1 << 1)
+#define IIC_CNTL_CHT        (1 << 2)
+#define IIC_CNTL_RPST       (1 << 3)
+
+#define IIC_STS_PT          (1 << 0)
+#define IIC_STS_ERR         (1 << 2)
+#define IIC_STS_MDBS        (1 << 5)
+
+#define IIC_EXTSTS_XFRA     (1 << 0)
+
+#define IIC_XTCNTLSS_SRST   (1 << 0)
+
+static void ppc4xx_i2c_reset(DeviceState *s)
+{
+    PPC4xxI2CState *i2c = PPC4xx_I2C(s);
+
+    /* FIXME: Should also reset bus?
+     *if (s->address != ADDR_RESET) {
+     *    i2c_end_transfer(s->bus);
+     *}
+     */
+
+    i2c->mdata = 0;
+    i2c->lmadr = 0;
+    i2c->hmadr = 0;
+    i2c->cntl = 0;
+    i2c->mdcntl = 0;
+    i2c->sts = 0;
+    i2c->extsts = 0x8f;
+    i2c->sdata = 0;
+    i2c->lsadr = 0;
+    i2c->hsadr = 0;
+    i2c->clkdiv = 0;
+    i2c->intrmsk = 0;
+    i2c->xfrcnt = 0;
+    i2c->xtcntlss = 0;
+    i2c->directcntl = 0x0f;
+    i2c->intr = 0;
+}
+
+static inline bool ppc4xx_i2c_is_master(PPC4xxI2CState *i2c)
+{
+    return true;
+}
 
 static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size)
 {
     PPC4xxI2CState *i2c = PPC4xx_I2C(opaque);
     uint64_t ret;
 
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
     switch (addr) {
     case 0x00:
-        /*i2c_readbyte(&i2c->mdata);*/
         ret = i2c->mdata;
+        if (ppc4xx_i2c_is_master(i2c)) {
+            ret = 0xff;
+
+            if (!(i2c->sts & IIC_STS_MDBS)) {
+                qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to read "
+                              "without starting transfer\n",
+                              TYPE_PPC4xx_I2C, __func__);
+            } else {
+                int pending = (i2c->cntl >> 4) & 3;
+
+                /* get the next byte */
+                int byte = i2c_recv(i2c->bus);
+                DPRINTF("received byte %04x\n", byte);
+
+                if (byte < 0) {
+                    qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: read failed "
+                                  "for device 0x%02x\n", TYPE_PPC4xx_I2C,
+                                  __func__, i2c->lmadr);
+                    ret = 0xff;
+                } else {
+                    ret = byte;
+                    /* Raise interrupt if enabled */
+                    /*ppc4xx_i2c_raise_interrupt(i2c)*/;
+                }
+
+                if (!pending) {
+                    i2c->sts &= ~IIC_STS_MDBS;
+                    /*i2c_end_transfer(i2c->bus);*/
+                /*} else if (i2c->cntl & (IIC_CNTL_RPST | IIC_CNTL_CHT)) {*/
+                } else if (pending) {
+                    /* current smbus implementation doesn't like
+                       multibyte xfer repeated start */
+                    i2c_end_transfer(i2c->bus);
+                    if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 1)) {
+                        /* if non zero is returned, the adress is not valid */
+                        i2c->sts &= ~IIC_STS_PT;
+                        i2c->sts |= IIC_STS_ERR;
+                        i2c->extsts |= IIC_EXTSTS_XFRA;
+                    } else {
+                        /*i2c->sts |= IIC_STS_PT;*/
+                        i2c->sts |= IIC_STS_MDBS;
+                        i2c->sts &= ~IIC_STS_ERR;
+                        i2c->extsts = 0;
+                    }
+                }
+                pending--;
+                i2c->cntl = (i2c->cntl & 0xcf) | (pending << 4);
+            }
+        } else {
+            qemu_log_mask(LOG_UNIMP, "[%s]%s: slave mode not implemented\n",
+                          TYPE_PPC4xx_I2C, __func__);
+        }
         break;
     case 0x02:
         ret = i2c->sdata;
@@ -88,13 +192,15 @@ static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size)
     case 0x10:
         ret = i2c->directcntl;
         break;
+    case 0x11:
+        ret = i2c->intr;
+        break;
     default:
-        ret = 0x00;
+        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
+                      HWADDR_PRIx "\n", TYPE_PPC4xx_I2C, __func__, addr);
+        ret = 0;
         break;
     }
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " %02" PRIx64 "\n", __func__, addr, ret);
-#endif
 
     return ret;
 }
@@ -103,26 +209,74 @@ static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
                               unsigned int size)
 {
     PPC4xxI2CState *i2c = opaque;
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx64 "\n",
-           __func__, addr, value);
-#endif
+
     switch (addr) {
     case 0x00:
         i2c->mdata = value;
-        /*i2c_sendbyte(&i2c->mdata);*/
+        if (!i2c_bus_busy(i2c->bus)) {
+            /* assume we start a write transfer */
+            if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 0)) {
+                /* if non zero is returned, the adress is not valid */
+                i2c->sts &= ~IIC_STS_PT;
+                i2c->sts |= IIC_STS_ERR;
+                i2c->extsts |= IIC_EXTSTS_XFRA;
+            } else {
+                i2c->sts |= IIC_STS_PT;
+                i2c->sts &= ~IIC_STS_ERR;
+                i2c->extsts = 0;
+            }
+        }
+        if (i2c_bus_busy(i2c->bus)) {
+            DPRINTF("sending byte %02x\n", i2c->mdata);
+            if (i2c_send(i2c->bus, i2c->mdata)) {
+                /* if the target return non zero then end the transfer */
+                i2c->sts &= ~IIC_STS_PT;
+                i2c->sts |= IIC_STS_ERR;
+                i2c->extsts |= IIC_EXTSTS_XFRA;
+                i2c_end_transfer(i2c->bus);
+            }
+        }
         break;
     case 0x02:
         i2c->sdata = value;
         break;
     case 0x04:
         i2c->lmadr = value;
+        if (i2c_bus_busy(i2c->bus)) {
+            i2c_end_transfer(i2c->bus);
+        }
+        DPRINTF("%s: device addr %02x\n", __func__, i2c->lmadr);
         break;
     case 0x05:
         i2c->hmadr = value;
         break;
     case 0x06:
         i2c->cntl = value;
+        if (i2c->cntl & IIC_CNTL_PT) {
+            if (i2c->cntl & IIC_CNTL_READ) {
+                DPRINTF("read xfer %d\n", ((i2c->cntl >> 4) & 3) + 1);
+                if (i2c_bus_busy(i2c->bus)) {
+                    /* end previous transfer */
+                    i2c->sts &= ~IIC_STS_PT;
+                    i2c_end_transfer(i2c->bus);
+                }
+                if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 1)) {
+                    /* if non zero is returned, the adress is not valid */
+                    i2c->sts &= ~IIC_STS_PT;
+                    i2c->sts |= IIC_STS_ERR;
+                    i2c->extsts |= IIC_EXTSTS_XFRA;
+                } else {
+                    /*i2c->sts |= IIC_STS_PT;*/
+                    i2c->sts |= IIC_STS_MDBS;
+                    i2c->sts &= ~IIC_STS_ERR;
+                    i2c->extsts = 0;
+                }
+            } else {
+                DPRINTF("write xfer %d\n", ((i2c->cntl >> 4) & 3) + 1);
+                /* we actually already did the write transfer... */
+                i2c->sts &= ~IIC_STS_PT;
+            }
+        }
         break;
     case 0x07:
         i2c->mdcntl = value & 0xDF;
@@ -135,6 +289,7 @@ static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
         break;
     case 0x0A:
         i2c->lsadr = value;
+        /*i2c_set_slave_address(i2c->bus, i2c->lsadr);*/
         break;
     case 0x0B:
         i2c->hsadr = value;
@@ -149,11 +304,23 @@ static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
         i2c->xfrcnt = value & 0x77;
         break;
     case 0x0F:
+        if (value & IIC_XTCNTLSS_SRST) {
+            /* Is it actually a full reset? U-Boot sets some regs before */
+            ppc4xx_i2c_reset(DEVICE(i2c));
+            break;
+        }
         i2c->xtcntlss = value;
         break;
     case 0x10:
         i2c->directcntl = value & 0x7;
         break;
+    case 0x11:
+        i2c->intr = value;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
+                      HWADDR_PRIx "\n", TYPE_PPC4xx_I2C, __func__, addr);
+        break;
     }
 }
 
@@ -167,21 +334,6 @@ static const MemoryRegionOps ppc4xx_i2c_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void ppc4xx_i2c_reset(DeviceState *s)
-{
-    PPC4xxI2CState *i2c = PPC4xx_I2C(s);
-
-    i2c->mdata = 0x00;
-    i2c->sdata = 0x00;
-    i2c->cntl = 0x00;
-    i2c->mdcntl = 0x00;
-    i2c->sts = 0x00;
-    i2c->extsts = 0x00;
-    i2c->clkdiv = 0x00;
-    i2c->xfrcnt = 0x00;
-    i2c->directcntl = 0x0F;
-}
-
 static void ppc4xx_i2c_init(Object *o)
 {
     PPC4xxI2CState *s = PPC4xx_I2C(o);
diff --git a/include/hw/i2c/ppc4xx_i2c.h b/include/hw/i2c/ppc4xx_i2c.h
index e53042f..71fb392 100644
--- a/include/hw/i2c/ppc4xx_i2c.h
+++ b/include/hw/i2c/ppc4xx_i2c.h
@@ -2,6 +2,8 @@
  * PPC4xx I2C controller emulation
  *
  * Copyright (c) 2007 Jocelyn Mayer
+ * Copyright (c) 2012 François Revol
+ * Copyright (c) 2016 BALATON Zoltan
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -56,6 +58,7 @@ typedef struct PPC4xxI2CState {
     uint8_t xfrcnt;
     uint8_t xtcntlss;
     uint8_t directcntl;
+    uint8_t intr;
 } PPC4xxI2CState;
 
 #endif /* PPC4XX_I2C_H */
-- 
2.7.6

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Qemu-devel] [PATCH 05/15] ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file
  2017-08-20 17:23 [Qemu-devel] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
                   ` (3 preceding siblings ...)
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 12/15] ppc4xx: Export ECB and PLB emulation BALATON Zoltan
@ 2017-08-20 17:23 ` BALATON Zoltan
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 11/15] ppc: Add 460EX embedded CPU BALATON Zoltan
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-20 17:23 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

This device appears in other SoCs as well not just in 405 ones and
subsequent patches will modify it, so move it out of ppc405_uc.c in
preparation

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/ppc/Makefile.objs |   2 +-
 hw/ppc/ppc405.h      |   2 +
 hw/ppc/ppc405_uc.c   | 241 ---------------------------------------------
 hw/ppc/ppc4xx_i2c.c  | 272 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 275 insertions(+), 242 deletions(-)
 create mode 100644 hw/ppc/ppc4xx_i2c.c

diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 7efc686..2077216 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -13,7 +13,7 @@ endif
 obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o
 # PowerPC 4xx boards
 obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
-obj-y += ppc4xx_pci.o
+obj-y += ppc4xx_pci.o ppc4xx_i2c.o
 # PReP
 obj-$(CONFIG_PREP) += prep.o
 obj-$(CONFIG_PREP) += prep_systemio.o
diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index a9ffc87..61ec739 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -59,6 +59,8 @@ struct ppc4xx_bd_info_t {
 ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
                                 uint32_t flags);
 
+void ppc405_i2c_init(hwaddr base, qemu_irq irq);
+
 CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
                         MemoryRegion ram_memories[4],
                         hwaddr ram_bases[4],
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 03856d5..3925e4c 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -40,7 +40,6 @@
 //#define DEBUG_GPIO
 //#define DEBUG_SERIAL
 //#define DEBUG_OCM
-//#define DEBUG_I2C
 //#define DEBUG_GPT
 //#define DEBUG_CLOCKS
 //#define DEBUG_CLOCKS_LL
@@ -993,246 +992,6 @@ static void ppc405_ocm_init(CPUPPCState *env)
 }
 
 /*****************************************************************************/
-/* I2C controller */
-typedef struct ppc4xx_i2c_t ppc4xx_i2c_t;
-struct ppc4xx_i2c_t {
-    qemu_irq irq;
-    MemoryRegion iomem;
-    uint8_t mdata;
-    uint8_t lmadr;
-    uint8_t hmadr;
-    uint8_t cntl;
-    uint8_t mdcntl;
-    uint8_t sts;
-    uint8_t extsts;
-    uint8_t sdata;
-    uint8_t lsadr;
-    uint8_t hsadr;
-    uint8_t clkdiv;
-    uint8_t intrmsk;
-    uint8_t xfrcnt;
-    uint8_t xtcntlss;
-    uint8_t directcntl;
-};
-
-static uint32_t ppc4xx_i2c_readb (void *opaque, hwaddr addr)
-{
-    ppc4xx_i2c_t *i2c;
-    uint32_t ret;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    i2c = opaque;
-    switch (addr) {
-    case 0x00:
-        //        i2c_readbyte(&i2c->mdata);
-        ret = i2c->mdata;
-        break;
-    case 0x02:
-        ret = i2c->sdata;
-        break;
-    case 0x04:
-        ret = i2c->lmadr;
-        break;
-    case 0x05:
-        ret = i2c->hmadr;
-        break;
-    case 0x06:
-        ret = i2c->cntl;
-        break;
-    case 0x07:
-        ret = i2c->mdcntl;
-        break;
-    case 0x08:
-        ret = i2c->sts;
-        break;
-    case 0x09:
-        ret = i2c->extsts;
-        break;
-    case 0x0A:
-        ret = i2c->lsadr;
-        break;
-    case 0x0B:
-        ret = i2c->hsadr;
-        break;
-    case 0x0C:
-        ret = i2c->clkdiv;
-        break;
-    case 0x0D:
-        ret = i2c->intrmsk;
-        break;
-    case 0x0E:
-        ret = i2c->xfrcnt;
-        break;
-    case 0x0F:
-        ret = i2c->xtcntlss;
-        break;
-    case 0x10:
-        ret = i2c->directcntl;
-        break;
-    default:
-        ret = 0x00;
-        break;
-    }
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__, addr, ret);
-#endif
-
-    return ret;
-}
-
-static void ppc4xx_i2c_writeb (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-    ppc4xx_i2c_t *i2c;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    i2c = opaque;
-    switch (addr) {
-    case 0x00:
-        i2c->mdata = value;
-        //        i2c_sendbyte(&i2c->mdata);
-        break;
-    case 0x02:
-        i2c->sdata = value;
-        break;
-    case 0x04:
-        i2c->lmadr = value;
-        break;
-    case 0x05:
-        i2c->hmadr = value;
-        break;
-    case 0x06:
-        i2c->cntl = value;
-        break;
-    case 0x07:
-        i2c->mdcntl = value & 0xDF;
-        break;
-    case 0x08:
-        i2c->sts &= ~(value & 0x0A);
-        break;
-    case 0x09:
-        i2c->extsts &= ~(value & 0x8F);
-        break;
-    case 0x0A:
-        i2c->lsadr = value;
-        break;
-    case 0x0B:
-        i2c->hsadr = value;
-        break;
-    case 0x0C:
-        i2c->clkdiv = value;
-        break;
-    case 0x0D:
-        i2c->intrmsk = value;
-        break;
-    case 0x0E:
-        i2c->xfrcnt = value & 0x77;
-        break;
-    case 0x0F:
-        i2c->xtcntlss = value;
-        break;
-    case 0x10:
-        i2c->directcntl = value & 0x7;
-        break;
-    }
-}
-
-static uint32_t ppc4xx_i2c_readw (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    ret = ppc4xx_i2c_readb(opaque, addr) << 8;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 1);
-
-    return ret;
-}
-
-static void ppc4xx_i2c_writew (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    ppc4xx_i2c_writeb(opaque, addr, value >> 8);
-    ppc4xx_i2c_writeb(opaque, addr + 1, value);
-}
-
-static uint32_t ppc4xx_i2c_readl (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    ret = ppc4xx_i2c_readb(opaque, addr) << 24;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 3);
-
-    return ret;
-}
-
-static void ppc4xx_i2c_writel (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    ppc4xx_i2c_writeb(opaque, addr, value >> 24);
-    ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16);
-    ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8);
-    ppc4xx_i2c_writeb(opaque, addr + 3, value);
-}
-
-static const MemoryRegionOps i2c_ops = {
-    .old_mmio = {
-        .read = { ppc4xx_i2c_readb, ppc4xx_i2c_readw, ppc4xx_i2c_readl, },
-        .write = { ppc4xx_i2c_writeb, ppc4xx_i2c_writew, ppc4xx_i2c_writel, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void ppc4xx_i2c_reset (void *opaque)
-{
-    ppc4xx_i2c_t *i2c;
-
-    i2c = opaque;
-    i2c->mdata = 0x00;
-    i2c->sdata = 0x00;
-    i2c->cntl = 0x00;
-    i2c->mdcntl = 0x00;
-    i2c->sts = 0x00;
-    i2c->extsts = 0x00;
-    i2c->clkdiv = 0x00;
-    i2c->xfrcnt = 0x00;
-    i2c->directcntl = 0x0F;
-}
-
-static void ppc405_i2c_init(hwaddr base, qemu_irq irq)
-{
-    ppc4xx_i2c_t *i2c;
-
-    i2c = g_malloc0(sizeof(ppc4xx_i2c_t));
-    i2c->irq = irq;
-#ifdef DEBUG_I2C
-    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
-#endif
-    memory_region_init_io(&i2c->iomem, NULL, &i2c_ops, i2c, "i2c", 0x011);
-    memory_region_add_subregion(get_system_memory(), base, &i2c->iomem);
-    qemu_register_reset(ppc4xx_i2c_reset, i2c);
-}
-
-/*****************************************************************************/
 /* General purpose timers */
 typedef struct ppc4xx_gpt_t ppc4xx_gpt_t;
 struct ppc4xx_gpt_t {
diff --git a/hw/ppc/ppc4xx_i2c.c b/hw/ppc/ppc4xx_i2c.c
new file mode 100644
index 0000000..15f2dea
--- /dev/null
+++ b/hw/ppc/ppc4xx_i2c.c
@@ -0,0 +1,272 @@
+/*
+ * PPC4xx I2C controller emulation
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "hw/hw.h"
+#include "exec/address-spaces.h"
+#include "hw/ppc/ppc.h"
+#include "ppc405.h"
+
+/*#define DEBUG_I2C*/
+
+typedef struct ppc4xx_i2c_t ppc4xx_i2c_t;
+struct ppc4xx_i2c_t {
+    qemu_irq irq;
+    MemoryRegion iomem;
+    uint8_t mdata;
+    uint8_t lmadr;
+    uint8_t hmadr;
+    uint8_t cntl;
+    uint8_t mdcntl;
+    uint8_t sts;
+    uint8_t extsts;
+    uint8_t sdata;
+    uint8_t lsadr;
+    uint8_t hsadr;
+    uint8_t clkdiv;
+    uint8_t intrmsk;
+    uint8_t xfrcnt;
+    uint8_t xtcntlss;
+    uint8_t directcntl;
+};
+
+static uint32_t ppc4xx_i2c_readb(void *opaque, hwaddr addr)
+{
+    ppc4xx_i2c_t *i2c;
+    uint32_t ret;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    i2c = opaque;
+    switch (addr) {
+    case 0x00:
+        /*i2c_readbyte(&i2c->mdata);*/
+        ret = i2c->mdata;
+        break;
+    case 0x02:
+        ret = i2c->sdata;
+        break;
+    case 0x04:
+        ret = i2c->lmadr;
+        break;
+    case 0x05:
+        ret = i2c->hmadr;
+        break;
+    case 0x06:
+        ret = i2c->cntl;
+        break;
+    case 0x07:
+        ret = i2c->mdcntl;
+        break;
+    case 0x08:
+        ret = i2c->sts;
+        break;
+    case 0x09:
+        ret = i2c->extsts;
+        break;
+    case 0x0A:
+        ret = i2c->lsadr;
+        break;
+    case 0x0B:
+        ret = i2c->hsadr;
+        break;
+    case 0x0C:
+        ret = i2c->clkdiv;
+        break;
+    case 0x0D:
+        ret = i2c->intrmsk;
+        break;
+    case 0x0E:
+        ret = i2c->xfrcnt;
+        break;
+    case 0x0F:
+        ret = i2c->xtcntlss;
+        break;
+    case 0x10:
+        ret = i2c->directcntl;
+        break;
+    default:
+        ret = 0x00;
+        break;
+    }
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__, addr, ret);
+#endif
+
+    return ret;
+}
+
+static void ppc4xx_i2c_writeb(void *opaque,
+                              hwaddr addr, uint32_t value)
+{
+    ppc4xx_i2c_t *i2c;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    i2c = opaque;
+    switch (addr) {
+    case 0x00:
+        i2c->mdata = value;
+        /*i2c_sendbyte(&i2c->mdata);*/
+        break;
+    case 0x02:
+        i2c->sdata = value;
+        break;
+    case 0x04:
+        i2c->lmadr = value;
+        break;
+    case 0x05:
+        i2c->hmadr = value;
+        break;
+    case 0x06:
+        i2c->cntl = value;
+        break;
+    case 0x07:
+        i2c->mdcntl = value & 0xDF;
+        break;
+    case 0x08:
+        i2c->sts &= ~(value & 0x0A);
+        break;
+    case 0x09:
+        i2c->extsts &= ~(value & 0x8F);
+        break;
+    case 0x0A:
+        i2c->lsadr = value;
+        break;
+    case 0x0B:
+        i2c->hsadr = value;
+        break;
+    case 0x0C:
+        i2c->clkdiv = value;
+        break;
+    case 0x0D:
+        i2c->intrmsk = value;
+        break;
+    case 0x0E:
+        i2c->xfrcnt = value & 0x77;
+        break;
+    case 0x0F:
+        i2c->xtcntlss = value;
+        break;
+    case 0x10:
+        i2c->directcntl = value & 0x7;
+        break;
+    }
+}
+
+static uint32_t ppc4xx_i2c_readw(void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    ret = ppc4xx_i2c_readb(opaque, addr) << 8;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 1);
+
+    return ret;
+}
+
+static void ppc4xx_i2c_writew(void *opaque,
+                              hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    ppc4xx_i2c_writeb(opaque, addr, value >> 8);
+    ppc4xx_i2c_writeb(opaque, addr + 1, value);
+}
+
+static uint32_t ppc4xx_i2c_readl(void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    ret = ppc4xx_i2c_readb(opaque, addr) << 24;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 3);
+
+    return ret;
+}
+
+static void ppc4xx_i2c_writel(void *opaque,
+                              hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    ppc4xx_i2c_writeb(opaque, addr, value >> 24);
+    ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16);
+    ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8);
+    ppc4xx_i2c_writeb(opaque, addr + 3, value);
+}
+
+static const MemoryRegionOps i2c_ops = {
+    .old_mmio = {
+        .read = { ppc4xx_i2c_readb, ppc4xx_i2c_readw, ppc4xx_i2c_readl, },
+        .write = { ppc4xx_i2c_writeb, ppc4xx_i2c_writew, ppc4xx_i2c_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void ppc4xx_i2c_reset(void *opaque)
+{
+    ppc4xx_i2c_t *i2c;
+
+    i2c = opaque;
+    i2c->mdata = 0x00;
+    i2c->sdata = 0x00;
+    i2c->cntl = 0x00;
+    i2c->mdcntl = 0x00;
+    i2c->sts = 0x00;
+    i2c->extsts = 0x00;
+    i2c->clkdiv = 0x00;
+    i2c->xfrcnt = 0x00;
+    i2c->directcntl = 0x0F;
+}
+
+void ppc405_i2c_init(hwaddr base, qemu_irq irq)
+{
+    ppc4xx_i2c_t *i2c;
+
+    i2c = g_malloc0(sizeof(ppc4xx_i2c_t));
+    i2c->irq = irq;
+#ifdef DEBUG_I2C
+    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
+#endif
+    memory_region_init_io(&i2c->iomem, NULL, &i2c_ops, i2c, "i2c", 0x011);
+    memory_region_add_subregion(get_system_memory(), base, &i2c->iomem);
+    qemu_register_reset(ppc4xx_i2c_reset, i2c);
+}
-- 
2.7.6

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Qemu-devel] [PATCH 01/15] ppc4xx: Move MAL from ppc405_uc to ppc4xx_devs
  2017-08-20 17:23 [Qemu-devel] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
                   ` (10 preceding siblings ...)
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 14/15] ppc4xx: Add device models found in PPC440 core SoCs BALATON Zoltan
@ 2017-08-20 17:23 ` BALATON Zoltan
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 10/15] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs BALATON Zoltan
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-20 17:23 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

This device appears in other SoCs as well not just in 405 ones

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/ppc405_uc.c      | 263 -----------------------------------------------
 hw/ppc/ppc4xx_devs.c    | 264 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/hw/ppc/ppc4xx.h |   2 +
 3 files changed, 266 insertions(+), 263 deletions(-)

diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index f6fe3e6..3c74402 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -42,7 +42,6 @@
 //#define DEBUG_OCM
 //#define DEBUG_I2C
 //#define DEBUG_GPT
-//#define DEBUG_MAL
 //#define DEBUG_CLOCKS
 //#define DEBUG_CLOCKS_LL
 
@@ -1513,268 +1512,6 @@ static void ppc4xx_gpt_init(hwaddr base, qemu_irq irqs[5])
 }
 
 /*****************************************************************************/
-/* MAL */
-enum {
-    MAL0_CFG      = 0x180,
-    MAL0_ESR      = 0x181,
-    MAL0_IER      = 0x182,
-    MAL0_TXCASR   = 0x184,
-    MAL0_TXCARR   = 0x185,
-    MAL0_TXEOBISR = 0x186,
-    MAL0_TXDEIR   = 0x187,
-    MAL0_RXCASR   = 0x190,
-    MAL0_RXCARR   = 0x191,
-    MAL0_RXEOBISR = 0x192,
-    MAL0_RXDEIR   = 0x193,
-    MAL0_TXCTP0R  = 0x1A0,
-    MAL0_TXCTP1R  = 0x1A1,
-    MAL0_TXCTP2R  = 0x1A2,
-    MAL0_TXCTP3R  = 0x1A3,
-    MAL0_RXCTP0R  = 0x1C0,
-    MAL0_RXCTP1R  = 0x1C1,
-    MAL0_RCBS0    = 0x1E0,
-    MAL0_RCBS1    = 0x1E1,
-};
-
-typedef struct ppc40x_mal_t ppc40x_mal_t;
-struct ppc40x_mal_t {
-    qemu_irq irqs[4];
-    uint32_t cfg;
-    uint32_t esr;
-    uint32_t ier;
-    uint32_t txcasr;
-    uint32_t txcarr;
-    uint32_t txeobisr;
-    uint32_t txdeir;
-    uint32_t rxcasr;
-    uint32_t rxcarr;
-    uint32_t rxeobisr;
-    uint32_t rxdeir;
-    uint32_t txctpr[4];
-    uint32_t rxctpr[2];
-    uint32_t rcbs[2];
-};
-
-static void ppc40x_mal_reset (void *opaque);
-
-static uint32_t dcr_read_mal (void *opaque, int dcrn)
-{
-    ppc40x_mal_t *mal;
-    uint32_t ret;
-
-    mal = opaque;
-    switch (dcrn) {
-    case MAL0_CFG:
-        ret = mal->cfg;
-        break;
-    case MAL0_ESR:
-        ret = mal->esr;
-        break;
-    case MAL0_IER:
-        ret = mal->ier;
-        break;
-    case MAL0_TXCASR:
-        ret = mal->txcasr;
-        break;
-    case MAL0_TXCARR:
-        ret = mal->txcarr;
-        break;
-    case MAL0_TXEOBISR:
-        ret = mal->txeobisr;
-        break;
-    case MAL0_TXDEIR:
-        ret = mal->txdeir;
-        break;
-    case MAL0_RXCASR:
-        ret = mal->rxcasr;
-        break;
-    case MAL0_RXCARR:
-        ret = mal->rxcarr;
-        break;
-    case MAL0_RXEOBISR:
-        ret = mal->rxeobisr;
-        break;
-    case MAL0_RXDEIR:
-        ret = mal->rxdeir;
-        break;
-    case MAL0_TXCTP0R:
-        ret = mal->txctpr[0];
-        break;
-    case MAL0_TXCTP1R:
-        ret = mal->txctpr[1];
-        break;
-    case MAL0_TXCTP2R:
-        ret = mal->txctpr[2];
-        break;
-    case MAL0_TXCTP3R:
-        ret = mal->txctpr[3];
-        break;
-    case MAL0_RXCTP0R:
-        ret = mal->rxctpr[0];
-        break;
-    case MAL0_RXCTP1R:
-        ret = mal->rxctpr[1];
-        break;
-    case MAL0_RCBS0:
-        ret = mal->rcbs[0];
-        break;
-    case MAL0_RCBS1:
-        ret = mal->rcbs[1];
-        break;
-    default:
-        ret = 0;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_mal (void *opaque, int dcrn, uint32_t val)
-{
-    ppc40x_mal_t *mal;
-    int idx;
-
-    mal = opaque;
-    switch (dcrn) {
-    case MAL0_CFG:
-        if (val & 0x80000000)
-            ppc40x_mal_reset(mal);
-        mal->cfg = val & 0x00FFC087;
-        break;
-    case MAL0_ESR:
-        /* Read/clear */
-        mal->esr &= ~val;
-        break;
-    case MAL0_IER:
-        mal->ier = val & 0x0000001F;
-        break;
-    case MAL0_TXCASR:
-        mal->txcasr = val & 0xF0000000;
-        break;
-    case MAL0_TXCARR:
-        mal->txcarr = val & 0xF0000000;
-        break;
-    case MAL0_TXEOBISR:
-        /* Read/clear */
-        mal->txeobisr &= ~val;
-        break;
-    case MAL0_TXDEIR:
-        /* Read/clear */
-        mal->txdeir &= ~val;
-        break;
-    case MAL0_RXCASR:
-        mal->rxcasr = val & 0xC0000000;
-        break;
-    case MAL0_RXCARR:
-        mal->rxcarr = val & 0xC0000000;
-        break;
-    case MAL0_RXEOBISR:
-        /* Read/clear */
-        mal->rxeobisr &= ~val;
-        break;
-    case MAL0_RXDEIR:
-        /* Read/clear */
-        mal->rxdeir &= ~val;
-        break;
-    case MAL0_TXCTP0R:
-        idx = 0;
-        goto update_tx_ptr;
-    case MAL0_TXCTP1R:
-        idx = 1;
-        goto update_tx_ptr;
-    case MAL0_TXCTP2R:
-        idx = 2;
-        goto update_tx_ptr;
-    case MAL0_TXCTP3R:
-        idx = 3;
-    update_tx_ptr:
-        mal->txctpr[idx] = val;
-        break;
-    case MAL0_RXCTP0R:
-        idx = 0;
-        goto update_rx_ptr;
-    case MAL0_RXCTP1R:
-        idx = 1;
-    update_rx_ptr:
-        mal->rxctpr[idx] = val;
-        break;
-    case MAL0_RCBS0:
-        idx = 0;
-        goto update_rx_size;
-    case MAL0_RCBS1:
-        idx = 1;
-    update_rx_size:
-        mal->rcbs[idx] = val & 0x000000FF;
-        break;
-    }
-}
-
-static void ppc40x_mal_reset (void *opaque)
-{
-    ppc40x_mal_t *mal;
-
-    mal = opaque;
-    mal->cfg = 0x0007C000;
-    mal->esr = 0x00000000;
-    mal->ier = 0x00000000;
-    mal->rxcasr = 0x00000000;
-    mal->rxdeir = 0x00000000;
-    mal->rxeobisr = 0x00000000;
-    mal->txcasr = 0x00000000;
-    mal->txdeir = 0x00000000;
-    mal->txeobisr = 0x00000000;
-}
-
-static void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
-{
-    ppc40x_mal_t *mal;
-    int i;
-
-    mal = g_malloc0(sizeof(ppc40x_mal_t));
-    for (i = 0; i < 4; i++)
-        mal->irqs[i] = irqs[i];
-    qemu_register_reset(&ppc40x_mal_reset, mal);
-    ppc_dcr_register(env, MAL0_CFG,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_ESR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_IER,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCASR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCARR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXEOBISR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXDEIR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCASR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCARR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXEOBISR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXDEIR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP0R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP1R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP2R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP3R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCTP0R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCTP1R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RCBS0,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RCBS1,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-}
-
-/*****************************************************************************/
 /* SPR */
 void ppc40x_core_reset(PowerPCCPU *cpu)
 {
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index e7f413e..8e4f78e 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -734,3 +734,267 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
 
     return ram_size;
 }
+
+/*****************************************************************************/
+/* MAL */
+enum {
+    MAL0_CFG      = 0x180,
+    MAL0_ESR      = 0x181,
+    MAL0_IER      = 0x182,
+    MAL0_TXCASR   = 0x184,
+    MAL0_TXCARR   = 0x185,
+    MAL0_TXEOBISR = 0x186,
+    MAL0_TXDEIR   = 0x187,
+    MAL0_RXCASR   = 0x190,
+    MAL0_RXCARR   = 0x191,
+    MAL0_RXEOBISR = 0x192,
+    MAL0_RXDEIR   = 0x193,
+    MAL0_TXCTP0R  = 0x1A0,
+    MAL0_TXCTP1R  = 0x1A1,
+    MAL0_TXCTP2R  = 0x1A2,
+    MAL0_TXCTP3R  = 0x1A3,
+    MAL0_RXCTP0R  = 0x1C0,
+    MAL0_RXCTP1R  = 0x1C1,
+    MAL0_RCBS0    = 0x1E0,
+    MAL0_RCBS1    = 0x1E1,
+};
+
+typedef struct ppc40x_mal_t ppc40x_mal_t;
+struct ppc40x_mal_t {
+    qemu_irq irqs[4];
+    uint32_t cfg;
+    uint32_t esr;
+    uint32_t ier;
+    uint32_t txcasr;
+    uint32_t txcarr;
+    uint32_t txeobisr;
+    uint32_t txdeir;
+    uint32_t rxcasr;
+    uint32_t rxcarr;
+    uint32_t rxeobisr;
+    uint32_t rxdeir;
+    uint32_t txctpr[4];
+    uint32_t rxctpr[2];
+    uint32_t rcbs[2];
+};
+
+static void ppc40x_mal_reset(void *opaque);
+
+static uint32_t dcr_read_mal(void *opaque, int dcrn)
+{
+    ppc40x_mal_t *mal;
+    uint32_t ret;
+
+    mal = opaque;
+    switch (dcrn) {
+    case MAL0_CFG:
+        ret = mal->cfg;
+        break;
+    case MAL0_ESR:
+        ret = mal->esr;
+        break;
+    case MAL0_IER:
+        ret = mal->ier;
+        break;
+    case MAL0_TXCASR:
+        ret = mal->txcasr;
+        break;
+    case MAL0_TXCARR:
+        ret = mal->txcarr;
+        break;
+    case MAL0_TXEOBISR:
+        ret = mal->txeobisr;
+        break;
+    case MAL0_TXDEIR:
+        ret = mal->txdeir;
+        break;
+    case MAL0_RXCASR:
+        ret = mal->rxcasr;
+        break;
+    case MAL0_RXCARR:
+        ret = mal->rxcarr;
+        break;
+    case MAL0_RXEOBISR:
+        ret = mal->rxeobisr;
+        break;
+    case MAL0_RXDEIR:
+        ret = mal->rxdeir;
+        break;
+    case MAL0_TXCTP0R:
+        ret = mal->txctpr[0];
+        break;
+    case MAL0_TXCTP1R:
+        ret = mal->txctpr[1];
+        break;
+    case MAL0_TXCTP2R:
+        ret = mal->txctpr[2];
+        break;
+    case MAL0_TXCTP3R:
+        ret = mal->txctpr[3];
+        break;
+    case MAL0_RXCTP0R:
+        ret = mal->rxctpr[0];
+        break;
+    case MAL0_RXCTP1R:
+        ret = mal->rxctpr[1];
+        break;
+    case MAL0_RCBS0:
+        ret = mal->rcbs[0];
+        break;
+    case MAL0_RCBS1:
+        ret = mal->rcbs[1];
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
+{
+    ppc40x_mal_t *mal;
+    int idx;
+
+    mal = opaque;
+    switch (dcrn) {
+    case MAL0_CFG:
+        if (val & 0x80000000) {
+            ppc40x_mal_reset(mal);
+        }
+        mal->cfg = val & 0x00FFC087;
+        break;
+    case MAL0_ESR:
+        /* Read/clear */
+        mal->esr &= ~val;
+        break;
+    case MAL0_IER:
+        mal->ier = val & 0x0000001F;
+        break;
+    case MAL0_TXCASR:
+        mal->txcasr = val & 0xF0000000;
+        break;
+    case MAL0_TXCARR:
+        mal->txcarr = val & 0xF0000000;
+        break;
+    case MAL0_TXEOBISR:
+        /* Read/clear */
+        mal->txeobisr &= ~val;
+        break;
+    case MAL0_TXDEIR:
+        /* Read/clear */
+        mal->txdeir &= ~val;
+        break;
+    case MAL0_RXCASR:
+        mal->rxcasr = val & 0xC0000000;
+        break;
+    case MAL0_RXCARR:
+        mal->rxcarr = val & 0xC0000000;
+        break;
+    case MAL0_RXEOBISR:
+        /* Read/clear */
+        mal->rxeobisr &= ~val;
+        break;
+    case MAL0_RXDEIR:
+        /* Read/clear */
+        mal->rxdeir &= ~val;
+        break;
+    case MAL0_TXCTP0R:
+        idx = 0;
+        goto update_tx_ptr;
+    case MAL0_TXCTP1R:
+        idx = 1;
+        goto update_tx_ptr;
+    case MAL0_TXCTP2R:
+        idx = 2;
+        goto update_tx_ptr;
+    case MAL0_TXCTP3R:
+        idx = 3;
+    update_tx_ptr:
+        mal->txctpr[idx] = val;
+        break;
+    case MAL0_RXCTP0R:
+        idx = 0;
+        goto update_rx_ptr;
+    case MAL0_RXCTP1R:
+        idx = 1;
+    update_rx_ptr:
+        mal->rxctpr[idx] = val;
+        break;
+    case MAL0_RCBS0:
+        idx = 0;
+        goto update_rx_size;
+    case MAL0_RCBS1:
+        idx = 1;
+    update_rx_size:
+        mal->rcbs[idx] = val & 0x000000FF;
+        break;
+    }
+}
+
+static void ppc40x_mal_reset(void *opaque)
+{
+    ppc40x_mal_t *mal;
+
+    mal = opaque;
+    mal->cfg = 0x0007C000;
+    mal->esr = 0x00000000;
+    mal->ier = 0x00000000;
+    mal->rxcasr = 0x00000000;
+    mal->rxdeir = 0x00000000;
+    mal->rxeobisr = 0x00000000;
+    mal->txcasr = 0x00000000;
+    mal->txdeir = 0x00000000;
+    mal->txeobisr = 0x00000000;
+}
+
+void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
+{
+    ppc40x_mal_t *mal;
+    int i;
+
+    mal = g_malloc0(sizeof(ppc40x_mal_t));
+    for (i = 0; i < 4; i++) {
+        mal->irqs[i] = irqs[i];
+    }
+    qemu_register_reset(&ppc40x_mal_reset, mal);
+    ppc_dcr_register(env, MAL0_CFG,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_ESR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_IER,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCASR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCARR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXEOBISR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXDEIR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXCASR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXCARR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXEOBISR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXDEIR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCTP0R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCTP1R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCTP2R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCTP3R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXCTP0R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXCTP1R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RCBS0,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RCBS1,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+}
diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
index 66e57a5..db50cfa 100644
--- a/include/hw/ppc/ppc4xx.h
+++ b/include/hw/ppc/ppc4xx.h
@@ -53,6 +53,8 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
                         hwaddr *ram_sizes,
                         int do_init);
 
+void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4]);
+
 #define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost"
 
 #endif /* PPC4XX_H */
-- 
2.7.6

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Qemu-devel] [PATCH 09/15] hw/ide: Emulate SiI3112 SATA controller
  2017-08-20 17:23 [Qemu-devel] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
                   ` (6 preceding siblings ...)
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 04/15] ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs BALATON Zoltan
@ 2017-08-20 17:23 ` BALATON Zoltan
  2017-08-21 21:14   ` John Snow
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 13/15] ppc4xx: Add more PLB registers BALATON Zoltan
                   ` (7 subsequent siblings)
  15 siblings, 1 reply; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-20 17:23 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: Alexander Graf, David Gibson, Francois Revol, John Snow

This is a common generic PCI SATA conroller that is also used in PCs
but more importantly guests running on the Sam460ex board prefer this
card and have a driver for it (unlike for other SATA controllers
already emulated).

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/ide/Makefile.objs |   1 +
 hw/ide/sii3112.c     | 369 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 370 insertions(+)
 create mode 100644 hw/ide/sii3112.c

diff --git a/hw/ide/Makefile.objs b/hw/ide/Makefile.objs
index 729e9bd..76f3d6d 100644
--- a/hw/ide/Makefile.objs
+++ b/hw/ide/Makefile.objs
@@ -10,3 +10,4 @@ common-obj-$(CONFIG_IDE_VIA) += via.o
 common-obj-$(CONFIG_MICRODRIVE) += microdrive.o
 common-obj-$(CONFIG_AHCI) += ahci.o
 common-obj-$(CONFIG_AHCI) += ich.o
+common-obj-$(CONFIG_IDE_SII3112) += sii3112.o
diff --git a/hw/ide/sii3112.c b/hw/ide/sii3112.c
new file mode 100644
index 0000000..9ec8cd1
--- /dev/null
+++ b/hw/ide/sii3112.c
@@ -0,0 +1,369 @@
+/*
+ * QEMU SiI3112A PCI to Serial ATA Controller Emulation
+ *
+ * Copyright (C) 2017 BALATON Zoltan <balaton@eik.bme.hu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+/* For documentation on this and similar cards see:
+ * http://wiki.osdev.org/User:Quok/Silicon_Image_Datasheets
+ */
+
+#include <qemu/osdep.h>
+#include <hw/ide/pci.h>
+
+#ifdef DEBUG_IDE
+#define DPRINTF(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__);
+#else
+#define DPRINTF(fmt, ...)
+#endif /* DEBUG */
+
+#define TYPE_SII3112_PCI "sii3112"
+#define SII3112_PCI(obj) OBJECT_CHECK(SiI3112PCIState, (obj), \
+                         TYPE_SII3112_PCI)
+
+typedef struct SiI3112Regs {
+    uint32_t confstat;
+    uint32_t scontrol;
+    uint16_t sien;
+    uint8_t swdata;
+} SiI3112Regs;
+
+typedef struct SiI3112PCIState {
+    PCIIDEState i;
+    MemoryRegion mmio;
+    SiI3112Regs regs[2];
+} SiI3112PCIState;
+
+static uint64_t sii3112_reg_read(void *opaque, hwaddr addr,
+                                unsigned int size)
+{
+    SiI3112PCIState *d = opaque;
+    uint64_t val = 0;
+
+    switch (addr) {
+    case 0x00:
+        val = d->i.bmdma[0].cmd;
+        break;
+    case 0x01:
+        val = d->regs[0].swdata;
+        break;
+    case 0x02:
+        val = d->i.bmdma[0].status;
+        break;
+    case 0x03:
+        val = 0;
+        break;
+    case 0x04 ... 0x07:
+        val = bmdma_addr_ioport_ops.read(&d->i.bmdma[0], addr - 4, size);
+        break;
+    case 0x08:
+        val = d->i.bmdma[1].cmd;
+        break;
+    case 0x09:
+        val = d->regs[1].swdata;
+        break;
+    case 0x0a:
+        val = d->i.bmdma[1].status;
+        break;
+    case 0x0b:
+        val = 0;
+        break;
+    case 0x0c ... 0x0f:
+        val = bmdma_addr_ioport_ops.read(&d->i.bmdma[1], addr - 12, size);
+        break;
+    case 0x10:
+        val = d->i.bmdma[0].cmd;
+        val |= (d->regs[0].confstat & (1UL << 11) ? (1 << 4) : 0); /*SATAINT0*/
+        val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 6) : 0); /*SATAINT1*/
+        val |= (d->i.bmdma[1].status & BM_STATUS_INT ? (1 << 14) : 0);
+        val |= d->i.bmdma[0].status << 16;
+        val |= d->i.bmdma[1].status << 24;
+        break;
+    case 0x18:
+        val = d->i.bmdma[1].cmd;
+        val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 4) : 0);
+        val |= d->i.bmdma[1].status << 16;
+        break;
+    case 0x80 ... 0x87:
+        if (size == 1) {
+            val = ide_ioport_read(&d->i.bus[0], addr - 0x80);
+        } else if (addr == 0x80) {
+            val = (size == 2) ? ide_data_readw(&d->i.bus[0], 0) :
+                                ide_data_readl(&d->i.bus[0], 0);
+        } else {
+            val = (1ULL << (size * 8)) - 1;
+        }
+        break;
+    case 0x8a:
+        val = (size == 1) ? ide_status_read(&d->i.bus[0], 4) :
+                            (1ULL << (size * 8)) - 1;
+        break;
+    case 0xa0:
+        val = d->regs[0].confstat;
+        break;
+    case 0xc0 ... 0xc7:
+        if (size == 1) {
+            val = ide_ioport_read(&d->i.bus[1], addr - 0xc0);
+        } else if (addr == 0xc0) {
+            val = (size == 2) ? ide_data_readw(&d->i.bus[1], 0) :
+                                ide_data_readl(&d->i.bus[1], 0);
+        } else {
+            val = (1ULL << (size * 8)) - 1;
+        }
+        break;
+    case 0xca:
+        val = (size == 1) ? ide_status_read(&d->i.bus[0], 4) :
+                            (1ULL << (size * 8)) - 1;
+        break;
+    case 0xe0:
+        val = d->regs[1].confstat;
+        break;
+    case 0x100:
+        val = d->regs[0].scontrol;
+        break;
+    case 0x104:
+        val = (d->i.bus[0].ifs[0].blk) ? 0x113 : 0;
+        break;
+    case 0x148:
+        val = d->regs[0].sien << 16;
+        break;
+    case 0x180:
+        val = d->regs[1].scontrol;
+        break;
+    case 0x184:
+        val = (d->i.bus[1].ifs[0].blk) ? 0x113 : 0;
+        break;
+    case 0x1c8:
+        val = d->regs[1].sien << 16;
+        break;
+    default:
+        val = 0;
+    }
+    DPRINTF("%s: addr 0x%"PRIx64 " size %d = %"PRIx64 "\n",
+            __func__, addr, size, val);
+    return val;
+}
+
+static void sii3112_reg_write(void *opaque, hwaddr addr,
+                              uint64_t val, unsigned int size)
+{
+    SiI3112PCIState *d = opaque;
+
+    DPRINTF("%s: addr 0x%"PRIx64 " size %d = %"PRIx64 "\n",
+            __func__, addr, size, val);
+    switch (addr) {
+    case 0x00:
+    case 0x10:
+        bmdma_cmd_writeb(&d->i.bmdma[0], val);
+        break;
+    case 0x01:
+    case 0x11:
+        d->regs[0].swdata = val & 0x3f;
+        break;
+    case 0x02:
+    case 0x12:
+        d->i.bmdma[0].status = (val & 0x60) | (d->i.bmdma[0].status & 1) |
+                               (d->i.bmdma[0].status & ~val & 6);
+        break;
+    case 0x04 ... 0x07:
+        bmdma_addr_ioport_ops.write(&d->i.bmdma[0], addr - 4, val, size);
+        break;
+    case 0x08:
+    case 0x18:
+        bmdma_cmd_writeb(&d->i.bmdma[1], val);
+        break;
+    case 0x09:
+    case 0x19:
+        d->regs[1].swdata = val & 0x3f;
+        break;
+    case 0x0a:
+    case 0x1a:
+        d->i.bmdma[1].status = (val & 0x60) | (d->i.bmdma[1].status & 1) |
+                               (d->i.bmdma[1].status & ~val & 6);
+        break;
+    case 0x0c ... 0x0f:
+        bmdma_addr_ioport_ops.write(&d->i.bmdma[1], addr - 12, val, size);
+        break;
+    case 0x80 ... 0x87:
+        if (size == 1) {
+            ide_ioport_write(&d->i.bus[0], addr - 0x80, val);
+        } else if (addr == 0x80) {
+            if (size == 2) {
+                ide_data_writew(&d->i.bus[0], 0, val);
+            } else {
+                ide_data_writel(&d->i.bus[0], 0, val);
+            }
+        }
+        break;
+    case 0x8a:
+        if (size == 1) {
+            ide_cmd_write(&d->i.bus[0], 4, val);
+        }
+        break;
+    case 0xc0 ... 0xc7:
+        if (size == 1) {
+            ide_ioport_write(&d->i.bus[1], addr - 0xc0, val);
+        } else if (addr == 0xc0) {
+            if (size == 2) {
+                ide_data_writew(&d->i.bus[1], 0, val);
+            } else {
+                ide_data_writel(&d->i.bus[1], 0, val);
+            }
+        }
+        break;
+    case 0xca:
+        if (size == 1) {
+            ide_cmd_write(&d->i.bus[1], 4, val);
+        }
+        break;
+    case 0x100:
+        d->regs[0].scontrol = val & 0xfff;
+        if (val & 1) {
+            ide_bus_reset(&d->i.bus[0]);
+        }
+        break;
+    case 0x148:
+        d->regs[0].sien = (val >> 16) & 0x3eed;
+        break;
+    case 0x180:
+        d->regs[1].scontrol = val & 0xfff;
+        if (val & 1) {
+            ide_bus_reset(&d->i.bus[1]);
+        }
+        break;
+    case 0x1c8:
+        d->regs[1].sien = (val >> 16) & 0x3eed;
+        break;
+    default:
+        val = 0;
+    }
+}
+
+static const MemoryRegionOps sii3112_reg_ops = {
+    .read = sii3112_reg_read,
+    .write = sii3112_reg_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+/* the PCI irq level is the logical OR of the two channels */
+static void sii3112_update_irq(SiI3112PCIState *s)
+{
+    int i, set = 0;
+
+    for (i = 0; i < 2; i++) {
+        set |= s->regs[i].confstat & (1UL << 11);
+    }
+    pci_set_irq(PCI_DEVICE(s), (set ? 1 : 0));
+}
+
+static void sii3112_set_irq(void *opaque, int channel, int level)
+{
+    SiI3112PCIState *s = opaque;
+
+    DPRINTF("%s: channel %d level %d\n", __func__, channel, level);
+    if (level) {
+        s->regs[channel].confstat |= (1UL << 11);
+    } else {
+        s->regs[channel].confstat &= ~(1UL << 11);
+    }
+
+    sii3112_update_irq(s);
+}
+
+static void sii3112_reset(void *opaque)
+{
+    SiI3112PCIState *s = opaque;
+    int i;
+
+    for (i = 0; i < 2; i++) {
+        s->regs[i].confstat = 0x6515 << 16;
+        ide_bus_reset(&s->i.bus[i]);
+    }
+}
+
+static void sii3112_pci_realize(PCIDevice *dev, Error **errp)
+{
+    SiI3112PCIState *d = SII3112_PCI(dev);
+    PCIIDEState *s = PCI_IDE(dev);
+    MemoryRegion *mr;
+    qemu_irq *irq;
+    int i;
+
+    pci_config_set_interrupt_pin(dev->config, 1);
+    pci_set_byte(dev->config + PCI_CACHE_LINE_SIZE, 8);
+
+    memory_region_init_io(&d->mmio, OBJECT(d), &sii3112_reg_ops, d,
+                         "sii3112.bar5", 0x200);
+    pci_register_bar(dev, 5, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
+
+    mr = g_new(MemoryRegion, 1);
+    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar0", &d->mmio, 0x80, 8);
+    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, mr);
+    mr = g_new(MemoryRegion, 1);
+    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar1", &d->mmio, 0x88, 4);
+    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, mr);
+    mr = g_new(MemoryRegion, 1);
+    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar2", &d->mmio, 0xc0, 8);
+    pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, mr);
+    mr = g_new(MemoryRegion, 1);
+    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar3", &d->mmio, 0xc8, 4);
+    pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_IO, mr);
+    mr = g_new(MemoryRegion, 1);
+    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar4", &d->mmio, 0, 16);
+    pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, mr);
+
+    irq = qemu_allocate_irqs(sii3112_set_irq, d, 2);
+    for (i = 0; i < 2; i++) {
+        ide_bus_new(&s->bus[i], sizeof(s->bus[i]), DEVICE(dev), i, 1);
+        ide_init2(&s->bus[i], irq[i]);
+
+        bmdma_init(&s->bus[i], &s->bmdma[i], s);
+        s->bmdma[i].bus = &s->bus[i];
+        ide_register_restart_cb(&s->bus[i]);
+    }
+    qemu_register_reset(sii3112_reset, s);
+}
+
+static void sii3112_pci_exitfn(PCIDevice *dev)
+{
+    PCIIDEState *d = PCI_IDE(dev);
+    int i;
+
+    for (i = 0; i < 2; ++i) {
+        memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].extra_io);
+        memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].addr_ioport);
+    }
+}
+
+static void sii3112_pci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *pd = PCI_DEVICE_CLASS(klass);
+
+    pd->vendor_id = 0x1095;
+    pd->device_id = 0x3112;
+    pd->class_id = PCI_CLASS_STORAGE_RAID;
+    pd->revision = 1;
+    pd->realize = sii3112_pci_realize;
+    pd->exit = sii3112_pci_exitfn;
+    dc->desc = "SiI3112A SATA controller";
+    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
+}
+
+static const TypeInfo sii3112_pci_info = {
+    .name = TYPE_SII3112_PCI,
+    .parent = TYPE_PCI_IDE,
+    .instance_size = sizeof(SiI3112PCIState),
+    .class_init = sii3112_pci_class_init,
+};
+
+static void sii3112_register_types(void)
+{
+    type_register_static(&sii3112_pci_info);
+}
+
+type_init(sii3112_register_types)
-- 
2.7.6

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Qemu-devel] [PATCH 10/15] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
  2017-08-20 17:23 [Qemu-devel] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
                   ` (11 preceding siblings ...)
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 01/15] ppc4xx: Move MAL from ppc405_uc to ppc4xx_devs BALATON Zoltan
@ 2017-08-20 17:23 ` BALATON Zoltan
  2017-08-20 22:20   ` Philippe Mathieu-Daudé
  2017-08-23  0:49   ` David Gibson
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 15/15] ppc: Add aCube Sam460ex board BALATON Zoltan
                   ` (2 subsequent siblings)
  15 siblings, 2 replies; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-20 17:23 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

This is the PCIX controller found in newer 440 core SoCs e.g. the AMMC
460EX. The device tree refers to this as plb-pcix compared to the
plb-pci controller in older 440 SoCs.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/ppc/Makefile.objs |   2 +-
 hw/ppc/ppc440_pcix.c | 516 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 517 insertions(+), 1 deletion(-)
 create mode 100644 hw/ppc/ppc440_pcix.c

diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 7efc686..fc39fe4 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -13,7 +13,7 @@ endif
 obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o
 # PowerPC 4xx boards
 obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
-obj-y += ppc4xx_pci.o
+obj-y += ppc4xx_pci.o ppc440_pcix.o
 # PReP
 obj-$(CONFIG_PREP) += prep.o
 obj-$(CONFIG_PREP) += prep_systemio.o
diff --git a/hw/ppc/ppc440_pcix.c b/hw/ppc/ppc440_pcix.c
new file mode 100644
index 0000000..5c2ceec
--- /dev/null
+++ b/hw/ppc/ppc440_pcix.c
@@ -0,0 +1,516 @@
+/*
+ * Emulation of the ibm,plb-pcix PCI controller
+ * This is found in some 440 SoCs e.g. the 460EX.
+ *
+ * Copyright (c) 2016 BALATON Zoltan
+ *
+ * Derived from ppc4xx_pci.c and pci-host/ppce500.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "hw/hw.h"
+#include "hw/ppc/ppc.h"
+#include "hw/ppc/ppc4xx.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "exec/address-spaces.h"
+
+/*#define DEBUG_PCI*/
+
+#ifdef DEBUG_PCI
+#define DPRINTF(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__);
+#else
+#define DPRINTF(fmt, ...)
+#endif /* DEBUG */
+
+struct PLBOutMap {
+    uint64_t la;
+    uint64_t pcia;
+    uint32_t sa;
+    MemoryRegion mr;
+};
+
+struct PLBInMap {
+    uint64_t sa;
+    uint64_t la;
+    MemoryRegion mr;
+};
+
+#define TYPE_PPC440_PCIX_HOST_BRIDGE "ppc440-pcix-host"
+#define PPC440_PCIX_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(PPC440PCIXState, (obj), TYPE_PPC440_PCIX_HOST_BRIDGE)
+
+#define PPC440_PCIX_NR_POMS 3
+#define PPC440_PCIX_NR_PIMS 3
+
+typedef struct PPC440PCIXState {
+    PCIHostState parent_obj;
+
+    PCIDevice *dev;
+    struct PLBOutMap pom[PPC440_PCIX_NR_POMS];
+    struct PLBInMap pim[PPC440_PCIX_NR_PIMS];
+    uint32_t sts;
+    qemu_irq irq[PCI_NUM_PINS];
+    AddressSpace bm_as;
+    MemoryRegion bm;
+
+    MemoryRegion container;
+    MemoryRegion iomem;
+    MemoryRegion busmem;
+} PPC440PCIXState;
+
+#define PPC440_REG_BASE     0x80000
+#define PPC440_REG_SIZE     0xff
+
+#define PCIC0_CFGADDR       0x0
+#define PCIC0_CFGDATA       0x4
+
+#define PCIX0_POM0LAL       0x68
+#define PCIX0_POM0LAH       0x6c
+#define PCIX0_POM0SA        0x70
+#define PCIX0_POM0PCIAL     0x74
+#define PCIX0_POM0PCIAH     0x78
+#define PCIX0_POM1LAL       0x7c
+#define PCIX0_POM1LAH       0x80
+#define PCIX0_POM1SA        0x84
+#define PCIX0_POM1PCIAL     0x88
+#define PCIX0_POM1PCIAH     0x8c
+#define PCIX0_POM2SA        0x90
+
+#define PCIX0_PIM0SAL       0x98
+#define PCIX0_PIM0LAL       0x9c
+#define PCIX0_PIM0LAH       0xa0
+#define PCIX0_PIM1SA        0xa4
+#define PCIX0_PIM1LAL       0xa8
+#define PCIX0_PIM1LAH       0xac
+#define PCIX0_PIM2SAL       0xb0
+#define PCIX0_PIM2LAL       0xb4
+#define PCIX0_PIM2LAH       0xb8
+#define PCIX0_PIM0SAH       0xf8
+#define PCIX0_PIM2SAH       0xfc
+
+#define PCIX0_STS           0xe0
+
+#define PCI_ALL_SIZE        (PPC440_REG_BASE + PPC440_REG_SIZE)
+
+static void ppc440_pcix_clear_region(MemoryRegion *parent,
+                                     MemoryRegion *mem)
+{
+    if (memory_region_is_mapped(mem)) {
+        memory_region_del_subregion(parent, mem);
+        object_unparent(OBJECT(mem));
+    }
+}
+
+/* DMA mapping */
+static void ppc440_pcix_update_pim(PPC440PCIXState *s, int idx)
+{
+    MemoryRegion *mem = &s->pim[idx].mr;
+    char *name;
+    uint64_t size;
+
+    /* Before we modify anything, unmap and destroy the region */
+    ppc440_pcix_clear_region(&s->bm, mem);
+
+    if (!(s->pim[idx].sa & 1)) {
+        /* Not enabled, nothing to do */
+        return;
+    }
+
+    name = g_strdup_printf("PCI Inbound Window %d", idx);
+    size = ~(s->pim[idx].sa & ~7ULL) + 1;
+    memory_region_init_alias(mem, OBJECT(s), name, get_system_memory(),
+                             s->pim[idx].la, size);
+    memory_region_add_subregion_overlap(&s->bm, 0, mem, -1);
+    g_free(name);
+
+    DPRINTF("%s: Added window %d of size=%#"PRIx64" to CPU=%#"PRIx64"\n",
+            __func__, idx, size, s->pim[idx].la);
+}
+
+/* BAR mapping */
+static void ppc440_pcix_update_pom(PPC440PCIXState *s, int idx)
+{
+    MemoryRegion *mem = &s->pom[idx].mr;
+    MemoryRegion *address_space_mem = get_system_memory();
+    char *name;
+    uint32_t size;
+
+    /* Before we modify anything, unmap and destroy the region */
+    ppc440_pcix_clear_region(address_space_mem, mem);
+
+    if (!(s->pom[idx].sa & 1)) {
+        /* Not enabled, nothing to do */
+        return;
+    }
+
+    name = g_strdup_printf("PCI Outbound Window %d", idx);
+    size = ~(s->pom[idx].sa & 0xfffffffe) + 1;
+    if (!size) {
+        size = 0xffffffff;
+    }
+    memory_region_init_alias(mem, OBJECT(s), name, &s->busmem,
+                             s->pom[idx].pcia, size);
+    memory_region_add_subregion(address_space_mem, s->pom[idx].la, mem);
+    g_free(name);
+
+    DPRINTF("%s: Added window %d of size=%#x from CPU=%#"PRIx64
+            " to PCI=%#"PRIx64"\n", __func__, idx, size, s->pom[idx].la,
+            s->pom[idx].pcia);
+}
+
+static void ppc440_pcix_reg_write4(void *opaque, hwaddr addr,
+                                   uint64_t val, unsigned size)
+{
+    struct PPC440PCIXState *s = opaque;
+
+    DPRINTF("%s: addr 0x%"PRIx64 " = %"PRIx64 "\n", __func__, addr, val);
+    switch (addr) {
+    case PCI_VENDOR_ID ... PCI_MAX_LAT:
+        stl_le_p(s->dev->config + addr, val);
+        break;
+
+    case PCIX0_POM0LAL:
+        s->pom[0].la &= 0xffffffff00000000ULL;
+        s->pom[0].la |= val;
+        ppc440_pcix_update_pom(s, 0);
+        break;
+    case PCIX0_POM0LAH:
+        s->pom[0].la &= 0xffffffffULL;
+        s->pom[0].la |= val << 32;
+        ppc440_pcix_update_pom(s, 0);
+        break;
+    case PCIX0_POM0SA:
+        s->pom[0].sa = val;
+        ppc440_pcix_update_pom(s, 0);
+        break;
+    case PCIX0_POM0PCIAL:
+        s->pom[0].pcia &= 0xffffffff00000000ULL;
+        s->pom[0].pcia |= val;
+        ppc440_pcix_update_pom(s, 0);
+        break;
+    case PCIX0_POM0PCIAH:
+        s->pom[0].pcia &= 0xffffffffULL;
+        s->pom[0].pcia |= val << 32;
+        ppc440_pcix_update_pom(s, 0);
+        break;
+    case PCIX0_POM1LAL:
+        s->pom[1].la &= 0xffffffff00000000ULL;
+        s->pom[1].la |= val;
+        ppc440_pcix_update_pom(s, 1);
+        break;
+    case PCIX0_POM1LAH:
+        s->pom[1].la &= 0xffffffffULL;
+        s->pom[1].la |= val << 32;
+        ppc440_pcix_update_pom(s, 1);
+        break;
+    case PCIX0_POM1SA:
+        s->pom[1].sa = val;
+        ppc440_pcix_update_pom(s, 1);
+        break;
+    case PCIX0_POM1PCIAL:
+        s->pom[1].pcia &= 0xffffffff00000000ULL;
+        s->pom[1].pcia |= val;
+        ppc440_pcix_update_pom(s, 1);
+        break;
+    case PCIX0_POM1PCIAH:
+        s->pom[1].pcia &= 0xffffffffULL;
+        s->pom[1].pcia |= val << 32;
+        ppc440_pcix_update_pom(s, 1);
+        break;
+    case PCIX0_POM2SA:
+        s->pom[2].sa = val;
+        break;
+
+    case PCIX0_PIM0SAL:
+        s->pim[0].sa &= 0xffffffff00000000ULL;
+        s->pim[0].sa |= val;
+        ppc440_pcix_update_pim(s, 0);
+        break;
+    case PCIX0_PIM0LAL:
+        s->pim[0].la &= 0xffffffff00000000ULL;
+        s->pim[0].la |= val;
+        ppc440_pcix_update_pim(s, 0);
+        break;
+    case PCIX0_PIM0LAH:
+        s->pim[0].la &= 0xffffffffULL;
+        s->pim[0].la |= val << 32;
+        ppc440_pcix_update_pim(s, 0);
+        break;
+    case PCIX0_PIM1SA:
+        s->pim[1].sa = val;
+        ppc440_pcix_update_pim(s, 1);
+        break;
+    case PCIX0_PIM1LAL:
+        s->pim[1].la &= 0xffffffff00000000ULL;
+        s->pim[1].la |= val;
+        ppc440_pcix_update_pim(s, 1);
+        break;
+    case PCIX0_PIM1LAH:
+        s->pim[1].la &= 0xffffffffULL;
+        s->pim[1].la |= val << 32;
+        ppc440_pcix_update_pim(s, 1);
+        break;
+    case PCIX0_PIM2SAL:
+        s->pim[2].sa &= 0xffffffff00000000ULL;
+        s->pim[2].sa = val;
+        ppc440_pcix_update_pim(s, 2);
+        break;
+    case PCIX0_PIM2LAL:
+        s->pim[2].la &= 0xffffffff00000000ULL;
+        s->pim[2].la |= val;
+        ppc440_pcix_update_pim(s, 2);
+        break;
+    case PCIX0_PIM2LAH:
+        s->pim[2].la &= 0xffffffffULL;
+        s->pim[2].la |= val << 32;
+        ppc440_pcix_update_pim(s, 2);
+        break;
+
+    case PCIX0_STS:
+        s->sts = val;
+        break;
+
+    case PCIX0_PIM0SAH:
+        s->pim[0].sa &= 0xffffffffULL;
+        s->pim[0].sa |= val << 32;
+        ppc440_pcix_update_pim(s, 0);
+        break;
+    case PCIX0_PIM2SAH:
+        s->pim[2].sa &= 0xffffffffULL;
+        s->pim[2].sa |= val << 32;
+        ppc440_pcix_update_pim(s, 2);
+        break;
+
+    default:
+        printf("%s: unhandled PCI internal register 0x%lx\n", __func__,
+               (unsigned long)addr);
+        break;
+    }
+}
+
+static uint64_t ppc440_pcix_reg_read4(void *opaque, hwaddr addr,
+                                     unsigned size)
+{
+    struct PPC440PCIXState *s = opaque;
+    uint32_t val;
+
+    switch (addr) {
+    case PCI_VENDOR_ID ... PCI_MAX_LAT:
+        val = ldl_le_p(s->dev->config + addr);
+        break;
+
+    case PCIX0_POM0LAL:
+        val = s->pom[0].la;
+        break;
+    case PCIX0_POM0LAH:
+        val = s->pom[0].la >> 32;
+        break;
+    case PCIX0_POM0SA:
+        val = s->pom[0].sa;
+        break;
+    case PCIX0_POM0PCIAL:
+        val = s->pom[0].pcia;
+        break;
+    case PCIX0_POM0PCIAH:
+        val = s->pom[0].pcia >> 32;
+        break;
+    case PCIX0_POM1LAL:
+        val = s->pom[1].la;
+        break;
+    case PCIX0_POM1LAH:
+        val = s->pom[1].la >> 32;
+        break;
+    case PCIX0_POM1SA:
+        val = s->pom[1].sa;
+        break;
+    case PCIX0_POM1PCIAL:
+        val = s->pom[1].pcia;
+        break;
+    case PCIX0_POM1PCIAH:
+        val = s->pom[1].pcia >> 32;
+        break;
+    case PCIX0_POM2SA:
+        val = s->pom[2].sa;
+        break;
+
+    case PCIX0_PIM0SAL:
+        val = s->pim[0].sa;
+        break;
+    case PCIX0_PIM0LAL:
+        val = s->pim[0].la;
+        break;
+    case PCIX0_PIM0LAH:
+        val = s->pim[0].la >> 32;
+        break;
+    case PCIX0_PIM1SA:
+        val = s->pim[1].sa;
+        break;
+    case PCIX0_PIM1LAL:
+        val = s->pim[1].la;
+        break;
+    case PCIX0_PIM1LAH:
+        val = s->pim[1].la >> 32;
+        break;
+    case PCIX0_PIM2SAL:
+        val = s->pim[2].sa;
+        break;
+    case PCIX0_PIM2LAL:
+        val = s->pim[2].la;
+        break;
+    case PCIX0_PIM2LAH:
+        val = s->pim[2].la >> 32;
+        break;
+
+    case PCIX0_STS:
+        val = s->sts;
+        break;
+
+    case PCIX0_PIM0SAH:
+        val = s->pim[0].sa  >> 32;
+        break;
+    case PCIX0_PIM2SAH:
+        val = s->pim[2].sa  >> 32;
+        break;
+
+    default:
+        printf("%s: invalid PCI internal register 0x%lx\n", __func__,
+               (unsigned long)addr);
+        val = 0;
+    }
+
+    DPRINTF("%s: addr 0x%"PRIx64 " = %"PRIx32 "\n", __func__, addr, val);
+    return val;
+}
+
+static const MemoryRegionOps pci_reg_ops = {
+    .read = ppc440_pcix_reg_read4,
+    .write = ppc440_pcix_reg_write4,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void ppc440_pcix_reset(DeviceState *dev)
+{
+    struct PPC440PCIXState *s = PPC440_PCIX_HOST_BRIDGE(dev);
+    int i;
+
+    for (i = 0; i < PPC440_PCIX_NR_POMS; i++) {
+        ppc440_pcix_clear_region(get_system_memory(), &s->pom[i].mr);
+    }
+    for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) {
+        ppc440_pcix_clear_region(&s->bm, &s->pim[i].mr);
+    }
+    memset(s->pom, 0, sizeof(s->pom));
+    memset(s->pim, 0, sizeof(s->pim));
+    for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) {
+        s->pim[i].sa = 0xffffffff00000000ULL;
+    }
+    s->sts = 0;
+}
+
+/* All pins from each slot are tied to a single board IRQ.
+ * This may need further refactoring for other boards. */
+static int ppc440_pcix_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    int slot = pci_dev->devfn >> 3;
+
+    DPRINTF("%s: devfn %x irq %d -> %d\n", __func__,
+            pci_dev->devfn, irq_num, slot);
+
+    return slot - 1;
+}
+
+static void ppc440_pcix_set_irq(void *opaque, int irq_num, int level)
+{
+    qemu_irq *pci_irqs = opaque;
+
+    DPRINTF("%s: PCI irq %d\n", __func__, irq_num);
+    if (irq_num < 0) {
+        error_report("%s: PCI irq %d", __func__, irq_num);
+        return;
+    }
+    qemu_set_irq(pci_irqs[irq_num], level);
+}
+
+static AddressSpace *ppc440_pcix_set_iommu(PCIBus *b, void *opaque, int devfn)
+{
+    PPC440PCIXState *s = opaque;
+
+    return &s->bm_as;
+}
+
+static int ppc440_pcix_initfn(SysBusDevice *dev)
+{
+    PPC440PCIXState *s;
+    PCIHostState *h;
+    int i;
+
+    h = PCI_HOST_BRIDGE(dev);
+    s = PPC440_PCIX_HOST_BRIDGE(dev);
+
+    for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
+        sysbus_init_irq(dev, &s->irq[i]);
+    }
+
+    memory_region_init(&s->busmem, OBJECT(dev), "pci bus memory", UINT64_MAX);
+    h->bus = pci_register_bus(DEVICE(dev), NULL, ppc440_pcix_set_irq,
+                         ppc440_pcix_map_irq, s->irq, &s->busmem,
+                         get_system_io(), PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
+
+    s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0), "ppc4xx-host-bridge");
+
+    memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX);
+    memory_region_add_subregion(&s->bm, 0x0, &s->busmem);
+    address_space_init(&s->bm_as, &s->bm, "pci-bm");
+    pci_setup_iommu(h->bus, ppc440_pcix_set_iommu, s);
+
+    memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE);
+    memory_region_init_io(&h->conf_mem, OBJECT(s), &pci_host_conf_le_ops, h,
+                          "pci-conf-idx", 4);
+    memory_region_init_io(&h->data_mem, OBJECT(s), &pci_host_data_le_ops, h,
+                          "pci-conf-data", 4);
+    memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s,
+                          "pci.reg", PPC440_REG_SIZE);
+    memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem);
+    memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem);
+    memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->iomem);
+    sysbus_init_mmio(dev, &s->container);
+
+    return 0;
+}
+
+static void ppc440_pcix_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    k->init = ppc440_pcix_initfn;
+    dc->reset = ppc440_pcix_reset;
+}
+
+static const TypeInfo ppc440_pcix_info = {
+    .name          = TYPE_PPC440_PCIX_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
+    .instance_size = sizeof(PPC440PCIXState),
+    .class_init    = ppc440_pcix_class_init,
+};
+
+static void ppc440_pcix_register_types(void)
+{
+    type_register_static(&ppc440_pcix_info);
+}
+
+type_init(ppc440_pcix_register_types)
-- 
2.7.6

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Qemu-devel] [PATCH 03/15] ohci: Allow sysbus version to be used as a companion
  2017-08-20 17:23 [Qemu-devel] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
                   ` (8 preceding siblings ...)
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 13/15] ppc4xx: Add more PLB registers BALATON Zoltan
@ 2017-08-20 17:23 ` BALATON Zoltan
  2017-08-21  4:10   ` David Gibson
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 14/15] ppc4xx: Add device models found in PPC440 core SoCs BALATON Zoltan
                   ` (5 subsequent siblings)
  15 siblings, 1 reply; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-20 17:23 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: Alexander Graf, David Gibson, Francois Revol, Gerd Hoffmann

Some PPC SoCs have an EHCI with OHCI companion USB controller. To
emulate this allow the sysbus version of OHCI to be used as a companion.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/usb/hcd-ohci.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 267982e..17beedd 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -1999,7 +1999,9 @@ typedef struct {
     /*< public >*/
 
     OHCIState ohci;
+    char *masterbus;
     uint32_t num_ports;
+    uint32_t firstport;
     dma_addr_t dma_offset;
 } OHCISysBusState;
 
@@ -2007,10 +2009,15 @@ static void ohci_realize_pxa(DeviceState *dev, Error **errp)
 {
     OHCISysBusState *s = SYSBUS_OHCI(dev);
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    Error *err = NULL;
 
-    /* Cannot fail as we pass NULL for masterbus */
-    usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset, NULL, 0,
-                  &address_space_memory, &error_abort);
+    usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset,
+                  s->masterbus, s->firstport,
+                  &address_space_memory, &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
     sysbus_init_irq(sbd, &s->ohci.irq);
     sysbus_init_mmio(sbd, &s->ohci.mem);
 }
@@ -2142,7 +2149,9 @@ static const TypeInfo ohci_pci_info = {
 };
 
 static Property ohci_sysbus_properties[] = {
+    DEFINE_PROP_STRING("masterbus", OHCISysBusState, masterbus),
     DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
+    DEFINE_PROP_UINT32("firstport", OHCISysBusState, firstport, 0),
     DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 0),
     DEFINE_PROP_END_OF_LIST(),
 };
-- 
2.7.6

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Qemu-devel] [PATCH 00/15] Sam460ex emulation
@ 2017-08-20 17:23 BALATON Zoltan
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 07/15] ppc4xx_i2c: Move to hw/i2c BALATON Zoltan
                   ` (15 more replies)
  0 siblings, 16 replies; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-20 17:23 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

This is the revised version of my series described in the cover letter
of the RFC series:
http://lists.nongnu.org/archive/html/qemu-ppc/2017-08/msg00112.html

This contains reorganisation and fixes suggested by review comments.

Even though I think I haven't changed anything (apart from mostly
moving code around) with this series the problem described here:

http://lists.nongnu.org/archive/html/qemu-ppc/2017-08/msg00227.html

also happens with just the u-boot-sam460-20100605-fixed.bin while the
unfixed original firmware does not show this problem (but does not
work as it has the problems that are fixed in my version). There's
definitely some QEMU bug here (client code should not be able to crash
QEMU) but I have no idea how to find it because it is triggered from
TCG generated code so I'd need some help to debug that.

BALATON Zoltan (15):
  ppc4xx: Move MAL from ppc405_uc to ppc4xx_devs
  ppc4xx: Make MAL emulation more generic
  ohci: Allow sysbus version to be used as a companion
  ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs
  ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file
  ppc4xx_i2c: QOMify
  ppc4xx_i2c: Move to hw/i2c
  ppc4xx_i2c: Implement basic I2C functions
  hw/ide: Emulate SiI3112 SATA controller
  ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
  ppc: Add 460EX embedded CPU
  ppc4xx: Export ECB and PLB emulation
  ppc4xx: Add more PLB registers
  ppc4xx: Add device models found in PPC440 core SoCs
  ppc: Add aCube Sam460ex board

 default-configs/ppc-softmmu.mak    |    1 +
 default-configs/ppc64-softmmu.mak  |    1 +
 default-configs/ppcemb-softmmu.mak |    4 +
 hw/i2c/Makefile.objs               |    1 +
 hw/i2c/ppc4xx_i2c.c                |  368 ++++++++++
 hw/ide/Makefile.objs               |    1 +
 hw/ide/sii3112.c                   |  369 ++++++++++
 hw/ppc/Makefile.objs               |    4 +-
 hw/ppc/ppc405.h                    |    3 +
 hw/ppc/ppc405_uc.c                 |  527 +--------------
 hw/ppc/ppc440.h                    |   26 +
 hw/ppc/ppc440_pcix.c               |  516 ++++++++++++++
 hw/ppc/ppc440_uc.c                 | 1305 ++++++++++++++++++++++++++++++++++++
 hw/ppc/ppc4xx_devs.c               |  227 +++++++
 hw/ppc/sam460ex.c                  |  611 +++++++++++++++++
 hw/usb/hcd-ehci-sysbus.c           |   25 +
 hw/usb/hcd-ehci.h                  |    1 +
 hw/usb/hcd-ohci.c                  |   15 +-
 include/hw/i2c/ppc4xx_i2c.h        |   64 ++
 include/hw/pci/pcie_host.h         |    2 +-
 include/hw/ppc/ppc4xx.h            |    3 +
 target/ppc/cpu-models.c            |    3 +
 target/ppc/cpu-models.h            |    1 +
 target/ppc/translate_init.c        |   38 ++
 24 files changed, 3599 insertions(+), 517 deletions(-)
 create mode 100644 hw/i2c/ppc4xx_i2c.c
 create mode 100644 hw/ide/sii3112.c
 create mode 100644 hw/ppc/ppc440.h
 create mode 100644 hw/ppc/ppc440_pcix.c
 create mode 100644 hw/ppc/ppc440_uc.c
 create mode 100644 hw/ppc/sam460ex.c
 create mode 100644 include/hw/i2c/ppc4xx_i2c.h

-- 
2.7.6

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [Qemu-devel] [PATCH 07/15] ppc4xx_i2c: Move to hw/i2c
  2017-08-20 17:23 [Qemu-devel] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
@ 2017-08-20 17:23 ` BALATON Zoltan
  2017-08-21 10:54   ` David Gibson
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 06/15] ppc4xx_i2c: QOMify BALATON Zoltan
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-20 17:23 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 default-configs/ppc-softmmu.mak    |   1 +
 default-configs/ppc64-softmmu.mak  |   1 +
 default-configs/ppcemb-softmmu.mak |   1 +
 hw/i2c/Makefile.objs               |   1 +
 hw/i2c/ppc4xx_i2c.c                | 216 +++++++++++++++++++++++++++++++++++++
 hw/ppc/Makefile.objs               |   2 +-
 hw/ppc/ppc4xx_i2c.c                | 216 -------------------------------------
 7 files changed, 221 insertions(+), 217 deletions(-)
 create mode 100644 hw/i2c/ppc4xx_i2c.c
 delete mode 100644 hw/ppc/ppc4xx_i2c.c

diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index 1f1cd85..d4d44eb 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -3,6 +3,7 @@
 include pci.mak
 include sound.mak
 include usb.mak
+CONFIG_PPC4XX=y
 CONFIG_ESCC=y
 CONFIG_M48T59=y
 CONFIG_SERIAL=y
diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
index 46c9599..af32589 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -3,6 +3,7 @@
 include pci.mak
 include sound.mak
 include usb.mak
+CONFIG_PPC4XX=y
 CONFIG_VIRTIO_VGA=y
 CONFIG_ESCC=y
 CONFIG_M48T59=y
diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
index 94340de..635923a 100644
--- a/default-configs/ppcemb-softmmu.mak
+++ b/default-configs/ppcemb-softmmu.mak
@@ -3,6 +3,7 @@
 include pci.mak
 include sound.mak
 include usb.mak
+CONFIG_PPC4XX=y
 CONFIG_M48T59=y
 CONFIG_SERIAL=y
 CONFIG_SERIAL_ISA=y
diff --git a/hw/i2c/Makefile.objs b/hw/i2c/Makefile.objs
index a081b8e..0594dea 100644
--- a/hw/i2c/Makefile.objs
+++ b/hw/i2c/Makefile.objs
@@ -8,3 +8,4 @@ common-obj-$(CONFIG_EXYNOS4) += exynos4210_i2c.o
 common-obj-$(CONFIG_IMX_I2C) += imx_i2c.o
 common-obj-$(CONFIG_ASPEED_SOC) += aspeed_i2c.o
 obj-$(CONFIG_OMAP) += omap_i2c.o
+obj-$(CONFIG_PPC4XX) += ppc4xx_i2c.o
diff --git a/hw/i2c/ppc4xx_i2c.c b/hw/i2c/ppc4xx_i2c.c
new file mode 100644
index 0000000..5a6bde9
--- /dev/null
+++ b/hw/i2c/ppc4xx_i2c.c
@@ -0,0 +1,216 @@
+/*
+ * PPC4xx I2C controller emulation
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "hw/hw.h"
+#include "hw/i2c/ppc4xx_i2c.h"
+
+/*#define DEBUG_I2C*/
+
+#define PPC4xx_I2C_MEM_SIZE 0x11
+
+static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size)
+{
+    PPC4xxI2CState *i2c = PPC4xx_I2C(opaque);
+    uint64_t ret;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    switch (addr) {
+    case 0x00:
+        /*i2c_readbyte(&i2c->mdata);*/
+        ret = i2c->mdata;
+        break;
+    case 0x02:
+        ret = i2c->sdata;
+        break;
+    case 0x04:
+        ret = i2c->lmadr;
+        break;
+    case 0x05:
+        ret = i2c->hmadr;
+        break;
+    case 0x06:
+        ret = i2c->cntl;
+        break;
+    case 0x07:
+        ret = i2c->mdcntl;
+        break;
+    case 0x08:
+        ret = i2c->sts;
+        break;
+    case 0x09:
+        ret = i2c->extsts;
+        break;
+    case 0x0A:
+        ret = i2c->lsadr;
+        break;
+    case 0x0B:
+        ret = i2c->hsadr;
+        break;
+    case 0x0C:
+        ret = i2c->clkdiv;
+        break;
+    case 0x0D:
+        ret = i2c->intrmsk;
+        break;
+    case 0x0E:
+        ret = i2c->xfrcnt;
+        break;
+    case 0x0F:
+        ret = i2c->xtcntlss;
+        break;
+    case 0x10:
+        ret = i2c->directcntl;
+        break;
+    default:
+        ret = 0x00;
+        break;
+    }
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " %02" PRIx64 "\n", __func__, addr, ret);
+#endif
+
+    return ret;
+}
+
+static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
+                              unsigned int size)
+{
+    PPC4xxI2CState *i2c = opaque;
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx64 "\n",
+           __func__, addr, value);
+#endif
+    switch (addr) {
+    case 0x00:
+        i2c->mdata = value;
+        /*i2c_sendbyte(&i2c->mdata);*/
+        break;
+    case 0x02:
+        i2c->sdata = value;
+        break;
+    case 0x04:
+        i2c->lmadr = value;
+        break;
+    case 0x05:
+        i2c->hmadr = value;
+        break;
+    case 0x06:
+        i2c->cntl = value;
+        break;
+    case 0x07:
+        i2c->mdcntl = value & 0xDF;
+        break;
+    case 0x08:
+        i2c->sts &= ~(value & 0x0A);
+        break;
+    case 0x09:
+        i2c->extsts &= ~(value & 0x8F);
+        break;
+    case 0x0A:
+        i2c->lsadr = value;
+        break;
+    case 0x0B:
+        i2c->hsadr = value;
+        break;
+    case 0x0C:
+        i2c->clkdiv = value;
+        break;
+    case 0x0D:
+        i2c->intrmsk = value;
+        break;
+    case 0x0E:
+        i2c->xfrcnt = value & 0x77;
+        break;
+    case 0x0F:
+        i2c->xtcntlss = value;
+        break;
+    case 0x10:
+        i2c->directcntl = value & 0x7;
+        break;
+    }
+}
+
+static const MemoryRegionOps ppc4xx_i2c_ops = {
+    .read = ppc4xx_i2c_readb,
+    .write = ppc4xx_i2c_writeb,
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 4,
+    .impl.min_access_size = 1,
+    .impl.max_access_size = 1,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void ppc4xx_i2c_reset(DeviceState *s)
+{
+    PPC4xxI2CState *i2c = PPC4xx_I2C(s);
+
+    i2c->mdata = 0x00;
+    i2c->sdata = 0x00;
+    i2c->cntl = 0x00;
+    i2c->mdcntl = 0x00;
+    i2c->sts = 0x00;
+    i2c->extsts = 0x00;
+    i2c->clkdiv = 0x00;
+    i2c->xfrcnt = 0x00;
+    i2c->directcntl = 0x0F;
+}
+
+static void ppc4xx_i2c_init(Object *o)
+{
+    PPC4xxI2CState *s = PPC4xx_I2C(o);
+
+    memory_region_init_io(&s->iomem, OBJECT(s), &ppc4xx_i2c_ops, s,
+                          TYPE_PPC4xx_I2C, PPC4xx_I2C_MEM_SIZE);
+    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
+    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
+    s->bus = i2c_init_bus(DEVICE(s), "i2c");
+}
+
+static void ppc4xx_i2c_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->reset = ppc4xx_i2c_reset;
+}
+
+static const TypeInfo ppc4xx_i2c_type_info = {
+    .name = TYPE_PPC4xx_I2C,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PPC4xxI2CState),
+    .instance_init = ppc4xx_i2c_init,
+    .class_init = ppc4xx_i2c_class_init,
+};
+
+static void ppc4xx_i2c_register_types(void)
+{
+    type_register_static(&ppc4xx_i2c_type_info);
+}
+
+type_init(ppc4xx_i2c_register_types)
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 2077216..7efc686 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -13,7 +13,7 @@ endif
 obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o
 # PowerPC 4xx boards
 obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
-obj-y += ppc4xx_pci.o ppc4xx_i2c.o
+obj-y += ppc4xx_pci.o
 # PReP
 obj-$(CONFIG_PREP) += prep.o
 obj-$(CONFIG_PREP) += prep_systemio.o
diff --git a/hw/ppc/ppc4xx_i2c.c b/hw/ppc/ppc4xx_i2c.c
deleted file mode 100644
index 5a6bde9..0000000
--- a/hw/ppc/ppc4xx_i2c.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * PPC4xx I2C controller emulation
- *
- * Copyright (c) 2007 Jocelyn Mayer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "qemu-common.h"
-#include "cpu.h"
-#include "hw/hw.h"
-#include "hw/i2c/ppc4xx_i2c.h"
-
-/*#define DEBUG_I2C*/
-
-#define PPC4xx_I2C_MEM_SIZE 0x11
-
-static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size)
-{
-    PPC4xxI2CState *i2c = PPC4xx_I2C(opaque);
-    uint64_t ret;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    switch (addr) {
-    case 0x00:
-        /*i2c_readbyte(&i2c->mdata);*/
-        ret = i2c->mdata;
-        break;
-    case 0x02:
-        ret = i2c->sdata;
-        break;
-    case 0x04:
-        ret = i2c->lmadr;
-        break;
-    case 0x05:
-        ret = i2c->hmadr;
-        break;
-    case 0x06:
-        ret = i2c->cntl;
-        break;
-    case 0x07:
-        ret = i2c->mdcntl;
-        break;
-    case 0x08:
-        ret = i2c->sts;
-        break;
-    case 0x09:
-        ret = i2c->extsts;
-        break;
-    case 0x0A:
-        ret = i2c->lsadr;
-        break;
-    case 0x0B:
-        ret = i2c->hsadr;
-        break;
-    case 0x0C:
-        ret = i2c->clkdiv;
-        break;
-    case 0x0D:
-        ret = i2c->intrmsk;
-        break;
-    case 0x0E:
-        ret = i2c->xfrcnt;
-        break;
-    case 0x0F:
-        ret = i2c->xtcntlss;
-        break;
-    case 0x10:
-        ret = i2c->directcntl;
-        break;
-    default:
-        ret = 0x00;
-        break;
-    }
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " %02" PRIx64 "\n", __func__, addr, ret);
-#endif
-
-    return ret;
-}
-
-static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
-                              unsigned int size)
-{
-    PPC4xxI2CState *i2c = opaque;
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx64 "\n",
-           __func__, addr, value);
-#endif
-    switch (addr) {
-    case 0x00:
-        i2c->mdata = value;
-        /*i2c_sendbyte(&i2c->mdata);*/
-        break;
-    case 0x02:
-        i2c->sdata = value;
-        break;
-    case 0x04:
-        i2c->lmadr = value;
-        break;
-    case 0x05:
-        i2c->hmadr = value;
-        break;
-    case 0x06:
-        i2c->cntl = value;
-        break;
-    case 0x07:
-        i2c->mdcntl = value & 0xDF;
-        break;
-    case 0x08:
-        i2c->sts &= ~(value & 0x0A);
-        break;
-    case 0x09:
-        i2c->extsts &= ~(value & 0x8F);
-        break;
-    case 0x0A:
-        i2c->lsadr = value;
-        break;
-    case 0x0B:
-        i2c->hsadr = value;
-        break;
-    case 0x0C:
-        i2c->clkdiv = value;
-        break;
-    case 0x0D:
-        i2c->intrmsk = value;
-        break;
-    case 0x0E:
-        i2c->xfrcnt = value & 0x77;
-        break;
-    case 0x0F:
-        i2c->xtcntlss = value;
-        break;
-    case 0x10:
-        i2c->directcntl = value & 0x7;
-        break;
-    }
-}
-
-static const MemoryRegionOps ppc4xx_i2c_ops = {
-    .read = ppc4xx_i2c_readb,
-    .write = ppc4xx_i2c_writeb,
-    .valid.min_access_size = 1,
-    .valid.max_access_size = 4,
-    .impl.min_access_size = 1,
-    .impl.max_access_size = 1,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void ppc4xx_i2c_reset(DeviceState *s)
-{
-    PPC4xxI2CState *i2c = PPC4xx_I2C(s);
-
-    i2c->mdata = 0x00;
-    i2c->sdata = 0x00;
-    i2c->cntl = 0x00;
-    i2c->mdcntl = 0x00;
-    i2c->sts = 0x00;
-    i2c->extsts = 0x00;
-    i2c->clkdiv = 0x00;
-    i2c->xfrcnt = 0x00;
-    i2c->directcntl = 0x0F;
-}
-
-static void ppc4xx_i2c_init(Object *o)
-{
-    PPC4xxI2CState *s = PPC4xx_I2C(o);
-
-    memory_region_init_io(&s->iomem, OBJECT(s), &ppc4xx_i2c_ops, s,
-                          TYPE_PPC4xx_I2C, PPC4xx_I2C_MEM_SIZE);
-    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
-    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
-    s->bus = i2c_init_bus(DEVICE(s), "i2c");
-}
-
-static void ppc4xx_i2c_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    dc->reset = ppc4xx_i2c_reset;
-}
-
-static const TypeInfo ppc4xx_i2c_type_info = {
-    .name = TYPE_PPC4xx_I2C,
-    .parent = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(PPC4xxI2CState),
-    .instance_init = ppc4xx_i2c_init,
-    .class_init = ppc4xx_i2c_class_init,
-};
-
-static void ppc4xx_i2c_register_types(void)
-{
-    type_register_static(&ppc4xx_i2c_type_info);
-}
-
-type_init(ppc4xx_i2c_register_types)
-- 
2.7.6

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Qemu-devel] [PATCH 15/15] ppc: Add aCube Sam460ex board
  2017-08-20 17:23 [Qemu-devel] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
                   ` (12 preceding siblings ...)
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 10/15] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs BALATON Zoltan
@ 2017-08-20 17:23 ` BALATON Zoltan
  2017-08-20 22:10   ` Philippe Mathieu-Daudé
  2017-08-23  4:16   ` David Gibson
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 08/15] ppc4xx_i2c: Implement basic I2C functions BALATON Zoltan
  2017-08-27 12:34 ` [Qemu-devel] [Qemu-ppc] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
  15 siblings, 2 replies; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-20 17:23 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

Add emulation of aCube Sam460ex board based on AMCC 460EX embedded SoC.
This is not a full implementation yet with a lot of components still
missing but enough to start a Linux kernel and the U-Boot firmware.

Signed-off-by: François Revol <revol@free.fr>
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 default-configs/ppcemb-softmmu.mak |   3 +
 hw/ppc/Makefile.objs               |   2 +
 hw/ppc/sam460ex.c                  | 611 +++++++++++++++++++++++++++++++++++++
 3 files changed, 616 insertions(+)
 create mode 100644 hw/ppc/sam460ex.c

diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
index 635923a..90b42f0 100644
--- a/default-configs/ppcemb-softmmu.mak
+++ b/default-configs/ppcemb-softmmu.mak
@@ -17,3 +17,6 @@ CONFIG_XILINX=y
 CONFIG_XILINX_ETHLITE=y
 CONFIG_LIBDECNUMBER=y
 CONFIG_SM501=y
+CONFIG_USB_EHCI_SYSBUS=y
+CONFIG_IDE_SII3112=y
+CONFIG_SAM460EX=y
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index fc39fe4..0aaea5b 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -27,3 +27,5 @@ obj-$(CONFIG_E500) += e500.o mpc8544ds.o e500plat.o
 obj-$(CONFIG_E500) += mpc8544_guts.o ppce500_spin.o
 # PowerPC 440 Xilinx ML507 reference board.
 obj-$(CONFIG_XILINX) += virtex_ml507.o
+# ACube Sam460ex board.
+obj-$(CONFIG_SAM460EX) += ppc440_uc.o sam460ex.o
diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
new file mode 100644
index 0000000..7cf4f6f
--- /dev/null
+++ b/hw/ppc/sam460ex.c
@@ -0,0 +1,611 @@
+/*
+ * QEMU aCube Sam460ex board emulation
+ *
+ * Copyright (c) 2012 François Revol
+ * Copyright (c) 2016-2017 BALATON Zoltan
+ *
+ * This file is derived from hw/ppc440_bamboo.c,
+ * the copyright for that material belongs to the original owners.
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/cutils.h"
+#include "qapi/error.h"
+#include "hw/hw.h"
+#include "sysemu/blockdev.h"
+#include "hw/boards.h"
+#include "sysemu/kvm.h"
+#include "kvm_ppc.h"
+#include "sysemu/device_tree.h"
+#include "sysemu/block-backend.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "exec/address-spaces.h"
+#include "exec/memory.h"
+#include "hw/ppc/ppc440.h"
+#include "hw/ppc/ppc405.h"
+#include "hw/block/flash.h"
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+#include "hw/char/serial.h"
+#include "hw/i2c/ppc4xx_i2c.h"
+#include "hw/i2c/smbus.h"
+#include "hw/usb/hcd-ehci.h"
+
+#define BINARY_DEVICE_TREE_FILE "sam460ex.dtb"
+#define UBOOT_FILENAME "u-boot-sam460-20100605.bin"
+/* to extract the official U-Boot bin from the updater: */
+/* dd bs=1 skip=$(($(stat -c '%s' updater/updater-460) - 0x80000)) \
+     if=updater/updater-460 of=u-boot-sam460-20100605.bin */
+
+/* from Sam460 U-Boot include/configs/Sam460ex.h */
+#define FLASH_BASE             0xfff00000
+#define FLASH_BASE_H           0x4
+#define FLASH_SIZE             (1 << 20)
+#define UBOOT_LOAD_BASE        0xfff80000
+#define UBOOT_SIZE             0x00080000
+#define UBOOT_ENTRY            0xfffffffc
+
+/* from U-Boot */
+#define EPAPR_MAGIC           (0x45504150)
+#define KERNEL_ADDR           0x1000000
+#define FDT_ADDR              0x1800000
+#define RAMDISK_ADDR          0x1900000
+
+/* Sam460ex IRQ MAP:
+   IRQ0  = ETH_INT
+   IRQ1  = FPGA_INT
+   IRQ2  = PCI_INT (PCIA, PCIB, PCIC, PCIB)
+   IRQ3  = FPGA_INT2
+   IRQ11 = RTC_INT
+   IRQ12 = SM502_INT
+*/
+
+#define SDRAM_NR_BANKS 4
+
+/* FIXME: See u-boot.git 8ac41e */
+static const unsigned int ppc460ex_sdram_bank_sizes[] = {
+    1024 << 20, 512 << 20, 256 << 20, 128 << 20, 64 << 20, 32 << 20, 0
+};
+
+struct boot_info {
+    uint32_t dt_base;
+    uint32_t dt_size;
+    uint32_t entry;
+};
+
+/*****************************************************************************/
+/* SPD eeprom content from mips_malta.c */
+
+struct _eeprom24c0x_t {
+  uint8_t tick;
+  uint8_t address;
+  uint8_t command;
+  uint8_t ack;
+  uint8_t scl;
+  uint8_t sda;
+  uint8_t data;
+  uint8_t contents[256];
+};
+
+typedef struct _eeprom24c0x_t eeprom24c0x_t;
+
+static eeprom24c0x_t spd_eeprom = {
+    .contents = {
+        /* 00000000: */ 0x80, 0x08, 0xFF, 0x0D, 0x0A, 0xFF, 0x40, 0x00,
+        /* 00000008: */ 0x04, 0x75, 0x54, 0x00, 0x82, 0x08, 0x00, 0x01,
+        /* 00000010: */ 0x8F, 0x04, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00,
+        /* 00000018: */ 0x00, 0x00, 0x00, 0x14, 0x0F, 0x14, 0x2D, 0xFF,
+        /* 00000020: */ 0x15, 0x08, 0x15, 0x08, 0x00, 0x00, 0x00, 0x00,
+        /* 00000028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        /* 00000030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        /* 00000038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xD0,
+        /* 00000040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        /* 00000048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        /* 00000050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        /* 00000058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        /* 00000060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        /* 00000068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        /* 00000070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        /* 00000078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xF4,
+    },
+};
+
+static void generate_eeprom_spd(uint8_t *eeprom, ram_addr_t ram_size)
+{
+    enum { SDR = 0x4, DDR1 = 0x7, DDR2 = 0x8 } type;
+    uint8_t *spd = spd_eeprom.contents;
+    uint8_t nbanks = 0;
+    uint16_t density = 0;
+    int i;
+
+    /* work in terms of MB */
+    ram_size >>= 20;
+
+    while ((ram_size >= 4) && (nbanks <= 2)) {
+        int sz_log2 = MIN(31 - clz32(ram_size), 14);
+        nbanks++;
+        density |= 1 << (sz_log2 - 2);
+        ram_size -= 1 << sz_log2;
+    }
+
+    /* split to 2 banks if possible */
+    if ((nbanks == 1) && (density > 1)) {
+        nbanks++;
+        density >>= 1;
+    }
+
+    if (density & 0xff00) {
+        density = (density & 0xe0) | ((density >> 8) & 0x1f);
+        type = DDR2;
+    } else if (!(density & 0x1f)) {
+        type = DDR2;
+    } else {
+        type = SDR;
+    }
+
+    if (ram_size) {
+        fprintf(stderr, "Warning: SPD cannot represent final %dMB"
+                " of SDRAM\n", (int)ram_size);
+    }
+
+    /* fill in SPD memory information */
+    spd[2] = type;
+    spd[5] = nbanks;
+    spd[31] = density;
+#ifdef DEBUG_SDRAM
+    printf("SPD: nbanks %d density %d\n", nbanks, density);
+#endif
+    /* XXX: this is totally random */
+    spd[9] = 0x10; /* CAS tcyc */
+    spd[18] = 0x20; /* CAS bit */
+    spd[23] = 0x10; /* CAS tcyc */
+    spd[25] = 0x10; /* CAS tcyc */
+
+    /* checksum */
+    spd[63] = 0;
+    for (i = 0; i < 63; i++) {
+        spd[63] += spd[i];
+    }
+
+    /* copy for SMBUS */
+    memcpy(eeprom, spd, sizeof(spd_eeprom.contents));
+}
+
+static void generate_eeprom_serial(uint8_t *eeprom)
+{
+    int i, pos = 0;
+    uint8_t mac[6] = { 0x00 };
+    uint8_t sn[5] = { 0x01, 0x23, 0x45, 0x67, 0x89 };
+
+    /* version */
+    eeprom[pos++] = 0x01;
+
+    /* count */
+    eeprom[pos++] = 0x02;
+
+    /* MAC address */
+    eeprom[pos++] = 0x01; /* MAC */
+    eeprom[pos++] = 0x06; /* length */
+    memcpy(&eeprom[pos], mac, sizeof(mac));
+    pos += sizeof(mac);
+
+    /* serial number */
+    eeprom[pos++] = 0x02; /* serial */
+    eeprom[pos++] = 0x05; /* length */
+    memcpy(&eeprom[pos], sn, sizeof(sn));
+    pos += sizeof(sn);
+
+    /* checksum */
+    eeprom[pos] = 0;
+    for (i = 0; i < pos; i++) {
+        eeprom[pos] += eeprom[i];
+    }
+}
+
+/*****************************************************************************/
+
+static int sam460ex_load_uboot(void)
+{
+    DriveInfo *dinfo;
+    BlockBackend *blk = NULL;
+    hwaddr base = FLASH_BASE | ((hwaddr)FLASH_BASE_H << 32);
+    long bios_size = FLASH_SIZE;
+    int fl_sectors;
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (dinfo) {
+        blk = blk_by_legacy_dinfo(dinfo);
+        bios_size = blk_getlength(blk);
+    }
+    fl_sectors = (bios_size + 65535) >> 16;
+
+    if (!pflash_cfi01_register(base, NULL, "sam460ex.flash", bios_size,
+                               blk, (64 * 1024), fl_sectors,
+                               1, 0x89, 0x18, 0x0000, 0x0, 1)) {
+        fprintf(stderr, "qemu: Error registering flash memory.\n");
+        /* XXX: return an error instead? */
+        exit(1);
+    }
+
+    if (!blk) {
+        /*fprintf(stderr, "No flash image given with the 'pflash' parameter,"
+                " using default u-boot image\n");*/
+        base = UBOOT_LOAD_BASE | ((hwaddr)FLASH_BASE_H << 32);
+        rom_add_file_fixed(UBOOT_FILENAME, base, -1);
+    }
+
+    return 0;
+}
+
+static int sam460ex_load_device_tree(hwaddr addr,
+                                     uint32_t ramsize,
+                                     hwaddr initrd_base,
+                                     hwaddr initrd_size,
+                                     const char *kernel_cmdline)
+{
+    int ret = -1;
+    uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) };
+    char *filename;
+    int fdt_size;
+    void *fdt;
+    uint32_t tb_freq = 400000000;
+    uint32_t clock_freq = 400000000;
+
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
+    if (!filename) {
+        goto out;
+    }
+    fdt = load_device_tree(filename, &fdt_size);
+    g_free(filename);
+    if (fdt == NULL) {
+        goto out;
+    }
+
+    /* Manipulate device tree in memory. */
+
+    ret = qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property,
+                               sizeof(mem_reg_property));
+    if (ret < 0) {
+        fprintf(stderr, "couldn't set /memory/reg\n");
+    }
+
+    /* default FDT doesn't have a /chosen node... */
+    qemu_fdt_add_subnode(fdt, "/chosen");
+
+    ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
+                                    initrd_base);
+    if (ret < 0) {
+        fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
+    }
+
+    ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
+                                    (initrd_base + initrd_size));
+    if (ret < 0) {
+        fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
+    }
+
+    ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
+                                      kernel_cmdline);
+    if (ret < 0) {
+        fprintf(stderr, "couldn't set /chosen/bootargs\n");
+    }
+
+    /* Copy data from the host device tree into the guest. Since the guest can
+     * directly access the timebase without host involvement, we must expose
+     * the correct frequencies. */
+    if (kvm_enabled()) {
+        tb_freq = kvmppc_get_tbfreq();
+        clock_freq = kvmppc_get_clockfreq();
+    }
+
+    qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency",
+                              clock_freq);
+    qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency",
+                              tb_freq);
+
+    rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
+    g_free(fdt);
+    ret = fdt_size;
+
+out:
+
+    return ret;
+}
+
+/* Create reset TLB entries for BookE, mapping only the flash memory.  */
+static void mmubooke_create_initial_mapping_uboot(CPUPPCState *env)
+{
+    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
+
+    /* on reset the flash is mapped by a shadow TLB,
+     * but since we don't implement them we need to use
+     * the same values U-Boot will use to avoid a fault.
+     */
+    tlb->attr = 0;
+    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
+    tlb->size = 0x10000000; /* up to 0xffffffff  */
+    tlb->EPN = 0xf0000000 & TARGET_PAGE_MASK;
+    tlb->RPN = (0xf0000000 & TARGET_PAGE_MASK) | 0x4;
+    tlb->PID = 0;
+}
+
+/* Create reset TLB entries for BookE, spanning the 32bit addr space.  */
+static void mmubooke_create_initial_mapping(CPUPPCState *env,
+                                     target_ulong va,
+                                     hwaddr pa)
+{
+    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
+
+    tlb->attr = 0;
+    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
+    tlb->size = 1 << 31; /* up to 0x80000000  */
+    tlb->EPN = va & TARGET_PAGE_MASK;
+    tlb->RPN = pa & TARGET_PAGE_MASK;
+    tlb->PID = 0;
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+    struct boot_info *bi = env->load_info;
+
+    cpu_reset(CPU(cpu));
+
+    /* either we have a kernel to boot or we jump to U-Boot */
+    if (bi->entry != UBOOT_ENTRY) {
+        env->gpr[1] = (16 << 20) - 8;
+        env->gpr[3] = FDT_ADDR;
+
+        fprintf(stderr, "cpu reset: kernel entry %x\n", bi->entry);
+        env->nip = bi->entry;
+
+        /* Create a mapping for the kernel.  */
+        mmubooke_create_initial_mapping(env, 0, 0);
+        env->gpr[6] = tswap32(EPAPR_MAGIC);
+        env->gpr[7] = (16 << 20) - 8; /*bi->ima_size;*/
+
+    } else {
+        env->nip = UBOOT_ENTRY;
+        mmubooke_create_initial_mapping_uboot(env);
+        fprintf(stderr, "cpu reset: U-Boot entry\n");
+    }
+}
+
+static void sam460ex_init(MachineState *machine)
+{
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *isa = g_new(MemoryRegion, 1);
+    MemoryRegion *ram_memories = g_new(MemoryRegion, SDRAM_NR_BANKS);
+    hwaddr ram_bases[SDRAM_NR_BANKS];
+    hwaddr ram_sizes[SDRAM_NR_BANKS];
+    MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1);
+    qemu_irq *irqs, *uic[4];
+    PCIBus *pci_bus;
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    PPC4xxI2CState *i2c[2];
+    hwaddr entry = UBOOT_ENTRY;
+    hwaddr loadaddr = 0;
+    target_long initrd_size = 0;
+    DeviceState *dev;
+    SysBusDevice *sbdev;
+    int success;
+    int i;
+    struct boot_info *boot_info;
+    const size_t smbus_eeprom_size = 8 * 256;
+    uint8_t *smbus_eeprom_buf = g_malloc0(smbus_eeprom_size);
+
+    /* Setup CPU. */
+    if (machine->cpu_model == NULL) {
+        machine->cpu_model = "460EX";
+    }
+    cpu = cpu_ppc_init(machine->cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to initialize CPU!\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    qemu_register_reset(main_cpu_reset, cpu);
+    boot_info = g_malloc0(sizeof(*boot_info));
+    env->load_info = boot_info;
+
+    ppc_booke_timers_init(cpu, 50000000, 0);
+    ppc_dcr_init(env, NULL, NULL);
+
+    /* PLB arbitrer */
+    ppc4xx_plb_init(env);
+
+    /* interrupt controllers */
+    irqs = g_malloc0(sizeof(*irqs) * PPCUIC_OUTPUT_NB);
+    irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
+    irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
+    uic[0] = ppcuic_init(env, irqs, 0x0C0, 0, 1);
+    uic[1] = ppcuic_init(env, &uic[0][30], 0x0D0, 0, 1);
+    uic[2] = ppcuic_init(env, &uic[0][10], 0x0E0, 0, 1);
+    uic[3] = ppcuic_init(env, &uic[0][16], 0x0F0, 0, 1);
+
+    /* SDRAM controller */
+    memset(ram_bases, 0, sizeof(ram_bases));
+    memset(ram_sizes, 0, sizeof(ram_sizes));
+    /* put all RAM on first bank because board has one slot
+     * and firmware only checks that */
+    machine->ram_size = ppc4xx_sdram_adjust(machine->ram_size,
+                                   1/*SDRAM_NR_BANKS*/,
+                                   ram_memories,
+                                   ram_bases, ram_sizes,
+                                   ppc460ex_sdram_bank_sizes);
+#ifdef DEBUG_SDRAM
+    printf("RAMSIZE %dMB\n", (int)(machine->ram_size / M_BYTE));
+#endif
+
+    /* XXX does 460EX have ECC interrupts? */
+    ppc440_sdram_init(env, SDRAM_NR_BANKS, ram_memories,
+                      ram_bases, ram_sizes, 1);
+
+    /* generate SPD EEPROM data */
+    for (i = 0; i < SDRAM_NR_BANKS; i++) {
+#ifdef DEBUG_SDRAM
+        printf("bank %d: %" HWADDR_PRIx "\n", i, ram_sizes[i]);
+#endif
+        generate_eeprom_spd(&smbus_eeprom_buf[i * 256], ram_sizes[i]);
+    }
+    generate_eeprom_serial(&smbus_eeprom_buf[4 * 256]);
+    generate_eeprom_serial(&smbus_eeprom_buf[6 * 256]);
+
+    /* IIC controllers */
+    dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700, uic[0][2]);
+    i2c[0] = PPC4xx_I2C(dev);
+    object_property_set_bool(OBJECT(dev), true, "realized", NULL);
+    smbus_eeprom_init(i2c[0]->bus, 8, smbus_eeprom_buf, smbus_eeprom_size);
+    g_free(smbus_eeprom_buf);
+
+    dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600800, uic[0][3]);
+    i2c[1] = PPC4xx_I2C(dev);
+
+    /* External bus controller */
+    ppc405_ebc_init(env);
+
+    /* CPR */
+    ppc4xx_cpr_init(env);
+
+    /* PLB to AHB bridge */
+    ppc4xx_ahb_init(env);
+
+    /* System DCRs */
+    ppc4xx_sdr_init(env);
+
+    /* MAL */
+    ppc4xx_mal_init(env, 4, 16, &uic[2][3]);
+
+    /* 256K of L2 cache as memory */
+    ppc4xx_l2sram_init(env);
+    /* FIXME: remove this after fixing l2sram mapping in ppc440_uc.c? */
+    memory_region_init_ram(l2cache_ram, NULL, "ppc440.l2cache_ram", 256 << 10,
+                           &error_abort);
+    memory_region_add_subregion(address_space_mem, 0x400000000LL, l2cache_ram);
+
+    /* USB */
+    sysbus_create_simple(TYPE_PPC4xx_EHCI, 0x4bffd0400, uic[2][29]);
+    dev = qdev_create(NULL, "sysbus-ohci");
+    qdev_prop_set_string(dev, "masterbus", "usb-bus.0");
+    qdev_prop_set_uint32(dev, "num-ports", 6);
+    qdev_init_nofail(dev);
+    sbdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(sbdev, 0, 0x4bffd0000);
+    sysbus_connect_irq(sbdev, 0, uic[2][30]);
+    usb_create_simple(usb_bus_find(-1), "usb-kbd");
+    usb_create_simple(usb_bus_find(-1), "usb-mouse");
+
+    /* PCI bus */
+    ppc460ex_pcie_init(env);
+    /*XXX: FIXME: is this correct? */
+    dev = sysbus_create_varargs("ppc440-pcix-host", 0xc0ec00000,
+                                uic[1][0], uic[1][20], uic[1][21], uic[1][22],
+                                NULL);
+    pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
+    if (!pci_bus) {
+        fprintf(stderr, "couldn't create PCI controller!\n");
+        exit(1);
+    }
+    memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(),
+                             0, 0x10000);
+    memory_region_add_subregion(get_system_memory(), 0xc08000000, isa);
+
+    /* PCI devices */
+    pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "sm501");
+    /* SoC has a single SATA port but we don't emulate that yet
+     * However, firmware and usual clients have driver for SiI311x
+     * so add one for convenience by default */
+    pci_create_simple(pci_bus, -1, "sii3112");
+
+    /* SoC has 4 UARTs
+     * but board has only one wired and two are present in fdt */
+    if (serial_hds[0] != NULL) {
+        serial_mm_init(address_space_mem, 0x4ef600300, 0, uic[1][1],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
+                       DEVICE_BIG_ENDIAN);
+    }
+    if (serial_hds[1] != NULL) {
+        serial_mm_init(address_space_mem, 0x4ef600400, 0, uic[0][1],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
+                       DEVICE_BIG_ENDIAN);
+    }
+
+    /* Load U-Boot image. */
+    if (!machine->kernel_filename) {
+        success = sam460ex_load_uboot();
+        if (success < 0) {
+            fprintf(stderr, "qemu: could not load firmware\n");
+            exit(1);
+        }
+    }
+
+    /* Load kernel. */
+    if (machine->kernel_filename) {
+        success = load_uimage(machine->kernel_filename, &entry, &loadaddr, NULL,
+            NULL, NULL);
+        fprintf(stderr, "load_uimage: %d\n", success);
+        if (success < 0) {
+            uint64_t elf_entry, elf_lowaddr;
+
+            success = load_elf(machine->kernel_filename, NULL, NULL, &elf_entry,
+                               &elf_lowaddr, NULL, 1, PPC_ELF_MACHINE, 0, 0);
+            fprintf(stderr, "load_elf: %d\n", success);
+            entry = elf_entry;
+            loadaddr = elf_lowaddr;
+        }
+        /* XXX try again as binary */
+        if (success < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    machine->kernel_filename);
+            exit(1);
+        }
+    }
+
+    /* Load initrd. */
+    if (machine->initrd_filename) {
+        initrd_size = load_image_targphys(machine->initrd_filename,
+                                          RAMDISK_ADDR,
+                                          machine->ram_size - RAMDISK_ADDR);
+        fprintf(stderr, "load_image: %d\n", initrd_size);
+        if (initrd_size < 0) {
+            fprintf(stderr, "qemu: could not load ram disk '%s' at %x\n",
+                    machine->initrd_filename, RAMDISK_ADDR);
+            exit(1);
+        }
+    }
+
+    /* If we're loading a kernel directly, we must load the device tree too. */
+    if (machine->kernel_filename) {
+        int dt_size;
+
+        dt_size = sam460ex_load_device_tree(FDT_ADDR, machine->ram_size,
+                                    RAMDISK_ADDR, initrd_size,
+                                    machine->kernel_cmdline);
+        if (dt_size < 0) {
+            fprintf(stderr, "couldn't load device tree\n");
+            exit(1);
+        }
+
+        boot_info->dt_base = FDT_ADDR;
+        boot_info->dt_size = dt_size;
+    }
+
+    boot_info->entry = entry;
+}
+
+static void sam460ex_machine_init(MachineClass *mc)
+{
+    mc->desc = "aCube Sam460ex";
+    mc->init = sam460ex_init;
+    mc->default_ram_size = 512 * M_BYTE;
+}
+
+DEFINE_MACHINE("sam460ex", sam460ex_machine_init)
-- 
2.7.6

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Qemu-devel] [PATCH 14/15] ppc4xx: Add device models found in PPC440 core SoCs
  2017-08-20 17:23 [Qemu-devel] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
                   ` (9 preceding siblings ...)
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 03/15] ohci: Allow sysbus version to be used as a companion BALATON Zoltan
@ 2017-08-20 17:23 ` BALATON Zoltan
  2017-08-23  2:49   ` David Gibson
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 01/15] ppc4xx: Move MAL from ppc405_uc to ppc4xx_devs BALATON Zoltan
                   ` (4 subsequent siblings)
  15 siblings, 1 reply; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-20 17:23 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexander Graf, David Gibson, Francois Revol

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 40852 bytes --]

These devices are found in newer SoCs based on 440 core e.g. the 460EX
(http://www.embeddeddeveloper.com/assets/processors/amcc/datasheets/
PP460EX_DS2063.pdf)

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/ppc/ppc440.h            |   26 +
 hw/ppc/ppc440_uc.c         | 1305 ++++++++++++++++++++++++++++++++++++++++++++
 include/hw/pci/pcie_host.h |    2 +-
 3 files changed, 1332 insertions(+), 1 deletion(-)
 create mode 100644 hw/ppc/ppc440.h
 create mode 100644 hw/ppc/ppc440_uc.c

diff --git a/hw/ppc/ppc440.h b/hw/ppc/ppc440.h
new file mode 100644
index 0000000..601ee3b
--- /dev/null
+++ b/hw/ppc/ppc440.h
@@ -0,0 +1,26 @@
+/*
+ * QEMU PowerPC 440 shared definitions
+ *
+ * Copyright (c) 2012 François Revol
+ * Copyright (c) 2016-2017 BALATON Zoltan
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+#ifndef PPC440_H
+#define PPC440_H
+
+#include "hw/ppc/ppc.h"
+
+void ppc4xx_l2sram_init(CPUPPCState *env);
+void ppc4xx_cpr_init(CPUPPCState *env);
+void ppc4xx_sdr_init(CPUPPCState *env);
+void ppc440_sdram_init(CPUPPCState *env, int nbanks,
+                       MemoryRegion *ram_memories,
+                       hwaddr *ram_bases, hwaddr *ram_sizes,
+                       int do_init);
+void ppc4xx_ahb_init(CPUPPCState *env);
+void ppc460ex_pcie_init(CPUPPCState *env);
+
+#endif /* PPC440_H */
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
new file mode 100644
index 0000000..2a9580e
--- /dev/null
+++ b/hw/ppc/ppc440_uc.c
@@ -0,0 +1,1305 @@
+/*
+ * QEMU PowerPC 440 embedded processors emulation
+ *
+ * Copyright (c) 2012 François Revol
+ * Copyright (c) 2016-2017 BALATON Zoltan
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/cutils.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "hw/hw.h"
+#include "exec/address-spaces.h"
+#include "exec/memory.h"
+#include "hw/ppc/ppc.h"
+#include "hw/pci/pci.h"
+#include "sysemu/block-backend.h"
+#include "hw/ppc/ppc440.h"
+
+#undef DEBUG_SDRAM
+#undef DEBUG_L2SRAM
+#undef DEBUG_CPR
+#undef DEBUG_SDR
+#undef DEBUG_AHB
+#undef DEBUG_PCIE
+
+/*****************************************************************************/
+/* L2 Cache as SRAM */
+/* FIXME:fix names */
+enum {
+    DCR_L2CACHE_BASE  = 0x030,
+    DCR_L2CACHE_CFG   = DCR_L2CACHE_BASE,
+    DCR_L2CACHE_CMD,
+    DCR_L2CACHE_ADDR,
+    DCR_L2CACHE_DATA,
+    DCR_L2CACHE_STAT,
+    DCR_L2CACHE_CVER,
+    DCR_L2CACHE_SNP0,
+    DCR_L2CACHE_SNP1,
+    DCR_L2CACHE_END   = DCR_L2CACHE_SNP1,
+};
+
+/* base is 460ex-specific, cf. U-Boot, ppc4xx-isram.h */
+enum {
+    DCR_ISRAM0_BASE   = 0x020,
+    DCR_ISRAM0_SB0CR  = DCR_ISRAM0_BASE,
+    DCR_ISRAM0_SB1CR,
+    DCR_ISRAM0_SB2CR,
+    DCR_ISRAM0_SB3CR,
+    DCR_ISRAM0_BEAR,
+    DCR_ISRAM0_BESR0,
+    DCR_ISRAM0_BESR1,
+    DCR_ISRAM0_PMEG,
+    DCR_ISRAM0_CID,
+    DCR_ISRAM0_REVID,
+    DCR_ISRAM0_DPC,
+    DCR_ISRAM0_END    = DCR_ISRAM0_DPC
+};
+
+enum {
+    DCR_ISRAM1_BASE   = 0x0b0,
+    DCR_ISRAM1_SB0CR  = DCR_ISRAM1_BASE,
+    /* single bank */
+    DCR_ISRAM1_BEAR   = DCR_ISRAM1_BASE + 0x04,
+    DCR_ISRAM1_BESR0,
+    DCR_ISRAM1_BESR1,
+    DCR_ISRAM1_PMEG,
+    DCR_ISRAM1_CID,
+    DCR_ISRAM1_REVID,
+    DCR_ISRAM1_DPC,
+    DCR_ISRAM1_END    = DCR_ISRAM1_DPC
+};
+
+typedef struct ppc4xx_l2sram_t {
+    MemoryRegion bank[4];
+    uint32_t l2cache[8];
+    uint32_t isram0[11];
+} ppc4xx_l2sram_t;
+
+#ifdef MAP_L2SRAM
+static void l2sram_update_mappings(ppc4xx_l2sram_t *l2sram,
+                                   uint32_t isarc, uint32_t isacntl,
+                                   uint32_t dsarc, uint32_t dsacntl)
+{
+#ifdef DEBUG_L2SRAM
+    printf("L2SRAM update ISA %08" PRIx32 " %08" PRIx32 " (%08" PRIx32
+           " %08" PRIx32 ") DSA %08" PRIx32 " %08" PRIx32
+           " (%08" PRIx32 " %08" PRIx32 ")\n",
+           isarc, isacntl, dsarc, dsacntl,
+           l2sram->isarc, l2sram->isacntl, l2sram->dsarc, l2sram->dsacntl);
+#endif
+    if (l2sram->isarc != isarc ||
+        (l2sram->isacntl & 0x80000000) != (isacntl & 0x80000000)) {
+        if (l2sram->isacntl & 0x80000000) {
+            /* Unmap previously assigned memory region */
+            printf("L2SRAM unmap ISA %08" PRIx32 "\n", l2sram->isarc);
+            memory_region_del_subregion(get_system_memory(),
+                                        &l2sram->isarc_ram);
+        }
+        if (isacntl & 0x80000000) {
+            /* Map new instruction memory region */
+#ifdef DEBUG_L2SRAM
+            printf("L2SRAM map ISA %08" PRIx32 "\n", isarc);
+#endif
+            memory_region_add_subregion(get_system_memory(), isarc,
+                                        &l2sram->isarc_ram);
+        }
+    }
+    if (l2sram->dsarc != dsarc ||
+        (l2sram->dsacntl & 0x80000000) != (dsacntl & 0x80000000)) {
+        if (l2sram->dsacntl & 0x80000000) {
+            /* Beware not to unmap the region we just mapped */
+            if (!(isacntl & 0x80000000) || l2sram->dsarc != isarc) {
+                /* Unmap previously assigned memory region */
+#ifdef DEBUG_L2SRAM
+                printf("L2SRAM unmap DSA %08" PRIx32 "\n", l2sram->dsarc);
+#endif
+                memory_region_del_subregion(get_system_memory(),
+                                            &l2sram->dsarc_ram);
+            }
+        }
+        if (dsacntl & 0x80000000) {
+            /* Beware not to remap the region we just mapped */
+            if (!(isacntl & 0x80000000) || dsarc != isarc) {
+                /* Map new data memory region */
+#ifdef DEBUG_L2SRAM
+                printf("L2SRAM map DSA %08" PRIx32 "\n", dsarc);
+#endif
+                memory_region_add_subregion(get_system_memory(), dsarc,
+                                            &l2sram->dsarc_ram);
+            }
+        }
+    }
+}
+#endif
+
+static uint32_t dcr_read_l2sram(void *opaque, int dcrn)
+{
+    ppc4xx_l2sram_t *l2sram;
+    uint32_t ret;
+
+    l2sram = opaque;
+    switch (dcrn) {
+    case DCR_L2CACHE_CFG:
+    case DCR_L2CACHE_CMD:
+    case DCR_L2CACHE_ADDR:
+    case DCR_L2CACHE_DATA:
+    case DCR_L2CACHE_STAT:
+    case DCR_L2CACHE_CVER:
+    case DCR_L2CACHE_SNP0:
+    case DCR_L2CACHE_SNP1:
+        ret = l2sram->l2cache[dcrn - DCR_L2CACHE_BASE];
+#ifdef DEBUG_L2SRAM
+        printf("L2SRAM: read DCR[%x(L2CACHE+%x)]: %08" PRIx32 "\n",
+               dcrn, dcrn - DCR_L2CACHE_BASE, ret);
+#endif
+        break;
+
+    case DCR_ISRAM0_SB0CR:
+    case DCR_ISRAM0_SB1CR:
+    case DCR_ISRAM0_SB2CR:
+    case DCR_ISRAM0_SB3CR:
+    case DCR_ISRAM0_BEAR:
+    case DCR_ISRAM0_BESR0:
+    case DCR_ISRAM0_BESR1:
+    case DCR_ISRAM0_PMEG:
+    case DCR_ISRAM0_CID:
+    case DCR_ISRAM0_REVID:
+    case DCR_ISRAM0_DPC:
+        ret = l2sram->isram0[dcrn - DCR_ISRAM0_BASE];
+#ifdef DEBUG_L2SRAM
+        printf("L2SRAM: read DCR[%x(ISRAM0+%x)]: %08" PRIx32 "\n",
+               dcrn, dcrn - DCR_ISRAM0_BASE, ret);
+#endif
+        break;
+
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_l2sram(void *opaque, int dcrn, uint32_t val)
+{
+    /*ppc4xx_l2sram_t *l2sram = opaque;*/
+    /* TODO */
+
+    switch (dcrn) {
+    case DCR_L2CACHE_CFG:
+    case DCR_L2CACHE_CMD:
+    case DCR_L2CACHE_ADDR:
+    case DCR_L2CACHE_DATA:
+    case DCR_L2CACHE_STAT:
+    case DCR_L2CACHE_CVER:
+    case DCR_L2CACHE_SNP0:
+    case DCR_L2CACHE_SNP1:
+        /*l2sram->l2cache[dcrn - DCR_L2CACHE_BASE] = val;*/
+#ifdef DEBUG_L2SRAM
+        printf("L2SRAM: write DCR[%x(L2CACHE+%x)]: %08" PRIx32 "\n",
+               dcrn, dcrn - DCR_L2CACHE_BASE, val);
+#endif
+        break;
+
+    case DCR_ISRAM0_SB0CR:
+    case DCR_ISRAM0_SB1CR:
+    case DCR_ISRAM0_SB2CR:
+    case DCR_ISRAM0_SB3CR:
+    case DCR_ISRAM0_BEAR:
+    case DCR_ISRAM0_BESR0:
+    case DCR_ISRAM0_BESR1:
+    case DCR_ISRAM0_PMEG:
+    case DCR_ISRAM0_CID:
+    case DCR_ISRAM0_REVID:
+    case DCR_ISRAM0_DPC:
+        /*l2sram->isram0[dcrn - DCR_L2CACHE_BASE] = val;*/
+#ifdef DEBUG_L2SRAM
+        printf("L2SRAM: write DCR[%x(ISRAM0+%x)]: %08" PRIx32 "\n",
+               dcrn, dcrn - DCR_ISRAM0_BASE, val);
+#endif
+        break;
+
+    case DCR_ISRAM1_SB0CR:
+    case DCR_ISRAM1_BEAR:
+    case DCR_ISRAM1_BESR0:
+    case DCR_ISRAM1_BESR1:
+    case DCR_ISRAM1_PMEG:
+    case DCR_ISRAM1_CID:
+    case DCR_ISRAM1_REVID:
+    case DCR_ISRAM1_DPC:
+        /*l2sram->isram1[dcrn - DCR_L2CACHE_BASE] = val;*/
+#ifdef DEBUG_L2SRAM
+        printf("L2SRAM: write DCR[%x(ISRAM1+%x)]: %08" PRIx32 "\n",
+               dcrn, dcrn - DCR_ISRAM1_BASE, val);
+#endif
+        break;
+    }
+    /*l2sram_update_mappings(l2sram, isarc, isacntl, dsarc, dsacntl);*/
+}
+
+static void l2sram_reset(void *opaque)
+{
+    ppc4xx_l2sram_t *l2sram;
+    /*uint32_t isarc, dsarc, isacntl, dsacntl;*/
+
+    l2sram = opaque;
+    memset(l2sram->l2cache, 0, sizeof(l2sram->l2cache));
+    l2sram->l2cache[DCR_L2CACHE_STAT - DCR_L2CACHE_BASE] = 0x80000000;
+    memset(l2sram->isram0, 0, sizeof(l2sram->isram0));
+    /*l2sram_update_mappings(l2sram, isarc, isacntl, dsarc, dsacntl);*/
+}
+
+void ppc4xx_l2sram_init(CPUPPCState *env)
+{
+    ppc4xx_l2sram_t *l2sram;
+
+    l2sram = g_malloc0(sizeof(ppc4xx_l2sram_t));
+    /* XXX: Size is 4*64kB for 460ex, cf. U-Boot, ppc4xx-isram.h */
+    memory_region_init_ram(&l2sram->bank[0], NULL, "ppc4xx.l2sram_bank0",
+                           64 * 1024, &error_abort);
+    memory_region_init_ram(&l2sram->bank[1], NULL, "ppc4xx.l2sram_bank1",
+                           64 * 1024, &error_abort);
+    memory_region_init_ram(&l2sram->bank[2], NULL, "ppc4xx.l2sram_bank2",
+                           64 * 1024, &error_abort);
+    memory_region_init_ram(&l2sram->bank[3], NULL, "ppc4xx.l2sram_bank3",
+                           64 * 1024, &error_abort);
+    qemu_register_reset(&l2sram_reset, l2sram);
+    ppc_dcr_register(env, DCR_L2CACHE_CFG,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_L2CACHE_CMD,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_L2CACHE_ADDR,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_L2CACHE_DATA,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_L2CACHE_STAT,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_L2CACHE_CVER,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_L2CACHE_SNP0,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_L2CACHE_SNP1,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+
+    ppc_dcr_register(env, DCR_ISRAM0_SB0CR,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_ISRAM0_SB1CR,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_ISRAM0_SB2CR,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_ISRAM0_SB3CR,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_ISRAM0_PMEG,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_ISRAM0_DPC,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+
+    ppc_dcr_register(env, DCR_ISRAM1_SB0CR,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_ISRAM1_PMEG,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+    ppc_dcr_register(env, DCR_ISRAM1_DPC,
+                     l2sram, &dcr_read_l2sram, &dcr_write_l2sram);
+}
+
+/*****************************************************************************/
+/* Clocking Power on Reset */
+enum {
+    CPR0_CFGADDR = 0x00C,
+    CPR0_CFGDATA = 0x00D,
+};
+
+typedef struct ppc4xx_cpr_t {
+    uint32_t addr;
+} ppc4xx_cpr_t;
+
+static uint32_t dcr_read_cpr(void *opaque, int dcrn)
+{
+    ppc4xx_cpr_t *cpr = opaque;
+    uint32_t ret;
+
+    switch (dcrn) {
+    case CPR0_CFGADDR:
+        ret = cpr->addr;
+#ifdef DEBUG_CPR
+        printf("read DCR[%x(CPR0ADDR)]: %08" PRIx32 "\n", dcrn, ret);
+#endif
+        break;
+    case CPR0_CFGDATA:
+        ret = 0;
+#ifdef DEBUG_CPR
+        printf("read DCR[%x(CPR0DATA)]: %08" PRIx32 "\n", dcrn, ret);
+#endif
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_cpr(void *opaque, int dcrn, uint32_t val)
+{
+    ppc4xx_cpr_t *cpr = opaque;
+
+    switch (dcrn) {
+    case CPR0_CFGADDR:
+        cpr->addr = val;
+#ifdef DEBUG_CPR
+        printf("write DCR[%x(CPRADDR)]: %08" PRIx32 "\n", dcrn, val);
+#endif
+        break;
+    case CPR0_CFGDATA:
+#ifdef DEBUG_CPR
+        printf("write DCR[%x(CPRDATA)]: %08" PRIx32 "\n", dcrn, val);
+#endif
+        break;
+    default:
+#ifdef DEBUG_CPR
+        printf("write DCR[%x]: %08" PRIx32 "\n", dcrn, val);
+#endif
+        break;
+    }
+}
+
+static void ppc4xx_cpr_reset(void *opaque)
+{
+    ppc4xx_cpr_t *cpr = opaque;
+
+    cpr->addr = 0;
+}
+
+void ppc4xx_cpr_init(CPUPPCState *env)
+{
+    ppc4xx_cpr_t *cpr;
+
+    cpr = g_malloc0(sizeof(*cpr));
+    ppc_dcr_register(env, CPR0_CFGADDR, cpr, &dcr_read_cpr, &dcr_write_cpr);
+    ppc_dcr_register(env, CPR0_CFGDATA, cpr, &dcr_read_cpr, &dcr_write_cpr);
+    qemu_register_reset(ppc4xx_cpr_reset, cpr);
+}
+
+/*****************************************************************************/
+/* System DCRs */
+typedef struct ppc4xx_sdr_t ppc4xx_sdr_t;
+struct ppc4xx_sdr_t {
+    uint32_t addr;
+};
+
+enum {
+    SDR0_CFGADDR = 0x00e,
+    SDR0_CFGDATA,
+    SDR0_STRP0 = 0x020,
+    SDR0_STRP1,
+    SDR0_ECID3 = 0x083,
+    SDR0_DDR0 = 0x0e1,
+    SDR0_USB0 = 0x320,
+};
+
+enum {
+    PESDR0_LOOP = 0x303,
+    PESDR0_RCSSET,
+    PESDR0_RCSSTS,
+    PESDR0_RSTSTA = 0x310,
+    PESDR1_LOOP = 0x343,
+    PESDR1_RCSSET,
+    PESDR1_RCSSTS,
+    PESDR1_RSTSTA = 0x365,
+};
+
+#define SDR0_DDR0_DDRM_ENCODE(n)  ((((unsigned long)(n)) & 0x03) << 29)
+#define SDR0_DDR0_DDRM_DDR1       0x20000000
+#define SDR0_DDR0_DDRM_DDR2       0x40000000
+
+static uint32_t dcr_read_sdr(void *opaque, int dcrn)
+{
+    ppc4xx_sdr_t *sdr;
+    uint32_t ret;
+
+    sdr = opaque;
+    switch (dcrn) {
+    case SDR0_CFGADDR:
+        ret = sdr->addr;
+        break;
+    case SDR0_CFGDATA:
+        switch (sdr->addr) {
+        case SDR0_STRP0:
+            /* FIXME: Is this correct? This breaks timing */
+            ret = 0 /*5 << 8 | 15 << 4*/;
+            break;
+        case SDR0_STRP1:
+            ret = 5 << 29 | 2 << 26 | 1 << 24;
+            break;
+        case SDR0_ECID3:
+            ret = 1 << 20; /* No Security/Kasumi support */
+            break;
+        case SDR0_DDR0:
+            ret = SDR0_DDR0_DDRM_ENCODE(1) | SDR0_DDR0_DDRM_DDR1;
+            break;
+        case PESDR0_RCSSET:
+        case PESDR1_RCSSET:
+            ret = (1 << 24) | (1 << 16);
+            break;
+        case PESDR0_RCSSTS:
+        case PESDR1_RCSSTS:
+            ret = (1 << 16) | (1 << 12);
+            break;
+        case PESDR0_RSTSTA:
+        case PESDR1_RSTSTA:
+            ret = 1;
+            break;
+        case PESDR0_LOOP:
+        case PESDR1_LOOP:
+            ret = 1 << 12;
+            break;
+        default:
+            ret = 0;
+            break;
+        }
+#ifdef DEBUG_SDR
+        if (sdr->addr != 0x20 && sdr->addr != 0x21) {
+            printf("read DCR[%x(SDRDATA[%x])]: %08" PRIx32 "\n",
+                   dcrn, sdr->addr, ret);
+        }
+#endif
+        break;
+    default:
+        ret = 0;
+#ifdef DEBUG_SDR
+        printf("read DCR[%x]: %08" PRIx32 "\n", dcrn, ret);
+#endif
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_sdr(void *opaque, int dcrn, uint32_t val)
+{
+    ppc4xx_sdr_t *sdr;
+
+    sdr = opaque;
+    switch (dcrn) {
+    case SDR0_CFGADDR:
+        sdr->addr = val;
+        break;
+    case SDR0_CFGDATA:
+#ifdef DEBUG_SDR
+        printf("write DCR[%x(SDRDATA[%x])]: %08" PRIx32 "\n",
+               dcrn, sdr->addr, val);
+#endif
+        switch (sdr->addr) {
+        case 0x00: /* B0CR */
+            break;
+        default:
+            break;
+        }
+        break;
+    default:
+#ifdef DEBUG_SDR
+        printf("write DCR[%x]: %08" PRIx32 "\n", dcrn, val);
+#endif
+        break;
+    }
+}
+
+static void sdr_reset(void *opaque)
+{
+    ppc4xx_sdr_t *sdr;
+
+    sdr = opaque;
+    sdr->addr = 0;
+}
+
+void ppc4xx_sdr_init(CPUPPCState *env)
+{
+    ppc4xx_sdr_t *sdr;
+
+    sdr = g_malloc0(sizeof(ppc4xx_sdr_t));
+    qemu_register_reset(&sdr_reset, sdr);
+    ppc_dcr_register(env, SDR0_CFGADDR,
+                     sdr, &dcr_read_sdr, &dcr_write_sdr);
+    ppc_dcr_register(env, SDR0_CFGDATA,
+                     sdr, &dcr_read_sdr, &dcr_write_sdr);
+    ppc_dcr_register(env, SDR0_USB0,
+                     sdr, &dcr_read_sdr, &dcr_write_sdr);
+}
+
+/*****************************************************************************/
+/* SDRAM controller */
+typedef struct ppc4xx_sdram_t {
+    uint32_t addr;
+    int nbanks;
+    MemoryRegion containers[4]; /* used for clipping */
+    MemoryRegion *ram_memories;
+    hwaddr ram_bases[4];
+    hwaddr ram_sizes[4];
+    uint32_t bcr[4];
+} ppc4xx_sdram_t;
+
+enum {
+    SDRAM_R0BAS = 0x040,
+    SDRAM_R1BAS,
+    SDRAM_R2BAS,
+    SDRAM_R3BAS,
+    SDRAM_CONF1HB = 0x045,
+    SDRAM_PLBADDULL = 0x04a,
+    SDRAM_CONF1LL = 0x04b,
+    SDRAM_CONFPATHB = 0x04f,
+    SDRAM_PLBADDUHB = 0x050,
+    SDRAM0_CFGADDR = 0x010,
+    SDRAM0_CFGDATA,
+};
+
+/* XXX: TOFIX: some patches have made this code become inconsistent:
+ *      there are type inconsistencies, mixing hwaddr, target_ulong
+ *      and uint32_t
+ */
+static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
+{
+    uint32_t bcr;
+
+    switch (ram_size) {
+    case (8 * M_BYTE):
+        bcr = 0xffc0;
+        break;
+    case (16 * M_BYTE):
+        bcr = 0xff80;
+        break;
+    case (32 * M_BYTE):
+        bcr = 0xff00;
+        break;
+    case (64 * M_BYTE):
+        bcr = 0xfe00;
+        break;
+    case (128 * M_BYTE):
+        bcr = 0xfc00;
+        break;
+    case (256 * M_BYTE):
+        bcr = 0xf800;
+        break;
+    case (512 * M_BYTE):
+        bcr = 0xf000;
+        break;
+    case (1 * G_BYTE):
+        bcr = 0xe000;
+        break;
+/*
+    case (2 * G_BYTE):
+        bcr = 0xc000;
+        break;
+    case (4 * G_BYTE):
+        bcr = 0x8000;
+        break;
+*/
+    default:
+        printf("%s: invalid RAM size " TARGET_FMT_plx "\n", __func__,
+               ram_size);
+        return 0;
+    }
+    bcr |= ram_base & 0xFF800000;
+    bcr |= 1;
+
+    return bcr;
+}
+
+static inline hwaddr sdram_base(uint32_t bcr)
+{
+    return bcr & 0xFF800000;
+}
+
+static target_ulong sdram_size(uint32_t bcr)
+{
+    target_ulong size;
+    int sh;
+
+    sh = 1024 - ((bcr >> 6) & 0x3ff);
+    if (sh == 0) {
+        size = -1;
+    } else {
+        size = 8 * M_BYTE * sh;
+    }
+
+    return size;
+}
+
+static void sdram_set_bcr(ppc4xx_sdram_t *sdram,
+                          uint32_t *bcrp, uint32_t bcr, int enabled)
+{
+    unsigned n = bcrp - sdram->bcr;
+
+    if (*bcrp & 1) {
+        /* Unmap RAM */
+#ifdef DEBUG_SDRAM
+        printf("%s: unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
+               __func__, sdram_base(*bcrp), sdram_size(*bcrp));
+#endif
+        memory_region_del_subregion(get_system_memory(),
+                                    &sdram->containers[n]);
+        memory_region_del_subregion(&sdram->containers[n],
+                                    &sdram->ram_memories[n]);
+        object_unparent(OBJECT(&sdram->containers[n]));
+    }
+    *bcrp = bcr & 0xFFDEE001;
+    if (enabled && (bcr & 1)) {
+#ifdef DEBUG_SDRAM
+        printf("%s: Map RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
+               __func__, sdram_base(bcr), sdram_size(bcr));
+#endif
+        memory_region_init(&sdram->containers[n], NULL, "sdram-containers",
+                           sdram_size(bcr));
+        memory_region_add_subregion(&sdram->containers[n], 0,
+                                    &sdram->ram_memories[n]);
+        memory_region_add_subregion(get_system_memory(),
+                                    sdram_base(bcr),
+                                    &sdram->containers[n]);
+    }
+}
+
+static void sdram_map_bcr(ppc4xx_sdram_t *sdram)
+{
+    int i;
+
+    for (i = 0; i < sdram->nbanks; i++) {
+        if (sdram->ram_sizes[i] != 0) {
+            sdram_set_bcr(sdram,
+                          &sdram->bcr[i],
+                          sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
+                          1);
+        } else {
+            sdram_set_bcr(sdram, &sdram->bcr[i], 0, 0);
+        }
+    }
+}
+
+static uint32_t dcr_read_sdram(void *opaque, int dcrn)
+{
+    ppc4xx_sdram_t *sdram;
+    uint32_t ret;
+
+    sdram = opaque;
+#ifdef DEBUG_SDR
+        printf("read DCR[%x(SDRAM)]\n", dcrn);
+#endif
+    switch (dcrn) {
+    case SDRAM_R0BAS:
+    case SDRAM_R1BAS:
+    case SDRAM_R2BAS:
+    case SDRAM_R3BAS:
+        ret = sdram_bcr(sdram->ram_bases[dcrn - SDRAM_R0BAS],
+                        sdram->ram_sizes[dcrn - SDRAM_R0BAS]);
+        break;
+    case SDRAM_CONF1HB:
+    case SDRAM_CONF1LL:
+    case SDRAM_CONFPATHB:
+    case SDRAM_PLBADDULL:
+    case SDRAM_PLBADDUHB:
+        ret = 0;
+        break;
+    case SDRAM0_CFGADDR:
+        ret = sdram->addr;
+#ifdef DEBUG_SDR
+        printf("read DCR[%x(SDRAMADDR)]: %08" PRIx32 "\n", dcrn, ret);
+#endif
+        break;
+    case SDRAM0_CFGDATA:
+        switch (sdram->addr) {
+        case 0x0014: /* SDRAM_MCSTAT (405EX) */
+        case 0x001F:
+            ret = 0x80000000;
+            break;
+        case 0x0021: /* SDRAM_MCOPT2 */
+            ret = 0x08000000;
+            break;
+        case 0x0040: /* SDRAM_MB0CF */
+            ret = 0x00008001;
+            break;
+        case 0x007A: /* SDRAM_DLCR */
+            ret = 0x02000000;
+            break;
+        case 0x00E1: /* SDR0_DDR0 */
+            ret = SDR0_DDR0_DDRM_ENCODE(1) | SDR0_DDR0_DDRM_DDR1;
+            break;
+        default:
+            ret = 0;
+            break;
+        }
+#ifdef DEBUG_SDR
+        printf("read DCR[%x(SDRAMDATA)]: %08" PRIx32 "\n", dcrn, ret);
+#endif
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = opaque;
+#ifdef DEBUG_SDR
+        printf("write DCR[%x(SDRAM)]: %08" PRIx32 "\n", dcrn, val);
+#endif
+    switch (dcrn) {
+    case SDRAM_R0BAS:
+    case SDRAM_R1BAS:
+    case SDRAM_R2BAS:
+    case SDRAM_R3BAS:
+    case SDRAM_CONF1HB:
+    case SDRAM_CONF1LL:
+    case SDRAM_CONFPATHB:
+    case SDRAM_PLBADDULL:
+    case SDRAM_PLBADDUHB:
+        break;
+    case SDRAM0_CFGADDR:
+        sdram->addr = val;
+#ifdef DEBUG_SDR
+        printf("write DCR[%x(SDRAMADDR)]: %08" PRIx32 "\n", dcrn, val);
+#endif
+        break;
+    case SDRAM0_CFGDATA:
+#ifdef DEBUG_SDR
+        printf("write DCR[%x(SDRAMDATA)]: %08" PRIx32 "\n", dcrn, val);
+#endif
+        switch (sdram->addr) {
+        case 0x00: /* B0CR */
+            break;
+        default:
+            break;
+        }
+        break;
+    default:
+        break;
+    }
+}
+
+static void sdram_reset(void *opaque)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = opaque;
+    sdram->addr = 0;
+}
+
+void ppc440_sdram_init(CPUPPCState *env, int nbanks,
+                       MemoryRegion *ram_memories,
+                       hwaddr *ram_bases, hwaddr *ram_sizes,
+                       int do_init)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = g_malloc0(sizeof(ppc4xx_sdram_t));
+    sdram->nbanks = nbanks;
+    sdram->ram_memories = ram_memories;
+    memcpy(sdram->ram_bases, ram_bases, nbanks * sizeof(hwaddr));
+    memcpy(sdram->ram_sizes, ram_sizes, nbanks * sizeof(hwaddr));
+    qemu_register_reset(&sdram_reset, sdram);
+    ppc_dcr_register(env, SDRAM0_CFGADDR,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM0_CFGDATA,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    if (do_init) {
+        sdram_map_bcr(sdram);
+    }
+
+    ppc_dcr_register(env, SDRAM_R0BAS,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM_R1BAS,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM_R2BAS,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM_R3BAS,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM_CONF1HB,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM_PLBADDULL,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM_CONF1LL,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM_CONFPATHB,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM_PLBADDUHB,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+}
+
+/*****************************************************************************/
+/* PLB to AHB bridge */
+enum {
+    AHB_TOP    = 0x0A4,
+    AHB_BOT    = 0x0A5,
+};
+
+typedef struct ppc4xx_ahb_t {
+    uint32_t top;
+    uint32_t bot;
+} ppc4xx_ahb_t;
+
+static uint32_t dcr_read_ahb(void *opaque, int dcrn)
+{
+    ppc4xx_ahb_t *ahb;
+    uint32_t ret;
+
+    ahb = opaque;
+    switch (dcrn) {
+    case AHB_TOP:
+        ret = ahb->top;
+        break;
+    case AHB_BOT:
+        ret = ahb->bot;
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0;
+        break;
+    }
+#ifdef DEBUG_AHB
+    printf("read DCR[%x(AHB+%x)]: %08" PRIx32 "\n", dcrn, dcrn - 0xA0, ret);
+#endif
+
+    return ret;
+}
+
+static void dcr_write_ahb(void *opaque, int dcrn, uint32_t val)
+{
+    ppc4xx_ahb_t *ahb;
+
+    ahb = opaque;
+#ifdef DEBUG_AHB
+    printf("write DCR[%x(AHB+%x)]: %08" PRIx32 "\n", dcrn, dcrn - 0xA0, val);
+#endif
+    switch (dcrn) {
+    case AHB_TOP:
+        ahb->top = val;
+        break;
+    case AHB_BOT:
+        ahb->bot = val;
+        break;
+    }
+}
+
+static void ppc4xx_ahb_reset(void *opaque)
+{
+    ppc4xx_ahb_t *ahb;
+
+    ahb = opaque;
+    /* No error */
+    ahb->top = 0;
+    ahb->bot = 0;
+}
+
+void ppc4xx_ahb_init(CPUPPCState *env)
+{
+    ppc4xx_ahb_t *ahb;
+
+    ahb = g_malloc0(sizeof(ppc4xx_ahb_t));
+    ppc_dcr_register(env, AHB_TOP, ahb, &dcr_read_ahb, &dcr_write_ahb);
+    ppc_dcr_register(env, AHB_BOT, ahb, &dcr_read_ahb, &dcr_write_ahb);
+    qemu_register_reset(ppc4xx_ahb_reset, ahb);
+}
+
+/*****************************************************************************/
+/* PCI Express controller */
+/* This is not complete and not meant to work, only implemented partially
+ * to allow firmware and guests to find an empty bus. Cards should use PCI.
+ */
+#include "hw/pci/pcie_host.h"
+
+#define TYPE_PPC460EX_PCIE_HOST "ppc460ex-pcie-host"
+#define PPC460EX_PCIE_HOST(obj) \
+    OBJECT_CHECK(PPC460EXPCIEState, (obj), TYPE_PPC460EX_PCIE_HOST)
+
+typedef struct PPC460EXPCIEState {
+    PCIExpressHost host;
+
+    MemoryRegion iomem;
+    qemu_irq irq[4];
+    int32_t dcrn_base;
+
+    uint64_t cfg_base;
+    uint32_t cfg_mask;
+    uint64_t msg_base;
+    uint32_t msg_mask;
+    uint64_t omr1_base;
+    uint64_t omr1_mask;
+    uint64_t omr2_base;
+    uint64_t omr2_mask;
+    uint64_t omr3_base;
+    uint64_t omr3_mask;
+    uint64_t reg_base;
+    uint32_t reg_mask;
+    uint32_t special;
+    uint32_t cfg;
+} PPC460EXPCIEState;
+
+#define DCRN_PCIE0_BASE 0x100
+#define DCRN_PCIE1_BASE 0x120
+
+enum {
+    PEGPL_CFGBAH = 0x0,
+    PEGPL_CFGBAL,
+    PEGPL_CFGMSK,
+    PEGPL_MSGBAH,
+    PEGPL_MSGBAL,
+    PEGPL_MSGMSK,
+    PEGPL_OMR1BAH,
+    PEGPL_OMR1BAL,
+    PEGPL_OMR1MSKH,
+    PEGPL_OMR1MSKL,
+    PEGPL_OMR2BAH,
+    PEGPL_OMR2BAL,
+    PEGPL_OMR2MSKH,
+    PEGPL_OMR2MSKL,
+    PEGPL_OMR3BAH,
+    PEGPL_OMR3BAL,
+    PEGPL_OMR3MSKH,
+    PEGPL_OMR3MSKL,
+    PEGPL_REGBAH,
+    PEGPL_REGBAL,
+    PEGPL_REGMSK,
+    PEGPL_SPECIAL,
+    PEGPL_CFG,
+};
+
+#ifdef DEBUG_PCIE
+static void dump_pcie_regs(PPC460EXPCIEState *state)
+{
+    printf("dcrn_base=%x\n", state->dcrn_base);
+    printf("cfg  base=%lx, mask=%x, size=%x\n", state->cfg_base,
+           state->cfg_mask, ~(state->cfg_mask & 0xfffffffe) + 1);
+    printf("msg  base=%lx, mask=%x, size=%x\n", state->msg_base,
+           state->msg_mask, ~(state->msg_mask & 0xfffffffe) + 1);
+    printf("omr1 base=%lx, mask=%lx, size=%"PRIu64"\n", state->omr1_base,
+           state->omr1_mask, ~state->omr1_mask + 1);
+    printf("omr2 base=%lx, mask=%lx, size=%"PRIu64"\n", state->omr2_base,
+           state->omr2_mask, ~state->omr2_mask + 1);
+    printf("omr3 base=%lx, mask=%lx, size=%"PRIu64"\n", state->omr3_base,
+           state->omr3_mask, ~state->omr3_mask + 1);
+    printf("reg  base=%lx, mask=%x, size=%x\n", state->reg_base,
+           state->reg_mask, ~(state->reg_mask & 0xfffffffe) + 1);
+    printf("special=%x, cfg=%x\n", state->special, state->cfg);
+}
+#endif
+
+static uint32_t dcr_read_pcie(void *opaque, int dcrn)
+{
+    uint32_t ret = 0;
+    PPC460EXPCIEState *state = opaque;
+
+    switch (dcrn - state->dcrn_base) {
+    case PEGPL_CFGBAH:
+        ret = state->cfg_base >> 32;
+        break;
+    case PEGPL_CFGBAL:
+        ret = state->cfg_base;
+        break;
+    case PEGPL_CFGMSK:
+        ret = state->cfg_mask;
+        break;
+    case PEGPL_MSGBAH:
+        ret = state->msg_base >> 32;
+        break;
+    case PEGPL_MSGBAL:
+        ret = state->msg_base;
+        break;
+    case PEGPL_MSGMSK:
+        ret = state->msg_mask;
+        break;
+    case PEGPL_OMR1BAH:
+        ret = state->omr1_base >> 32;
+        break;
+    case PEGPL_OMR1BAL:
+        ret = state->omr1_base;
+        break;
+    case PEGPL_OMR1MSKH:
+        ret = state->omr1_mask >> 32;
+        break;
+    case PEGPL_OMR1MSKL:
+        ret = state->omr1_mask;
+        break;
+    case PEGPL_OMR2BAH:
+        ret = state->omr2_base >> 32;
+        break;
+    case PEGPL_OMR2BAL:
+        ret = state->omr2_base;
+        break;
+    case PEGPL_OMR2MSKH:
+        ret = state->omr2_mask >> 32;
+        break;
+    case PEGPL_OMR2MSKL:
+        ret = state->omr3_mask;
+        break;
+    case PEGPL_OMR3BAH:
+        ret = state->omr3_base >> 32;
+        break;
+    case PEGPL_OMR3BAL:
+        ret = state->omr3_base;
+        break;
+    case PEGPL_OMR3MSKH:
+        ret = state->omr3_mask >> 32;
+        break;
+    case PEGPL_OMR3MSKL:
+        ret = state->omr3_mask;
+        break;
+    case PEGPL_REGBAH:
+        ret = state->reg_base >> 32;
+        break;
+    case PEGPL_REGBAL:
+        ret = state->reg_base;
+        break;
+    case PEGPL_REGMSK:
+        ret = state->reg_mask;
+        break;
+    case PEGPL_SPECIAL:
+        ret = state->special;
+        break;
+    case PEGPL_CFG:
+        ret = state->cfg;
+        break;
+    }
+#ifdef DEBUG_PCIE
+        printf("read DCR[%x(PCIE)]: %08" PRIx32 "\n", dcrn, ret);
+#endif
+
+    return ret;
+}
+
+static void dcr_write_pcie(void *opaque, int dcrn, uint32_t val)
+{
+    PPC460EXPCIEState *s = opaque;
+    uint64_t size;
+
+#ifdef DEBUG_PCIE
+    printf("write DCR[%x(PCIE)]: %08" PRIx32 "\n", dcrn, val);
+#endif
+    switch (dcrn - s->dcrn_base) {
+    case PEGPL_CFGBAH:
+        s->cfg_base = ((uint64_t)val << 32) | (s->cfg_base & 0xffffffff);
+        break;
+    case PEGPL_CFGBAL:
+        s->cfg_base = (s->cfg_base & 0xffffffff00000000ULL) | val;
+        break;
+    case PEGPL_CFGMSK:
+        s->cfg_mask = val;
+        size = ~(val & 0xfffffffe) + 1;
+#ifdef DEBUG_PCIE
+        printf("%s: %smapping cfg at %lx/%x (size=%lx)\n", __func__,
+               (val & 1 ? "" : "un"), s->cfg_base, val, size);
+#endif
+        qemu_mutex_lock_iothread();
+        pcie_host_mmcfg_update(PCIE_HOST_BRIDGE(s), val & 1, s->cfg_base, size);
+        qemu_mutex_unlock_iothread();
+        break;
+    case PEGPL_MSGBAH:
+        s->msg_base = ((uint64_t)val << 32) | (s->msg_base & 0xffffffff);
+        break;
+    case PEGPL_MSGBAL:
+        s->msg_base = (s->msg_base & 0xffffffff00000000ULL) | val;
+        break;
+    case PEGPL_MSGMSK:
+        s->msg_mask = val;
+        break;
+    case PEGPL_OMR1BAH:
+        s->omr1_base = ((uint64_t)val << 32) | (s->omr1_base & 0xffffffff);
+        break;
+    case PEGPL_OMR1BAL:
+        s->omr1_base = (s->omr1_base & 0xffffffff00000000ULL) | val;
+        break;
+    case PEGPL_OMR1MSKH:
+        s->omr1_mask = ((uint64_t)val << 32) | (s->omr1_mask & 0xffffffff);
+        break;
+    case PEGPL_OMR1MSKL:
+        s->omr1_mask = (s->omr1_mask & 0xffffffff00000000ULL) | val;
+        break;
+    case PEGPL_OMR2BAH:
+        s->omr2_base = ((uint64_t)val << 32) | (s->omr2_base & 0xffffffff);
+        break;
+    case PEGPL_OMR2BAL:
+        s->omr2_base = (s->omr2_base & 0xffffffff00000000ULL) | val;
+        break;
+    case PEGPL_OMR2MSKH:
+        s->omr2_mask = ((uint64_t)val << 32) | (s->omr2_mask & 0xffffffff);
+        break;
+    case PEGPL_OMR2MSKL:
+        s->omr2_mask = (s->omr2_mask & 0xffffffff00000000ULL) | val;
+        break;
+    case PEGPL_OMR3BAH:
+        s->omr3_base = ((uint64_t)val << 32) | (s->omr3_base & 0xffffffff);
+        break;
+    case PEGPL_OMR3BAL:
+        s->omr3_base = (s->omr3_base & 0xffffffff00000000ULL) | val;
+        break;
+    case PEGPL_OMR3MSKH:
+        s->omr3_mask = ((uint64_t)val << 32) | (s->omr3_mask & 0xffffffff);
+        break;
+    case PEGPL_OMR3MSKL:
+        s->omr3_mask = (s->omr3_mask & 0xffffffff00000000ULL) | val;
+        break;
+    case PEGPL_REGBAH:
+        s->reg_base = ((uint64_t)val << 32) | (s->reg_base & 0xffffffff);
+        break;
+    case PEGPL_REGBAL:
+        s->reg_base = (s->reg_base & 0xffffffff00000000ULL) | val;
+        break;
+    case PEGPL_REGMSK:
+        s->reg_mask = val;
+        /* FIXME: how is size encoded? */
+        size = (val == 0x7001 ? 4096 : ~(val & 0xfffffffe) + 1);
+#ifdef DEBUG_PCIE
+        printf("%s: %smapping reg at %lx/%x (size=%lx)\n", __func__,
+               (val & 1 ? "" : "un"), s->reg_base, val, size);
+#endif
+        break;
+    case PEGPL_SPECIAL:
+        s->special = val;
+        break;
+    case PEGPL_CFG:
+        s->cfg = val;
+#ifdef DEBUG_PCIE
+        dump_pcie_regs(s);
+#endif
+        break;
+    }
+}
+
+static void ppc460ex_set_irq(void *opaque, int irq_num, int level)
+{
+       PPC460EXPCIEState *s = opaque;
+       qemu_set_irq(s->irq[irq_num], level);
+}
+
+static void ppc460ex_pcie_realize(DeviceState *dev, Error **errp)
+{
+    PPC460EXPCIEState *s = PPC460EX_PCIE_HOST(dev);
+    PCIHostState *pci = PCI_HOST_BRIDGE(dev);
+    int i, id;
+    char buf[16];
+
+    switch (s->dcrn_base) {
+    case DCRN_PCIE0_BASE:
+        id = 0;
+        break;
+    case DCRN_PCIE1_BASE:
+        id = 1;
+        break;
+    }
+    snprintf(buf, sizeof(buf), "pcie%d-io", id);
+    memory_region_init(&s->iomem, OBJECT(s), buf, UINT64_MAX);
+    for (i = 0; i < 4; i++) {
+        sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]);
+    }
+    snprintf(buf, sizeof(buf), "pcie.%d", id);
+    pci->bus = pci_register_bus(DEVICE(s), buf, ppc460ex_set_irq,
+                                pci_swizzle_map_irq_fn, s, &s->iomem,
+                                get_system_io(), 0, 4, TYPE_PCIE_BUS);
+}
+
+static Property ppc460ex_pcie_props[] = {
+    DEFINE_PROP_INT32("dcrn-base", PPC460EXPCIEState, dcrn_base, -1),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ppc460ex_pcie_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
+    dc->realize = ppc460ex_pcie_realize;
+    dc->props = ppc460ex_pcie_props;
+    dc->hotpluggable = false;
+}
+
+static const TypeInfo ppc460ex_pcie_host_info = {
+    .name = TYPE_PPC460EX_PCIE_HOST,
+    .parent = TYPE_PCIE_HOST_BRIDGE,
+    .instance_size = sizeof(PPC460EXPCIEState),
+    .class_init = ppc460ex_pcie_class_init,
+};
+
+static void ppc460ex_pcie_register(void)
+{
+    type_register_static(&ppc460ex_pcie_host_info);
+}
+
+type_init(ppc460ex_pcie_register)
+
+static void ppc460ex_pcie_register_dcrs(PPC460EXPCIEState *s, CPUPPCState *env)
+{
+#ifdef DEBUG_PCIE
+    printf("%s: base=%x\n", __func__, s->dcrn_base);
+#endif
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGBAH, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGBAL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGMSK, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_MSGBAH, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_MSGBAL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_MSGMSK, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1BAH, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1BAL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1MSKH, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1MSKL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2BAH, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2BAL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2MSKH, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2MSKL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3BAH, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3BAL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3MSKH, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3MSKL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_REGBAH, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_REGBAL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_REGMSK, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_SPECIAL, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+    ppc_dcr_register(env, s->dcrn_base + PEGPL_CFG, s,
+                     &dcr_read_pcie, &dcr_write_pcie);
+}
+
+void ppc460ex_pcie_init(CPUPPCState *env)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, TYPE_PPC460EX_PCIE_HOST);
+    qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE0_BASE);
+    qdev_init_nofail(dev);
+    object_property_set_bool(OBJECT(dev), true, "realized", NULL);
+    ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), env);
+
+    dev = qdev_create(NULL, TYPE_PPC460EX_PCIE_HOST);
+    qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE1_BASE);
+    qdev_init_nofail(dev);
+    object_property_set_bool(OBJECT(dev), true, "realized", NULL);
+    ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), env);
+}
diff --git a/include/hw/pci/pcie_host.h b/include/hw/pci/pcie_host.h
index 4d23c80..3f7b988 100644
--- a/include/hw/pci/pcie_host.h
+++ b/include/hw/pci/pcie_host.h
@@ -65,7 +65,7 @@ void pcie_host_mmcfg_update(PCIExpressHost *e,
  * bit 12 - 14: function number
  * bit  0 - 11: offset in configuration space of a given device
  */
-#define PCIE_MMCFG_SIZE_MAX             (1ULL << 28)
+#define PCIE_MMCFG_SIZE_MAX             (1ULL << 29)
 #define PCIE_MMCFG_SIZE_MIN             (1ULL << 20)
 #define PCIE_MMCFG_BUS_BIT              20
 #define PCIE_MMCFG_BUS_MASK             0x1ff
-- 
2.7.6

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 13/15] ppc4xx: Add more PLB registers
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 13/15] ppc4xx: Add more PLB registers BALATON Zoltan
@ 2017-08-20 21:58   ` Philippe Mathieu-Daudé
  2017-08-20 22:12     ` BALATON Zoltan
  2017-08-23  2:40     ` David Gibson
  2017-08-23  2:39   ` David Gibson
  1 sibling, 2 replies; 66+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-08-20 21:58 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel, qemu-ppc
  Cc: Francois Revol, Alexander Graf, David Gibson

Hi Zoltan,

On 08/20/2017 02:23 PM, BALATON Zoltan wrote:
> These registers are present in 440 SoCs (and maybe in others too) and
> U-Boot accesses them when printing register info. We don't emulate
> these but add them to avoid crashing when they are read or written.

Your code isn't incorrect but it doesn't sound the right way to fix your 
problem. Your firmware shouldn't *crash* on unimplemented dcr.

Looking at ppc_dcr_read() I see that *valp isn't updated on unimp dcrn, 
while the dcr_read_plb() callback you are using return 0 on unimp (with 
an "avoid gcc warning" misleading comment).

What is the hardware behavior on implemented dcr? return 0? In that case 
this should be used in ppc_dcr_read(), also adding some 
qemu_log_mask(LOG_UNIMP,...) log entry there.

Regards,

Phil.

> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
>   hw/ppc/ppc405_uc.c | 12 +++++++++---
>   1 file changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
> index e621d0a..8e58065 100644
> --- a/hw/ppc/ppc405_uc.c
> +++ b/hw/ppc/ppc405_uc.c
> @@ -105,9 +105,12 @@ ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
>   /*****************************************************************************/
>   /* Peripheral local bus arbitrer */
>   enum {
> -    PLB0_BESR = 0x084,
> -    PLB0_BEAR = 0x086,
> -    PLB0_ACR  = 0x087,
> +    PLB3A0_ACR = 0x077,
> +    PLB4A0_ACR = 0x081,
> +    PLB0_BESR  = 0x084,
> +    PLB0_BEAR  = 0x086,
> +    PLB0_ACR   = 0x087,
> +    PLB4A1_ACR = 0x089,
>   };
>   
>   typedef struct ppc4xx_plb_t ppc4xx_plb_t;
> @@ -179,9 +182,12 @@ void ppc4xx_plb_init(CPUPPCState *env)
>       ppc4xx_plb_t *plb;
>   
>       plb = g_malloc0(sizeof(ppc4xx_plb_t));
> +    ppc_dcr_register(env, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
> +    ppc_dcr_register(env, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>       ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>       ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
>       ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
> +    ppc_dcr_register(env, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>       qemu_register_reset(ppc4xx_plb_reset, plb);
>   }
>   
> 

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 15/15] ppc: Add aCube Sam460ex board
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 15/15] ppc: Add aCube Sam460ex board BALATON Zoltan
@ 2017-08-20 22:10   ` Philippe Mathieu-Daudé
  2017-08-23  4:16   ` David Gibson
  1 sibling, 0 replies; 66+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-08-20 22:10 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel, qemu-ppc
  Cc: Francois Revol, Alexander Graf, David Gibson

Hi Zoltan,

On 08/20/2017 02:23 PM, BALATON Zoltan wrote:
> Add emulation of aCube Sam460ex board based on AMCC 460EX embedded SoC.
> This is not a full implementation yet with a lot of components still
> missing but enough to start a Linux kernel and the U-Boot firmware.
> 
> Signed-off-by: François Revol <revol@free.fr>
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
>   default-configs/ppcemb-softmmu.mak |   3 +
>   hw/ppc/Makefile.objs               |   2 +
>   hw/ppc/sam460ex.c                  | 611 +++++++++++++++++++++++++++++++++++++
>   3 files changed, 616 insertions(+)
>   create mode 100644 hw/ppc/sam460ex.c
> 
> diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
> index 635923a..90b42f0 100644
> --- a/default-configs/ppcemb-softmmu.mak
> +++ b/default-configs/ppcemb-softmmu.mak
> @@ -17,3 +17,6 @@ CONFIG_XILINX=y
>   CONFIG_XILINX_ETHLITE=y
>   CONFIG_LIBDECNUMBER=y
>   CONFIG_SM501=y
> +CONFIG_USB_EHCI_SYSBUS=y
> +CONFIG_IDE_SII3112=y
> +CONFIG_SAM460EX=y
> diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
> index fc39fe4..0aaea5b 100644
> --- a/hw/ppc/Makefile.objs
> +++ b/hw/ppc/Makefile.objs
> @@ -27,3 +27,5 @@ obj-$(CONFIG_E500) += e500.o mpc8544ds.o e500plat.o
>   obj-$(CONFIG_E500) += mpc8544_guts.o ppce500_spin.o
>   # PowerPC 440 Xilinx ML507 reference board.
>   obj-$(CONFIG_XILINX) += virtex_ml507.o
> +# ACube Sam460ex board.
> +obj-$(CONFIG_SAM460EX) += ppc440_uc.o sam460ex.o
> diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
> new file mode 100644
> index 0000000..7cf4f6f
> --- /dev/null
> +++ b/hw/ppc/sam460ex.c
> @@ -0,0 +1,611 @@
> +/*
> + * QEMU aCube Sam460ex board emulation
> + *
> + * Copyright (c) 2012 François Revol
> + * Copyright (c) 2016-2017 BALATON Zoltan
> + *
> + * This file is derived from hw/ppc440_bamboo.c,
> + * the copyright for that material belongs to the original owners.
> + *
> + * This work is licensed under the GNU GPL license version 2 or later.
> + *
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu-common.h"
> +#include "qemu/cutils.h"
> +#include "qapi/error.h"
> +#include "hw/hw.h"
> +#include "sysemu/blockdev.h"
> +#include "hw/boards.h"
> +#include "sysemu/kvm.h"
> +#include "kvm_ppc.h"
> +#include "sysemu/device_tree.h"
> +#include "sysemu/block-backend.h"
> +#include "hw/loader.h"
> +#include "elf.h"
> +#include "exec/address-spaces.h"
> +#include "exec/memory.h"
> +#include "hw/ppc/ppc440.h"
> +#include "hw/ppc/ppc405.h"
> +#include "hw/block/flash.h"
> +#include "sysemu/sysemu.h"
> +#include "hw/sysbus.h"
> +#include "hw/char/serial.h"
> +#include "hw/i2c/ppc4xx_i2c.h"
> +#include "hw/i2c/smbus.h"
> +#include "hw/usb/hcd-ehci.h"
> +
> +#define BINARY_DEVICE_TREE_FILE "sam460ex.dtb"
> +#define UBOOT_FILENAME "u-boot-sam460-20100605.bin"
> +/* to extract the official U-Boot bin from the updater: */
> +/* dd bs=1 skip=$(($(stat -c '%s' updater/updater-460) - 0x80000)) \
> +     if=updater/updater-460 of=u-boot-sam460-20100605.bin */
> +
> +/* from Sam460 U-Boot include/configs/Sam460ex.h */
> +#define FLASH_BASE             0xfff00000
> +#define FLASH_BASE_H           0x4
> +#define FLASH_SIZE             (1 << 20)
> +#define UBOOT_LOAD_BASE        0xfff80000
> +#define UBOOT_SIZE             0x00080000
> +#define UBOOT_ENTRY            0xfffffffc
> +
> +/* from U-Boot */
> +#define EPAPR_MAGIC           (0x45504150)
> +#define KERNEL_ADDR           0x1000000
> +#define FDT_ADDR              0x1800000
> +#define RAMDISK_ADDR          0x1900000
> +
> +/* Sam460ex IRQ MAP:
> +   IRQ0  = ETH_INT
> +   IRQ1  = FPGA_INT
> +   IRQ2  = PCI_INT (PCIA, PCIB, PCIC, PCIB)
> +   IRQ3  = FPGA_INT2
> +   IRQ11 = RTC_INT
> +   IRQ12 = SM502_INT
> +*/
> +
> +#define SDRAM_NR_BANKS 4
> +
> +/* FIXME: See u-boot.git 8ac41e */
> +static const unsigned int ppc460ex_sdram_bank_sizes[] = {
> +    1024 << 20, 512 << 20, 256 << 20, 128 << 20, 64 << 20, 32 << 20, 0
> +};
> +
> +struct boot_info {
> +    uint32_t dt_base;
> +    uint32_t dt_size;
> +    uint32_t entry;
> +};
> +
> +/*****************************************************************************/
> +/* SPD eeprom content from mips_malta.c */
> +
> +struct _eeprom24c0x_t {
> +  uint8_t tick;
> +  uint8_t address;
> +  uint8_t command;
> +  uint8_t ack;
> +  uint8_t scl;
> +  uint8_t sda;
> +  uint8_t data;
> +  uint8_t contents[256];
> +};
> +
> +typedef struct _eeprom24c0x_t eeprom24c0x_t;
> +
> +static eeprom24c0x_t spd_eeprom = {
> +    .contents = {
> +        /* 00000000: */ 0x80, 0x08, 0xFF, 0x0D, 0x0A, 0xFF, 0x40, 0x00,
> +        /* 00000008: */ 0x04, 0x75, 0x54, 0x00, 0x82, 0x08, 0x00, 0x01,
> +        /* 00000010: */ 0x8F, 0x04, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00,
> +        /* 00000018: */ 0x00, 0x00, 0x00, 0x14, 0x0F, 0x14, 0x2D, 0xFF,
> +        /* 00000020: */ 0x15, 0x08, 0x15, 0x08, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xD0,
> +        /* 00000040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xF4,
> +    },
> +};
> +
> +static void generate_eeprom_spd(uint8_t *eeprom, ram_addr_t ram_size)
> +{
> +    enum { SDR = 0x4, DDR1 = 0x7, DDR2 = 0x8 } type;
> +    uint8_t *spd = spd_eeprom.contents;
> +    uint8_t nbanks = 0;
> +    uint16_t density = 0;
> +    int i;
> +
> +    /* work in terms of MB */
> +    ram_size >>= 20;
> +
> +    while ((ram_size >= 4) && (nbanks <= 2)) {
> +        int sz_log2 = MIN(31 - clz32(ram_size), 14);
> +        nbanks++;
> +        density |= 1 << (sz_log2 - 2);
> +        ram_size -= 1 << sz_log2;
> +    }
> +
> +    /* split to 2 banks if possible */
> +    if ((nbanks == 1) && (density > 1)) {
> +        nbanks++;
> +        density >>= 1;
> +    }
> +
> +    if (density & 0xff00) {
> +        density = (density & 0xe0) | ((density >> 8) & 0x1f);
> +        type = DDR2;
> +    } else if (!(density & 0x1f)) {
> +        type = DDR2;
> +    } else {
> +        type = SDR;
> +    }
> +
> +    if (ram_size) {
> +        fprintf(stderr, "Warning: SPD cannot represent final %dMB"
> +                " of SDRAM\n", (int)ram_size);
> +    }
> +
> +    /* fill in SPD memory information */
> +    spd[2] = type;
> +    spd[5] = nbanks;
> +    spd[31] = density;
> +#ifdef DEBUG_SDRAM
> +    printf("SPD: nbanks %d density %d\n", nbanks, density);
> +#endif
> +    /* XXX: this is totally random */
> +    spd[9] = 0x10; /* CAS tcyc */
> +    spd[18] = 0x20; /* CAS bit */
> +    spd[23] = 0x10; /* CAS tcyc */
> +    spd[25] = 0x10; /* CAS tcyc */
> +
> +    /* checksum */
> +    spd[63] = 0;
> +    for (i = 0; i < 63; i++) {
> +        spd[63] += spd[i];
> +    }
> +
> +    /* copy for SMBUS */
> +    memcpy(eeprom, spd, sizeof(spd_eeprom.contents));
> +}
> +
> +static void generate_eeprom_serial(uint8_t *eeprom)
> +{
> +    int i, pos = 0;
> +    uint8_t mac[6] = { 0x00 };
> +    uint8_t sn[5] = { 0x01, 0x23, 0x45, 0x67, 0x89 };
> +
> +    /* version */
> +    eeprom[pos++] = 0x01;
> +
> +    /* count */
> +    eeprom[pos++] = 0x02;
> +
> +    /* MAC address */
> +    eeprom[pos++] = 0x01; /* MAC */
> +    eeprom[pos++] = 0x06; /* length */
> +    memcpy(&eeprom[pos], mac, sizeof(mac));
> +    pos += sizeof(mac);
> +
> +    /* serial number */
> +    eeprom[pos++] = 0x02; /* serial */
> +    eeprom[pos++] = 0x05; /* length */
> +    memcpy(&eeprom[pos], sn, sizeof(sn));
> +    pos += sizeof(sn);
> +
> +    /* checksum */
> +    eeprom[pos] = 0;
> +    for (i = 0; i < pos; i++) {
> +        eeprom[pos] += eeprom[i];
> +    }
> +}
> +
> +/*****************************************************************************/
> +
> +static int sam460ex_load_uboot(void)
> +{
> +    DriveInfo *dinfo;
> +    BlockBackend *blk = NULL;
> +    hwaddr base = FLASH_BASE | ((hwaddr)FLASH_BASE_H << 32);
> +    long bios_size = FLASH_SIZE;
> +    int fl_sectors;
> +
> +    dinfo = drive_get(IF_PFLASH, 0, 0);
> +    if (dinfo) {
> +        blk = blk_by_legacy_dinfo(dinfo);
> +        bios_size = blk_getlength(blk);
> +    }
> +    fl_sectors = (bios_size + 65535) >> 16;
> +
> +    if (!pflash_cfi01_register(base, NULL, "sam460ex.flash", bios_size,
> +                               blk, (64 * 1024), fl_sectors,
> +                               1, 0x89, 0x18, 0x0000, 0x0, 1)) {
> +        fprintf(stderr, "qemu: Error registering flash memory.\n");
> +        /* XXX: return an error instead? */
> +        exit(1);
> +    }
> +
> +    if (!blk) {
> +        /*fprintf(stderr, "No flash image given with the 'pflash' parameter,"
> +                " using default u-boot image\n");*/
> +        base = UBOOT_LOAD_BASE | ((hwaddr)FLASH_BASE_H << 32);
> +        rom_add_file_fixed(UBOOT_FILENAME, base, -1);
> +    }
> +
> +    return 0;
> +}
> +
> +static int sam460ex_load_device_tree(hwaddr addr,

This function looks generic enough to go in hw/ppc/loader.c eventually.

> +                                     uint32_t ramsize,
> +                                     hwaddr initrd_base,
> +                                     hwaddr initrd_size,
> +                                     const char *kernel_cmdline)
> +{
> +    int ret = -1;
> +    uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) };
> +    char *filename;
> +    int fdt_size;
> +    void *fdt;
> +    uint32_t tb_freq = 400000000;
> +    uint32_t clock_freq = 400000000;
> +
> +    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
> +    if (!filename) {
> +        goto out;
> +    }
> +    fdt = load_device_tree(filename, &fdt_size);
> +    g_free(filename);
> +    if (fdt == NULL) {
> +        goto out;
> +    }
> +
> +    /* Manipulate device tree in memory. */
> +
> +    ret = qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property,
> +                               sizeof(mem_reg_property));
> +    if (ret < 0) {
> +        fprintf(stderr, "couldn't set /memory/reg\n");
> +    }
> +
> +    /* default FDT doesn't have a /chosen node... */
> +    qemu_fdt_add_subnode(fdt, "/chosen");
> +
> +    ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
> +                                    initrd_base);
> +    if (ret < 0) {
> +        fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
> +    }
> +
> +    ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
> +                                    (initrd_base + initrd_size));
> +    if (ret < 0) {
> +        fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
> +    }
> +
> +    ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
> +                                      kernel_cmdline);
> +    if (ret < 0) {
> +        fprintf(stderr, "couldn't set /chosen/bootargs\n");
> +    }
> +
> +    /* Copy data from the host device tree into the guest. Since the guest can
> +     * directly access the timebase without host involvement, we must expose
> +     * the correct frequencies. */
> +    if (kvm_enabled()) {
> +        tb_freq = kvmppc_get_tbfreq();
> +        clock_freq = kvmppc_get_clockfreq();
> +    }
> +
> +    qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency",
> +                              clock_freq);
> +    qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency",
> +                              tb_freq);
> +
> +    rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
> +    g_free(fdt);
> +    ret = fdt_size;
> +
> +out:
> +
> +    return ret;
> +}
> +
> +/* Create reset TLB entries for BookE, mapping only the flash memory.  */
> +static void mmubooke_create_initial_mapping_uboot(CPUPPCState *env)
> +{
> +    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
> +
> +    /* on reset the flash is mapped by a shadow TLB,
> +     * but since we don't implement them we need to use
> +     * the same values U-Boot will use to avoid a fault.
> +     */
> +    tlb->attr = 0;
> +    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
> +    tlb->size = 0x10000000; /* up to 0xffffffff  */
> +    tlb->EPN = 0xf0000000 & TARGET_PAGE_MASK;
> +    tlb->RPN = (0xf0000000 & TARGET_PAGE_MASK) | 0x4;
> +    tlb->PID = 0;
> +}
> +
> +/* Create reset TLB entries for BookE, spanning the 32bit addr space.  */
> +static void mmubooke_create_initial_mapping(CPUPPCState *env,
> +                                     target_ulong va,
> +                                     hwaddr pa)
> +{
> +    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
> +
> +    tlb->attr = 0;
> +    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
> +    tlb->size = 1 << 31; /* up to 0x80000000  */
> +    tlb->EPN = va & TARGET_PAGE_MASK;
> +    tlb->RPN = pa & TARGET_PAGE_MASK;
> +    tlb->PID = 0;
> +}
> +
> +static void main_cpu_reset(void *opaque)
> +{
> +    PowerPCCPU *cpu = opaque;
> +    CPUPPCState *env = &cpu->env;
> +    struct boot_info *bi = env->load_info;
> +
> +    cpu_reset(CPU(cpu));
> +
> +    /* either we have a kernel to boot or we jump to U-Boot */
> +    if (bi->entry != UBOOT_ENTRY) {
> +        env->gpr[1] = (16 << 20) - 8;
> +        env->gpr[3] = FDT_ADDR;
> +
> +        fprintf(stderr, "cpu reset: kernel entry %x\n", bi->entry);
> +        env->nip = bi->entry;
> +
> +        /* Create a mapping for the kernel.  */
> +        mmubooke_create_initial_mapping(env, 0, 0);
> +        env->gpr[6] = tswap32(EPAPR_MAGIC);
> +        env->gpr[7] = (16 << 20) - 8; /*bi->ima_size;*/
> +
> +    } else {
> +        env->nip = UBOOT_ENTRY;
> +        mmubooke_create_initial_mapping_uboot(env);
> +        fprintf(stderr, "cpu reset: U-Boot entry\n");
> +    }
> +}
> +
> +static void sam460ex_init(MachineState *machine)
> +{
> +    MemoryRegion *address_space_mem = get_system_memory();
> +    MemoryRegion *isa = g_new(MemoryRegion, 1);
> +    MemoryRegion *ram_memories = g_new(MemoryRegion, SDRAM_NR_BANKS);
> +    hwaddr ram_bases[SDRAM_NR_BANKS];
> +    hwaddr ram_sizes[SDRAM_NR_BANKS];
> +    MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1);
> +    qemu_irq *irqs, *uic[4];
> +    PCIBus *pci_bus;
> +    PowerPCCPU *cpu;
> +    CPUPPCState *env;
> +    PPC4xxI2CState *i2c[2];
> +    hwaddr entry = UBOOT_ENTRY;
> +    hwaddr loadaddr = 0;
> +    target_long initrd_size = 0;
> +    DeviceState *dev;
> +    SysBusDevice *sbdev;
> +    int success;
> +    int i;
> +    struct boot_info *boot_info;
> +    const size_t smbus_eeprom_size = 8 * 256;
> +    uint8_t *smbus_eeprom_buf = g_malloc0(smbus_eeprom_size);
> +
> +    /* Setup CPU. */
> +    if (machine->cpu_model == NULL) {
> +        machine->cpu_model = "460EX";
> +    }
> +    cpu = cpu_ppc_init(machine->cpu_model);
> +    if (cpu == NULL) {
> +        fprintf(stderr, "Unable to initialize CPU!\n");
> +        exit(1);
> +    }
> +    env = &cpu->env;
> +
> +    qemu_register_reset(main_cpu_reset, cpu);
> +    boot_info = g_malloc0(sizeof(*boot_info));
> +    env->load_info = boot_info;
> +
> +    ppc_booke_timers_init(cpu, 50000000, 0);
> +    ppc_dcr_init(env, NULL, NULL);
> +
> +    /* PLB arbitrer */
> +    ppc4xx_plb_init(env);
> +
> +    /* interrupt controllers */
> +    irqs = g_malloc0(sizeof(*irqs) * PPCUIC_OUTPUT_NB);
> +    irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
> +    irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
> +    uic[0] = ppcuic_init(env, irqs, 0x0C0, 0, 1);
> +    uic[1] = ppcuic_init(env, &uic[0][30], 0x0D0, 0, 1);
> +    uic[2] = ppcuic_init(env, &uic[0][10], 0x0E0, 0, 1);
> +    uic[3] = ppcuic_init(env, &uic[0][16], 0x0F0, 0, 1);
> +
> +    /* SDRAM controller */
> +    memset(ram_bases, 0, sizeof(ram_bases));
> +    memset(ram_sizes, 0, sizeof(ram_sizes));
> +    /* put all RAM on first bank because board has one slot
> +     * and firmware only checks that */
> +    machine->ram_size = ppc4xx_sdram_adjust(machine->ram_size,
> +                                   1/*SDRAM_NR_BANKS*/,
> +                                   ram_memories,
> +                                   ram_bases, ram_sizes,
> +                                   ppc460ex_sdram_bank_sizes);
> +#ifdef DEBUG_SDRAM
> +    printf("RAMSIZE %dMB\n", (int)(machine->ram_size / M_BYTE));
> +#endif
> +
> +    /* XXX does 460EX have ECC interrupts? */
> +    ppc440_sdram_init(env, SDRAM_NR_BANKS, ram_memories,
> +                      ram_bases, ram_sizes, 1);
> +
> +    /* generate SPD EEPROM data */
> +    for (i = 0; i < SDRAM_NR_BANKS; i++) {
> +#ifdef DEBUG_SDRAM
> +        printf("bank %d: %" HWADDR_PRIx "\n", i, ram_sizes[i]);
> +#endif
> +        generate_eeprom_spd(&smbus_eeprom_buf[i * 256], ram_sizes[i]);
> +    }
> +    generate_eeprom_serial(&smbus_eeprom_buf[4 * 256]);
> +    generate_eeprom_serial(&smbus_eeprom_buf[6 * 256]);
> +
> +    /* IIC controllers */
> +    dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700, uic[0][2]);
> +    i2c[0] = PPC4xx_I2C(dev);
> +    object_property_set_bool(OBJECT(dev), true, "realized", NULL);
> +    smbus_eeprom_init(i2c[0]->bus, 8, smbus_eeprom_buf, smbus_eeprom_size);
> +    g_free(smbus_eeprom_buf);
> +
> +    dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600800, uic[0][3]);
> +    i2c[1] = PPC4xx_I2C(dev);
> +
> +    /* External bus controller */
> +    ppc405_ebc_init(env);
> +
> +    /* CPR */
> +    ppc4xx_cpr_init(env);
> +
> +    /* PLB to AHB bridge */
> +    ppc4xx_ahb_init(env);
> +
> +    /* System DCRs */
> +    ppc4xx_sdr_init(env);
> +
> +    /* MAL */
> +    ppc4xx_mal_init(env, 4, 16, &uic[2][3]);
> +
> +    /* 256K of L2 cache as memory */
> +    ppc4xx_l2sram_init(env);
> +    /* FIXME: remove this after fixing l2sram mapping in ppc440_uc.c? */
> +    memory_region_init_ram(l2cache_ram, NULL, "ppc440.l2cache_ram", 256 << 10,
> +                           &error_abort);
> +    memory_region_add_subregion(address_space_mem, 0x400000000LL, l2cache_ram);
> +
> +    /* USB */
> +    sysbus_create_simple(TYPE_PPC4xx_EHCI, 0x4bffd0400, uic[2][29]);
> +    dev = qdev_create(NULL, "sysbus-ohci");
> +    qdev_prop_set_string(dev, "masterbus", "usb-bus.0");
> +    qdev_prop_set_uint32(dev, "num-ports", 6);
> +    qdev_init_nofail(dev);
> +    sbdev = SYS_BUS_DEVICE(dev);
> +    sysbus_mmio_map(sbdev, 0, 0x4bffd0000);
> +    sysbus_connect_irq(sbdev, 0, uic[2][30]);
> +    usb_create_simple(usb_bus_find(-1), "usb-kbd");
> +    usb_create_simple(usb_bus_find(-1), "usb-mouse");
> +
> +    /* PCI bus */
> +    ppc460ex_pcie_init(env);
> +    /*XXX: FIXME: is this correct? */
> +    dev = sysbus_create_varargs("ppc440-pcix-host", 0xc0ec00000,
> +                                uic[1][0], uic[1][20], uic[1][21], uic[1][22],
> +                                NULL);
> +    pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
> +    if (!pci_bus) {
> +        fprintf(stderr, "couldn't create PCI controller!\n");
> +        exit(1);
> +    }
> +    memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(),
> +                             0, 0x10000);
> +    memory_region_add_subregion(get_system_memory(), 0xc08000000, isa);
> +
> +    /* PCI devices */
> +    pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "sm501");
> +    /* SoC has a single SATA port but we don't emulate that yet
> +     * However, firmware and usual clients have driver for SiI311x
> +     * so add one for convenience by default */
> +    pci_create_simple(pci_bus, -1, "sii3112");
> +
> +    /* SoC has 4 UARTs
> +     * but board has only one wired and two are present in fdt */
> +    if (serial_hds[0] != NULL) {
> +        serial_mm_init(address_space_mem, 0x4ef600300, 0, uic[1][1],
> +                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
> +                       DEVICE_BIG_ENDIAN);
> +    }
> +    if (serial_hds[1] != NULL) {
> +        serial_mm_init(address_space_mem, 0x4ef600400, 0, uic[0][1],
> +                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
> +                       DEVICE_BIG_ENDIAN);
> +    }
> +
> +    /* Load U-Boot image. */
> +    if (!machine->kernel_filename) {
> +        success = sam460ex_load_uboot();
> +        if (success < 0) {
> +            fprintf(stderr, "qemu: could not load firmware\n");
> +            exit(1);
> +        }
> +    }
> +
> +    /* Load kernel. */
> +    if (machine->kernel_filename) {
> +        success = load_uimage(machine->kernel_filename, &entry, &loadaddr, NULL,
> +            NULL, NULL);
> +        fprintf(stderr, "load_uimage: %d\n", success);
> +        if (success < 0) {
> +            uint64_t elf_entry, elf_lowaddr;
> +
> +            success = load_elf(machine->kernel_filename, NULL, NULL, &elf_entry,
> +                               &elf_lowaddr, NULL, 1, PPC_ELF_MACHINE, 0, 0);
> +            fprintf(stderr, "load_elf: %d\n", success);
> +            entry = elf_entry;
> +            loadaddr = elf_lowaddr;
> +        }
> +        /* XXX try again as binary */
> +        if (success < 0) {
> +            fprintf(stderr, "qemu: could not load kernel '%s'\n",
> +                    machine->kernel_filename);
> +            exit(1);
> +        }
> +    }
> +
> +    /* Load initrd. */
> +    if (machine->initrd_filename) {
> +        initrd_size = load_image_targphys(machine->initrd_filename,
> +                                          RAMDISK_ADDR,
> +                                          machine->ram_size - RAMDISK_ADDR);
> +        fprintf(stderr, "load_image: %d\n", initrd_size);
> +        if (initrd_size < 0) {
> +            fprintf(stderr, "qemu: could not load ram disk '%s' at %x\n",
> +                    machine->initrd_filename, RAMDISK_ADDR);
> +            exit(1);
> +        }
> +    }
> +
> +    /* If we're loading a kernel directly, we must load the device tree too. */
> +    if (machine->kernel_filename) {
> +        int dt_size;
> +
> +        dt_size = sam460ex_load_device_tree(FDT_ADDR, machine->ram_size,
> +                                    RAMDISK_ADDR, initrd_size,
> +                                    machine->kernel_cmdline);
> +        if (dt_size < 0) {
> +            fprintf(stderr, "couldn't load device tree\n");
> +            exit(1);
> +        }
> +
> +        boot_info->dt_base = FDT_ADDR;
> +        boot_info->dt_size = dt_size;
> +    }
> +
> +    boot_info->entry = entry;
> +}
> +
> +static void sam460ex_machine_init(MachineClass *mc)
> +{
> +    mc->desc = "aCube Sam460ex";
> +    mc->init = sam460ex_init;
> +    mc->default_ram_size = 512 * M_BYTE;
> +}
> +
> +DEFINE_MACHINE("sam460ex", sam460ex_machine_init)
> 

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 13/15] ppc4xx: Add more PLB registers
  2017-08-20 21:58   ` Philippe Mathieu-Daudé
@ 2017-08-20 22:12     ` BALATON Zoltan
  2017-08-23  2:40     ` David Gibson
  1 sibling, 0 replies; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-20 22:12 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: qemu-devel, qemu-ppc, Francois Revol, Alexander Graf, David Gibson

On Sun, 20 Aug 2017, Philippe Mathieu-Daudé wrote:
> On 08/20/2017 02:23 PM, BALATON Zoltan wrote:
>> These registers are present in 440 SoCs (and maybe in others too) and
>> U-Boot accesses them when printing register info. We don't emulate
>> these but add them to avoid crashing when they are read or written.
>
> Your code isn't incorrect but it doesn't sound the right way to fix your 
> problem. Your firmware shouldn't *crash* on unimplemented dcr.

The firmware shouldn't crash but it's just isn't written expecting missing 
DCRs (and we aim to run the board's patched U-Boot version as it is 
because it is needed by the OSes running on the board). QEMU makes it 
crash by raising an exception for unknown DCRs, I think in 
target/ppc/timebase_helper.c:150

> Looking at ppc_dcr_read() I see that *valp isn't updated on unimp dcrn, while 
> the dcr_read_plb() callback you are using return 0 on unimp (with an "avoid 
> gcc warning" misleading comment).
>
> What is the hardware behavior on implemented dcr? return 0? In that case this 
> should be used in ppc_dcr_read(), also adding some 
> qemu_log_mask(LOG_UNIMP,...) log entry there.

Of course the right way would be to emulate what these registers do on 
hardware but I don't know what the hardware does and for a lot of DCRs the 
firmware just writes some values to initialise the hadware which is not 
needed on QEMU so we can just do read zero, ignore writes which we are 
doing here. (That's what I was trying to say in the commit message too.) 
Actually these registers aren't even used by the firmware, only included 
in register dumps so this should be safe until we find something tries to 
use it.

> Regards,
>
> Phil.
>
>> 
>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>> ---
>>   hw/ppc/ppc405_uc.c | 12 +++++++++---
>>   1 file changed, 9 insertions(+), 3 deletions(-)
>> 
>> diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
>> index e621d0a..8e58065 100644
>> --- a/hw/ppc/ppc405_uc.c
>> +++ b/hw/ppc/ppc405_uc.c
>> @@ -105,9 +105,12 @@ ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, 
>> ppc4xx_bd_info_t *bd,
>>   /*****************************************************************************/
>>   /* Peripheral local bus arbitrer */
>>   enum {
>> -    PLB0_BESR = 0x084,
>> -    PLB0_BEAR = 0x086,
>> -    PLB0_ACR  = 0x087,
>> +    PLB3A0_ACR = 0x077,
>> +    PLB4A0_ACR = 0x081,
>> +    PLB0_BESR  = 0x084,
>> +    PLB0_BEAR  = 0x086,
>> +    PLB0_ACR   = 0x087,
>> +    PLB4A1_ACR = 0x089,
>>   };
>>     typedef struct ppc4xx_plb_t ppc4xx_plb_t;
>> @@ -179,9 +182,12 @@ void ppc4xx_plb_init(CPUPPCState *env)
>>       ppc4xx_plb_t *plb;
>>         plb = g_malloc0(sizeof(ppc4xx_plb_t));
>> +    ppc_dcr_register(env, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>> +    ppc_dcr_register(env, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>>       ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>>       ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
>>       ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
>> +    ppc_dcr_register(env, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>>       qemu_register_reset(ppc4xx_plb_reset, plb);
>>   }
>> 
>
>

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 10/15] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 10/15] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs BALATON Zoltan
@ 2017-08-20 22:20   ` Philippe Mathieu-Daudé
  2017-08-24 22:12     ` BALATON Zoltan
  2017-08-23  0:49   ` David Gibson
  1 sibling, 1 reply; 66+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-08-20 22:20 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel, qemu-ppc
  Cc: Francois Revol, Alexander Graf, David Gibson

Hi Zoltan,

On 08/20/2017 02:23 PM, BALATON Zoltan wrote:
> This is the PCIX controller found in newer 440 core SoCs e.g. the AMMC
> 460EX. The device tree refers to this as plb-pcix compared to the
> plb-pci controller in older 440 SoCs.
> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
>   hw/ppc/Makefile.objs |   2 +-
>   hw/ppc/ppc440_pcix.c | 516 +++++++++++++++++++++++++++++++++++++++++++++++++++
>   2 files changed, 517 insertions(+), 1 deletion(-)
>   create mode 100644 hw/ppc/ppc440_pcix.c
> 
> diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
> index 7efc686..fc39fe4 100644
> --- a/hw/ppc/Makefile.objs
> +++ b/hw/ppc/Makefile.objs
> @@ -13,7 +13,7 @@ endif
>   obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o
>   # PowerPC 4xx boards
>   obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
> -obj-y += ppc4xx_pci.o
> +obj-y += ppc4xx_pci.o ppc440_pcix.o
>   # PReP
>   obj-$(CONFIG_PREP) += prep.o
>   obj-$(CONFIG_PREP) += prep_systemio.o
> diff --git a/hw/ppc/ppc440_pcix.c b/hw/ppc/ppc440_pcix.c
> new file mode 100644
> index 0000000..5c2ceec
> --- /dev/null
> +++ b/hw/ppc/ppc440_pcix.c
> @@ -0,0 +1,516 @@
> +/*
> + * Emulation of the ibm,plb-pcix PCI controller
> + * This is found in some 440 SoCs e.g. the 460EX.
> + *
> + * Copyright (c) 2016 BALATON Zoltan
> + *
> + * Derived from ppc4xx_pci.c and pci-host/ppce500.c
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License, version 2, as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/error-report.h"
> +#include "hw/hw.h"
> +#include "hw/ppc/ppc.h"
> +#include "hw/ppc/ppc4xx.h"
> +#include "hw/pci/pci.h"
> +#include "hw/pci/pci_host.h"
> +#include "exec/address-spaces.h"
> +
> +/*#define DEBUG_PCI*/
> +
> +#ifdef DEBUG_PCI
> +#define DPRINTF(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__);
> +#else
> +#define DPRINTF(fmt, ...)
> +#endif /* DEBUG */
> +
> +struct PLBOutMap {
> +    uint64_t la;
> +    uint64_t pcia;
> +    uint32_t sa;
> +    MemoryRegion mr;
> +};
> +
> +struct PLBInMap {
> +    uint64_t sa;
> +    uint64_t la;
> +    MemoryRegion mr;
> +};
> +
> +#define TYPE_PPC440_PCIX_HOST_BRIDGE "ppc440-pcix-host"
> +#define PPC440_PCIX_HOST_BRIDGE(obj) \
> +    OBJECT_CHECK(PPC440PCIXState, (obj), TYPE_PPC440_PCIX_HOST_BRIDGE)
> +
> +#define PPC440_PCIX_NR_POMS 3
> +#define PPC440_PCIX_NR_PIMS 3
> +
> +typedef struct PPC440PCIXState {
> +    PCIHostState parent_obj;
> +
> +    PCIDevice *dev;
> +    struct PLBOutMap pom[PPC440_PCIX_NR_POMS];
> +    struct PLBInMap pim[PPC440_PCIX_NR_PIMS];
> +    uint32_t sts;
> +    qemu_irq irq[PCI_NUM_PINS];
> +    AddressSpace bm_as;
> +    MemoryRegion bm;
> +
> +    MemoryRegion container;
> +    MemoryRegion iomem;
> +    MemoryRegion busmem;
> +} PPC440PCIXState;
> +
> +#define PPC440_REG_BASE     0x80000
> +#define PPC440_REG_SIZE     0xff
> +
> +#define PCIC0_CFGADDR       0x0
> +#define PCIC0_CFGDATA       0x4
> +
> +#define PCIX0_POM0LAL       0x68
> +#define PCIX0_POM0LAH       0x6c
> +#define PCIX0_POM0SA        0x70
> +#define PCIX0_POM0PCIAL     0x74
> +#define PCIX0_POM0PCIAH     0x78
> +#define PCIX0_POM1LAL       0x7c
> +#define PCIX0_POM1LAH       0x80
> +#define PCIX0_POM1SA        0x84
> +#define PCIX0_POM1PCIAL     0x88
> +#define PCIX0_POM1PCIAH     0x8c
> +#define PCIX0_POM2SA        0x90
> +
> +#define PCIX0_PIM0SAL       0x98
> +#define PCIX0_PIM0LAL       0x9c
> +#define PCIX0_PIM0LAH       0xa0
> +#define PCIX0_PIM1SA        0xa4
> +#define PCIX0_PIM1LAL       0xa8
> +#define PCIX0_PIM1LAH       0xac
> +#define PCIX0_PIM2SAL       0xb0
> +#define PCIX0_PIM2LAL       0xb4
> +#define PCIX0_PIM2LAH       0xb8
> +#define PCIX0_PIM0SAH       0xf8
> +#define PCIX0_PIM2SAH       0xfc
> +
> +#define PCIX0_STS           0xe0
> +
> +#define PCI_ALL_SIZE        (PPC440_REG_BASE + PPC440_REG_SIZE)
> +
> +static void ppc440_pcix_clear_region(MemoryRegion *parent,
> +                                     MemoryRegion *mem)
> +{
> +    if (memory_region_is_mapped(mem)) {
> +        memory_region_del_subregion(parent, mem);
> +        object_unparent(OBJECT(mem));
> +    }
> +}
> +
> +/* DMA mapping */
> +static void ppc440_pcix_update_pim(PPC440PCIXState *s, int idx)
> +{
> +    MemoryRegion *mem = &s->pim[idx].mr;
> +    char *name;
> +    uint64_t size;
> +
> +    /* Before we modify anything, unmap and destroy the region */
> +    ppc440_pcix_clear_region(&s->bm, mem);
> +
> +    if (!(s->pim[idx].sa & 1)) {
> +        /* Not enabled, nothing to do */
> +        return;
> +    }
> +
> +    name = g_strdup_printf("PCI Inbound Window %d", idx);
> +    size = ~(s->pim[idx].sa & ~7ULL) + 1;
> +    memory_region_init_alias(mem, OBJECT(s), name, get_system_memory(),
> +                             s->pim[idx].la, size);
> +    memory_region_add_subregion_overlap(&s->bm, 0, mem, -1);
> +    g_free(name);
> +
> +    DPRINTF("%s: Added window %d of size=%#"PRIx64" to CPU=%#"PRIx64"\n",
> +            __func__, idx, size, s->pim[idx].la);
> +}
> +
> +/* BAR mapping */
> +static void ppc440_pcix_update_pom(PPC440PCIXState *s, int idx)
> +{
> +    MemoryRegion *mem = &s->pom[idx].mr;
> +    MemoryRegion *address_space_mem = get_system_memory();
> +    char *name;
> +    uint32_t size;
> +
> +    /* Before we modify anything, unmap and destroy the region */
> +    ppc440_pcix_clear_region(address_space_mem, mem);
> +
> +    if (!(s->pom[idx].sa & 1)) {
> +        /* Not enabled, nothing to do */
> +        return;
> +    }
> +
> +    name = g_strdup_printf("PCI Outbound Window %d", idx);
> +    size = ~(s->pom[idx].sa & 0xfffffffe) + 1;
> +    if (!size) {
> +        size = 0xffffffff;
> +    }
> +    memory_region_init_alias(mem, OBJECT(s), name, &s->busmem,
> +                             s->pom[idx].pcia, size);
> +    memory_region_add_subregion(address_space_mem, s->pom[idx].la, mem);
> +    g_free(name);
> +
> +    DPRINTF("%s: Added window %d of size=%#x from CPU=%#"PRIx64
> +            " to PCI=%#"PRIx64"\n", __func__, idx, size, s->pom[idx].la,
> +            s->pom[idx].pcia);
> +}
> +
> +static void ppc440_pcix_reg_write4(void *opaque, hwaddr addr,
> +                                   uint64_t val, unsigned size)
> +{
> +    struct PPC440PCIXState *s = opaque;
> +
> +    DPRINTF("%s: addr 0x%"PRIx64 " = %"PRIx64 "\n", __func__, addr, val);
> +    switch (addr) {
> +    case PCI_VENDOR_ID ... PCI_MAX_LAT:
> +        stl_le_p(s->dev->config + addr, val);
> +        break;
> +
> +    case PCIX0_POM0LAL:

Those lines ...

> +        s->pom[0].la &= 0xffffffff00000000ULL;
> +        s->pom[0].la |= val;

equivs to:

	   s->pom[0].la = deposit64(s->pom[0].la, 0, 32, val);

> +        ppc440_pcix_update_pom(s, 0);
> +        break;
> +    case PCIX0_POM0LAH:

Those

> +        s->pom[0].la &= 0xffffffffULL;
> +        s->pom[0].la |= val << 32;

to:

	   s->pom[0].la = deposit64(s->pom[0].la, 32, 32, val);

> +        ppc440_pcix_update_pom(s, 0);
> +        break;
> +    case PCIX0_POM0SA:
> +        s->pom[0].sa = val;
> +        ppc440_pcix_update_pom(s, 0);
> +        break;
> +    case PCIX0_POM0PCIAL:
> +        s->pom[0].pcia &= 0xffffffff00000000ULL;
> +        s->pom[0].pcia |= val;

and so on

> +        ppc440_pcix_update_pom(s, 0);
> +        break;
> +    case PCIX0_POM0PCIAH:
> +        s->pom[0].pcia &= 0xffffffffULL;
> +        s->pom[0].pcia |= val << 32;
> +        ppc440_pcix_update_pom(s, 0);
> +        break;
> +    case PCIX0_POM1LAL:
> +        s->pom[1].la &= 0xffffffff00000000ULL;
> +        s->pom[1].la |= val;
> +        ppc440_pcix_update_pom(s, 1);
> +        break;
> +    case PCIX0_POM1LAH:
> +        s->pom[1].la &= 0xffffffffULL;
> +        s->pom[1].la |= val << 32;
> +        ppc440_pcix_update_pom(s, 1);
> +        break;
> +    case PCIX0_POM1SA:
> +        s->pom[1].sa = val;
> +        ppc440_pcix_update_pom(s, 1);
> +        break;
> +    case PCIX0_POM1PCIAL:
> +        s->pom[1].pcia &= 0xffffffff00000000ULL;
> +        s->pom[1].pcia |= val;
> +        ppc440_pcix_update_pom(s, 1);
> +        break;
> +    case PCIX0_POM1PCIAH:
> +        s->pom[1].pcia &= 0xffffffffULL;
> +        s->pom[1].pcia |= val << 32;
> +        ppc440_pcix_update_pom(s, 1);
> +        break;
> +    case PCIX0_POM2SA:
> +        s->pom[2].sa = val;
> +        break;
> +
> +    case PCIX0_PIM0SAL:
> +        s->pim[0].sa &= 0xffffffff00000000ULL;
> +        s->pim[0].sa |= val;
> +        ppc440_pcix_update_pim(s, 0);
> +        break;
> +    case PCIX0_PIM0LAL:
> +        s->pim[0].la &= 0xffffffff00000000ULL;
> +        s->pim[0].la |= val;
> +        ppc440_pcix_update_pim(s, 0);
> +        break;
> +    case PCIX0_PIM0LAH:
> +        s->pim[0].la &= 0xffffffffULL;
> +        s->pim[0].la |= val << 32;
> +        ppc440_pcix_update_pim(s, 0);
> +        break;
> +    case PCIX0_PIM1SA:
> +        s->pim[1].sa = val;
> +        ppc440_pcix_update_pim(s, 1);
> +        break;
> +    case PCIX0_PIM1LAL:
> +        s->pim[1].la &= 0xffffffff00000000ULL;
> +        s->pim[1].la |= val;
> +        ppc440_pcix_update_pim(s, 1);
> +        break;
> +    case PCIX0_PIM1LAH:
> +        s->pim[1].la &= 0xffffffffULL;
> +        s->pim[1].la |= val << 32;
> +        ppc440_pcix_update_pim(s, 1);
> +        break;
> +    case PCIX0_PIM2SAL:
> +        s->pim[2].sa &= 0xffffffff00000000ULL;
> +        s->pim[2].sa = val;
> +        ppc440_pcix_update_pim(s, 2);
> +        break;
> +    case PCIX0_PIM2LAL:
> +        s->pim[2].la &= 0xffffffff00000000ULL;
> +        s->pim[2].la |= val;
> +        ppc440_pcix_update_pim(s, 2);
> +        break;
> +    case PCIX0_PIM2LAH:
> +        s->pim[2].la &= 0xffffffffULL;
> +        s->pim[2].la |= val << 32;
> +        ppc440_pcix_update_pim(s, 2);
> +        break;
> +
> +    case PCIX0_STS:
> +        s->sts = val;
> +        break;
> +
> +    case PCIX0_PIM0SAH:
> +        s->pim[0].sa &= 0xffffffffULL;
> +        s->pim[0].sa |= val << 32;
> +        ppc440_pcix_update_pim(s, 0);
> +        break;
> +    case PCIX0_PIM2SAH:
> +        s->pim[2].sa &= 0xffffffffULL;
> +        s->pim[2].sa |= val << 32;
> +        ppc440_pcix_update_pim(s, 2);
> +        break;
> +
> +    default:
> +        printf("%s: unhandled PCI internal register 0x%lx\n", __func__,
> +               (unsigned long)addr);
> +        break;
> +    }
> +}
> +
> +static uint64_t ppc440_pcix_reg_read4(void *opaque, hwaddr addr,
> +                                     unsigned size)
> +{
> +    struct PPC440PCIXState *s = opaque;
> +    uint32_t val;
> +
> +    switch (addr) {
> +    case PCI_VENDOR_ID ... PCI_MAX_LAT:
> +        val = ldl_le_p(s->dev->config + addr);
> +        break;
> +
> +    case PCIX0_POM0LAL:
> +        val = s->pom[0].la;

This should be

            val = s->pom[0].la & 0xffffffffULL;

or:

            val = extract64(s->pom[0].la, 0, 32);

> +        break;
> +    case PCIX0_POM0LAH:
> +        val = s->pom[0].la >> 32;

or to be consistent:

            val = extract64(s->pom[0].la, 32, 32);

> +        break;
> +    case PCIX0_POM0SA:
> +        val = s->pom[0].sa;
> +        break;
> +    case PCIX0_POM0PCIAL:
> +        val = s->pom[0].pcia;

also 32-bit masked

> +        break;
> +    case PCIX0_POM0PCIAH:
> +        val = s->pom[0].pcia >> 32;
> +        break;
> +    case PCIX0_POM1LAL:
> +        val = s->pom[1].la;

also 32-bit masked

> +        break;
> +    case PCIX0_POM1LAH:
> +        val = s->pom[1].la >> 32;
> +        break;
> +    case PCIX0_POM1SA:
> +        val = s->pom[1].sa;

also 32-bit masked, etc...

> +        break;
> +    case PCIX0_POM1PCIAL:
> +        val = s->pom[1].pcia;
> +        break;
> +    case PCIX0_POM1PCIAH:
> +        val = s->pom[1].pcia >> 32;
> +        break;
> +    case PCIX0_POM2SA:
> +        val = s->pom[2].sa;
> +        break;
> +
> +    case PCIX0_PIM0SAL:
> +        val = s->pim[0].sa;
> +        break;
> +    case PCIX0_PIM0LAL:
> +        val = s->pim[0].la;
> +        break;
> +    case PCIX0_PIM0LAH:
> +        val = s->pim[0].la >> 32;
> +        break;
> +    case PCIX0_PIM1SA:
> +        val = s->pim[1].sa;
> +        break;
> +    case PCIX0_PIM1LAL:
> +        val = s->pim[1].la;
> +        break;
> +    case PCIX0_PIM1LAH:
> +        val = s->pim[1].la >> 32;
> +        break;
> +    case PCIX0_PIM2SAL:
> +        val = s->pim[2].sa;
> +        break;
> +    case PCIX0_PIM2LAL:
> +        val = s->pim[2].la;
> +        break;
> +    case PCIX0_PIM2LAH:
> +        val = s->pim[2].la >> 32;
> +        break;
> +
> +    case PCIX0_STS:
> +        val = s->sts;
> +        break;
> +
> +    case PCIX0_PIM0SAH:
> +        val = s->pim[0].sa  >> 32;
> +        break;
> +    case PCIX0_PIM2SAH:
> +        val = s->pim[2].sa  >> 32;
> +        break;
> +
> +    default:
> +        printf("%s: invalid PCI internal register 0x%lx\n", __func__,
> +               (unsigned long)addr);
> +        val = 0;
> +    }
> +
> +    DPRINTF("%s: addr 0x%"PRIx64 " = %"PRIx32 "\n", __func__, addr, val);
> +    return val;
> +}
> +
> +static const MemoryRegionOps pci_reg_ops = {
> +    .read = ppc440_pcix_reg_read4,
> +    .write = ppc440_pcix_reg_write4,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +};
> +
> +static void ppc440_pcix_reset(DeviceState *dev)
> +{
> +    struct PPC440PCIXState *s = PPC440_PCIX_HOST_BRIDGE(dev);
> +    int i;
> +
> +    for (i = 0; i < PPC440_PCIX_NR_POMS; i++) {
> +        ppc440_pcix_clear_region(get_system_memory(), &s->pom[i].mr);
> +    }
> +    for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) {
> +        ppc440_pcix_clear_region(&s->bm, &s->pim[i].mr);
> +    }
> +    memset(s->pom, 0, sizeof(s->pom));
> +    memset(s->pim, 0, sizeof(s->pim));
> +    for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) {
> +        s->pim[i].sa = 0xffffffff00000000ULL;
> +    }
> +    s->sts = 0;
> +}
> +
> +/* All pins from each slot are tied to a single board IRQ.
> + * This may need further refactoring for other boards. */
> +static int ppc440_pcix_map_irq(PCIDevice *pci_dev, int irq_num)
> +{
> +    int slot = pci_dev->devfn >> 3;
> +
> +    DPRINTF("%s: devfn %x irq %d -> %d\n", __func__,
> +            pci_dev->devfn, irq_num, slot);
> +
> +    return slot - 1;
> +}
> +
> +static void ppc440_pcix_set_irq(void *opaque, int irq_num, int level)
> +{
> +    qemu_irq *pci_irqs = opaque;
> +
> +    DPRINTF("%s: PCI irq %d\n", __func__, irq_num);
> +    if (irq_num < 0) {
> +        error_report("%s: PCI irq %d", __func__, irq_num);
> +        return;
> +    }
> +    qemu_set_irq(pci_irqs[irq_num], level);
> +}
> +
> +static AddressSpace *ppc440_pcix_set_iommu(PCIBus *b, void *opaque, int devfn)
> +{
> +    PPC440PCIXState *s = opaque;
> +
> +    return &s->bm_as;
> +}
> +
> +static int ppc440_pcix_initfn(SysBusDevice *dev)
> +{
> +    PPC440PCIXState *s;
> +    PCIHostState *h;
> +    int i;
> +
> +    h = PCI_HOST_BRIDGE(dev);
> +    s = PPC440_PCIX_HOST_BRIDGE(dev);
> +
> +    for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
> +        sysbus_init_irq(dev, &s->irq[i]);
> +    }
> +
> +    memory_region_init(&s->busmem, OBJECT(dev), "pci bus memory", UINT64_MAX);
> +    h->bus = pci_register_bus(DEVICE(dev), NULL, ppc440_pcix_set_irq,
> +                         ppc440_pcix_map_irq, s->irq, &s->busmem,
> +                         get_system_io(), PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
> +
> +    s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0), "ppc4xx-host-bridge");
> +
> +    memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX);
> +    memory_region_add_subregion(&s->bm, 0x0, &s->busmem);
> +    address_space_init(&s->bm_as, &s->bm, "pci-bm");
> +    pci_setup_iommu(h->bus, ppc440_pcix_set_iommu, s);
> +
> +    memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE);
> +    memory_region_init_io(&h->conf_mem, OBJECT(s), &pci_host_conf_le_ops, h,
> +                          "pci-conf-idx", 4);
> +    memory_region_init_io(&h->data_mem, OBJECT(s), &pci_host_data_le_ops, h,
> +                          "pci-conf-data", 4);
> +    memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s,
> +                          "pci.reg", PPC440_REG_SIZE);
> +    memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem);
> +    memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem);
> +    memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->iomem);
> +    sysbus_init_mmio(dev, &s->container);
> +
> +    return 0;
> +}
> +
> +static void ppc440_pcix_class_init(ObjectClass *klass, void *data)
> +{
> +    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    k->init = ppc440_pcix_initfn;
> +    dc->reset = ppc440_pcix_reset;
> +}
> +
> +static const TypeInfo ppc440_pcix_info = {
> +    .name          = TYPE_PPC440_PCIX_HOST_BRIDGE,
> +    .parent        = TYPE_PCI_HOST_BRIDGE,
> +    .instance_size = sizeof(PPC440PCIXState),
> +    .class_init    = ppc440_pcix_class_init,
> +};
> +
> +static void ppc440_pcix_register_types(void)
> +{
> +    type_register_static(&ppc440_pcix_info);
> +}
> +
> +type_init(ppc440_pcix_register_types)
> 

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 03/15] ohci: Allow sysbus version to be used as a companion
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 03/15] ohci: Allow sysbus version to be used as a companion BALATON Zoltan
@ 2017-08-21  4:10   ` David Gibson
  2017-08-23 13:58     ` Gerd Hoffmann
  0 siblings, 1 reply; 66+ messages in thread
From: David Gibson @ 2017-08-21  4:10 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol, Gerd Hoffmann

[-- Attachment #1: Type: text/plain, Size: 2332 bytes --]

On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
1;4803;0c> Some PPC SoCs have an EHCI with OHCI companion USB controller. To
> emulate this allow the sysbus version of OHCI to be used as a companion.
> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

Gerd,  if you're happy with this, I can queue it for 2.11.  Let me
know what you'd prefer.

> ---
>  hw/usb/hcd-ohci.c | 15 ++++++++++++---
>  1 file changed, 12 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
> index 267982e..17beedd 100644
> --- a/hw/usb/hcd-ohci.c
> +++ b/hw/usb/hcd-ohci.c
> @@ -1999,7 +1999,9 @@ typedef struct {
>      /*< public >*/
>  
>      OHCIState ohci;
> +    char *masterbus;
>      uint32_t num_ports;
> +    uint32_t firstport;
>      dma_addr_t dma_offset;
>  } OHCISysBusState;
>  
> @@ -2007,10 +2009,15 @@ static void ohci_realize_pxa(DeviceState *dev, Error **errp)
>  {
>      OHCISysBusState *s = SYSBUS_OHCI(dev);
>      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> +    Error *err = NULL;
>  
> -    /* Cannot fail as we pass NULL for masterbus */
> -    usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset, NULL, 0,
> -                  &address_space_memory, &error_abort);
> +    usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset,
> +                  s->masterbus, s->firstport,
> +                  &address_space_memory, &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
>      sysbus_init_irq(sbd, &s->ohci.irq);
>      sysbus_init_mmio(sbd, &s->ohci.mem);
>  }
> @@ -2142,7 +2149,9 @@ static const TypeInfo ohci_pci_info = {
>  };
>  
>  static Property ohci_sysbus_properties[] = {
> +    DEFINE_PROP_STRING("masterbus", OHCISysBusState, masterbus),
>      DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
> +    DEFINE_PROP_UINT32("firstport", OHCISysBusState, firstport, 0),
>      DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 0),
>      DEFINE_PROP_END_OF_LIST(),
>  };

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 04/15] ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 04/15] ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs BALATON Zoltan
@ 2017-08-21  4:18   ` David Gibson
  2017-08-23 13:57     ` Gerd Hoffmann
  0 siblings, 1 reply; 66+ messages in thread
From: David Gibson @ 2017-08-21  4:18 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol, Gerd Hoffmann

[-- Attachment #1: Type: text/plain, Size: 2620 bytes --]

On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
> Some PPC SoCs have an EHCI with OHCI companion USB controller. Add a
> new type for this similar to types used for other embedded SoCs.
> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

Gerd, again, if it's convenient to you, I can queue this for 2.11.

> ---
>  hw/usb/hcd-ehci-sysbus.c | 25 +++++++++++++++++++++++++
>  hw/usb/hcd-ehci.h        |  1 +
>  2 files changed, 26 insertions(+)
> 
> diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
> index 6c20604..3b83beb 100644
> --- a/hw/usb/hcd-ehci-sysbus.c
> +++ b/hw/usb/hcd-ehci-sysbus.c
> @@ -142,6 +142,30 @@ static const TypeInfo ehci_tegra2_type_info = {
>      .class_init    = ehci_tegra2_class_init,
>  };
>  
> +static void ehci_ppc4xx_init(Object *o)
> +{
> +    EHCISysBusState *s = SYS_BUS_EHCI(o);
> +
> +    s->ehci.companion_enable = true;
> +}
> +
> +static void ehci_ppc4xx_class_init(ObjectClass *oc, void *data)
> +{
> +    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
> +    DeviceClass *dc = DEVICE_CLASS(oc);
> +
> +    sec->capsbase = 0x0;
> +    sec->opregbase = 0x10;
> +    set_bit(DEVICE_CATEGORY_USB, dc->categories);
> +}
> +
> +static const TypeInfo ehci_ppc4xx_type_info = {
> +    .name          = TYPE_PPC4xx_EHCI,
> +    .parent        = TYPE_SYS_BUS_EHCI,
> +    .class_init    = ehci_ppc4xx_class_init,
> +    .instance_init = ehci_ppc4xx_init,
> +};
> +
>  /*
>   * Faraday FUSBH200 USB 2.0 EHCI
>   */
> @@ -224,6 +248,7 @@ static void ehci_sysbus_register_types(void)
>      type_register_static(&ehci_xlnx_type_info);
>      type_register_static(&ehci_exynos4210_type_info);
>      type_register_static(&ehci_tegra2_type_info);
> +    type_register_static(&ehci_ppc4xx_type_info);
>      type_register_static(&ehci_fusbh200_type_info);
>  }
>  
> diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
> index 821f1de..0bc364b 100644
> --- a/hw/usb/hcd-ehci.h
> +++ b/hw/usb/hcd-ehci.h
> @@ -344,6 +344,7 @@ typedef struct EHCIPCIState {
>  #define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb"
>  #define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb"
>  #define TYPE_TEGRA2_EHCI "tegra2-ehci-usb"
> +#define TYPE_PPC4xx_EHCI "ppc4xx-ehci-usb"
>  #define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb"
>  
>  #define SYS_BUS_EHCI(obj) \

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 02/15] ppc4xx: Make MAL emulation more generic
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 02/15] ppc4xx: Make MAL emulation more generic BALATON Zoltan
@ 2017-08-21 10:40   ` David Gibson
  0 siblings, 0 replies; 66+ messages in thread
From: David Gibson @ 2017-08-21 10:40 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 9814 bytes --]

On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
> Allow MAL with more RX and TX channels as found in newer versions.
> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

I've applied patches 1 & 2 to my ppc-for-2.11 tree.

> ---
>  hw/ppc/ppc405_uc.c      |   2 +-
>  hw/ppc/ppc4xx_devs.c    | 171 +++++++++++++++++++-----------------------------
>  include/hw/ppc/ppc4xx.h |   3 +-
>  3 files changed, 70 insertions(+), 106 deletions(-)
> 
> diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
> index 3c74402..03856d5 100644
> --- a/hw/ppc/ppc405_uc.c
> +++ b/hw/ppc/ppc405_uc.c
> @@ -2281,7 +2281,7 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
>      mal_irqs[1] = pic[12];
>      mal_irqs[2] = pic[13];
>      mal_irqs[3] = pic[14];
> -    ppc405_mal_init(env, mal_irqs);
> +    ppc4xx_mal_init(env, 4, 2, mal_irqs);
>      /* Ethernet */
>      /* Uses pic[9], pic[15], pic[17] */
>      /* CPU control */
> diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
> index 8e4f78e..6e1cc09 100644
> --- a/hw/ppc/ppc4xx_devs.c
> +++ b/hw/ppc/ppc4xx_devs.c
> @@ -737,6 +737,7 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
>  
>  /*****************************************************************************/
>  /* MAL */
> +
>  enum {
>      MAL0_CFG      = 0x180,
>      MAL0_ESR      = 0x181,
> @@ -750,17 +751,13 @@ enum {
>      MAL0_RXEOBISR = 0x192,
>      MAL0_RXDEIR   = 0x193,
>      MAL0_TXCTP0R  = 0x1A0,
> -    MAL0_TXCTP1R  = 0x1A1,
> -    MAL0_TXCTP2R  = 0x1A2,
> -    MAL0_TXCTP3R  = 0x1A3,
>      MAL0_RXCTP0R  = 0x1C0,
> -    MAL0_RXCTP1R  = 0x1C1,
>      MAL0_RCBS0    = 0x1E0,
>      MAL0_RCBS1    = 0x1E1,
>  };
>  
> -typedef struct ppc40x_mal_t ppc40x_mal_t;
> -struct ppc40x_mal_t {
> +typedef struct ppc4xx_mal_t ppc4xx_mal_t;
> +struct ppc4xx_mal_t {
>      qemu_irq irqs[4];
>      uint32_t cfg;
>      uint32_t esr;
> @@ -773,16 +770,32 @@ struct ppc40x_mal_t {
>      uint32_t rxcarr;
>      uint32_t rxeobisr;
>      uint32_t rxdeir;
> -    uint32_t txctpr[4];
> -    uint32_t rxctpr[2];
> -    uint32_t rcbs[2];
> +    uint32_t *txctpr;
> +    uint32_t *rxctpr;
> +    uint32_t *rcbs;
> +    uint8_t  txcnum;
> +    uint8_t  rxcnum;
>  };
>  
> -static void ppc40x_mal_reset(void *opaque);
> +static void ppc4xx_mal_reset(void *opaque)
> +{
> +    ppc4xx_mal_t *mal;
> +
> +    mal = opaque;
> +    mal->cfg = 0x0007C000;
> +    mal->esr = 0x00000000;
> +    mal->ier = 0x00000000;
> +    mal->rxcasr = 0x00000000;
> +    mal->rxdeir = 0x00000000;
> +    mal->rxeobisr = 0x00000000;
> +    mal->txcasr = 0x00000000;
> +    mal->txdeir = 0x00000000;
> +    mal->txeobisr = 0x00000000;
> +}
>  
>  static uint32_t dcr_read_mal(void *opaque, int dcrn)
>  {
> -    ppc40x_mal_t *mal;
> +    ppc4xx_mal_t *mal;
>      uint32_t ret;
>  
>      mal = opaque;
> @@ -820,48 +833,32 @@ static uint32_t dcr_read_mal(void *opaque, int dcrn)
>      case MAL0_RXDEIR:
>          ret = mal->rxdeir;
>          break;
> -    case MAL0_TXCTP0R:
> -        ret = mal->txctpr[0];
> -        break;
> -    case MAL0_TXCTP1R:
> -        ret = mal->txctpr[1];
> -        break;
> -    case MAL0_TXCTP2R:
> -        ret = mal->txctpr[2];
> -        break;
> -    case MAL0_TXCTP3R:
> -        ret = mal->txctpr[3];
> -        break;
> -    case MAL0_RXCTP0R:
> -        ret = mal->rxctpr[0];
> -        break;
> -    case MAL0_RXCTP1R:
> -        ret = mal->rxctpr[1];
> -        break;
> -    case MAL0_RCBS0:
> -        ret = mal->rcbs[0];
> -        break;
> -    case MAL0_RCBS1:
> -        ret = mal->rcbs[1];
> -        break;
>      default:
>          ret = 0;
>          break;
>      }
> +    if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
> +        ret = mal->txctpr[dcrn - MAL0_TXCTP0R];
> +    }
> +    if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
> +        ret = mal->rxctpr[dcrn - MAL0_RXCTP0R];
> +    }
> +    if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
> +        ret = mal->rcbs[dcrn - MAL0_RCBS0];
> +    }
>  
>      return ret;
>  }
>  
>  static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
>  {
> -    ppc40x_mal_t *mal;
> -    int idx;
> +    ppc4xx_mal_t *mal;
>  
>      mal = opaque;
>      switch (dcrn) {
>      case MAL0_CFG:
>          if (val & 0x80000000) {
> -            ppc40x_mal_reset(mal);
> +            ppc4xx_mal_reset(mal);
>          }
>          mal->cfg = val & 0x00FFC087;
>          break;
> @@ -900,65 +897,35 @@ static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
>          /* Read/clear */
>          mal->rxdeir &= ~val;
>          break;
> -    case MAL0_TXCTP0R:
> -        idx = 0;
> -        goto update_tx_ptr;
> -    case MAL0_TXCTP1R:
> -        idx = 1;
> -        goto update_tx_ptr;
> -    case MAL0_TXCTP2R:
> -        idx = 2;
> -        goto update_tx_ptr;
> -    case MAL0_TXCTP3R:
> -        idx = 3;
> -    update_tx_ptr:
> -        mal->txctpr[idx] = val;
> -        break;
> -    case MAL0_RXCTP0R:
> -        idx = 0;
> -        goto update_rx_ptr;
> -    case MAL0_RXCTP1R:
> -        idx = 1;
> -    update_rx_ptr:
> -        mal->rxctpr[idx] = val;
> -        break;
> -    case MAL0_RCBS0:
> -        idx = 0;
> -        goto update_rx_size;
> -    case MAL0_RCBS1:
> -        idx = 1;
> -    update_rx_size:
> -        mal->rcbs[idx] = val & 0x000000FF;
> -        break;
> +    }
> +    if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
> +        mal->txctpr[dcrn - MAL0_TXCTP0R] = val;
> +    }
> +    if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
> +        mal->rxctpr[dcrn - MAL0_RXCTP0R] = val;
> +    }
> +    if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
> +        mal->rcbs[dcrn - MAL0_RCBS0] = val & 0x000000FF;
>      }
>  }
>  
> -static void ppc40x_mal_reset(void *opaque)
> -{
> -    ppc40x_mal_t *mal;
> -
> -    mal = opaque;
> -    mal->cfg = 0x0007C000;
> -    mal->esr = 0x00000000;
> -    mal->ier = 0x00000000;
> -    mal->rxcasr = 0x00000000;
> -    mal->rxdeir = 0x00000000;
> -    mal->rxeobisr = 0x00000000;
> -    mal->txcasr = 0x00000000;
> -    mal->txdeir = 0x00000000;
> -    mal->txeobisr = 0x00000000;
> -}
> -
> -void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
> +void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
> +                     qemu_irq irqs[4])
>  {
> -    ppc40x_mal_t *mal;
> +    ppc4xx_mal_t *mal;
>      int i;
>  
> -    mal = g_malloc0(sizeof(ppc40x_mal_t));
> +    assert(txcnum <= 32 && rxcnum <= 32);
> +    mal = g_malloc0(sizeof(*mal));
> +    mal->txcnum = txcnum;
> +    mal->rxcnum = rxcnum;
> +    mal->txctpr = g_new0(uint32_t, txcnum);
> +    mal->rxctpr = g_new0(uint32_t, rxcnum);
> +    mal->rcbs = g_new0(uint32_t, rxcnum);
>      for (i = 0; i < 4; i++) {
>          mal->irqs[i] = irqs[i];
>      }
> -    qemu_register_reset(&ppc40x_mal_reset, mal);
> +    qemu_register_reset(&ppc4xx_mal_reset, mal);
>      ppc_dcr_register(env, MAL0_CFG,
>                       mal, &dcr_read_mal, &dcr_write_mal);
>      ppc_dcr_register(env, MAL0_ESR,
> @@ -981,20 +948,16 @@ void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
>                       mal, &dcr_read_mal, &dcr_write_mal);
>      ppc_dcr_register(env, MAL0_RXDEIR,
>                       mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_TXCTP0R,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_TXCTP1R,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_TXCTP2R,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_TXCTP3R,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_RXCTP0R,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_RXCTP1R,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_RCBS0,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> -    ppc_dcr_register(env, MAL0_RCBS1,
> -                     mal, &dcr_read_mal, &dcr_write_mal);
> +    for (i = 0; i < txcnum; i++) {
> +        ppc_dcr_register(env, MAL0_TXCTP0R + i,
> +                         mal, &dcr_read_mal, &dcr_write_mal);
> +    }
> +    for (i = 0; i < rxcnum; i++) {
> +        ppc_dcr_register(env, MAL0_RXCTP0R + i,
> +                         mal, &dcr_read_mal, &dcr_write_mal);
> +    }
> +    for (i = 0; i < rxcnum; i++) {
> +        ppc_dcr_register(env, MAL0_RCBS0 + i,
> +                         mal, &dcr_read_mal, &dcr_write_mal);
> +    }
>  }
> diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
> index db50cfa..cb0bb55 100644
> --- a/include/hw/ppc/ppc4xx.h
> +++ b/include/hw/ppc/ppc4xx.h
> @@ -53,7 +53,8 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
>                          hwaddr *ram_sizes,
>                          int do_init);
>  
> -void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4]);
> +void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
> +                     qemu_irq irqs[4]);
>  
>  #define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost"
>  

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 06/15] ppc4xx_i2c: QOMify
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 06/15] ppc4xx_i2c: QOMify BALATON Zoltan
@ 2017-08-21 10:50   ` David Gibson
  0 siblings, 0 replies; 66+ messages in thread
From: David Gibson @ 2017-08-21 10:50 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 11274 bytes --]

On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>

Applied patches 5 & 6 to ppc-for-2.11.

> ---
>  hw/ppc/ppc405.h             |   2 -
>  hw/ppc/ppc405_uc.c          |   5 +-
>  hw/ppc/ppc4xx_i2c.c         | 154 ++++++++++++++------------------------------
>  include/hw/i2c/ppc4xx_i2c.h |  61 ++++++++++++++++++
>  4 files changed, 113 insertions(+), 109 deletions(-)
>  create mode 100644 include/hw/i2c/ppc4xx_i2c.h
> 
> diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
> index 61ec739..a9ffc87 100644
> --- a/hw/ppc/ppc405.h
> +++ b/hw/ppc/ppc405.h
> @@ -59,8 +59,6 @@ struct ppc4xx_bd_info_t {
>  ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
>                                  uint32_t flags);
>  
> -void ppc405_i2c_init(hwaddr base, qemu_irq irq);
> -
>  CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
>                          MemoryRegion ram_memories[4],
>                          hwaddr ram_bases[4],
> diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
> index 3925e4c..8f44cb4 100644
> --- a/hw/ppc/ppc405_uc.c
> +++ b/hw/ppc/ppc405_uc.c
> @@ -28,6 +28,7 @@
>  #include "hw/hw.h"
>  #include "hw/ppc/ppc.h"
>  #include "hw/boards.h"
> +#include "hw/i2c/ppc4xx_i2c.h"
>  #include "ppc405.h"
>  #include "hw/char/serial.h"
>  #include "qemu/timer.h"
> @@ -1663,7 +1664,7 @@ CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
>                         DEVICE_BIG_ENDIAN);
>      }
>      /* IIC controller */
> -    ppc405_i2c_init(0xef600500, pic[2]);
> +    sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500, pic[2]);
>      /* GPIO */
>      ppc405_gpio_init(0xef600700);
>      /* CPU control */
> @@ -2010,7 +2011,7 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
>      dma_irqs[3] = pic[8];
>      ppc405_dma_init(env, dma_irqs);
>      /* IIC controller */
> -    ppc405_i2c_init(0xef600500, pic[2]);
> +    sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500, pic[2]);
>      /* GPIO */
>      ppc405_gpio_init(0xef600700);
>      /* Serial ports */
> diff --git a/hw/ppc/ppc4xx_i2c.c b/hw/ppc/ppc4xx_i2c.c
> index 15f2dea..5a6bde9 100644
> --- a/hw/ppc/ppc4xx_i2c.c
> +++ b/hw/ppc/ppc4xx_i2c.c
> @@ -27,42 +27,20 @@
>  #include "qemu-common.h"
>  #include "cpu.h"
>  #include "hw/hw.h"
> -#include "exec/address-spaces.h"
> -#include "hw/ppc/ppc.h"
> -#include "ppc405.h"
> +#include "hw/i2c/ppc4xx_i2c.h"
>  
>  /*#define DEBUG_I2C*/
>  
> -typedef struct ppc4xx_i2c_t ppc4xx_i2c_t;
> -struct ppc4xx_i2c_t {
> -    qemu_irq irq;
> -    MemoryRegion iomem;
> -    uint8_t mdata;
> -    uint8_t lmadr;
> -    uint8_t hmadr;
> -    uint8_t cntl;
> -    uint8_t mdcntl;
> -    uint8_t sts;
> -    uint8_t extsts;
> -    uint8_t sdata;
> -    uint8_t lsadr;
> -    uint8_t hsadr;
> -    uint8_t clkdiv;
> -    uint8_t intrmsk;
> -    uint8_t xfrcnt;
> -    uint8_t xtcntlss;
> -    uint8_t directcntl;
> -};
> +#define PPC4xx_I2C_MEM_SIZE 0x11
>  
> -static uint32_t ppc4xx_i2c_readb(void *opaque, hwaddr addr)
> +static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size)
>  {
> -    ppc4xx_i2c_t *i2c;
> -    uint32_t ret;
> +    PPC4xxI2CState *i2c = PPC4xx_I2C(opaque);
> +    uint64_t ret;
>  
>  #ifdef DEBUG_I2C
>      printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
>  #endif
> -    i2c = opaque;
>      switch (addr) {
>      case 0x00:
>          /*i2c_readbyte(&i2c->mdata);*/
> @@ -115,22 +93,20 @@ static uint32_t ppc4xx_i2c_readb(void *opaque, hwaddr addr)
>          break;
>      }
>  #ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__, addr, ret);
> +    printf("%s: addr " TARGET_FMT_plx " %02" PRIx64 "\n", __func__, addr, ret);
>  #endif
>  
>      return ret;
>  }
>  
> -static void ppc4xx_i2c_writeb(void *opaque,
> -                              hwaddr addr, uint32_t value)
> +static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
> +                              unsigned int size)
>  {
> -    ppc4xx_i2c_t *i2c;
> -
> +    PPC4xxI2CState *i2c = opaque;
>  #ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
> -           value);
> +    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx64 "\n",
> +           __func__, addr, value);
>  #endif
> -    i2c = opaque;
>      switch (addr) {
>      case 0x00:
>          i2c->mdata = value;
> @@ -181,71 +157,20 @@ static void ppc4xx_i2c_writeb(void *opaque,
>      }
>  }
>  
> -static uint32_t ppc4xx_i2c_readw(void *opaque, hwaddr addr)
> -{
> -    uint32_t ret;
> -
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
> -#endif
> -    ret = ppc4xx_i2c_readb(opaque, addr) << 8;
> -    ret |= ppc4xx_i2c_readb(opaque, addr + 1);
> -
> -    return ret;
> -}
> -
> -static void ppc4xx_i2c_writew(void *opaque,
> -                              hwaddr addr, uint32_t value)
> -{
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
> -           value);
> -#endif
> -    ppc4xx_i2c_writeb(opaque, addr, value >> 8);
> -    ppc4xx_i2c_writeb(opaque, addr + 1, value);
> -}
> -
> -static uint32_t ppc4xx_i2c_readl(void *opaque, hwaddr addr)
> -{
> -    uint32_t ret;
> -
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
> -#endif
> -    ret = ppc4xx_i2c_readb(opaque, addr) << 24;
> -    ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16;
> -    ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8;
> -    ret |= ppc4xx_i2c_readb(opaque, addr + 3);
> -
> -    return ret;
> -}
> -
> -static void ppc4xx_i2c_writel(void *opaque,
> -                              hwaddr addr, uint32_t value)
> -{
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
> -           value);
> -#endif
> -    ppc4xx_i2c_writeb(opaque, addr, value >> 24);
> -    ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16);
> -    ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8);
> -    ppc4xx_i2c_writeb(opaque, addr + 3, value);
> -}
> -
> -static const MemoryRegionOps i2c_ops = {
> -    .old_mmio = {
> -        .read = { ppc4xx_i2c_readb, ppc4xx_i2c_readw, ppc4xx_i2c_readl, },
> -        .write = { ppc4xx_i2c_writeb, ppc4xx_i2c_writew, ppc4xx_i2c_writel, },
> -    },
> +static const MemoryRegionOps ppc4xx_i2c_ops = {
> +    .read = ppc4xx_i2c_readb,
> +    .write = ppc4xx_i2c_writeb,
> +    .valid.min_access_size = 1,
> +    .valid.max_access_size = 4,
> +    .impl.min_access_size = 1,
> +    .impl.max_access_size = 1,
>      .endianness = DEVICE_NATIVE_ENDIAN,
>  };
>  
> -static void ppc4xx_i2c_reset(void *opaque)
> +static void ppc4xx_i2c_reset(DeviceState *s)
>  {
> -    ppc4xx_i2c_t *i2c;
> +    PPC4xxI2CState *i2c = PPC4xx_I2C(s);
>  
> -    i2c = opaque;
>      i2c->mdata = 0x00;
>      i2c->sdata = 0x00;
>      i2c->cntl = 0x00;
> @@ -257,16 +182,35 @@ static void ppc4xx_i2c_reset(void *opaque)
>      i2c->directcntl = 0x0F;
>  }
>  
> -void ppc405_i2c_init(hwaddr base, qemu_irq irq)
> +static void ppc4xx_i2c_init(Object *o)
>  {
> -    ppc4xx_i2c_t *i2c;
> +    PPC4xxI2CState *s = PPC4xx_I2C(o);
>  
> -    i2c = g_malloc0(sizeof(ppc4xx_i2c_t));
> -    i2c->irq = irq;
> -#ifdef DEBUG_I2C
> -    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
> -#endif
> -    memory_region_init_io(&i2c->iomem, NULL, &i2c_ops, i2c, "i2c", 0x011);
> -    memory_region_add_subregion(get_system_memory(), base, &i2c->iomem);
> -    qemu_register_reset(ppc4xx_i2c_reset, i2c);
> +    memory_region_init_io(&s->iomem, OBJECT(s), &ppc4xx_i2c_ops, s,
> +                          TYPE_PPC4xx_I2C, PPC4xx_I2C_MEM_SIZE);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
> +    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
> +    s->bus = i2c_init_bus(DEVICE(s), "i2c");
>  }
> +
> +static void ppc4xx_i2c_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->reset = ppc4xx_i2c_reset;
> +}
> +
> +static const TypeInfo ppc4xx_i2c_type_info = {
> +    .name = TYPE_PPC4xx_I2C,
> +    .parent = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(PPC4xxI2CState),
> +    .instance_init = ppc4xx_i2c_init,
> +    .class_init = ppc4xx_i2c_class_init,
> +};
> +
> +static void ppc4xx_i2c_register_types(void)
> +{
> +    type_register_static(&ppc4xx_i2c_type_info);
> +}
> +
> +type_init(ppc4xx_i2c_register_types)
> diff --git a/include/hw/i2c/ppc4xx_i2c.h b/include/hw/i2c/ppc4xx_i2c.h
> new file mode 100644
> index 0000000..e53042f
> --- /dev/null
> +++ b/include/hw/i2c/ppc4xx_i2c.h
> @@ -0,0 +1,61 @@
> +/*
> + * PPC4xx I2C controller emulation
> + *
> + * Copyright (c) 2007 Jocelyn Mayer
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#ifndef PPC4XX_I2C_H
> +#define PPC4XX_I2C_H
> +
> +#include "qemu/osdep.h"
> +#include "qemu-common.h"
> +#include "hw/sysbus.h"
> +#include "hw/i2c/i2c.h"
> +
> +#define TYPE_PPC4xx_I2C "ppc4xx-i2c"
> +#define PPC4xx_I2C(obj) OBJECT_CHECK(PPC4xxI2CState, (obj), TYPE_PPC4xx_I2C)
> +
> +typedef struct PPC4xxI2CState {
> +    /*< private >*/
> +    SysBusDevice parent_obj;
> +
> +    /*< public >*/
> +    I2CBus *bus;
> +    qemu_irq irq;
> +    MemoryRegion iomem;
> +    uint8_t mdata;
> +    uint8_t lmadr;
> +    uint8_t hmadr;
> +    uint8_t cntl;
> +    uint8_t mdcntl;
> +    uint8_t sts;
> +    uint8_t extsts;
> +    uint8_t sdata;
> +    uint8_t lsadr;
> +    uint8_t hsadr;
> +    uint8_t clkdiv;
> +    uint8_t intrmsk;
> +    uint8_t xfrcnt;
> +    uint8_t xtcntlss;
> +    uint8_t directcntl;
> +} PPC4xxI2CState;
> +
> +#endif /* PPC4XX_I2C_H */

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 07/15] ppc4xx_i2c: Move to hw/i2c
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 07/15] ppc4xx_i2c: Move to hw/i2c BALATON Zoltan
@ 2017-08-21 10:54   ` David Gibson
  0 siblings, 0 replies; 66+ messages in thread
From: David Gibson @ 2017-08-21 10:54 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 15781 bytes --]

On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>

Applied to ppc-for-2.11.

> ---
>  default-configs/ppc-softmmu.mak    |   1 +
>  default-configs/ppc64-softmmu.mak  |   1 +
>  default-configs/ppcemb-softmmu.mak |   1 +
>  hw/i2c/Makefile.objs               |   1 +
>  hw/i2c/ppc4xx_i2c.c                | 216 +++++++++++++++++++++++++++++++++++++
>  hw/ppc/Makefile.objs               |   2 +-
>  hw/ppc/ppc4xx_i2c.c                | 216 -------------------------------------
>  7 files changed, 221 insertions(+), 217 deletions(-)
>  create mode 100644 hw/i2c/ppc4xx_i2c.c
>  delete mode 100644 hw/ppc/ppc4xx_i2c.c
> 
> diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
> index 1f1cd85..d4d44eb 100644
> --- a/default-configs/ppc-softmmu.mak
> +++ b/default-configs/ppc-softmmu.mak
> @@ -3,6 +3,7 @@
>  include pci.mak
>  include sound.mak
>  include usb.mak
> +CONFIG_PPC4XX=y
>  CONFIG_ESCC=y
>  CONFIG_M48T59=y
>  CONFIG_SERIAL=y
> diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
> index 46c9599..af32589 100644
> --- a/default-configs/ppc64-softmmu.mak
> +++ b/default-configs/ppc64-softmmu.mak
> @@ -3,6 +3,7 @@
>  include pci.mak
>  include sound.mak
>  include usb.mak
> +CONFIG_PPC4XX=y
>  CONFIG_VIRTIO_VGA=y
>  CONFIG_ESCC=y
>  CONFIG_M48T59=y
> diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
> index 94340de..635923a 100644
> --- a/default-configs/ppcemb-softmmu.mak
> +++ b/default-configs/ppcemb-softmmu.mak
> @@ -3,6 +3,7 @@
>  include pci.mak
>  include sound.mak
>  include usb.mak
> +CONFIG_PPC4XX=y
>  CONFIG_M48T59=y
>  CONFIG_SERIAL=y
>  CONFIG_SERIAL_ISA=y
> diff --git a/hw/i2c/Makefile.objs b/hw/i2c/Makefile.objs
> index a081b8e..0594dea 100644
> --- a/hw/i2c/Makefile.objs
> +++ b/hw/i2c/Makefile.objs
> @@ -8,3 +8,4 @@ common-obj-$(CONFIG_EXYNOS4) += exynos4210_i2c.o
>  common-obj-$(CONFIG_IMX_I2C) += imx_i2c.o
>  common-obj-$(CONFIG_ASPEED_SOC) += aspeed_i2c.o
>  obj-$(CONFIG_OMAP) += omap_i2c.o
> +obj-$(CONFIG_PPC4XX) += ppc4xx_i2c.o
> diff --git a/hw/i2c/ppc4xx_i2c.c b/hw/i2c/ppc4xx_i2c.c
> new file mode 100644
> index 0000000..5a6bde9
> --- /dev/null
> +++ b/hw/i2c/ppc4xx_i2c.c
> @@ -0,0 +1,216 @@
> +/*
> + * PPC4xx I2C controller emulation
> + *
> + * Copyright (c) 2007 Jocelyn Mayer
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qemu-common.h"
> +#include "cpu.h"
> +#include "hw/hw.h"
> +#include "hw/i2c/ppc4xx_i2c.h"
> +
> +/*#define DEBUG_I2C*/
> +
> +#define PPC4xx_I2C_MEM_SIZE 0x11
> +
> +static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size)
> +{
> +    PPC4xxI2CState *i2c = PPC4xx_I2C(opaque);
> +    uint64_t ret;
> +
> +#ifdef DEBUG_I2C
> +    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
> +#endif
> +    switch (addr) {
> +    case 0x00:
> +        /*i2c_readbyte(&i2c->mdata);*/
> +        ret = i2c->mdata;
> +        break;
> +    case 0x02:
> +        ret = i2c->sdata;
> +        break;
> +    case 0x04:
> +        ret = i2c->lmadr;
> +        break;
> +    case 0x05:
> +        ret = i2c->hmadr;
> +        break;
> +    case 0x06:
> +        ret = i2c->cntl;
> +        break;
> +    case 0x07:
> +        ret = i2c->mdcntl;
> +        break;
> +    case 0x08:
> +        ret = i2c->sts;
> +        break;
> +    case 0x09:
> +        ret = i2c->extsts;
> +        break;
> +    case 0x0A:
> +        ret = i2c->lsadr;
> +        break;
> +    case 0x0B:
> +        ret = i2c->hsadr;
> +        break;
> +    case 0x0C:
> +        ret = i2c->clkdiv;
> +        break;
> +    case 0x0D:
> +        ret = i2c->intrmsk;
> +        break;
> +    case 0x0E:
> +        ret = i2c->xfrcnt;
> +        break;
> +    case 0x0F:
> +        ret = i2c->xtcntlss;
> +        break;
> +    case 0x10:
> +        ret = i2c->directcntl;
> +        break;
> +    default:
> +        ret = 0x00;
> +        break;
> +    }
> +#ifdef DEBUG_I2C
> +    printf("%s: addr " TARGET_FMT_plx " %02" PRIx64 "\n", __func__, addr, ret);
> +#endif
> +
> +    return ret;
> +}
> +
> +static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
> +                              unsigned int size)
> +{
> +    PPC4xxI2CState *i2c = opaque;
> +#ifdef DEBUG_I2C
> +    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx64 "\n",
> +           __func__, addr, value);
> +#endif
> +    switch (addr) {
> +    case 0x00:
> +        i2c->mdata = value;
> +        /*i2c_sendbyte(&i2c->mdata);*/
> +        break;
> +    case 0x02:
> +        i2c->sdata = value;
> +        break;
> +    case 0x04:
> +        i2c->lmadr = value;
> +        break;
> +    case 0x05:
> +        i2c->hmadr = value;
> +        break;
> +    case 0x06:
> +        i2c->cntl = value;
> +        break;
> +    case 0x07:
> +        i2c->mdcntl = value & 0xDF;
> +        break;
> +    case 0x08:
> +        i2c->sts &= ~(value & 0x0A);
> +        break;
> +    case 0x09:
> +        i2c->extsts &= ~(value & 0x8F);
> +        break;
> +    case 0x0A:
> +        i2c->lsadr = value;
> +        break;
> +    case 0x0B:
> +        i2c->hsadr = value;
> +        break;
> +    case 0x0C:
> +        i2c->clkdiv = value;
> +        break;
> +    case 0x0D:
> +        i2c->intrmsk = value;
> +        break;
> +    case 0x0E:
> +        i2c->xfrcnt = value & 0x77;
> +        break;
> +    case 0x0F:
> +        i2c->xtcntlss = value;
> +        break;
> +    case 0x10:
> +        i2c->directcntl = value & 0x7;
> +        break;
> +    }
> +}
> +
> +static const MemoryRegionOps ppc4xx_i2c_ops = {
> +    .read = ppc4xx_i2c_readb,
> +    .write = ppc4xx_i2c_writeb,
> +    .valid.min_access_size = 1,
> +    .valid.max_access_size = 4,
> +    .impl.min_access_size = 1,
> +    .impl.max_access_size = 1,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +};
> +
> +static void ppc4xx_i2c_reset(DeviceState *s)
> +{
> +    PPC4xxI2CState *i2c = PPC4xx_I2C(s);
> +
> +    i2c->mdata = 0x00;
> +    i2c->sdata = 0x00;
> +    i2c->cntl = 0x00;
> +    i2c->mdcntl = 0x00;
> +    i2c->sts = 0x00;
> +    i2c->extsts = 0x00;
> +    i2c->clkdiv = 0x00;
> +    i2c->xfrcnt = 0x00;
> +    i2c->directcntl = 0x0F;
> +}
> +
> +static void ppc4xx_i2c_init(Object *o)
> +{
> +    PPC4xxI2CState *s = PPC4xx_I2C(o);
> +
> +    memory_region_init_io(&s->iomem, OBJECT(s), &ppc4xx_i2c_ops, s,
> +                          TYPE_PPC4xx_I2C, PPC4xx_I2C_MEM_SIZE);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
> +    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
> +    s->bus = i2c_init_bus(DEVICE(s), "i2c");
> +}
> +
> +static void ppc4xx_i2c_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->reset = ppc4xx_i2c_reset;
> +}
> +
> +static const TypeInfo ppc4xx_i2c_type_info = {
> +    .name = TYPE_PPC4xx_I2C,
> +    .parent = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(PPC4xxI2CState),
> +    .instance_init = ppc4xx_i2c_init,
> +    .class_init = ppc4xx_i2c_class_init,
> +};
> +
> +static void ppc4xx_i2c_register_types(void)
> +{
> +    type_register_static(&ppc4xx_i2c_type_info);
> +}
> +
> +type_init(ppc4xx_i2c_register_types)
> diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
> index 2077216..7efc686 100644
> --- a/hw/ppc/Makefile.objs
> +++ b/hw/ppc/Makefile.objs
> @@ -13,7 +13,7 @@ endif
>  obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o
>  # PowerPC 4xx boards
>  obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
> -obj-y += ppc4xx_pci.o ppc4xx_i2c.o
> +obj-y += ppc4xx_pci.o
>  # PReP
>  obj-$(CONFIG_PREP) += prep.o
>  obj-$(CONFIG_PREP) += prep_systemio.o
> diff --git a/hw/ppc/ppc4xx_i2c.c b/hw/ppc/ppc4xx_i2c.c
> deleted file mode 100644
> index 5a6bde9..0000000
> --- a/hw/ppc/ppc4xx_i2c.c
> +++ /dev/null
> @@ -1,216 +0,0 @@
> -/*
> - * PPC4xx I2C controller emulation
> - *
> - * Copyright (c) 2007 Jocelyn Mayer
> - *
> - * Permission is hereby granted, free of charge, to any person obtaining a copy
> - * of this software and associated documentation files (the "Software"), to deal
> - * in the Software without restriction, including without limitation the rights
> - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> - * copies of the Software, and to permit persons to whom the Software is
> - * furnished to do so, subject to the following conditions:
> - *
> - * The above copyright notice and this permission notice shall be included in
> - * all copies or substantial portions of the Software.
> - *
> - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> - * THE SOFTWARE.
> - */
> -
> -#include "qemu/osdep.h"
> -#include "qapi/error.h"
> -#include "qemu-common.h"
> -#include "cpu.h"
> -#include "hw/hw.h"
> -#include "hw/i2c/ppc4xx_i2c.h"
> -
> -/*#define DEBUG_I2C*/
> -
> -#define PPC4xx_I2C_MEM_SIZE 0x11
> -
> -static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size)
> -{
> -    PPC4xxI2CState *i2c = PPC4xx_I2C(opaque);
> -    uint64_t ret;
> -
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
> -#endif
> -    switch (addr) {
> -    case 0x00:
> -        /*i2c_readbyte(&i2c->mdata);*/
> -        ret = i2c->mdata;
> -        break;
> -    case 0x02:
> -        ret = i2c->sdata;
> -        break;
> -    case 0x04:
> -        ret = i2c->lmadr;
> -        break;
> -    case 0x05:
> -        ret = i2c->hmadr;
> -        break;
> -    case 0x06:
> -        ret = i2c->cntl;
> -        break;
> -    case 0x07:
> -        ret = i2c->mdcntl;
> -        break;
> -    case 0x08:
> -        ret = i2c->sts;
> -        break;
> -    case 0x09:
> -        ret = i2c->extsts;
> -        break;
> -    case 0x0A:
> -        ret = i2c->lsadr;
> -        break;
> -    case 0x0B:
> -        ret = i2c->hsadr;
> -        break;
> -    case 0x0C:
> -        ret = i2c->clkdiv;
> -        break;
> -    case 0x0D:
> -        ret = i2c->intrmsk;
> -        break;
> -    case 0x0E:
> -        ret = i2c->xfrcnt;
> -        break;
> -    case 0x0F:
> -        ret = i2c->xtcntlss;
> -        break;
> -    case 0x10:
> -        ret = i2c->directcntl;
> -        break;
> -    default:
> -        ret = 0x00;
> -        break;
> -    }
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx " %02" PRIx64 "\n", __func__, addr, ret);
> -#endif
> -
> -    return ret;
> -}
> -
> -static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
> -                              unsigned int size)
> -{
> -    PPC4xxI2CState *i2c = opaque;
> -#ifdef DEBUG_I2C
> -    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx64 "\n",
> -           __func__, addr, value);
> -#endif
> -    switch (addr) {
> -    case 0x00:
> -        i2c->mdata = value;
> -        /*i2c_sendbyte(&i2c->mdata);*/
> -        break;
> -    case 0x02:
> -        i2c->sdata = value;
> -        break;
> -    case 0x04:
> -        i2c->lmadr = value;
> -        break;
> -    case 0x05:
> -        i2c->hmadr = value;
> -        break;
> -    case 0x06:
> -        i2c->cntl = value;
> -        break;
> -    case 0x07:
> -        i2c->mdcntl = value & 0xDF;
> -        break;
> -    case 0x08:
> -        i2c->sts &= ~(value & 0x0A);
> -        break;
> -    case 0x09:
> -        i2c->extsts &= ~(value & 0x8F);
> -        break;
> -    case 0x0A:
> -        i2c->lsadr = value;
> -        break;
> -    case 0x0B:
> -        i2c->hsadr = value;
> -        break;
> -    case 0x0C:
> -        i2c->clkdiv = value;
> -        break;
> -    case 0x0D:
> -        i2c->intrmsk = value;
> -        break;
> -    case 0x0E:
> -        i2c->xfrcnt = value & 0x77;
> -        break;
> -    case 0x0F:
> -        i2c->xtcntlss = value;
> -        break;
> -    case 0x10:
> -        i2c->directcntl = value & 0x7;
> -        break;
> -    }
> -}
> -
> -static const MemoryRegionOps ppc4xx_i2c_ops = {
> -    .read = ppc4xx_i2c_readb,
> -    .write = ppc4xx_i2c_writeb,
> -    .valid.min_access_size = 1,
> -    .valid.max_access_size = 4,
> -    .impl.min_access_size = 1,
> -    .impl.max_access_size = 1,
> -    .endianness = DEVICE_NATIVE_ENDIAN,
> -};
> -
> -static void ppc4xx_i2c_reset(DeviceState *s)
> -{
> -    PPC4xxI2CState *i2c = PPC4xx_I2C(s);
> -
> -    i2c->mdata = 0x00;
> -    i2c->sdata = 0x00;
> -    i2c->cntl = 0x00;
> -    i2c->mdcntl = 0x00;
> -    i2c->sts = 0x00;
> -    i2c->extsts = 0x00;
> -    i2c->clkdiv = 0x00;
> -    i2c->xfrcnt = 0x00;
> -    i2c->directcntl = 0x0F;
> -}
> -
> -static void ppc4xx_i2c_init(Object *o)
> -{
> -    PPC4xxI2CState *s = PPC4xx_I2C(o);
> -
> -    memory_region_init_io(&s->iomem, OBJECT(s), &ppc4xx_i2c_ops, s,
> -                          TYPE_PPC4xx_I2C, PPC4xx_I2C_MEM_SIZE);
> -    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
> -    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
> -    s->bus = i2c_init_bus(DEVICE(s), "i2c");
> -}
> -
> -static void ppc4xx_i2c_class_init(ObjectClass *klass, void *data)
> -{
> -    DeviceClass *dc = DEVICE_CLASS(klass);
> -
> -    dc->reset = ppc4xx_i2c_reset;
> -}
> -
> -static const TypeInfo ppc4xx_i2c_type_info = {
> -    .name = TYPE_PPC4xx_I2C,
> -    .parent = TYPE_SYS_BUS_DEVICE,
> -    .instance_size = sizeof(PPC4xxI2CState),
> -    .instance_init = ppc4xx_i2c_init,
> -    .class_init = ppc4xx_i2c_class_init,
> -};
> -
> -static void ppc4xx_i2c_register_types(void)
> -{
> -    type_register_static(&ppc4xx_i2c_type_info);
> -}
> -
> -type_init(ppc4xx_i2c_register_types)

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 09/15] hw/ide: Emulate SiI3112 SATA controller
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 09/15] hw/ide: Emulate SiI3112 SATA controller BALATON Zoltan
@ 2017-08-21 21:14   ` John Snow
  2017-08-22 11:08     ` BALATON Zoltan
  0 siblings, 1 reply; 66+ messages in thread
From: John Snow @ 2017-08-21 21:14 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel, qemu-ppc
  Cc: Francois Revol, Alexander Graf, David Gibson



On 08/20/2017 01:23 PM, BALATON Zoltan wrote:
> This is a common generic PCI SATA conroller that is also used in PCs
> but more importantly guests running on the Sam460ex board prefer this
> card and have a driver for it (unlike for other SATA controllers
> already emulated).
> 

Oh, interesting. This is basically an alternative to the PCI BMDMA
interface and not really an alternative to AHCI. It doesn't really seem
to use any of the SATA-specific interfaces to SATA drives (cough, not
that we currently emulate a difference in QEMU... ATA and SATA both are
simply IDEState*) so this really seems like another PCI IDE interface
akin to the PCI BMDMA adapter we already have.

It's just that guests will think they're using SATA, except... not. Not
a big deal, *I think*...

...It isn't a problem that our support for NCQ commands is tied to AHCI,
is it? Some of our current "SATA" support is tied very directly to AHCI
(see is_ncq() in ahci.c) -- is that relevant here?

> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>

I'd like to invite you to create a Sam460ex MAINTAINERS stanza, add
yourself, and add hw/ide/sii3112.c to that stanza.

--js

> ---
>  hw/ide/Makefile.objs |   1 +
>  hw/ide/sii3112.c     | 369 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 370 insertions(+)
>  create mode 100644 hw/ide/sii3112.c
> 
> diff --git a/hw/ide/Makefile.objs b/hw/ide/Makefile.objs
> index 729e9bd..76f3d6d 100644
> --- a/hw/ide/Makefile.objs
> +++ b/hw/ide/Makefile.objs
> @@ -10,3 +10,4 @@ common-obj-$(CONFIG_IDE_VIA) += via.o
>  common-obj-$(CONFIG_MICRODRIVE) += microdrive.o
>  common-obj-$(CONFIG_AHCI) += ahci.o
>  common-obj-$(CONFIG_AHCI) += ich.o
> +common-obj-$(CONFIG_IDE_SII3112) += sii3112.o
> diff --git a/hw/ide/sii3112.c b/hw/ide/sii3112.c
> new file mode 100644
> index 0000000..9ec8cd1
> --- /dev/null
> +++ b/hw/ide/sii3112.c
> @@ -0,0 +1,369 @@
> +/*
> + * QEMU SiI3112A PCI to Serial ATA Controller Emulation
> + *
> + * Copyright (C) 2017 BALATON Zoltan <balaton@eik.bme.hu>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + *
> + */
> +
> +/* For documentation on this and similar cards see:
> + * http://wiki.osdev.org/User:Quok/Silicon_Image_Datasheets
> + */

Thank you so much for including docs!

> +
> +#include <qemu/osdep.h>
> +#include <hw/ide/pci.h>
> +
> +#ifdef DEBUG_IDE
> +#define DPRINTF(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__);
> +#else
> +#define DPRINTF(fmt, ...)
> +#endif /* DEBUG */
> +

Please use trace events instead of DPRINTF; I'm in the process of
removing them from the rest of IDE.

> +#define TYPE_SII3112_PCI "sii3112"
> +#define SII3112_PCI(obj) OBJECT_CHECK(SiI3112PCIState, (obj), \
> +                         TYPE_SII3112_PCI)
> +
> +typedef struct SiI3112Regs {
> +    uint32_t confstat;
> +    uint32_t scontrol;
> +    uint16_t sien;
> +    uint8_t swdata;
> +} SiI3112Regs;
> +
> +typedef struct SiI3112PCIState {
> +    PCIIDEState i;
> +    MemoryRegion mmio;
> +    SiI3112Regs regs[2];
> +} SiI3112PCIState;
> +
> +static uint64_t sii3112_reg_read(void *opaque, hwaddr addr,
> +                                unsigned int size)
> +{
> +    SiI3112PCIState *d = opaque;
> +    uint64_t val = 0;
> +
> +    switch (addr) {
> +    case 0x00:
> +        val = d->i.bmdma[0].cmd;
> +        break;
> +    case 0x01:
> +        val = d->regs[0].swdata;
> +        break;
> +    case 0x02:
> +        val = d->i.bmdma[0].status;
> +        break;
> +    case 0x03:
> +        val = 0;
> +        break;
> +    case 0x04 ... 0x07:
> +        val = bmdma_addr_ioport_ops.read(&d->i.bmdma[0], addr - 4, size);
> +        break;
> +    case 0x08:
> +        val = d->i.bmdma[1].cmd;
> +        break;
> +    case 0x09:
> +        val = d->regs[1].swdata;
> +        break;
> +    case 0x0a:
> +        val = d->i.bmdma[1].status;
> +        break;
> +    case 0x0b:
> +        val = 0;
> +        break;
> +    case 0x0c ... 0x0f:
> +        val = bmdma_addr_ioport_ops.read(&d->i.bmdma[1], addr - 12, size);
> +        break;
> +    case 0x10:
> +        val = d->i.bmdma[0].cmd;
> +        val |= (d->regs[0].confstat & (1UL << 11) ? (1 << 4) : 0); /*SATAINT0*/
> +        val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 6) : 0); /*SATAINT1*/
> +        val |= (d->i.bmdma[1].status & BM_STATUS_INT ? (1 << 14) : 0);
> +        val |= d->i.bmdma[0].status << 16;
> +        val |= d->i.bmdma[1].status << 24;
> +        break;
> +    case 0x18:
> +        val = d->i.bmdma[1].cmd;
> +        val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 4) : 0);
> +        val |= d->i.bmdma[1].status << 16;
> +        break;
> +    case 0x80 ... 0x87:
> +        if (size == 1) {
> +            val = ide_ioport_read(&d->i.bus[0], addr - 0x80);
> +        } else if (addr == 0x80) {
> +            val = (size == 2) ? ide_data_readw(&d->i.bus[0], 0) :
> +                                ide_data_readl(&d->i.bus[0], 0);
> +        } else {
> +            val = (1ULL << (size * 8)) - 1;
> +        }
> +        break;
> +    case 0x8a:
> +        val = (size == 1) ? ide_status_read(&d->i.bus[0], 4) :
> +                            (1ULL << (size * 8)) - 1;
> +        break;
> +    case 0xa0:
> +        val = d->regs[0].confstat;
> +        break;
> +    case 0xc0 ... 0xc7:
> +        if (size == 1) {
> +            val = ide_ioport_read(&d->i.bus[1], addr - 0xc0);
> +        } else if (addr == 0xc0) {
> +            val = (size == 2) ? ide_data_readw(&d->i.bus[1], 0) :
> +                                ide_data_readl(&d->i.bus[1], 0);
> +        } else {
> +            val = (1ULL << (size * 8)) - 1;
> +        }
> +        break;
> +    case 0xca:
> +        val = (size == 1) ? ide_status_read(&d->i.bus[0], 4) :
> +                            (1ULL << (size * 8)) - 1;
> +        break;
> +    case 0xe0:
> +        val = d->regs[1].confstat;
> +        break;
> +    case 0x100:
> +        val = d->regs[0].scontrol;
> +        break;
> +    case 0x104:
> +        val = (d->i.bus[0].ifs[0].blk) ? 0x113 : 0;
> +        break;
> +    case 0x148:
> +        val = d->regs[0].sien << 16;
> +        break;
> +    case 0x180:
> +        val = d->regs[1].scontrol;
> +        break;
> +    case 0x184:
> +        val = (d->i.bus[1].ifs[0].blk) ? 0x113 : 0;
> +        break;
> +    case 0x1c8:
> +        val = d->regs[1].sien << 16;
> +        break;
> +    default:
> +        val = 0;
> +    }
> +    DPRINTF("%s: addr 0x%"PRIx64 " size %d = %"PRIx64 "\n",
> +            __func__, addr, size, val);
> +    return val;
> +}
> +
> +static void sii3112_reg_write(void *opaque, hwaddr addr,
> +                              uint64_t val, unsigned int size)
> +{
> +    SiI3112PCIState *d = opaque;
> +
> +    DPRINTF("%s: addr 0x%"PRIx64 " size %d = %"PRIx64 "\n",
> +            __func__, addr, size, val);
> +    switch (addr) {
> +    case 0x00:
> +    case 0x10:
> +        bmdma_cmd_writeb(&d->i.bmdma[0], val);
> +        break;
> +    case 0x01:
> +    case 0x11:
> +        d->regs[0].swdata = val & 0x3f;
> +        break;
> +    case 0x02:
> +    case 0x12:
> +        d->i.bmdma[0].status = (val & 0x60) | (d->i.bmdma[0].status & 1) |
> +                               (d->i.bmdma[0].status & ~val & 6);
> +        break;
> +    case 0x04 ... 0x07:
> +        bmdma_addr_ioport_ops.write(&d->i.bmdma[0], addr - 4, val, size);
> +        break;
> +    case 0x08:
> +    case 0x18:
> +        bmdma_cmd_writeb(&d->i.bmdma[1], val);
> +        break;
> +    case 0x09:
> +    case 0x19:
> +        d->regs[1].swdata = val & 0x3f;
> +        break;
> +    case 0x0a:
> +    case 0x1a:
> +        d->i.bmdma[1].status = (val & 0x60) | (d->i.bmdma[1].status & 1) |
> +                               (d->i.bmdma[1].status & ~val & 6);
> +        break;
> +    case 0x0c ... 0x0f:
> +        bmdma_addr_ioport_ops.write(&d->i.bmdma[1], addr - 12, val, size);
> +        break;


What register(s) sit at [0x10 - 0x1a]?
Isn't BAR4 only 0x00 through 0x0F?


> +    case 0x80 ... 0x87:
> +        if (size == 1) {
> +            ide_ioport_write(&d->i.bus[0], addr - 0x80, val);
> +        } else if (addr == 0x80) {
> +            if (size == 2) {
> +                ide_data_writew(&d->i.bus[0], 0, val);
> +            } else {
> +                ide_data_writel(&d->i.bus[0], 0, val);
> +            }
> +        }
> +        break;
> +    case 0x8a:
> +        if (size == 1) {
> +            ide_cmd_write(&d->i.bus[0], 4, val);
> +        }
> +        break;

IDE0 stuff.

> +    case 0xc0 ... 0xc7:
> +        if (size == 1) {
> +            ide_ioport_write(&d->i.bus[1], addr - 0xc0, val);
> +        } else if (addr == 0xc0) {
> +            if (size == 2) {
> +                ide_data_writew(&d->i.bus[1], 0, val);
> +            } else {
> +                ide_data_writel(&d->i.bus[1], 0, val);
> +            }
> +        }
> +        break;
> +    case 0xca:
> +        if (size == 1) {
> +            ide_cmd_write(&d->i.bus[1], 4, val);
> +        }
> +        break;

IDE1 stuff.

> +    case 0x100:
> +        d->regs[0].scontrol = val & 0xfff;
> +        if (val & 1) {
> +            ide_bus_reset(&d->i.bus[0]);
> +        }
> +        break;
> +    case 0x148:
> +        d->regs[0].sien = (val >> 16) & 0x3eed;
> +        break;
> +    case 0x180:
> +        d->regs[1].scontrol = val & 0xfff;
> +        if (val & 1) {
> +            ide_bus_reset(&d->i.bus[1]);
> +        }
> +        break;
> +    case 0x1c8:
> +        d->regs[1].sien = (val >> 16) & 0x3eed;
> +        break;

Not sure what these ones are.

> +    default:
> +        val = 0;
> +    }
> +}
> +
> +static const MemoryRegionOps sii3112_reg_ops = {
> +    .read = sii3112_reg_read,
> +    .write = sii3112_reg_write,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +};
> +
> +/* the PCI irq level is the logical OR of the two channels */
> +static void sii3112_update_irq(SiI3112PCIState *s)
> +{
> +    int i, set = 0;
> +
> +    for (i = 0; i < 2; i++) {
> +        set |= s->regs[i].confstat & (1UL << 11);
> +    }
> +    pci_set_irq(PCI_DEVICE(s), (set ? 1 : 0));
> +}
> +
> +static void sii3112_set_irq(void *opaque, int channel, int level)
> +{
> +    SiI3112PCIState *s = opaque;
> +
> +    DPRINTF("%s: channel %d level %d\n", __func__, channel, level);
> +    if (level) {
> +        s->regs[channel].confstat |= (1UL << 11);
> +    } else {
> +        s->regs[channel].confstat &= ~(1UL << 11);
> +    }
> +
> +    sii3112_update_irq(s);
> +}
> +
> +static void sii3112_reset(void *opaque)
> +{
> +    SiI3112PCIState *s = opaque;
> +    int i;
> +
> +    for (i = 0; i < 2; i++) {
> +        s->regs[i].confstat = 0x6515 << 16;
> +        ide_bus_reset(&s->i.bus[i]);
> +    }
> +}
> +
> +static void sii3112_pci_realize(PCIDevice *dev, Error **errp)
> +{
> +    SiI3112PCIState *d = SII3112_PCI(dev);
> +    PCIIDEState *s = PCI_IDE(dev);
> +    MemoryRegion *mr;
> +    qemu_irq *irq;
> +    int i;
> +
> +    pci_config_set_interrupt_pin(dev->config, 1);
> +    pci_set_byte(dev->config + PCI_CACHE_LINE_SIZE, 8);
> +
> +    memory_region_init_io(&d->mmio, OBJECT(d), &sii3112_reg_ops, d,
> +                         "sii3112.bar5", 0x200);
> +    pci_register_bar(dev, 5, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
> +
> +    mr = g_new(MemoryRegion, 1);
> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar0", &d->mmio, 0x80, 8);
> +    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, mr);
> +    mr = g_new(MemoryRegion, 1);
> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar1", &d->mmio, 0x88, 4);
> +    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, mr);
> +    mr = g_new(MemoryRegion, 1);

BARS 0 and 1 for IDE0 occupy 0x80 through 0x8C;

> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar2", &d->mmio, 0xc0, 8);
> +    pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, mr);
> +    mr = g_new(MemoryRegion, 1);
> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar3", &d->mmio, 0xc8, 4);
> +    pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_IO, mr);
> +    mr = g_new(MemoryRegion, 1);

BARS 1 and 2 for IDE1 occupy 0xC0 through 0xCC;

> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar4", &d->mmio, 0, 16);
> +    pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, mr);

BAR4 at 0x00 through 0x0F which houses the BMDMA registers.

What occupies 0x10 through 0x7F or 0x8D through 0x1FF?

> +
> +    irq = qemu_allocate_irqs(sii3112_set_irq, d, 2);
> +    for (i = 0; i < 2; i++) {
> +        ide_bus_new(&s->bus[i], sizeof(s->bus[i]), DEVICE(dev), i, 1);
> +        ide_init2(&s->bus[i], irq[i]);
> +
> +        bmdma_init(&s->bus[i], &s->bmdma[i], s);
> +        s->bmdma[i].bus = &s->bus[i];
> +        ide_register_restart_cb(&s->bus[i]);
> +    }
> +    qemu_register_reset(sii3112_reset, s);
> +}
> +
> +static void sii3112_pci_exitfn(PCIDevice *dev)
> +{
> +    PCIIDEState *d = PCI_IDE(dev);
> +    int i;
> +
> +    for (i = 0; i < 2; ++i) {
> +        memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].extra_io);
> +        memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].addr_ioport);
> +    }
> +}
> +
> +static void sii3112_pci_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    PCIDeviceClass *pd = PCI_DEVICE_CLASS(klass);
> +
> +    pd->vendor_id = 0x1095;
> +    pd->device_id = 0x3112;
> +    pd->class_id = PCI_CLASS_STORAGE_RAID;
> +    pd->revision = 1;
> +    pd->realize = sii3112_pci_realize;
> +    pd->exit = sii3112_pci_exitfn;
> +    dc->desc = "SiI3112A SATA controller";
> +    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
> +}
> +
> +static const TypeInfo sii3112_pci_info = {
> +    .name = TYPE_SII3112_PCI,
> +    .parent = TYPE_PCI_IDE,
> +    .instance_size = sizeof(SiI3112PCIState),
> +    .class_init = sii3112_pci_class_init,
> +};
> +
> +static void sii3112_register_types(void)
> +{
> +    type_register_static(&sii3112_pci_info);
> +}
> +
> +type_init(sii3112_register_types)
> 

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 09/15] hw/ide: Emulate SiI3112 SATA controller
  2017-08-21 21:14   ` John Snow
@ 2017-08-22 11:08     ` BALATON Zoltan
  2017-08-22 19:01       ` John Snow
  0 siblings, 1 reply; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-22 11:08 UTC (permalink / raw)
  To: John Snow
  Cc: qemu-devel, qemu-ppc, Francois Revol, Alexander Graf, David Gibson

Hello,

Thanks for the review.

On Mon, 21 Aug 2017, John Snow wrote:
> On 08/20/2017 01:23 PM, BALATON Zoltan wrote:
>> This is a common generic PCI SATA conroller that is also used in PCs
>> but more importantly guests running on the Sam460ex board prefer this
>> card and have a driver for it (unlike for other SATA controllers
>> already emulated).
>
> Oh, interesting. This is basically an alternative to the PCI BMDMA
> interface and not really an alternative to AHCI. It doesn't really seem

Yes, this is a simple PCI SATA interface similar to IDE and not like AHCI. 
I think it's an updated version of the CMD640 IDE interface or more 
closely related to that. The Linux driver references CMD680 as well so 
it's probably a SATA version of that chip.

> to use any of the SATA-specific interfaces to SATA drives (cough, not
> that we currently emulate a difference in QEMU... ATA and SATA both are
> simply IDEState*) so this really seems like another PCI IDE interface
> akin to the PCI BMDMA adapter we already have.
>
> It's just that guests will think they're using SATA, except... not. Not
> a big deal, *I think*...
>
> ...It isn't a problem that our support for NCQ commands is tied to AHCI,
> is it? Some of our current "SATA" support is tied very directly to AHCI
> (see is_ncq() in ahci.c) -- is that relevant here?

I don't think any of the clients on Sam460ex tries to use NCQ so maybe 
it's OK. Linux might have a better driver but I'm not sure. This could be 
fixed later. Although I've seen a hang in Linux which I haven't debugged 
yet and don't know what causes it or if it's related to SATA at all.

I'm not sure I've implemented everything correctly but at least the 
firmware of the board can find disks and load files to boot OSes so basic 
functions should be working. There are some other bugs elsewhere which 
prevent me from testing more OSes at the moment. One of them is QEMU 
crashing sometimes while accessing this SATA controller but it's triggered 
from TCG generated code and depends on some timing because it goes away if 
I change code running in the client or add some debug logs. This is 
described here:

http://lists.nongnu.org/archive/html/qemu-ppc/2017-08/msg00249.html

You don't happen to have an idea or seen similar before, do you? (Likely 
it's not related to IDE but more likely some io memory region interaction 
with TCG.)

I intend to improve this device model later when found necessary but I 
don't have much free time for it now so I'd like to submit it now to get 
some more testing and maybe contributions from others.

>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>
> I'd like to invite you to create a Sam460ex MAINTAINERS stanza, add
> yourself, and add hw/ide/sii3112.c to that stanza.

OK, I'll send a patch for that. David, is it enough to add sii3112 for now 
and leave the others under PPC? I'd get cc as main contributor for them 
anyway I think.

> --js
>
>> ---
>>  hw/ide/Makefile.objs |   1 +
>>  hw/ide/sii3112.c     | 369 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 370 insertions(+)
>>  create mode 100644 hw/ide/sii3112.c
>>
>> diff --git a/hw/ide/Makefile.objs b/hw/ide/Makefile.objs
>> index 729e9bd..76f3d6d 100644
>> --- a/hw/ide/Makefile.objs
>> +++ b/hw/ide/Makefile.objs
>> @@ -10,3 +10,4 @@ common-obj-$(CONFIG_IDE_VIA) += via.o
>>  common-obj-$(CONFIG_MICRODRIVE) += microdrive.o
>>  common-obj-$(CONFIG_AHCI) += ahci.o
>>  common-obj-$(CONFIG_AHCI) += ich.o
>> +common-obj-$(CONFIG_IDE_SII3112) += sii3112.o
>> diff --git a/hw/ide/sii3112.c b/hw/ide/sii3112.c
>> new file mode 100644
>> index 0000000..9ec8cd1
>> --- /dev/null
>> +++ b/hw/ide/sii3112.c
>> @@ -0,0 +1,369 @@
>> +/*
>> + * QEMU SiI3112A PCI to Serial ATA Controller Emulation
>> + *
>> + * Copyright (C) 2017 BALATON Zoltan <balaton@eik.bme.hu>
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
>> + * See the COPYING file in the top-level directory.
>> + *
>> + */
>> +
>> +/* For documentation on this and similar cards see:
>> + * http://wiki.osdev.org/User:Quok/Silicon_Image_Datasheets
>> + */
>
> Thank you so much for including docs!

Thank David who asked for it in the RFC review. :-)

>> +
>> +#include <qemu/osdep.h>
>> +#include <hw/ide/pci.h>
>> +
>> +#ifdef DEBUG_IDE
>> +#define DPRINTF(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__);
>> +#else
>> +#define DPRINTF(fmt, ...)
>> +#endif /* DEBUG */
>> +
>
> Please use trace events instead of DPRINTF; I'm in the process of
> removing them from the rest of IDE.

OK. I found working with DPRINTF easier but I'll convert this to trace 
then.

>> +#define TYPE_SII3112_PCI "sii3112"
>> +#define SII3112_PCI(obj) OBJECT_CHECK(SiI3112PCIState, (obj), \
>> +                         TYPE_SII3112_PCI)
>> +
>> +typedef struct SiI3112Regs {
>> +    uint32_t confstat;
>> +    uint32_t scontrol;
>> +    uint16_t sien;
>> +    uint8_t swdata;
>> +} SiI3112Regs;
>> +
>> +typedef struct SiI3112PCIState {
>> +    PCIIDEState i;
>> +    MemoryRegion mmio;
>> +    SiI3112Regs regs[2];
>> +} SiI3112PCIState;
>> +
>> +static uint64_t sii3112_reg_read(void *opaque, hwaddr addr,
>> +                                unsigned int size)
>> +{
>> +    SiI3112PCIState *d = opaque;
>> +    uint64_t val = 0;
>> +
>> +    switch (addr) {
>> +    case 0x00:
>> +        val = d->i.bmdma[0].cmd;
>> +        break;
>> +    case 0x01:
>> +        val = d->regs[0].swdata;
>> +        break;
>> +    case 0x02:
>> +        val = d->i.bmdma[0].status;
>> +        break;
>> +    case 0x03:
>> +        val = 0;
>> +        break;
>> +    case 0x04 ... 0x07:
>> +        val = bmdma_addr_ioport_ops.read(&d->i.bmdma[0], addr - 4, size);
>> +        break;
>> +    case 0x08:
>> +        val = d->i.bmdma[1].cmd;
>> +        break;
>> +    case 0x09:
>> +        val = d->regs[1].swdata;
>> +        break;
>> +    case 0x0a:
>> +        val = d->i.bmdma[1].status;
>> +        break;
>> +    case 0x0b:
>> +        val = 0;
>> +        break;
>> +    case 0x0c ... 0x0f:
>> +        val = bmdma_addr_ioport_ops.read(&d->i.bmdma[1], addr - 12, size);
>> +        break;
>> +    case 0x10:
>> +        val = d->i.bmdma[0].cmd;
>> +        val |= (d->regs[0].confstat & (1UL << 11) ? (1 << 4) : 0); /*SATAINT0*/
>> +        val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 6) : 0); /*SATAINT1*/
>> +        val |= (d->i.bmdma[1].status & BM_STATUS_INT ? (1 << 14) : 0);
>> +        val |= d->i.bmdma[0].status << 16;
>> +        val |= d->i.bmdma[1].status << 24;
>> +        break;
>> +    case 0x18:
>> +        val = d->i.bmdma[1].cmd;
>> +        val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 4) : 0);
>> +        val |= d->i.bmdma[1].status << 16;
>> +        break;
>> +    case 0x80 ... 0x87:
>> +        if (size == 1) {
>> +            val = ide_ioport_read(&d->i.bus[0], addr - 0x80);
>> +        } else if (addr == 0x80) {
>> +            val = (size == 2) ? ide_data_readw(&d->i.bus[0], 0) :
>> +                                ide_data_readl(&d->i.bus[0], 0);
>> +        } else {
>> +            val = (1ULL << (size * 8)) - 1;
>> +        }
>> +        break;
>> +    case 0x8a:
>> +        val = (size == 1) ? ide_status_read(&d->i.bus[0], 4) :
>> +                            (1ULL << (size * 8)) - 1;
>> +        break;
>> +    case 0xa0:
>> +        val = d->regs[0].confstat;
>> +        break;
>> +    case 0xc0 ... 0xc7:
>> +        if (size == 1) {
>> +            val = ide_ioport_read(&d->i.bus[1], addr - 0xc0);
>> +        } else if (addr == 0xc0) {
>> +            val = (size == 2) ? ide_data_readw(&d->i.bus[1], 0) :
>> +                                ide_data_readl(&d->i.bus[1], 0);
>> +        } else {
>> +            val = (1ULL << (size * 8)) - 1;
>> +        }
>> +        break;
>> +    case 0xca:
>> +        val = (size == 1) ? ide_status_read(&d->i.bus[0], 4) :
>> +                            (1ULL << (size * 8)) - 1;
>> +        break;
>> +    case 0xe0:
>> +        val = d->regs[1].confstat;
>> +        break;
>> +    case 0x100:
>> +        val = d->regs[0].scontrol;
>> +        break;
>> +    case 0x104:
>> +        val = (d->i.bus[0].ifs[0].blk) ? 0x113 : 0;
>> +        break;
>> +    case 0x148:
>> +        val = d->regs[0].sien << 16;
>> +        break;
>> +    case 0x180:
>> +        val = d->regs[1].scontrol;
>> +        break;
>> +    case 0x184:
>> +        val = (d->i.bus[1].ifs[0].blk) ? 0x113 : 0;
>> +        break;
>> +    case 0x1c8:
>> +        val = d->regs[1].sien << 16;
>> +        break;
>> +    default:
>> +        val = 0;
>> +    }
>> +    DPRINTF("%s: addr 0x%"PRIx64 " size %d = %"PRIx64 "\n",
>> +            __func__, addr, size, val);
>> +    return val;
>> +}
>> +
>> +static void sii3112_reg_write(void *opaque, hwaddr addr,
>> +                              uint64_t val, unsigned int size)
>> +{
>> +    SiI3112PCIState *d = opaque;
>> +
>> +    DPRINTF("%s: addr 0x%"PRIx64 " size %d = %"PRIx64 "\n",
>> +            __func__, addr, size, val);
>> +    switch (addr) {
>> +    case 0x00:
>> +    case 0x10:
>> +        bmdma_cmd_writeb(&d->i.bmdma[0], val);
>> +        break;
>> +    case 0x01:
>> +    case 0x11:
>> +        d->regs[0].swdata = val & 0x3f;
>> +        break;
>> +    case 0x02:
>> +    case 0x12:
>> +        d->i.bmdma[0].status = (val & 0x60) | (d->i.bmdma[0].status & 1) |
>> +                               (d->i.bmdma[0].status & ~val & 6);
>> +        break;
>> +    case 0x04 ... 0x07:
>> +        bmdma_addr_ioport_ops.write(&d->i.bmdma[0], addr - 4, val, size);
>> +        break;
>> +    case 0x08:
>> +    case 0x18:
>> +        bmdma_cmd_writeb(&d->i.bmdma[1], val);
>> +        break;
>> +    case 0x09:
>> +    case 0x19:
>> +        d->regs[1].swdata = val & 0x3f;
>> +        break;
>> +    case 0x0a:
>> +    case 0x1a:
>> +        d->i.bmdma[1].status = (val & 0x60) | (d->i.bmdma[1].status & 1) |
>> +                               (d->i.bmdma[1].status & ~val & 6);
>> +        break;
>> +    case 0x0c ... 0x0f:
>> +        bmdma_addr_ioport_ops.write(&d->i.bmdma[1], addr - 12, val, size);
>> +        break;
>
>
> What register(s) sit at [0x10 - 0x1a]?
> Isn't BAR4 only 0x00 through 0x0F?
>
>
>> +    case 0x80 ... 0x87:
>> +        if (size == 1) {
>> +            ide_ioport_write(&d->i.bus[0], addr - 0x80, val);
>> +        } else if (addr == 0x80) {
>> +            if (size == 2) {
>> +                ide_data_writew(&d->i.bus[0], 0, val);
>> +            } else {
>> +                ide_data_writel(&d->i.bus[0], 0, val);
>> +            }
>> +        }
>> +        break;
>> +    case 0x8a:
>> +        if (size == 1) {
>> +            ide_cmd_write(&d->i.bus[0], 4, val);
>> +        }
>> +        break;
>
> IDE0 stuff.
>
>> +    case 0xc0 ... 0xc7:
>> +        if (size == 1) {
>> +            ide_ioport_write(&d->i.bus[1], addr - 0xc0, val);
>> +        } else if (addr == 0xc0) {
>> +            if (size == 2) {
>> +                ide_data_writew(&d->i.bus[1], 0, val);
>> +            } else {
>> +                ide_data_writel(&d->i.bus[1], 0, val);
>> +            }
>> +        }
>> +        break;
>> +    case 0xca:
>> +        if (size == 1) {
>> +            ide_cmd_write(&d->i.bus[1], 4, val);
>> +        }
>> +        break;
>
> IDE1 stuff.
>
>> +    case 0x100:
>> +        d->regs[0].scontrol = val & 0xfff;
>> +        if (val & 1) {
>> +            ide_bus_reset(&d->i.bus[0]);
>> +        }
>> +        break;
>> +    case 0x148:
>> +        d->regs[0].sien = (val >> 16) & 0x3eed;
>> +        break;
>> +    case 0x180:
>> +        d->regs[1].scontrol = val & 0xfff;
>> +        if (val & 1) {
>> +            ide_bus_reset(&d->i.bus[1]);
>> +        }
>> +        break;
>> +    case 0x1c8:
>> +        d->regs[1].sien = (val >> 16) & 0x3eed;
>> +        break;
>
> Not sure what these ones are.

These are some SATA specific registers mostly controlling features we 
don't emulate (such as power management, SATA standard level and also used 
to reset the connected drive which is the only thing emulated because 
drivers use this). 0x100 and 0x148 are for channel 0 the other two are 
corresponding registers for channel 1.

>> +    default:
>> +        val = 0;
>> +    }
>> +}
>> +
>> +static const MemoryRegionOps sii3112_reg_ops = {
>> +    .read = sii3112_reg_read,
>> +    .write = sii3112_reg_write,
>> +    .endianness = DEVICE_LITTLE_ENDIAN,
>> +};
>> +
>> +/* the PCI irq level is the logical OR of the two channels */
>> +static void sii3112_update_irq(SiI3112PCIState *s)
>> +{
>> +    int i, set = 0;
>> +
>> +    for (i = 0; i < 2; i++) {
>> +        set |= s->regs[i].confstat & (1UL << 11);
>> +    }
>> +    pci_set_irq(PCI_DEVICE(s), (set ? 1 : 0));
>> +}
>> +
>> +static void sii3112_set_irq(void *opaque, int channel, int level)
>> +{
>> +    SiI3112PCIState *s = opaque;
>> +
>> +    DPRINTF("%s: channel %d level %d\n", __func__, channel, level);
>> +    if (level) {
>> +        s->regs[channel].confstat |= (1UL << 11);
>> +    } else {
>> +        s->regs[channel].confstat &= ~(1UL << 11);
>> +    }
>> +
>> +    sii3112_update_irq(s);
>> +}
>> +
>> +static void sii3112_reset(void *opaque)
>> +{
>> +    SiI3112PCIState *s = opaque;
>> +    int i;
>> +
>> +    for (i = 0; i < 2; i++) {
>> +        s->regs[i].confstat = 0x6515 << 16;
>> +        ide_bus_reset(&s->i.bus[i]);
>> +    }
>> +}
>> +
>> +static void sii3112_pci_realize(PCIDevice *dev, Error **errp)
>> +{
>> +    SiI3112PCIState *d = SII3112_PCI(dev);
>> +    PCIIDEState *s = PCI_IDE(dev);
>> +    MemoryRegion *mr;
>> +    qemu_irq *irq;
>> +    int i;
>> +
>> +    pci_config_set_interrupt_pin(dev->config, 1);
>> +    pci_set_byte(dev->config + PCI_CACHE_LINE_SIZE, 8);
>> +
>> +    memory_region_init_io(&d->mmio, OBJECT(d), &sii3112_reg_ops, d,
>> +                         "sii3112.bar5", 0x200);
>> +    pci_register_bar(dev, 5, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
>> +
>> +    mr = g_new(MemoryRegion, 1);
>> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar0", &d->mmio, 0x80, 8);
>> +    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, mr);
>> +    mr = g_new(MemoryRegion, 1);
>> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar1", &d->mmio, 0x88, 4);
>> +    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, mr);
>> +    mr = g_new(MemoryRegion, 1);
>
> BARS 0 and 1 for IDE0 occupy 0x80 through 0x8C;
>
>> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar2", &d->mmio, 0xc0, 8);
>> +    pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, mr);
>> +    mr = g_new(MemoryRegion, 1);
>> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar3", &d->mmio, 0xc8, 4);
>> +    pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_IO, mr);
>> +    mr = g_new(MemoryRegion, 1);
>
> BARS 1 and 2 for IDE1 occupy 0xC0 through 0xCC;
>
>> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar4", &d->mmio, 0, 16);
>> +    pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, mr);
>
> BAR4 at 0x00 through 0x0F which houses the BMDMA registers.
>
> What occupies 0x10 through 0x7F or 0x8D through 0x1FF?

I'm not sure, there's a table in the datasheet that details this. 
Basically everything is in BAR5 which is an mmio region and BAR0-4 are io 
space aliases into this mmio region. (I think this is to support accessing 
it both via mmio and io space or to make it similar to IDE to make it 
easier to port older drivers.) Most of the empty areas are documented as 
Reserved in the datasheet.

>> +
>> +    irq = qemu_allocate_irqs(sii3112_set_irq, d, 2);
>> +    for (i = 0; i < 2; i++) {
>> +        ide_bus_new(&s->bus[i], sizeof(s->bus[i]), DEVICE(dev), i, 1);
>> +        ide_init2(&s->bus[i], irq[i]);
>> +
>> +        bmdma_init(&s->bus[i], &s->bmdma[i], s);
>> +        s->bmdma[i].bus = &s->bus[i];
>> +        ide_register_restart_cb(&s->bus[i]);
>> +    }
>> +    qemu_register_reset(sii3112_reset, s);
>> +}
>> +
>> +static void sii3112_pci_exitfn(PCIDevice *dev)
>> +{
>> +    PCIIDEState *d = PCI_IDE(dev);
>> +    int i;
>> +
>> +    for (i = 0; i < 2; ++i) {
>> +        memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].extra_io);
>> +        memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].addr_ioport);
>> +    }
>> +}
>> +
>> +static void sii3112_pci_class_init(ObjectClass *klass, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>> +    PCIDeviceClass *pd = PCI_DEVICE_CLASS(klass);
>> +
>> +    pd->vendor_id = 0x1095;
>> +    pd->device_id = 0x3112;
>> +    pd->class_id = PCI_CLASS_STORAGE_RAID;
>> +    pd->revision = 1;
>> +    pd->realize = sii3112_pci_realize;
>> +    pd->exit = sii3112_pci_exitfn;
>> +    dc->desc = "SiI3112A SATA controller";
>> +    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>> +}
>> +
>> +static const TypeInfo sii3112_pci_info = {
>> +    .name = TYPE_SII3112_PCI,
>> +    .parent = TYPE_PCI_IDE,
>> +    .instance_size = sizeof(SiI3112PCIState),
>> +    .class_init = sii3112_pci_class_init,
>> +};
>> +
>> +static void sii3112_register_types(void)
>> +{
>> +    type_register_static(&sii3112_pci_info);
>> +}
>> +
>> +type_init(sii3112_register_types)
>>
>
>

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 09/15] hw/ide: Emulate SiI3112 SATA controller
  2017-08-22 11:08     ` BALATON Zoltan
@ 2017-08-22 19:01       ` John Snow
  2017-08-22 20:15         ` BALATON Zoltan
  2017-08-23  0:52         ` David Gibson
  0 siblings, 2 replies; 66+ messages in thread
From: John Snow @ 2017-08-22 19:01 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: qemu-devel, qemu-ppc, Francois Revol, Alexander Graf, David Gibson



On 08/22/2017 07:08 AM, BALATON Zoltan wrote:
> Hello,
> 
> Thanks for the review.
> 
> On Mon, 21 Aug 2017, John Snow wrote:
>> On 08/20/2017 01:23 PM, BALATON Zoltan wrote:
>>> This is a common generic PCI SATA conroller that is also used in PCs
>>> but more importantly guests running on the Sam460ex board prefer this
>>> card and have a driver for it (unlike for other SATA controllers
>>> already emulated).
>>
>> Oh, interesting. This is basically an alternative to the PCI BMDMA
>> interface and not really an alternative to AHCI. It doesn't really seem
> 
> Yes, this is a simple PCI SATA interface similar to IDE and not like
> AHCI. I think it's an updated version of the CMD640 IDE interface or
> more closely related to that. The Linux driver references CMD680 as well
> so it's probably a SATA version of that chip.
> 
>> to use any of the SATA-specific interfaces to SATA drives (cough, not
>> that we currently emulate a difference in QEMU... ATA and SATA both are
>> simply IDEState*) so this really seems like another PCI IDE interface
>> akin to the PCI BMDMA adapter we already have.
>>
>> It's just that guests will think they're using SATA, except... not. Not
>> a big deal, *I think*...
>>
>> ...It isn't a problem that our support for NCQ commands is tied to AHCI,
>> is it? Some of our current "SATA" support is tied very directly to AHCI
>> (see is_ncq() in ahci.c) -- is that relevant here?
> 
> I don't think any of the clients on Sam460ex tries to use NCQ so maybe
> it's OK. Linux might have a better driver but I'm not sure. This could
> be fixed later. Although I've seen a hang in Linux which I haven't
> debugged yet and don't know what causes it or if it's related to SATA at
> all.
> 
> I'm not sure I've implemented everything correctly but at least the
> firmware of the board can find disks and load files to boot OSes so
> basic functions should be working. There are some other bugs elsewhere
> which prevent me from testing more OSes at the moment. One of them is
> QEMU crashing sometimes while accessing this SATA controller but it's
> triggered from TCG generated code and depends on some timing because it
> goes away if I change code running in the client or add some debug logs.
> This is described here:
> 

"Elsewhere" as in "Not seemingly related to this controller," it seems.

> http://lists.nongnu.org/archive/html/qemu-ppc/2017-08/msg00249.html
> 
> You don't happen to have an idea or seen similar before, do you? (Likely
> it's not related to IDE but more likely some io memory region
> interaction with TCG.)
> 

Sorry, the traces look foreign to me.

> I intend to improve this device model later when found necessary but I
> don't have much free time for it now so I'd like to submit it now to get
> some more testing and maybe contributions from others.
> 

Sure, but be advised that if the device causes problems outside of this
use case and there's nobody willing or able to review it, that it may
get removed again.

I don't have a lot of free time to go through the register list point by
point and make sure this is implemented correctly either, but if this
helps your work I'm OK not holding it up.

>>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>>
>> I'd like to invite you to create a Sam460ex MAINTAINERS stanza, add
>> yourself, and add hw/ide/sii3112.c to that stanza.
> 
> OK, I'll send a patch for that. David, is it enough to add sii3112 for
> now and leave the others under PPC? I'd get cc as main contributor for
> them anyway I think.
> 
>> --js
>>
>>> ---
>>>  hw/ide/Makefile.objs |   1 +
>>>  hw/ide/sii3112.c     | 369
>>> +++++++++++++++++++++++++++++++++++++++++++++++++++
>>>  2 files changed, 370 insertions(+)
>>>  create mode 100644 hw/ide/sii3112.c
>>>
>>> diff --git a/hw/ide/Makefile.objs b/hw/ide/Makefile.objs
>>> index 729e9bd..76f3d6d 100644
>>> --- a/hw/ide/Makefile.objs
>>> +++ b/hw/ide/Makefile.objs
>>> @@ -10,3 +10,4 @@ common-obj-$(CONFIG_IDE_VIA) += via.o
>>>  common-obj-$(CONFIG_MICRODRIVE) += microdrive.o
>>>  common-obj-$(CONFIG_AHCI) += ahci.o
>>>  common-obj-$(CONFIG_AHCI) += ich.o
>>> +common-obj-$(CONFIG_IDE_SII3112) += sii3112.o
>>> diff --git a/hw/ide/sii3112.c b/hw/ide/sii3112.c
>>> new file mode 100644
>>> index 0000000..9ec8cd1
>>> --- /dev/null
>>> +++ b/hw/ide/sii3112.c
>>> @@ -0,0 +1,369 @@
>>> +/*
>>> + * QEMU SiI3112A PCI to Serial ATA Controller Emulation
>>> + *
>>> + * Copyright (C) 2017 BALATON Zoltan <balaton@eik.bme.hu>
>>> + *
>>> + * This work is licensed under the terms of the GNU GPL, version 2
>>> or later.
>>> + * See the COPYING file in the top-level directory.
>>> + *
>>> + */
>>> +
>>> +/* For documentation on this and similar cards see:
>>> + * http://wiki.osdev.org/User:Quok/Silicon_Image_Datasheets
>>> + */
>>
>> Thank you so much for including docs!
> 
> Thank David who asked for it in the RFC review. :-)
> 
>>> +
>>> +#include <qemu/osdep.h>
>>> +#include <hw/ide/pci.h>
>>> +
>>> +#ifdef DEBUG_IDE
>>> +#define DPRINTF(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__);
>>> +#else
>>> +#define DPRINTF(fmt, ...)
>>> +#endif /* DEBUG */
>>> +
>>
>> Please use trace events instead of DPRINTF; I'm in the process of
>> removing them from the rest of IDE.
> 
> OK. I found working with DPRINTF easier but I'll convert this to trace
> then.
> 

yeah, they're easier to implement but they're more prone to bitrot, and
harder to control with any finesse, so they're coming out for 2.11.

>>> +#define TYPE_SII3112_PCI "sii3112"
>>> +#define SII3112_PCI(obj) OBJECT_CHECK(SiI3112PCIState, (obj), \
>>> +                         TYPE_SII3112_PCI)
>>> +
>>> +typedef struct SiI3112Regs {
>>> +    uint32_t confstat;
>>> +    uint32_t scontrol;
>>> +    uint16_t sien;
>>> +    uint8_t swdata;
>>> +} SiI3112Regs;
>>> +
>>> +typedef struct SiI3112PCIState {
>>> +    PCIIDEState i;
>>> +    MemoryRegion mmio;
>>> +    SiI3112Regs regs[2];
>>> +} SiI3112PCIState;
>>> +
>>> +static uint64_t sii3112_reg_read(void *opaque, hwaddr addr,
>>> +                                unsigned int size)
>>> +{
>>> +    SiI3112PCIState *d = opaque;
>>> +    uint64_t val = 0;
>>> +
>>> +    switch (addr) {
>>> +    case 0x00:
>>> +        val = d->i.bmdma[0].cmd;
>>> +        break;
>>> +    case 0x01:
>>> +        val = d->regs[0].swdata;
>>> +        break;
>>> +    case 0x02:
>>> +        val = d->i.bmdma[0].status;
>>> +        break;
>>> +    case 0x03:
>>> +        val = 0;
>>> +        break;
>>> +    case 0x04 ... 0x07:
>>> +        val = bmdma_addr_ioport_ops.read(&d->i.bmdma[0], addr - 4,
>>> size);
>>> +        break;
>>> +    case 0x08:
>>> +        val = d->i.bmdma[1].cmd;
>>> +        break;
>>> +    case 0x09:
>>> +        val = d->regs[1].swdata;
>>> +        break;
>>> +    case 0x0a:
>>> +        val = d->i.bmdma[1].status;
>>> +        break;
>>> +    case 0x0b:
>>> +        val = 0;
>>> +        break;
>>> +    case 0x0c ... 0x0f:
>>> +        val = bmdma_addr_ioport_ops.read(&d->i.bmdma[1], addr - 12,
>>> size);
>>> +        break;
>>> +    case 0x10:
>>> +        val = d->i.bmdma[0].cmd;
>>> +        val |= (d->regs[0].confstat & (1UL << 11) ? (1 << 4) : 0);
>>> /*SATAINT0*/
>>> +        val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 6) : 0);
>>> /*SATAINT1*/
>>> +        val |= (d->i.bmdma[1].status & BM_STATUS_INT ? (1 << 14) : 0);
>>> +        val |= d->i.bmdma[0].status << 16;
>>> +        val |= d->i.bmdma[1].status << 24;
>>> +        break;
>>> +    case 0x18:
>>> +        val = d->i.bmdma[1].cmd;
>>> +        val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 4) : 0);
>>> +        val |= d->i.bmdma[1].status << 16;
>>> +        break;
>>> +    case 0x80 ... 0x87:
>>> +        if (size == 1) {
>>> +            val = ide_ioport_read(&d->i.bus[0], addr - 0x80);
>>> +        } else if (addr == 0x80) {
>>> +            val = (size == 2) ? ide_data_readw(&d->i.bus[0], 0) :
>>> +                                ide_data_readl(&d->i.bus[0], 0);
>>> +        } else {
>>> +            val = (1ULL << (size * 8)) - 1;
>>> +        }
>>> +        break;
>>> +    case 0x8a:
>>> +        val = (size == 1) ? ide_status_read(&d->i.bus[0], 4) :
>>> +                            (1ULL << (size * 8)) - 1;
>>> +        break;
>>> +    case 0xa0:
>>> +        val = d->regs[0].confstat;
>>> +        break;
>>> +    case 0xc0 ... 0xc7:
>>> +        if (size == 1) {
>>> +            val = ide_ioport_read(&d->i.bus[1], addr - 0xc0);
>>> +        } else if (addr == 0xc0) {
>>> +            val = (size == 2) ? ide_data_readw(&d->i.bus[1], 0) :
>>> +                                ide_data_readl(&d->i.bus[1], 0);
>>> +        } else {
>>> +            val = (1ULL << (size * 8)) - 1;
>>> +        }
>>> +        break;
>>> +    case 0xca:
>>> +        val = (size == 1) ? ide_status_read(&d->i.bus[0], 4) :
>>> +                            (1ULL << (size * 8)) - 1;
>>> +        break;
>>> +    case 0xe0:
>>> +        val = d->regs[1].confstat;
>>> +        break;
>>> +    case 0x100:
>>> +        val = d->regs[0].scontrol;
>>> +        break;
>>> +    case 0x104:
>>> +        val = (d->i.bus[0].ifs[0].blk) ? 0x113 : 0;
>>> +        break;
>>> +    case 0x148:
>>> +        val = d->regs[0].sien << 16;
>>> +        break;
>>> +    case 0x180:
>>> +        val = d->regs[1].scontrol;
>>> +        break;
>>> +    case 0x184:
>>> +        val = (d->i.bus[1].ifs[0].blk) ? 0x113 : 0;
>>> +        break;
>>> +    case 0x1c8:
>>> +        val = d->regs[1].sien << 16;
>>> +        break;
>>> +    default:
>>> +        val = 0;
>>> +    }
>>> +    DPRINTF("%s: addr 0x%"PRIx64 " size %d = %"PRIx64 "\n",
>>> +            __func__, addr, size, val);
>>> +    return val;
>>> +}
>>> +
>>> +static void sii3112_reg_write(void *opaque, hwaddr addr,
>>> +                              uint64_t val, unsigned int size)
>>> +{
>>> +    SiI3112PCIState *d = opaque;
>>> +
>>> +    DPRINTF("%s: addr 0x%"PRIx64 " size %d = %"PRIx64 "\n",
>>> +            __func__, addr, size, val);
>>> +    switch (addr) {
>>> +    case 0x00:
>>> +    case 0x10:
>>> +        bmdma_cmd_writeb(&d->i.bmdma[0], val);
>>> +        break;
>>> +    case 0x01:
>>> +    case 0x11:
>>> +        d->regs[0].swdata = val & 0x3f;
>>> +        break;
>>> +    case 0x02:
>>> +    case 0x12:
>>> +        d->i.bmdma[0].status = (val & 0x60) | (d->i.bmdma[0].status
>>> & 1) |
>>> +                               (d->i.bmdma[0].status & ~val & 6);
>>> +        break;
>>> +    case 0x04 ... 0x07:
>>> +        bmdma_addr_ioport_ops.write(&d->i.bmdma[0], addr - 4, val,
>>> size);
>>> +        break;
>>> +    case 0x08:
>>> +    case 0x18:
>>> +        bmdma_cmd_writeb(&d->i.bmdma[1], val);
>>> +        break;
>>> +    case 0x09:
>>> +    case 0x19:
>>> +        d->regs[1].swdata = val & 0x3f;
>>> +        break;
>>> +    case 0x0a:
>>> +    case 0x1a:
>>> +        d->i.bmdma[1].status = (val & 0x60) | (d->i.bmdma[1].status
>>> & 1) |
>>> +                               (d->i.bmdma[1].status & ~val & 6);
>>> +        break;
>>> +    case 0x0c ... 0x0f:
>>> +        bmdma_addr_ioport_ops.write(&d->i.bmdma[1], addr - 12, val,
>>> size);
>>> +        break;
>>
>>
>> What register(s) sit at [0x10 - 0x1a]?
>> Isn't BAR4 only 0x00 through 0x0F?
>>
>>
>>> +    case 0x80 ... 0x87:
>>> +        if (size == 1) {
>>> +            ide_ioport_write(&d->i.bus[0], addr - 0x80, val);
>>> +        } else if (addr == 0x80) {
>>> +            if (size == 2) {
>>> +                ide_data_writew(&d->i.bus[0], 0, val);
>>> +            } else {
>>> +                ide_data_writel(&d->i.bus[0], 0, val);
>>> +            }
>>> +        }
>>> +        break;
>>> +    case 0x8a:
>>> +        if (size == 1) {
>>> +            ide_cmd_write(&d->i.bus[0], 4, val);
>>> +        }
>>> +        break;
>>
>> IDE0 stuff.
>>
>>> +    case 0xc0 ... 0xc7:
>>> +        if (size == 1) {
>>> +            ide_ioport_write(&d->i.bus[1], addr - 0xc0, val);
>>> +        } else if (addr == 0xc0) {
>>> +            if (size == 2) {
>>> +                ide_data_writew(&d->i.bus[1], 0, val);
>>> +            } else {
>>> +                ide_data_writel(&d->i.bus[1], 0, val);
>>> +            }
>>> +        }
>>> +        break;
>>> +    case 0xca:
>>> +        if (size == 1) {
>>> +            ide_cmd_write(&d->i.bus[1], 4, val);
>>> +        }
>>> +        break;
>>
>> IDE1 stuff.
>>
>>> +    case 0x100:
>>> +        d->regs[0].scontrol = val & 0xfff;
>>> +        if (val & 1) {
>>> +            ide_bus_reset(&d->i.bus[0]);
>>> +        }
>>> +        break;
>>> +    case 0x148:
>>> +        d->regs[0].sien = (val >> 16) & 0x3eed;
>>> +        break;
>>> +    case 0x180:
>>> +        d->regs[1].scontrol = val & 0xfff;
>>> +        if (val & 1) {
>>> +            ide_bus_reset(&d->i.bus[1]);
>>> +        }
>>> +        break;
>>> +    case 0x1c8:
>>> +        d->regs[1].sien = (val >> 16) & 0x3eed;
>>> +        break;
>>
>> Not sure what these ones are.
> 
> These are some SATA specific registers mostly controlling features we
> don't emulate (such as power management, SATA standard level and also
> used to reset the connected drive which is the only thing emulated
> because drivers use this). 0x100 and 0x148 are for channel 0 the other
> two are corresponding registers for channel 1.
> 
>>> +    default:
>>> +        val = 0;
>>> +    }
>>> +}
>>> +
>>> +static const MemoryRegionOps sii3112_reg_ops = {
>>> +    .read = sii3112_reg_read,
>>> +    .write = sii3112_reg_write,
>>> +    .endianness = DEVICE_LITTLE_ENDIAN,
>>> +};
>>> +
>>> +/* the PCI irq level is the logical OR of the two channels */
>>> +static void sii3112_update_irq(SiI3112PCIState *s)
>>> +{
>>> +    int i, set = 0;
>>> +
>>> +    for (i = 0; i < 2; i++) {
>>> +        set |= s->regs[i].confstat & (1UL << 11);
>>> +    }
>>> +    pci_set_irq(PCI_DEVICE(s), (set ? 1 : 0));
>>> +}
>>> +
>>> +static void sii3112_set_irq(void *opaque, int channel, int level)
>>> +{
>>> +    SiI3112PCIState *s = opaque;
>>> +
>>> +    DPRINTF("%s: channel %d level %d\n", __func__, channel, level);
>>> +    if (level) {
>>> +        s->regs[channel].confstat |= (1UL << 11);
>>> +    } else {
>>> +        s->regs[channel].confstat &= ~(1UL << 11);
>>> +    }
>>> +
>>> +    sii3112_update_irq(s);
>>> +}
>>> +
>>> +static void sii3112_reset(void *opaque)
>>> +{
>>> +    SiI3112PCIState *s = opaque;
>>> +    int i;
>>> +
>>> +    for (i = 0; i < 2; i++) {
>>> +        s->regs[i].confstat = 0x6515 << 16;
>>> +        ide_bus_reset(&s->i.bus[i]);
>>> +    }
>>> +}
>>> +
>>> +static void sii3112_pci_realize(PCIDevice *dev, Error **errp)
>>> +{
>>> +    SiI3112PCIState *d = SII3112_PCI(dev);
>>> +    PCIIDEState *s = PCI_IDE(dev);
>>> +    MemoryRegion *mr;
>>> +    qemu_irq *irq;
>>> +    int i;
>>> +
>>> +    pci_config_set_interrupt_pin(dev->config, 1);
>>> +    pci_set_byte(dev->config + PCI_CACHE_LINE_SIZE, 8);
>>> +
>>> +    memory_region_init_io(&d->mmio, OBJECT(d), &sii3112_reg_ops, d,
>>> +                         "sii3112.bar5", 0x200);
>>> +    pci_register_bar(dev, 5, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
>>> +
>>> +    mr = g_new(MemoryRegion, 1);
>>> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar0",
>>> &d->mmio, 0x80, 8);
>>> +    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, mr);
>>> +    mr = g_new(MemoryRegion, 1);
>>> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar1",
>>> &d->mmio, 0x88, 4);
>>> +    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, mr);
>>> +    mr = g_new(MemoryRegion, 1);
>>
>> BARS 0 and 1 for IDE0 occupy 0x80 through 0x8C;
>>
>>> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar2",
>>> &d->mmio, 0xc0, 8);
>>> +    pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, mr);
>>> +    mr = g_new(MemoryRegion, 1);
>>> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar3",
>>> &d->mmio, 0xc8, 4);
>>> +    pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_IO, mr);
>>> +    mr = g_new(MemoryRegion, 1);
>>
>> BARS 1 and 2 for IDE1 occupy 0xC0 through 0xCC;
>>
>>> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar4",
>>> &d->mmio, 0, 16);
>>> +    pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, mr);
>>
>> BAR4 at 0x00 through 0x0F which houses the BMDMA registers.
>>
>> What occupies 0x10 through 0x7F or 0x8D through 0x1FF?
> 
> I'm not sure, there's a table in the datasheet that details this.
> Basically everything is in BAR5 which is an mmio region and BAR0-4 are
> io space aliases into this mmio region. (I think this is to support
> accessing it both via mmio and io space or to make it similar to IDE to
> make it easier to port older drivers.) Most of the empty areas are
> documented as Reserved in the datasheet.
> 

oh, I did actually miss that you register BAR5 as MMIO first, thanks,
that clears this all up.

So we've got BAR5 that occupies 0x200 bytes of PCI MMIO space and for which:

[0x00 - 0x0F]: Duplicated as PCI I/O space via BAR4
[0x80 - 0x87]: Duplicated as PCI I/O space via BAR0
[0x88 - 0x8B]: Duplicated as PCI I/O space via BAR1
[0xC0 - 0xC7]: Duplicated as PCI I/O space via BAR2
[0xC8 - 0xCB]: Duplicated as PCI I/O space via BAR3

I might appreciate a comment somewhere near the read or write (or both)
with a quick pointer to check out section 6.7 of the spec for a listing
of the BAR5 offsets and meanings, with a brief mention of the
dual-mapping for the registers in BAR0-4.

Oh, as a last question, does the dual-mapping here work correctly with
respects to the offsets? I imagine the read/write functions get offsets
into the region mapped (0x200) and not necessarily offsets into the
region accessed (4, 8, 16 bytes etc) right?

>>> +
>>> +    irq = qemu_allocate_irqs(sii3112_set_irq, d, 2);
>>> +    for (i = 0; i < 2; i++) {
>>> +        ide_bus_new(&s->bus[i], sizeof(s->bus[i]), DEVICE(dev), i, 1);
>>> +        ide_init2(&s->bus[i], irq[i]);
>>> +
>>> +        bmdma_init(&s->bus[i], &s->bmdma[i], s);
>>> +        s->bmdma[i].bus = &s->bus[i];
>>> +        ide_register_restart_cb(&s->bus[i]);
>>> +    }
>>> +    qemu_register_reset(sii3112_reset, s);
>>> +}
>>> +
>>> +static void sii3112_pci_exitfn(PCIDevice *dev)
>>> +{
>>> +    PCIIDEState *d = PCI_IDE(dev);
>>> +    int i;
>>> +
>>> +    for (i = 0; i < 2; ++i) {
>>> +        memory_region_del_subregion(&d->bmdma_bar,
>>> &d->bmdma[i].extra_io);
>>> +        memory_region_del_subregion(&d->bmdma_bar,
>>> &d->bmdma[i].addr_ioport);
>>> +    }
>>> +}
>>> +
>>> +static void sii3112_pci_class_init(ObjectClass *klass, void *data)
>>> +{
>>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>>> +    PCIDeviceClass *pd = PCI_DEVICE_CLASS(klass);
>>> +
>>> +    pd->vendor_id = 0x1095;
>>> +    pd->device_id = 0x3112;
>>> +    pd->class_id = PCI_CLASS_STORAGE_RAID;
>>> +    pd->revision = 1;
>>> +    pd->realize = sii3112_pci_realize;
>>> +    pd->exit = sii3112_pci_exitfn;
>>> +    dc->desc = "SiI3112A SATA controller";
>>> +    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>>> +}
>>> +
>>> +static const TypeInfo sii3112_pci_info = {
>>> +    .name = TYPE_SII3112_PCI,
>>> +    .parent = TYPE_PCI_IDE,
>>> +    .instance_size = sizeof(SiI3112PCIState),
>>> +    .class_init = sii3112_pci_class_init,
>>> +};
>>> +
>>> +static void sii3112_register_types(void)
>>> +{
>>> +    type_register_static(&sii3112_pci_info);
>>> +}
>>> +
>>> +type_init(sii3112_register_types)
>>>
>>
>>

-- 
—js

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 09/15] hw/ide: Emulate SiI3112 SATA controller
  2017-08-22 19:01       ` John Snow
@ 2017-08-22 20:15         ` BALATON Zoltan
  2017-08-22 20:21           ` John Snow
  2017-08-23  0:52         ` David Gibson
  1 sibling, 1 reply; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-22 20:15 UTC (permalink / raw)
  To: John Snow
  Cc: qemu-devel, qemu-ppc, Francois Revol, Alexander Graf, David Gibson

On Tue, 22 Aug 2017, John Snow wrote:
> On 08/22/2017 07:08 AM, BALATON Zoltan wrote:
>> Hello,
>>
>> Thanks for the review.
>>
>> On Mon, 21 Aug 2017, John Snow wrote:
>>> On 08/20/2017 01:23 PM, BALATON Zoltan wrote:
>>>> This is a common generic PCI SATA conroller that is also used in PCs
>>>> but more importantly guests running on the Sam460ex board prefer this
>>>> card and have a driver for it (unlike for other SATA controllers
>>>> already emulated).
>>>
>>> Oh, interesting. This is basically an alternative to the PCI BMDMA
>>> interface and not really an alternative to AHCI. It doesn't really seem
>>
>> Yes, this is a simple PCI SATA interface similar to IDE and not like
>> AHCI. I think it's an updated version of the CMD640 IDE interface or
>> more closely related to that. The Linux driver references CMD680 as well
>> so it's probably a SATA version of that chip.
>>
>>> to use any of the SATA-specific interfaces to SATA drives (cough, not
>>> that we currently emulate a difference in QEMU... ATA and SATA both are
>>> simply IDEState*) so this really seems like another PCI IDE interface
>>> akin to the PCI BMDMA adapter we already have.
>>>
>>> It's just that guests will think they're using SATA, except... not. Not
>>> a big deal, *I think*...
>>>
>>> ...It isn't a problem that our support for NCQ commands is tied to AHCI,
>>> is it? Some of our current "SATA" support is tied very directly to AHCI
>>> (see is_ncq() in ahci.c) -- is that relevant here?
>>
>> I don't think any of the clients on Sam460ex tries to use NCQ so maybe
>> it's OK. Linux might have a better driver but I'm not sure. This could
>> be fixed later. Although I've seen a hang in Linux which I haven't
>> debugged yet and don't know what causes it or if it's related to SATA at
>> all.
>>
>> I'm not sure I've implemented everything correctly but at least the
>> firmware of the board can find disks and load files to boot OSes so
>> basic functions should be working. There are some other bugs elsewhere
>> which prevent me from testing more OSes at the moment. One of them is
>> QEMU crashing sometimes while accessing this SATA controller but it's
>> triggered from TCG generated code and depends on some timing because it
>> goes away if I change code running in the client or add some debug logs.
>> This is described here:
>>
>
> "Elsewhere" as in "Not seemingly related to this controller," it seems.

Yes, I suspect the bug is not related to this controller implementation 
(although happening while accessing this device) but since I don't know 
what causes it I'm not 100% sure. But since it's not crashing in this code 
it's likely not related.

>> http://lists.nongnu.org/archive/html/qemu-ppc/2017-08/msg00249.html
>>
>> You don't happen to have an idea or seen similar before, do you? (Likely
>> it's not related to IDE but more likely some io memory region
>> interaction with TCG.)
>>
>
> Sorry, the traces look foreign to me.
>
>> I intend to improve this device model later when found necessary but I
>> don't have much free time for it now so I'd like to submit it now to get
>> some more testing and maybe contributions from others.
>>
>
> Sure, but be advised that if the device causes problems outside of this
> use case and there's nobody willing or able to review it, that it may
> get removed again.
>
> I don't have a lot of free time to go through the register list point by
> point and make sure this is implemented correctly either, but if this
> helps your work I'm OK not holding it up.

No problem, of course if a bug is reported I'll try to fix it or if I 
can't it's OK to remove it again. I just hope it gets more testing and 
maybe others could contribute fixes if it's in the main line.

>>>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>>>
>>> I'd like to invite you to create a Sam460ex MAINTAINERS stanza, add
>>> yourself, and add hw/ide/sii3112.c to that stanza.
>>
>> OK, I'll send a patch for that. David, is it enough to add sii3112 for
>> now and leave the others under PPC? I'd get cc as main contributor for
>> them anyway I think.
>>
>>> --js
>>>
>>>> ---
>>>>  hw/ide/Makefile.objs |   1 +
>>>>  hw/ide/sii3112.c     | 369
>>>> +++++++++++++++++++++++++++++++++++++++++++++++++++
>>>>  2 files changed, 370 insertions(+)
>>>>  create mode 100644 hw/ide/sii3112.c
>>>>
>>>> diff --git a/hw/ide/Makefile.objs b/hw/ide/Makefile.objs
>>>> index 729e9bd..76f3d6d 100644
>>>> --- a/hw/ide/Makefile.objs
>>>> +++ b/hw/ide/Makefile.objs
>>>> @@ -10,3 +10,4 @@ common-obj-$(CONFIG_IDE_VIA) += via.o
>>>>  common-obj-$(CONFIG_MICRODRIVE) += microdrive.o
>>>>  common-obj-$(CONFIG_AHCI) += ahci.o
>>>>  common-obj-$(CONFIG_AHCI) += ich.o
>>>> +common-obj-$(CONFIG_IDE_SII3112) += sii3112.o
>>>> diff --git a/hw/ide/sii3112.c b/hw/ide/sii3112.c
>>>> new file mode 100644
>>>> index 0000000..9ec8cd1
>>>> --- /dev/null
>>>> +++ b/hw/ide/sii3112.c
>>>> @@ -0,0 +1,369 @@
>>>> +/*
>>>> + * QEMU SiI3112A PCI to Serial ATA Controller Emulation
>>>> + *
>>>> + * Copyright (C) 2017 BALATON Zoltan <balaton@eik.bme.hu>
>>>> + *
>>>> + * This work is licensed under the terms of the GNU GPL, version 2
>>>> or later.
>>>> + * See the COPYING file in the top-level directory.
>>>> + *
>>>> + */
>>>> +
>>>> +/* For documentation on this and similar cards see:
>>>> + * http://wiki.osdev.org/User:Quok/Silicon_Image_Datasheets
>>>> + */
>>>
>>> Thank you so much for including docs!
>>
>> Thank David who asked for it in the RFC review. :-)
>>
>>>> +
>>>> +#include <qemu/osdep.h>
>>>> +#include <hw/ide/pci.h>
>>>> +
>>>> +#ifdef DEBUG_IDE
>>>> +#define DPRINTF(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__);
>>>> +#else
>>>> +#define DPRINTF(fmt, ...)
>>>> +#endif /* DEBUG */
>>>> +
>>>
>>> Please use trace events instead of DPRINTF; I'm in the process of
>>> removing them from the rest of IDE.
>>
>> OK. I found working with DPRINTF easier but I'll convert this to trace
>> then.
>>
>
> yeah, they're easier to implement but they're more prone to bitrot, and
> harder to control with any finesse, so they're coming out for 2.11.
>
>>>> +#define TYPE_SII3112_PCI "sii3112"
>>>> +#define SII3112_PCI(obj) OBJECT_CHECK(SiI3112PCIState, (obj), \
>>>> +                         TYPE_SII3112_PCI)
>>>> +
>>>> +typedef struct SiI3112Regs {
>>>> +    uint32_t confstat;
>>>> +    uint32_t scontrol;
>>>> +    uint16_t sien;
>>>> +    uint8_t swdata;
>>>> +} SiI3112Regs;
>>>> +
>>>> +typedef struct SiI3112PCIState {
>>>> +    PCIIDEState i;
>>>> +    MemoryRegion mmio;
>>>> +    SiI3112Regs regs[2];
>>>> +} SiI3112PCIState;
>>>> +
>>>> +static uint64_t sii3112_reg_read(void *opaque, hwaddr addr,
>>>> +                                unsigned int size)
>>>> +{
>>>> +    SiI3112PCIState *d = opaque;
>>>> +    uint64_t val = 0;
>>>> +
>>>> +    switch (addr) {
>>>> +    case 0x00:
>>>> +        val = d->i.bmdma[0].cmd;
>>>> +        break;
>>>> +    case 0x01:
>>>> +        val = d->regs[0].swdata;
>>>> +        break;
>>>> +    case 0x02:
>>>> +        val = d->i.bmdma[0].status;
>>>> +        break;
>>>> +    case 0x03:
>>>> +        val = 0;
>>>> +        break;
>>>> +    case 0x04 ... 0x07:
>>>> +        val = bmdma_addr_ioport_ops.read(&d->i.bmdma[0], addr - 4,
>>>> size);
>>>> +        break;
>>>> +    case 0x08:
>>>> +        val = d->i.bmdma[1].cmd;
>>>> +        break;
>>>> +    case 0x09:
>>>> +        val = d->regs[1].swdata;
>>>> +        break;
>>>> +    case 0x0a:
>>>> +        val = d->i.bmdma[1].status;
>>>> +        break;
>>>> +    case 0x0b:
>>>> +        val = 0;
>>>> +        break;
>>>> +    case 0x0c ... 0x0f:
>>>> +        val = bmdma_addr_ioport_ops.read(&d->i.bmdma[1], addr - 12,
>>>> size);
>>>> +        break;
>>>> +    case 0x10:
>>>> +        val = d->i.bmdma[0].cmd;
>>>> +        val |= (d->regs[0].confstat & (1UL << 11) ? (1 << 4) : 0);
>>>> /*SATAINT0*/
>>>> +        val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 6) : 0);
>>>> /*SATAINT1*/
>>>> +        val |= (d->i.bmdma[1].status & BM_STATUS_INT ? (1 << 14) : 0);
>>>> +        val |= d->i.bmdma[0].status << 16;
>>>> +        val |= d->i.bmdma[1].status << 24;
>>>> +        break;
>>>> +    case 0x18:
>>>> +        val = d->i.bmdma[1].cmd;
>>>> +        val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 4) : 0);
>>>> +        val |= d->i.bmdma[1].status << 16;
>>>> +        break;
>>>> +    case 0x80 ... 0x87:
>>>> +        if (size == 1) {
>>>> +            val = ide_ioport_read(&d->i.bus[0], addr - 0x80);
>>>> +        } else if (addr == 0x80) {
>>>> +            val = (size == 2) ? ide_data_readw(&d->i.bus[0], 0) :
>>>> +                                ide_data_readl(&d->i.bus[0], 0);
>>>> +        } else {
>>>> +            val = (1ULL << (size * 8)) - 1;
>>>> +        }
>>>> +        break;
>>>> +    case 0x8a:
>>>> +        val = (size == 1) ? ide_status_read(&d->i.bus[0], 4) :
>>>> +                            (1ULL << (size * 8)) - 1;
>>>> +        break;
>>>> +    case 0xa0:
>>>> +        val = d->regs[0].confstat;
>>>> +        break;
>>>> +    case 0xc0 ... 0xc7:
>>>> +        if (size == 1) {
>>>> +            val = ide_ioport_read(&d->i.bus[1], addr - 0xc0);
>>>> +        } else if (addr == 0xc0) {
>>>> +            val = (size == 2) ? ide_data_readw(&d->i.bus[1], 0) :
>>>> +                                ide_data_readl(&d->i.bus[1], 0);
>>>> +        } else {
>>>> +            val = (1ULL << (size * 8)) - 1;
>>>> +        }
>>>> +        break;
>>>> +    case 0xca:
>>>> +        val = (size == 1) ? ide_status_read(&d->i.bus[0], 4) :
>>>> +                            (1ULL << (size * 8)) - 1;
>>>> +        break;
>>>> +    case 0xe0:
>>>> +        val = d->regs[1].confstat;
>>>> +        break;
>>>> +    case 0x100:
>>>> +        val = d->regs[0].scontrol;
>>>> +        break;
>>>> +    case 0x104:
>>>> +        val = (d->i.bus[0].ifs[0].blk) ? 0x113 : 0;
>>>> +        break;
>>>> +    case 0x148:
>>>> +        val = d->regs[0].sien << 16;
>>>> +        break;
>>>> +    case 0x180:
>>>> +        val = d->regs[1].scontrol;
>>>> +        break;
>>>> +    case 0x184:
>>>> +        val = (d->i.bus[1].ifs[0].blk) ? 0x113 : 0;
>>>> +        break;
>>>> +    case 0x1c8:
>>>> +        val = d->regs[1].sien << 16;
>>>> +        break;
>>>> +    default:
>>>> +        val = 0;
>>>> +    }
>>>> +    DPRINTF("%s: addr 0x%"PRIx64 " size %d = %"PRIx64 "\n",
>>>> +            __func__, addr, size, val);
>>>> +    return val;
>>>> +}
>>>> +
>>>> +static void sii3112_reg_write(void *opaque, hwaddr addr,
>>>> +                              uint64_t val, unsigned int size)
>>>> +{
>>>> +    SiI3112PCIState *d = opaque;
>>>> +
>>>> +    DPRINTF("%s: addr 0x%"PRIx64 " size %d = %"PRIx64 "\n",
>>>> +            __func__, addr, size, val);
>>>> +    switch (addr) {
>>>> +    case 0x00:
>>>> +    case 0x10:
>>>> +        bmdma_cmd_writeb(&d->i.bmdma[0], val);
>>>> +        break;
>>>> +    case 0x01:
>>>> +    case 0x11:
>>>> +        d->regs[0].swdata = val & 0x3f;
>>>> +        break;
>>>> +    case 0x02:
>>>> +    case 0x12:
>>>> +        d->i.bmdma[0].status = (val & 0x60) | (d->i.bmdma[0].status
>>>> & 1) |
>>>> +                               (d->i.bmdma[0].status & ~val & 6);
>>>> +        break;
>>>> +    case 0x04 ... 0x07:
>>>> +        bmdma_addr_ioport_ops.write(&d->i.bmdma[0], addr - 4, val,
>>>> size);
>>>> +        break;
>>>> +    case 0x08:
>>>> +    case 0x18:
>>>> +        bmdma_cmd_writeb(&d->i.bmdma[1], val);
>>>> +        break;
>>>> +    case 0x09:
>>>> +    case 0x19:
>>>> +        d->regs[1].swdata = val & 0x3f;
>>>> +        break;
>>>> +    case 0x0a:
>>>> +    case 0x1a:
>>>> +        d->i.bmdma[1].status = (val & 0x60) | (d->i.bmdma[1].status
>>>> & 1) |
>>>> +                               (d->i.bmdma[1].status & ~val & 6);
>>>> +        break;
>>>> +    case 0x0c ... 0x0f:
>>>> +        bmdma_addr_ioport_ops.write(&d->i.bmdma[1], addr - 12, val,
>>>> size);
>>>> +        break;
>>>
>>>
>>> What register(s) sit at [0x10 - 0x1a]?
>>> Isn't BAR4 only 0x00 through 0x0F?
>>>
>>>
>>>> +    case 0x80 ... 0x87:
>>>> +        if (size == 1) {
>>>> +            ide_ioport_write(&d->i.bus[0], addr - 0x80, val);
>>>> +        } else if (addr == 0x80) {
>>>> +            if (size == 2) {
>>>> +                ide_data_writew(&d->i.bus[0], 0, val);
>>>> +            } else {
>>>> +                ide_data_writel(&d->i.bus[0], 0, val);
>>>> +            }
>>>> +        }
>>>> +        break;
>>>> +    case 0x8a:
>>>> +        if (size == 1) {
>>>> +            ide_cmd_write(&d->i.bus[0], 4, val);
>>>> +        }
>>>> +        break;
>>>
>>> IDE0 stuff.
>>>
>>>> +    case 0xc0 ... 0xc7:
>>>> +        if (size == 1) {
>>>> +            ide_ioport_write(&d->i.bus[1], addr - 0xc0, val);
>>>> +        } else if (addr == 0xc0) {
>>>> +            if (size == 2) {
>>>> +                ide_data_writew(&d->i.bus[1], 0, val);
>>>> +            } else {
>>>> +                ide_data_writel(&d->i.bus[1], 0, val);
>>>> +            }
>>>> +        }
>>>> +        break;
>>>> +    case 0xca:
>>>> +        if (size == 1) {
>>>> +            ide_cmd_write(&d->i.bus[1], 4, val);
>>>> +        }
>>>> +        break;
>>>
>>> IDE1 stuff.
>>>
>>>> +    case 0x100:
>>>> +        d->regs[0].scontrol = val & 0xfff;
>>>> +        if (val & 1) {
>>>> +            ide_bus_reset(&d->i.bus[0]);
>>>> +        }
>>>> +        break;
>>>> +    case 0x148:
>>>> +        d->regs[0].sien = (val >> 16) & 0x3eed;
>>>> +        break;
>>>> +    case 0x180:
>>>> +        d->regs[1].scontrol = val & 0xfff;
>>>> +        if (val & 1) {
>>>> +            ide_bus_reset(&d->i.bus[1]);
>>>> +        }
>>>> +        break;
>>>> +    case 0x1c8:
>>>> +        d->regs[1].sien = (val >> 16) & 0x3eed;
>>>> +        break;
>>>
>>> Not sure what these ones are.
>>
>> These are some SATA specific registers mostly controlling features we
>> don't emulate (such as power management, SATA standard level and also
>> used to reset the connected drive which is the only thing emulated
>> because drivers use this). 0x100 and 0x148 are for channel 0 the other
>> two are corresponding registers for channel 1.
>>
>>>> +    default:
>>>> +        val = 0;
>>>> +    }
>>>> +}
>>>> +
>>>> +static const MemoryRegionOps sii3112_reg_ops = {
>>>> +    .read = sii3112_reg_read,
>>>> +    .write = sii3112_reg_write,
>>>> +    .endianness = DEVICE_LITTLE_ENDIAN,
>>>> +};
>>>> +
>>>> +/* the PCI irq level is the logical OR of the two channels */
>>>> +static void sii3112_update_irq(SiI3112PCIState *s)
>>>> +{
>>>> +    int i, set = 0;
>>>> +
>>>> +    for (i = 0; i < 2; i++) {
>>>> +        set |= s->regs[i].confstat & (1UL << 11);
>>>> +    }
>>>> +    pci_set_irq(PCI_DEVICE(s), (set ? 1 : 0));
>>>> +}
>>>> +
>>>> +static void sii3112_set_irq(void *opaque, int channel, int level)
>>>> +{
>>>> +    SiI3112PCIState *s = opaque;
>>>> +
>>>> +    DPRINTF("%s: channel %d level %d\n", __func__, channel, level);
>>>> +    if (level) {
>>>> +        s->regs[channel].confstat |= (1UL << 11);
>>>> +    } else {
>>>> +        s->regs[channel].confstat &= ~(1UL << 11);
>>>> +    }
>>>> +
>>>> +    sii3112_update_irq(s);
>>>> +}
>>>> +
>>>> +static void sii3112_reset(void *opaque)
>>>> +{
>>>> +    SiI3112PCIState *s = opaque;
>>>> +    int i;
>>>> +
>>>> +    for (i = 0; i < 2; i++) {
>>>> +        s->regs[i].confstat = 0x6515 << 16;
>>>> +        ide_bus_reset(&s->i.bus[i]);
>>>> +    }
>>>> +}
>>>> +
>>>> +static void sii3112_pci_realize(PCIDevice *dev, Error **errp)
>>>> +{
>>>> +    SiI3112PCIState *d = SII3112_PCI(dev);
>>>> +    PCIIDEState *s = PCI_IDE(dev);
>>>> +    MemoryRegion *mr;
>>>> +    qemu_irq *irq;
>>>> +    int i;
>>>> +
>>>> +    pci_config_set_interrupt_pin(dev->config, 1);
>>>> +    pci_set_byte(dev->config + PCI_CACHE_LINE_SIZE, 8);
>>>> +
>>>> +    memory_region_init_io(&d->mmio, OBJECT(d), &sii3112_reg_ops, d,
>>>> +                         "sii3112.bar5", 0x200);
>>>> +    pci_register_bar(dev, 5, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
>>>> +
>>>> +    mr = g_new(MemoryRegion, 1);
>>>> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar0",
>>>> &d->mmio, 0x80, 8);
>>>> +    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, mr);
>>>> +    mr = g_new(MemoryRegion, 1);
>>>> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar1",
>>>> &d->mmio, 0x88, 4);
>>>> +    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, mr);
>>>> +    mr = g_new(MemoryRegion, 1);
>>>
>>> BARS 0 and 1 for IDE0 occupy 0x80 through 0x8C;
>>>
>>>> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar2",
>>>> &d->mmio, 0xc0, 8);
>>>> +    pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, mr);
>>>> +    mr = g_new(MemoryRegion, 1);
>>>> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar3",
>>>> &d->mmio, 0xc8, 4);
>>>> +    pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_IO, mr);
>>>> +    mr = g_new(MemoryRegion, 1);
>>>
>>> BARS 1 and 2 for IDE1 occupy 0xC0 through 0xCC;
>>>
>>>> +    memory_region_init_alias(mr, OBJECT(d), "sii3112.bar4",
>>>> &d->mmio, 0, 16);
>>>> +    pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, mr);
>>>
>>> BAR4 at 0x00 through 0x0F which houses the BMDMA registers.
>>>
>>> What occupies 0x10 through 0x7F or 0x8D through 0x1FF?
>>
>> I'm not sure, there's a table in the datasheet that details this.
>> Basically everything is in BAR5 which is an mmio region and BAR0-4 are
>> io space aliases into this mmio region. (I think this is to support
>> accessing it both via mmio and io space or to make it similar to IDE to
>> make it easier to port older drivers.) Most of the empty areas are
>> documented as Reserved in the datasheet.
>>
>
> oh, I did actually miss that you register BAR5 as MMIO first, thanks,
> that clears this all up.
>
> So we've got BAR5 that occupies 0x200 bytes of PCI MMIO space and for which:
>
> [0x00 - 0x0F]: Duplicated as PCI I/O space via BAR4
> [0x80 - 0x87]: Duplicated as PCI I/O space via BAR0
> [0x88 - 0x8B]: Duplicated as PCI I/O space via BAR1
> [0xC0 - 0xC7]: Duplicated as PCI I/O space via BAR2
> [0xC8 - 0xCB]: Duplicated as PCI I/O space via BAR3

Correct.

> I might appreciate a comment somewhere near the read or write (or both)
> with a quick pointer to check out section 6.7 of the spec for a listing
> of the BAR5 offsets and meanings, with a brief mention of the
> dual-mapping for the registers in BAR0-4.

OK, I'll try to add some comments to clarify this.

> Oh, as a last question, does the dual-mapping here work correctly with
> respects to the offsets? I imagine the read/write functions get offsets
> into the region mapped (0x200) and not necessarily offsets into the
> region accessed (4, 8, 16 bytes etc) right?

It seems to work because the firmware's driver is using the aliased io 
regions and can talk to the device. Since the read write functions are 
only registered for the mmio BAR5 and the other BARs are just alias 
regions I think the memory region code in QEMU takes care of this.

>>>> +
>>>> +    irq = qemu_allocate_irqs(sii3112_set_irq, d, 2);
>>>> +    for (i = 0; i < 2; i++) {
>>>> +        ide_bus_new(&s->bus[i], sizeof(s->bus[i]), DEVICE(dev), i, 1);
>>>> +        ide_init2(&s->bus[i], irq[i]);
>>>> +
>>>> +        bmdma_init(&s->bus[i], &s->bmdma[i], s);
>>>> +        s->bmdma[i].bus = &s->bus[i];
>>>> +        ide_register_restart_cb(&s->bus[i]);
>>>> +    }
>>>> +    qemu_register_reset(sii3112_reset, s);
>>>> +}
>>>> +
>>>> +static void sii3112_pci_exitfn(PCIDevice *dev)
>>>> +{
>>>> +    PCIIDEState *d = PCI_IDE(dev);
>>>> +    int i;
>>>> +
>>>> +    for (i = 0; i < 2; ++i) {
>>>> +        memory_region_del_subregion(&d->bmdma_bar,
>>>> &d->bmdma[i].extra_io);
>>>> +        memory_region_del_subregion(&d->bmdma_bar,
>>>> &d->bmdma[i].addr_ioport);
>>>> +    }
>>>> +}
>>>> +
>>>> +static void sii3112_pci_class_init(ObjectClass *klass, void *data)
>>>> +{
>>>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>>>> +    PCIDeviceClass *pd = PCI_DEVICE_CLASS(klass);
>>>> +
>>>> +    pd->vendor_id = 0x1095;
>>>> +    pd->device_id = 0x3112;
>>>> +    pd->class_id = PCI_CLASS_STORAGE_RAID;
>>>> +    pd->revision = 1;
>>>> +    pd->realize = sii3112_pci_realize;
>>>> +    pd->exit = sii3112_pci_exitfn;
>>>> +    dc->desc = "SiI3112A SATA controller";
>>>> +    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>>>> +}
>>>> +
>>>> +static const TypeInfo sii3112_pci_info = {
>>>> +    .name = TYPE_SII3112_PCI,
>>>> +    .parent = TYPE_PCI_IDE,
>>>> +    .instance_size = sizeof(SiI3112PCIState),
>>>> +    .class_init = sii3112_pci_class_init,
>>>> +};
>>>> +
>>>> +static void sii3112_register_types(void)
>>>> +{
>>>> +    type_register_static(&sii3112_pci_info);
>>>> +}
>>>> +
>>>> +type_init(sii3112_register_types)
>>>>
>>>
>>>
>
>

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 09/15] hw/ide: Emulate SiI3112 SATA controller
  2017-08-22 20:15         ` BALATON Zoltan
@ 2017-08-22 20:21           ` John Snow
  2017-08-22 21:54             ` BALATON Zoltan
  0 siblings, 1 reply; 66+ messages in thread
From: John Snow @ 2017-08-22 20:21 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: qemu-devel, qemu-ppc, Francois Revol, Alexander Graf,
	David Gibson, Peter Maydell



On 08/22/2017 04:15 PM, BALATON Zoltan wrote:
> On Tue, 22 Aug 2017, John Snow wrote:
>> On 08/22/2017 07:08 AM, BALATON Zoltan wrote:
>>> On Mon, 21 Aug 2017, John Snow wrote:
>>
>> Sure, but be advised that if the device causes problems outside of this
>> use case and there's nobody willing or able to review it, that it may
>> get removed again.
>>
>> I don't have a lot of free time to go through the register list point by
>> point and make sure this is implemented correctly either, but if this
>> helps your work I'm OK not holding it up.
> 
> No problem, of course if a bug is reported I'll try to fix it or if I
> can't it's OK to remove it again. I just hope it gets more testing and
> maybe others could contribute fixes if it's in the main line.
> 

Yep, just a "warning"!

Thanks, it looks sane enough to me in general, If you have instructions
for installing and testing a machine using this advice I'd like to check
it out later this week and I'll sign off on the re-spin.

(As a side-note; do we offer hardware support lists as part of canonical
QEMU releases? It would be nice to annotate this device as something
that is "experimental" instead of "supported" such that it would reflect
its work-in-progress nature. I keep asking about this every now and
again, but with the recent deprecations and removals from QEMU perhaps
it's time to ask again if we can start codifying things down to the
exact device...)

--js

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 09/15] hw/ide: Emulate SiI3112 SATA controller
  2017-08-22 20:21           ` John Snow
@ 2017-08-22 21:54             ` BALATON Zoltan
  0 siblings, 0 replies; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-22 21:54 UTC (permalink / raw)
  To: John Snow
  Cc: qemu-devel, qemu-ppc, Francois Revol, Alexander Graf,
	David Gibson, Peter Maydell

On Tue, 22 Aug 2017, John Snow wrote:
> On 08/22/2017 04:15 PM, BALATON Zoltan wrote:
>> On Tue, 22 Aug 2017, John Snow wrote:
>>> On 08/22/2017 07:08 AM, BALATON Zoltan wrote:
>>>> On Mon, 21 Aug 2017, John Snow wrote:
>>>
>>> Sure, but be advised that if the device causes problems outside of this
>>> use case and there's nobody willing or able to review it, that it may
>>> get removed again.
>>>
>>> I don't have a lot of free time to go through the register list point by
>>> point and make sure this is implemented correctly either, but if this
>>> helps your work I'm OK not holding it up.
>>
>> No problem, of course if a bug is reported I'll try to fix it or if I
>> can't it's OK to remove it again. I just hope it gets more testing and
>> maybe others could contribute fixes if it's in the main line.
>>
>
> Yep, just a "warning"!
>
> Thanks, it looks sane enough to me in general, If you have instructions
> for installing and testing a machine using this advice I'd like to check
> it out later this week and I'll sign off on the re-spin.

I'll probably won't have time to send an updated version before the end of 
the week but since the modifications requested are about DPRINTFs and 
comments (nothing changing functionality) at this point, you could test 
this version if you'll have time.

Since this card is a generic PCI device and not specific to the machine my 
series aims to emulate, I think it could be tested alone in any other 
machine such as pc or some other emulated machine. Linux has a driver 
(sata_sil I think) and a lot of other OSes too so if you can try adding 
this device with an ide-hd and an ide-cd and install any of these OSes 
this could verify if it's working or could uncover some bugs. I don't know 
a better test now because of the bugs in the Sam460ex that prevents it 
from working reliably at the moment.

Thank you for your support.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 10/15] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 10/15] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs BALATON Zoltan
  2017-08-20 22:20   ` Philippe Mathieu-Daudé
@ 2017-08-23  0:49   ` David Gibson
  1 sibling, 0 replies; 66+ messages in thread
From: David Gibson @ 2017-08-23  0:49 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 18255 bytes --]

On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
> This is the PCIX controller found in newer 440 core SoCs e.g. the AMMC
> 460EX. The device tree refers to this as plb-pcix compared to the
> plb-pci controller in older 440 SoCs.
> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>

So I don't have the time to read the manuals to give this a detailed
review.  But since you're replacing nothing at all, it kind of doesn't
matter if it's pretty broken, it's still an improvement.  I didn't see
anything blatantly bogus, so:

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

> ---
>  hw/ppc/Makefile.objs |   2 +-
>  hw/ppc/ppc440_pcix.c | 516 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 517 insertions(+), 1 deletion(-)
>  create mode 100644 hw/ppc/ppc440_pcix.c
> 
> diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
> index 7efc686..fc39fe4 100644
> --- a/hw/ppc/Makefile.objs
> +++ b/hw/ppc/Makefile.objs
> @@ -13,7 +13,7 @@ endif
>  obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o
>  # PowerPC 4xx boards
>  obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
> -obj-y += ppc4xx_pci.o
> +obj-y += ppc4xx_pci.o ppc440_pcix.o
>  # PReP
>  obj-$(CONFIG_PREP) += prep.o
>  obj-$(CONFIG_PREP) += prep_systemio.o
> diff --git a/hw/ppc/ppc440_pcix.c b/hw/ppc/ppc440_pcix.c
> new file mode 100644
> index 0000000..5c2ceec
> --- /dev/null
> +++ b/hw/ppc/ppc440_pcix.c
> @@ -0,0 +1,516 @@
> +/*
> + * Emulation of the ibm,plb-pcix PCI controller
> + * This is found in some 440 SoCs e.g. the 460EX.
> + *
> + * Copyright (c) 2016 BALATON Zoltan
> + *
> + * Derived from ppc4xx_pci.c and pci-host/ppce500.c
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License, version 2, as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/error-report.h"
> +#include "hw/hw.h"
> +#include "hw/ppc/ppc.h"
> +#include "hw/ppc/ppc4xx.h"
> +#include "hw/pci/pci.h"
> +#include "hw/pci/pci_host.h"
> +#include "exec/address-spaces.h"
> +
> +/*#define DEBUG_PCI*/
> +
> +#ifdef DEBUG_PCI
> +#define DPRINTF(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__);
> +#else
> +#define DPRINTF(fmt, ...)
> +#endif /* DEBUG */
> +
> +struct PLBOutMap {
> +    uint64_t la;
> +    uint64_t pcia;
> +    uint32_t sa;
> +    MemoryRegion mr;
> +};
> +
> +struct PLBInMap {
> +    uint64_t sa;
> +    uint64_t la;
> +    MemoryRegion mr;
> +};
> +
> +#define TYPE_PPC440_PCIX_HOST_BRIDGE "ppc440-pcix-host"
> +#define PPC440_PCIX_HOST_BRIDGE(obj) \
> +    OBJECT_CHECK(PPC440PCIXState, (obj), TYPE_PPC440_PCIX_HOST_BRIDGE)
> +
> +#define PPC440_PCIX_NR_POMS 3
> +#define PPC440_PCIX_NR_PIMS 3
> +
> +typedef struct PPC440PCIXState {
> +    PCIHostState parent_obj;
> +
> +    PCIDevice *dev;
> +    struct PLBOutMap pom[PPC440_PCIX_NR_POMS];
> +    struct PLBInMap pim[PPC440_PCIX_NR_PIMS];
> +    uint32_t sts;
> +    qemu_irq irq[PCI_NUM_PINS];
> +    AddressSpace bm_as;
> +    MemoryRegion bm;
> +
> +    MemoryRegion container;
> +    MemoryRegion iomem;
> +    MemoryRegion busmem;
> +} PPC440PCIXState;
> +
> +#define PPC440_REG_BASE     0x80000
> +#define PPC440_REG_SIZE     0xff
> +
> +#define PCIC0_CFGADDR       0x0
> +#define PCIC0_CFGDATA       0x4
> +
> +#define PCIX0_POM0LAL       0x68
> +#define PCIX0_POM0LAH       0x6c
> +#define PCIX0_POM0SA        0x70
> +#define PCIX0_POM0PCIAL     0x74
> +#define PCIX0_POM0PCIAH     0x78
> +#define PCIX0_POM1LAL       0x7c
> +#define PCIX0_POM1LAH       0x80
> +#define PCIX0_POM1SA        0x84
> +#define PCIX0_POM1PCIAL     0x88
> +#define PCIX0_POM1PCIAH     0x8c
> +#define PCIX0_POM2SA        0x90
> +
> +#define PCIX0_PIM0SAL       0x98
> +#define PCIX0_PIM0LAL       0x9c
> +#define PCIX0_PIM0LAH       0xa0
> +#define PCIX0_PIM1SA        0xa4
> +#define PCIX0_PIM1LAL       0xa8
> +#define PCIX0_PIM1LAH       0xac
> +#define PCIX0_PIM2SAL       0xb0
> +#define PCIX0_PIM2LAL       0xb4
> +#define PCIX0_PIM2LAH       0xb8
> +#define PCIX0_PIM0SAH       0xf8
> +#define PCIX0_PIM2SAH       0xfc
> +
> +#define PCIX0_STS           0xe0
> +
> +#define PCI_ALL_SIZE        (PPC440_REG_BASE + PPC440_REG_SIZE)
> +
> +static void ppc440_pcix_clear_region(MemoryRegion *parent,
> +                                     MemoryRegion *mem)
> +{
> +    if (memory_region_is_mapped(mem)) {
> +        memory_region_del_subregion(parent, mem);
> +        object_unparent(OBJECT(mem));
> +    }
> +}
> +
> +/* DMA mapping */
> +static void ppc440_pcix_update_pim(PPC440PCIXState *s, int idx)
> +{
> +    MemoryRegion *mem = &s->pim[idx].mr;
> +    char *name;
> +    uint64_t size;
> +
> +    /* Before we modify anything, unmap and destroy the region */
> +    ppc440_pcix_clear_region(&s->bm, mem);
> +
> +    if (!(s->pim[idx].sa & 1)) {
> +        /* Not enabled, nothing to do */
> +        return;
> +    }
> +
> +    name = g_strdup_printf("PCI Inbound Window %d", idx);
> +    size = ~(s->pim[idx].sa & ~7ULL) + 1;
> +    memory_region_init_alias(mem, OBJECT(s), name, get_system_memory(),
> +                             s->pim[idx].la, size);
> +    memory_region_add_subregion_overlap(&s->bm, 0, mem, -1);
> +    g_free(name);
> +
> +    DPRINTF("%s: Added window %d of size=%#"PRIx64" to CPU=%#"PRIx64"\n",
> +            __func__, idx, size, s->pim[idx].la);
> +}
> +
> +/* BAR mapping */
> +static void ppc440_pcix_update_pom(PPC440PCIXState *s, int idx)
> +{
> +    MemoryRegion *mem = &s->pom[idx].mr;
> +    MemoryRegion *address_space_mem = get_system_memory();
> +    char *name;
> +    uint32_t size;
> +
> +    /* Before we modify anything, unmap and destroy the region */
> +    ppc440_pcix_clear_region(address_space_mem, mem);
> +
> +    if (!(s->pom[idx].sa & 1)) {
> +        /* Not enabled, nothing to do */
> +        return;
> +    }
> +
> +    name = g_strdup_printf("PCI Outbound Window %d", idx);
> +    size = ~(s->pom[idx].sa & 0xfffffffe) + 1;
> +    if (!size) {
> +        size = 0xffffffff;
> +    }
> +    memory_region_init_alias(mem, OBJECT(s), name, &s->busmem,
> +                             s->pom[idx].pcia, size);
> +    memory_region_add_subregion(address_space_mem, s->pom[idx].la, mem);
> +    g_free(name);
> +
> +    DPRINTF("%s: Added window %d of size=%#x from CPU=%#"PRIx64
> +            " to PCI=%#"PRIx64"\n", __func__, idx, size, s->pom[idx].la,
> +            s->pom[idx].pcia);
> +}
> +
> +static void ppc440_pcix_reg_write4(void *opaque, hwaddr addr,
> +                                   uint64_t val, unsigned size)
> +{
> +    struct PPC440PCIXState *s = opaque;
> +
> +    DPRINTF("%s: addr 0x%"PRIx64 " = %"PRIx64 "\n", __func__, addr, val);
> +    switch (addr) {
> +    case PCI_VENDOR_ID ... PCI_MAX_LAT:
> +        stl_le_p(s->dev->config + addr, val);
> +        break;
> +
> +    case PCIX0_POM0LAL:
> +        s->pom[0].la &= 0xffffffff00000000ULL;
> +        s->pom[0].la |= val;
> +        ppc440_pcix_update_pom(s, 0);
> +        break;
> +    case PCIX0_POM0LAH:
> +        s->pom[0].la &= 0xffffffffULL;
> +        s->pom[0].la |= val << 32;
> +        ppc440_pcix_update_pom(s, 0);
> +        break;
> +    case PCIX0_POM0SA:
> +        s->pom[0].sa = val;
> +        ppc440_pcix_update_pom(s, 0);
> +        break;
> +    case PCIX0_POM0PCIAL:
> +        s->pom[0].pcia &= 0xffffffff00000000ULL;
> +        s->pom[0].pcia |= val;
> +        ppc440_pcix_update_pom(s, 0);
> +        break;
> +    case PCIX0_POM0PCIAH:
> +        s->pom[0].pcia &= 0xffffffffULL;
> +        s->pom[0].pcia |= val << 32;
> +        ppc440_pcix_update_pom(s, 0);
> +        break;
> +    case PCIX0_POM1LAL:
> +        s->pom[1].la &= 0xffffffff00000000ULL;
> +        s->pom[1].la |= val;
> +        ppc440_pcix_update_pom(s, 1);
> +        break;
> +    case PCIX0_POM1LAH:
> +        s->pom[1].la &= 0xffffffffULL;
> +        s->pom[1].la |= val << 32;
> +        ppc440_pcix_update_pom(s, 1);
> +        break;
> +    case PCIX0_POM1SA:
> +        s->pom[1].sa = val;
> +        ppc440_pcix_update_pom(s, 1);
> +        break;
> +    case PCIX0_POM1PCIAL:
> +        s->pom[1].pcia &= 0xffffffff00000000ULL;
> +        s->pom[1].pcia |= val;
> +        ppc440_pcix_update_pom(s, 1);
> +        break;
> +    case PCIX0_POM1PCIAH:
> +        s->pom[1].pcia &= 0xffffffffULL;
> +        s->pom[1].pcia |= val << 32;
> +        ppc440_pcix_update_pom(s, 1);
> +        break;
> +    case PCIX0_POM2SA:
> +        s->pom[2].sa = val;
> +        break;
> +
> +    case PCIX0_PIM0SAL:
> +        s->pim[0].sa &= 0xffffffff00000000ULL;
> +        s->pim[0].sa |= val;
> +        ppc440_pcix_update_pim(s, 0);
> +        break;
> +    case PCIX0_PIM0LAL:
> +        s->pim[0].la &= 0xffffffff00000000ULL;
> +        s->pim[0].la |= val;
> +        ppc440_pcix_update_pim(s, 0);
> +        break;
> +    case PCIX0_PIM0LAH:
> +        s->pim[0].la &= 0xffffffffULL;
> +        s->pim[0].la |= val << 32;
> +        ppc440_pcix_update_pim(s, 0);
> +        break;
> +    case PCIX0_PIM1SA:
> +        s->pim[1].sa = val;
> +        ppc440_pcix_update_pim(s, 1);
> +        break;
> +    case PCIX0_PIM1LAL:
> +        s->pim[1].la &= 0xffffffff00000000ULL;
> +        s->pim[1].la |= val;
> +        ppc440_pcix_update_pim(s, 1);
> +        break;
> +    case PCIX0_PIM1LAH:
> +        s->pim[1].la &= 0xffffffffULL;
> +        s->pim[1].la |= val << 32;
> +        ppc440_pcix_update_pim(s, 1);
> +        break;
> +    case PCIX0_PIM2SAL:
> +        s->pim[2].sa &= 0xffffffff00000000ULL;
> +        s->pim[2].sa = val;
> +        ppc440_pcix_update_pim(s, 2);
> +        break;
> +    case PCIX0_PIM2LAL:
> +        s->pim[2].la &= 0xffffffff00000000ULL;
> +        s->pim[2].la |= val;
> +        ppc440_pcix_update_pim(s, 2);
> +        break;
> +    case PCIX0_PIM2LAH:
> +        s->pim[2].la &= 0xffffffffULL;
> +        s->pim[2].la |= val << 32;
> +        ppc440_pcix_update_pim(s, 2);
> +        break;
> +
> +    case PCIX0_STS:
> +        s->sts = val;
> +        break;
> +
> +    case PCIX0_PIM0SAH:
> +        s->pim[0].sa &= 0xffffffffULL;
> +        s->pim[0].sa |= val << 32;
> +        ppc440_pcix_update_pim(s, 0);
> +        break;
> +    case PCIX0_PIM2SAH:
> +        s->pim[2].sa &= 0xffffffffULL;
> +        s->pim[2].sa |= val << 32;
> +        ppc440_pcix_update_pim(s, 2);
> +        break;
> +
> +    default:
> +        printf("%s: unhandled PCI internal register 0x%lx\n", __func__,
> +               (unsigned long)addr);
> +        break;
> +    }
> +}
> +
> +static uint64_t ppc440_pcix_reg_read4(void *opaque, hwaddr addr,
> +                                     unsigned size)
> +{
> +    struct PPC440PCIXState *s = opaque;
> +    uint32_t val;
> +
> +    switch (addr) {
> +    case PCI_VENDOR_ID ... PCI_MAX_LAT:
> +        val = ldl_le_p(s->dev->config + addr);
> +        break;
> +
> +    case PCIX0_POM0LAL:
> +        val = s->pom[0].la;
> +        break;
> +    case PCIX0_POM0LAH:
> +        val = s->pom[0].la >> 32;
> +        break;
> +    case PCIX0_POM0SA:
> +        val = s->pom[0].sa;
> +        break;
> +    case PCIX0_POM0PCIAL:
> +        val = s->pom[0].pcia;
> +        break;
> +    case PCIX0_POM0PCIAH:
> +        val = s->pom[0].pcia >> 32;
> +        break;
> +    case PCIX0_POM1LAL:
> +        val = s->pom[1].la;
> +        break;
> +    case PCIX0_POM1LAH:
> +        val = s->pom[1].la >> 32;
> +        break;
> +    case PCIX0_POM1SA:
> +        val = s->pom[1].sa;
> +        break;
> +    case PCIX0_POM1PCIAL:
> +        val = s->pom[1].pcia;
> +        break;
> +    case PCIX0_POM1PCIAH:
> +        val = s->pom[1].pcia >> 32;
> +        break;
> +    case PCIX0_POM2SA:
> +        val = s->pom[2].sa;
> +        break;
> +
> +    case PCIX0_PIM0SAL:
> +        val = s->pim[0].sa;
> +        break;
> +    case PCIX0_PIM0LAL:
> +        val = s->pim[0].la;
> +        break;
> +    case PCIX0_PIM0LAH:
> +        val = s->pim[0].la >> 32;
> +        break;
> +    case PCIX0_PIM1SA:
> +        val = s->pim[1].sa;
> +        break;
> +    case PCIX0_PIM1LAL:
> +        val = s->pim[1].la;
> +        break;
> +    case PCIX0_PIM1LAH:
> +        val = s->pim[1].la >> 32;
> +        break;
> +    case PCIX0_PIM2SAL:
> +        val = s->pim[2].sa;
> +        break;
> +    case PCIX0_PIM2LAL:
> +        val = s->pim[2].la;
> +        break;
> +    case PCIX0_PIM2LAH:
> +        val = s->pim[2].la >> 32;
> +        break;
> +
> +    case PCIX0_STS:
> +        val = s->sts;
> +        break;
> +
> +    case PCIX0_PIM0SAH:
> +        val = s->pim[0].sa  >> 32;
> +        break;
> +    case PCIX0_PIM2SAH:
> +        val = s->pim[2].sa  >> 32;
> +        break;
> +
> +    default:
> +        printf("%s: invalid PCI internal register 0x%lx\n", __func__,
> +               (unsigned long)addr);
> +        val = 0;
> +    }
> +
> +    DPRINTF("%s: addr 0x%"PRIx64 " = %"PRIx32 "\n", __func__, addr, val);
> +    return val;
> +}
> +
> +static const MemoryRegionOps pci_reg_ops = {
> +    .read = ppc440_pcix_reg_read4,
> +    .write = ppc440_pcix_reg_write4,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +};
> +
> +static void ppc440_pcix_reset(DeviceState *dev)
> +{
> +    struct PPC440PCIXState *s = PPC440_PCIX_HOST_BRIDGE(dev);
> +    int i;
> +
> +    for (i = 0; i < PPC440_PCIX_NR_POMS; i++) {
> +        ppc440_pcix_clear_region(get_system_memory(), &s->pom[i].mr);
> +    }
> +    for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) {
> +        ppc440_pcix_clear_region(&s->bm, &s->pim[i].mr);
> +    }
> +    memset(s->pom, 0, sizeof(s->pom));
> +    memset(s->pim, 0, sizeof(s->pim));
> +    for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) {
> +        s->pim[i].sa = 0xffffffff00000000ULL;
> +    }
> +    s->sts = 0;
> +}
> +
> +/* All pins from each slot are tied to a single board IRQ.
> + * This may need further refactoring for other boards. */
> +static int ppc440_pcix_map_irq(PCIDevice *pci_dev, int irq_num)
> +{
> +    int slot = pci_dev->devfn >> 3;
> +
> +    DPRINTF("%s: devfn %x irq %d -> %d\n", __func__,
> +            pci_dev->devfn, irq_num, slot);
> +
> +    return slot - 1;
> +}
> +
> +static void ppc440_pcix_set_irq(void *opaque, int irq_num, int level)
> +{
> +    qemu_irq *pci_irqs = opaque;
> +
> +    DPRINTF("%s: PCI irq %d\n", __func__, irq_num);
> +    if (irq_num < 0) {
> +        error_report("%s: PCI irq %d", __func__, irq_num);
> +        return;
> +    }
> +    qemu_set_irq(pci_irqs[irq_num], level);
> +}
> +
> +static AddressSpace *ppc440_pcix_set_iommu(PCIBus *b, void *opaque, int devfn)
> +{
> +    PPC440PCIXState *s = opaque;
> +
> +    return &s->bm_as;
> +}
> +
> +static int ppc440_pcix_initfn(SysBusDevice *dev)
> +{
> +    PPC440PCIXState *s;
> +    PCIHostState *h;
> +    int i;
> +
> +    h = PCI_HOST_BRIDGE(dev);
> +    s = PPC440_PCIX_HOST_BRIDGE(dev);
> +
> +    for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
> +        sysbus_init_irq(dev, &s->irq[i]);
> +    }
> +
> +    memory_region_init(&s->busmem, OBJECT(dev), "pci bus memory", UINT64_MAX);
> +    h->bus = pci_register_bus(DEVICE(dev), NULL, ppc440_pcix_set_irq,
> +                         ppc440_pcix_map_irq, s->irq, &s->busmem,
> +                         get_system_io(), PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
> +
> +    s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0), "ppc4xx-host-bridge");
> +
> +    memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX);
> +    memory_region_add_subregion(&s->bm, 0x0, &s->busmem);
> +    address_space_init(&s->bm_as, &s->bm, "pci-bm");
> +    pci_setup_iommu(h->bus, ppc440_pcix_set_iommu, s);
> +
> +    memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE);
> +    memory_region_init_io(&h->conf_mem, OBJECT(s), &pci_host_conf_le_ops, h,
> +                          "pci-conf-idx", 4);
> +    memory_region_init_io(&h->data_mem, OBJECT(s), &pci_host_data_le_ops, h,
> +                          "pci-conf-data", 4);
> +    memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s,
> +                          "pci.reg", PPC440_REG_SIZE);
> +    memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem);
> +    memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem);
> +    memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->iomem);
> +    sysbus_init_mmio(dev, &s->container);
> +
> +    return 0;
> +}
> +
> +static void ppc440_pcix_class_init(ObjectClass *klass, void *data)
> +{
> +    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    k->init = ppc440_pcix_initfn;
> +    dc->reset = ppc440_pcix_reset;
> +}
> +
> +static const TypeInfo ppc440_pcix_info = {
> +    .name          = TYPE_PPC440_PCIX_HOST_BRIDGE,
> +    .parent        = TYPE_PCI_HOST_BRIDGE,
> +    .instance_size = sizeof(PPC440PCIXState),
> +    .class_init    = ppc440_pcix_class_init,
> +};
> +
> +static void ppc440_pcix_register_types(void)
> +{
> +    type_register_static(&ppc440_pcix_info);
> +}
> +
> +type_init(ppc440_pcix_register_types)

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 09/15] hw/ide: Emulate SiI3112 SATA controller
  2017-08-22 19:01       ` John Snow
  2017-08-22 20:15         ` BALATON Zoltan
@ 2017-08-23  0:52         ` David Gibson
  2017-08-23 16:16           ` John Snow
  1 sibling, 1 reply; 66+ messages in thread
From: David Gibson @ 2017-08-23  0:52 UTC (permalink / raw)
  To: John Snow
  Cc: BALATON Zoltan, qemu-devel, qemu-ppc, Francois Revol, Alexander Graf

[-- Attachment #1: Type: text/plain, Size: 4048 bytes --]

On Tue, Aug 22, 2017 at 03:01:18PM -0400, John Snow wrote:
> 
> 
> On 08/22/2017 07:08 AM, BALATON Zoltan wrote:
> > Hello,
> > 
> > Thanks for the review.
> > 
> > On Mon, 21 Aug 2017, John Snow wrote:
> >> On 08/20/2017 01:23 PM, BALATON Zoltan wrote:
> >>> This is a common generic PCI SATA conroller that is also used in PCs
> >>> but more importantly guests running on the Sam460ex board prefer this
> >>> card and have a driver for it (unlike for other SATA controllers
> >>> already emulated).
> >>
> >> Oh, interesting. This is basically an alternative to the PCI BMDMA
> >> interface and not really an alternative to AHCI. It doesn't really seem
> > 
> > Yes, this is a simple PCI SATA interface similar to IDE and not like
> > AHCI. I think it's an updated version of the CMD640 IDE interface or
> > more closely related to that. The Linux driver references CMD680 as well
> > so it's probably a SATA version of that chip.
> > 
> >> to use any of the SATA-specific interfaces to SATA drives (cough, not
> >> that we currently emulate a difference in QEMU... ATA and SATA both are
> >> simply IDEState*) so this really seems like another PCI IDE interface
> >> akin to the PCI BMDMA adapter we already have.
> >>
> >> It's just that guests will think they're using SATA, except... not. Not
> >> a big deal, *I think*...
> >>
> >> ...It isn't a problem that our support for NCQ commands is tied to AHCI,
> >> is it? Some of our current "SATA" support is tied very directly to AHCI
> >> (see is_ncq() in ahci.c) -- is that relevant here?
> > 
> > I don't think any of the clients on Sam460ex tries to use NCQ so maybe
> > it's OK. Linux might have a better driver but I'm not sure. This could
> > be fixed later. Although I've seen a hang in Linux which I haven't
> > debugged yet and don't know what causes it or if it's related to SATA at
> > all.
> > 
> > I'm not sure I've implemented everything correctly but at least the
> > firmware of the board can find disks and load files to boot OSes so
> > basic functions should be working. There are some other bugs elsewhere
> > which prevent me from testing more OSes at the moment. One of them is
> > QEMU crashing sometimes while accessing this SATA controller but it's
> > triggered from TCG generated code and depends on some timing because it
> > goes away if I change code running in the client or add some debug logs.
> > This is described here:
> > 
> 
> "Elsewhere" as in "Not seemingly related to this controller," it seems.
> 
> > http://lists.nongnu.org/archive/html/qemu-ppc/2017-08/msg00249.html
> > 
> > You don't happen to have an idea or seen similar before, do you? (Likely
> > it's not related to IDE but more likely some io memory region
> > interaction with TCG.)
> > 
> 
> Sorry, the traces look foreign to me.
> 
> > I intend to improve this device model later when found necessary but I
> > don't have much free time for it now so I'd like to submit it now to get
> > some more testing and maybe contributions from others.
> > 
> 
> Sure, but be advised that if the device causes problems outside of this
> use case and there's nobody willing or able to review it, that it may
> get removed again.
> 
> I don't have a lot of free time to go through the register list point by
> point and make sure this is implemented correctly either, but if this
> helps your work I'm OK not holding it up.

That's been pretty much my view on most of this.  I have neither the
at-hand knowledge of the hardware, nor time to look it up to give a
detailed review.  But if it's replacing a complete lack of support and
there's nothing obviously bogus, seems reasonable to let it in.

Jon, do you want me to queue this driver in my tree (for 2.11,
obviously), or do you want to take it through another tree?

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 11/15] ppc: Add 460EX embedded CPU
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 11/15] ppc: Add 460EX embedded CPU BALATON Zoltan
@ 2017-08-23  2:28   ` David Gibson
  2017-08-23  9:08     ` BALATON Zoltan
  0 siblings, 1 reply; 66+ messages in thread
From: David Gibson @ 2017-08-23  2:28 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 4424 bytes --]

On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
> Despite its name it is a 440 core CPU

As I recall 460 was supposed to be a 440 with SMP support.  Except
they screwed up the cache coherence, so it's basically unusable for
SMP (at least with Linux).  They finally got 440 SMP right in 470
IIRC.

Or are you saying that the 460EX is more 440 like than other 460 cpus?
> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
> ---
>  target/ppc/cpu-models.c     |  3 +++
>  target/ppc/cpu-models.h     |  1 +
>  target/ppc/translate_init.c | 38 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 42 insertions(+)
> 
> diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
> index 4d3e635..7c368fc 100644
> --- a/target/ppc/cpu-models.c
> +++ b/target/ppc/cpu-models.c
> @@ -348,6 +348,8 @@
>                  "PowerPC 440 EPb")
>      POWERPC_DEF("440EPX",        CPU_POWERPC_440EPX,                 440EP,
>                  "PowerPC 440 EPX")
> +    POWERPC_DEF("460EXb",        CPU_POWERPC_460EXb,                 460EX,
> +                "PowerPC 460 EXb")
>  #if defined(TODO_USER_ONLY)
>      POWERPC_DEF("440GPb",        CPU_POWERPC_440GPb,                 440GP,
>                  "PowerPC 440 GPb")
> @@ -1238,6 +1240,7 @@ PowerPCCPUAlias ppc_cpu_aliases[] = {
>      { "440GP", "440GPc" },
>      { "440GR", "440GRa" },
>      { "440GX", "440GXf" },
> +    { "460EX", "460EXb" },
>  
>      { "RCPU", "MPC5xx" },
>      /* MPC5xx microcontrollers */
> diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h
> index b563c45..92f99c0 100644
> --- a/target/ppc/cpu-models.h
> +++ b/target/ppc/cpu-models.h
> @@ -241,6 +241,7 @@ enum {
>      CPU_POWERPC_440SP              = 0x53221850,
>      CPU_POWERPC_440SP2             = 0x53221891,
>      CPU_POWERPC_440SPE             = 0x53421890,
> +    CPU_POWERPC_460EXb             = 0x130218A4, /* called 460 but 440 core */
>      /* PowerPC 460 family */
>  #if 0
>      /* Generic PowerPC 464 */
> diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c
> index 8fb407e..1e0d566 100644
> --- a/target/ppc/translate_init.c
> +++ b/target/ppc/translate_init.c
> @@ -3832,6 +3832,44 @@ POWERPC_FAMILY(440EP)(ObjectClass *oc, void *data)
>                   POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
>  }
>  
> +POWERPC_FAMILY(460EX)(ObjectClass *oc, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(oc);
> +    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
> +
> +    dc->desc = "PowerPC 460 EX";
> +    pcc->init_proc = init_proc_440EP;
> +    pcc->check_pow = check_pow_nocheck;
> +    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
> +                       PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |
> +                       PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> +                       PPC_FLOAT_STFIWX |
> +                       PPC_DCR | PPC_DCRX | PPC_WRTEE | PPC_RFMCI |
> +                       PPC_CACHE | PPC_CACHE_ICBI |
> +                       PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
> +                       PPC_MEM_TLBSYNC | PPC_MFTB |
> +                       PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
> +                       PPC_440_SPEC;
> +    pcc->msr_mask = (1ull << MSR_POW) |
> +                    (1ull << MSR_CE) |
> +                    (1ull << MSR_EE) |
> +                    (1ull << MSR_PR) |
> +                    (1ull << MSR_FP) |
> +                    (1ull << MSR_ME) |
> +                    (1ull << MSR_FE0) |
> +                    (1ull << MSR_DWE) |
> +                    (1ull << MSR_DE) |
> +                    (1ull << MSR_FE1) |
> +                    (1ull << MSR_IR) |
> +                    (1ull << MSR_DR);
> +    pcc->mmu_model = POWERPC_MMU_BOOKE;
> +    pcc->excp_model = POWERPC_EXCP_BOOKE;
> +    pcc->bus_model = PPC_FLAGS_INPUT_BookE;
> +    pcc->bfd_mach = bfd_mach_ppc_403;
> +    pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DWE |
> +                 POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
> +}
> +
>  static void init_proc_440GP(CPUPPCState *env)
>  {
>      /* Time base */

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 12/15] ppc4xx: Export ECB and PLB emulation
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 12/15] ppc4xx: Export ECB and PLB emulation BALATON Zoltan
@ 2017-08-23  2:30   ` David Gibson
  0 siblings, 0 replies; 66+ messages in thread
From: David Gibson @ 2017-08-23  2:30 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 2078 bytes --]

On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
> Make these device models available outside ppc405_uc.c for reuse in
> 460EX emulation. They are left in their current place for now because
> they are used mostly unchanged and I'm not sure these correctly model
> the components in 440 SoCs (but they seem to be good enough). These
> functions could be moved in a subsequent clean up series when this is
> confirmed.

Your reasoning convinces me.  Applied to ppc-for-2.11.

> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
>  hw/ppc/ppc405.h    | 3 +++
>  hw/ppc/ppc405_uc.c | 4 ++--
>  2 files changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
> index a9ffc87..7ed25cf 100644
> --- a/hw/ppc/ppc405.h
> +++ b/hw/ppc/ppc405.h
> @@ -59,6 +59,9 @@ struct ppc4xx_bd_info_t {
>  ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
>                                  uint32_t flags);
>  
> +void ppc4xx_plb_init(CPUPPCState *env);
> +void ppc405_ebc_init(CPUPPCState *env);
> +
>  CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
>                          MemoryRegion ram_memories[4],
>                          hwaddr ram_bases[4],
> diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
> index 8f44cb4..e621d0a 100644
> --- a/hw/ppc/ppc405_uc.c
> +++ b/hw/ppc/ppc405_uc.c
> @@ -174,7 +174,7 @@ static void ppc4xx_plb_reset (void *opaque)
>      plb->besr = 0x00000000;
>  }
>  
> -static void ppc4xx_plb_init(CPUPPCState *env)
> +void ppc4xx_plb_init(CPUPPCState *env)
>  {
>      ppc4xx_plb_t *plb;
>  
> @@ -585,7 +585,7 @@ static void ebc_reset (void *opaque)
>      ebc->cfg = 0x80400000;
>  }
>  
> -static void ppc405_ebc_init(CPUPPCState *env)
> +void ppc405_ebc_init(CPUPPCState *env)
>  {
>      ppc4xx_ebc_t *ebc;
>  

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 13/15] ppc4xx: Add more PLB registers
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 13/15] ppc4xx: Add more PLB registers BALATON Zoltan
  2017-08-20 21:58   ` Philippe Mathieu-Daudé
@ 2017-08-23  2:39   ` David Gibson
  2017-08-23 10:16     ` BALATON Zoltan
  1 sibling, 1 reply; 66+ messages in thread
From: David Gibson @ 2017-08-23  2:39 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 2167 bytes --]

On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
> These registers are present in 440 SoCs (and maybe in others too) and
> U-Boot accesses them when printing register info. We don't emulate
> these but add them to avoid crashing when they are read or written.
> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>

I'm ok with stub implementation, but I'm a bit uncomfortable with
registering these DCRs unconditionally rather than just on the chips
that actually implement them.

> ---
>  hw/ppc/ppc405_uc.c | 12 +++++++++---
>  1 file changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
> index e621d0a..8e58065 100644
> --- a/hw/ppc/ppc405_uc.c
> +++ b/hw/ppc/ppc405_uc.c
> @@ -105,9 +105,12 @@ ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
>  /*****************************************************************************/
>  /* Peripheral local bus arbitrer */
>  enum {
> -    PLB0_BESR = 0x084,
> -    PLB0_BEAR = 0x086,
> -    PLB0_ACR  = 0x087,
> +    PLB3A0_ACR = 0x077,
> +    PLB4A0_ACR = 0x081,
> +    PLB0_BESR  = 0x084,
> +    PLB0_BEAR  = 0x086,
> +    PLB0_ACR   = 0x087,
> +    PLB4A1_ACR = 0x089,
>  };
>  
>  typedef struct ppc4xx_plb_t ppc4xx_plb_t;
> @@ -179,9 +182,12 @@ void ppc4xx_plb_init(CPUPPCState *env)
>      ppc4xx_plb_t *plb;
>  
>      plb = g_malloc0(sizeof(ppc4xx_plb_t));
> +    ppc_dcr_register(env, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
> +    ppc_dcr_register(env, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>      ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>      ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
>      ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
> +    ppc_dcr_register(env, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>      qemu_register_reset(ppc4xx_plb_reset, plb);
>  }
>  

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 13/15] ppc4xx: Add more PLB registers
  2017-08-20 21:58   ` Philippe Mathieu-Daudé
  2017-08-20 22:12     ` BALATON Zoltan
@ 2017-08-23  2:40     ` David Gibson
  1 sibling, 0 replies; 66+ messages in thread
From: David Gibson @ 2017-08-23  2:40 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: BALATON Zoltan, qemu-devel, qemu-ppc, Francois Revol, Alexander Graf

[-- Attachment #1: Type: text/plain, Size: 2834 bytes --]

On Sun, Aug 20, 2017 at 06:58:52PM -0300, Philippe Mathieu-Daudé wrote:
> Hi Zoltan,
> 
> On 08/20/2017 02:23 PM, BALATON Zoltan wrote:
> > These registers are present in 440 SoCs (and maybe in others too) and
> > U-Boot accesses them when printing register info. We don't emulate
> > these but add them to avoid crashing when they are read or written.
> 
> Your code isn't incorrect but it doesn't sound the right way to fix your
> problem. Your firmware shouldn't *crash* on unimplemented dcr.
> 
> Looking at ppc_dcr_read() I see that *valp isn't updated on unimp dcrn,
> while the dcr_read_plb() callback you are using return 0 on unimp (with an
> "avoid gcc warning" misleading comment).

Hrm.. I thought accessing a bad DCR led to a 0x700 exception rather
than just returning a dummy value.

> 
> What is the hardware behavior on implemented dcr? return 0? In that case
> this should be used in ppc_dcr_read(), also adding some
> qemu_log_mask(LOG_UNIMP,...) log entry there.
> 
> Regards,
> 
> Phil.
> 
> > 
> > Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> > ---
> >   hw/ppc/ppc405_uc.c | 12 +++++++++---
> >   1 file changed, 9 insertions(+), 3 deletions(-)
> > 
> > diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
> > index e621d0a..8e58065 100644
> > --- a/hw/ppc/ppc405_uc.c
> > +++ b/hw/ppc/ppc405_uc.c
> > @@ -105,9 +105,12 @@ ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
> >   /*****************************************************************************/
> >   /* Peripheral local bus arbitrer */
> >   enum {
> > -    PLB0_BESR = 0x084,
> > -    PLB0_BEAR = 0x086,
> > -    PLB0_ACR  = 0x087,
> > +    PLB3A0_ACR = 0x077,
> > +    PLB4A0_ACR = 0x081,
> > +    PLB0_BESR  = 0x084,
> > +    PLB0_BEAR  = 0x086,
> > +    PLB0_ACR   = 0x087,
> > +    PLB4A1_ACR = 0x089,
> >   };
> >   typedef struct ppc4xx_plb_t ppc4xx_plb_t;
> > @@ -179,9 +182,12 @@ void ppc4xx_plb_init(CPUPPCState *env)
> >       ppc4xx_plb_t *plb;
> >       plb = g_malloc0(sizeof(ppc4xx_plb_t));
> > +    ppc_dcr_register(env, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
> > +    ppc_dcr_register(env, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
> >       ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
> >       ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
> >       ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
> > +    ppc_dcr_register(env, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb);
> >       qemu_register_reset(ppc4xx_plb_reset, plb);
> >   }
> > 
> 

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 14/15] ppc4xx: Add device models found in PPC440 core SoCs
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 14/15] ppc4xx: Add device models found in PPC440 core SoCs BALATON Zoltan
@ 2017-08-23  2:49   ` David Gibson
  0 siblings, 0 replies; 66+ messages in thread
From: David Gibson @ 2017-08-23  2:49 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 1325 bytes --]

On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
> These devices are found in newer SoCs based on 440 core e.g. the 460EX
> (http://www.embeddeddeveloper.com/assets/processors/amcc/datasheets/
> PP460EX_DS2063.pdf)

As usual, I can't review in depth, but there's not much obviously
bogus, so I'm inclined to merge, except for one detail:

[snip]
> +#ifdef MAP_L2SRAM
> +static void l2sram_update_mappings(ppc4xx_l2sram_t *l2sram,
> +                                   uint32_t isarc, uint32_t isacntl,
> +                                   uint32_t dsarc, uint32_t dsacntl)
> +{
> +#ifdef DEBUG_L2SRAM
> +    printf("L2SRAM update ISA %08" PRIx32 " %08" PRIx32 " (%08" PRIx32
> +           " %08" PRIx32 ") DSA %08" PRIx32 " %08" PRIx32
> +           " (%08" PRIx32 " %08" PRIx32 ")\n",
> +           isarc, isacntl, dsarc, dsacntl,
> +           l2sram->isarc, l2sram->isacntl, l2sram->dsarc, l2sram->dsacntl);

For new code, trace points are strongly preferred to DPRINTF() macros
or explicit printf()s.  In addition sending this output to stdout
rather than stderr is a pretty bad idea.

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 15/15] ppc: Add aCube Sam460ex board
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 15/15] ppc: Add aCube Sam460ex board BALATON Zoltan
  2017-08-20 22:10   ` Philippe Mathieu-Daudé
@ 2017-08-23  4:16   ` David Gibson
  2017-08-23 11:12     ` BALATON Zoltan
  1 sibling, 1 reply; 66+ messages in thread
From: David Gibson @ 2017-08-23  4:16 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 25418 bytes --]

On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
> Add emulation of aCube Sam460ex board based on AMCC 460EX embedded SoC.
> This is not a full implementation yet with a lot of components still
> missing but enough to start a Linux kernel and the U-Boot firmware.
> 
> Signed-off-by: François Revol <revol@free.fr>
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>

As usual, only fairly superficial review here.

> ---
>  default-configs/ppcemb-softmmu.mak |   3 +
>  hw/ppc/Makefile.objs               |   2 +
>  hw/ppc/sam460ex.c                  | 611 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 616 insertions(+)
>  create mode 100644 hw/ppc/sam460ex.c
> 
> diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
> index 635923a..90b42f0 100644
> --- a/default-configs/ppcemb-softmmu.mak
> +++ b/default-configs/ppcemb-softmmu.mak
> @@ -17,3 +17,6 @@ CONFIG_XILINX=y
>  CONFIG_XILINX_ETHLITE=y
>  CONFIG_LIBDECNUMBER=y
>  CONFIG_SM501=y
> +CONFIG_USB_EHCI_SYSBUS=y
> +CONFIG_IDE_SII3112=y
> +CONFIG_SAM460EX=y
> diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
> index fc39fe4..0aaea5b 100644
> --- a/hw/ppc/Makefile.objs
> +++ b/hw/ppc/Makefile.objs
> @@ -27,3 +27,5 @@ obj-$(CONFIG_E500) += e500.o mpc8544ds.o e500plat.o
>  obj-$(CONFIG_E500) += mpc8544_guts.o ppce500_spin.o
>  # PowerPC 440 Xilinx ML507 reference board.
>  obj-$(CONFIG_XILINX) += virtex_ml507.o
> +# ACube Sam460ex board.
> +obj-$(CONFIG_SAM460EX) += ppc440_uc.o sam460ex.o
> diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
> new file mode 100644
> index 0000000..7cf4f6f
> --- /dev/null
> +++ b/hw/ppc/sam460ex.c
> @@ -0,0 +1,611 @@
> +/*
> + * QEMU aCube Sam460ex board emulation
> + *
> + * Copyright (c) 2012 François Revol
> + * Copyright (c) 2016-2017 BALATON Zoltan
> + *
> + * This file is derived from hw/ppc440_bamboo.c,
> + * the copyright for that material belongs to the original owners.
> + *
> + * This work is licensed under the GNU GPL license version 2 or later.
> + *
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu-common.h"
> +#include "qemu/cutils.h"
> +#include "qapi/error.h"
> +#include "hw/hw.h"
> +#include "sysemu/blockdev.h"
> +#include "hw/boards.h"
> +#include "sysemu/kvm.h"
> +#include "kvm_ppc.h"
> +#include "sysemu/device_tree.h"
> +#include "sysemu/block-backend.h"
> +#include "hw/loader.h"
> +#include "elf.h"
> +#include "exec/address-spaces.h"
> +#include "exec/memory.h"
> +#include "hw/ppc/ppc440.h"
> +#include "hw/ppc/ppc405.h"
> +#include "hw/block/flash.h"
> +#include "sysemu/sysemu.h"
> +#include "hw/sysbus.h"
> +#include "hw/char/serial.h"
> +#include "hw/i2c/ppc4xx_i2c.h"
> +#include "hw/i2c/smbus.h"
> +#include "hw/usb/hcd-ehci.h"
> +
> +#define BINARY_DEVICE_TREE_FILE "sam460ex.dtb"
> +#define UBOOT_FILENAME "u-boot-sam460-20100605.bin"
> +/* to extract the official U-Boot bin from the updater: */
> +/* dd bs=1 skip=$(($(stat -c '%s' updater/updater-460) - 0x80000)) \
> +     if=updater/updater-460 of=u-boot-sam460-20100605.bin */
> +
> +/* from Sam460 U-Boot include/configs/Sam460ex.h */
> +#define FLASH_BASE             0xfff00000
> +#define FLASH_BASE_H           0x4
> +#define FLASH_SIZE             (1 << 20)
> +#define UBOOT_LOAD_BASE        0xfff80000
> +#define UBOOT_SIZE             0x00080000
> +#define UBOOT_ENTRY            0xfffffffc
> +
> +/* from U-Boot */
> +#define EPAPR_MAGIC           (0x45504150)
> +#define KERNEL_ADDR           0x1000000
> +#define FDT_ADDR              0x1800000
> +#define RAMDISK_ADDR          0x1900000
> +
> +/* Sam460ex IRQ MAP:
> +   IRQ0  = ETH_INT
> +   IRQ1  = FPGA_INT
> +   IRQ2  = PCI_INT (PCIA, PCIB, PCIC, PCIB)
> +   IRQ3  = FPGA_INT2
> +   IRQ11 = RTC_INT
> +   IRQ12 = SM502_INT
> +*/
> +
> +#define SDRAM_NR_BANKS 4
> +
> +/* FIXME: See u-boot.git 8ac41e */
> +static const unsigned int ppc460ex_sdram_bank_sizes[] = {
> +    1024 << 20, 512 << 20, 256 << 20, 128 << 20, 64 << 20, 32 << 20, 0
> +};
> +
> +struct boot_info {
> +    uint32_t dt_base;
> +    uint32_t dt_size;
> +    uint32_t entry;
> +};
> +
> +/*****************************************************************************/
> +/* SPD eeprom content from mips_malta.c */

What's the connection with mips_malta?

> +struct _eeprom24c0x_t {
> +  uint8_t tick;
> +  uint8_t address;
> +  uint8_t command;
> +  uint8_t ack;
> +  uint8_t scl;
> +  uint8_t sda;
> +  uint8_t data;
> +  uint8_t contents[256];
> +};
> +
> +typedef struct _eeprom24c0x_t eeprom24c0x_t;
> +
> +static eeprom24c0x_t spd_eeprom = {
> +    .contents = {
> +        /* 00000000: */ 0x80, 0x08, 0xFF, 0x0D, 0x0A, 0xFF, 0x40, 0x00,
> +        /* 00000008: */ 0x04, 0x75, 0x54, 0x00, 0x82, 0x08, 0x00, 0x01,
> +        /* 00000010: */ 0x8F, 0x04, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00,
> +        /* 00000018: */ 0x00, 0x00, 0x00, 0x14, 0x0F, 0x14, 0x2D, 0xFF,
> +        /* 00000020: */ 0x15, 0x08, 0x15, 0x08, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xD0,
> +        /* 00000040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +        /* 00000078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xF4,
> +    },
> +};
> +
> +static void generate_eeprom_spd(uint8_t *eeprom, ram_addr_t ram_size)
> +{
> +    enum { SDR = 0x4, DDR1 = 0x7, DDR2 = 0x8 } type;
> +    uint8_t *spd = spd_eeprom.contents;
> +    uint8_t nbanks = 0;
> +    uint16_t density = 0;
> +    int i;
> +
> +    /* work in terms of MB */
> +    ram_size >>= 20;
> +
> +    while ((ram_size >= 4) && (nbanks <= 2)) {
> +        int sz_log2 = MIN(31 - clz32(ram_size), 14);
> +        nbanks++;
> +        density |= 1 << (sz_log2 - 2);
> +        ram_size -= 1 << sz_log2;
> +    }
> +
> +    /* split to 2 banks if possible */
> +    if ((nbanks == 1) && (density > 1)) {
> +        nbanks++;
> +        density >>= 1;
> +    }
> +
> +    if (density & 0xff00) {
> +        density = (density & 0xe0) | ((density >> 8) & 0x1f);
> +        type = DDR2;
> +    } else if (!(density & 0x1f)) {
> +        type = DDR2;
> +    } else {
> +        type = SDR;
> +    }
> +
> +    if (ram_size) {
> +        fprintf(stderr, "Warning: SPD cannot represent final %dMB"
> +                " of SDRAM\n", (int)ram_size);
> +    }
> +
> +    /* fill in SPD memory information */
> +    spd[2] = type;
> +    spd[5] = nbanks;
> +    spd[31] = density;
> +#ifdef DEBUG_SDRAM
> +    printf("SPD: nbanks %d density %d\n", nbanks, density);
> +#endif
> +    /* XXX: this is totally random */
> +    spd[9] = 0x10; /* CAS tcyc */
> +    spd[18] = 0x20; /* CAS bit */
> +    spd[23] = 0x10; /* CAS tcyc */
> +    spd[25] = 0x10; /* CAS tcyc */
> +
> +    /* checksum */
> +    spd[63] = 0;
> +    for (i = 0; i < 63; i++) {
> +        spd[63] += spd[i];
> +    }
> +
> +    /* copy for SMBUS */
> +    memcpy(eeprom, spd, sizeof(spd_eeprom.contents));
> +}
> +
> +static void generate_eeprom_serial(uint8_t *eeprom)
> +{
> +    int i, pos = 0;
> +    uint8_t mac[6] = { 0x00 };
> +    uint8_t sn[5] = { 0x01, 0x23, 0x45, 0x67, 0x89 };
> +
> +    /* version */
> +    eeprom[pos++] = 0x01;
> +
> +    /* count */
> +    eeprom[pos++] = 0x02;
> +
> +    /* MAC address */
> +    eeprom[pos++] = 0x01; /* MAC */
> +    eeprom[pos++] = 0x06; /* length */
> +    memcpy(&eeprom[pos], mac, sizeof(mac));
> +    pos += sizeof(mac);
> +
> +    /* serial number */
> +    eeprom[pos++] = 0x02; /* serial */
> +    eeprom[pos++] = 0x05; /* length */
> +    memcpy(&eeprom[pos], sn, sizeof(sn));
> +    pos += sizeof(sn);
> +
> +    /* checksum */
> +    eeprom[pos] = 0;
> +    for (i = 0; i < pos; i++) {
> +        eeprom[pos] += eeprom[i];
> +    }
> +}
> +
> +/*****************************************************************************/
> +
> +static int sam460ex_load_uboot(void)
> +{
> +    DriveInfo *dinfo;
> +    BlockBackend *blk = NULL;
> +    hwaddr base = FLASH_BASE | ((hwaddr)FLASH_BASE_H << 32);
> +    long bios_size = FLASH_SIZE;
> +    int fl_sectors;
> +
> +    dinfo = drive_get(IF_PFLASH, 0, 0);
> +    if (dinfo) {
> +        blk = blk_by_legacy_dinfo(dinfo);
> +        bios_size = blk_getlength(blk);
> +    }
> +    fl_sectors = (bios_size + 65535) >> 16;
> +
> +    if (!pflash_cfi01_register(base, NULL, "sam460ex.flash", bios_size,
> +                               blk, (64 * 1024), fl_sectors,
> +                               1, 0x89, 0x18, 0x0000, 0x0, 1)) {
> +        fprintf(stderr, "qemu: Error registering flash memory.\n");

Use error_report() instead, please.

> +        /* XXX: return an error instead? */
> +        exit(1);
> +    }
> +
> +    if (!blk) {
> +        /*fprintf(stderr, "No flash image given with the 'pflash' parameter,"
> +                " using default u-boot image\n");*/
> +        base = UBOOT_LOAD_BASE | ((hwaddr)FLASH_BASE_H << 32);
> +        rom_add_file_fixed(UBOOT_FILENAME, base, -1);
> +    }
> +
> +    return 0;
> +}
> +
> +static int sam460ex_load_device_tree(hwaddr addr,
> +                                     uint32_t ramsize,
> +                                     hwaddr initrd_base,
> +                                     hwaddr initrd_size,
> +                                     const char *kernel_cmdline)
> +{
> +    int ret = -1;
> +    uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) };
> +    char *filename;
> +    int fdt_size;
> +    void *fdt;
> +    uint32_t tb_freq = 400000000;
> +    uint32_t clock_freq = 400000000;
> +
> +    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
> +    if (!filename) {
> +        goto out;
> +    }
> +    fdt = load_device_tree(filename, &fdt_size);
> +    g_free(filename);
> +    if (fdt == NULL) {
> +        goto out;
> +    }
> +
> +    /* Manipulate device tree in memory. */
> +
> +    ret = qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property,
> +                               sizeof(mem_reg_property));
> +    if (ret < 0) {
> +        fprintf(stderr, "couldn't set /memory/reg\n");

And in all these places.

> +    }
> +
> +    /* default FDT doesn't have a /chosen node... */
> +    qemu_fdt_add_subnode(fdt, "/chosen");
> +
> +    ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
> +                                    initrd_base);
> +    if (ret < 0) {
> +        fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
> +    }
> +
> +    ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
> +                                    (initrd_base + initrd_size));
> +    if (ret < 0) {
> +        fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
> +    }
> +
> +    ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
> +                                      kernel_cmdline);
> +    if (ret < 0) {
> +        fprintf(stderr, "couldn't set /chosen/bootargs\n");
> +    }
> +
> +    /* Copy data from the host device tree into the guest. Since the guest can
> +     * directly access the timebase without host involvement, we must expose
> +     * the correct frequencies. */
> +    if (kvm_enabled()) {
> +        tb_freq = kvmppc_get_tbfreq();
> +        clock_freq = kvmppc_get_clockfreq();
> +    }
> +
> +    qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency",
> +                              clock_freq);
> +    qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency",
> +                              tb_freq);
> +
> +    rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
> +    g_free(fdt);
> +    ret = fdt_size;
> +
> +out:
> +
> +    return ret;
> +}
> +
> +/* Create reset TLB entries for BookE, mapping only the flash memory.  */
> +static void mmubooke_create_initial_mapping_uboot(CPUPPCState *env)
> +{
> +    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
> +
> +    /* on reset the flash is mapped by a shadow TLB,
> +     * but since we don't implement them we need to use
> +     * the same values U-Boot will use to avoid a fault.
> +     */

Usually the reset state of the MMU is handled in the cpu code rather
than the board code.  Is there a specific reason you need it in the
board code here?

> +    tlb->attr = 0;
> +    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
> +    tlb->size = 0x10000000; /* up to 0xffffffff  */
> +    tlb->EPN = 0xf0000000 & TARGET_PAGE_MASK;
> +    tlb->RPN = (0xf0000000 & TARGET_PAGE_MASK) | 0x4;
> +    tlb->PID = 0;
> +}
> +
> +/* Create reset TLB entries for BookE, spanning the 32bit addr space.  */
> +static void mmubooke_create_initial_mapping(CPUPPCState *env,
> +                                     target_ulong va,
> +                                     hwaddr pa)
> +{
> +    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
> +
> +    tlb->attr = 0;
> +    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
> +    tlb->size = 1 << 31; /* up to 0x80000000  */
> +    tlb->EPN = va & TARGET_PAGE_MASK;
> +    tlb->RPN = pa & TARGET_PAGE_MASK;
> +    tlb->PID = 0;
> +}
> +
> +static void main_cpu_reset(void *opaque)
> +{
> +    PowerPCCPU *cpu = opaque;
> +    CPUPPCState *env = &cpu->env;
> +    struct boot_info *bi = env->load_info;
> +
> +    cpu_reset(CPU(cpu));
> +
> +    /* either we have a kernel to boot or we jump to U-Boot */
> +    if (bi->entry != UBOOT_ENTRY) {
> +        env->gpr[1] = (16 << 20) - 8;
> +        env->gpr[3] = FDT_ADDR;
> +
> +        fprintf(stderr, "cpu reset: kernel entry %x\n", bi->entry);

These should be tracepoints rather than bare fprintf().

> +        env->nip = bi->entry;
> +
> +        /* Create a mapping for the kernel.  */
> +        mmubooke_create_initial_mapping(env, 0, 0);
> +        env->gpr[6] = tswap32(EPAPR_MAGIC);

I'm pretty sure the tswap can't be right here.  env->gpr is in host
native order and I'd expect the constant to be as well.  

> +        env->gpr[7] = (16 << 20) - 8; /*bi->ima_size;*/

So, entering the kernel directly can be useful, particularly during
early development.  However, having both firmware and non-firmware
entry paths can lead to confusing bugs if there's a subtle difference
between the initial (to the kernel) states between the two paths.  For
that reason, the usual preferred way to implement -kernel is to still
run the usual firmware, but use some way of telling it to boot
immediately into the supplied kernel.

I won't object to merging it this way - just a wanrning that this may
bite you in the future if you're not careful.

> +
> +    } else {
> +        env->nip = UBOOT_ENTRY;
> +        mmubooke_create_initial_mapping_uboot(env);
> +        fprintf(stderr, "cpu reset: U-Boot entry\n");

Tracepoint.

> +    }
> +}
> +
> +static void sam460ex_init(MachineState *machine)
> +{
> +    MemoryRegion *address_space_mem = get_system_memory();
> +    MemoryRegion *isa = g_new(MemoryRegion, 1);
> +    MemoryRegion *ram_memories = g_new(MemoryRegion, SDRAM_NR_BANKS);
> +    hwaddr ram_bases[SDRAM_NR_BANKS];
> +    hwaddr ram_sizes[SDRAM_NR_BANKS];
> +    MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1);
> +    qemu_irq *irqs, *uic[4];
> +    PCIBus *pci_bus;
> +    PowerPCCPU *cpu;
> +    CPUPPCState *env;
> +    PPC4xxI2CState *i2c[2];
> +    hwaddr entry = UBOOT_ENTRY;
> +    hwaddr loadaddr = 0;
> +    target_long initrd_size = 0;
> +    DeviceState *dev;
> +    SysBusDevice *sbdev;
> +    int success;
> +    int i;
> +    struct boot_info *boot_info;
> +    const size_t smbus_eeprom_size = 8 * 256;
> +    uint8_t *smbus_eeprom_buf = g_malloc0(smbus_eeprom_size);
> +
> +    /* Setup CPU. */
> +    if (machine->cpu_model == NULL) {
> +        machine->cpu_model = "460EX";
> +    }
> +    cpu = cpu_ppc_init(machine->cpu_model);
> +    if (cpu == NULL) {
> +        fprintf(stderr, "Unable to initialize CPU!\n");
> +        exit(1);
> +    }
> +    env = &cpu->env;
> +
> +    qemu_register_reset(main_cpu_reset, cpu);
> +    boot_info = g_malloc0(sizeof(*boot_info));
> +    env->load_info = boot_info;
> +
> +    ppc_booke_timers_init(cpu, 50000000, 0);
> +    ppc_dcr_init(env, NULL, NULL);
> +
> +    /* PLB arbitrer */
> +    ppc4xx_plb_init(env);
> +
> +    /* interrupt controllers */
> +    irqs = g_malloc0(sizeof(*irqs) * PPCUIC_OUTPUT_NB);
> +    irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
> +    irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
> +    uic[0] = ppcuic_init(env, irqs, 0x0C0, 0, 1);
> +    uic[1] = ppcuic_init(env, &uic[0][30], 0x0D0, 0, 1);
> +    uic[2] = ppcuic_init(env, &uic[0][10], 0x0E0, 0, 1);
> +    uic[3] = ppcuic_init(env, &uic[0][16], 0x0F0, 0, 1);
> +
> +    /* SDRAM controller */
> +    memset(ram_bases, 0, sizeof(ram_bases));
> +    memset(ram_sizes, 0, sizeof(ram_sizes));
> +    /* put all RAM on first bank because board has one slot
> +     * and firmware only checks that */
> +    machine->ram_size = ppc4xx_sdram_adjust(machine->ram_size,
> +                                   1/*SDRAM_NR_BANKS*/,
> +                                   ram_memories,
> +                                   ram_bases, ram_sizes,
> +                                   ppc460ex_sdram_bank_sizes);
> +#ifdef DEBUG_SDRAM
> +    printf("RAMSIZE %dMB\n", (int)(machine->ram_size / M_BYTE));
> +#endif
> +
> +    /* XXX does 460EX have ECC interrupts? */
> +    ppc440_sdram_init(env, SDRAM_NR_BANKS, ram_memories,
> +                      ram_bases, ram_sizes, 1);
> +
> +    /* generate SPD EEPROM data */
> +    for (i = 0; i < SDRAM_NR_BANKS; i++) {
> +#ifdef DEBUG_SDRAM
> +        printf("bank %d: %" HWADDR_PRIx "\n", i, ram_sizes[i]);
> +#endif

Tracepoint.

> +        generate_eeprom_spd(&smbus_eeprom_buf[i * 256], ram_sizes[i]);
> +    }
> +    generate_eeprom_serial(&smbus_eeprom_buf[4 * 256]);
> +    generate_eeprom_serial(&smbus_eeprom_buf[6 * 256]);
> +
> +    /* IIC controllers */
> +    dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700, uic[0][2]);
> +    i2c[0] = PPC4xx_I2C(dev);
> +    object_property_set_bool(OBJECT(dev), true, "realized", NULL);
> +    smbus_eeprom_init(i2c[0]->bus, 8, smbus_eeprom_buf, smbus_eeprom_size);
> +    g_free(smbus_eeprom_buf);
> +
> +    dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600800, uic[0][3]);
> +    i2c[1] = PPC4xx_I2C(dev);
> +
> +    /* External bus controller */
> +    ppc405_ebc_init(env);
> +
> +    /* CPR */
> +    ppc4xx_cpr_init(env);
> +
> +    /* PLB to AHB bridge */
> +    ppc4xx_ahb_init(env);
> +
> +    /* System DCRs */
> +    ppc4xx_sdr_init(env);
> +
> +    /* MAL */
> +    ppc4xx_mal_init(env, 4, 16, &uic[2][3]);
> +
> +    /* 256K of L2 cache as memory */
> +    ppc4xx_l2sram_init(env);

Seems like a lot of this peripheral setup should be handled by a SoC
helper function, since it's not really board specific (I'm guessing).
I'm ok with that being a later clean up though.

> +    /* FIXME: remove this after fixing l2sram mapping in ppc440_uc.c? */
> +    memory_region_init_ram(l2cache_ram, NULL, "ppc440.l2cache_ram", 256 << 10,
> +                           &error_abort);
> +    memory_region_add_subregion(address_space_mem, 0x400000000LL, l2cache_ram);
> +
> +    /* USB */
> +    sysbus_create_simple(TYPE_PPC4xx_EHCI, 0x4bffd0400, uic[2][29]);
> +    dev = qdev_create(NULL, "sysbus-ohci");
> +    qdev_prop_set_string(dev, "masterbus", "usb-bus.0");
> +    qdev_prop_set_uint32(dev, "num-ports", 6);
> +    qdev_init_nofail(dev);
> +    sbdev = SYS_BUS_DEVICE(dev);
> +    sysbus_mmio_map(sbdev, 0, 0x4bffd0000);
> +    sysbus_connect_irq(sbdev, 0, uic[2][30]);
> +    usb_create_simple(usb_bus_find(-1), "usb-kbd");
> +    usb_create_simple(usb_bus_find(-1), "usb-mouse");
> +
> +    /* PCI bus */
> +    ppc460ex_pcie_init(env);
> +    /*XXX: FIXME: is this correct? */
> +    dev = sysbus_create_varargs("ppc440-pcix-host", 0xc0ec00000,
> +                                uic[1][0], uic[1][20], uic[1][21], uic[1][22],
> +                                NULL);
> +    pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
> +    if (!pci_bus) {
> +        fprintf(stderr, "couldn't create PCI controller!\n");
> +        exit(1);
> +    }
> +    memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(),
> +                             0, 0x10000);
> +    memory_region_add_subregion(get_system_memory(), 0xc08000000, isa);

Does it really make sense to just embed the ISA IO space here, rather
than actually instanting a PCI<->ISA bridge?

> +    /* PCI devices */
> +    pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "sm501");
> +    /* SoC has a single SATA port but we don't emulate that yet
> +     * However, firmware and usual clients have driver for SiI311x
> +     * so add one for convenience by default */
> +    pci_create_simple(pci_bus, -1, "sii3112");

You should probably not create this when started with -nodefaults.

> +    /* SoC has 4 UARTs
> +     * but board has only one wired and two are present in fdt */
> +    if (serial_hds[0] != NULL) {
> +        serial_mm_init(address_space_mem, 0x4ef600300, 0, uic[1][1],
> +                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
> +                       DEVICE_BIG_ENDIAN);
> +    }
> +    if (serial_hds[1] != NULL) {
> +        serial_mm_init(address_space_mem, 0x4ef600400, 0, uic[0][1],
> +                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
> +                       DEVICE_BIG_ENDIAN);
> +    }
> +
> +    /* Load U-Boot image. */
> +    if (!machine->kernel_filename) {
> +        success = sam460ex_load_uboot();
> +        if (success < 0) {
> +            fprintf(stderr, "qemu: could not load firmware\n");
> +            exit(1);
> +        }
> +    }
> +
> +    /* Load kernel. */
> +    if (machine->kernel_filename) {
> +        success = load_uimage(machine->kernel_filename, &entry, &loadaddr, NULL,
> +            NULL, NULL);
> +        fprintf(stderr, "load_uimage: %d\n", success);

tracepoint

> +        if (success < 0) {
> +            uint64_t elf_entry, elf_lowaddr;
> +
> +            success = load_elf(machine->kernel_filename, NULL, NULL, &elf_entry,
> +                               &elf_lowaddr, NULL, 1, PPC_ELF_MACHINE, 0, 0);
> +            fprintf(stderr, "load_elf: %d\n", success);

tracepoint

> +            entry = elf_entry;
> +            loadaddr = elf_lowaddr;
> +        }
> +        /* XXX try again as binary */
> +        if (success < 0) {
> +            fprintf(stderr, "qemu: could not load kernel '%s'\n",
> +                    machine->kernel_filename);

error_report().

> +            exit(1);
> +        }
> +    }
> +
> +    /* Load initrd. */
> +    if (machine->initrd_filename) {
> +        initrd_size = load_image_targphys(machine->initrd_filename,
> +                                          RAMDISK_ADDR,
> +                                          machine->ram_size - RAMDISK_ADDR);
> +        fprintf(stderr, "load_image: %d\n", initrd_size);
> +        if (initrd_size < 0) {
> +            fprintf(stderr, "qemu: could not load ram disk '%s' at %x\n",
> +                    machine->initrd_filename, RAMDISK_ADDR);
> +            exit(1);
> +        }
> +    }
> +
> +    /* If we're loading a kernel directly, we must load the device tree too. */
> +    if (machine->kernel_filename) {
> +        int dt_size;
> +
> +        dt_size = sam460ex_load_device_tree(FDT_ADDR, machine->ram_size,
> +                                    RAMDISK_ADDR, initrd_size,
> +                                    machine->kernel_cmdline);
> +        if (dt_size < 0) {
> +            fprintf(stderr, "couldn't load device tree\n");
> +            exit(1);
> +        }
> +
> +        boot_info->dt_base = FDT_ADDR;
> +        boot_info->dt_size = dt_size;
> +    }
> +
> +    boot_info->entry = entry;
> +}
> +
> +static void sam460ex_machine_init(MachineClass *mc)
> +{
> +    mc->desc = "aCube Sam460ex";
> +    mc->init = sam460ex_init;
> +    mc->default_ram_size = 512 * M_BYTE;
> +}
> +
> +DEFINE_MACHINE("sam460ex", sam460ex_machine_init)

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 11/15] ppc: Add 460EX embedded CPU
  2017-08-23  2:28   ` David Gibson
@ 2017-08-23  9:08     ` BALATON Zoltan
  2017-08-23  9:20       ` David Gibson
  0 siblings, 1 reply; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-23  9:08 UTC (permalink / raw)
  To: David Gibson; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

On Wed, 23 Aug 2017, David Gibson wrote:
> On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
>> Despite its name it is a 440 core CPU
>
> As I recall 460 was supposed to be a 440 with SMP support.  Except
> they screwed up the cache coherence, so it's basically unusable for
> SMP (at least with Linux).  They finally got 440 SMP right in 470
> IIRC.
>
> Or are you saying that the 460EX is more 440 like than other 460 cpus?

AFAIK this SoC really has a 440 core with some of the embedded devices 
(such as PCIe and SDRAM controller) similar to real 460 core SoCs, so its 
name is a bit misleading. It definitely does not have a 460 CPU core so 
it's more like 440 than other 460 core SoCs.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 11/15] ppc: Add 460EX embedded CPU
  2017-08-23  9:08     ` BALATON Zoltan
@ 2017-08-23  9:20       ` David Gibson
  0 siblings, 0 replies; 66+ messages in thread
From: David Gibson @ 2017-08-23  9:20 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 1026 bytes --]

On Wed, Aug 23, 2017 at 11:08:16AM +0200, BALATON Zoltan wrote:
> On Wed, 23 Aug 2017, David Gibson wrote:
> > On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
> > > Despite its name it is a 440 core CPU
> > 
> > As I recall 460 was supposed to be a 440 with SMP support.  Except
> > they screwed up the cache coherence, so it's basically unusable for
> > SMP (at least with Linux).  They finally got 440 SMP right in 470
> > IIRC.
> > 
> > Or are you saying that the 460EX is more 440 like than other 460 cpus?
> 
> AFAIK this SoC really has a 440 core with some of the embedded devices (such
> as PCIe and SDRAM controller) similar to real 460 core SoCs, so its name is
> a bit misleading. It definitely does not have a 460 CPU core so it's more
> like 440 than other 460 core SoCs.

Ok, noted.

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 13/15] ppc4xx: Add more PLB registers
  2017-08-23  2:39   ` David Gibson
@ 2017-08-23 10:16     ` BALATON Zoltan
  2017-08-24  2:35       ` David Gibson
  0 siblings, 1 reply; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-23 10:16 UTC (permalink / raw)
  To: David Gibson; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

On Wed, 23 Aug 2017, David Gibson wrote:
> On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
>> These registers are present in 440 SoCs (and maybe in others too) and
>> U-Boot accesses them when printing register info. We don't emulate
>> these but add them to avoid crashing when they are read or written.
>>
>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>
> I'm ok with stub implementation, but I'm a bit uncomfortable with
> registering these DCRs unconditionally rather than just on the chips
> that actually implement them.

Problem is that I don't know which chips have these. I can only try to 
find out from the U-Boot sources where a comment says these are common 
registers for all SoCs (in u-boot/arch/powerpc/include/asm/ppc4xx.h:

http://git.denx.de/?p=u-boot.git;a=blob;f=arch/powerpc/include/asm/ppc4xx.h;h=45ff5dbacd9243e83bb2f6551e2dd64a7e544bf5;hb=e2351d5cf1e97408b4c52bafeaa85e0ca85c920c

while looking for this I've just noticed that u-boot has removed ppc440 
support just before 2017.07-rc3 so this is the last version that still has 
these files). So if that's true it should be OK for 405 too.

>> ---
>>  hw/ppc/ppc405_uc.c | 12 +++++++++---
>>  1 file changed, 9 insertions(+), 3 deletions(-)
>>
>> diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
>> index e621d0a..8e58065 100644
>> --- a/hw/ppc/ppc405_uc.c
>> +++ b/hw/ppc/ppc405_uc.c
>> @@ -105,9 +105,12 @@ ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
>>  /*****************************************************************************/
>>  /* Peripheral local bus arbitrer */
>>  enum {
>> -    PLB0_BESR = 0x084,
>> -    PLB0_BEAR = 0x086,
>> -    PLB0_ACR  = 0x087,
>> +    PLB3A0_ACR = 0x077,
>> +    PLB4A0_ACR = 0x081,
>> +    PLB0_BESR  = 0x084,
>> +    PLB0_BEAR  = 0x086,
>> +    PLB0_ACR   = 0x087,
>> +    PLB4A1_ACR = 0x089,
>>  };
>>
>>  typedef struct ppc4xx_plb_t ppc4xx_plb_t;
>> @@ -179,9 +182,12 @@ void ppc4xx_plb_init(CPUPPCState *env)
>>      ppc4xx_plb_t *plb;
>>
>>      plb = g_malloc0(sizeof(ppc4xx_plb_t));
>> +    ppc_dcr_register(env, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>> +    ppc_dcr_register(env, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>>      ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>>      ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
>>      ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
>> +    ppc_dcr_register(env, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>>      qemu_register_reset(ppc4xx_plb_reset, plb);
>>  }
>>
>
>

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 15/15] ppc: Add aCube Sam460ex board
  2017-08-23  4:16   ` David Gibson
@ 2017-08-23 11:12     ` BALATON Zoltan
  2017-08-23 11:43       ` François Revol
  2017-08-24  2:44       ` David Gibson
  0 siblings, 2 replies; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-23 11:12 UTC (permalink / raw)
  To: David Gibson; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

On Wed, 23 Aug 2017, David Gibson wrote:
> On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
>> Add emulation of aCube Sam460ex board based on AMCC 460EX embedded SoC.
>> This is not a full implementation yet with a lot of components still
>> missing but enough to start a Linux kernel and the U-Boot firmware.
>>
>> Signed-off-by: François Revol <revol@free.fr>
>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>
> As usual, only fairly superficial review here.
>
>> ---
>>  default-configs/ppcemb-softmmu.mak |   3 +
>>  hw/ppc/Makefile.objs               |   2 +
>>  hw/ppc/sam460ex.c                  | 611 +++++++++++++++++++++++++++++++++++++
>>  3 files changed, 616 insertions(+)
>>  create mode 100644 hw/ppc/sam460ex.c
>>
>> diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
>> index 635923a..90b42f0 100644
>> --- a/default-configs/ppcemb-softmmu.mak
>> +++ b/default-configs/ppcemb-softmmu.mak
[...]
>> +/*****************************************************************************/
>> +/* SPD eeprom content from mips_malta.c */
>
> What's the connection with mips_malta?

The board's firmware wants to see SPD EEPROMs of the connected memory 
while initialising the memory controller. This is why we need to implement 
SDRAM controller, I2C and SPD EEPROMs. MIPS malta board had already SPD 
EEPROM implementation so this is based on that. The comment just indicates 
where this code comes from.

>> +struct _eeprom24c0x_t {
>> +  uint8_t tick;
>> +  uint8_t address;
>> +  uint8_t command;
>> +  uint8_t ack;
>> +  uint8_t scl;
>> +  uint8_t sda;
>> +  uint8_t data;
>> +  uint8_t contents[256];
>> +};
>> +
>> +typedef struct _eeprom24c0x_t eeprom24c0x_t;
>> +
>> +static eeprom24c0x_t spd_eeprom = {
>> +    .contents = {
>> +        /* 00000000: */ 0x80, 0x08, 0xFF, 0x0D, 0x0A, 0xFF, 0x40, 0x00,
>> +        /* 00000008: */ 0x04, 0x75, 0x54, 0x00, 0x82, 0x08, 0x00, 0x01,
>> +        /* 00000010: */ 0x8F, 0x04, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00,
>> +        /* 00000018: */ 0x00, 0x00, 0x00, 0x14, 0x0F, 0x14, 0x2D, 0xFF,
>> +        /* 00000020: */ 0x15, 0x08, 0x15, 0x08, 0x00, 0x00, 0x00, 0x00,
>> +        /* 00000028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>> +        /* 00000030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>> +        /* 00000038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xD0,
>> +        /* 00000040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>> +        /* 00000048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>> +        /* 00000050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>> +        /* 00000058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>> +        /* 00000060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>> +        /* 00000068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>> +        /* 00000070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>> +        /* 00000078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xF4,
>> +    },
>> +};
>> +
>> +static void generate_eeprom_spd(uint8_t *eeprom, ram_addr_t ram_size)
>> +{
>> +    enum { SDR = 0x4, DDR1 = 0x7, DDR2 = 0x8 } type;
>> +    uint8_t *spd = spd_eeprom.contents;
>> +    uint8_t nbanks = 0;
>> +    uint16_t density = 0;
>> +    int i;
>> +
>> +    /* work in terms of MB */
>> +    ram_size >>= 20;
>> +
>> +    while ((ram_size >= 4) && (nbanks <= 2)) {
>> +        int sz_log2 = MIN(31 - clz32(ram_size), 14);
>> +        nbanks++;
>> +        density |= 1 << (sz_log2 - 2);
>> +        ram_size -= 1 << sz_log2;
>> +    }
>> +
>> +    /* split to 2 banks if possible */
>> +    if ((nbanks == 1) && (density > 1)) {
>> +        nbanks++;
>> +        density >>= 1;
>> +    }
>> +
>> +    if (density & 0xff00) {
>> +        density = (density & 0xe0) | ((density >> 8) & 0x1f);
>> +        type = DDR2;
>> +    } else if (!(density & 0x1f)) {
>> +        type = DDR2;
>> +    } else {
>> +        type = SDR;
>> +    }
>> +
>> +    if (ram_size) {
>> +        fprintf(stderr, "Warning: SPD cannot represent final %dMB"
>> +                " of SDRAM\n", (int)ram_size);
>> +    }
>> +
>> +    /* fill in SPD memory information */
>> +    spd[2] = type;
>> +    spd[5] = nbanks;
>> +    spd[31] = density;
>> +#ifdef DEBUG_SDRAM
>> +    printf("SPD: nbanks %d density %d\n", nbanks, density);
>> +#endif
>> +    /* XXX: this is totally random */
>> +    spd[9] = 0x10; /* CAS tcyc */
>> +    spd[18] = 0x20; /* CAS bit */
>> +    spd[23] = 0x10; /* CAS tcyc */
>> +    spd[25] = 0x10; /* CAS tcyc */
>> +
>> +    /* checksum */
>> +    spd[63] = 0;
>> +    for (i = 0; i < 63; i++) {
>> +        spd[63] += spd[i];
>> +    }
>> +
>> +    /* copy for SMBUS */
>> +    memcpy(eeprom, spd, sizeof(spd_eeprom.contents));
>> +}
>> +
>> +static void generate_eeprom_serial(uint8_t *eeprom)
>> +{
>> +    int i, pos = 0;
>> +    uint8_t mac[6] = { 0x00 };
>> +    uint8_t sn[5] = { 0x01, 0x23, 0x45, 0x67, 0x89 };
>> +
>> +    /* version */
>> +    eeprom[pos++] = 0x01;
>> +
>> +    /* count */
>> +    eeprom[pos++] = 0x02;
>> +
>> +    /* MAC address */
>> +    eeprom[pos++] = 0x01; /* MAC */
>> +    eeprom[pos++] = 0x06; /* length */
>> +    memcpy(&eeprom[pos], mac, sizeof(mac));
>> +    pos += sizeof(mac);
>> +
>> +    /* serial number */
>> +    eeprom[pos++] = 0x02; /* serial */
>> +    eeprom[pos++] = 0x05; /* length */
>> +    memcpy(&eeprom[pos], sn, sizeof(sn));
>> +    pos += sizeof(sn);
>> +
>> +    /* checksum */
>> +    eeprom[pos] = 0;
>> +    for (i = 0; i < pos; i++) {
>> +        eeprom[pos] += eeprom[i];
>> +    }
>> +}
>> +
>> +/*****************************************************************************/
>> +
>> +static int sam460ex_load_uboot(void)
>> +{
>> +    DriveInfo *dinfo;
>> +    BlockBackend *blk = NULL;
>> +    hwaddr base = FLASH_BASE | ((hwaddr)FLASH_BASE_H << 32);
>> +    long bios_size = FLASH_SIZE;
>> +    int fl_sectors;
>> +
>> +    dinfo = drive_get(IF_PFLASH, 0, 0);
>> +    if (dinfo) {
>> +        blk = blk_by_legacy_dinfo(dinfo);
>> +        bios_size = blk_getlength(blk);
>> +    }
>> +    fl_sectors = (bios_size + 65535) >> 16;
>> +
>> +    if (!pflash_cfi01_register(base, NULL, "sam460ex.flash", bios_size,
>> +                               blk, (64 * 1024), fl_sectors,
>> +                               1, 0x89, 0x18, 0x0000, 0x0, 1)) {
>> +        fprintf(stderr, "qemu: Error registering flash memory.\n");
>
> Use error_report() instead, please.
>
>> +        /* XXX: return an error instead? */
>> +        exit(1);
>> +    }
>> +
>> +    if (!blk) {
>> +        /*fprintf(stderr, "No flash image given with the 'pflash' parameter,"
>> +                " using default u-boot image\n");*/
>> +        base = UBOOT_LOAD_BASE | ((hwaddr)FLASH_BASE_H << 32);
>> +        rom_add_file_fixed(UBOOT_FILENAME, base, -1);
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +static int sam460ex_load_device_tree(hwaddr addr,
>> +                                     uint32_t ramsize,
>> +                                     hwaddr initrd_base,
>> +                                     hwaddr initrd_size,
>> +                                     const char *kernel_cmdline)
>> +{
>> +    int ret = -1;
>> +    uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) };
>> +    char *filename;
>> +    int fdt_size;
>> +    void *fdt;
>> +    uint32_t tb_freq = 400000000;
>> +    uint32_t clock_freq = 400000000;
>> +
>> +    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
>> +    if (!filename) {
>> +        goto out;
>> +    }
>> +    fdt = load_device_tree(filename, &fdt_size);
>> +    g_free(filename);
>> +    if (fdt == NULL) {
>> +        goto out;
>> +    }
>> +
>> +    /* Manipulate device tree in memory. */
>> +
>> +    ret = qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property,
>> +                               sizeof(mem_reg_property));
>> +    if (ret < 0) {
>> +        fprintf(stderr, "couldn't set /memory/reg\n");
>
> And in all these places.
>
>> +    }
>> +
>> +    /* default FDT doesn't have a /chosen node... */
>> +    qemu_fdt_add_subnode(fdt, "/chosen");
>> +
>> +    ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
>> +                                    initrd_base);
>> +    if (ret < 0) {
>> +        fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
>> +    }
>> +
>> +    ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
>> +                                    (initrd_base + initrd_size));
>> +    if (ret < 0) {
>> +        fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
>> +    }
>> +
>> +    ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
>> +                                      kernel_cmdline);
>> +    if (ret < 0) {
>> +        fprintf(stderr, "couldn't set /chosen/bootargs\n");
>> +    }
>> +
>> +    /* Copy data from the host device tree into the guest. Since the guest can
>> +     * directly access the timebase without host involvement, we must expose
>> +     * the correct frequencies. */
>> +    if (kvm_enabled()) {
>> +        tb_freq = kvmppc_get_tbfreq();
>> +        clock_freq = kvmppc_get_clockfreq();
>> +    }
>> +
>> +    qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency",
>> +                              clock_freq);
>> +    qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency",
>> +                              tb_freq);
>> +
>> +    rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
>> +    g_free(fdt);
>> +    ret = fdt_size;
>> +
>> +out:
>> +
>> +    return ret;
>> +}
>> +
>> +/* Create reset TLB entries for BookE, mapping only the flash memory.  */
>> +static void mmubooke_create_initial_mapping_uboot(CPUPPCState *env)
>> +{
>> +    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
>> +
>> +    /* on reset the flash is mapped by a shadow TLB,
>> +     * but since we don't implement them we need to use
>> +     * the same values U-Boot will use to avoid a fault.
>> +     */
>
> Usually the reset state of the MMU is handled in the cpu code rather
> than the board code.  Is there a specific reason you need it in the
> board code here?

I'm not sure, probably lack of a better place. The ppc440_bamboo board 
this is based on has it the same way in the board code. Maybe this could 
be cleaned up when someone wants to QOMify the SoC models sometimes.

>> +    tlb->attr = 0;
>> +    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
>> +    tlb->size = 0x10000000; /* up to 0xffffffff  */
>> +    tlb->EPN = 0xf0000000 & TARGET_PAGE_MASK;
>> +    tlb->RPN = (0xf0000000 & TARGET_PAGE_MASK) | 0x4;
>> +    tlb->PID = 0;
>> +}
>> +
>> +/* Create reset TLB entries for BookE, spanning the 32bit addr space.  */
>> +static void mmubooke_create_initial_mapping(CPUPPCState *env,
>> +                                     target_ulong va,
>> +                                     hwaddr pa)
>> +{
>> +    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
>> +
>> +    tlb->attr = 0;
>> +    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
>> +    tlb->size = 1 << 31; /* up to 0x80000000  */
>> +    tlb->EPN = va & TARGET_PAGE_MASK;
>> +    tlb->RPN = pa & TARGET_PAGE_MASK;
>> +    tlb->PID = 0;
>> +}
>> +
>> +static void main_cpu_reset(void *opaque)
>> +{
>> +    PowerPCCPU *cpu = opaque;
>> +    CPUPPCState *env = &cpu->env;
>> +    struct boot_info *bi = env->load_info;
>> +
>> +    cpu_reset(CPU(cpu));
>> +
>> +    /* either we have a kernel to boot or we jump to U-Boot */
>> +    if (bi->entry != UBOOT_ENTRY) {
>> +        env->gpr[1] = (16 << 20) - 8;
>> +        env->gpr[3] = FDT_ADDR;
>> +
>> +        fprintf(stderr, "cpu reset: kernel entry %x\n", bi->entry);
>
> These should be tracepoints rather than bare fprintf().
>
>> +        env->nip = bi->entry;
>> +
>> +        /* Create a mapping for the kernel.  */
>> +        mmubooke_create_initial_mapping(env, 0, 0);
>> +        env->gpr[6] = tswap32(EPAPR_MAGIC);
>
> I'm pretty sure the tswap can't be right here.  env->gpr is in host
> native order and I'd expect the constant to be as well.

I know nothing about this, maybe Francois remembers why it's there. But 
booting linux with -kernel works so it's probably either correct or does 
not matter.

>> +        env->gpr[7] = (16 << 20) - 8; /*bi->ima_size;*/
>
> So, entering the kernel directly can be useful, particularly during
> early development.  However, having both firmware and non-firmware
> entry paths can lead to confusing bugs if there's a subtle difference
> between the initial (to the kernel) states between the two paths.  For
> that reason, the usual preferred way to implement -kernel is to still
> run the usual firmware, but use some way of telling it to boot
> immediately into the supplied kernel.
>
> I won't object to merging it this way - just a wanrning that this may
> bite you in the future if you're not careful.

Warning taken, at this point until firmware cannot reliably boot things 
having another way to test is useful to have. In the future when booting 
via firmware works well we can figure out what to do with this.

>> +
>> +    } else {
>> +        env->nip = UBOOT_ENTRY;
>> +        mmubooke_create_initial_mapping_uboot(env);
>> +        fprintf(stderr, "cpu reset: U-Boot entry\n");
>
> Tracepoint.
>
>> +    }
>> +}
>> +
>> +static void sam460ex_init(MachineState *machine)
>> +{
>> +    MemoryRegion *address_space_mem = get_system_memory();
>> +    MemoryRegion *isa = g_new(MemoryRegion, 1);
>> +    MemoryRegion *ram_memories = g_new(MemoryRegion, SDRAM_NR_BANKS);
>> +    hwaddr ram_bases[SDRAM_NR_BANKS];
>> +    hwaddr ram_sizes[SDRAM_NR_BANKS];
>> +    MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1);
>> +    qemu_irq *irqs, *uic[4];
>> +    PCIBus *pci_bus;
>> +    PowerPCCPU *cpu;
>> +    CPUPPCState *env;
>> +    PPC4xxI2CState *i2c[2];
>> +    hwaddr entry = UBOOT_ENTRY;
>> +    hwaddr loadaddr = 0;
>> +    target_long initrd_size = 0;
>> +    DeviceState *dev;
>> +    SysBusDevice *sbdev;
>> +    int success;
>> +    int i;
>> +    struct boot_info *boot_info;
>> +    const size_t smbus_eeprom_size = 8 * 256;
>> +    uint8_t *smbus_eeprom_buf = g_malloc0(smbus_eeprom_size);
>> +
>> +    /* Setup CPU. */
>> +    if (machine->cpu_model == NULL) {
>> +        machine->cpu_model = "460EX";
>> +    }
>> +    cpu = cpu_ppc_init(machine->cpu_model);
>> +    if (cpu == NULL) {
>> +        fprintf(stderr, "Unable to initialize CPU!\n");
>> +        exit(1);
>> +    }
>> +    env = &cpu->env;
>> +
>> +    qemu_register_reset(main_cpu_reset, cpu);
>> +    boot_info = g_malloc0(sizeof(*boot_info));
>> +    env->load_info = boot_info;
>> +
>> +    ppc_booke_timers_init(cpu, 50000000, 0);
>> +    ppc_dcr_init(env, NULL, NULL);
>> +
>> +    /* PLB arbitrer */
>> +    ppc4xx_plb_init(env);
>> +
>> +    /* interrupt controllers */
>> +    irqs = g_malloc0(sizeof(*irqs) * PPCUIC_OUTPUT_NB);
>> +    irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
>> +    irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
>> +    uic[0] = ppcuic_init(env, irqs, 0x0C0, 0, 1);
>> +    uic[1] = ppcuic_init(env, &uic[0][30], 0x0D0, 0, 1);
>> +    uic[2] = ppcuic_init(env, &uic[0][10], 0x0E0, 0, 1);
>> +    uic[3] = ppcuic_init(env, &uic[0][16], 0x0F0, 0, 1);
>> +
>> +    /* SDRAM controller */
>> +    memset(ram_bases, 0, sizeof(ram_bases));
>> +    memset(ram_sizes, 0, sizeof(ram_sizes));
>> +    /* put all RAM on first bank because board has one slot
>> +     * and firmware only checks that */
>> +    machine->ram_size = ppc4xx_sdram_adjust(machine->ram_size,
>> +                                   1/*SDRAM_NR_BANKS*/,
>> +                                   ram_memories,
>> +                                   ram_bases, ram_sizes,
>> +                                   ppc460ex_sdram_bank_sizes);
>> +#ifdef DEBUG_SDRAM
>> +    printf("RAMSIZE %dMB\n", (int)(machine->ram_size / M_BYTE));
>> +#endif
>> +
>> +    /* XXX does 460EX have ECC interrupts? */
>> +    ppc440_sdram_init(env, SDRAM_NR_BANKS, ram_memories,
>> +                      ram_bases, ram_sizes, 1);
>> +
>> +    /* generate SPD EEPROM data */
>> +    for (i = 0; i < SDRAM_NR_BANKS; i++) {
>> +#ifdef DEBUG_SDRAM
>> +        printf("bank %d: %" HWADDR_PRIx "\n", i, ram_sizes[i]);
>> +#endif
>
> Tracepoint.
>
>> +        generate_eeprom_spd(&smbus_eeprom_buf[i * 256], ram_sizes[i]);
>> +    }
>> +    generate_eeprom_serial(&smbus_eeprom_buf[4 * 256]);
>> +    generate_eeprom_serial(&smbus_eeprom_buf[6 * 256]);
>> +
>> +    /* IIC controllers */
>> +    dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700, uic[0][2]);
>> +    i2c[0] = PPC4xx_I2C(dev);
>> +    object_property_set_bool(OBJECT(dev), true, "realized", NULL);
>> +    smbus_eeprom_init(i2c[0]->bus, 8, smbus_eeprom_buf, smbus_eeprom_size);
>> +    g_free(smbus_eeprom_buf);
>> +
>> +    dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600800, uic[0][3]);
>> +    i2c[1] = PPC4xx_I2C(dev);
>> +
>> +    /* External bus controller */
>> +    ppc405_ebc_init(env);
>> +
>> +    /* CPR */
>> +    ppc4xx_cpr_init(env);
>> +
>> +    /* PLB to AHB bridge */
>> +    ppc4xx_ahb_init(env);
>> +
>> +    /* System DCRs */
>> +    ppc4xx_sdr_init(env);
>> +
>> +    /* MAL */
>> +    ppc4xx_mal_init(env, 4, 16, &uic[2][3]);
>> +
>> +    /* 256K of L2 cache as memory */
>> +    ppc4xx_l2sram_init(env);
>
> Seems like a lot of this peripheral setup should be handled by a SoC
> helper function, since it's not really board specific (I'm guessing).
> I'm ok with that being a later clean up though.

I know, the ppc405 has an init function and I considered moving some of 
this to a similar function but I've left it here for now for simplicity 
until it's decided what's the best way to clean this up.

>> +    /* FIXME: remove this after fixing l2sram mapping in ppc440_uc.c? */
>> +    memory_region_init_ram(l2cache_ram, NULL, "ppc440.l2cache_ram", 256 << 10,
>> +                           &error_abort);
>> +    memory_region_add_subregion(address_space_mem, 0x400000000LL, l2cache_ram);
>> +
>> +    /* USB */
>> +    sysbus_create_simple(TYPE_PPC4xx_EHCI, 0x4bffd0400, uic[2][29]);
>> +    dev = qdev_create(NULL, "sysbus-ohci");
>> +    qdev_prop_set_string(dev, "masterbus", "usb-bus.0");
>> +    qdev_prop_set_uint32(dev, "num-ports", 6);
>> +    qdev_init_nofail(dev);
>> +    sbdev = SYS_BUS_DEVICE(dev);
>> +    sysbus_mmio_map(sbdev, 0, 0x4bffd0000);
>> +    sysbus_connect_irq(sbdev, 0, uic[2][30]);
>> +    usb_create_simple(usb_bus_find(-1), "usb-kbd");
>> +    usb_create_simple(usb_bus_find(-1), "usb-mouse");
>> +
>> +    /* PCI bus */
>> +    ppc460ex_pcie_init(env);
>> +    /*XXX: FIXME: is this correct? */
>> +    dev = sysbus_create_varargs("ppc440-pcix-host", 0xc0ec00000,
>> +                                uic[1][0], uic[1][20], uic[1][21], uic[1][22],
>> +                                NULL);
>> +    pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
>> +    if (!pci_bus) {
>> +        fprintf(stderr, "couldn't create PCI controller!\n");
>> +        exit(1);
>> +    }
>> +    memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(),
>> +                             0, 0x10000);
>> +    memory_region_add_subregion(get_system_memory(), 0xc08000000, isa);
>
> Does it really make sense to just embed the ISA IO space here, rather
> than actually instanting a PCI<->ISA bridge?

I'm not sure if this is correct but I don't know how it's handled on real 
hardware. The board does not have ISA and I don't think it has a bridge 
but the IO space appears at this location according to the datasheet (In 
System Memory Address Map it's listed as PCI I/O 0xc08000000-0xc0800ffff) 
and clients expect PCI card's io registers to be accessible here. If 
anyone knows how it's done on real hardware and if there's a better way to 
model this please let me know.

>> +    /* PCI devices */
>> +    pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "sm501");
>> +    /* SoC has a single SATA port but we don't emulate that yet
>> +     * However, firmware and usual clients have driver for SiI311x
>> +     * so add one for convenience by default */
>> +    pci_create_simple(pci_bus, -1, "sii3112");
>
> You should probably not create this when started with -nodefaults.

We don't emulate the on-board SATA port of the SoC and without this 
there's no other way to connect disks (maybe over USB, but firmware has a 
bug which prevents that too even on real hardware AFAIK, I've backported a 
fix which made booting from USB work but that broke keyboard) so while 
this is an external card it's pretty much unusable without this so it's 
added by default.

>> +    /* SoC has 4 UARTs
>> +     * but board has only one wired and two are present in fdt */
>> +    if (serial_hds[0] != NULL) {
>> +        serial_mm_init(address_space_mem, 0x4ef600300, 0, uic[1][1],
>> +                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
>> +                       DEVICE_BIG_ENDIAN);
>> +    }
>> +    if (serial_hds[1] != NULL) {
>> +        serial_mm_init(address_space_mem, 0x4ef600400, 0, uic[0][1],
>> +                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
>> +                       DEVICE_BIG_ENDIAN);
>> +    }
>> +
>> +    /* Load U-Boot image. */
>> +    if (!machine->kernel_filename) {
>> +        success = sam460ex_load_uboot();
>> +        if (success < 0) {
>> +            fprintf(stderr, "qemu: could not load firmware\n");
>> +            exit(1);
>> +        }
>> +    }
>> +
>> +    /* Load kernel. */
>> +    if (machine->kernel_filename) {
>> +        success = load_uimage(machine->kernel_filename, &entry, &loadaddr, NULL,
>> +            NULL, NULL);
>> +        fprintf(stderr, "load_uimage: %d\n", success);
>
> tracepoint
>
>> +        if (success < 0) {
>> +            uint64_t elf_entry, elf_lowaddr;
>> +
>> +            success = load_elf(machine->kernel_filename, NULL, NULL, &elf_entry,
>> +                               &elf_lowaddr, NULL, 1, PPC_ELF_MACHINE, 0, 0);
>> +            fprintf(stderr, "load_elf: %d\n", success);
>
> tracepoint
>
>> +            entry = elf_entry;
>> +            loadaddr = elf_lowaddr;
>> +        }
>> +        /* XXX try again as binary */
>> +        if (success < 0) {
>> +            fprintf(stderr, "qemu: could not load kernel '%s'\n",
>> +                    machine->kernel_filename);
>
> error_report().
>
>> +            exit(1);
>> +        }
>> +    }
>> +
>> +    /* Load initrd. */
>> +    if (machine->initrd_filename) {
>> +        initrd_size = load_image_targphys(machine->initrd_filename,
>> +                                          RAMDISK_ADDR,
>> +                                          machine->ram_size - RAMDISK_ADDR);
>> +        fprintf(stderr, "load_image: %d\n", initrd_size);
>> +        if (initrd_size < 0) {
>> +            fprintf(stderr, "qemu: could not load ram disk '%s' at %x\n",
>> +                    machine->initrd_filename, RAMDISK_ADDR);
>> +            exit(1);
>> +        }
>> +    }
>> +
>> +    /* If we're loading a kernel directly, we must load the device tree too. */
>> +    if (machine->kernel_filename) {
>> +        int dt_size;
>> +
>> +        dt_size = sam460ex_load_device_tree(FDT_ADDR, machine->ram_size,
>> +                                    RAMDISK_ADDR, initrd_size,
>> +                                    machine->kernel_cmdline);
>> +        if (dt_size < 0) {
>> +            fprintf(stderr, "couldn't load device tree\n");
>> +            exit(1);
>> +        }
>> +
>> +        boot_info->dt_base = FDT_ADDR;
>> +        boot_info->dt_size = dt_size;
>> +    }
>> +
>> +    boot_info->entry = entry;
>> +}
>> +
>> +static void sam460ex_machine_init(MachineClass *mc)
>> +{
>> +    mc->desc = "aCube Sam460ex";
>> +    mc->init = sam460ex_init;
>> +    mc->default_ram_size = 512 * M_BYTE;
>> +}
>> +
>> +DEFINE_MACHINE("sam460ex", sam460ex_machine_init)
>
>

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 15/15] ppc: Add aCube Sam460ex board
  2017-08-23 11:12     ` BALATON Zoltan
@ 2017-08-23 11:43       ` François Revol
  2017-08-23 12:47         ` BALATON Zoltan
  2017-08-24  2:51         ` David Gibson
  2017-08-24  2:44       ` David Gibson
  1 sibling, 2 replies; 66+ messages in thread
From: François Revol @ 2017-08-23 11:43 UTC (permalink / raw)
  To: BALATON Zoltan, David Gibson; +Cc: qemu-devel, qemu-ppc, Alexander Graf

Le 23/08/2017 à 13:12, BALATON Zoltan a écrit :
>> What's the connection with mips_malta?
> 
> The board's firmware wants to see SPD EEPROMs of the connected memory
> while initialising the memory controller. This is why we need to
> implement SDRAM controller, I2C and SPD EEPROMs. MIPS malta board had
> already SPD EEPROM implementation so this is based on that. The comment
> just indicates where this code comes from.

Indeed, and I copy-pasted from elsewhere for this.

>>> +        fprintf(stderr, "qemu: Error registering flash memory.\n");
>>
>> Use error_report() instead, please.

I guess this didn't exist back when I started writing it...

>>> +/* Create reset TLB entries for BookE, mapping only the flash
>>> memory.  */
>>> +static void mmubooke_create_initial_mapping_uboot(CPUPPCState *env)
>>> +{
>>> +    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
>>> +
>>> +    /* on reset the flash is mapped by a shadow TLB,
>>> +     * but since we don't implement them we need to use
>>> +     * the same values U-Boot will use to avoid a fault.
>>> +     */
>>
>> Usually the reset state of the MMU is handled in the cpu code rather
>> than the board code.  Is there a specific reason you need it in the
>> board code here?
> 
> I'm not sure, probably lack of a better place. The ppc440_bamboo board
> this is based on has it the same way in the board code. Maybe this could
> be cleaned up when someone wants to QOMify the SoC models sometimes.

Thing is, the code allows both booting with U-Boot and with a kernel
directly, and the MMU mapping differ in those cases.

Maybe the CPU reset should use the U-Boot setup and the kernel boot
would just overwrite it?

>>> +        env->nip = bi->entry;
>>> +
>>> +        /* Create a mapping for the kernel.  */
>>> +        mmubooke_create_initial_mapping(env, 0, 0);
>>> +        env->gpr[6] = tswap32(EPAPR_MAGIC);
>>
>> I'm pretty sure the tswap can't be right here.  env->gpr is in host
>> native order and I'd expect the constant to be as well.
> 
> I know nothing about this, maybe Francois remembers why it's there. But
> booting linux with -kernel works so it's probably either correct or does
> not matter.

Absolutely no idea. It seems to be there from the first commit in my own
history here.

I don't recall testing booting linux at all though.
Linux does check the magic, so it'd be weird if it booted:

https://github.com/torvalds/linux/blob/master/arch/powerpc/boot/epapr.c

But maybe it got added later than the version you tested?

At least my current Haiku port ignores the magic for now.

>>> +        env->gpr[7] = (16 << 20) - 8; /*bi->ima_size;*/
>>
>> So, entering the kernel directly can be useful, particularly during
>> early development.  However, having both firmware and non-firmware
>> entry paths can lead to confusing bugs if there's a subtle difference
>> between the initial (to the kernel) states between the two paths.  For
>> that reason, the usual preferred way to implement -kernel is to still
>> run the usual firmware, but use some way of telling it to boot
>> immediately into the supplied kernel.
>>
>> I won't object to merging it this way - just a wanrning that this may
>> bite you in the future if you're not careful.
> 
> Warning taken, at this point until firmware cannot reliably boot things
> having another way to test is useful to have. In the future when booting
> via firmware works well we can figure out what to do with this.

Possibly we could dig the U-Boot environment...

>>> +    memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(),
>>> +                             0, 0x10000);
>>> +    memory_region_add_subregion(get_system_memory(), 0xc08000000, isa);
>>
>> Does it really make sense to just embed the ISA IO space here, rather
>> than actually instanting a PCI<->ISA bridge?
> 
> I'm not sure if this is correct but I don't know how it's handled on
> real hardware. The board does not have ISA and I don't think it has a
> bridge but the IO space appears at this location according to the
> datasheet (In System Memory Address Map it's listed as PCI I/O
> 0xc08000000-0xc0800ffff) and clients expect PCI card's io registers to
> be accessible here. If anyone knows how it's done on real hardware and
> if there's a better way to model this please let me know.

Indeed it's the PCI I/O space, maybe it's just copy-paste error.

As for how to declare it, keep in mind this code is years old and I
fixed it several times when compilation broke, without really reading
the documentation (actually, do we have proper documentation for the
internal API?), and it kept changing over the years.

> 
>>> +    /* PCI devices */
>>> +    pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "sm501");
>>> +    /* SoC has a single SATA port but we don't emulate that yet
>>> +     * However, firmware and usual clients have driver for SiI311x
>>> +     * so add one for convenience by default */
>>> +    pci_create_simple(pci_bus, -1, "sii3112");
>>
>> You should probably not create this when started with -nodefaults.
> 
> We don't emulate the on-board SATA port of the SoC and without this
> there's no other way to connect disks (maybe over USB, but firmware has
> a bug which prevents that too even on real hardware AFAIK, I've
> backported a fix which made booting from USB work but that broke
> keyboard) so while this is an external card it's pretty much unusable
> without this so it's added by default.

Maybe add a /*TODO*/ then?

François.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 15/15] ppc: Add aCube Sam460ex board
  2017-08-23 11:43       ` François Revol
@ 2017-08-23 12:47         ` BALATON Zoltan
  2017-08-23 13:33           ` [Qemu-devel] [Qemu-ppc] " luigi burdo
  2017-08-24  2:54           ` [Qemu-devel] " David Gibson
  2017-08-24  2:51         ` David Gibson
  1 sibling, 2 replies; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-23 12:47 UTC (permalink / raw)
  To: François Revol; +Cc: David Gibson, qemu-devel, qemu-ppc, Alexander Graf

On Wed, 23 Aug 2017, François Revol wrote:
> Le 23/08/2017 à 13:12, BALATON Zoltan a écrit :
>>> What's the connection with mips_malta?
>>
>> The board's firmware wants to see SPD EEPROMs of the connected memory
>> while initialising the memory controller. This is why we need to
>> implement SDRAM controller, I2C and SPD EEPROMs. MIPS malta board had
>> already SPD EEPROM implementation so this is based on that. The comment
>> just indicates where this code comes from.
>
> Indeed, and I copy-pasted from elsewhere for this.
>
>>>> +        fprintf(stderr, "qemu: Error registering flash memory.\n");
>>>
>>> Use error_report() instead, please.
>
> I guess this didn't exist back when I started writing it...

No problem, I can take care of these.

>>>> +/* Create reset TLB entries for BookE, mapping only the flash
>>>> memory.  */
>>>> +static void mmubooke_create_initial_mapping_uboot(CPUPPCState *env)
>>>> +{
>>>> +    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
>>>> +
>>>> +    /* on reset the flash is mapped by a shadow TLB,
>>>> +     * but since we don't implement them we need to use
>>>> +     * the same values U-Boot will use to avoid a fault.
>>>> +     */
>>>
>>> Usually the reset state of the MMU is handled in the cpu code rather
>>> than the board code.  Is there a specific reason you need it in the
>>> board code here?
>>
>> I'm not sure, probably lack of a better place. The ppc440_bamboo board
>> this is based on has it the same way in the board code. Maybe this could
>> be cleaned up when someone wants to QOMify the SoC models sometimes.
>
> Thing is, the code allows both booting with U-Boot and with a kernel
> directly, and the MMU mapping differ in those cases.
>
> Maybe the CPU reset should use the U-Boot setup and the kernel boot
> would just overwrite it?
>
>>>> +        env->nip = bi->entry;
>>>> +
>>>> +        /* Create a mapping for the kernel.  */
>>>> +        mmubooke_create_initial_mapping(env, 0, 0);
>>>> +        env->gpr[6] = tswap32(EPAPR_MAGIC);
>>>
>>> I'm pretty sure the tswap can't be right here.  env->gpr is in host
>>> native order and I'd expect the constant to be as well.
>>
>> I know nothing about this, maybe Francois remembers why it's there. But
>> booting linux with -kernel works so it's probably either correct or does
>> not matter.
>
> Absolutely no idea. It seems to be there from the first commit in my own
> history here.
>
> I don't recall testing booting linux at all though.
> Linux does check the magic, so it'd be weird if it booted:
>
> https://github.com/torvalds/linux/blob/master/arch/powerpc/boot/epapr.c

Is this code used on Sam460 at all? Is U-Boot ePAPR compliant firmware? 
Isn't that only needed on OpenFirmware?

> But maybe it got added later than the version you tested?

I've tried some of these: 
http://www.supertuxkart-amiga.de/amiga/sam.html#downloads
which also have kernel 4.5 so that's fairly recent. These kernels are 
"u-boot legacy uImage" so maybe they don't need ePAPR magic? Are there 
some docs on what the kernel expects on this board or it has to be dug out 
from U-Boot?

> At least my current Haiku port ignores the magic for now.
>
>>>> +        env->gpr[7] = (16 << 20) - 8; /*bi->ima_size;*/
>>>
>>> So, entering the kernel directly can be useful, particularly during
>>> early development.  However, having both firmware and non-firmware
>>> entry paths can lead to confusing bugs if there's a subtle difference
>>> between the initial (to the kernel) states between the two paths.  For
>>> that reason, the usual preferred way to implement -kernel is to still
>>> run the usual firmware, but use some way of telling it to boot
>>> immediately into the supplied kernel.
>>>
>>> I won't object to merging it this way - just a wanrning that this may
>>> bite you in the future if you're not careful.
>>
>> Warning taken, at this point until firmware cannot reliably boot things
>> having another way to test is useful to have. In the future when booting
>> via firmware works well we can figure out what to do with this.
>
> Possibly we could dig the U-Boot environment...
>
>>>> +    memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(),
>>>> +                             0, 0x10000);
>>>> +    memory_region_add_subregion(get_system_memory(), 0xc08000000, isa);
>>>
>>> Does it really make sense to just embed the ISA IO space here, rather
>>> than actually instanting a PCI<->ISA bridge?
>>
>> I'm not sure if this is correct but I don't know how it's handled on
>> real hardware. The board does not have ISA and I don't think it has a
>> bridge but the IO space appears at this location according to the
>> datasheet (In System Memory Address Map it's listed as PCI I/O
>> 0xc08000000-0xc0800ffff) and clients expect PCI card's io registers to
>> be accessible here. If anyone knows how it's done on real hardware and
>> if there's a better way to model this please let me know.
>
> Indeed it's the PCI I/O space, maybe it's just copy-paste error.
>
> As for how to declare it, keep in mind this code is years old and I
> fixed it several times when compilation broke, without really reading
> the documentation (actually, do we have proper documentation for the
> internal API?), and it kept changing over the years.

And I've also changed it while cleaning up and getting it to work with 
some clients. This particular mapping was at the wrong place in your first 
commits then got removed but I found it's needed but at a different 
address so I've added it again with the fixed address.

>>>> +    /* PCI devices */
>>>> +    pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "sm501");
>>>> +    /* SoC has a single SATA port but we don't emulate that yet
>>>> +     * However, firmware and usual clients have driver for SiI311x
>>>> +     * so add one for convenience by default */
>>>> +    pci_create_simple(pci_bus, -1, "sii3112");
>>>
>>> You should probably not create this when started with -nodefaults.
>>
>> We don't emulate the on-board SATA port of the SoC and without this
>> there's no other way to connect disks (maybe over USB, but firmware has
>> a bug which prevents that too even on real hardware AFAIK, I've
>> backported a fix which made booting from USB work but that broke
>> keyboard) so while this is an external card it's pretty much unusable
>> without this so it's added by default.
>
> Maybe add a /*TODO*/ then?

I don't indent to implement that. Seems to be too complex and unnecessary 
when we have sii3112 (unless you want to test drivers for it on QEMU). I'd 
rather see an implementation of the network interfaces that seems to be 
more useful to spend time on than another SATA controller. So I chose to 
use the sii3112 by default.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH 15/15] ppc: Add aCube Sam460ex board
  2017-08-23 12:47         ` BALATON Zoltan
@ 2017-08-23 13:33           ` luigi burdo
  2017-08-24  2:54           ` [Qemu-devel] " David Gibson
  1 sibling, 0 replies; 66+ messages in thread
From: luigi burdo @ 2017-08-23 13:33 UTC (permalink / raw)
  To: BALATON Zoltan, François Revol; +Cc: qemu-ppc, qemu-devel, David Gibson

Hi Zoltan,

>So I chose to

>use the sii3112 by default.
right chooice because internal sata on sam460 had issue and wont boot os4,morphos... only the cdrom was booting if i remember  good from internal sata 0.
personally when i had a Sam460ex i was using a sii3114 or internal micro sd for boot... the sii was perfect compatible with sam uboot.

Thanks
Luigi

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 04/15] ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs
  2017-08-21  4:18   ` David Gibson
@ 2017-08-23 13:57     ` Gerd Hoffmann
  0 siblings, 0 replies; 66+ messages in thread
From: Gerd Hoffmann @ 2017-08-23 13:57 UTC (permalink / raw)
  To: David Gibson, BALATON Zoltan
  Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

On Mon, 2017-08-21 at 14:18 +1000, David Gibson wrote:
> On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
> > Some PPC SoCs have an EHCI with OHCI companion USB controller. Add
> > a
> > new type for this similar to types used for other embedded SoCs.
> > 
> > Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> 
> Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
> 
> Gerd, again, if it's convenient to you, I can queue this for 2.11.

Yes please.  I think merging this way it is easier, patches later in
this series probably depend on these two usb patches.

Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>

cheers,
  Gerd

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 03/15] ohci: Allow sysbus version to be used as a companion
  2017-08-21  4:10   ` David Gibson
@ 2017-08-23 13:58     ` Gerd Hoffmann
  0 siblings, 0 replies; 66+ messages in thread
From: Gerd Hoffmann @ 2017-08-23 13:58 UTC (permalink / raw)
  To: David Gibson, BALATON Zoltan
  Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

On Mon, 2017-08-21 at 14:10 +1000, David Gibson wrote:
> On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
> 1;4803;0c> Some PPC SoCs have an EHCI with OHCI companion USB
> controller. To
> > emulate this allow the sysbus version of OHCI to be used as a
> > companion.
> > 
> > Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> 
> Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
> 
> Gerd,  if you're happy with this, I can queue it for 2.11.  Let me
> know what you'd prefer.

Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>

cheers,
  Gerd

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 09/15] hw/ide: Emulate SiI3112 SATA controller
  2017-08-23  0:52         ` David Gibson
@ 2017-08-23 16:16           ` John Snow
  0 siblings, 0 replies; 66+ messages in thread
From: John Snow @ 2017-08-23 16:16 UTC (permalink / raw)
  To: David Gibson; +Cc: Alexander Graf, Francois Revol, qemu-ppc, qemu-devel



On 08/22/2017 08:52 PM, David Gibson wrote:
> Jon, do you want me to queue this driver in my tree (for 2.11,
> obviously), or do you want to take it through another tree?

If you're queuing up the rest of it, feel free to take this one, too.

Thanks!

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 13/15] ppc4xx: Add more PLB registers
  2017-08-23 10:16     ` BALATON Zoltan
@ 2017-08-24  2:35       ` David Gibson
  2017-08-24 20:28         ` BALATON Zoltan
  0 siblings, 1 reply; 66+ messages in thread
From: David Gibson @ 2017-08-24  2:35 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 3402 bytes --]

On Wed, Aug 23, 2017 at 12:16:24PM +0200, BALATON Zoltan wrote:
> On Wed, 23 Aug 2017, David Gibson wrote:
> > On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
> > > These registers are present in 440 SoCs (and maybe in others too) and
> > > U-Boot accesses them when printing register info. We don't emulate
> > > these but add them to avoid crashing when they are read or written.
> > > 
> > > Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> > 
> > I'm ok with stub implementation, but I'm a bit uncomfortable with
> > registering these DCRs unconditionally rather than just on the chips
> > that actually implement them.
> 
> Problem is that I don't know which chips have these. I can only try to find
> out from the U-Boot sources where a comment says these are common registers
> for all SoCs (in u-boot/arch/powerpc/include/asm/ppc4xx.h:
> 
> http://git.denx.de/?p=u-boot.git;a=blob;f=arch/powerpc/include/asm/ppc4xx.h;h=45ff5dbacd9243e83bb2f6551e2dd64a7e544bf5;hb=e2351d5cf1e97408b4c52bafeaa85e0ca85c920c
> 
> while looking for this I've just noticed that u-boot has removed ppc440
> support just before 2017.07-rc3 so this is the last version that still has
> these files). So if that's true it should be OK for 405 too.

Ok, just to make sure I'm understanding correctly are you saying:

1) You suspect these registers were actually on all versions of the
   device, they just weren't implemented until now.

or

2) The registers are definitely on only some versions of the device,
   but you're not sure which ones

> 
> > > ---
> > >  hw/ppc/ppc405_uc.c | 12 +++++++++---
> > >  1 file changed, 9 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
> > > index e621d0a..8e58065 100644
> > > --- a/hw/ppc/ppc405_uc.c
> > > +++ b/hw/ppc/ppc405_uc.c
> > > @@ -105,9 +105,12 @@ ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
> > >  /*****************************************************************************/
> > >  /* Peripheral local bus arbitrer */
> > >  enum {
> > > -    PLB0_BESR = 0x084,
> > > -    PLB0_BEAR = 0x086,
> > > -    PLB0_ACR  = 0x087,
> > > +    PLB3A0_ACR = 0x077,
> > > +    PLB4A0_ACR = 0x081,
> > > +    PLB0_BESR  = 0x084,
> > > +    PLB0_BEAR  = 0x086,
> > > +    PLB0_ACR   = 0x087,
> > > +    PLB4A1_ACR = 0x089,
> > >  };
> > > 
> > >  typedef struct ppc4xx_plb_t ppc4xx_plb_t;
> > > @@ -179,9 +182,12 @@ void ppc4xx_plb_init(CPUPPCState *env)
> > >      ppc4xx_plb_t *plb;
> > > 
> > >      plb = g_malloc0(sizeof(ppc4xx_plb_t));
> > > +    ppc_dcr_register(env, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
> > > +    ppc_dcr_register(env, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
> > >      ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
> > >      ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
> > >      ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
> > > +    ppc_dcr_register(env, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb);
> > >      qemu_register_reset(ppc4xx_plb_reset, plb);
> > >  }
> > > 
> > 
> > 
> 

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 15/15] ppc: Add aCube Sam460ex board
  2017-08-23 11:12     ` BALATON Zoltan
  2017-08-23 11:43       ` François Revol
@ 2017-08-24  2:44       ` David Gibson
  2017-08-24 21:37         ` BALATON Zoltan
  1 sibling, 1 reply; 66+ messages in thread
From: David Gibson @ 2017-08-24  2:44 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 9101 bytes --]

On Wed, Aug 23, 2017 at 01:12:06PM +0200, BALATON Zoltan wrote:
> On Wed, 23 Aug 2017, David Gibson wrote:
> > On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
> > > Add emulation of aCube Sam460ex board based on AMCC 460EX embedded SoC.
> > > This is not a full implementation yet with a lot of components still
> > > missing but enough to start a Linux kernel and the U-Boot firmware.
> > > 
> > > Signed-off-by: François Revol <revol@free.fr>
> > > Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> > 
> > As usual, only fairly superficial review here.
> > 
> > > ---
> > >  default-configs/ppcemb-softmmu.mak |   3 +
> > >  hw/ppc/Makefile.objs               |   2 +
> > >  hw/ppc/sam460ex.c                  | 611 +++++++++++++++++++++++++++++++++++++
> > >  3 files changed, 616 insertions(+)
> > >  create mode 100644 hw/ppc/sam460ex.c
> > > 
> > > diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
> > > index 635923a..90b42f0 100644
> > > --- a/default-configs/ppcemb-softmmu.mak
> > > +++ b/default-configs/ppcemb-softmmu.mak
> [...]
> > > +/*****************************************************************************/
> > > +/* SPD eeprom content from mips_malta.c */
> > 
> > What's the connection with mips_malta?
> 
> The board's firmware wants to see SPD EEPROMs of the connected memory while
> initialising the memory controller. This is why we need to implement SDRAM
> controller, I2C and SPD EEPROMs. MIPS malta board had already SPD EEPROM
> implementation so this is based on that. The comment just indicates where
> this code comes from.

Ok.

[snip]
> > > +        env->nip = bi->entry;
> > > +
> > > +        /* Create a mapping for the kernel.  */
> > > +        mmubooke_create_initial_mapping(env, 0, 0);
> > > +        env->gpr[6] = tswap32(EPAPR_MAGIC);
> > 
> > I'm pretty sure the tswap can't be right here.  env->gpr is in host
> > native order and I'd expect the constant to be as well.
> 
> I know nothing about this, maybe Francois remembers why it's there. But
> booting linux with -kernel works so it's probably either correct or does not
> matter.

Have you attempted it on both BE and LE hosts though?

> 
> > > +        env->gpr[7] = (16 << 20) - 8; /*bi->ima_size;*/
> > 
> > So, entering the kernel directly can be useful, particularly during
> > early development.  However, having both firmware and non-firmware
> > entry paths can lead to confusing bugs if there's a subtle difference
> > between the initial (to the kernel) states between the two paths.  For
> > that reason, the usual preferred way to implement -kernel is to still
> > run the usual firmware, but use some way of telling it to boot
> > immediately into the supplied kernel.
> > 
> > I won't object to merging it this way - just a wanrning that this may
> > bite you in the future if you're not careful.
> 
> Warning taken, at this point until firmware cannot reliably boot things
> having another way to test is useful to have. In the future when booting via
> firmware works well we can figure out what to do with this.

Fair enough.

[snip]
> > > +        generate_eeprom_spd(&smbus_eeprom_buf[i * 256], ram_sizes[i]);
> > > +    }
> > > +    generate_eeprom_serial(&smbus_eeprom_buf[4 * 256]);
> > > +    generate_eeprom_serial(&smbus_eeprom_buf[6 * 256]);
> > > +
> > > +    /* IIC controllers */
> > > +    dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700, uic[0][2]);
> > > +    i2c[0] = PPC4xx_I2C(dev);
> > > +    object_property_set_bool(OBJECT(dev), true, "realized", NULL);
> > > +    smbus_eeprom_init(i2c[0]->bus, 8, smbus_eeprom_buf, smbus_eeprom_size);
> > > +    g_free(smbus_eeprom_buf);
> > > +
> > > +    dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600800, uic[0][3]);
> > > +    i2c[1] = PPC4xx_I2C(dev);
> > > +
> > > +    /* External bus controller */
> > > +    ppc405_ebc_init(env);
> > > +
> > > +    /* CPR */
> > > +    ppc4xx_cpr_init(env);
> > > +
> > > +    /* PLB to AHB bridge */
> > > +    ppc4xx_ahb_init(env);
> > > +
> > > +    /* System DCRs */
> > > +    ppc4xx_sdr_init(env);
> > > +
> > > +    /* MAL */
> > > +    ppc4xx_mal_init(env, 4, 16, &uic[2][3]);
> > > +
> > > +    /* 256K of L2 cache as memory */
> > > +    ppc4xx_l2sram_init(env);
> > 
> > Seems like a lot of this peripheral setup should be handled by a SoC
> > helper function, since it's not really board specific (I'm guessing).
> > I'm ok with that being a later clean up though.
> 
> I know, the ppc405 has an init function and I considered moving some of this
> to a similar function but I've left it here for now for simplicity until
> it's decided what's the best way to clean this up.

Ok, seems reasonable.

> > > +    /* FIXME: remove this after fixing l2sram mapping in ppc440_uc.c? */
> > > +    memory_region_init_ram(l2cache_ram, NULL, "ppc440.l2cache_ram", 256 << 10,
> > > +                           &error_abort);
> > > +    memory_region_add_subregion(address_space_mem, 0x400000000LL, l2cache_ram);
> > > +
> > > +    /* USB */
> > > +    sysbus_create_simple(TYPE_PPC4xx_EHCI, 0x4bffd0400, uic[2][29]);
> > > +    dev = qdev_create(NULL, "sysbus-ohci");
> > > +    qdev_prop_set_string(dev, "masterbus", "usb-bus.0");
> > > +    qdev_prop_set_uint32(dev, "num-ports", 6);
> > > +    qdev_init_nofail(dev);
> > > +    sbdev = SYS_BUS_DEVICE(dev);
> > > +    sysbus_mmio_map(sbdev, 0, 0x4bffd0000);
> > > +    sysbus_connect_irq(sbdev, 0, uic[2][30]);
> > > +    usb_create_simple(usb_bus_find(-1), "usb-kbd");
> > > +    usb_create_simple(usb_bus_find(-1), "usb-mouse");
> > > +
> > > +    /* PCI bus */
> > > +    ppc460ex_pcie_init(env);
> > > +    /*XXX: FIXME: is this correct? */
> > > +    dev = sysbus_create_varargs("ppc440-pcix-host", 0xc0ec00000,
> > > +                                uic[1][0], uic[1][20], uic[1][21], uic[1][22],
> > > +                                NULL);
> > > +    pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
> > > +    if (!pci_bus) {
> > > +        fprintf(stderr, "couldn't create PCI controller!\n");
> > > +        exit(1);
> > > +    }
> > > +    memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(),
> > > +                             0, 0x10000);
> > > +    memory_region_add_subregion(get_system_memory(), 0xc08000000, isa);
> > 
> > Does it really make sense to just embed the ISA IO space here, rather
> > than actually instanting a PCI<->ISA bridge?
> 
> I'm not sure if this is correct but I don't know how it's handled on real
> hardware. The board does not have ISA and I don't think it has a bridge but
> the IO space appears at this location according to the datasheet (In System
> Memory Address Map it's listed as PCI I/O 0xc08000000-0xc0800ffff) and
> clients expect PCI card's io registers to be accessible here. If anyone
> knows how it's done on real hardware and if there's a better way to model
> this please let me know.

Ah, ok.  I think the confusion here is that you can have PCI I/O space
without ISA or a system IO space.  In fact that's pretty standard on
things without a CPU level IO space (which means just about everything
except x86).

But in that case I'd expect the PCI host bridge to map its IO memory
regions directly into address_space_memory rather than involving the
global address_space_io (what get_system_io()) returns.  The only
reason I can see that you'd need to involve get_system_io() is if you
have devices registering themselves directly into the global IO space,
which should only happen for legacy ISA devices, which it sounds like
you don't have.

Possibly this is an error in the PCI bridge implementation that your
code here is essentially a workaround for, though.

> 
> > > +    /* PCI devices */
> > > +    pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "sm501");
> > > +    /* SoC has a single SATA port but we don't emulate that yet
> > > +     * However, firmware and usual clients have driver for SiI311x
> > > +     * so add one for convenience by default */
> > > +    pci_create_simple(pci_bus, -1, "sii3112");
> > 
> > You should probably not create this when started with -nodefaults.
> 
> We don't emulate the on-board SATA port of the SoC and without this there's
> no other way to connect disks (maybe over USB, but firmware has a bug which
> prevents that too even on real hardware AFAIK, I've backported a fix which
> made booting from USB work but that broke keyboard) so while this is an
> external card it's pretty much unusable without this so it's added by
> default.

Yes, but you're not just adding it by default, you're adding it
*always*.  -nodefaults should turn that off (and the user will need to
manually instantiate it - or another disk controller, I guess).

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 15/15] ppc: Add aCube Sam460ex board
  2017-08-23 11:43       ` François Revol
  2017-08-23 12:47         ` BALATON Zoltan
@ 2017-08-24  2:51         ` David Gibson
  2017-08-24 21:43           ` BALATON Zoltan
  1 sibling, 1 reply; 66+ messages in thread
From: David Gibson @ 2017-08-24  2:51 UTC (permalink / raw)
  To: François Revol; +Cc: BALATON Zoltan, qemu-devel, qemu-ppc, Alexander Graf

[-- Attachment #1: Type: text/plain, Size: 2606 bytes --]

On Wed, Aug 23, 2017 at 01:43:56PM +0200, François Revol wrote:
> Le 23/08/2017 à 13:12, BALATON Zoltan a écrit :
> >> What's the connection with mips_malta?
> > 
> > The board's firmware wants to see SPD EEPROMs of the connected memory
> > while initialising the memory controller. This is why we need to
> > implement SDRAM controller, I2C and SPD EEPROMs. MIPS malta board had
> > already SPD EEPROM implementation so this is based on that. The comment
> > just indicates where this code comes from.
> 
> Indeed, and I copy-pasted from elsewhere for this.
> 
> >>> +        fprintf(stderr, "qemu: Error registering flash memory.\n");
> >>
> >> Use error_report() instead, please.
> 
> I guess this didn't exist back when I started writing it...

Probably not.

> >>> +/* Create reset TLB entries for BookE, mapping only the flash
> >>> memory.  */
> >>> +static void mmubooke_create_initial_mapping_uboot(CPUPPCState *env)
> >>> +{
> >>> +    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
> >>> +
> >>> +    /* on reset the flash is mapped by a shadow TLB,
> >>> +     * but since we don't implement them we need to use
> >>> +     * the same values U-Boot will use to avoid a fault.
> >>> +     */
> >>
> >> Usually the reset state of the MMU is handled in the cpu code rather
> >> than the board code.  Is there a specific reason you need it in the
> >> board code here?
> > 
> > I'm not sure, probably lack of a better place. The ppc440_bamboo board
> > this is based on has it the same way in the board code. Maybe this could
> > be cleaned up when someone wants to QOMify the SoC models sometimes.
> 
> Thing is, the code allows both booting with U-Boot and with a kernel
> directly, and the MMU mapping differ in those cases.
> 
> Maybe the CPU reset should use the U-Boot setup and the kernel boot
> would just overwrite it?

Yes.  Basically the CPU reset should do what real hardware does - and
I'd expect u-boot to be written to work with that.  The kernel, on the
other hand will expect whatever mappings come out of u-boot (or
another bootloader).  Long term, I think you want to always use the
hardware setup and actually run the guest firmware to set up the
mappings the kernel expects.  For early development where it's useful
to be able to boot into a kernel without firmware, faking the right
mappings in the board code is perfectly reasonable.

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 15/15] ppc: Add aCube Sam460ex board
  2017-08-23 12:47         ` BALATON Zoltan
  2017-08-23 13:33           ` [Qemu-devel] [Qemu-ppc] " luigi burdo
@ 2017-08-24  2:54           ` David Gibson
  1 sibling, 0 replies; 66+ messages in thread
From: David Gibson @ 2017-08-24  2:54 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: François Revol, qemu-devel, qemu-ppc, Alexander Graf

[-- Attachment #1: Type: text/plain, Size: 4070 bytes --]

On Wed, Aug 23, 2017 at 02:47:42PM +0200, BALATON Zoltan wrote:
> On Wed, 23 Aug 2017, François Revol wrote:
> > Le 23/08/2017 à 13:12, BALATON Zoltan a écrit :
> > > > What's the connection with mips_malta?
> > > 
> > > The board's firmware wants to see SPD EEPROMs of the connected memory
> > > while initialising the memory controller. This is why we need to
> > > implement SDRAM controller, I2C and SPD EEPROMs. MIPS malta board had
> > > already SPD EEPROM implementation so this is based on that. The comment
> > > just indicates where this code comes from.
> > 
> > Indeed, and I copy-pasted from elsewhere for this.
> > 
> > > > > +        fprintf(stderr, "qemu: Error registering flash memory.\n");
> > > > 
> > > > Use error_report() instead, please.
> > 
> > I guess this didn't exist back when I started writing it...
> 
> No problem, I can take care of these.
> 
> > > > > +/* Create reset TLB entries for BookE, mapping only the flash
> > > > > memory.  */
> > > > > +static void mmubooke_create_initial_mapping_uboot(CPUPPCState *env)
> > > > > +{
> > > > > +    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
> > > > > +
> > > > > +    /* on reset the flash is mapped by a shadow TLB,
> > > > > +     * but since we don't implement them we need to use
> > > > > +     * the same values U-Boot will use to avoid a fault.
> > > > > +     */
> > > > 
> > > > Usually the reset state of the MMU is handled in the cpu code rather
> > > > than the board code.  Is there a specific reason you need it in the
> > > > board code here?
> > > 
> > > I'm not sure, probably lack of a better place. The ppc440_bamboo board
> > > this is based on has it the same way in the board code. Maybe this could
> > > be cleaned up when someone wants to QOMify the SoC models sometimes.
> > 
> > Thing is, the code allows both booting with U-Boot and with a kernel
> > directly, and the MMU mapping differ in those cases.
> > 
> > Maybe the CPU reset should use the U-Boot setup and the kernel boot
> > would just overwrite it?
> > 
> > > > > +        env->nip = bi->entry;
> > > > > +
> > > > > +        /* Create a mapping for the kernel.  */
> > > > > +        mmubooke_create_initial_mapping(env, 0, 0);
> > > > > +        env->gpr[6] = tswap32(EPAPR_MAGIC);
> > > > 
> > > > I'm pretty sure the tswap can't be right here.  env->gpr is in host
> > > > native order and I'd expect the constant to be as well.
> > > 
> > > I know nothing about this, maybe Francois remembers why it's there. But
> > > booting linux with -kernel works so it's probably either correct or does
> > > not matter.
> > 
> > Absolutely no idea. It seems to be there from the first commit in my own
> > history here.
> > 
> > I don't recall testing booting linux at all though.
> > Linux does check the magic, so it'd be weird if it booted:
> > 
> > https://github.com/torvalds/linux/blob/master/arch/powerpc/boot/epapr.c
> 
> Is this code used on Sam460 at all? Is U-Boot ePAPR compliant
> firmware?

It can be, depends on the build, I think.

> Isn't that only needed on OpenFirmware?

No, not at all.  True OF will generally *not* be ePAPR compliant -
ePAPR was explicitly built as a much simpler interface that doesn't
require an OF implementation.  It uses some concepts from OF,
specifically the contents of the device tree, but other than that it's
not related.

> 
> > But maybe it got added later than the version you tested?
> 
> I've tried some of these:
> http://www.supertuxkart-amiga.de/amiga/sam.html#downloads
> which also have kernel 4.5 so that's fairly recent. These kernels are
> "u-boot legacy uImage" so maybe they don't need ePAPR magic? Are there some
> docs on what the kernel expects on this board or it has to be dug out from
> U-Boot?

If it's a legacy uImage I suspect it's not using ePAPR.

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 13/15] ppc4xx: Add more PLB registers
  2017-08-24  2:35       ` David Gibson
@ 2017-08-24 20:28         ` BALATON Zoltan
  2017-08-25  5:05           ` David Gibson
  0 siblings, 1 reply; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-24 20:28 UTC (permalink / raw)
  To: David Gibson; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

On Thu, 24 Aug 2017, David Gibson wrote:
> On Wed, Aug 23, 2017 at 12:16:24PM +0200, BALATON Zoltan wrote:
>> On Wed, 23 Aug 2017, David Gibson wrote:
>>> On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
>>>> These registers are present in 440 SoCs (and maybe in others too) and
>>>> U-Boot accesses them when printing register info. We don't emulate
>>>> these but add them to avoid crashing when they are read or written.
>>>>
>>>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>>>
>>> I'm ok with stub implementation, but I'm a bit uncomfortable with
>>> registering these DCRs unconditionally rather than just on the chips
>>> that actually implement them.
>>
>> Problem is that I don't know which chips have these. I can only try to find
>> out from the U-Boot sources where a comment says these are common registers
>> for all SoCs (in u-boot/arch/powerpc/include/asm/ppc4xx.h:
>>
>> http://git.denx.de/?p=u-boot.git;a=blob;f=arch/powerpc/include/asm/ppc4xx.h;h=45ff5dbacd9243e83bb2f6551e2dd64a7e544bf5;hb=e2351d5cf1e97408b4c52bafeaa85e0ca85c920c
>>
>> while looking for this I've just noticed that u-boot has removed ppc440
>> support just before 2017.07-rc3 so this is the last version that still has
>> these files). So if that's true it should be OK for 405 too.
>
> Ok, just to make sure I'm understanding correctly are you saying:
>
> 1) You suspect these registers were actually on all versions of the
>   device, they just weren't implemented until now.

That's what I suspect from the comment in the file quoted above but I 
don't have any other evidence.

> or
>
> 2) The registers are definitely on only some versions of the device,
>   but you're not sure which ones

I don't know any of these devices very well and have no definitive sources 
to confirm so I'm not sure but I think these should be on all the versions 
(at least on all three that QEMU emulates, namely 405, 440 and 460ex).

>>>> ---
>>>>  hw/ppc/ppc405_uc.c | 12 +++++++++---
>>>>  1 file changed, 9 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
>>>> index e621d0a..8e58065 100644
>>>> --- a/hw/ppc/ppc405_uc.c
>>>> +++ b/hw/ppc/ppc405_uc.c
>>>> @@ -105,9 +105,12 @@ ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
>>>>  /*****************************************************************************/
>>>>  /* Peripheral local bus arbitrer */
>>>>  enum {
>>>> -    PLB0_BESR = 0x084,
>>>> -    PLB0_BEAR = 0x086,
>>>> -    PLB0_ACR  = 0x087,
>>>> +    PLB3A0_ACR = 0x077,
>>>> +    PLB4A0_ACR = 0x081,
>>>> +    PLB0_BESR  = 0x084,
>>>> +    PLB0_BEAR  = 0x086,
>>>> +    PLB0_ACR   = 0x087,
>>>> +    PLB4A1_ACR = 0x089,
>>>>  };
>>>>
>>>>  typedef struct ppc4xx_plb_t ppc4xx_plb_t;
>>>> @@ -179,9 +182,12 @@ void ppc4xx_plb_init(CPUPPCState *env)
>>>>      ppc4xx_plb_t *plb;
>>>>
>>>>      plb = g_malloc0(sizeof(ppc4xx_plb_t));
>>>> +    ppc_dcr_register(env, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>>>> +    ppc_dcr_register(env, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>>>>      ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>>>>      ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
>>>>      ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
>>>> +    ppc_dcr_register(env, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb);
>>>>      qemu_register_reset(ppc4xx_plb_reset, plb);
>>>>  }
>>>>
>>>
>>>
>>
>
>

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 15/15] ppc: Add aCube Sam460ex board
  2017-08-24  2:44       ` David Gibson
@ 2017-08-24 21:37         ` BALATON Zoltan
  2017-08-25  0:15           ` David Gibson
  0 siblings, 1 reply; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-24 21:37 UTC (permalink / raw)
  To: David Gibson; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

On Thu, 24 Aug 2017, David Gibson wrote:
> On Wed, Aug 23, 2017 at 01:12:06PM +0200, BALATON Zoltan wrote:
>> On Wed, 23 Aug 2017, David Gibson wrote:
>>> On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
>>>> Add emulation of aCube Sam460ex board based on AMCC 460EX embedded SoC.
>>>> This is not a full implementation yet with a lot of components still
>>>> missing but enough to start a Linux kernel and the U-Boot firmware.
>>>>
>>>> Signed-off-by: François Revol <revol@free.fr>
>>>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>>>
>>> As usual, only fairly superficial review here.
>>>
>>>> ---
>>>>  default-configs/ppcemb-softmmu.mak |   3 +
>>>>  hw/ppc/Makefile.objs               |   2 +
>>>>  hw/ppc/sam460ex.c                  | 611 +++++++++++++++++++++++++++++++++++++
>>>>  3 files changed, 616 insertions(+)
>>>>  create mode 100644 hw/ppc/sam460ex.c
>>>>
>>>> diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
>>>> index 635923a..90b42f0 100644
>>>> --- a/default-configs/ppcemb-softmmu.mak
>>>> +++ b/default-configs/ppcemb-softmmu.mak
>> [...]
>>>> +/*****************************************************************************/
>>>> +/* SPD eeprom content from mips_malta.c */
>>>
>>> What's the connection with mips_malta?
>>
>> The board's firmware wants to see SPD EEPROMs of the connected memory while
>> initialising the memory controller. This is why we need to implement SDRAM
>> controller, I2C and SPD EEPROMs. MIPS malta board had already SPD EEPROM
>> implementation so this is based on that. The comment just indicates where
>> this code comes from.
>
> Ok.
>
> [snip]
>>>> +        env->nip = bi->entry;
>>>> +
>>>> +        /* Create a mapping for the kernel.  */
>>>> +        mmubooke_create_initial_mapping(env, 0, 0);
>>>> +        env->gpr[6] = tswap32(EPAPR_MAGIC);
>>>
>>> I'm pretty sure the tswap can't be right here.  env->gpr is in host
>>> native order and I'd expect the constant to be as well.
>>
>> I know nothing about this, maybe Francois remembers why it's there. But
>> booting linux with -kernel works so it's probably either correct or does not
>> matter.
>
> Have you attempted it on both BE and LE hosts though?

No, I don't have a BE host, only tried on LE. I'm guessing this may come 
from hw/ppc/virtex_ml507.c where EPAPR_MAGIC is also swapped. The only 
other place this magic number appears is in e500 where it's not swapped 
though so I don't really know what should be correct here. In u-boot 
sources (arch/powerpc/lib/bootm.c) it seems to use this magic if 
CONFIG_OF_LIBFDT is defined which seems to be set for this board so that 
means we likely need this (but maybe not for the legacy uImages I've 
tried). Since CPU is big endian and constant is defined on the host this 
probably should be cpu_to_be32(EPAPR_MAGIC). Does that sound better?

[...]
>>>> +    /* FIXME: remove this after fixing l2sram mapping in ppc440_uc.c? */
>>>> +    memory_region_init_ram(l2cache_ram, NULL, "ppc440.l2cache_ram", 256 << 10,
>>>> +                           &error_abort);
>>>> +    memory_region_add_subregion(address_space_mem, 0x400000000LL, l2cache_ram);
>>>> +
>>>> +    /* USB */
>>>> +    sysbus_create_simple(TYPE_PPC4xx_EHCI, 0x4bffd0400, uic[2][29]);
>>>> +    dev = qdev_create(NULL, "sysbus-ohci");
>>>> +    qdev_prop_set_string(dev, "masterbus", "usb-bus.0");
>>>> +    qdev_prop_set_uint32(dev, "num-ports", 6);
>>>> +    qdev_init_nofail(dev);
>>>> +    sbdev = SYS_BUS_DEVICE(dev);
>>>> +    sysbus_mmio_map(sbdev, 0, 0x4bffd0000);
>>>> +    sysbus_connect_irq(sbdev, 0, uic[2][30]);
>>>> +    usb_create_simple(usb_bus_find(-1), "usb-kbd");
>>>> +    usb_create_simple(usb_bus_find(-1), "usb-mouse");
>>>> +
>>>> +    /* PCI bus */
>>>> +    ppc460ex_pcie_init(env);
>>>> +    /*XXX: FIXME: is this correct? */
>>>> +    dev = sysbus_create_varargs("ppc440-pcix-host", 0xc0ec00000,
>>>> +                                uic[1][0], uic[1][20], uic[1][21], uic[1][22],
>>>> +                                NULL);
>>>> +    pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
>>>> +    if (!pci_bus) {
>>>> +        fprintf(stderr, "couldn't create PCI controller!\n");
>>>> +        exit(1);
>>>> +    }
>>>> +    memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(),
>>>> +                             0, 0x10000);
>>>> +    memory_region_add_subregion(get_system_memory(), 0xc08000000, isa);
>>>
>>> Does it really make sense to just embed the ISA IO space here, rather
>>> than actually instanting a PCI<->ISA bridge?
>>
>> I'm not sure if this is correct but I don't know how it's handled on real
>> hardware. The board does not have ISA and I don't think it has a bridge but
>> the IO space appears at this location according to the datasheet (In System
>> Memory Address Map it's listed as PCI I/O 0xc08000000-0xc0800ffff) and
>> clients expect PCI card's io registers to be accessible here. If anyone
>> knows how it's done on real hardware and if there's a better way to model
>> this please let me know.
>
> Ah, ok.  I think the confusion here is that you can have PCI I/O space
> without ISA or a system IO space.  In fact that's pretty standard on
> things without a CPU level IO space (which means just about everything
> except x86).
>
> But in that case I'd expect the PCI host bridge to map its IO memory
> regions directly into address_space_memory rather than involving the
> global address_space_io (what get_system_io()) returns.  The only
> reason I can see that you'd need to involve get_system_io() is if you
> have devices registering themselves directly into the global IO space,
> which should only happen for legacy ISA devices, which it sounds like
> you don't have.
>
> Possibly this is an error in the PCI bridge implementation that your
> code here is essentially a workaround for, though.

So in my understanding, there's a system_io space created automatically 
which appears in the memory tree anyway but would otherwise be unused and 
this was just reused here for the pci io space so it does not need another 
memory region for this. If it's not acceptable this way (although 
ppc440_bamboo.c and ppc4xx_pci.c also does it the exact same way) an 
alternative may be to change it to add another mem region for io to 
ppc440_pcix.c (although it already has iomem for pci.reg so this might be 
more confusing than using system_io here) but I think pcix device can't 
map this to address_space_memory itself because this device could appear 
in different SoCs where the memory areas might be at different addresses 
so this new region should then be registered as a sysbus mmio space and be 
mapped from the board code with sysbus_mmio_map()? I find that much more 
confusing than how it's done now which is also more consistent with 
existing code modelling similar devices.

>>>> +    /* PCI devices */
>>>> +    pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "sm501");
>>>> +    /* SoC has a single SATA port but we don't emulate that yet
>>>> +     * However, firmware and usual clients have driver for SiI311x
>>>> +     * so add one for convenience by default */
>>>> +    pci_create_simple(pci_bus, -1, "sii3112");
>>>
>>> You should probably not create this when started with -nodefaults.
>>
>> We don't emulate the on-board SATA port of the SoC and without this there's
>> no other way to connect disks (maybe over USB, but firmware has a bug which
>> prevents that too even on real hardware AFAIK, I've backported a fix which
>> made booting from USB work but that broke keyboard) so while this is an
>> external card it's pretty much unusable without this so it's added by
>> default.
>
> Yes, but you're not just adding it by default, you're adding it
> *always*.  -nodefaults should turn that off (and the user will need to
> manually instantiate it - or another disk controller, I guess).

OK I got it now. I still don't see when -nodefaults could be useful to 
cripple the board and make it easier to create non-working configurations 
but I can easily add this conditional around this line and hope users stay 
away from this switch and won't complain when it does not boot when they 
use it. (Well, it does not really boot most of the time without this 
switch either so I don't think it matters much at the moment :-) )

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 15/15] ppc: Add aCube Sam460ex board
  2017-08-24  2:51         ` David Gibson
@ 2017-08-24 21:43           ` BALATON Zoltan
  2017-08-24 23:55             ` David Gibson
  0 siblings, 1 reply; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-24 21:43 UTC (permalink / raw)
  To: David Gibson; +Cc: François Revol, qemu-devel, qemu-ppc, Alexander Graf

On Thu, 24 Aug 2017, David Gibson wrote:
> On Wed, Aug 23, 2017 at 01:43:56PM +0200, François Revol wrote:
>> Le 23/08/2017 à 13:12, BALATON Zoltan a écrit :
>>>> What's the connection with mips_malta?
>>>
>>> The board's firmware wants to see SPD EEPROMs of the connected memory
>>> while initialising the memory controller. This is why we need to
>>> implement SDRAM controller, I2C and SPD EEPROMs. MIPS malta board had
>>> already SPD EEPROM implementation so this is based on that. The comment
>>> just indicates where this code comes from.
>>
>> Indeed, and I copy-pasted from elsewhere for this.
>>
>>>>> +        fprintf(stderr, "qemu: Error registering flash memory.\n");
>>>>
>>>> Use error_report() instead, please.
>>
>> I guess this didn't exist back when I started writing it...
>
> Probably not.
>
>>>>> +/* Create reset TLB entries for BookE, mapping only the flash
>>>>> memory.  */
>>>>> +static void mmubooke_create_initial_mapping_uboot(CPUPPCState *env)
>>>>> +{
>>>>> +    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
>>>>> +
>>>>> +    /* on reset the flash is mapped by a shadow TLB,
>>>>> +     * but since we don't implement them we need to use
>>>>> +     * the same values U-Boot will use to avoid a fault.
>>>>> +     */
>>>>
>>>> Usually the reset state of the MMU is handled in the cpu code rather
>>>> than the board code.  Is there a specific reason you need it in the
>>>> board code here?
>>>
>>> I'm not sure, probably lack of a better place. The ppc440_bamboo board
>>> this is based on has it the same way in the board code. Maybe this could
>>> be cleaned up when someone wants to QOMify the SoC models sometimes.
>>
>> Thing is, the code allows both booting with U-Boot and with a kernel
>> directly, and the MMU mapping differ in those cases.
>>
>> Maybe the CPU reset should use the U-Boot setup and the kernel boot
>> would just overwrite it?
>
> Yes.  Basically the CPU reset should do what real hardware does - and
> I'd expect u-boot to be written to work with that.  The kernel, on the
> other hand will expect whatever mappings come out of u-boot (or
> another bootloader).  Long term, I think you want to always use the
> hardware setup and actually run the guest firmware to set up the
> mappings the kernel expects.

Maybe we should emulate the nvram for that and then we could patch it to 
have it boot the kernel with the parameters specified in the command line? 
This would also be needed to avoid the warning from u-boot about bad 
checksum and always going with the built in defaults and would also allow 
users to store settings like on real hardware but it's not something that 
looks high priority to me at the moment.

>  For early development where it's useful
> to be able to boot into a kernel without firmware, faking the right
> mappings in the board code is perfectly reasonable.

So for now I'd just go with this, because there's much more to clean up 
and improve before this becomes and issue I think.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 10/15] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
  2017-08-20 22:20   ` Philippe Mathieu-Daudé
@ 2017-08-24 22:12     ` BALATON Zoltan
  0 siblings, 0 replies; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-24 22:12 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: qemu-devel, qemu-ppc, Francois Revol, Alexander Graf, David Gibson

On Sun, 20 Aug 2017, Philippe Mathieu-Daudé wrote:
> Hi Zoltan,

Hello,

Thanks for the review and comments.

> On 08/20/2017 02:23 PM, BALATON Zoltan wrote:
>> This is the PCIX controller found in newer 440 core SoCs e.g. the AMMC
>> 460EX. The device tree refers to this as plb-pcix compared to the
>> plb-pci controller in older 440 SoCs.
>> 
>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>> ---
>>   hw/ppc/Makefile.objs |   2 +-
>>   hw/ppc/ppc440_pcix.c | 516 
>> +++++++++++++++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 517 insertions(+), 1 deletion(-)
>>   create mode 100644 hw/ppc/ppc440_pcix.c
>> 
>> diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
>> index 7efc686..fc39fe4 100644
>> --- a/hw/ppc/Makefile.objs
>> +++ b/hw/ppc/Makefile.objs
>> @@ -13,7 +13,7 @@ endif
>>   obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o
>>   # PowerPC 4xx boards
>>   obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
>> -obj-y += ppc4xx_pci.o
>> +obj-y += ppc4xx_pci.o ppc440_pcix.o
>>   # PReP
>>   obj-$(CONFIG_PREP) += prep.o
>>   obj-$(CONFIG_PREP) += prep_systemio.o
>> diff --git a/hw/ppc/ppc440_pcix.c b/hw/ppc/ppc440_pcix.c
>> new file mode 100644
>> index 0000000..5c2ceec
>> --- /dev/null
>> +++ b/hw/ppc/ppc440_pcix.c
>> @@ -0,0 +1,516 @@
>> +/*
>> + * Emulation of the ibm,plb-pcix PCI controller
>> + * This is found in some 440 SoCs e.g. the 460EX.
>> + *
>> + * Copyright (c) 2016 BALATON Zoltan
>> + *
>> + * Derived from ppc4xx_pci.c and pci-host/ppce500.c
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License, version 2, as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "qemu/error-report.h"
>> +#include "hw/hw.h"
>> +#include "hw/ppc/ppc.h"
>> +#include "hw/ppc/ppc4xx.h"
>> +#include "hw/pci/pci.h"
>> +#include "hw/pci/pci_host.h"
>> +#include "exec/address-spaces.h"
>> +
>> +/*#define DEBUG_PCI*/
>> +
>> +#ifdef DEBUG_PCI
>> +#define DPRINTF(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__);
>> +#else
>> +#define DPRINTF(fmt, ...)
>> +#endif /* DEBUG */
>> +
>> +struct PLBOutMap {
>> +    uint64_t la;
>> +    uint64_t pcia;
>> +    uint32_t sa;
>> +    MemoryRegion mr;
>> +};
>> +
>> +struct PLBInMap {
>> +    uint64_t sa;
>> +    uint64_t la;
>> +    MemoryRegion mr;
>> +};
>> +
>> +#define TYPE_PPC440_PCIX_HOST_BRIDGE "ppc440-pcix-host"
>> +#define PPC440_PCIX_HOST_BRIDGE(obj) \
>> +    OBJECT_CHECK(PPC440PCIXState, (obj), TYPE_PPC440_PCIX_HOST_BRIDGE)
>> +
>> +#define PPC440_PCIX_NR_POMS 3
>> +#define PPC440_PCIX_NR_PIMS 3
>> +
>> +typedef struct PPC440PCIXState {
>> +    PCIHostState parent_obj;
>> +
>> +    PCIDevice *dev;
>> +    struct PLBOutMap pom[PPC440_PCIX_NR_POMS];
>> +    struct PLBInMap pim[PPC440_PCIX_NR_PIMS];
>> +    uint32_t sts;
>> +    qemu_irq irq[PCI_NUM_PINS];
>> +    AddressSpace bm_as;
>> +    MemoryRegion bm;
>> +
>> +    MemoryRegion container;
>> +    MemoryRegion iomem;
>> +    MemoryRegion busmem;
>> +} PPC440PCIXState;
>> +
>> +#define PPC440_REG_BASE     0x80000
>> +#define PPC440_REG_SIZE     0xff
>> +
>> +#define PCIC0_CFGADDR       0x0
>> +#define PCIC0_CFGDATA       0x4
>> +
>> +#define PCIX0_POM0LAL       0x68
>> +#define PCIX0_POM0LAH       0x6c
>> +#define PCIX0_POM0SA        0x70
>> +#define PCIX0_POM0PCIAL     0x74
>> +#define PCIX0_POM0PCIAH     0x78
>> +#define PCIX0_POM1LAL       0x7c
>> +#define PCIX0_POM1LAH       0x80
>> +#define PCIX0_POM1SA        0x84
>> +#define PCIX0_POM1PCIAL     0x88
>> +#define PCIX0_POM1PCIAH     0x8c
>> +#define PCIX0_POM2SA        0x90
>> +
>> +#define PCIX0_PIM0SAL       0x98
>> +#define PCIX0_PIM0LAL       0x9c
>> +#define PCIX0_PIM0LAH       0xa0
>> +#define PCIX0_PIM1SA        0xa4
>> +#define PCIX0_PIM1LAL       0xa8
>> +#define PCIX0_PIM1LAH       0xac
>> +#define PCIX0_PIM2SAL       0xb0
>> +#define PCIX0_PIM2LAL       0xb4
>> +#define PCIX0_PIM2LAH       0xb8
>> +#define PCIX0_PIM0SAH       0xf8
>> +#define PCIX0_PIM2SAH       0xfc
>> +
>> +#define PCIX0_STS           0xe0
>> +
>> +#define PCI_ALL_SIZE        (PPC440_REG_BASE + PPC440_REG_SIZE)
>> +
>> +static void ppc440_pcix_clear_region(MemoryRegion *parent,
>> +                                     MemoryRegion *mem)
>> +{
>> +    if (memory_region_is_mapped(mem)) {
>> +        memory_region_del_subregion(parent, mem);
>> +        object_unparent(OBJECT(mem));
>> +    }
>> +}
>> +
>> +/* DMA mapping */
>> +static void ppc440_pcix_update_pim(PPC440PCIXState *s, int idx)
>> +{
>> +    MemoryRegion *mem = &s->pim[idx].mr;
>> +    char *name;
>> +    uint64_t size;
>> +
>> +    /* Before we modify anything, unmap and destroy the region */
>> +    ppc440_pcix_clear_region(&s->bm, mem);
>> +
>> +    if (!(s->pim[idx].sa & 1)) {
>> +        /* Not enabled, nothing to do */
>> +        return;
>> +    }
>> +
>> +    name = g_strdup_printf("PCI Inbound Window %d", idx);
>> +    size = ~(s->pim[idx].sa & ~7ULL) + 1;
>> +    memory_region_init_alias(mem, OBJECT(s), name, get_system_memory(),
>> +                             s->pim[idx].la, size);
>> +    memory_region_add_subregion_overlap(&s->bm, 0, mem, -1);
>> +    g_free(name);
>> +
>> +    DPRINTF("%s: Added window %d of size=%#"PRIx64" to CPU=%#"PRIx64"\n",
>> +            __func__, idx, size, s->pim[idx].la);
>> +}
>> +
>> +/* BAR mapping */
>> +static void ppc440_pcix_update_pom(PPC440PCIXState *s, int idx)
>> +{
>> +    MemoryRegion *mem = &s->pom[idx].mr;
>> +    MemoryRegion *address_space_mem = get_system_memory();
>> +    char *name;
>> +    uint32_t size;
>> +
>> +    /* Before we modify anything, unmap and destroy the region */
>> +    ppc440_pcix_clear_region(address_space_mem, mem);
>> +
>> +    if (!(s->pom[idx].sa & 1)) {
>> +        /* Not enabled, nothing to do */
>> +        return;
>> +    }
>> +
>> +    name = g_strdup_printf("PCI Outbound Window %d", idx);
>> +    size = ~(s->pom[idx].sa & 0xfffffffe) + 1;
>> +    if (!size) {
>> +        size = 0xffffffff;
>> +    }
>> +    memory_region_init_alias(mem, OBJECT(s), name, &s->busmem,
>> +                             s->pom[idx].pcia, size);
>> +    memory_region_add_subregion(address_space_mem, s->pom[idx].la, mem);
>> +    g_free(name);
>> +
>> +    DPRINTF("%s: Added window %d of size=%#x from CPU=%#"PRIx64
>> +            " to PCI=%#"PRIx64"\n", __func__, idx, size, s->pom[idx].la,
>> +            s->pom[idx].pcia);
>> +}
>> +
>> +static void ppc440_pcix_reg_write4(void *opaque, hwaddr addr,
>> +                                   uint64_t val, unsigned size)
>> +{
>> +    struct PPC440PCIXState *s = opaque;
>> +
>> +    DPRINTF("%s: addr 0x%"PRIx64 " = %"PRIx64 "\n", __func__, addr, val);
>> +    switch (addr) {
>> +    case PCI_VENDOR_ID ... PCI_MAX_LAT:
>> +        stl_le_p(s->dev->config + addr, val);
>> +        break;
>> +
>> +    case PCIX0_POM0LAL:
>
> Those lines ...
>
>> +        s->pom[0].la &= 0xffffffff00000000ULL;
>> +        s->pom[0].la |= val;
>
> equivs to:
>
> 	   s->pom[0].la = deposit64(s->pom[0].la, 0, 32, val);
>
>> +        ppc440_pcix_update_pom(s, 0);
>> +        break;
>> +    case PCIX0_POM0LAH:
>
> Those
>
>> +        s->pom[0].la &= 0xffffffffULL;
>> +        s->pom[0].la |= val << 32;
>
> to:
>
> 	   s->pom[0].la = deposit64(s->pom[0].la, 32, 32, val);

Except that deposit64 also seems to call an (in this case) unnecessary 
assert. Not sure how much overhead is that and I don't think this is 
performance critical as these regs are probably not accessed too 
frequently but why not avoid an unneded call for such simple operation? 
The deposit and extract functions are not currently used in most other 
device models as it seems so I'm happy with the current way unless there's 
a good reason to change it other than one line instead of two. But the 
current version could also be written as one I line just found this easier 
to read but it's personal taste I guess so everyone can have different 
view on this what's more readable to them. If less lines is preferred I 
would rather make them one line without calling deposit here. But that 
would increase the number of paranthesis. Maybe I could define some macros 
for this and use those instead.

>> +        ppc440_pcix_update_pom(s, 0);
>> +        break;
>> +    case PCIX0_POM0SA:
>> +        s->pom[0].sa = val;
>> +        ppc440_pcix_update_pom(s, 0);
>> +        break;
>> +    case PCIX0_POM0PCIAL:
>> +        s->pom[0].pcia &= 0xffffffff00000000ULL;
>> +        s->pom[0].pcia |= val;
>
> and so on
>
>> +        ppc440_pcix_update_pom(s, 0);
>> +        break;
>> +    case PCIX0_POM0PCIAH:
>> +        s->pom[0].pcia &= 0xffffffffULL;
>> +        s->pom[0].pcia |= val << 32;
>> +        ppc440_pcix_update_pom(s, 0);
>> +        break;
>> +    case PCIX0_POM1LAL:
>> +        s->pom[1].la &= 0xffffffff00000000ULL;
>> +        s->pom[1].la |= val;
>> +        ppc440_pcix_update_pom(s, 1);
>> +        break;
>> +    case PCIX0_POM1LAH:
>> +        s->pom[1].la &= 0xffffffffULL;
>> +        s->pom[1].la |= val << 32;
>> +        ppc440_pcix_update_pom(s, 1);
>> +        break;
>> +    case PCIX0_POM1SA:
>> +        s->pom[1].sa = val;
>> +        ppc440_pcix_update_pom(s, 1);
>> +        break;
>> +    case PCIX0_POM1PCIAL:
>> +        s->pom[1].pcia &= 0xffffffff00000000ULL;
>> +        s->pom[1].pcia |= val;
>> +        ppc440_pcix_update_pom(s, 1);
>> +        break;
>> +    case PCIX0_POM1PCIAH:
>> +        s->pom[1].pcia &= 0xffffffffULL;
>> +        s->pom[1].pcia |= val << 32;
>> +        ppc440_pcix_update_pom(s, 1);
>> +        break;
>> +    case PCIX0_POM2SA:
>> +        s->pom[2].sa = val;
>> +        break;
>> +
>> +    case PCIX0_PIM0SAL:
>> +        s->pim[0].sa &= 0xffffffff00000000ULL;
>> +        s->pim[0].sa |= val;
>> +        ppc440_pcix_update_pim(s, 0);
>> +        break;
>> +    case PCIX0_PIM0LAL:
>> +        s->pim[0].la &= 0xffffffff00000000ULL;
>> +        s->pim[0].la |= val;
>> +        ppc440_pcix_update_pim(s, 0);
>> +        break;
>> +    case PCIX0_PIM0LAH:
>> +        s->pim[0].la &= 0xffffffffULL;
>> +        s->pim[0].la |= val << 32;
>> +        ppc440_pcix_update_pim(s, 0);
>> +        break;
>> +    case PCIX0_PIM1SA:
>> +        s->pim[1].sa = val;
>> +        ppc440_pcix_update_pim(s, 1);
>> +        break;
>> +    case PCIX0_PIM1LAL:
>> +        s->pim[1].la &= 0xffffffff00000000ULL;
>> +        s->pim[1].la |= val;
>> +        ppc440_pcix_update_pim(s, 1);
>> +        break;
>> +    case PCIX0_PIM1LAH:
>> +        s->pim[1].la &= 0xffffffffULL;
>> +        s->pim[1].la |= val << 32;
>> +        ppc440_pcix_update_pim(s, 1);
>> +        break;
>> +    case PCIX0_PIM2SAL:
>> +        s->pim[2].sa &= 0xffffffff00000000ULL;
>> +        s->pim[2].sa = val;
>> +        ppc440_pcix_update_pim(s, 2);
>> +        break;
>> +    case PCIX0_PIM2LAL:
>> +        s->pim[2].la &= 0xffffffff00000000ULL;
>> +        s->pim[2].la |= val;
>> +        ppc440_pcix_update_pim(s, 2);
>> +        break;
>> +    case PCIX0_PIM2LAH:
>> +        s->pim[2].la &= 0xffffffffULL;
>> +        s->pim[2].la |= val << 32;
>> +        ppc440_pcix_update_pim(s, 2);
>> +        break;
>> +
>> +    case PCIX0_STS:
>> +        s->sts = val;
>> +        break;
>> +
>> +    case PCIX0_PIM0SAH:
>> +        s->pim[0].sa &= 0xffffffffULL;
>> +        s->pim[0].sa |= val << 32;
>> +        ppc440_pcix_update_pim(s, 0);
>> +        break;
>> +    case PCIX0_PIM2SAH:
>> +        s->pim[2].sa &= 0xffffffffULL;
>> +        s->pim[2].sa |= val << 32;
>> +        ppc440_pcix_update_pim(s, 2);
>> +        break;
>> +
>> +    default:
>> +        printf("%s: unhandled PCI internal register 0x%lx\n", __func__,
>> +               (unsigned long)addr);
>> +        break;
>> +    }
>> +}
>> +
>> +static uint64_t ppc440_pcix_reg_read4(void *opaque, hwaddr addr,
>> +                                     unsigned size)
>> +{
>> +    struct PPC440PCIXState *s = opaque;
>> +    uint32_t val;
>> +
>> +    switch (addr) {
>> +    case PCI_VENDOR_ID ... PCI_MAX_LAT:
>> +        val = ldl_le_p(s->dev->config + addr);
>> +        break;
>> +
>> +    case PCIX0_POM0LAL:
>> +        val = s->pom[0].la;
>
> This should be
>
>           val = s->pom[0].la & 0xffffffffULL;

Since val is uint32_t the value should be automatically truncated to 32 
bit, shouldn't it? Is there a reason explicit masks are needed here? Is 
this truncation not well defined and some compilers may do it differently?

Thank you,
BALATON Zoltan

> or:
>
>           val = extract64(s->pom[0].la, 0, 32);
>
>> +        break;
>> +    case PCIX0_POM0LAH:
>> +        val = s->pom[0].la >> 32;
>
> or to be consistent:
>
>           val = extract64(s->pom[0].la, 32, 32);
>
>> +        break;
>> +    case PCIX0_POM0SA:
>> +        val = s->pom[0].sa;
>> +        break;
>> +    case PCIX0_POM0PCIAL:
>> +        val = s->pom[0].pcia;
>
> also 32-bit masked
>
>> +        break;
>> +    case PCIX0_POM0PCIAH:
>> +        val = s->pom[0].pcia >> 32;
>> +        break;
>> +    case PCIX0_POM1LAL:
>> +        val = s->pom[1].la;
>
> also 32-bit masked
>
>> +        break;
>> +    case PCIX0_POM1LAH:
>> +        val = s->pom[1].la >> 32;
>> +        break;
>> +    case PCIX0_POM1SA:
>> +        val = s->pom[1].sa;
>
> also 32-bit masked, etc...
>
>> +        break;
>> +    case PCIX0_POM1PCIAL:
>> +        val = s->pom[1].pcia;
>> +        break;
>> +    case PCIX0_POM1PCIAH:
>> +        val = s->pom[1].pcia >> 32;
>> +        break;
>> +    case PCIX0_POM2SA:
>> +        val = s->pom[2].sa;
>> +        break;
>> +
>> +    case PCIX0_PIM0SAL:
>> +        val = s->pim[0].sa;
>> +        break;
>> +    case PCIX0_PIM0LAL:
>> +        val = s->pim[0].la;
>> +        break;
>> +    case PCIX0_PIM0LAH:
>> +        val = s->pim[0].la >> 32;
>> +        break;
>> +    case PCIX0_PIM1SA:
>> +        val = s->pim[1].sa;
>> +        break;
>> +    case PCIX0_PIM1LAL:
>> +        val = s->pim[1].la;
>> +        break;
>> +    case PCIX0_PIM1LAH:
>> +        val = s->pim[1].la >> 32;
>> +        break;
>> +    case PCIX0_PIM2SAL:
>> +        val = s->pim[2].sa;
>> +        break;
>> +    case PCIX0_PIM2LAL:
>> +        val = s->pim[2].la;
>> +        break;
>> +    case PCIX0_PIM2LAH:
>> +        val = s->pim[2].la >> 32;
>> +        break;
>> +
>> +    case PCIX0_STS:
>> +        val = s->sts;
>> +        break;
>> +
>> +    case PCIX0_PIM0SAH:
>> +        val = s->pim[0].sa  >> 32;
>> +        break;
>> +    case PCIX0_PIM2SAH:
>> +        val = s->pim[2].sa  >> 32;
>> +        break;
>> +
>> +    default:
>> +        printf("%s: invalid PCI internal register 0x%lx\n", __func__,
>> +               (unsigned long)addr);
>> +        val = 0;
>> +    }
>> +
>> +    DPRINTF("%s: addr 0x%"PRIx64 " = %"PRIx32 "\n", __func__, addr, val);
>> +    return val;
>> +}
>> +
>> +static const MemoryRegionOps pci_reg_ops = {
>> +    .read = ppc440_pcix_reg_read4,
>> +    .write = ppc440_pcix_reg_write4,
>> +    .endianness = DEVICE_LITTLE_ENDIAN,
>> +};
>> +
>> +static void ppc440_pcix_reset(DeviceState *dev)
>> +{
>> +    struct PPC440PCIXState *s = PPC440_PCIX_HOST_BRIDGE(dev);
>> +    int i;
>> +
>> +    for (i = 0; i < PPC440_PCIX_NR_POMS; i++) {
>> +        ppc440_pcix_clear_region(get_system_memory(), &s->pom[i].mr);
>> +    }
>> +    for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) {
>> +        ppc440_pcix_clear_region(&s->bm, &s->pim[i].mr);
>> +    }
>> +    memset(s->pom, 0, sizeof(s->pom));
>> +    memset(s->pim, 0, sizeof(s->pim));
>> +    for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) {
>> +        s->pim[i].sa = 0xffffffff00000000ULL;
>> +    }
>> +    s->sts = 0;
>> +}
>> +
>> +/* All pins from each slot are tied to a single board IRQ.
>> + * This may need further refactoring for other boards. */
>> +static int ppc440_pcix_map_irq(PCIDevice *pci_dev, int irq_num)
>> +{
>> +    int slot = pci_dev->devfn >> 3;
>> +
>> +    DPRINTF("%s: devfn %x irq %d -> %d\n", __func__,
>> +            pci_dev->devfn, irq_num, slot);
>> +
>> +    return slot - 1;
>> +}
>> +
>> +static void ppc440_pcix_set_irq(void *opaque, int irq_num, int level)
>> +{
>> +    qemu_irq *pci_irqs = opaque;
>> +
>> +    DPRINTF("%s: PCI irq %d\n", __func__, irq_num);
>> +    if (irq_num < 0) {
>> +        error_report("%s: PCI irq %d", __func__, irq_num);
>> +        return;
>> +    }
>> +    qemu_set_irq(pci_irqs[irq_num], level);
>> +}
>> +
>> +static AddressSpace *ppc440_pcix_set_iommu(PCIBus *b, void *opaque, int 
>> devfn)
>> +{
>> +    PPC440PCIXState *s = opaque;
>> +
>> +    return &s->bm_as;
>> +}
>> +
>> +static int ppc440_pcix_initfn(SysBusDevice *dev)
>> +{
>> +    PPC440PCIXState *s;
>> +    PCIHostState *h;
>> +    int i;
>> +
>> +    h = PCI_HOST_BRIDGE(dev);
>> +    s = PPC440_PCIX_HOST_BRIDGE(dev);
>> +
>> +    for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
>> +        sysbus_init_irq(dev, &s->irq[i]);
>> +    }
>> +
>> +    memory_region_init(&s->busmem, OBJECT(dev), "pci bus memory", 
>> UINT64_MAX);
>> +    h->bus = pci_register_bus(DEVICE(dev), NULL, ppc440_pcix_set_irq,
>> +                         ppc440_pcix_map_irq, s->irq, &s->busmem,
>> +                         get_system_io(), PCI_DEVFN(0, 0), 4, 
>> TYPE_PCI_BUS);
>> +
>> +    s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0), 
>> "ppc4xx-host-bridge");
>> +
>> +    memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX);
>> +    memory_region_add_subregion(&s->bm, 0x0, &s->busmem);
>> +    address_space_init(&s->bm_as, &s->bm, "pci-bm");
>> +    pci_setup_iommu(h->bus, ppc440_pcix_set_iommu, s);
>> +
>> +    memory_region_init(&s->container, OBJECT(s), "pci-container", 
>> PCI_ALL_SIZE);
>> +    memory_region_init_io(&h->conf_mem, OBJECT(s), &pci_host_conf_le_ops, 
>> h,
>> +                          "pci-conf-idx", 4);
>> +    memory_region_init_io(&h->data_mem, OBJECT(s), &pci_host_data_le_ops, 
>> h,
>> +                          "pci-conf-data", 4);
>> +    memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s,
>> +                          "pci.reg", PPC440_REG_SIZE);
>> +    memory_region_add_subregion(&s->container, PCIC0_CFGADDR, 
>> &h->conf_mem);
>> +    memory_region_add_subregion(&s->container, PCIC0_CFGDATA, 
>> &h->data_mem);
>> +    memory_region_add_subregion(&s->container, PPC440_REG_BASE, 
>> &s->iomem);
>> +    sysbus_init_mmio(dev, &s->container);
>> +
>> +    return 0;
>> +}
>> +
>> +static void ppc440_pcix_class_init(ObjectClass *klass, void *data)
>> +{
>> +    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>> +
>> +    k->init = ppc440_pcix_initfn;
>> +    dc->reset = ppc440_pcix_reset;
>> +}
>> +
>> +static const TypeInfo ppc440_pcix_info = {
>> +    .name          = TYPE_PPC440_PCIX_HOST_BRIDGE,
>> +    .parent        = TYPE_PCI_HOST_BRIDGE,
>> +    .instance_size = sizeof(PPC440PCIXState),
>> +    .class_init    = ppc440_pcix_class_init,
>> +};
>> +
>> +static void ppc440_pcix_register_types(void)
>> +{
>> +    type_register_static(&ppc440_pcix_info);
>> +}
>> +
>> +type_init(ppc440_pcix_register_types)
>> 
>
>

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 15/15] ppc: Add aCube Sam460ex board
  2017-08-24 21:43           ` BALATON Zoltan
@ 2017-08-24 23:55             ` David Gibson
  0 siblings, 0 replies; 66+ messages in thread
From: David Gibson @ 2017-08-24 23:55 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: François Revol, qemu-devel, qemu-ppc, Alexander Graf

[-- Attachment #1: Type: text/plain, Size: 3578 bytes --]

On Thu, Aug 24, 2017 at 11:43:18PM +0200, BALATON Zoltan wrote:
> On Thu, 24 Aug 2017, David Gibson wrote:
> > On Wed, Aug 23, 2017 at 01:43:56PM +0200, François Revol wrote:
> > > Le 23/08/2017 à 13:12, BALATON Zoltan a écrit :
> > > > > What's the connection with mips_malta?
> > > > 
> > > > The board's firmware wants to see SPD EEPROMs of the connected memory
> > > > while initialising the memory controller. This is why we need to
> > > > implement SDRAM controller, I2C and SPD EEPROMs. MIPS malta board had
> > > > already SPD EEPROM implementation so this is based on that. The comment
> > > > just indicates where this code comes from.
> > > 
> > > Indeed, and I copy-pasted from elsewhere for this.
> > > 
> > > > > > +        fprintf(stderr, "qemu: Error registering flash memory.\n");
> > > > > 
> > > > > Use error_report() instead, please.
> > > 
> > > I guess this didn't exist back when I started writing it...
> > 
> > Probably not.
> > 
> > > > > > +/* Create reset TLB entries for BookE, mapping only the flash
> > > > > > memory.  */
> > > > > > +static void mmubooke_create_initial_mapping_uboot(CPUPPCState *env)
> > > > > > +{
> > > > > > +    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
> > > > > > +
> > > > > > +    /* on reset the flash is mapped by a shadow TLB,
> > > > > > +     * but since we don't implement them we need to use
> > > > > > +     * the same values U-Boot will use to avoid a fault.
> > > > > > +     */
> > > > > 
> > > > > Usually the reset state of the MMU is handled in the cpu code rather
> > > > > than the board code.  Is there a specific reason you need it in the
> > > > > board code here?
> > > > 
> > > > I'm not sure, probably lack of a better place. The ppc440_bamboo board
> > > > this is based on has it the same way in the board code. Maybe this could
> > > > be cleaned up when someone wants to QOMify the SoC models sometimes.
> > > 
> > > Thing is, the code allows both booting with U-Boot and with a kernel
> > > directly, and the MMU mapping differ in those cases.
> > > 
> > > Maybe the CPU reset should use the U-Boot setup and the kernel boot
> > > would just overwrite it?
> > 
> > Yes.  Basically the CPU reset should do what real hardware does - and
> > I'd expect u-boot to be written to work with that.  The kernel, on the
> > other hand will expect whatever mappings come out of u-boot (or
> > another bootloader).  Long term, I think you want to always use the
> > hardware setup and actually run the guest firmware to set up the
> > mappings the kernel expects.
> 
> Maybe we should emulate the nvram for that and then we could patch it to
> have it boot the kernel with the parameters specified in the command line?
> This would also be needed to avoid the warning from u-boot about bad
> checksum and always going with the built in defaults and would also allow
> users to store settings like on real hardware but it's not something that
> looks high priority to me at the moment.

That all sounds reasonable.

> >  For early development where it's useful
> > to be able to boot into a kernel without firmware, faking the right
> > mappings in the board code is perfectly reasonable.
> 
> So for now I'd just go with this, because there's much more to clean up and
> improve before this becomes and issue I think.

Yup, makes sense.

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 15/15] ppc: Add aCube Sam460ex board
  2017-08-24 21:37         ` BALATON Zoltan
@ 2017-08-25  0:15           ` David Gibson
  0 siblings, 0 replies; 66+ messages in thread
From: David Gibson @ 2017-08-25  0:15 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 11438 bytes --]

On Thu, Aug 24, 2017 at 11:37:09PM +0200, BALATON Zoltan wrote:
> On Thu, 24 Aug 2017, David Gibson wrote:
> > On Wed, Aug 23, 2017 at 01:12:06PM +0200, BALATON Zoltan wrote:
> > > On Wed, 23 Aug 2017, David Gibson wrote:
> > > > On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
> > > > > Add emulation of aCube Sam460ex board based on AMCC 460EX embedded SoC.
> > > > > This is not a full implementation yet with a lot of components still
> > > > > missing but enough to start a Linux kernel and the U-Boot firmware.
> > > > > 
> > > > > Signed-off-by: François Revol <revol@free.fr>
> > > > > Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> > > > 
> > > > As usual, only fairly superficial review here.
> > > > 
> > > > > ---
> > > > >  default-configs/ppcemb-softmmu.mak |   3 +
> > > > >  hw/ppc/Makefile.objs               |   2 +
> > > > >  hw/ppc/sam460ex.c                  | 611 +++++++++++++++++++++++++++++++++++++
> > > > >  3 files changed, 616 insertions(+)
> > > > >  create mode 100644 hw/ppc/sam460ex.c
> > > > > 
> > > > > diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
> > > > > index 635923a..90b42f0 100644
> > > > > --- a/default-configs/ppcemb-softmmu.mak
> > > > > +++ b/default-configs/ppcemb-softmmu.mak
> > > [...]
> > > > > +/*****************************************************************************/
> > > > > +/* SPD eeprom content from mips_malta.c */
> > > > 
> > > > What's the connection with mips_malta?
> > > 
> > > The board's firmware wants to see SPD EEPROMs of the connected memory while
> > > initialising the memory controller. This is why we need to implement SDRAM
> > > controller, I2C and SPD EEPROMs. MIPS malta board had already SPD EEPROM
> > > implementation so this is based on that. The comment just indicates where
> > > this code comes from.
> > 
> > Ok.
> > 
> > [snip]
> > > > > +        env->nip = bi->entry;
> > > > > +
> > > > > +        /* Create a mapping for the kernel.  */
> > > > > +        mmubooke_create_initial_mapping(env, 0, 0);
> > > > > +        env->gpr[6] = tswap32(EPAPR_MAGIC);
> > > > 
> > > > I'm pretty sure the tswap can't be right here.  env->gpr is in host
> > > > native order and I'd expect the constant to be as well.
> > > 
> > > I know nothing about this, maybe Francois remembers why it's there. But
> > > booting linux with -kernel works so it's probably either correct or does not
> > > matter.
> > 
> > Have you attempted it on both BE and LE hosts though?
> 
> No, I don't have a BE host, only tried on LE. I'm guessing this may come
> from hw/ppc/virtex_ml507.c where EPAPR_MAGIC is also swapped.

Sounds like virtex is wrong too - bet they haven't tried on a BE host either.

> The only other
> place this magic number appears is in e500 where it's not swapped though so
> I don't really know what should be correct here. In u-boot sources
> (arch/powerpc/lib/bootm.c) it seems to use this magic if CONFIG_OF_LIBFDT is
> defined which seems to be set for this board so that means we likely need
> this (but maybe not for the legacy uImages I've tried). Since CPU is big
> endian and constant is defined on the host this probably should be
> cpu_to_be32(EPAPR_MAGIC). Does that sound better?

No.  It's going into a register, not memory, and the registers are in
host-native order, since they're being manipulated as whole values,
not byte arrays (the appropriate swaps for the guest endianness happen
when emulating load and store instructions).  Remember an integer is
just an integer - it's only when you encode it into a byte array that
it acquires an endianness.

Although it sounded from another part of this thread as if this might
be a non-epapr boot anyway, making the whole thing moot.

> [...]
> > > > > +    /* FIXME: remove this after fixing l2sram mapping in ppc440_uc.c? */
> > > > > +    memory_region_init_ram(l2cache_ram, NULL, "ppc440.l2cache_ram", 256 << 10,
> > > > > +                           &error_abort);
> > > > > +    memory_region_add_subregion(address_space_mem, 0x400000000LL, l2cache_ram);
> > > > > +
> > > > > +    /* USB */
> > > > > +    sysbus_create_simple(TYPE_PPC4xx_EHCI, 0x4bffd0400, uic[2][29]);
> > > > > +    dev = qdev_create(NULL, "sysbus-ohci");
> > > > > +    qdev_prop_set_string(dev, "masterbus", "usb-bus.0");
> > > > > +    qdev_prop_set_uint32(dev, "num-ports", 6);
> > > > > +    qdev_init_nofail(dev);
> > > > > +    sbdev = SYS_BUS_DEVICE(dev);
> > > > > +    sysbus_mmio_map(sbdev, 0, 0x4bffd0000);
> > > > > +    sysbus_connect_irq(sbdev, 0, uic[2][30]);
> > > > > +    usb_create_simple(usb_bus_find(-1), "usb-kbd");
> > > > > +    usb_create_simple(usb_bus_find(-1), "usb-mouse");
> > > > > +
> > > > > +    /* PCI bus */
> > > > > +    ppc460ex_pcie_init(env);
> > > > > +    /*XXX: FIXME: is this correct? */
> > > > > +    dev = sysbus_create_varargs("ppc440-pcix-host", 0xc0ec00000,
> > > > > +                                uic[1][0], uic[1][20], uic[1][21], uic[1][22],
> > > > > +                                NULL);
> > > > > +    pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
> > > > > +    if (!pci_bus) {
> > > > > +        fprintf(stderr, "couldn't create PCI controller!\n");
> > > > > +        exit(1);
> > > > > +    }
> > > > > +    memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(),
> > > > > +                             0, 0x10000);
> > > > > +    memory_region_add_subregion(get_system_memory(), 0xc08000000, isa);
> > > > 
> > > > Does it really make sense to just embed the ISA IO space here, rather
> > > > than actually instanting a PCI<->ISA bridge?
> > > 
> > > I'm not sure if this is correct but I don't know how it's handled on real
> > > hardware. The board does not have ISA and I don't think it has a bridge but
> > > the IO space appears at this location according to the datasheet (In System
> > > Memory Address Map it's listed as PCI I/O 0xc08000000-0xc0800ffff) and
> > > clients expect PCI card's io registers to be accessible here. If anyone
> > > knows how it's done on real hardware and if there's a better way to model
> > > this please let me know.
> > 
> > Ah, ok.  I think the confusion here is that you can have PCI I/O space
> > without ISA or a system IO space.  In fact that's pretty standard on
> > things without a CPU level IO space (which means just about everything
> > except x86).
> > 
> > But in that case I'd expect the PCI host bridge to map its IO memory
> > regions directly into address_space_memory rather than involving the
> > global address_space_io (what get_system_io()) returns.  The only
> > reason I can see that you'd need to involve get_system_io() is if you
> > have devices registering themselves directly into the global IO space,
> > which should only happen for legacy ISA devices, which it sounds like
> > you don't have.
> > 
> > Possibly this is an error in the PCI bridge implementation that your
> > code here is essentially a workaround for, though.
> 
> So in my understanding, there's a system_io space created automatically
> which appears in the memory tree anyway but would otherwise be unused and
> this was just reused here for the pci io space so it does not need another
> memory region for this. If it's not acceptable this way (although
> ppc440_bamboo.c and ppc4xx_pci.c also does it the exact same way) an
> alternative may be to change it to add another mem region for io to
> ppc440_pcix.c (although it already has iomem for pci.reg so this might be
> more confusing than using system_io here) but I think pcix device can't map
> this to address_space_memory itself because this device could appear in
> different SoCs where the memory areas might be at different addresses so
> this new region should then be registered as a sysbus mmio space and be
> mapped from the board code with sysbus_mmio_map()? I find that much more
> confusing than how it's done now which is also more consistent with existing
> code modelling similar devices.

Ugh, I see.  I hadn't realized bamboo etc. were doing this.  It's not
a good idea - most obviously it breaks down if you have multiple
independent PCI host bridges, which have independent IO spaces.

I'm a bit torn whether to let this in as is because precedent and hope
to get them all fixed at some future point, or to insist that you
change it to stop the bad idea spreading.

The right way is, indeed, to create a new memory region for the
bridge's IO space.  A SysBusDevice can have multiple MMIO regions, so
you can use one for the bridge's memory space, another for its IO
space (and still more for config space and/or bridge internal
registers if you need them).

> > > > > +    /* PCI devices */
> > > > > +    pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "sm501");
> > > > > +    /* SoC has a single SATA port but we don't emulate that yet
> > > > > +     * However, firmware and usual clients have driver for SiI311x
> > > > > +     * so add one for convenience by default */
> > > > > +    pci_create_simple(pci_bus, -1, "sii3112");
> > > > 
> > > > You should probably not create this when started with -nodefaults.
> > > 
> > > We don't emulate the on-board SATA port of the SoC and without this there's
> > > no other way to connect disks (maybe over USB, but firmware has a bug which
> > > prevents that too even on real hardware AFAIK, I've backported a fix which
> > > made booting from USB work but that broke keyboard) so while this is an
> > > external card it's pretty much unusable without this so it's added by
> > > default.
> > 
> > Yes, but you're not just adding it by default, you're adding it
> > *always*.  -nodefaults should turn that off (and the user will need to
> > manually instantiate it - or another disk controller, I guess).
> 
> OK I got it now. I still don't see when -nodefaults could be useful to
> cripple the board and make it easier to create non-working configurations
> but I can easily add this conditional around this line and hope users stay
> away from this switch and won't complain when it does not boot when they use
> it. (Well, it does not really boot most of the time without this switch
> either so I don't think it matters much at the moment :-) )

The convention exists because for non-trivial cases the next layer up
- whether it's a person or a management layer like livirt - often
needs more explicit and complete control of the device in the system.
Even if that's at the cost of having to explicitly add essential
devices.  It's still pretty imperfect, there's still a distinction
between "default" and "always present" devices which can be far from
obvious.

Nonetheless, I think the sil device lies firmly enough on the
"shouldn't be always present" side of the fuzzy line to exclude it
with -nodefaults.

Note that this can also be useful for experiments - e.g. just looking
at firmware behaviour with no disk at all, adding some entirely
different block interface with a specialized kernel to handle it.  Or
even booting into a kernel running purely from a ramfs with no disk.

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [PATCH 13/15] ppc4xx: Add more PLB registers
  2017-08-24 20:28         ` BALATON Zoltan
@ 2017-08-25  5:05           ` David Gibson
  0 siblings, 0 replies; 66+ messages in thread
From: David Gibson @ 2017-08-25  5:05 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Alexander Graf, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 2517 bytes --]

On Thu, Aug 24, 2017 at 10:28:15PM +0200, BALATON Zoltan wrote:
> On Thu, 24 Aug 2017, David Gibson wrote:
> > On Wed, Aug 23, 2017 at 12:16:24PM +0200, BALATON Zoltan wrote:
> > > On Wed, 23 Aug 2017, David Gibson wrote:
> > > > On Sun, Aug 20, 2017 at 07:23:05PM +0200, BALATON Zoltan wrote:
> > > > > These registers are present in 440 SoCs (and maybe in others too) and
> > > > > U-Boot accesses them when printing register info. We don't emulate
> > > > > these but add them to avoid crashing when they are read or written.
> > > > > 
> > > > > Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> > > > 
> > > > I'm ok with stub implementation, but I'm a bit uncomfortable with
> > > > registering these DCRs unconditionally rather than just on the chips
> > > > that actually implement them.
> > > 
> > > Problem is that I don't know which chips have these. I can only try to find
> > > out from the U-Boot sources where a comment says these are common registers
> > > for all SoCs (in u-boot/arch/powerpc/include/asm/ppc4xx.h:
> > > 
> > > http://git.denx.de/?p=u-boot.git;a=blob;f=arch/powerpc/include/asm/ppc4xx.h;h=45ff5dbacd9243e83bb2f6551e2dd64a7e544bf5;hb=e2351d5cf1e97408b4c52bafeaa85e0ca85c920c
> > > 
> > > while looking for this I've just noticed that u-boot has removed ppc440
> > > support just before 2017.07-rc3 so this is the last version that still has
> > > these files). So if that's true it should be OK for 405 too.
> > 
> > Ok, just to make sure I'm understanding correctly are you saying:
> > 
> > 1) You suspect these registers were actually on all versions of the
> >   device, they just weren't implemented until now.
> 
> That's what I suspect from the comment in the file quoted above but I don't
> have any other evidence.
> 
> > or
> > 
> > 2) The registers are definitely on only some versions of the device,
> >   but you're not sure which ones
> 
> I don't know any of these devices very well and have no definitive sources
> to confirm so I'm not sure but I think these should be on all the versions
> (at least on all three that QEMU emulates, namely 405, 440 and
> 460ex).

Ah, ok.  I couldn't seem to find any relevant manuals either.  Ok,
given the scanty evidence we have I'm ok with including the registers
always, as proposed.

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH 00/15] Sam460ex emulation
  2017-08-20 17:23 [Qemu-devel] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
                   ` (14 preceding siblings ...)
  2017-08-20 17:23 ` [Qemu-devel] [PATCH 08/15] ppc4xx_i2c: Implement basic I2C functions BALATON Zoltan
@ 2017-08-27 12:34 ` BALATON Zoltan
  2017-08-27 16:56   ` [Qemu-devel] Qemu 2.10 rc4 build issue on BE luigi burdo
  2017-08-29  7:34   ` [Qemu-devel] [Qemu-ppc] [PATCH 00/15] Sam460ex emulation David Gibson
  15 siblings, 2 replies; 66+ messages in thread
From: BALATON Zoltan @ 2017-08-27 12:34 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Francois Revol, David Gibson

Hello,

Just to confirm where we are with this series, let me summarise what I got 
from the replies and what's my plan for this based on that. Here's the 
list of patches for reference:

[PATCH 01/15] ppc4xx: Move MAL from ppc405_uc to ppc4xx_devs
[PATCH 02/15] ppc4xx: Make MAL emulation more generic
[PATCH 03/15] ohci: Allow sysbus version to be used as a companion
[PATCH 04/15] ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs
[PATCH 05/15] ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file
[PATCH 06/15] ppc4xx_i2c: QOMify
[PATCH 07/15] ppc4xx_i2c: Move to hw/i2c
[PATCH 08/15] ppc4xx_i2c: Implement basic I2C functions
[PATCH 09/15] hw/ide: Emulate SiI3112 SATA controller
[PATCH 10/15] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
[PATCH 11/15] ppc: Add 460EX embedded CPU
[PATCH 12/15] ppc4xx: Export ECB and PLB emulation
[PATCH 13/15] ppc4xx: Add more PLB registers
[PATCH 14/15] ppc4xx: Add device models found in PPC440 core SoCs
[PATCH 15/15] ppc: Add aCube Sam460ex board

- I think 1-7 is either already queued for 2.11 or could be applied as is 
having got reviews without need to change so I don't need to resend them. 
So are 11-13 if I got that right. That leaves 8-10 and 14-15 that I'll 
resend.

- I'm not sure if 8 was reviewed or do I need to make any modifications to 
it.

- I know I should change 9-10 and 14-15 based on review comments and 
resend.

Since I'll likely also need to change those patches to fix the bugs we 
know about currently, I thought I should probably resend after those bugs 
are fixed to avoid subsequent fixup patches. Since this will not be before 
next week (because I don't have time for it before that) I hope 
development should be open again and those patches that are already OK 
could be merged by then so I can rebase on that and only resend the 
missing ones as described above. Is that OK or did I miss something?

David, in case you want to stage all of this in your for-2.11 branch 
before all patches are ready and send them together, then where is this 
branch I should rebase to?

Regards,
BALATON Zoltan

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [Qemu-devel] Qemu 2.10 rc4 build issue on BE
  2017-08-27 12:34 ` [Qemu-devel] [Qemu-ppc] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
@ 2017-08-27 16:56   ` luigi burdo
  2017-08-28  9:20     ` [Qemu-devel] [Qemu-ppc] " Thomas Huth
  2017-08-28 15:56     ` [Qemu-devel] " Eric Blake
  2017-08-29  7:34   ` [Qemu-devel] [Qemu-ppc] [PATCH 00/15] Sam460ex emulation David Gibson
  1 sibling, 2 replies; 66+ messages in thread
From: luigi burdo @ 2017-08-27 16:56 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc

[-- Attachment #1: Type: text/plain, Size: 268 bytes --]

Hi all,

the last rc4 from the qemu website fail in build in some parts on BE hardware.

attached on this email there is the configure and the build log hope it helps


My machine is : PowerMac G5 Quad .

Distro is Ferdora 25 PPC64.



Thanks

Luigi


[-- Attachment #2: qemu_log.txt --]
[-- Type: text/plain, Size: 75783 bytes --]

 ./configure --target-list=ppc64-softmmu,ppc-softmmu,x86_64-softmmu,arm-softmmu,i386-softmmu --with-sdlabi=2.0 --with-gtkabi=3.0 --audio-drv-list=pa,sdl,alsa --disable-werror
Install prefix    /usr/local
BIOS directory    /usr/local/share/qemu
binary directory  /usr/local/bin
library directory /usr/local/lib
module directory  /usr/local/lib/qemu
libexec directory /usr/local/libexec
include directory /usr/local/include
config directory  /usr/local/etc
local state directory   /usr/local/var
Manual directory  /usr/local/share/man
ELF interp prefix /usr/gnemul/qemu-%M
Source path       /home/amigaone/Downloads/qemu-2.10.0-rc4
C compiler        cc
Host C compiler   cc
C++ compiler      c++
Objective-C compiler clang
ARFLAGS           rv
CFLAGS            -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -g 
QEMU_CFLAGS       -I/usr/include/pixman-1  -pthread -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -DNCURSES_WIDECHAR -D_GNU_SOURCE -m64 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv  -Wendif-labels -Wno-shift-negative-value -Wno-missing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -fstack-protector-strong -I/usr/include/p11-kit-1   -I/usr/include/libpng16 -I/usr/include/libdrm  -I/usr/include/libusb-1.0
LDFLAGS           -Wl,--warn-common -m64 -g 
make              make
install           install
python            python -B
smbd              /usr/sbin/smbd
module support    no
host CPU          ppc64
host big endian   yes
target list       ppc64-softmmu ppc-softmmu x86_64-softmmu arm-softmmu i386-softmmu
gprof enabled     no
sparse enabled    no
strip binaries    yes
profiler          no
static build      no
pixman            system
SDL support       yes (2.0.5)
GTK support       yes (3.22.17)
GTK GL support    yes
VTE support       no 
TLS priority      NORMAL
GNUTLS support    yes
GNUTLS rnd        yes
libgcrypt         no
libgcrypt kdf     no
nettle            yes (3.3)
nettle kdf        yes
libtasn1          yes
curses support    yes
virgl support     yes
curl support      no
mingw32 support   no
Audio drivers     pa sdl alsa
Block whitelist (rw) 
Block whitelist (ro) 
VirtFS support    yes
VNC support       yes
VNC SASL support  no
VNC JPEG support  yes
VNC PNG support   yes
xen support       no
brlapi support    no
bluez  support    no
Documentation     no
PIE               no
vde support       no
netmap support    no
Linux AIO support yes
ATTR/XATTR support yes
Install blobs     yes
KVM support       yes
HAX support       no
TCG support       yes
TCG debug enabled no
TCG interpreter   no
RDMA support      no
fdt support       yes
preadv support    yes
fdatasync         yes
madvise           yes
posix_madvise     yes
libcap-ng support no
vhost-net support yes
vhost-scsi support yes
vhost-vsock support yes
vhost-user support yes
Trace backends    log
spice support     no 
rbd support       no
xfsctl support    no
smartcard support no
libusb            yes
usb net redir     no
OpenGL support    yes
OpenGL dmabufs    yes
libiscsi support  no
libnfs support    no
build guest agent yes
QGA VSS support   no
QGA w32 disk info no
QGA MSI support   no
seccomp support   no
coroutine backend ucontext
coroutine pool    yes
debug stack usage no
crypto afalg      no
GlusterFS support no
gcov              gcov
gcov enabled      no
TPM support       yes
libssh2 support   no
TPM passthrough   no
QOM debugging     yes
Live block migration yes
lzo support       no
snappy support    yes
bzip2 support     yes
NUMA host support yes
tcmalloc support  no
jemalloc support  no
avx2 optimization no
replication support yes
VxHS block device no




[$ make -j4
  GEN     ppc64-softmmu/config-devices.mak.tmp
  GEN     ppc-softmmu/config-devices.mak.tmp
  GEN     x86_64-softmmu/config-devices.mak.tmp
  GEN     arm-softmmu/config-devices.mak.tmp
  GEN     arm-softmmu/config-devices.mak
  GEN     x86_64-softmmu/config-devices.mak
  GEN     ppc-softmmu/config-devices.mak
  GEN     ppc64-softmmu/config-devices.mak
  GEN     i386-softmmu/config-devices.mak.tmp
  GEN     config-host.h
  GEN     qemu-options.def
  GEN     qmp-commands.h
  GEN     i386-softmmu/config-devices.mak
  GEN     qapi-types.h
  GEN     qapi-visit.h
  GEN     qapi-event.h
  GEN     qmp-marshal.c
  GEN     qapi-types.c
  GEN     qapi-visit.c
  GEN     qapi-event.c
  GEN     qmp-introspect.h
  GEN     qmp-introspect.c
  GEN     trace/generated-tcg-tracers.h
  GEN     trace/generated-helpers-wrappers.h
  GEN     trace/generated-helpers.h
  GEN     trace/generated-helpers.c
  GEN     module_block.h
  GEN     tests/test-qapi-types.h
  GEN     tests/test-qapi-visit.h
  GEN     tests/test-qmp-commands.h
  GEN     tests/test-qapi-event.h
  GEN     tests/test-qmp-introspect.h
  GEN     trace-root.h
  GEN     util/trace.h
  GEN     crypto/trace.h
  GEN     io/trace.h
  GEN     migration/trace.h
  GEN     block/trace.h
  GEN     chardev/trace.h
  GEN     hw/block/trace.h
  GEN     hw/block/dataplane/trace.h
  GEN     hw/char/trace.h
  GEN     hw/intc/trace.h
  GEN     hw/net/trace.h
  GEN     hw/virtio/trace.h
  GEN     hw/audio/trace.h
  GEN     hw/misc/trace.h
  GEN     hw/usb/trace.h
  GEN     hw/scsi/trace.h
  GEN     hw/nvram/trace.h
  GEN     hw/display/trace.h
  GEN     hw/input/trace.h
  GEN     hw/timer/trace.h
  GEN     hw/dma/trace.h
  GEN     hw/sparc/trace.h
  GEN     hw/sd/trace.h
  GEN     hw/isa/trace.h
  GEN     hw/mem/trace.h
  GEN     hw/i386/trace.h
  GEN     hw/i386/xen/trace.h
  GEN     hw/9pfs/trace.h
  GEN     hw/ppc/trace.h
  GEN     hw/pci/trace.h
  GEN     hw/s390x/trace.h
  GEN     hw/vfio/trace.h
  GEN     hw/acpi/trace.h
  GEN     hw/arm/trace.h
  GEN     hw/alpha/trace.h
  GEN     hw/xen/trace.h
  GEN     ui/trace.h
  GEN     audio/trace.h
  GEN     net/trace.h
  GEN     target/arm/trace.h
  GEN     target/i386/trace.h
  GEN     target/mips/trace.h
  GEN     target/sparc/trace.h
  GEN     target/s390x/trace.h
  GEN     target/ppc/trace.h
  GEN     qom/trace.h
  GEN     linux-user/trace.h
  GEN     qapi/trace.h
  GEN     accel/tcg/trace.h
  GEN     accel/kvm/trace.h
  GEN     nbd/trace.h
  GEN     trace-root.c
  GEN     util/trace.c
  GEN     crypto/trace.c
  GEN     io/trace.c
  GEN     migration/trace.c
  GEN     block/trace.c
  GEN     chardev/trace.c
  GEN     hw/block/trace.c
  GEN     hw/block/dataplane/trace.c
  GEN     hw/char/trace.c
  GEN     hw/intc/trace.c
  GEN     hw/net/trace.c
  GEN     hw/virtio/trace.c
  GEN     hw/audio/trace.c
  GEN     hw/misc/trace.c
  GEN     hw/usb/trace.c
  GEN     hw/scsi/trace.c
  GEN     hw/nvram/trace.c
  GEN     hw/display/trace.c
  GEN     hw/input/trace.c
  GEN     hw/timer/trace.c
  GEN     hw/dma/trace.c
  GEN     hw/sparc/trace.c
  GEN     hw/sd/trace.c
  GEN     hw/isa/trace.c
  GEN     hw/mem/trace.c
  GEN     hw/i386/trace.c
  GEN     hw/i386/xen/trace.c
  GEN     hw/9pfs/trace.c
  GEN     hw/ppc/trace.c
  GEN     hw/pci/trace.c
  GEN     hw/s390x/trace.c
  GEN     hw/vfio/trace.c
  GEN     hw/acpi/trace.c
  GEN     hw/arm/trace.c
  GEN     hw/alpha/trace.c
  GEN     hw/xen/trace.c
  GEN     ui/trace.c
  GEN     audio/trace.c
  GEN     net/trace.c
  GEN     target/arm/trace.c
  GEN     target/i386/trace.c
  GEN     target/mips/trace.c
  GEN     target/sparc/trace.c
  GEN     target/s390x/trace.c
  GEN     target/ppc/trace.c
  GEN     qom/trace.c
  GEN     linux-user/trace.c
  GEN     qapi/trace.c
  GEN     accel/tcg/trace.c
  GEN     accel/kvm/trace.c
  GEN     nbd/trace.c
  GEN     config-all-devices.mak
  CC      tests/qemu-iotests/socket_scm_helper.o
  GEN     qga/qapi-generated/qga-qapi-types.h
  GEN     qga/qapi-generated/qga-qapi-visit.h
  GEN     qga/qapi-generated/qga-qmp-commands.h
  GEN     qga/qapi-generated/qga-qapi-types.c
  GEN     qga/qapi-generated/qga-qapi-visit.c
  GEN     qga/qapi-generated/qga-qmp-marshal.c
  CC      qmp-introspect.o
  CC      qapi-types.o
  CC      qapi-visit.o
  CC      qapi-event.o
  CC      qapi/qapi-visit-core.o
  CC      qapi/qobject-input-visitor.o
  CC      qapi/qapi-dealloc-visitor.o
  CC      qapi/qobject-output-visitor.o
  CC      qapi/qmp-registry.o
  CC      qapi/qmp-dispatch.o
  CC      qapi/string-input-visitor.o
  CC      qapi/string-output-visitor.o
  CC      qapi/opts-visitor.o
  CC      qapi/qapi-clone-visitor.o
  CC      qapi/qmp-event.o
  CC      qapi/qapi-util.o
  CC      qobject/qnull.o
  CC      qobject/qnum.o
  CC      qobject/qstring.o
  CC      qobject/qdict.o
  CC      qobject/qlist.o
  CC      qobject/qbool.o
  CC      qobject/qjson.o
  CC      qobject/qobject.o
  CC      qobject/json-lexer.o
  CC      qobject/json-streamer.o
  CC      qobject/json-parser.o
  CC      trace/control.o
  CC      trace/qmp.o
  CC      util/osdep.o
  CC      util/cutils.o
  CC      util/unicode.o
  CC      util/qemu-timer-common.o
  CC      util/bufferiszero.o
  CC      util/lockcnt.o
  CC      util/aiocb.o
  CC      util/async.o
  CC      util/thread-pool.o
  CC      util/qemu-timer.o
  CC      util/main-loop.o
  CC      util/iohandler.o
  CC      util/aio-posix.o
  CC      util/compatfd.o
  CC      util/event_notifier-posix.o
  CC      util/mmap-alloc.o
  CC      util/oslib-posix.o
  CC      util/qemu-openpty.o
  CC      util/qemu-thread-posix.o
  CC      util/memfd.o
  CC      util/envlist.o
  CC      util/path.o
  CC      util/module.o
  CC      util/host-utils.o
  CC      util/bitmap.o
  CC      util/bitops.o
  CC      util/hbitmap.o
  CC      util/fifo8.o
  CC      util/acl.o
  CC      util/cacheinfo.o
  CC      util/error.o
  CC      util/qemu-error.o
  CC      util/id.o
  CC      util/iov.o
  CC      util/qemu-config.o
  CC      util/qemu-sockets.o
  CC      util/uri.o
  CC      util/notify.o
  CC      util/qemu-option.o
  CC      util/qemu-progress.o
  CC      util/keyval.o
  CC      util/hexdump.o
  CC      util/crc32c.o
  CC      util/uuid.o
  CC      util/throttle.o
  CC      util/getauxval.o
  CC      util/readline.o
  CC      util/rcu.o
  CC      util/qemu-coroutine.o
  CC      util/qemu-coroutine-lock.o
  CC      util/qemu-coroutine-io.o
  CC      util/qemu-coroutine-sleep.o
  CC      util/coroutine-ucontext.o
  CC      util/buffer.o
  CC      util/timed-average.o
  CC      util/base64.o
  CC      util/log.o
  CC      util/qdist.o
  CC      util/qht.o
  CC      util/range.o
  CC      util/stats64.o
  CC      util/systemd.o
  CC      trace-root.o
  CC      util/trace.o
  CC      crypto/trace.o
  CC      io/trace.o
  CC      migration/trace.o
  CC      block/trace.o
  CC      chardev/trace.o
  CC      hw/block/trace.o
  CC      hw/block/dataplane/trace.o
  CC      hw/char/trace.o
  CC      hw/intc/trace.o
  CC      hw/net/trace.o
  CC      hw/virtio/trace.o
  CC      hw/audio/trace.o
  CC      hw/misc/trace.o
  CC      hw/usb/trace.o
  CC      hw/scsi/trace.o
  CC      hw/nvram/trace.o
  CC      hw/display/trace.o
  CC      hw/input/trace.o
  CC      hw/timer/trace.o
  CC      hw/dma/trace.o
  CC      hw/sparc/trace.o
  CC      hw/sd/trace.o
  CC      hw/isa/trace.o
  CC      hw/mem/trace.o
  CC      hw/i386/trace.o
  CC      hw/i386/xen/trace.o
  CC      hw/9pfs/trace.o
  CC      hw/ppc/trace.o
  CC      hw/pci/trace.o
  CC      hw/s390x/trace.o
  CC      hw/vfio/trace.o
  CC      hw/acpi/trace.o
  CC      hw/arm/trace.o
  CC      hw/alpha/trace.o
  CC      hw/xen/trace.o
  CC      ui/trace.o
  CC      audio/trace.o
  CC      net/trace.o
  CC      target/arm/trace.o
  CC      target/i386/trace.o
  CC      target/mips/trace.o
  CC      target/sparc/trace.o
  CC      target/s390x/trace.o
  CC      target/ppc/trace.o
  CC      qom/trace.o
  CC      linux-user/trace.o
  CC      qapi/trace.o
  CC      accel/tcg/trace.o
  CC      accel/kvm/trace.o
  CC      nbd/trace.o
  CC      crypto/pbkdf-stub.o
  CC      stubs/arch-query-cpu-def.o
  CC      stubs/arch-query-cpu-model-expansion.o
  CC      stubs/arch-query-cpu-model-comparison.o
  CC      stubs/arch-query-cpu-model-baseline.o
  CC      stubs/bdrv-next-monitor-owned.o
  CC      stubs/blk-commit-all.o
  CC      stubs/blockdev-close-all-bdrv-states.o
  CC      stubs/clock-warp.o
  CC      stubs/cpu-get-clock.o
  CC      stubs/cpu-get-icount.o
  CC      stubs/dump.o
  CC      stubs/error-printf.o
  CC      stubs/fdset.o
  CC      stubs/gdbstub.o
  CC      stubs/get-vm-name.o
  CC      stubs/iothread.o
  CC      stubs/iothread-lock.o
  CC      stubs/is-daemonized.o
  CC      stubs/linux-aio.o
  CC      stubs/machine-init-done.o
  CC      stubs/migr-blocker.o
  CC      stubs/change-state-handler.o
  CC      stubs/monitor.o
  CC      stubs/notify-event.o
  CC      stubs/qtest.o
  CC      stubs/replay.o
  CC      stubs/runstate-check.o
  CC      stubs/set-fd-handler.o
  CC      stubs/slirp.o
  CC      stubs/sysbus.o
  CC      stubs/trace-control.o
  CC      stubs/uuid.o
  CC      stubs/vm-stop.o
  CC      stubs/vmstate.o
  CC      stubs/qmp_pc_dimm_device_list.o
  CC      stubs/target-monitor-defs.o
  CC      stubs/target-get-monitor-def.o
  CC      stubs/pc_madt_cpu_entry.o
  CC      stubs/vmgenid.o
  CC      stubs/xen-common.o
  CC      stubs/xen-hvm.o
  CC      contrib/ivshmem-client/ivshmem-client.o
  CC      contrib/ivshmem-client/main.o
  CC      contrib/ivshmem-server/ivshmem-server.o
  CC      contrib/ivshmem-server/main.o
  CC      qemu-nbd.o
  CC      block.o
  CC      blockjob.o
  CC      qemu-io-cmds.o
  CC      replication.o
  CC      block/raw-format.o
  CC      block/qcow.o
  CC      block/vdi.o
  CC      block/vmdk.o
  CC      block/cloop.o
  CC      block/bochs.o
  CC      block/vpc.o
  CC      block/vvfat.o
  CC      block/dmg.o
  CC      block/qcow2.o
  CC      block/qcow2-refcount.o
  CC      block/qcow2-cluster.o
  CC      block/qcow2-snapshot.o
  CC      block/qcow2-cache.o
  CC      block/qcow2-bitmap.o
  CC      block/qed.o
  CC      block/qed-l2-cache.o
  CC      block/qed-table.o
  CC      block/qed-cluster.o
  CC      block/qed-check.o
  CC      block/vhdx.o
  CC      block/vhdx-endian.o
  CC      block/vhdx-log.o
  CC      block/quorum.o
  CC      block/parallels.o
  CC      block/blkdebug.o
  CC      block/blkverify.o
  CC      block/blkreplay.o
  CC      block/block-backend.o
  CC      block/snapshot.o
  CC      block/qapi.o
  CC      block/file-posix.o
  CC      block/linux-aio.o
  CC      block/null.o
  CC      block/mirror.o
  CC      block/commit.o
  CC      block/io.o
  CC      block/throttle-groups.o
  CC      block/nbd.o
  CC      block/nbd-client.o
  CC      block/sheepdog.o
  CC      block/accounting.o
  CC      block/dirty-bitmap.o
  CC      block/write-threshold.o
  CC      block/backup.o
  CC      block/crypto.o
  CC      block/replication.o
  CC      nbd/server.o
  CC      nbd/client.o
  CC      nbd/common.o
  CC      block/dmg-bz2.o
  CC      crypto/init.o
  CC      crypto/hash.o
  CC      crypto/hash-nettle.o
  CC      crypto/hmac.o
  CC      crypto/hmac-nettle.o
  CC      crypto/aes.o
  CC      crypto/desrfb.o
  CC      crypto/cipher.o
  CC      crypto/tlscreds.o
  CC      crypto/tlscredsanon.o
  CC      crypto/tlscredsx509.o
  CC      crypto/tlssession.o
  CC      crypto/secret.o
  CC      crypto/random-gnutls.o
  CC      crypto/pbkdf.o
  CC      crypto/pbkdf-nettle.o
  CC      crypto/ivgen.o
  CC      crypto/ivgen-essiv.o
  CC      crypto/ivgen-plain.o
  CC      crypto/ivgen-plain64.o
  CC      crypto/afsplit.o
  CC      crypto/xts.o
  CC      crypto/block.o
  CC      crypto/block-qcow.o
  CC      crypto/block-luks.o
  CC      io/channel.o
  CC      io/channel-buffer.o
  CC      io/channel-command.o
  CC      io/channel-file.o
  CC      io/channel-socket.o
  CC      io/channel-tls.o
  CC      io/channel-watch.o
  CC      io/channel-websock.o
  CC      io/channel-util.o
  CC      io/dns-resolver.o
  CC      io/task.o
  CC      qom/object.o
  CC      qom/container.o
  CC      qom/qom-qobject.o
  CC      qom/object_interfaces.o
  GEN     qemu-img-cmds.h
  CC      qemu-io.o
  CC      fsdev/virtfs-proxy-helper.o
  CC      fsdev/9p-marshal.o
  CC      fsdev/9p-iov-marshal.o
  CC      qemu-bridge-helper.o
  CC      blockdev.o
  CC      blockdev-nbd.o
  CC      bootdevice.o
  CC      iothread.o
  CC      qdev-monitor.o
  CC      device-hotplug.o
  CC      os-posix.o
  CC      bt-host.o
  CC      bt-vhci.o
  CC      dma-helpers.o
  CC      vl.o
  CC      tpm.o
  CC      device_tree.o
  CC      qmp-marshal.o
  CC      qmp.o
  CC      hmp.o
  CC      cpus-common.o
  CC      audio/audio.o
  CC      audio/noaudio.o
  CC      audio/wavaudio.o
  CC      audio/mixeng.o
  CC      audio/sdlaudio.o
  CC      audio/alsaaudio.o
  CC      audio/paaudio.o
  CC      audio/audio_pt_int.o
  CC      audio/wavcapture.o
  CC      backends/rng.o
  CC      backends/rng-egd.o
  CC      backends/rng-random.o
  CC      backends/tpm.o
  CC      backends/hostmem.o
  CC      backends/hostmem-ram.o
  CC      backends/hostmem-file.o
  CC      backends/cryptodev.o
  CC      backends/cryptodev-builtin.o
  CC      block/stream.o
  CC      chardev/msmouse.o
  CC      chardev/wctablet.o
  CC      chardev/testdev.o
  CC      disas/arm.o
  CXX     disas/arm-a64.o
  CC      disas/i386.o
  CC      disas/ppc.o
  CXX     disas/libvixl/vixl/utils.o
  CXX     disas/libvixl/vixl/compiler-intrinsics.o
  CXX     disas/libvixl/vixl/a64/instructions-a64.o
  CXX     disas/libvixl/vixl/a64/decoder-a64.o
  CXX     disas/libvixl/vixl/a64/disasm-a64.o
  CC      fsdev/qemu-fsdev.o
  CC      fsdev/qemu-fsdev-opts.o
  CC      fsdev/qemu-fsdev-throttle.o
  CC      fsdev/qemu-fsdev-dummy.o
  CC      hw/9pfs/9p.o
  CC      hw/9pfs/9p-util.o
  CC      hw/9pfs/9p-local.o
  CC      hw/9pfs/9p-xattr.o
  CC      hw/9pfs/9p-xattr-user.o
  CC      hw/9pfs/9p-posix-acl.o
  CC      hw/9pfs/coth.o
  CC      hw/9pfs/cofs.o
  CC      hw/9pfs/codir.o
  CC      hw/9pfs/cofile.o
  CC      hw/9pfs/coxattr.o
  CC      hw/9pfs/9p-synth.o
  CC      hw/9pfs/9p-handle.o
  CC      hw/9pfs/9p-proxy.o
  CC      hw/acpi/core.o
  CC      hw/acpi/piix4.o
  CC      hw/acpi/pcihp.o
  CC      hw/acpi/ich9.o
  CC      hw/acpi/tco.o
  CC      hw/acpi/cpu_hotplug.o
  CC      hw/acpi/memory_hotplug.o
  CC      hw/acpi/cpu.o
  CC      hw/acpi/nvdimm.o
  CC      hw/acpi/vmgenid.o
  CC      hw/acpi/acpi_interface.o
  CC      hw/acpi/bios-linker-loader.o
  CC      hw/acpi/aml-build.o
  CC      hw/acpi/ipmi.o
  CC      hw/acpi/acpi-stub.o
  CC      hw/acpi/ipmi-stub.o
  CC      hw/audio/sb16.o
  CC      hw/audio/es1370.o
  CC      hw/audio/ac97.o
  CC      hw/audio/fmopl.o
  CC      hw/audio/adlib.o
  CC      hw/audio/gus.o
  CC      hw/audio/gusemu_hal.o
  CC      hw/audio/gusemu_mixer.o
  CC      hw/audio/cs4231a.o
  CC      hw/audio/intel-hda.o
  CC      hw/audio/hda-codec.o
  CC      hw/audio/pcspk.o
  CC      hw/audio/wm8750.o
  CC      hw/audio/pl041.o
  CC      hw/audio/lm4549.o
  CC      hw/audio/marvell_88w8618.o
  CC      hw/audio/soundhw.o
  CC      hw/block/block.o
  CC      hw/block/cdrom.o
  CC      hw/block/hd-geometry.o
  CC      hw/block/fdc.o
  CC      hw/block/m25p80.o
  CC      hw/block/nand.o
  CC      hw/block/pflash_cfi01.o
  CC      hw/block/pflash_cfi02.o
  CC      hw/block/ecc.o
  CC      hw/block/onenand.o
  CC      hw/block/nvme.o
  CC      hw/bt/core.o
  CC      hw/bt/l2cap.o
  CC      hw/bt/sdp.o
  CC      hw/bt/hci.o
  CC      hw/bt/hid.o
  CC      hw/bt/hci-csr.o
  CC      hw/char/ipoctal232.o
  CC      hw/char/escc.o
  CC      hw/char/parallel.o
  CC      hw/char/pl011.o
  CC      hw/char/serial.o
  CC      hw/char/serial-isa.o
  CC      hw/char/serial-pci.o
  CC      hw/char/virtio-console.o
  CC      hw/char/xilinx_uartlite.o
  CC      hw/char/cadence_uart.o
  CC      hw/char/cmsdk-apb-uart.o
  CC      hw/char/debugcon.o
  CC      hw/char/imx_serial.o
  CC      hw/core/qdev.o
  CC      hw/core/qdev-properties.o
  CC      hw/core/bus.o
  CC      hw/core/reset.o
  CC      hw/core/fw-path-provider.o
  CC      hw/core/irq.o
  CC      hw/core/hotplug.o
  CC      hw/core/nmi.o
  CC      hw/core/ptimer.o
  CC      hw/core/sysbus.o
  CC      hw/core/machine.o
  CC      hw/core/loader.o
  CC      hw/core/qdev-properties-system.o
  CC      hw/core/register.o
  CC      hw/core/or-irq.o
  CC      hw/core/platform-bus.o
  CC      hw/cpu/core.o
  CC      hw/display/ads7846.o
  CC      hw/display/cirrus_vga.o
  CC      hw/display/pl110.o
  CC      hw/display/ssd0303.o
  CC      hw/display/ssd0323.o
  CC      hw/display/vga-pci.o
  CC      hw/display/vga-isa.o
  CC      hw/display/vmware_vga.o
  CC      hw/display/blizzard.o
  CC      hw/display/exynos4210_fimd.o
  CC      hw/display/framebuffer.o
  CC      hw/display/tc6393xb.o
  CC      hw/dma/pl080.o
  CC      hw/dma/pl330.o
  CC      hw/dma/i82374.o
  CC      hw/dma/i8257.o
  CC      hw/dma/xlnx-zynq-devcfg.o
  CC      hw/gpio/max7310.o
  CC      hw/gpio/pl061.o
  CC      hw/gpio/zaurus.o
  CC      hw/gpio/mpc8xxx.o
  CC      hw/gpio/gpio_key.o
  CC      hw/i2c/core.o
  CC      hw/i2c/smbus.o
  CC      hw/i2c/smbus_eeprom.o
  CC      hw/i2c/versatile_i2c.o
  CC      hw/i2c/smbus_ich9.o
  CC      hw/i2c/pm_smbus.o
  CC      hw/i2c/bitbang_i2c.o
  CC      hw/i2c/exynos4210_i2c.o
  CC      hw/i2c/imx_i2c.o
  CC      hw/i2c/aspeed_i2c.o
  CC      hw/ide/core.o
  CC      hw/ide/atapi.o
  CC      hw/ide/qdev.o
  CC      hw/ide/pci.o
  CC      hw/ide/isa.o
  CC      hw/ide/piix.o
  CC      hw/ide/cmd646.o
  CC      hw/ide/macio.o
  CC      hw/ide/microdrive.o
  CC      hw/ide/ahci.o
  CC      hw/ide/ich.o
  CC      hw/input/adb.o
  CC      hw/input/hid.o
  CC      hw/input/lm832x.o
  CC      hw/input/pckbd.o
  CC      hw/input/pl050.o
  CC      hw/input/ps2.o
  CC      hw/input/stellaris_input.o
  CC      hw/input/tsc2005.o
  CC      hw/input/vmmouse.o
  CC      hw/input/virtio-input.o
  CC      hw/input/virtio-input-hid.o
  CC      hw/input/virtio-input-host.o
  CC      hw/intc/heathrow_pic.o
  CC      hw/intc/i8259_common.o
  CC      hw/intc/i8259.o
  CC      hw/intc/pl190.o
  CC      hw/intc/xilinx_intc.o
  CC      hw/intc/imx_avic.o
  CC      hw/intc/realview_gic.o
  CC      hw/intc/ioapic_common.o
  CC      hw/intc/arm_gic_common.o
  CC      hw/intc/arm_gic.o
  CC      hw/intc/arm_gicv2m.o
  CC      hw/intc/arm_gicv3_common.o
  CC      hw/intc/arm_gicv3.o
  CC      hw/intc/arm_gicv3_dist.o
  CC      hw/intc/arm_gicv3_redist.o
  CC      hw/intc/arm_gicv3_its_common.o
  CC      hw/intc/openpic.o
  CC      hw/intc/intc.o
  CC      hw/ipack/ipack.o
  CC      hw/ipack/tpci200.o
  CC      hw/ipmi/ipmi.o
  CC      hw/ipmi/ipmi_bmc_sim.o
  CC      hw/ipmi/ipmi_bmc_extern.o
  CC      hw/ipmi/isa_ipmi_kcs.o
  CC      hw/ipmi/isa_ipmi_bt.o
  CC      hw/isa/isa-bus.o
  CC      hw/isa/apm.o
  CC      hw/isa/i82378.o
  CC      hw/isa/pc87312.o
  CC      hw/mem/pc-dimm.o
  CC      hw/mem/nvdimm.o
  CC      hw/misc/applesmc.o
  CC      hw/misc/max111x.o
  CC      hw/misc/tmp105.o
  CC      hw/misc/tmp421.o
  CC      hw/misc/debugexit.o
  CC      hw/misc/sga.o
  CC      hw/misc/pc-testdev.o
  CC      hw/misc/pci-testdev.o
  CC      hw/misc/edu.o
  CC      hw/misc/unimp.o
  CC      hw/misc/arm_l2x0.o
  CC      hw/misc/arm_integrator_debug.o
  CC      hw/misc/a9scu.o
  CC      hw/misc/arm11scu.o
  CC      hw/misc/macio/macio.o
  CC      hw/misc/macio/cuda.o
  CC      hw/misc/macio/mac_dbdma.o
  CC      hw/net/ne2000.o
  CC      hw/net/eepro100.o
  CC      hw/net/pcnet-pci.o
  CC      hw/net/pcnet.o
  CC      hw/net/e1000.o
  CC      hw/net/e1000x_common.o
  CC      hw/net/net_tx_pkt.o
  CC      hw/net/net_rx_pkt.o
  CC      hw/net/e1000e.o
  CC      hw/net/e1000e_core.o
  CC      hw/net/rtl8139.o
  CC      hw/net/vmxnet3.o
  CC      hw/net/smc91c111.o
  CC      hw/net/lan9118.o
  CC      hw/net/ne2000-isa.o
  CC      hw/net/xgmac.o
  CC      hw/net/allwinner_emac.o
  CC      hw/net/imx_fec.o
  CC      hw/net/cadence_gem.o
  CC      hw/net/stellaris_enet.o
  CC      hw/net/ftgmac100.o
  CC      hw/net/rocker/rocker.o
  CC      hw/net/rocker/rocker_fp.o
  CC      hw/net/rocker/rocker_desc.o
  CC      hw/net/rocker/rocker_world.o
  CC      hw/net/rocker/rocker_of_dpa.o
  CC      hw/nvram/eeprom93xx.o
  CC      hw/nvram/fw_cfg.o
  CC      hw/nvram/chrp_nvram.o
  CC      hw/nvram/mac_nvram.o
  CC      hw/pci-bridge/pci_bridge_dev.o
  CC      hw/pci-bridge/pcie_root_port.o
  CC      hw/pci-bridge/gen_pcie_root_port.o
  CC      hw/pci-bridge/pci_expander_bridge.o
  CC      hw/pci-bridge/xio3130_upstream.o
  CC      hw/pci-bridge/xio3130_downstream.o
  CC      hw/pci-bridge/ioh3420.o
  CC      hw/pci-bridge/i82801b11.o
  CC      hw/pci-bridge/dec.o
  CC      hw/pci-host/pam.o
  CC      hw/pci-host/prep.o
  CC      hw/pci-host/grackle.o
  CC      hw/pci-host/uninorth.o
  CC      hw/pci-host/ppce500.o
  CC      hw/pci-host/versatile.o
  CC      hw/pci-host/piix.o
  CC      hw/pci-host/q35.o
  CC      hw/pci-host/gpex.o
  CC      hw/pci/pci.o
  CC      hw/pci/pci_bridge.o
  CC      hw/pci/msix.o
  CC      hw/pci/msi.o
  CC      hw/pci/shpc.o
  CC      hw/pci/slotid_cap.o
  CC      hw/pci/pci_host.o
  CC      hw/pci/pcie_host.o
  CC      hw/pci/pcie.o
  CC      hw/pci/pcie_aer.o
  CC      hw/pci/pcie_port.o
  CC      hw/pci/pci-stub.o
  CC      hw/pcmcia/pcmcia.o
  CC      hw/scsi/scsi-disk.o
  CC      hw/scsi/scsi-generic.o
  CC      hw/scsi/scsi-bus.o
  CC      hw/scsi/lsi53c895a.o
  CC      hw/scsi/mptsas.o
  CC      hw/scsi/mptconfig.o
  CC      hw/scsi/mptendian.o
  CC      hw/scsi/megasas.o
  CC      hw/scsi/vmw_pvscsi.o
  CC      hw/scsi/esp.o
  CC      hw/scsi/esp-pci.o
  CC      hw/sd/pl181.o
  CC      hw/sd/ssi-sd.o
  CC      hw/sd/sd.o
  CC      hw/sd/core.o
  CC      hw/sd/sdhci.o
  CC      hw/smbios/smbios.o
  CC      hw/smbios/smbios_type_38.o
  CC      hw/smbios/smbios-stub.o
  CC      hw/smbios/smbios_type_38-stub.o
  CC      hw/ssi/pl022.o
  CC      hw/ssi/ssi.o
  CC      hw/ssi/xilinx_spips.o
  CC      hw/ssi/aspeed_smc.o
  CC      hw/ssi/stm32f2xx_spi.o
  CC      hw/timer/arm_timer.o
  CC      hw/timer/arm_mptimer.o
  CC      hw/timer/armv7m_systick.o
  CC      hw/timer/a9gtimer.o
  CC      hw/timer/cadence_ttc.o
  CC      hw/timer/ds1338.o
  CC      hw/timer/hpet.o
  CC      hw/timer/i8254_common.o
  CC      hw/timer/i8254.o
  CC      hw/timer/m48t59.o
  CC      hw/timer/m48t59-isa.o
  CC      hw/timer/pl031.o
  CC      hw/timer/twl92230.o
  CC      hw/timer/xilinx_timer.o
  CC      hw/timer/imx_epit.o
  CC      hw/timer/imx_gpt.o
  CC      hw/timer/stm32f2xx_timer.o
  CC      hw/timer/aspeed_timer.o
  CC      hw/timer/cmsdk-apb-timer.o
  CC      hw/tpm/tpm_tis.o
  CC      hw/usb/core.o
  CC      hw/usb/combined-packet.o
  CC      hw/usb/bus.o
  CC      hw/usb/libhw.o
  CC      hw/usb/desc.o
  CC      hw/usb/desc-msos.o
  CC      hw/usb/hcd-uhci.o
  CC      hw/usb/hcd-ohci.o
  CC      hw/usb/hcd-ehci.o
  CC      hw/usb/hcd-ehci-pci.o
  CC      hw/usb/hcd-ehci-sysbus.o
  CC      hw/usb/hcd-xhci.o
  CC      hw/usb/hcd-xhci-nec.o
  CC      hw/usb/hcd-musb.o
  CC      hw/usb/dev-hub.o
  CC      hw/usb/dev-hid.o
  CC      hw/usb/dev-wacom.o
  CC      hw/usb/dev-storage.o
  CC      hw/usb/dev-uas.o
  CC      hw/usb/dev-audio.o
  CC      hw/usb/dev-serial.o
  CC      hw/usb/dev-network.o
  CC      hw/usb/dev-bluetooth.o
  CC      hw/usb/dev-smartcard-reader.o
  CC      hw/usb/dev-mtp.o
  CC      hw/usb/host-libusb.o
  CC      hw/usb/host-legacy.o
  CC      hw/virtio/virtio-rng.o
  CC      hw/virtio/virtio-pci.o
  CC      hw/virtio/virtio-bus.o
  CC      hw/virtio/virtio-mmio.o
  CC      hw/virtio/vhost-stub.o
  CC      hw/watchdog/watchdog.o
  CC      hw/watchdog/wdt_i6300esb.o
  CC      hw/watchdog/wdt_ib700.o
  CC      hw/watchdog/wdt_aspeed.o
  CC      migration/migration.o
  CC      migration/socket.o
  CC      migration/fd.o
  CC      migration/exec.o
  CC      migration/tls.o
  CC      migration/channel.o
  CC      migration/savevm.o
  CC      migration/colo-comm.o
  CC      migration/colo.o
  CC      migration/colo-failover.o
  CC      migration/vmstate.o
  CC      migration/vmstate-types.o
  CC      migration/page_cache.o
  CC      migration/qemu-file.o
  CC      migration/global_state.o
  CC      migration/qemu-file-channel.o
  CC      migration/xbzrle.o
  CC      migration/postcopy-ram.o
  CC      migration/qjson.o
  CC      migration/block.o
  CC      net/net.o
  CC      net/queue.o
  CC      net/checksum.o
  CC      net/util.o
  CC      net/hub.o
  CC      net/socket.o
  CC      net/dump.o
  CC      net/eth.o
  CC      net/l2tpv3.o
  CC      net/vhost-user.o
  CC      net/slirp.o
  CC      net/filter.o
  CC      net/filter-buffer.o
  CC      net/filter-mirror.o
  CC      net/colo-compare.o
  CC      net/colo.o
  CC      net/filter-rewriter.o
  CC      net/filter-replay.o
  CC      net/tap.o
  CC      net/tap-linux.o
  CC      qom/cpu.o
  CC      replay/replay.o
  CC      replay/replay-internal.o
  CC      replay/replay-events.o
  CC      replay/replay-time.o
  CC      replay/replay-input.o
  CC      replay/replay-char.o
  CC      replay/replay-snapshot.o
  CC      replay/replay-net.o
  CC      replay/replay-audio.o
  CC      slirp/cksum.o
  CC      slirp/if.o
  CC      slirp/ip_icmp.o
  CC      slirp/ip6_icmp.o
  CC      slirp/ip6_input.o
  CC      slirp/ip6_output.o
  CC      slirp/ip_input.o
  CC      slirp/ip_output.o
  CC      slirp/dnssearch.o
  CC      slirp/dhcpv6.o
  CC      slirp/slirp.o
  CC      slirp/mbuf.o
  CC      slirp/misc.o
  CC      slirp/sbuf.o
  CC      slirp/socket.o
  CC      slirp/tcp_input.o
  CC      slirp/tcp_output.o
  CC      slirp/tcp_subr.o
  CC      slirp/tcp_timer.o
  CC      slirp/udp.o
  CC      slirp/udp6.o
  CC      slirp/bootp.o
  CC      slirp/tftp.o
  CC      slirp/arp_table.o
  CC      slirp/ndp_table.o
  CC      slirp/ncsi.o
  CC      ui/keymaps.o
  CC      ui/console.o
  CC      ui/cursor.o
  CC      ui/qemu-pixman.o
  CC      ui/input.o
  CC      ui/input-keymap.o
  CC      ui/input-legacy.o
  CC      ui/input-linux.o
  CC      ui/sdl2.o
  CC      ui/sdl2-input.o
  CC      ui/sdl2-2d.o
  CC      ui/sdl2-gl.o
  CC      ui/x_keymap.o
  CC      ui/curses.o
  CC      ui/vnc.o
  CC      ui/vnc-enc-zlib.o
  CC      ui/vnc-enc-hextile.o
  CC      ui/vnc-enc-tight.o
  CC      ui/vnc-palette.o
  CC      ui/vnc-enc-zrle.o
  CC      ui/vnc-auth-vencrypt.o
  CC      ui/vnc-ws.o
  CC      ui/vnc-jobs.o
  CC      ui/gtk.o
  CC      ui/shader.o
  VERT    ui/shader/texture-blit-vert.h
  FRAG    ui/shader/texture-blit-frag.h
  CC      ui/egl-helpers.o
  CC      ui/egl-context.o
  CC      ui/egl-headless.o
  CC      ui/gtk-gl-area.o
  CC      chardev/char.o
  CC      chardev/char-fd.o
  CC      chardev/char-fe.o
  CC      chardev/char-file.o
  CC      chardev/char-io.o
  CC      chardev/char-mux.o
  CC      chardev/char-null.o
  CC      chardev/char-parallel.o
  CC      chardev/char-pipe.o
  CC      chardev/char-pty.o
  CC      chardev/char-ringbuf.o
  CC      chardev/char-serial.o
  CC      chardev/char-socket.o
  CC      chardev/char-stdio.o
  CC      chardev/char-udp.o
  CCAS    spapr-rtas/spapr-rtas.o
  Building spapr-rtas/spapr-rtas.img
  Building spapr-rtas/spapr-rtas.bin
rm spapr-rtas.img spapr-rtas.o
  LINK    tests/qemu-iotests/socket_scm_helper
  CC      qga/commands.o
  CC      qga/guest-agent-command-state.o
  CC      qga/main.o
  CC      qga/commands-posix.o
  CC      qga/channel-posix.o
  CC      qga/qapi-generated/qga-qapi-types.o
  CC      qga/qapi-generated/qga-qapi-visit.o
  CC      qga/qapi-generated/qga-qmp-marshal.o
  AR      libqemuutil.a
  AR      libqemustub.a
  CC      qemu-img.o
  LINK    qemu-io
  LINK    fsdev/virtfs-proxy-helper
  LINK    qemu-bridge-helper
  CC      ui/console-gl.o
  LINK    qemu-ga
  LINK    ivshmem-client
  LINK    ivshmem-server
  LINK    qemu-nbd
  GEN     ppc64-softmmu/hmp-commands.h
  CC      ppc64-softmmu/exec.o
  GEN     ppc-softmmu/hmp-commands.h
  CC      ppc-softmmu/exec.o
  GEN     x86_64-softmmu/hmp-commands.h
  CC      x86_64-softmmu/exec.o
  GEN     arm-softmmu/hmp-commands.h
  CC      arm-softmmu/exec.o
  CC      ppc64-softmmu/tcg/tcg.o
  CC      ppc-softmmu/tcg/tcg.o
  CC      x86_64-softmmu/tcg/tcg.o
  CC      arm-softmmu/tcg/tcg.o
  CC      ppc64-softmmu/tcg/tcg-op.o
  CC      x86_64-softmmu/tcg/tcg-op.o
  CC      ppc-softmmu/tcg/tcg-op.o
  CC      arm-softmmu/tcg/tcg-op.o
  CC      x86_64-softmmu/tcg/optimize.o
  CC      ppc64-softmmu/tcg/optimize.o
  CC      ppc-softmmu/tcg/optimize.o
  CC      arm-softmmu/tcg/optimize.o
  CC      x86_64-softmmu/tcg/tcg-common.o
  CC      ppc64-softmmu/tcg/tcg-common.o
  CC      ppc-softmmu/tcg/tcg-common.o
  CC      x86_64-softmmu/tcg/tcg-runtime.o
  CC      ppc64-softmmu/tcg/tcg-runtime.o
  CC      arm-softmmu/tcg/tcg-common.o
  CC      ppc-softmmu/tcg/tcg-runtime.o
  CC      arm-softmmu/tcg/tcg-runtime.o
  CC      x86_64-softmmu/fpu/softfloat.o
  CC      ppc64-softmmu/fpu/softfloat.o
  CC      ppc-softmmu/fpu/softfloat.o
  CC      arm-softmmu/fpu/softfloat.o
  CC      ppc64-softmmu/disas.o
  CC      x86_64-softmmu/disas.o
  CC      ppc-softmmu/disas.o
  GEN     ppc64-softmmu/gdbstub-xml.c
  GEN     x86_64-softmmu/gdbstub-xml.c
  GEN     ppc-softmmu/gdbstub-xml.c
  CC      x86_64-softmmu/hax-stub.o
  CC      ppc64-softmmu/hax-stub.o
  CC      ppc-softmmu/hax-stub.o
  CC      arm-softmmu/disas.o
  CC      x86_64-softmmu/arch_init.o
  CC      ppc64-softmmu/libdecnumber/decContext.o
  CC      ppc-softmmu/libdecnumber/decContext.o
  CC      x86_64-softmmu/cpus.o
  CC      ppc64-softmmu/libdecnumber/decNumber.o
  GEN     arm-softmmu/gdbstub-xml.c
  CC      ppc-softmmu/libdecnumber/decNumber.o
  CC      arm-softmmu/hax-stub.o
  CC      arm-softmmu/arch_init.o
  CC      arm-softmmu/cpus.o
  CC      x86_64-softmmu/monitor.o
  CC      arm-softmmu/monitor.o
  CC      ppc64-softmmu/libdecnumber/dpd/decimal32.o
  CC      ppc-softmmu/libdecnumber/dpd/decimal32.o
  CC      ppc64-softmmu/libdecnumber/dpd/decimal64.o
  CC      ppc-softmmu/libdecnumber/dpd/decimal64.o
  CC      x86_64-softmmu/gdbstub.o
  CC      ppc64-softmmu/libdecnumber/dpd/decimal128.o
  CC      ppc-softmmu/libdecnumber/dpd/decimal128.o
  CC      ppc-softmmu/arch_init.o
  CC      ppc64-softmmu/arch_init.o
  CC      arm-softmmu/gdbstub.o
  CC      ppc-softmmu/cpus.o
  CC      ppc64-softmmu/cpus.o
  CC      x86_64-softmmu/balloon.o
  CC      x86_64-softmmu/ioport.o
  CC      arm-softmmu/balloon.o
  CC      x86_64-softmmu/numa.o
  CC      ppc64-softmmu/monitor.o
  CC      ppc-softmmu/monitor.o
  CC      arm-softmmu/ioport.o
  CC      x86_64-softmmu/qtest.o
  CC      arm-softmmu/numa.o
  CC      x86_64-softmmu/memory.o
  CC      arm-softmmu/qtest.o
  CC      arm-softmmu/memory.o
  CC      ppc64-softmmu/gdbstub.o
  CC      ppc-softmmu/gdbstub.o
  CC      x86_64-softmmu/memory_mapping.o
  CC      ppc64-softmmu/balloon.o
  CC      ppc-softmmu/balloon.o
  CC      x86_64-softmmu/dump.o
  CC      ppc64-softmmu/ioport.o
  CC      ppc-softmmu/ioport.o
  CC      arm-softmmu/memory_mapping.o
  CC      ppc64-softmmu/numa.o
  CC      ppc-softmmu/numa.o
  CC      arm-softmmu/dump.o
  CC      x86_64-softmmu/migration/ram.o
  CC      ppc64-softmmu/qtest.o
  CC      ppc-softmmu/qtest.o
  CC      arm-softmmu/migration/ram.o
  CC      ppc64-softmmu/memory.o
  CC      ppc-softmmu/memory.o
  CC      x86_64-softmmu/accel/accel.o
  CC      x86_64-softmmu/accel/stubs/kvm-stub.o
  CC      x86_64-softmmu/accel/tcg/tcg-all.o
  CC      x86_64-softmmu/accel/tcg/cputlb.o
  CC      arm-softmmu/accel/accel.o
  CC      arm-softmmu/accel/stubs/kvm-stub.o
  CC      arm-softmmu/accel/tcg/tcg-all.o
  CC      ppc-softmmu/memory_mapping.o
  CC      ppc64-softmmu/memory_mapping.o
  CC      arm-softmmu/accel/tcg/cputlb.o
  CC      ppc-softmmu/dump.o
  CC      ppc64-softmmu/dump.o
  CC      ppc-softmmu/migration/ram.o
  CC      ppc64-softmmu/migration/ram.o
  CC      x86_64-softmmu/accel/tcg/cpu-exec.o
  CC      x86_64-softmmu/accel/tcg/cpu-exec-common.o
  CC      x86_64-softmmu/accel/tcg/translate-all.o
  CC      ppc-softmmu/accel/accel.o
  CC      arm-softmmu/accel/tcg/cpu-exec.o
  CC      ppc64-softmmu/accel/accel.o
  CC      ppc-softmmu/accel/kvm/kvm-all.o
  CC      ppc64-softmmu/accel/kvm/kvm-all.o
  CC      x86_64-softmmu/hw/9pfs/virtio-9p-device.o
  CC      x86_64-softmmu/hw/block/virtio-blk.o
  CC      arm-softmmu/accel/tcg/cpu-exec-common.o
  CC      ppc-softmmu/accel/tcg/tcg-all.o
  CC      x86_64-softmmu/hw/block/dataplane/virtio-blk.o
  CC      arm-softmmu/accel/tcg/translate-all.o
  CC      ppc64-softmmu/accel/tcg/tcg-all.o
  CC      ppc-softmmu/accel/tcg/cputlb.o
  CC      ppc64-softmmu/accel/tcg/cputlb.o
  CC      x86_64-softmmu/hw/char/virtio-serial-bus.o
  CC      arm-softmmu/hw/9pfs/virtio-9p-device.o
  CC      x86_64-softmmu/hw/core/generic-loader.o
  CC      arm-softmmu/hw/adc/stm32f2xx_adc.o
  CC      x86_64-softmmu/hw/core/null-machine.o
  CC      arm-softmmu/hw/block/virtio-blk.o
  CC      x86_64-softmmu/hw/display/vga.o
  CC      ppc-softmmu/accel/tcg/cpu-exec.o
  CC      ppc64-softmmu/accel/tcg/cpu-exec.o
  CC      arm-softmmu/hw/block/dataplane/virtio-blk.o
  CC      arm-softmmu/hw/char/exynos4210_uart.o
  CC      ppc-softmmu/accel/tcg/cpu-exec-common.o
  CC      ppc64-softmmu/accel/tcg/cpu-exec-common.o
  CC      ppc-softmmu/accel/tcg/translate-all.o
  CC      arm-softmmu/hw/char/omap_uart.o
  CC      ppc64-softmmu/accel/tcg/translate-all.o
  CC      x86_64-softmmu/hw/display/virtio-gpu.o
  CC      arm-softmmu/hw/char/digic-uart.o
  CC      arm-softmmu/hw/char/stm32f2xx_usart.o
  CC      ppc-softmmu/hw/9pfs/virtio-9p-device.o
  CC      ppc64-softmmu/hw/9pfs/virtio-9p-device.o
  CC      arm-softmmu/hw/char/bcm2835_aux.o
  CC      ppc-softmmu/hw/block/virtio-blk.o
  CC      ppc64-softmmu/hw/block/virtio-blk.o
  CC      arm-softmmu/hw/char/virtio-serial-bus.o
  CC      x86_64-softmmu/hw/display/virtio-gpu-3d.o
  CC      ppc-softmmu/hw/block/dataplane/virtio-blk.o
  CC      ppc64-softmmu/hw/block/dataplane/virtio-blk.o
  CC      arm-softmmu/hw/core/generic-loader.o
  CC      ppc-softmmu/hw/char/virtio-serial-bus.o
  CC      ppc64-softmmu/hw/char/spapr_vty.o
  CC      x86_64-softmmu/hw/display/virtio-gpu-pci.o
  CC      arm-softmmu/hw/core/null-machine.o
  CC      arm-softmmu/hw/cpu/arm11mpcore.o
  CC      ppc64-softmmu/hw/char/virtio-serial-bus.o
  CC      x86_64-softmmu/hw/display/virtio-vga.o
  CC      arm-softmmu/hw/cpu/realview_mpcore.o
  CC      ppc-softmmu/hw/core/generic-loader.o
  CC      arm-softmmu/hw/cpu/a9mpcore.o
  CC      ppc-softmmu/hw/core/null-machine.o
  CC      ppc64-softmmu/hw/core/generic-loader.o
  CC      x86_64-softmmu/hw/intc/apic.o
  CC      arm-softmmu/hw/cpu/a15mpcore.o
  CC      ppc-softmmu/hw/display/sm501.o
  CC      ppc64-softmmu/hw/core/null-machine.o
  CC      arm-softmmu/hw/display/omap_dss.o
  CC      ppc64-softmmu/hw/display/sm501.o
  CC      x86_64-softmmu/hw/intc/apic_common.o
  CC      arm-softmmu/hw/display/omap_lcdc.o
  CC      x86_64-softmmu/hw/intc/ioapic.o
  CC      ppc-softmmu/hw/display/vga.o
  CC      x86_64-softmmu/hw/isa/lpc_ich9.o
  CC      ppc64-softmmu/hw/display/vga.o
  CC      arm-softmmu/hw/display/pxa2xx_lcd.o
  CC      x86_64-softmmu/hw/misc/vmport.o
  CC      x86_64-softmmu/hw/misc/ivshmem.o
  CC      ppc-softmmu/hw/display/virtio-gpu.o
  CC      x86_64-softmmu/hw/misc/pvpanic.o
  CC      ppc64-softmmu/hw/display/virtio-gpu.o
  CC      arm-softmmu/hw/display/bcm2835_fb.o
  CC      x86_64-softmmu/hw/misc/mmio_interface.o
  CC      x86_64-softmmu/hw/net/virtio-net.o
  CC      arm-softmmu/hw/display/vga.o
  CC      ppc-softmmu/hw/display/virtio-gpu-3d.o
  CC      ppc64-softmmu/hw/display/virtio-gpu-3d.o
  CC      x86_64-softmmu/hw/net/vhost_net.o
  CC      ppc-softmmu/hw/display/virtio-gpu-pci.o
  CC      x86_64-softmmu/hw/scsi/virtio-scsi.o
  CC      arm-softmmu/hw/display/virtio-gpu.o
  CC      ppc64-softmmu/hw/display/virtio-gpu-pci.o
  CC      ppc-softmmu/hw/intc/openpic_kvm.o
  CC      ppc-softmmu/hw/misc/ivshmem.o
  CC      x86_64-softmmu/hw/scsi/virtio-scsi-dataplane.o
  CC      ppc64-softmmu/hw/display/virtio-vga.o
  CC      x86_64-softmmu/hw/scsi/vhost-scsi-common.o
  CC      ppc-softmmu/hw/misc/mmio_interface.o
  CC      x86_64-softmmu/hw/scsi/vhost-scsi.o
  CC      ppc64-softmmu/hw/intc/openpic_kvm.o
  CC      arm-softmmu/hw/display/virtio-gpu-3d.o
  CC      ppc-softmmu/hw/net/xilinx_ethlite.o
  CC      x86_64-softmmu/hw/scsi/vhost-user-scsi.o
  CC      ppc64-softmmu/hw/intc/xics.o
  CC      ppc-softmmu/hw/net/virtio-net.o
  CC      x86_64-softmmu/hw/timer/mc146818rtc.o
  CC      arm-softmmu/hw/display/virtio-gpu-pci.o
  CC      ppc64-softmmu/hw/intc/xics_spapr.o
  CC      x86_64-softmmu/hw/vfio/common.o
  CC      arm-softmmu/hw/dma/omap_dma.o
  CC      ppc64-softmmu/hw/intc/xics_kvm.o
  CC      ppc-softmmu/hw/net/vhost_net.o
  CC      ppc-softmmu/hw/net/fsl_etsec/etsec.o
  CC      ppc64-softmmu/hw/intc/xics_pnv.o
  CC      x86_64-softmmu/hw/vfio/pci.o
  CC      arm-softmmu/hw/dma/soc_dma.o
  CC      ppc64-softmmu/hw/misc/ivshmem.o
  CC      ppc-softmmu/hw/net/fsl_etsec/registers.o
  CC      ppc-softmmu/hw/net/fsl_etsec/rings.o
  CC      arm-softmmu/hw/dma/pxa2xx_dma.o
  CC      ppc-softmmu/hw/net/fsl_etsec/miim.o
  CC      ppc64-softmmu/hw/misc/mmio_interface.o
  CC      arm-softmmu/hw/dma/bcm2835_dma.o
  CC      ppc-softmmu/hw/scsi/virtio-scsi.o
  CC      ppc64-softmmu/hw/net/spapr_llan.o
  CC      arm-softmmu/hw/gpio/omap_gpio.o
  CC      x86_64-softmmu/hw/vfio/pci-quirks.o
  CC      ppc-softmmu/hw/scsi/virtio-scsi-dataplane.o
  CC      arm-softmmu/hw/gpio/imx_gpio.o
  CC      ppc64-softmmu/hw/net/xilinx_ethlite.o
  CC      arm-softmmu/hw/gpio/bcm2835_gpio.o
  CC      ppc-softmmu/hw/scsi/vhost-scsi-common.o
  CC      ppc64-softmmu/hw/net/virtio-net.o
  CC      arm-softmmu/hw/i2c/omap_i2c.o
  CC      ppc-softmmu/hw/scsi/vhost-scsi.o
  CC      x86_64-softmmu/hw/vfio/platform.o
  CC      ppc-softmmu/hw/scsi/vhost-user-scsi.o
  CC      arm-softmmu/hw/input/pxa2xx_keypad.o
  CC      x86_64-softmmu/hw/vfio/spapr.o
  CC      ppc-softmmu/hw/timer/mc146818rtc.o
  CC      ppc64-softmmu/hw/net/vhost_net.o
  CC      arm-softmmu/hw/input/tsc210x.o
  CC      x86_64-softmmu/hw/virtio/virtio.o
  CC      ppc64-softmmu/hw/net/fsl_etsec/etsec.o
  CC      ppc-softmmu/hw/vfio/common.o
  CC      ppc64-softmmu/hw/net/fsl_etsec/registers.o
  CC      arm-softmmu/hw/intc/armv7m_nvic.o
  CC      ppc64-softmmu/hw/net/fsl_etsec/rings.o
  CC      ppc64-softmmu/hw/net/fsl_etsec/miim.o
  CC      ppc-softmmu/hw/vfio/pci.o
  CC      ppc64-softmmu/hw/nvram/spapr_nvram.o
  CC      arm-softmmu/hw/intc/exynos4210_gic.o
  CC      x86_64-softmmu/hw/virtio/virtio-balloon.o
  CC      arm-softmmu/hw/intc/exynos4210_combiner.o
  CC      ppc64-softmmu/hw/scsi/spapr_vscsi.o
  CC      x86_64-softmmu/hw/virtio/vhost.o
  CC      arm-softmmu/hw/intc/omap_intc.o
  CC      ppc64-softmmu/hw/scsi/virtio-scsi.o
  CC      arm-softmmu/hw/intc/bcm2835_ic.o
  CC      ppc-softmmu/hw/vfio/pci-quirks.o
  CC      x86_64-softmmu/hw/virtio/vhost-backend.o
  CC      arm-softmmu/hw/intc/bcm2836_control.o
  CC      x86_64-softmmu/hw/virtio/vhost-user.o
  CC      ppc64-softmmu/hw/scsi/virtio-scsi-dataplane.o
  CC      arm-softmmu/hw/intc/allwinner-a10-pic.o
  CC      arm-softmmu/hw/intc/aspeed_vic.o
  CC      ppc64-softmmu/hw/scsi/vhost-scsi-common.o
  CC      ppc-softmmu/hw/vfio/platform.o
  CC      x86_64-softmmu/hw/virtio/vhost-vsock.o
  CC      ppc64-softmmu/hw/scsi/vhost-scsi.o
  CC      arm-softmmu/hw/intc/arm_gicv3_cpuif.o
  CC      x86_64-softmmu/hw/virtio/virtio-crypto.o
  CC      ppc-softmmu/hw/vfio/spapr.o
  CC      ppc64-softmmu/hw/scsi/vhost-user-scsi.o
  CC      ppc-softmmu/hw/virtio/virtio.o
  CC      ppc64-softmmu/hw/timer/mc146818rtc.o
  CC      x86_64-softmmu/hw/virtio/virtio-crypto-pci.o
  CC      x86_64-softmmu/hw/i386/multiboot.o
  CC      ppc64-softmmu/hw/vfio/common.o
  CC      arm-softmmu/hw/misc/ivshmem.o
  CC      x86_64-softmmu/hw/i386/pc.o
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c: In function ‘pc_dimm_unplug_request’:
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1744:9: error: unknown type name ‘gCto’
         gCto out;
         ^~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1744:14: warning: unused variable ‘out’ [-Wunused-variable]
         gCto out;
              ^~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1747:49: error: stray ‘@’ in program
     if (object_dynamic_cast(OBJECT(dev), TYPE_NV@IMM)) {
                                                 ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1747:42: error: ‘TYPE_NV’ undeclared (first use in this function)
     if (object_dynamic_cast(OBJECT(dev), TYPE_NV@IMM)) {
                                          ^~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1747:42: note: each undeclared identifier is reported only once for each function it appears in
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1747:50: error: expected ‘)’ before ‘IMM’
     if (object_dynamic_cast(OBJECT(dev), TYPE_NV@IMM)) {
                                                  ^~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1754:5: error: stray ‘@’ in program
     @hc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &localCerr);
     ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1754:6: error: ‘hc’ undeclared (first use in this function)
     @hc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &localCerr);
      ^~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1754:64: error: ‘localCerr’ undeclared (first use in this function)
     @hc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &localCerr);
                                                                ^~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1737:26: warning: variable ‘hhc’ set but not used [-Wunused-but-set-variable]
     HotplugHandlerClass *hhc;
                          ^~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c: At top level:
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1760:11: error: stray ‘@’ in program
 static voi@ pc_dimm_unplug(HotplugHandler *hotplug_dev,
           ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1760:8: error: unknown type name ‘voi’
 static voi@ pc_dimm_unplug(HotplugHandler *hotplug_dev,
        ^~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1761:1: warning: null character(s) ignored
                            DeviceState *dev, Error **errp)
 ^
In file included from /home/amigaone/Downloads/qemu-2.10.0-rc4/include/hw/hw.h:10:0,
                 from /home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:25:
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c: In function ‘pc_dimm_unplug’:
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1764:34: error: stray ‘@’ in program
     PCDIMMDevice *dimm = PC_DIMM(@ev);
                                  ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/include/qom/object.h:474:17: note: in definition of macro ‘OBJECT’
     ((Object *)(obj))
                 ^~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/include/hw/mem/pc-dimm.h:25:5: note: in expansion of macro ‘OBJECT_CHECK’
     OBJECT_CHECK(PCDIMMDevice, (obj), TYPE_PC_DIMM)
     ^~~~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1764:26: note: in expansion of macro ‘PC_DIMM’
     PCDIMMDevice *dimm = PC_DIMM(@ev);
                          ^~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1764:35: error: ‘ev’ undeclared (first use in this function)
     PCDIMMDevice *dimm = PC_DIMM(@ev);
                                   ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/include/qom/object.h:474:17: note: in definition of macro ‘OBJECT’
     ((Object *)(obj))
                 ^~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/include/hw/mem/pc-dimm.h:25:5: note: in expansion of macro ‘OBJECT_CHECK’
     OBJECT_CHECK(PCDIMMDevice, (obj), TYPE_PC_DIMM)
     ^~~~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1764:26: note: in expansion of macro ‘PC_DIMM’
     PCDIMMDevice *dimm = PC_DIMM(@ev);
                          ^~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1766:5: error: unknown type name ‘AemoryRegion’
     AemoryRegion *mr;
     ^~~~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1770:40: error: ‘local_err’ undeclared (first use in this function)
     mr = ddc->get_memory_region(dimm, &local_err);\x02    if (local_err) {
                                        ^~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1770:51: error: stray ‘\2’ in program
     mr = ddc->get_memory_region(dimm, &local_err);\x02    if (local_err) {
                                                   ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1774:11: warning: implicit declaration of function ‘HOTPLUGKHANDLER_GET_CLASS’ [-Wimplicit-function-declaration]
     hhc = HOTPLUGKHANDLER_GET_CLASS(pcms->acpi_dev);
           ^~~~~~~~~~~~~~~~~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1774:5: warning: nested extern declaration of ‘HOTPLUGKHANDLER_GET_CLASS’ [-Wnested-externs]
     hhc = HOTPLUGKHANDLER_GET_CLASS(pcms->acpi_dev);
     ^~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1774:37: error: ‘pcms’ undeclared (first use in this function)
     hhc = HOTPLUGKHANDLER_GET_CLASS(pcms->acpi_dev);
                                     ^~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1775:29: error: stray ‘@’ in program
     hhc->unplug(HOTPLUG_HAND@ER(pcms->acpi_dev), dev, &local_err);
                             ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1775:17: error: ‘HOTPLUG_HAND’ undeclared (first use in this function)
     hhc->unplug(HOTPLUG_HAND@ER(pcms->acpi_dev), dev, &local_err);
                 ^~~~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1775:30: error: expected ‘)’ before ‘ER’
     hhc->unplug(HOTPLUG_HAND@ER(pcms->acpi_dev), dev, &local_err);
                              ^~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1775:5: error: too few arguments to function ‘hhc->unplug’
     hhc->unplug(HOTPLUG_HAND@ER(pcms->acpi_dev), dev, &local_err);
     ^~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1778:1: warning: null character(s) ignored
         goto out;
 ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1781:43: error: stray ‘@’ in program
     pc_dimm_memory_unplug(dev, &pcms->hotp@ug_memory, mr);
                                           ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1781:44: error: expected ‘)’ before ‘ug_memory’
     pc_dimm_memory_unplug(dev, &pcms->hotp@ug_memory, mr);
                                            ^~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1781:5: error: too few arguments to function ‘pc_dimm_memory_unplug’
     pc_dimm_memory_unplug(dev, &pcms->hotp@ug_memory, mr);
     ^~~~~~~~~~~~~~~~~~~~~
In file included from /home/amigaone/Downloads/qemu-2.10.0-rc4/include/hw/i386/pc.h:17:0,
                 from /home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:26:
/home/amigaone/Downloads/qemu-2.10.0-rc4/include/hw/mem/pc-dimm.h:100:6: note: declared here
 void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms,
      ^~~~~~~~~~~~~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1785:5: warning: implicit declaration of function ‘erBor_propagate’ [-Wimplicit-function-declaration]
     erBor_propagate(errp, local_err);
     ^~~~~~~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1785:5: warning: nested extern declaration of ‘erBor_propagate’ [-Wnested-externs]
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1768:12: warning: unused variable ‘localCerr’ [-Wunused-variable]
     Error *localCerr = NULL;
            ^~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1766:19: warning: variable ‘mr’ set but not used [-Wunused-but-set-variable]
     AemoryRegion *mr;
                   ^~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1763:21: warning: unused variable ‘pCms’ [-Wunused-variable]
     PCMachineState *pCms = PC_MACHINE(hotplug_dev);
                     ^~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1786:1: warning: no return statement in function returning non-void [-Wreturn-type]
 }
 ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c: At top level:
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1788:30: error: unknown type name ‘Boid’
 static int pc_apic_cmp(const Boid *a, const void *b)
                              ^~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c: In function ‘pc_apic_cmp’:
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1790:39: error: stray ‘\2’ in program
    CPUArchId *apic_a = (CPUArchId *)a;\x02   CPUArchId *apic_b = (CPUArchId *)b;
                                       ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1792:17: error: ‘CPUArchId {aka struct <anonymous>}’ has no member named ‘arch_Ad’; did you mean ‘arch_id’?
    return apic_a->arch_Ad - apic_b->arch_id;
                 ^~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c: At top level:
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1799:39: error: stray ‘@’ in program
 static CPUArchId *pc_find_cpu_slot(Mac@ineState *ms, uint32_t id, int *idx)
                                       ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1799:36: error: unknown type name ‘Mac’
 static CPUArchId *pc_find_cpu_slot(Mac@ineState *ms, uint32_t id, int *idx)
                                    ^~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1804:27: error: stray ‘@’ in program
     found_cpu = bsearch(&a@ic_id, ms->possible_cpus->cpus,
                           ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1807:7: warning: null character(s) ignored
     if  found_cpu && idx) {
       ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1813:25: error: stray ‘@’ in program
 static void pc_cpu_plug(@otplugHandler *hotplug_dev,
                         ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1813:26: error: unknown type name ‘otplugHandler’
 static void pc_cpu_plug(@otplugHandler *hotplug_dev,
                          ^~~~~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1814:36: warning: null character(s) ignored
                         DeviceState *dev, Error **errp)
                                    ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1817:16: error: stray ‘@’ in program
     HotplugHand@erClass *hhc;
                ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1819:21: error: stray ‘\2’ in program
     X86CPU *cpu = X8\x02_CPU(dev);
                     ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1821:1: error: stray ‘\2’ in program
 \x02    if (pcms->acpi_dev) {
 ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1830:1: warning: null character(s) ignored
     pcms->boot_cpus++;
 ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1838:5: warning: data definition has no type or storage class
     found_cpu = pc_find_cpu_slot(MACHINE(pcms\x01, cpu->apic_id, NULL);
     ^~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1838:5: warning: type defaults to ‘int’ in declaration of ‘found_cpu’ [-Wimplicit-int]
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1838:17: warning: implicit declaration of function ‘pc_find_cpu_slot’ [-Wimplicit-function-declaration]
     found_cpu = pc_find_cpu_slot(MACHINE(pcms\x01, cpu->apic_id, NULL);
                 ^~~~~~~~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1838:67: error: macro "MACHINE" passed 3 arguments, but takes just 1
     found_cpu = pc_find_cpu_slot(MACHINE(pcms\x01, cpu->apic_id, NULL);
                                                                   ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1838:34: error: ‘MACHINE’ undeclared here (not in a function)
     found_cpu = pc_find_cpu_slot(MACHINE(pcms\x01, cpu->apic_id, NULL);
                                  ^~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1838:68: error: expected ‘)’ before ‘;’ token
     found_cpu = pc_find_cpu_slot(MACHINE(pcms\x01, cpu->apic_id, NULL);
                                                                    ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1841:1: warning: null character(s) ignored
     error_propagate(errp, local_err);
 ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1842:1: error: expected ‘,’ or ‘;’ before ‘}’ token
 }
 ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1844:1: warning: null character(s) ignored
                                      DeviceState *dev, Error **errp)
 ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c: In function ‘pc_cpu_unplugCrequest_cb’:
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1846:17: error: stray ‘\3’ in program
     int idx = -1\x03
                 ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1847:5: error: expected ‘,’ or ‘;’ before ‘HotplugHandlerClass’
     HotplugHandlerClass *hhc;
     ^~~~~~~~~~~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1849:1: warning: null character(s) ignored
     X86CPU *cpu = X86_CPU(dev);
 ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1850:28: warning: implicit declaration of function ‘PC_MACHIBE’ [-Wimplicit-function-declaration]
     PCMachineState *pcms = PC_MACHIBE(hotplug_dev);
                            ^~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1850:5: warning: nested extern declaration of ‘PC_MACHIBE’ [-Wnested-externs]
     PCMachineState *pcms = PC_MACHIBE(hotplug_dev);
     ^~~~~~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1850:28: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
     PCMachineState *pcms = PC_MACHIBE(hotplug_dev);
                            ^~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1852:40: error: ‘X86CPU {aka struct X86CPU}’ has no member named ‘apic_Ad’; did you mean ‘apic_id’?
     pc_find_cpu_slot(MACHINE(pcms), cpu->apic_Ad, &idx);
                                        ^~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1855:9: warning: implicit declaration of function ‘erBor_setg’ [-Wimplicit-function-declaration]
         erBor_setg(&local_err, "Boot CPU is unpluggable");
         ^~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1855:9: warning: nested extern declaration of ‘erBor_setg’ [-Wnested-externs]
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1856:16: error: stray ‘@’ in program
         goto ou@;
                ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1859:5: error: ‘hhc’ undeclared (first use in this function)
     hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
     ^~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1860:1: warning: null character(s) ignored
     hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &loCal_err);
 ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1860:64: error: ‘loCal_err’ undeclared (first use in this function)
     hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &loCal_err);
                                                                ^~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1867:1: warning: null character(s) ignored
     error_propagate(errp, local_err);
 ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1856:9: error: label ‘ou’ used but not defined
         goto ou@;
         ^~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c: At top level:
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1872:30: error: stray ‘@’ in program
                              @eviceState *dev, Error **errp)
                              ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1872:31: error: unknown type name ‘eviceState’
                              @eviceState *dev, Error **errp)
                               ^~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1875:5: error: stray ‘@’ in program
     @otplugHandlerClass *hhc;
     ^
In file included from /home/amigaone/Downloads/qemu-2.10.0-rc4/include/hw/hw.h:10:0,
                 from /home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:25:
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1878:42: error: stray ‘@’ in program
     PCMachineState *pcms = PC_MACHINE(hot@lug_dev);
                                          ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/include/qom/object.h:474:17: note: in definition of macro ‘OBJECT’
     ((Object *)(obj))
                 ^~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/include/hw/i386/pc.h:148:5: note: in expansion of macro ‘OBJECT_CHECK’
     OBJECT_CHECK(PCMachineState, (obj), TYPE_PC_MACHINE)
     ^~~~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1878:28: note: in expansion of macro ‘PC_MACHINE’
     PCMachineState *pcms = PC_MACHINE(hot@lug_dev);
                            ^~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1880:53: error: stray ‘\2’ in program
     hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);\x02    hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_erB);
                                                     ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1886:14: warning: null character(s) ignored
     found_cpu = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, NULL);
              ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1887:9: error: stray ‘@’ in program
     foun@_cpu->cpu = NULL;
         ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c: In function ‘pc_cpu_pre_plug’:
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1944:14: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
     cpu_slot = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, &idx);
              ^
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c: In function ‘pc_machine_device_plug_cb’:
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:2010:9: warning: implicit declaration of function ‘pc_cpu_plug’ [-Wimplicit-function-declaration]
         pc_cpu_plug(hotplug_dev, dev, errp);
         ^~~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:2010:9: warning: nested extern declaration of ‘pc_cpu_plug’ [-Wnested-externs]
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c: In function ‘pc_machine_device_unplug_request_cb’:
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:2020:9: warning: implicit declaration of function ‘pc_cpu_unplug_request_cb’ [-Wimplicit-function-declaration]
         pc_cpu_unplug_request_cb(hotplug_dev, dev, errp);
         ^~~~~~~~~~~~~~~~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:2020:9: warning: nested extern declaration of ‘pc_cpu_unplug_request_cb’ [-Wnested-externs]
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c: In function ‘pc_machine_device_unplug_cb’:
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:2033:9: warning: implicit declaration of function ‘pc_cpu_unplug_cb’ [-Wimplicit-function-declaration]
         pc_cpu_unplug_cb(hotplug_dev, dev, errp);
         ^~~~~~~~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:2033:9: warning: nested extern declaration of ‘pc_cpu_unplug_cb’ [-Wnested-externs]
At top level:
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1843:13: warning: ‘pc_cpu_unplugCrequest_cb’ defined but not used [-Wunused-function]
 static void pc_cpu_unplugCrequest_cb(HotplugHandler *hotplug_dev,
             ^~~~~~~~~~~~~~~~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1788:12: warning: ‘pc_apic_cmp’ defined but not used [-Wunused-function]
 static int pc_apic_cmp(const Boid *a, const void *b)
            ^~~~~~~~~~~
/home/amigaone/Downloads/qemu-2.10.0-rc4/rules.mak:66: recipe for target 'hw/i386/pc.o' failed
make[1]: *** [hw/i386/pc.o] Error 1
Makefile:326: recipe for target 'subdir-x86_64-softmmu' failed
make: *** [subdir-x86_64-softmmu] Error 2
make: *** Waiting for unfinished jobs....
  CC      arm-softmmu/hw/misc/arm_sysctl.o
  CC      ppc-softmmu/hw/virtio/virtio-balloon.o
  CC      ppc64-softmmu/hw/vfio/pci.o
  CC      arm-softmmu/hw/misc/cbus.o
  CC      arm-softmmu/hw/misc/exynos4210_pmu.o
  CC      arm-softmmu/hw/misc/exynos4210_clk.o
  CC      arm-softmmu/hw/misc/exynos4210_rng.o
  CC      ppc-softmmu/hw/virtio/vhost.o
  CC      arm-softmmu/hw/misc/imx_ccm.o
  CC      arm-softmmu/hw/misc/imx31_ccm.o
  CC      arm-softmmu/hw/misc/imx25_ccm.o
  CC      arm-softmmu/hw/misc/imx6_ccm.o
  CC      ppc64-softmmu/hw/vfio/pci-quirks.o
  CC      arm-softmmu/hw/misc/imx6_src.o
  CC      ppc-softmmu/hw/virtio/vhost-backend.o
  CC      arm-softmmu/hw/misc/mst_fpga.o
  CC      ppc64-softmmu/hw/vfio/platform.o
  CC      arm-softmmu/hw/misc/omap_clk.o
  CC      ppc-softmmu/hw/virtio/vhost-user.o
  CC      arm-softmmu/hw/misc/omap_gpmc.o
  CC      ppc64-softmmu/hw/vfio/spapr.o
  CC      ppc64-softmmu/hw/virtio/virtio.o
  CC      ppc-softmmu/hw/virtio/vhost-vsock.o
  CC      arm-softmmu/hw/misc/omap_l4.o
  CC      ppc64-softmmu/hw/virtio/virtio-balloon.o
  CC      ppc-softmmu/hw/virtio/virtio-crypto.o
  CC      arm-softmmu/hw/misc/omap_sdrc.o
  CC      arm-softmmu/hw/misc/omap_tap.o
  CC      arm-softmmu/hw/misc/bcm2835_mbox.o
  CC      ppc-softmmu/hw/virtio/virtio-crypto-pci.o
  CC      ppc64-softmmu/hw/virtio/vhost.o
  CC      arm-softmmu/hw/misc/bcm2835_property.o
  CC      arm-softmmu/hw/misc/bcm2835_rng.o
  CC      ppc-softmmu/hw/ppc/ppc.o
  CC      ppc64-softmmu/hw/virtio/vhost-backend.o
  CC      arm-softmmu/hw/misc/zynq_slcr.o
  CC      ppc-softmmu/hw/ppc/ppc_booke.o
  CC      ppc64-softmmu/hw/virtio/vhost-user.o
  CC      arm-softmmu/hw/misc/zynq-xadc.o
  CC      ppc-softmmu/hw/ppc/fdt.o
  CC      arm-softmmu/hw/misc/stm32f2xx_syscfg.o
  CC      ppc-softmmu/hw/ppc/ppc405_boards.o
  CC      ppc-softmmu/hw/ppc/ppc4xx_devs.o
  CC      ppc64-softmmu/hw/virtio/vhost-vsock.o
  CC      arm-softmmu/hw/misc/mps2-scc.o
  CC      arm-softmmu/hw/misc/aspeed_scu.o
  CC      ppc-softmmu/hw/ppc/ppc405_uc.o
  CC      ppc64-softmmu/hw/virtio/virtio-crypto.o
  CC      ppc64-softmmu/hw/virtio/virtio-crypto-pci.o
  CC      arm-softmmu/hw/misc/aspeed_sdmc.o
  CC      arm-softmmu/hw/misc/mmio_interface.o
  CC      arm-softmmu/hw/net/virtio-net.o
  CC      ppc64-softmmu/hw/ppc/ppc.o
  CC      ppc-softmmu/hw/ppc/ppc440_bamboo.o
  CC      ppc-softmmu/hw/ppc/ppc4xx_pci.o
  CC      ppc64-softmmu/hw/ppc/ppc_booke.o
  CC      ppc-softmmu/hw/ppc/prep.o
  CC      arm-softmmu/hw/net/vhost_net.o
  CC      ppc64-softmmu/hw/ppc/fdt.o
  CC      ppc64-softmmu/hw/ppc/spapr.o
  CC      arm-softmmu/hw/pcmcia/pxa2xx.o
  CC      ppc-softmmu/hw/ppc/prep_systemio.o
  CC      ppc64-softmmu/hw/ppc/spapr_vio.o
  CC      arm-softmmu/hw/scsi/virtio-scsi.o
  CC      ppc-softmmu/hw/ppc/rs6000_mc.o
  CC      arm-softmmu/hw/scsi/virtio-scsi-dataplane.o
  CC      ppc-softmmu/hw/ppc/mac_oldworld.o
  CC      ppc64-softmmu/hw/ppc/spapr_events.o
  CC      arm-softmmu/hw/scsi/vhost-scsi-common.o
  CC      ppc-softmmu/hw/ppc/mac_newworld.o
  CC      arm-softmmu/hw/scsi/vhost-scsi.o
  CC      ppc-softmmu/hw/ppc/e500.o
  CC      ppc64-softmmu/hw/ppc/spapr_hcall.o
  CC      arm-softmmu/hw/scsi/vhost-user-scsi.o
  CC      ppc64-softmmu/hw/ppc/spapr_iommu.o
  CC      arm-softmmu/hw/sd/omap_mmc.o
  CC      ppc-softmmu/hw/ppc/mpc8544ds.o
  CC      ppc-softmmu/hw/ppc/e500plat.o
  CC      arm-softmmu/hw/sd/pxa2xx_mmci.o
  CC      ppc-softmmu/hw/ppc/mpc8544_guts.o
  CC      ppc64-softmmu/hw/ppc/spapr_rtas.o
  CC      ppc64-softmmu/hw/ppc/spapr_pci.o
  CC      ppc-softmmu/hw/ppc/ppce500_spin.o
  CC      arm-softmmu/hw/sd/bcm2835_sdhost.o
  CC      arm-softmmu/hw/ssi/omap_spi.o
  CC      ppc-softmmu/hw/ppc/virtex_ml507.o
  CC      ppc64-softmmu/hw/ppc/spapr_rtc.o
  CC      arm-softmmu/hw/ssi/imx_spi.o
  CC      ppc-softmmu/target/ppc/cpu-models.o
  CC      arm-softmmu/hw/timer/exynos4210_mct.o
  CC      ppc-softmmu/target/ppc/cpu.o
  CC      ppc64-softmmu/hw/ppc/spapr_drc.o
  CC      ppc-softmmu/target/ppc/translate.o
  CC      arm-softmmu/hw/timer/exynos4210_pwm.o
  CC      arm-softmmu/hw/timer/exynos4210_rtc.o
  CC      ppc64-softmmu/hw/ppc/spapr_rng.o
  CC      arm-softmmu/hw/timer/omap_gptimer.o
  CC      ppc64-softmmu/hw/ppc/spapr_cpu_core.o
  CC      arm-softmmu/hw/timer/omap_synctimer.o
  CC      ppc64-softmmu/hw/ppc/spapr_ovec.o
  CC      arm-softmmu/hw/timer/pxa2xx_timer.o
  CC      ppc64-softmmu/hw/ppc/pnv.o
  CC      arm-softmmu/hw/timer/digic-timer.o
  CC      arm-softmmu/hw/timer/allwinner-a10-pit.o
  CC      arm-softmmu/hw/usb/tusb6010.o
  CC      ppc64-softmmu/hw/ppc/pnv_xscom.o
  CC      ppc-softmmu/target/ppc/machine.o
  CC      arm-softmmu/hw/vfio/common.o
  CC      ppc64-softmmu/hw/ppc/pnv_core.o
  CC      ppc64-softmmu/hw/ppc/pnv_lpc.o
  CC      ppc-softmmu/target/ppc/mmu_helper.o
  CC      ppc64-softmmu/hw/ppc/pnv_psi.o
  CC      arm-softmmu/hw/vfio/pci.o
  CC      ppc64-softmmu/hw/ppc/pnv_occ.o
  CC      ppc64-softmmu/hw/ppc/pnv_bmc.o
  CC      ppc64-softmmu/hw/ppc/spapr_pci_vfio.o
  CC      ppc64-softmmu/hw/ppc/spapr_rtas_ddw.o
  CC      arm-softmmu/hw/vfio/pci-quirks.o
  CC      ppc64-softmmu/hw/ppc/ppc405_boards.o
  CC      ppc64-softmmu/hw/ppc/ppc4xx_devs.o
  CC      arm-softmmu/hw/vfio/platform.o
  CC      ppc64-softmmu/hw/ppc/ppc405_uc.o
  CC      ppc64-softmmu/hw/ppc/ppc440_bamboo.o
  CC      arm-softmmu/hw/vfio/calxeda-xgmac.o
  CC      ppc-softmmu/target/ppc/mmu-hash32.o
  CC      arm-softmmu/hw/vfio/amd-xgbe.o
  CC      ppc64-softmmu/hw/ppc/ppc4xx_pci.o
  CC      arm-softmmu/hw/vfio/spapr.o
  CC      ppc64-softmmu/hw/ppc/prep.o
  CC      ppc-softmmu/target/ppc/monitor.o
  CC      arm-softmmu/hw/virtio/virtio.o
  CC      arm-softmmu/hw/virtio/virtio-balloon.o
  CC      ppc64-softmmu/hw/ppc/prep_systemio.o
  CC      ppc64-softmmu/hw/ppc/rs6000_mc.o
  CC      arm-softmmu/hw/virtio/vhost.o
  CC      ppc64-softmmu/hw/ppc/mac_oldworld.o
  CC      ppc64-softmmu/hw/ppc/mac_newworld.o
  CC      ppc64-softmmu/hw/ppc/e500.o
  CC      arm-softmmu/hw/virtio/vhost-backend.o
  CC      arm-softmmu/hw/virtio/vhost-user.o
  CC      ppc64-softmmu/hw/ppc/mpc8544ds.o
  CC      arm-softmmu/hw/virtio/vhost-vsock.o
  CC      ppc64-softmmu/hw/ppc/e500plat.o
  CC      ppc-softmmu/target/ppc/arch_dump.o
  CC      arm-softmmu/hw/virtio/virtio-crypto.o
  CC      ppc64-softmmu/hw/ppc/mpc8544_guts.o
  CC      ppc64-softmmu/hw/ppc/ppce500_spin.o
  CC      arm-softmmu/hw/virtio/virtio-crypto-pci.o
  CC      ppc-softmmu/target/ppc/kvm.o
  CC      ppc64-softmmu/hw/ppc/virtex_ml507.o
  CC      arm-softmmu/hw/arm/boot.o
  CC      ppc64-softmmu/target/ppc/cpu-models.o
  CC      arm-softmmu/hw/arm/collie.o
  CC      ppc64-softmmu/target/ppc/cpu.o
  CC      arm-softmmu/hw/arm/exynos4_boards.o
  CC      arm-softmmu/hw/arm/gumstix.o
  CC      ppc64-softmmu/target/ppc/translate.o
  CC      arm-softmmu/hw/arm/highbank.o
  CC      arm-softmmu/hw/arm/digic_boards.o
  CC      arm-softmmu/hw/arm/integratorcp.o
  CC      arm-softmmu/hw/arm/mainstone.o
  CC      arm-softmmu/hw/arm/musicpal.o
  CC      arm-softmmu/hw/arm/nseries.o
  CC      ppc64-softmmu/target/ppc/machine.o
  CC      arm-softmmu/hw/arm/omap_sx1.o
  CC      ppc64-softmmu/target/ppc/mmu_helper.o
  CC      arm-softmmu/hw/arm/palm.o
  CC      arm-softmmu/hw/arm/realview.o
  CC      arm-softmmu/hw/arm/spitz.o
  CC      arm-softmmu/hw/arm/stellaris.o
  CC      ppc64-softmmu/target/ppc/mmu-hash32.o
  CC      arm-softmmu/hw/arm/tosa.o
  CC      ppc-softmmu/target/ppc/dfp_helper.o
  CC      arm-softmmu/hw/arm/versatilepb.o
  CC      arm-softmmu/hw/arm/vexpress.o
  CC      arm-softmmu/hw/arm/virt.o
  CC      ppc64-softmmu/target/ppc/monitor.o
  CC      ppc-softmmu/target/ppc/excp_helper.o
  CC      arm-softmmu/hw/arm/xilinx_zynq.o
  CC      ppc64-softmmu/target/ppc/arch_dump.o
  CC      ppc-softmmu/target/ppc/fpu_helper.o
  CC      arm-softmmu/hw/arm/z2.o
  CC      ppc64-softmmu/target/ppc/mmu-hash64.o
  CC      arm-softmmu/hw/arm/virt-acpi-build.o
  CC      ppc-softmmu/target/ppc/int_helper.o
  CC      arm-softmmu/hw/arm/netduino2.o
  CC      arm-softmmu/hw/arm/sysbus-fdt.o
  CC      arm-softmmu/hw/arm/armv7m.o
  CC      arm-softmmu/hw/arm/exynos4210.o
  CC      arm-softmmu/hw/arm/pxa2xx.o
  CC      ppc64-softmmu/target/ppc/mmu-book3s-v3.o
  CC      ppc-softmmu/target/ppc/timebase_helper.o
  CC      arm-softmmu/hw/arm/pxa2xx_gpio.o
  CC      ppc64-softmmu/target/ppc/compat.o
  CC      arm-softmmu/hw/arm/pxa2xx_pic.o
  CC      ppc-softmmu/target/ppc/misc_helper.o
  CC      arm-softmmu/hw/arm/digic.o
  CC      ppc64-softmmu/target/ppc/mmu-radix64.o
  CC      arm-softmmu/hw/arm/omap1.o
  CC      ppc-softmmu/target/ppc/mem_helper.o
  CC      ppc64-softmmu/target/ppc/kvm.o
  CC      ppc-softmmu/target/ppc/gdbstub.o
  GEN     trace/generated-helpers.c
  CC      ppc-softmmu/trace/control-target.o
  CC      ppc-softmmu/gdbstub-xml.o
  CC      arm-softmmu/hw/arm/omap2.o
  CC      ppc-softmmu/trace/generated-helpers.o
  CC      arm-softmmu/hw/arm/strongarm.o
  LINK    ppc-softmmu/qemu-system-ppc
  CC      ppc64-softmmu/target/ppc/dfp_helper.o
  CC      arm-softmmu/hw/arm/allwinner-a10.o
  CC      arm-softmmu/hw/arm/cubieboard.o
  CC      arm-softmmu/hw/arm/bcm2835_peripherals.o
  CC      arm-softmmu/hw/arm/bcm2836.o
  CC      ppc64-softmmu/target/ppc/excp_helper.o
  CC      arm-softmmu/hw/arm/raspi.o
  CC      arm-softmmu/hw/arm/stm32f205_soc.o
  CC      arm-softmmu/hw/arm/fsl-imx25.o
  CC      arm-softmmu/hw/arm/imx25_pdk.o
  CC      arm-softmmu/hw/arm/fsl-imx31.o
  CC      arm-softmmu/hw/arm/kzm.o
  CC      arm-softmmu/hw/arm/fsl-imx6.o
  CC      arm-softmmu/hw/arm/sabrelite.o
  CC      arm-softmmu/hw/arm/aspeed_soc.o
  CC      arm-softmmu/hw/arm/aspeed.o
  CC      arm-softmmu/hw/arm/mps2.o
  CC      arm-softmmu/target/arm/arm-semi.o
  CC      arm-softmmu/target/arm/machine.o
  CC      arm-softmmu/target/arm/psci.o
  CC      arm-softmmu/target/arm/arch_dump.o
  CC      arm-softmmu/target/arm/monitor.o
  CC      arm-softmmu/target/arm/kvm-stub.o
  CC      arm-softmmu/target/arm/translate.o
  CC      arm-softmmu/target/arm/op_helper.o
  CC      arm-softmmu/target/arm/helper.o
  CC      arm-softmmu/target/arm/cpu.o
  CC      arm-softmmu/target/arm/neon_helper.o
  CC      ppc64-softmmu/target/ppc/fpu_helper.o
  CC      arm-softmmu/target/arm/iwmmxt_helper.o
  CC      arm-softmmu/target/arm/gdbstub.o
  CC      arm-softmmu/target/arm/crypto_helper.o
  CC      arm-softmmu/target/arm/arm-powerctl.o
  GEN     trace/generated-helpers.c
  CC      arm-softmmu/trace/control-target.o
  CC      arm-softmmu/gdbstub-xml.o
  CC      arm-softmmu/trace/generated-helpers.o
  CC      ppc64-softmmu/target/ppc/int_helper.o
  CC      ppc64-softmmu/target/ppc/timebase_helper.o
  CC      ppc64-softmmu/target/ppc/misc_helper.o
  CC      ppc64-softmmu/target/ppc/mem_helper.o
  CC      ppc64-softmmu/target/ppc/gdbstub.o
  GEN     trace/generated-helpers.c
  CC      ppc64-softmmu/trace/control-target.o
  CC      ppc64-softmmu/gdbstub-xml.o
  CC      ppc64-softmmu/trace/generated-helpers.o
  LINK    ppc64-softmmu/qemu-system-ppc64
  LINK    arm-softmmu/qemu-system-arm
[amigaone@dhcppc0 qemu-2.10.0-rc4]$ ls


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] Qemu 2.10 rc4 build issue on BE
  2017-08-27 16:56   ` [Qemu-devel] Qemu 2.10 rc4 build issue on BE luigi burdo
@ 2017-08-28  9:20     ` Thomas Huth
  2017-08-28 11:13       ` luigi burdo
  2017-08-28 15:56     ` [Qemu-devel] " Eric Blake
  1 sibling, 1 reply; 66+ messages in thread
From: Thomas Huth @ 2017-08-28  9:20 UTC (permalink / raw)
  To: luigi burdo, qemu-devel, qemu-ppc

On 27.08.2017 18:56, luigi burdo wrote:
> Hi all,
> 
> the last rc4 from the qemu website fail in build in some parts on BE
> hardware.
> 
> attached on this email there is the configure and the build log hope it
> helps
> 
> 
> My machine is : PowerMac G5 Quad .
> 
> Distro is Ferdora 25 PPC64.

In your log there is:

/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c: In function
‘pc_dimm_unplug_request’:
/home/amigaone/Downloads/qemu-2.10.0-rc4/hw/i386/pc.c:1744:9: error:
unknown type name ‘gCto’
         gCto out;

But if you have a look at the freshly unpacked sources, that line
clearly reads "goto out;" and not "gCto out;" ... so it looks like
something messed up your sources very badly.
Can you reproduce this problem when starting again from scratch?

 Thomas

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] Qemu 2.10 rc4 build issue on BE
  2017-08-28  9:20     ` [Qemu-devel] [Qemu-ppc] " Thomas Huth
@ 2017-08-28 11:13       ` luigi burdo
  0 siblings, 0 replies; 66+ messages in thread
From: luigi burdo @ 2017-08-28 11:13 UTC (permalink / raw)
  To: Thomas Huth, qemu-devel, qemu-ppc

Hi Thomas,

i will check again and report.

Luigi



In your log there is:


But if you have a look at the freshly unpacked sources, that line
clearly reads "goto out;" and not "gCto out;" ... so it looks like
something messed up your sources very badly.
Can you reproduce this problem when starting again from scratch?

 Thomas

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] Qemu 2.10 rc4 build issue on BE
  2017-08-27 16:56   ` [Qemu-devel] Qemu 2.10 rc4 build issue on BE luigi burdo
  2017-08-28  9:20     ` [Qemu-devel] [Qemu-ppc] " Thomas Huth
@ 2017-08-28 15:56     ` Eric Blake
  1 sibling, 0 replies; 66+ messages in thread
From: Eric Blake @ 2017-08-28 15:56 UTC (permalink / raw)
  To: luigi burdo, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 803 bytes --]

On 08/27/2017 11:56 AM, luigi burdo wrote:
> Hi all,
> 
> the last rc4 from the qemu website fail in build in some parts on BE hardware.

Please don't commandeer unrelated threads (replying to an existing
message sets up In-Reply-To: and References: headers that thread your
mail to the previous one, even if you change the subject and drop all
previous content; it would have been better to post your message as a
top-level thread instead of buried in an unrelated thread).

https://lists.gnu.org/archive/html/qemu-devel/2017-08/threads.html#03659
demonstrates how your message was inappropriately threaded to
"[Qemu-ppc] [PATCH 00/15] Sam460ex emulation"

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH 00/15] Sam460ex emulation
  2017-08-27 12:34 ` [Qemu-devel] [Qemu-ppc] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
  2017-08-27 16:56   ` [Qemu-devel] Qemu 2.10 rc4 build issue on BE luigi burdo
@ 2017-08-29  7:34   ` David Gibson
  1 sibling, 0 replies; 66+ messages in thread
From: David Gibson @ 2017-08-29  7:34 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel, qemu-ppc, Francois Revol

[-- Attachment #1: Type: text/plain, Size: 3021 bytes --]

On Sun, Aug 27, 2017 at 02:34:14PM +0200, BALATON Zoltan wrote:
> Hello,
> 
> Just to confirm where we are with this series, let me summarise what I got
> from the replies and what's my plan for this based on that. Here's the list
> of patches for reference:
> 
> [PATCH 01/15] ppc4xx: Move MAL from ppc405_uc to ppc4xx_devs
> [PATCH 02/15] ppc4xx: Make MAL emulation more generic
> [PATCH 03/15] ohci: Allow sysbus version to be used as a companion
> [PATCH 04/15] ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs
> [PATCH 05/15] ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file
> [PATCH 06/15] ppc4xx_i2c: QOMify
> [PATCH 07/15] ppc4xx_i2c: Move to hw/i2c
> [PATCH 08/15] ppc4xx_i2c: Implement basic I2C functions
> [PATCH 09/15] hw/ide: Emulate SiI3112 SATA controller
> [PATCH 10/15] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs
> [PATCH 11/15] ppc: Add 460EX embedded CPU
> [PATCH 12/15] ppc4xx: Export ECB and PLB emulation
> [PATCH 13/15] ppc4xx: Add more PLB registers
> [PATCH 14/15] ppc4xx: Add device models found in PPC440 core SoCs
> [PATCH 15/15] ppc: Add aCube Sam460ex board
> 
> - I think 1-7 is either already queued for 2.11 or could be applied as is
> having got reviews without need to change so I don't need to resend them. So
> are 11-13 if I got that right. That leaves 8-10 and 14-15 that I'll resend.

The way to handle this is to pull the 'ppc-for-2.11' tree from
git://github.com/dgibson/qemu.git, then rebase your series on top of
it.  That should automatically filter out the patches I've already applied.

> - I'm not sure if 8 was reviewed or do I need to make any modifications to
> it.

I think I didn't get to it.  Just include it in the next spin and
we'll see how we go.

> 
> - I know I should change 9-10 and 14-15 based on review comments and resend.
> 
> Since I'll likely also need to change those patches to fix the bugs we know
> about currently, I thought I should probably resend after those bugs are
> fixed to avoid subsequent fixup patches. Since this will not be before next
> week (because I don't have time for it before that) I hope development
> should be open again and those patches that are already OK could be merged
> by then so I can rebase on that and only resend the missing ones as
> described above. Is that OK or did I miss something?

2.11 dev should open soon, but I don't know how long it will take to
get my already queued patches merged there.

> David, in case you want to stage all of this in your for-2.11 branch before
> all patches are ready and send them together, then where is this branch I
> should rebase to?

As above, use the 'ppc-for-2.11' branch at
git://github.com/dgibson/qemu.git.  Note that this is a rebasing branch.

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

end of thread, other threads:[~2017-08-29 11:02 UTC | newest]

Thread overview: 66+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-20 17:23 [Qemu-devel] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
2017-08-20 17:23 ` [Qemu-devel] [PATCH 07/15] ppc4xx_i2c: Move to hw/i2c BALATON Zoltan
2017-08-21 10:54   ` David Gibson
2017-08-20 17:23 ` [Qemu-devel] [PATCH 06/15] ppc4xx_i2c: QOMify BALATON Zoltan
2017-08-21 10:50   ` David Gibson
2017-08-20 17:23 ` [Qemu-devel] [PATCH 02/15] ppc4xx: Make MAL emulation more generic BALATON Zoltan
2017-08-21 10:40   ` David Gibson
2017-08-20 17:23 ` [Qemu-devel] [PATCH 12/15] ppc4xx: Export ECB and PLB emulation BALATON Zoltan
2017-08-23  2:30   ` David Gibson
2017-08-20 17:23 ` [Qemu-devel] [PATCH 05/15] ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file BALATON Zoltan
2017-08-20 17:23 ` [Qemu-devel] [PATCH 11/15] ppc: Add 460EX embedded CPU BALATON Zoltan
2017-08-23  2:28   ` David Gibson
2017-08-23  9:08     ` BALATON Zoltan
2017-08-23  9:20       ` David Gibson
2017-08-20 17:23 ` [Qemu-devel] [PATCH 04/15] ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs BALATON Zoltan
2017-08-21  4:18   ` David Gibson
2017-08-23 13:57     ` Gerd Hoffmann
2017-08-20 17:23 ` [Qemu-devel] [PATCH 09/15] hw/ide: Emulate SiI3112 SATA controller BALATON Zoltan
2017-08-21 21:14   ` John Snow
2017-08-22 11:08     ` BALATON Zoltan
2017-08-22 19:01       ` John Snow
2017-08-22 20:15         ` BALATON Zoltan
2017-08-22 20:21           ` John Snow
2017-08-22 21:54             ` BALATON Zoltan
2017-08-23  0:52         ` David Gibson
2017-08-23 16:16           ` John Snow
2017-08-20 17:23 ` [Qemu-devel] [PATCH 13/15] ppc4xx: Add more PLB registers BALATON Zoltan
2017-08-20 21:58   ` Philippe Mathieu-Daudé
2017-08-20 22:12     ` BALATON Zoltan
2017-08-23  2:40     ` David Gibson
2017-08-23  2:39   ` David Gibson
2017-08-23 10:16     ` BALATON Zoltan
2017-08-24  2:35       ` David Gibson
2017-08-24 20:28         ` BALATON Zoltan
2017-08-25  5:05           ` David Gibson
2017-08-20 17:23 ` [Qemu-devel] [PATCH 03/15] ohci: Allow sysbus version to be used as a companion BALATON Zoltan
2017-08-21  4:10   ` David Gibson
2017-08-23 13:58     ` Gerd Hoffmann
2017-08-20 17:23 ` [Qemu-devel] [PATCH 14/15] ppc4xx: Add device models found in PPC440 core SoCs BALATON Zoltan
2017-08-23  2:49   ` David Gibson
2017-08-20 17:23 ` [Qemu-devel] [PATCH 01/15] ppc4xx: Move MAL from ppc405_uc to ppc4xx_devs BALATON Zoltan
2017-08-20 17:23 ` [Qemu-devel] [PATCH 10/15] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs BALATON Zoltan
2017-08-20 22:20   ` Philippe Mathieu-Daudé
2017-08-24 22:12     ` BALATON Zoltan
2017-08-23  0:49   ` David Gibson
2017-08-20 17:23 ` [Qemu-devel] [PATCH 15/15] ppc: Add aCube Sam460ex board BALATON Zoltan
2017-08-20 22:10   ` Philippe Mathieu-Daudé
2017-08-23  4:16   ` David Gibson
2017-08-23 11:12     ` BALATON Zoltan
2017-08-23 11:43       ` François Revol
2017-08-23 12:47         ` BALATON Zoltan
2017-08-23 13:33           ` [Qemu-devel] [Qemu-ppc] " luigi burdo
2017-08-24  2:54           ` [Qemu-devel] " David Gibson
2017-08-24  2:51         ` David Gibson
2017-08-24 21:43           ` BALATON Zoltan
2017-08-24 23:55             ` David Gibson
2017-08-24  2:44       ` David Gibson
2017-08-24 21:37         ` BALATON Zoltan
2017-08-25  0:15           ` David Gibson
2017-08-20 17:23 ` [Qemu-devel] [PATCH 08/15] ppc4xx_i2c: Implement basic I2C functions BALATON Zoltan
2017-08-27 12:34 ` [Qemu-devel] [Qemu-ppc] [PATCH 00/15] Sam460ex emulation BALATON Zoltan
2017-08-27 16:56   ` [Qemu-devel] Qemu 2.10 rc4 build issue on BE luigi burdo
2017-08-28  9:20     ` [Qemu-devel] [Qemu-ppc] " Thomas Huth
2017-08-28 11:13       ` luigi burdo
2017-08-28 15:56     ` [Qemu-devel] " Eric Blake
2017-08-29  7:34   ` [Qemu-devel] [Qemu-ppc] [PATCH 00/15] Sam460ex emulation David Gibson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.