All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] KVM PowerPC support
@ 2008-12-15 16:44 ` Hollis Blanchard
  0 siblings, 0 replies; 31+ messages in thread
From: Hollis Blanchard @ 2008-12-15 16:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

I believe all comments from the first series have been addressed (thanks for
the quick review!). I was able to drop the first patch entirely, but realized
I should move/rename the 4xx SDRAM controller code, so that change is new.

Summary:
These patches implement KVM support for the PowerPC Bamboo board, a system
built around the 440EP SoC. In the KVM model, the KVM kernel module is
responsible for all instruction execution, so it doesn't matter that TCG
doesn't emulate the 440 core.

We've only tested KVM and Bamboo with the -kernel option. I have no idea what
it would take to run a firmware like u-boot inside the VM, but it's basically
the same problem as running u-boot inside a 405 VM.

-Hollis

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

* KVM PowerPC support
@ 2008-12-15 16:44 ` Hollis Blanchard
  0 siblings, 0 replies; 31+ messages in thread
From: Hollis Blanchard @ 2008-12-15 16:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

I believe all comments from the first series have been addressed (thanks for
the quick review!). I was able to drop the first patch entirely, but realized
I should move/rename the 4xx SDRAM controller code, so that change is new.

Summary:
These patches implement KVM support for the PowerPC Bamboo board, a system
built around the 440EP SoC. In the KVM model, the KVM kernel module is
responsible for all instruction execution, so it doesn't matter that TCG
doesn't emulate the 440 core.

We've only tested KVM and Bamboo with the -kernel option. I have no idea what
it would take to run a firmware like u-boot inside the VM, but it's basically
the same problem as running u-boot inside a 405 VM.

-Hollis



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

* [Qemu-devel] [PATCH 1/8] Move PPC4xx SDRAM controller emulation from ppc405_uc.c to ppc4xx_devs.c
  2008-12-15 16:44 ` Hollis Blanchard
@ 2008-12-15 16:44   ` Hollis Blanchard
  -1 siblings, 0 replies; 31+ messages in thread
From: Hollis Blanchard @ 2008-12-15 16:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

The SDRAM controller is shared across almost all 405 and 440 embedded
processors, with some slight differences such as the sizes supported for each
memory bank.

Code movement only; no functional changes.

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
---
I think all device emulation should move from ppc405_uc.c to ppc4xx_devs.c,
since it is shared between all 4xx SoCs (405 and 440). At the moment, the SDRAM
controller is the only piece I have code for, so I'm only moving it.

(I can only guess "uc" means "microcontroller"; the file should be renamed as
well.)
---
 hw/ppc405.h      |    5 -
 hw/ppc405_uc.c   |  341 ------------------------------------------------------
 hw/ppc4xx.h      |    5 +
 hw/ppc4xx_devs.c |  341 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 346 insertions(+), 346 deletions(-)

diff --git a/hw/ppc405.h b/hw/ppc405.h
index e032170..eebcef3 100644
--- a/hw/ppc405.h
+++ b/hw/ppc405.h
@@ -66,11 +66,6 @@ void ppc4xx_pob_init (CPUState *env);
 /* OPB arbitrer */
 void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio,
                        target_phys_addr_t offset);
-/* SDRAM controller */
-void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
-                        target_phys_addr_t *ram_bases,
-                        target_phys_addr_t *ram_sizes,
-                        int do_init);
 /* Peripheral controller */
 void ppc405_ebc_init (CPUState *env);
 /* DMA controller */
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index 25bcfd8..7e7fb38 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -401,347 +401,6 @@ void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio,
 /* XXX: TODO */
 
 /*****************************************************************************/
-/* SDRAM controller */
-typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
-struct ppc4xx_sdram_t {
-    uint32_t addr;
-    int nbanks;
-    target_phys_addr_t ram_bases[4];
-    target_phys_addr_t ram_sizes[4];
-    uint32_t besr0;
-    uint32_t besr1;
-    uint32_t bear;
-    uint32_t cfg;
-    uint32_t status;
-    uint32_t rtr;
-    uint32_t pmit;
-    uint32_t bcr[4];
-    uint32_t tr;
-    uint32_t ecccfg;
-    uint32_t eccesr;
-    qemu_irq irq;
-};
-
-enum {
-    SDRAM0_CFGADDR = 0x010,
-    SDRAM0_CFGDATA = 0x011,
-};
-
-/* XXX: TOFIX: some patches have made this code become inconsistent:
- *      there are type inconsistencies, mixing target_phys_addr_t, target_ulong
- *      and uint32_t
- */
-static uint32_t sdram_bcr (target_phys_addr_t ram_base,
-                           target_phys_addr_t ram_size)
-{
-    uint32_t bcr;
-
-    switch (ram_size) {
-    case (4 * 1024 * 1024):
-        bcr = 0x00000000;
-        break;
-    case (8 * 1024 * 1024):
-        bcr = 0x00020000;
-        break;
-    case (16 * 1024 * 1024):
-        bcr = 0x00040000;
-        break;
-    case (32 * 1024 * 1024):
-        bcr = 0x00060000;
-        break;
-    case (64 * 1024 * 1024):
-        bcr = 0x00080000;
-        break;
-    case (128 * 1024 * 1024):
-        bcr = 0x000A0000;
-        break;
-    case (256 * 1024 * 1024):
-        bcr = 0x000C0000;
-        break;
-    default:
-        printf("%s: invalid RAM size " PADDRX "\n", __func__, ram_size);
-        return 0x00000000;
-    }
-    bcr |= ram_base & 0xFF800000;
-    bcr |= 1;
-
-    return bcr;
-}
-
-static always_inline target_phys_addr_t sdram_base (uint32_t bcr)
-{
-    return bcr & 0xFF800000;
-}
-
-static target_ulong sdram_size (uint32_t bcr)
-{
-    target_ulong size;
-    int sh;
-
-    sh = (bcr >> 17) & 0x7;
-    if (sh == 7)
-        size = -1;
-    else
-        size = (4 * 1024 * 1024) << sh;
-
-    return size;
-}
-
-static void sdram_set_bcr (uint32_t *bcrp, uint32_t bcr, int enabled)
-{
-    if (*bcrp & 0x00000001) {
-        /* Unmap RAM */
-#ifdef DEBUG_SDRAM
-        printf("%s: unmap RAM area " PADDRX " " ADDRX "\n",
-               __func__, sdram_base(*bcrp), sdram_size(*bcrp));
-#endif
-        cpu_register_physical_memory(sdram_base(*bcrp), sdram_size(*bcrp),
-                                     IO_MEM_UNASSIGNED);
-    }
-    *bcrp = bcr & 0xFFDEE001;
-    if (enabled && (bcr & 0x00000001)) {
-#ifdef DEBUG_SDRAM
-        printf("%s: Map RAM area " PADDRX " " ADDRX "\n",
-               __func__, sdram_base(bcr), sdram_size(bcr));
-#endif
-        cpu_register_physical_memory(sdram_base(bcr), sdram_size(bcr),
-                                     sdram_base(bcr) | IO_MEM_RAM);
-    }
-}
-
-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->bcr[i],
-                          sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
-                          1);
-        } else {
-            sdram_set_bcr(&sdram->bcr[i], 0x00000000, 0);
-        }
-    }
-}
-
-static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram)
-{
-    int i;
-
-    for (i = 0; i < sdram->nbanks; i++) {
-#ifdef DEBUG_SDRAM
-        printf("%s: Unmap RAM area " PADDRX " " ADDRX "\n",
-               __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
-#endif
-        cpu_register_physical_memory(sdram_base(sdram->bcr[i]),
-                                     sdram_size(sdram->bcr[i]),
-                                     IO_MEM_UNASSIGNED);
-    }
-}
-
-static target_ulong dcr_read_sdram (void *opaque, int dcrn)
-{
-    ppc4xx_sdram_t *sdram;
-    target_ulong ret;
-
-    sdram = opaque;
-    switch (dcrn) {
-    case SDRAM0_CFGADDR:
-        ret = sdram->addr;
-        break;
-    case SDRAM0_CFGDATA:
-        switch (sdram->addr) {
-        case 0x00: /* SDRAM_BESR0 */
-            ret = sdram->besr0;
-            break;
-        case 0x08: /* SDRAM_BESR1 */
-            ret = sdram->besr1;
-            break;
-        case 0x10: /* SDRAM_BEAR */
-            ret = sdram->bear;
-            break;
-        case 0x20: /* SDRAM_CFG */
-            ret = sdram->cfg;
-            break;
-        case 0x24: /* SDRAM_STATUS */
-            ret = sdram->status;
-            break;
-        case 0x30: /* SDRAM_RTR */
-            ret = sdram->rtr;
-            break;
-        case 0x34: /* SDRAM_PMIT */
-            ret = sdram->pmit;
-            break;
-        case 0x40: /* SDRAM_B0CR */
-            ret = sdram->bcr[0];
-            break;
-        case 0x44: /* SDRAM_B1CR */
-            ret = sdram->bcr[1];
-            break;
-        case 0x48: /* SDRAM_B2CR */
-            ret = sdram->bcr[2];
-            break;
-        case 0x4C: /* SDRAM_B3CR */
-            ret = sdram->bcr[3];
-            break;
-        case 0x80: /* SDRAM_TR */
-            ret = -1; /* ? */
-            break;
-        case 0x94: /* SDRAM_ECCCFG */
-            ret = sdram->ecccfg;
-            break;
-        case 0x98: /* SDRAM_ECCESR */
-            ret = sdram->eccesr;
-            break;
-        default: /* Error */
-            ret = -1;
-            break;
-        }
-        break;
-    default:
-        /* Avoid gcc warning */
-        ret = 0x00000000;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_sdram (void *opaque, int dcrn, target_ulong val)
-{
-    ppc4xx_sdram_t *sdram;
-
-    sdram = opaque;
-    switch (dcrn) {
-    case SDRAM0_CFGADDR:
-        sdram->addr = val;
-        break;
-    case SDRAM0_CFGDATA:
-        switch (sdram->addr) {
-        case 0x00: /* SDRAM_BESR0 */
-            sdram->besr0 &= ~val;
-            break;
-        case 0x08: /* SDRAM_BESR1 */
-            sdram->besr1 &= ~val;
-            break;
-        case 0x10: /* SDRAM_BEAR */
-            sdram->bear = val;
-            break;
-        case 0x20: /* SDRAM_CFG */
-            val &= 0xFFE00000;
-            if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
-#ifdef DEBUG_SDRAM
-                printf("%s: enable SDRAM controller\n", __func__);
-#endif
-                /* validate all RAM mappings */
-                sdram_map_bcr(sdram);
-                sdram->status &= ~0x80000000;
-            } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
-#ifdef DEBUG_SDRAM
-                printf("%s: disable SDRAM controller\n", __func__);
-#endif
-                /* invalidate all RAM mappings */
-                sdram_unmap_bcr(sdram);
-                sdram->status |= 0x80000000;
-            }
-            if (!(sdram->cfg & 0x40000000) && (val & 0x40000000))
-                sdram->status |= 0x40000000;
-            else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000))
-                sdram->status &= ~0x40000000;
-            sdram->cfg = val;
-            break;
-        case 0x24: /* SDRAM_STATUS */
-            /* Read-only register */
-            break;
-        case 0x30: /* SDRAM_RTR */
-            sdram->rtr = val & 0x3FF80000;
-            break;
-        case 0x34: /* SDRAM_PMIT */
-            sdram->pmit = (val & 0xF8000000) | 0x07C00000;
-            break;
-        case 0x40: /* SDRAM_B0CR */
-            sdram_set_bcr(&sdram->bcr[0], val, sdram->cfg & 0x80000000);
-            break;
-        case 0x44: /* SDRAM_B1CR */
-            sdram_set_bcr(&sdram->bcr[1], val, sdram->cfg & 0x80000000);
-            break;
-        case 0x48: /* SDRAM_B2CR */
-            sdram_set_bcr(&sdram->bcr[2], val, sdram->cfg & 0x80000000);
-            break;
-        case 0x4C: /* SDRAM_B3CR */
-            sdram_set_bcr(&sdram->bcr[3], val, sdram->cfg & 0x80000000);
-            break;
-        case 0x80: /* SDRAM_TR */
-            sdram->tr = val & 0x018FC01F;
-            break;
-        case 0x94: /* SDRAM_ECCCFG */
-            sdram->ecccfg = val & 0x00F00000;
-            break;
-        case 0x98: /* SDRAM_ECCESR */
-            val &= 0xFFF0F000;
-            if (sdram->eccesr == 0 && val != 0)
-                qemu_irq_raise(sdram->irq);
-            else if (sdram->eccesr != 0 && val == 0)
-                qemu_irq_lower(sdram->irq);
-            sdram->eccesr = val;
-            break;
-        default: /* Error */
-            break;
-        }
-        break;
-    }
-}
-
-static void sdram_reset (void *opaque)
-{
-    ppc4xx_sdram_t *sdram;
-
-    sdram = opaque;
-    sdram->addr = 0x00000000;
-    sdram->bear = 0x00000000;
-    sdram->besr0 = 0x00000000; /* No error */
-    sdram->besr1 = 0x00000000; /* No error */
-    sdram->cfg = 0x00000000;
-    sdram->ecccfg = 0x00000000; /* No ECC */
-    sdram->eccesr = 0x00000000; /* No error */
-    sdram->pmit = 0x07C00000;
-    sdram->rtr = 0x05F00000;
-    sdram->tr = 0x00854009;
-    /* We pre-initialize RAM banks */
-    sdram->status = 0x00000000;
-    sdram->cfg = 0x00800000;
-    sdram_unmap_bcr(sdram);
-}
-
-void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
-                        target_phys_addr_t *ram_bases,
-                        target_phys_addr_t *ram_sizes,
-                        int do_init)
-{
-    ppc4xx_sdram_t *sdram;
-
-    sdram = qemu_mallocz(sizeof(ppc4xx_sdram_t));
-    if (sdram != NULL) {
-        sdram->irq = irq;
-        sdram->nbanks = nbanks;
-        memset(sdram->ram_bases, 0, 4 * sizeof(target_phys_addr_t));
-        memcpy(sdram->ram_bases, ram_bases,
-               nbanks * sizeof(target_phys_addr_t));
-        memset(sdram->ram_sizes, 0, 4 * sizeof(target_phys_addr_t));
-        memcpy(sdram->ram_sizes, ram_sizes,
-               nbanks * sizeof(target_phys_addr_t));
-        sdram_reset(sdram);
-        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);
-    }
-}
-
-/*****************************************************************************/
 /* Peripheral controller */
 typedef struct ppc4xx_ebc_t ppc4xx_ebc_t;
 struct ppc4xx_ebc_t {
diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h
index 88802ae..8c2878a 100644
--- a/hw/ppc4xx.h
+++ b/hw/ppc4xx.h
@@ -48,6 +48,11 @@ enum {
 qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
                        uint32_t dcr_base, int has_ssr, int has_vr);
 
+void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
+                        target_phys_addr_t *ram_bases,
+                        target_phys_addr_t *ram_sizes,
+                        int do_init);
+
 PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
                         target_phys_addr_t config_space,
                         target_phys_addr_t int_ack,
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index ff67011..c6be2d6 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -532,3 +532,344 @@ qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
 
     return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
 }
+
+/*****************************************************************************/
+/* SDRAM controller */
+typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
+struct ppc4xx_sdram_t {
+    uint32_t addr;
+    int nbanks;
+    target_phys_addr_t ram_bases[4];
+    target_phys_addr_t ram_sizes[4];
+    uint32_t besr0;
+    uint32_t besr1;
+    uint32_t bear;
+    uint32_t cfg;
+    uint32_t status;
+    uint32_t rtr;
+    uint32_t pmit;
+    uint32_t bcr[4];
+    uint32_t tr;
+    uint32_t ecccfg;
+    uint32_t eccesr;
+    qemu_irq irq;
+};
+
+enum {
+    SDRAM0_CFGADDR = 0x010,
+    SDRAM0_CFGDATA = 0x011,
+};
+
+/* XXX: TOFIX: some patches have made this code become inconsistent:
+ *      there are type inconsistencies, mixing target_phys_addr_t, target_ulong
+ *      and uint32_t
+ */
+static uint32_t sdram_bcr (target_phys_addr_t ram_base,
+                           target_phys_addr_t ram_size)
+{
+    uint32_t bcr;
+
+    switch (ram_size) {
+    case (4 * 1024 * 1024):
+        bcr = 0x00000000;
+        break;
+    case (8 * 1024 * 1024):
+        bcr = 0x00020000;
+        break;
+    case (16 * 1024 * 1024):
+        bcr = 0x00040000;
+        break;
+    case (32 * 1024 * 1024):
+        bcr = 0x00060000;
+        break;
+    case (64 * 1024 * 1024):
+        bcr = 0x00080000;
+        break;
+    case (128 * 1024 * 1024):
+        bcr = 0x000A0000;
+        break;
+    case (256 * 1024 * 1024):
+        bcr = 0x000C0000;
+        break;
+    default:
+        printf("%s: invalid RAM size " PADDRX "\n", __func__, ram_size);
+        return 0x00000000;
+    }
+    bcr |= ram_base & 0xFF800000;
+    bcr |= 1;
+
+    return bcr;
+}
+
+static always_inline target_phys_addr_t sdram_base (uint32_t bcr)
+{
+    return bcr & 0xFF800000;
+}
+
+static target_ulong sdram_size (uint32_t bcr)
+{
+    target_ulong size;
+    int sh;
+
+    sh = (bcr >> 17) & 0x7;
+    if (sh == 7)
+        size = -1;
+    else
+        size = (4 * 1024 * 1024) << sh;
+
+    return size;
+}
+
+static void sdram_set_bcr (uint32_t *bcrp, uint32_t bcr, int enabled)
+{
+    if (*bcrp & 0x00000001) {
+        /* Unmap RAM */
+#ifdef DEBUG_SDRAM
+        printf("%s: unmap RAM area " PADDRX " " ADDRX "\n",
+               __func__, sdram_base(*bcrp), sdram_size(*bcrp));
+#endif
+        cpu_register_physical_memory(sdram_base(*bcrp), sdram_size(*bcrp),
+                                     IO_MEM_UNASSIGNED);
+    }
+    *bcrp = bcr & 0xFFDEE001;
+    if (enabled && (bcr & 0x00000001)) {
+#ifdef DEBUG_SDRAM
+        printf("%s: Map RAM area " PADDRX " " ADDRX "\n",
+               __func__, sdram_base(bcr), sdram_size(bcr));
+#endif
+        cpu_register_physical_memory(sdram_base(bcr), sdram_size(bcr),
+                                     sdram_base(bcr) | IO_MEM_RAM);
+    }
+}
+
+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->bcr[i],
+                          sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
+                          1);
+        } else {
+            sdram_set_bcr(&sdram->bcr[i], 0x00000000, 0);
+        }
+    }
+}
+
+static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram)
+{
+    int i;
+
+    for (i = 0; i < sdram->nbanks; i++) {
+#ifdef DEBUG_SDRAM
+        printf("%s: Unmap RAM area " PADDRX " " ADDRX "\n",
+               __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
+#endif
+        cpu_register_physical_memory(sdram_base(sdram->bcr[i]),
+                                     sdram_size(sdram->bcr[i]),
+                                     IO_MEM_UNASSIGNED);
+    }
+}
+
+static target_ulong dcr_read_sdram (void *opaque, int dcrn)
+{
+    ppc4xx_sdram_t *sdram;
+    target_ulong ret;
+
+    sdram = opaque;
+    switch (dcrn) {
+    case SDRAM0_CFGADDR:
+        ret = sdram->addr;
+        break;
+    case SDRAM0_CFGDATA:
+        switch (sdram->addr) {
+        case 0x00: /* SDRAM_BESR0 */
+            ret = sdram->besr0;
+            break;
+        case 0x08: /* SDRAM_BESR1 */
+            ret = sdram->besr1;
+            break;
+        case 0x10: /* SDRAM_BEAR */
+            ret = sdram->bear;
+            break;
+        case 0x20: /* SDRAM_CFG */
+            ret = sdram->cfg;
+            break;
+        case 0x24: /* SDRAM_STATUS */
+            ret = sdram->status;
+            break;
+        case 0x30: /* SDRAM_RTR */
+            ret = sdram->rtr;
+            break;
+        case 0x34: /* SDRAM_PMIT */
+            ret = sdram->pmit;
+            break;
+        case 0x40: /* SDRAM_B0CR */
+            ret = sdram->bcr[0];
+            break;
+        case 0x44: /* SDRAM_B1CR */
+            ret = sdram->bcr[1];
+            break;
+        case 0x48: /* SDRAM_B2CR */
+            ret = sdram->bcr[2];
+            break;
+        case 0x4C: /* SDRAM_B3CR */
+            ret = sdram->bcr[3];
+            break;
+        case 0x80: /* SDRAM_TR */
+            ret = -1; /* ? */
+            break;
+        case 0x94: /* SDRAM_ECCCFG */
+            ret = sdram->ecccfg;
+            break;
+        case 0x98: /* SDRAM_ECCESR */
+            ret = sdram->eccesr;
+            break;
+        default: /* Error */
+            ret = -1;
+            break;
+        }
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0x00000000;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_sdram (void *opaque, int dcrn, target_ulong val)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = opaque;
+    switch (dcrn) {
+    case SDRAM0_CFGADDR:
+        sdram->addr = val;
+        break;
+    case SDRAM0_CFGDATA:
+        switch (sdram->addr) {
+        case 0x00: /* SDRAM_BESR0 */
+            sdram->besr0 &= ~val;
+            break;
+        case 0x08: /* SDRAM_BESR1 */
+            sdram->besr1 &= ~val;
+            break;
+        case 0x10: /* SDRAM_BEAR */
+            sdram->bear = val;
+            break;
+        case 0x20: /* SDRAM_CFG */
+            val &= 0xFFE00000;
+            if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
+#ifdef DEBUG_SDRAM
+                printf("%s: enable SDRAM controller\n", __func__);
+#endif
+                /* validate all RAM mappings */
+                sdram_map_bcr(sdram);
+                sdram->status &= ~0x80000000;
+            } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
+#ifdef DEBUG_SDRAM
+                printf("%s: disable SDRAM controller\n", __func__);
+#endif
+                /* invalidate all RAM mappings */
+                sdram_unmap_bcr(sdram);
+                sdram->status |= 0x80000000;
+            }
+            if (!(sdram->cfg & 0x40000000) && (val & 0x40000000))
+                sdram->status |= 0x40000000;
+            else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000))
+                sdram->status &= ~0x40000000;
+            sdram->cfg = val;
+            break;
+        case 0x24: /* SDRAM_STATUS */
+            /* Read-only register */
+            break;
+        case 0x30: /* SDRAM_RTR */
+            sdram->rtr = val & 0x3FF80000;
+            break;
+        case 0x34: /* SDRAM_PMIT */
+            sdram->pmit = (val & 0xF8000000) | 0x07C00000;
+            break;
+        case 0x40: /* SDRAM_B0CR */
+            sdram_set_bcr(&sdram->bcr[0], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x44: /* SDRAM_B1CR */
+            sdram_set_bcr(&sdram->bcr[1], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x48: /* SDRAM_B2CR */
+            sdram_set_bcr(&sdram->bcr[2], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x4C: /* SDRAM_B3CR */
+            sdram_set_bcr(&sdram->bcr[3], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x80: /* SDRAM_TR */
+            sdram->tr = val & 0x018FC01F;
+            break;
+        case 0x94: /* SDRAM_ECCCFG */
+            sdram->ecccfg = val & 0x00F00000;
+            break;
+        case 0x98: /* SDRAM_ECCESR */
+            val &= 0xFFF0F000;
+            if (sdram->eccesr == 0 && val != 0)
+                qemu_irq_raise(sdram->irq);
+            else if (sdram->eccesr != 0 && val == 0)
+                qemu_irq_lower(sdram->irq);
+            sdram->eccesr = val;
+            break;
+        default: /* Error */
+            break;
+        }
+        break;
+    }
+}
+
+static void sdram_reset (void *opaque)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = opaque;
+    sdram->addr = 0x00000000;
+    sdram->bear = 0x00000000;
+    sdram->besr0 = 0x00000000; /* No error */
+    sdram->besr1 = 0x00000000; /* No error */
+    sdram->cfg = 0x00000000;
+    sdram->ecccfg = 0x00000000; /* No ECC */
+    sdram->eccesr = 0x00000000; /* No error */
+    sdram->pmit = 0x07C00000;
+    sdram->rtr = 0x05F00000;
+    sdram->tr = 0x00854009;
+    /* We pre-initialize RAM banks */
+    sdram->status = 0x00000000;
+    sdram->cfg = 0x00800000;
+    sdram_unmap_bcr(sdram);
+}
+
+void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
+                        target_phys_addr_t *ram_bases,
+                        target_phys_addr_t *ram_sizes,
+                        int do_init)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = qemu_mallocz(sizeof(ppc4xx_sdram_t));
+    if (sdram != NULL) {
+        sdram->irq = irq;
+        sdram->nbanks = nbanks;
+        memset(sdram->ram_bases, 0, 4 * sizeof(target_phys_addr_t));
+        memcpy(sdram->ram_bases, ram_bases,
+               nbanks * sizeof(target_phys_addr_t));
+        memset(sdram->ram_sizes, 0, 4 * sizeof(target_phys_addr_t));
+        memcpy(sdram->ram_sizes, ram_sizes,
+               nbanks * sizeof(target_phys_addr_t));
+        sdram_reset(sdram);
+        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);
+    }
+}
-- 
1.5.6.5

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

* [PATCH 1/8] Move PPC4xx SDRAM controller emulation from ppc405_uc.c to ppc4xx_devs.c
@ 2008-12-15 16:44   ` Hollis Blanchard
  0 siblings, 0 replies; 31+ messages in thread
From: Hollis Blanchard @ 2008-12-15 16:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

The SDRAM controller is shared across almost all 405 and 440 embedded
processors, with some slight differences such as the sizes supported for each
memory bank.

Code movement only; no functional changes.

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
---
I think all device emulation should move from ppc405_uc.c to ppc4xx_devs.c,
since it is shared between all 4xx SoCs (405 and 440). At the moment, the SDRAM
controller is the only piece I have code for, so I'm only moving it.

(I can only guess "uc" means "microcontroller"; the file should be renamed as
well.)
---
 hw/ppc405.h      |    5 -
 hw/ppc405_uc.c   |  341 ------------------------------------------------------
 hw/ppc4xx.h      |    5 +
 hw/ppc4xx_devs.c |  341 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 346 insertions(+), 346 deletions(-)

diff --git a/hw/ppc405.h b/hw/ppc405.h
index e032170..eebcef3 100644
--- a/hw/ppc405.h
+++ b/hw/ppc405.h
@@ -66,11 +66,6 @@ void ppc4xx_pob_init (CPUState *env);
 /* OPB arbitrer */
 void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio,
                        target_phys_addr_t offset);
-/* SDRAM controller */
-void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
-                        target_phys_addr_t *ram_bases,
-                        target_phys_addr_t *ram_sizes,
-                        int do_init);
 /* Peripheral controller */
 void ppc405_ebc_init (CPUState *env);
 /* DMA controller */
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index 25bcfd8..7e7fb38 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -401,347 +401,6 @@ void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio,
 /* XXX: TODO */
 
 /*****************************************************************************/
-/* SDRAM controller */
-typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
-struct ppc4xx_sdram_t {
-    uint32_t addr;
-    int nbanks;
-    target_phys_addr_t ram_bases[4];
-    target_phys_addr_t ram_sizes[4];
-    uint32_t besr0;
-    uint32_t besr1;
-    uint32_t bear;
-    uint32_t cfg;
-    uint32_t status;
-    uint32_t rtr;
-    uint32_t pmit;
-    uint32_t bcr[4];
-    uint32_t tr;
-    uint32_t ecccfg;
-    uint32_t eccesr;
-    qemu_irq irq;
-};
-
-enum {
-    SDRAM0_CFGADDR = 0x010,
-    SDRAM0_CFGDATA = 0x011,
-};
-
-/* XXX: TOFIX: some patches have made this code become inconsistent:
- *      there are type inconsistencies, mixing target_phys_addr_t, target_ulong
- *      and uint32_t
- */
-static uint32_t sdram_bcr (target_phys_addr_t ram_base,
-                           target_phys_addr_t ram_size)
-{
-    uint32_t bcr;
-
-    switch (ram_size) {
-    case (4 * 1024 * 1024):
-        bcr = 0x00000000;
-        break;
-    case (8 * 1024 * 1024):
-        bcr = 0x00020000;
-        break;
-    case (16 * 1024 * 1024):
-        bcr = 0x00040000;
-        break;
-    case (32 * 1024 * 1024):
-        bcr = 0x00060000;
-        break;
-    case (64 * 1024 * 1024):
-        bcr = 0x00080000;
-        break;
-    case (128 * 1024 * 1024):
-        bcr = 0x000A0000;
-        break;
-    case (256 * 1024 * 1024):
-        bcr = 0x000C0000;
-        break;
-    default:
-        printf("%s: invalid RAM size " PADDRX "\n", __func__, ram_size);
-        return 0x00000000;
-    }
-    bcr |= ram_base & 0xFF800000;
-    bcr |= 1;
-
-    return bcr;
-}
-
-static always_inline target_phys_addr_t sdram_base (uint32_t bcr)
-{
-    return bcr & 0xFF800000;
-}
-
-static target_ulong sdram_size (uint32_t bcr)
-{
-    target_ulong size;
-    int sh;
-
-    sh = (bcr >> 17) & 0x7;
-    if (sh = 7)
-        size = -1;
-    else
-        size = (4 * 1024 * 1024) << sh;
-
-    return size;
-}
-
-static void sdram_set_bcr (uint32_t *bcrp, uint32_t bcr, int enabled)
-{
-    if (*bcrp & 0x00000001) {
-        /* Unmap RAM */
-#ifdef DEBUG_SDRAM
-        printf("%s: unmap RAM area " PADDRX " " ADDRX "\n",
-               __func__, sdram_base(*bcrp), sdram_size(*bcrp));
-#endif
-        cpu_register_physical_memory(sdram_base(*bcrp), sdram_size(*bcrp),
-                                     IO_MEM_UNASSIGNED);
-    }
-    *bcrp = bcr & 0xFFDEE001;
-    if (enabled && (bcr & 0x00000001)) {
-#ifdef DEBUG_SDRAM
-        printf("%s: Map RAM area " PADDRX " " ADDRX "\n",
-               __func__, sdram_base(bcr), sdram_size(bcr));
-#endif
-        cpu_register_physical_memory(sdram_base(bcr), sdram_size(bcr),
-                                     sdram_base(bcr) | IO_MEM_RAM);
-    }
-}
-
-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->bcr[i],
-                          sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
-                          1);
-        } else {
-            sdram_set_bcr(&sdram->bcr[i], 0x00000000, 0);
-        }
-    }
-}
-
-static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram)
-{
-    int i;
-
-    for (i = 0; i < sdram->nbanks; i++) {
-#ifdef DEBUG_SDRAM
-        printf("%s: Unmap RAM area " PADDRX " " ADDRX "\n",
-               __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
-#endif
-        cpu_register_physical_memory(sdram_base(sdram->bcr[i]),
-                                     sdram_size(sdram->bcr[i]),
-                                     IO_MEM_UNASSIGNED);
-    }
-}
-
-static target_ulong dcr_read_sdram (void *opaque, int dcrn)
-{
-    ppc4xx_sdram_t *sdram;
-    target_ulong ret;
-
-    sdram = opaque;
-    switch (dcrn) {
-    case SDRAM0_CFGADDR:
-        ret = sdram->addr;
-        break;
-    case SDRAM0_CFGDATA:
-        switch (sdram->addr) {
-        case 0x00: /* SDRAM_BESR0 */
-            ret = sdram->besr0;
-            break;
-        case 0x08: /* SDRAM_BESR1 */
-            ret = sdram->besr1;
-            break;
-        case 0x10: /* SDRAM_BEAR */
-            ret = sdram->bear;
-            break;
-        case 0x20: /* SDRAM_CFG */
-            ret = sdram->cfg;
-            break;
-        case 0x24: /* SDRAM_STATUS */
-            ret = sdram->status;
-            break;
-        case 0x30: /* SDRAM_RTR */
-            ret = sdram->rtr;
-            break;
-        case 0x34: /* SDRAM_PMIT */
-            ret = sdram->pmit;
-            break;
-        case 0x40: /* SDRAM_B0CR */
-            ret = sdram->bcr[0];
-            break;
-        case 0x44: /* SDRAM_B1CR */
-            ret = sdram->bcr[1];
-            break;
-        case 0x48: /* SDRAM_B2CR */
-            ret = sdram->bcr[2];
-            break;
-        case 0x4C: /* SDRAM_B3CR */
-            ret = sdram->bcr[3];
-            break;
-        case 0x80: /* SDRAM_TR */
-            ret = -1; /* ? */
-            break;
-        case 0x94: /* SDRAM_ECCCFG */
-            ret = sdram->ecccfg;
-            break;
-        case 0x98: /* SDRAM_ECCESR */
-            ret = sdram->eccesr;
-            break;
-        default: /* Error */
-            ret = -1;
-            break;
-        }
-        break;
-    default:
-        /* Avoid gcc warning */
-        ret = 0x00000000;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_sdram (void *opaque, int dcrn, target_ulong val)
-{
-    ppc4xx_sdram_t *sdram;
-
-    sdram = opaque;
-    switch (dcrn) {
-    case SDRAM0_CFGADDR:
-        sdram->addr = val;
-        break;
-    case SDRAM0_CFGDATA:
-        switch (sdram->addr) {
-        case 0x00: /* SDRAM_BESR0 */
-            sdram->besr0 &= ~val;
-            break;
-        case 0x08: /* SDRAM_BESR1 */
-            sdram->besr1 &= ~val;
-            break;
-        case 0x10: /* SDRAM_BEAR */
-            sdram->bear = val;
-            break;
-        case 0x20: /* SDRAM_CFG */
-            val &= 0xFFE00000;
-            if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
-#ifdef DEBUG_SDRAM
-                printf("%s: enable SDRAM controller\n", __func__);
-#endif
-                /* validate all RAM mappings */
-                sdram_map_bcr(sdram);
-                sdram->status &= ~0x80000000;
-            } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
-#ifdef DEBUG_SDRAM
-                printf("%s: disable SDRAM controller\n", __func__);
-#endif
-                /* invalidate all RAM mappings */
-                sdram_unmap_bcr(sdram);
-                sdram->status |= 0x80000000;
-            }
-            if (!(sdram->cfg & 0x40000000) && (val & 0x40000000))
-                sdram->status |= 0x40000000;
-            else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000))
-                sdram->status &= ~0x40000000;
-            sdram->cfg = val;
-            break;
-        case 0x24: /* SDRAM_STATUS */
-            /* Read-only register */
-            break;
-        case 0x30: /* SDRAM_RTR */
-            sdram->rtr = val & 0x3FF80000;
-            break;
-        case 0x34: /* SDRAM_PMIT */
-            sdram->pmit = (val & 0xF8000000) | 0x07C00000;
-            break;
-        case 0x40: /* SDRAM_B0CR */
-            sdram_set_bcr(&sdram->bcr[0], val, sdram->cfg & 0x80000000);
-            break;
-        case 0x44: /* SDRAM_B1CR */
-            sdram_set_bcr(&sdram->bcr[1], val, sdram->cfg & 0x80000000);
-            break;
-        case 0x48: /* SDRAM_B2CR */
-            sdram_set_bcr(&sdram->bcr[2], val, sdram->cfg & 0x80000000);
-            break;
-        case 0x4C: /* SDRAM_B3CR */
-            sdram_set_bcr(&sdram->bcr[3], val, sdram->cfg & 0x80000000);
-            break;
-        case 0x80: /* SDRAM_TR */
-            sdram->tr = val & 0x018FC01F;
-            break;
-        case 0x94: /* SDRAM_ECCCFG */
-            sdram->ecccfg = val & 0x00F00000;
-            break;
-        case 0x98: /* SDRAM_ECCESR */
-            val &= 0xFFF0F000;
-            if (sdram->eccesr = 0 && val != 0)
-                qemu_irq_raise(sdram->irq);
-            else if (sdram->eccesr != 0 && val = 0)
-                qemu_irq_lower(sdram->irq);
-            sdram->eccesr = val;
-            break;
-        default: /* Error */
-            break;
-        }
-        break;
-    }
-}
-
-static void sdram_reset (void *opaque)
-{
-    ppc4xx_sdram_t *sdram;
-
-    sdram = opaque;
-    sdram->addr = 0x00000000;
-    sdram->bear = 0x00000000;
-    sdram->besr0 = 0x00000000; /* No error */
-    sdram->besr1 = 0x00000000; /* No error */
-    sdram->cfg = 0x00000000;
-    sdram->ecccfg = 0x00000000; /* No ECC */
-    sdram->eccesr = 0x00000000; /* No error */
-    sdram->pmit = 0x07C00000;
-    sdram->rtr = 0x05F00000;
-    sdram->tr = 0x00854009;
-    /* We pre-initialize RAM banks */
-    sdram->status = 0x00000000;
-    sdram->cfg = 0x00800000;
-    sdram_unmap_bcr(sdram);
-}
-
-void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
-                        target_phys_addr_t *ram_bases,
-                        target_phys_addr_t *ram_sizes,
-                        int do_init)
-{
-    ppc4xx_sdram_t *sdram;
-
-    sdram = qemu_mallocz(sizeof(ppc4xx_sdram_t));
-    if (sdram != NULL) {
-        sdram->irq = irq;
-        sdram->nbanks = nbanks;
-        memset(sdram->ram_bases, 0, 4 * sizeof(target_phys_addr_t));
-        memcpy(sdram->ram_bases, ram_bases,
-               nbanks * sizeof(target_phys_addr_t));
-        memset(sdram->ram_sizes, 0, 4 * sizeof(target_phys_addr_t));
-        memcpy(sdram->ram_sizes, ram_sizes,
-               nbanks * sizeof(target_phys_addr_t));
-        sdram_reset(sdram);
-        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);
-    }
-}
-
-/*****************************************************************************/
 /* Peripheral controller */
 typedef struct ppc4xx_ebc_t ppc4xx_ebc_t;
 struct ppc4xx_ebc_t {
diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h
index 88802ae..8c2878a 100644
--- a/hw/ppc4xx.h
+++ b/hw/ppc4xx.h
@@ -48,6 +48,11 @@ enum {
 qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
                        uint32_t dcr_base, int has_ssr, int has_vr);
 
+void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
+                        target_phys_addr_t *ram_bases,
+                        target_phys_addr_t *ram_sizes,
+                        int do_init);
+
 PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
                         target_phys_addr_t config_space,
                         target_phys_addr_t int_ack,
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index ff67011..c6be2d6 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -532,3 +532,344 @@ qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
 
     return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
 }
+
+/*****************************************************************************/
+/* SDRAM controller */
+typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
+struct ppc4xx_sdram_t {
+    uint32_t addr;
+    int nbanks;
+    target_phys_addr_t ram_bases[4];
+    target_phys_addr_t ram_sizes[4];
+    uint32_t besr0;
+    uint32_t besr1;
+    uint32_t bear;
+    uint32_t cfg;
+    uint32_t status;
+    uint32_t rtr;
+    uint32_t pmit;
+    uint32_t bcr[4];
+    uint32_t tr;
+    uint32_t ecccfg;
+    uint32_t eccesr;
+    qemu_irq irq;
+};
+
+enum {
+    SDRAM0_CFGADDR = 0x010,
+    SDRAM0_CFGDATA = 0x011,
+};
+
+/* XXX: TOFIX: some patches have made this code become inconsistent:
+ *      there are type inconsistencies, mixing target_phys_addr_t, target_ulong
+ *      and uint32_t
+ */
+static uint32_t sdram_bcr (target_phys_addr_t ram_base,
+                           target_phys_addr_t ram_size)
+{
+    uint32_t bcr;
+
+    switch (ram_size) {
+    case (4 * 1024 * 1024):
+        bcr = 0x00000000;
+        break;
+    case (8 * 1024 * 1024):
+        bcr = 0x00020000;
+        break;
+    case (16 * 1024 * 1024):
+        bcr = 0x00040000;
+        break;
+    case (32 * 1024 * 1024):
+        bcr = 0x00060000;
+        break;
+    case (64 * 1024 * 1024):
+        bcr = 0x00080000;
+        break;
+    case (128 * 1024 * 1024):
+        bcr = 0x000A0000;
+        break;
+    case (256 * 1024 * 1024):
+        bcr = 0x000C0000;
+        break;
+    default:
+        printf("%s: invalid RAM size " PADDRX "\n", __func__, ram_size);
+        return 0x00000000;
+    }
+    bcr |= ram_base & 0xFF800000;
+    bcr |= 1;
+
+    return bcr;
+}
+
+static always_inline target_phys_addr_t sdram_base (uint32_t bcr)
+{
+    return bcr & 0xFF800000;
+}
+
+static target_ulong sdram_size (uint32_t bcr)
+{
+    target_ulong size;
+    int sh;
+
+    sh = (bcr >> 17) & 0x7;
+    if (sh = 7)
+        size = -1;
+    else
+        size = (4 * 1024 * 1024) << sh;
+
+    return size;
+}
+
+static void sdram_set_bcr (uint32_t *bcrp, uint32_t bcr, int enabled)
+{
+    if (*bcrp & 0x00000001) {
+        /* Unmap RAM */
+#ifdef DEBUG_SDRAM
+        printf("%s: unmap RAM area " PADDRX " " ADDRX "\n",
+               __func__, sdram_base(*bcrp), sdram_size(*bcrp));
+#endif
+        cpu_register_physical_memory(sdram_base(*bcrp), sdram_size(*bcrp),
+                                     IO_MEM_UNASSIGNED);
+    }
+    *bcrp = bcr & 0xFFDEE001;
+    if (enabled && (bcr & 0x00000001)) {
+#ifdef DEBUG_SDRAM
+        printf("%s: Map RAM area " PADDRX " " ADDRX "\n",
+               __func__, sdram_base(bcr), sdram_size(bcr));
+#endif
+        cpu_register_physical_memory(sdram_base(bcr), sdram_size(bcr),
+                                     sdram_base(bcr) | IO_MEM_RAM);
+    }
+}
+
+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->bcr[i],
+                          sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
+                          1);
+        } else {
+            sdram_set_bcr(&sdram->bcr[i], 0x00000000, 0);
+        }
+    }
+}
+
+static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram)
+{
+    int i;
+
+    for (i = 0; i < sdram->nbanks; i++) {
+#ifdef DEBUG_SDRAM
+        printf("%s: Unmap RAM area " PADDRX " " ADDRX "\n",
+               __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
+#endif
+        cpu_register_physical_memory(sdram_base(sdram->bcr[i]),
+                                     sdram_size(sdram->bcr[i]),
+                                     IO_MEM_UNASSIGNED);
+    }
+}
+
+static target_ulong dcr_read_sdram (void *opaque, int dcrn)
+{
+    ppc4xx_sdram_t *sdram;
+    target_ulong ret;
+
+    sdram = opaque;
+    switch (dcrn) {
+    case SDRAM0_CFGADDR:
+        ret = sdram->addr;
+        break;
+    case SDRAM0_CFGDATA:
+        switch (sdram->addr) {
+        case 0x00: /* SDRAM_BESR0 */
+            ret = sdram->besr0;
+            break;
+        case 0x08: /* SDRAM_BESR1 */
+            ret = sdram->besr1;
+            break;
+        case 0x10: /* SDRAM_BEAR */
+            ret = sdram->bear;
+            break;
+        case 0x20: /* SDRAM_CFG */
+            ret = sdram->cfg;
+            break;
+        case 0x24: /* SDRAM_STATUS */
+            ret = sdram->status;
+            break;
+        case 0x30: /* SDRAM_RTR */
+            ret = sdram->rtr;
+            break;
+        case 0x34: /* SDRAM_PMIT */
+            ret = sdram->pmit;
+            break;
+        case 0x40: /* SDRAM_B0CR */
+            ret = sdram->bcr[0];
+            break;
+        case 0x44: /* SDRAM_B1CR */
+            ret = sdram->bcr[1];
+            break;
+        case 0x48: /* SDRAM_B2CR */
+            ret = sdram->bcr[2];
+            break;
+        case 0x4C: /* SDRAM_B3CR */
+            ret = sdram->bcr[3];
+            break;
+        case 0x80: /* SDRAM_TR */
+            ret = -1; /* ? */
+            break;
+        case 0x94: /* SDRAM_ECCCFG */
+            ret = sdram->ecccfg;
+            break;
+        case 0x98: /* SDRAM_ECCESR */
+            ret = sdram->eccesr;
+            break;
+        default: /* Error */
+            ret = -1;
+            break;
+        }
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0x00000000;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_sdram (void *opaque, int dcrn, target_ulong val)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = opaque;
+    switch (dcrn) {
+    case SDRAM0_CFGADDR:
+        sdram->addr = val;
+        break;
+    case SDRAM0_CFGDATA:
+        switch (sdram->addr) {
+        case 0x00: /* SDRAM_BESR0 */
+            sdram->besr0 &= ~val;
+            break;
+        case 0x08: /* SDRAM_BESR1 */
+            sdram->besr1 &= ~val;
+            break;
+        case 0x10: /* SDRAM_BEAR */
+            sdram->bear = val;
+            break;
+        case 0x20: /* SDRAM_CFG */
+            val &= 0xFFE00000;
+            if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
+#ifdef DEBUG_SDRAM
+                printf("%s: enable SDRAM controller\n", __func__);
+#endif
+                /* validate all RAM mappings */
+                sdram_map_bcr(sdram);
+                sdram->status &= ~0x80000000;
+            } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
+#ifdef DEBUG_SDRAM
+                printf("%s: disable SDRAM controller\n", __func__);
+#endif
+                /* invalidate all RAM mappings */
+                sdram_unmap_bcr(sdram);
+                sdram->status |= 0x80000000;
+            }
+            if (!(sdram->cfg & 0x40000000) && (val & 0x40000000))
+                sdram->status |= 0x40000000;
+            else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000))
+                sdram->status &= ~0x40000000;
+            sdram->cfg = val;
+            break;
+        case 0x24: /* SDRAM_STATUS */
+            /* Read-only register */
+            break;
+        case 0x30: /* SDRAM_RTR */
+            sdram->rtr = val & 0x3FF80000;
+            break;
+        case 0x34: /* SDRAM_PMIT */
+            sdram->pmit = (val & 0xF8000000) | 0x07C00000;
+            break;
+        case 0x40: /* SDRAM_B0CR */
+            sdram_set_bcr(&sdram->bcr[0], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x44: /* SDRAM_B1CR */
+            sdram_set_bcr(&sdram->bcr[1], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x48: /* SDRAM_B2CR */
+            sdram_set_bcr(&sdram->bcr[2], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x4C: /* SDRAM_B3CR */
+            sdram_set_bcr(&sdram->bcr[3], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x80: /* SDRAM_TR */
+            sdram->tr = val & 0x018FC01F;
+            break;
+        case 0x94: /* SDRAM_ECCCFG */
+            sdram->ecccfg = val & 0x00F00000;
+            break;
+        case 0x98: /* SDRAM_ECCESR */
+            val &= 0xFFF0F000;
+            if (sdram->eccesr = 0 && val != 0)
+                qemu_irq_raise(sdram->irq);
+            else if (sdram->eccesr != 0 && val = 0)
+                qemu_irq_lower(sdram->irq);
+            sdram->eccesr = val;
+            break;
+        default: /* Error */
+            break;
+        }
+        break;
+    }
+}
+
+static void sdram_reset (void *opaque)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = opaque;
+    sdram->addr = 0x00000000;
+    sdram->bear = 0x00000000;
+    sdram->besr0 = 0x00000000; /* No error */
+    sdram->besr1 = 0x00000000; /* No error */
+    sdram->cfg = 0x00000000;
+    sdram->ecccfg = 0x00000000; /* No ECC */
+    sdram->eccesr = 0x00000000; /* No error */
+    sdram->pmit = 0x07C00000;
+    sdram->rtr = 0x05F00000;
+    sdram->tr = 0x00854009;
+    /* We pre-initialize RAM banks */
+    sdram->status = 0x00000000;
+    sdram->cfg = 0x00800000;
+    sdram_unmap_bcr(sdram);
+}
+
+void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
+                        target_phys_addr_t *ram_bases,
+                        target_phys_addr_t *ram_sizes,
+                        int do_init)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = qemu_mallocz(sizeof(ppc4xx_sdram_t));
+    if (sdram != NULL) {
+        sdram->irq = irq;
+        sdram->nbanks = nbanks;
+        memset(sdram->ram_bases, 0, 4 * sizeof(target_phys_addr_t));
+        memcpy(sdram->ram_bases, ram_bases,
+               nbanks * sizeof(target_phys_addr_t));
+        memset(sdram->ram_sizes, 0, 4 * sizeof(target_phys_addr_t));
+        memcpy(sdram->ram_sizes, ram_sizes,
+               nbanks * sizeof(target_phys_addr_t));
+        sdram_reset(sdram);
+        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);
+    }
+}
-- 
1.5.6.5


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

* [Qemu-devel] [PATCH 2/8] Rename ppc405_sdram_init() to ppc4xx_sdram_init()
  2008-12-15 16:44 ` Hollis Blanchard
@ 2008-12-15 16:44     ` Hollis Blanchard
  -1 siblings, 0 replies; 31+ messages in thread
From: Hollis Blanchard @ 2008-12-15 16:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

The SDRAM controller is shared across almost all 405 and 440 embedded
processors, with some slight differences such as the sizes supported for each
memory bank.

Rename only; no functional changes.

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
---
 hw/ppc405_uc.c   |    4 ++--
 hw/ppc4xx.h      |    2 +-
 hw/ppc4xx_devs.c |    2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index 7e7fb38..9275416 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -2230,7 +2230,7 @@ CPUState *ppc405cr_init (target_phys_addr_t ram_bases[4],
     pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
     *picp = pic;
     /* SDRAM controller */
-    ppc405_sdram_init(env, pic[14], 1, ram_bases, ram_sizes, do_init);
+    ppc4xx_sdram_init(env, pic[14], 1, ram_bases, ram_sizes, do_init);
     offset = 0;
     for (i = 0; i < 4; i++)
         offset += ram_sizes[i];
@@ -2588,7 +2588,7 @@ CPUState *ppc405ep_init (target_phys_addr_t ram_bases[2],
     *picp = pic;
     /* SDRAM controller */
 	/* XXX 405EP has no ECC interrupt */
-    ppc405_sdram_init(env, pic[17], 2, ram_bases, ram_sizes, do_init);
+    ppc4xx_sdram_init(env, pic[17], 2, ram_bases, ram_sizes, do_init);
     offset = 0;
     for (i = 0; i < 2; i++)
         offset += ram_sizes[i];
diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h
index 8c2878a..3b98662 100644
--- a/hw/ppc4xx.h
+++ b/hw/ppc4xx.h
@@ -48,7 +48,7 @@ enum {
 qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
                        uint32_t dcr_base, int has_ssr, int has_vr);
 
-void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
+void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
                         target_phys_addr_t *ram_bases,
                         target_phys_addr_t *ram_sizes,
                         int do_init);
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index c6be2d6..2d27e23 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -846,7 +846,7 @@ static void sdram_reset (void *opaque)
     sdram_unmap_bcr(sdram);
 }
 
-void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
+void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
                         target_phys_addr_t *ram_bases,
                         target_phys_addr_t *ram_sizes,
                         int do_init)
-- 
1.5.6.5

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

* [PATCH 2/8] Rename ppc405_sdram_init() to ppc4xx_sdram_init()
@ 2008-12-15 16:44     ` Hollis Blanchard
  0 siblings, 0 replies; 31+ messages in thread
From: Hollis Blanchard @ 2008-12-15 16:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

The SDRAM controller is shared across almost all 405 and 440 embedded
processors, with some slight differences such as the sizes supported for each
memory bank.

Rename only; no functional changes.

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
---
 hw/ppc405_uc.c   |    4 ++--
 hw/ppc4xx.h      |    2 +-
 hw/ppc4xx_devs.c |    2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index 7e7fb38..9275416 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -2230,7 +2230,7 @@ CPUState *ppc405cr_init (target_phys_addr_t ram_bases[4],
     pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
     *picp = pic;
     /* SDRAM controller */
-    ppc405_sdram_init(env, pic[14], 1, ram_bases, ram_sizes, do_init);
+    ppc4xx_sdram_init(env, pic[14], 1, ram_bases, ram_sizes, do_init);
     offset = 0;
     for (i = 0; i < 4; i++)
         offset += ram_sizes[i];
@@ -2588,7 +2588,7 @@ CPUState *ppc405ep_init (target_phys_addr_t ram_bases[2],
     *picp = pic;
     /* SDRAM controller */
 	/* XXX 405EP has no ECC interrupt */
-    ppc405_sdram_init(env, pic[17], 2, ram_bases, ram_sizes, do_init);
+    ppc4xx_sdram_init(env, pic[17], 2, ram_bases, ram_sizes, do_init);
     offset = 0;
     for (i = 0; i < 2; i++)
         offset += ram_sizes[i];
diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h
index 8c2878a..3b98662 100644
--- a/hw/ppc4xx.h
+++ b/hw/ppc4xx.h
@@ -48,7 +48,7 @@ enum {
 qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
                        uint32_t dcr_base, int has_ssr, int has_vr);
 
-void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
+void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
                         target_phys_addr_t *ram_bases,
                         target_phys_addr_t *ram_sizes,
                         int do_init);
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index c6be2d6..2d27e23 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -846,7 +846,7 @@ static void sdram_reset (void *opaque)
     sdram_unmap_bcr(sdram);
 }
 
-void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
+void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
                         target_phys_addr_t *ram_bases,
                         target_phys_addr_t *ram_sizes,
                         int do_init)
-- 
1.5.6.5


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

* [Qemu-devel] [PATCH 3/8] Create a helper function to allow more flexible RAM allocation for PPC 4xx
  2008-12-15 16:44 ` Hollis Blanchard
@ 2008-12-15 16:44     ` Hollis Blanchard
  -1 siblings, 0 replies; 31+ messages in thread
From: Hollis Blanchard @ 2008-12-15 16:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

The 4xx SDRAM controller supports a small number of banks, and each bank must
be one of a small set of sizes. The number of banks and the supported sizes
varies by SoC.

This function uses the user-specified RAM size to fill in the "ram_bases" and
"ram_sizes" arrays required by ppc4xx_sdram_init().

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
---
 hw/ppc4xx.h      |    5 +++++
 hw/ppc4xx_devs.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+), 0 deletions(-)

diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h
index 3b98662..7832cd9 100644
--- a/hw/ppc4xx.h
+++ b/hw/ppc4xx.h
@@ -48,6 +48,11 @@ enum {
 qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
                        uint32_t dcr_base, int has_ssr, int has_vr);
 
+ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
+                               target_phys_addr_t ram_bases[],
+                               target_phys_addr_t ram_sizes[],
+                               const unsigned int sdram_bank_sizes[]);
+
 void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
                         target_phys_addr_t *ram_bases,
                         target_phys_addr_t *ram_sizes,
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index 2d27e23..939e066 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -873,3 +873,45 @@ void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
             sdram_map_bcr(sdram);
     }
 }
+
+/* Fill in consecutive SDRAM banks with 'ram_size' bytes of memory.
+ *
+ * sdram_bank_sizes[] must be 0-terminated.
+ *
+ * The 4xx SDRAM controller supports a small number of banks, and each bank
+ * must be one of a small set of sizes. The number of banks and the supported
+ * sizes varies by SoC. */
+ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
+                               target_phys_addr_t ram_bases[],
+                               target_phys_addr_t ram_sizes[],
+                               const unsigned int sdram_bank_sizes[])
+{
+    ram_addr_t ram_end = 0;
+    int i;
+    int j;
+
+    for (i = 0; i < nr_banks; i++) {
+        for (j = 0; sdram_bank_sizes[j] != 0; j++) {
+            unsigned int bank_size = sdram_bank_sizes[j];
+
+            if (bank_size <= ram_size) {
+                ram_bases[i] = ram_end;
+                ram_sizes[i] = bank_size;
+                ram_end += bank_size;
+                ram_size -= bank_size;
+                break;
+            }
+        }
+
+        if (!ram_size) {
+            /* No need to use the remaining banks. */
+            break;
+        }
+    }
+
+    if (ram_size)
+        printf("Truncating memory to %d MiB to fit SDRAM controller limits.\n",
+               (int)(ram_end >> 20));
+
+    return ram_end;
+}
-- 
1.5.6.5

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

* [PATCH 3/8] Create a helper function to allow more flexible RAM allocation for PPC 4xx
@ 2008-12-15 16:44     ` Hollis Blanchard
  0 siblings, 0 replies; 31+ messages in thread
From: Hollis Blanchard @ 2008-12-15 16:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

The 4xx SDRAM controller supports a small number of banks, and each bank must
be one of a small set of sizes. The number of banks and the supported sizes
varies by SoC.

This function uses the user-specified RAM size to fill in the "ram_bases" and
"ram_sizes" arrays required by ppc4xx_sdram_init().

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
---
 hw/ppc4xx.h      |    5 +++++
 hw/ppc4xx_devs.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+), 0 deletions(-)

diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h
index 3b98662..7832cd9 100644
--- a/hw/ppc4xx.h
+++ b/hw/ppc4xx.h
@@ -48,6 +48,11 @@ enum {
 qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
                        uint32_t dcr_base, int has_ssr, int has_vr);
 
+ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
+                               target_phys_addr_t ram_bases[],
+                               target_phys_addr_t ram_sizes[],
+                               const unsigned int sdram_bank_sizes[]);
+
 void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
                         target_phys_addr_t *ram_bases,
                         target_phys_addr_t *ram_sizes,
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index 2d27e23..939e066 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -873,3 +873,45 @@ void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
             sdram_map_bcr(sdram);
     }
 }
+
+/* Fill in consecutive SDRAM banks with 'ram_size' bytes of memory.
+ *
+ * sdram_bank_sizes[] must be 0-terminated.
+ *
+ * The 4xx SDRAM controller supports a small number of banks, and each bank
+ * must be one of a small set of sizes. The number of banks and the supported
+ * sizes varies by SoC. */
+ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
+                               target_phys_addr_t ram_bases[],
+                               target_phys_addr_t ram_sizes[],
+                               const unsigned int sdram_bank_sizes[])
+{
+    ram_addr_t ram_end = 0;
+    int i;
+    int j;
+
+    for (i = 0; i < nr_banks; i++) {
+        for (j = 0; sdram_bank_sizes[j] != 0; j++) {
+            unsigned int bank_size = sdram_bank_sizes[j];
+
+            if (bank_size <= ram_size) {
+                ram_bases[i] = ram_end;
+                ram_sizes[i] = bank_size;
+                ram_end += bank_size;
+                ram_size -= bank_size;
+                break;
+            }
+        }
+
+        if (!ram_size) {
+            /* No need to use the remaining banks. */
+            break;
+        }
+    }
+
+    if (ram_size)
+        printf("Truncating memory to %d MiB to fit SDRAM controller limits.\n",
+               (int)(ram_end >> 20));
+
+    return ram_end;
+}
-- 
1.5.6.5


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

* [Qemu-devel] [PATCH 4/8] kvm: sync vcpu state during initialization
  2008-12-15 16:44 ` Hollis Blanchard
@ 2008-12-15 16:44     ` Hollis Blanchard
  -1 siblings, 0 replies; 31+ messages in thread
From: Hollis Blanchard @ 2008-12-15 16:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

Currently on x86, qemu initializes CPUState but KVM ignores it and does its
own vcpu initialization. However, PowerPC KVM needs to be able to set the
initial register state to support the -kernel and -append options.

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
---
 kvm-all.c |   15 +++++++++++++++
 kvm.h     |    1 +
 vl.c      |   11 +++++++++++
 3 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/kvm-all.c b/kvm-all.c
index dad80df..11034df 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -141,6 +141,21 @@ err:
     return ret;
 }
 
+int kvm_sync_vcpus(void)
+{
+    CPUState *env;
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        int ret;
+
+        ret = kvm_arch_put_registers(env);
+        if (ret)
+            return ret;
+    }
+
+    return 0;
+}
+
 /*
  * dirty pages logging control
  */
diff --git a/kvm.h b/kvm.h
index ac464ab..efce145 100644
--- a/kvm.h
+++ b/kvm.h
@@ -31,6 +31,7 @@ struct kvm_run;
 int kvm_init(int smp_cpus);
 
 int kvm_init_vcpu(CPUState *env);
+int kvm_sync_vcpus(void);
 
 int kvm_cpu_exec(CPUState *env);
 
diff --git a/vl.c b/vl.c
index c3a8d8f..0a02151 100644
--- a/vl.c
+++ b/vl.c
@@ -5456,6 +5456,17 @@ int main(int argc, char **argv, char **envp)
     machine->init(ram_size, vga_ram_size, boot_devices, ds,
                   kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
 
+    /* Set KVM's vcpu state to qemu's initial CPUState. */
+    if (kvm_enabled()) {
+        int ret;
+
+        ret = kvm_sync_vcpus();
+        if (ret < 0) {
+            fprintf(stderr, "failed to initialize vcpus\n");
+            exit(1);
+        }
+    }
+
     /* init USB devices */
     if (usb_enabled) {
         for(i = 0; i < usb_devices_index; i++) {
-- 
1.5.6.5

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

* [PATCH 4/8] kvm: sync vcpu state during initialization
@ 2008-12-15 16:44     ` Hollis Blanchard
  0 siblings, 0 replies; 31+ messages in thread
From: Hollis Blanchard @ 2008-12-15 16:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

Currently on x86, qemu initializes CPUState but KVM ignores it and does its
own vcpu initialization. However, PowerPC KVM needs to be able to set the
initial register state to support the -kernel and -append options.

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
---
 kvm-all.c |   15 +++++++++++++++
 kvm.h     |    1 +
 vl.c      |   11 +++++++++++
 3 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/kvm-all.c b/kvm-all.c
index dad80df..11034df 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -141,6 +141,21 @@ err:
     return ret;
 }
 
+int kvm_sync_vcpus(void)
+{
+    CPUState *env;
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        int ret;
+
+        ret = kvm_arch_put_registers(env);
+        if (ret)
+            return ret;
+    }
+
+    return 0;
+}
+
 /*
  * dirty pages logging control
  */
diff --git a/kvm.h b/kvm.h
index ac464ab..efce145 100644
--- a/kvm.h
+++ b/kvm.h
@@ -31,6 +31,7 @@ struct kvm_run;
 int kvm_init(int smp_cpus);
 
 int kvm_init_vcpu(CPUState *env);
+int kvm_sync_vcpus(void);
 
 int kvm_cpu_exec(CPUState *env);
 
diff --git a/vl.c b/vl.c
index c3a8d8f..0a02151 100644
--- a/vl.c
+++ b/vl.c
@@ -5456,6 +5456,17 @@ int main(int argc, char **argv, char **envp)
     machine->init(ram_size, vga_ram_size, boot_devices, ds,
                   kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
 
+    /* Set KVM's vcpu state to qemu's initial CPUState. */
+    if (kvm_enabled()) {
+        int ret;
+
+        ret = kvm_sync_vcpus();
+        if (ret < 0) {
+            fprintf(stderr, "failed to initialize vcpus\n");
+            exit(1);
+        }
+    }
+
     /* init USB devices */
     if (usb_enabled) {
         for(i = 0; i < usb_devices_index; i++) {
-- 
1.5.6.5


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

* [Qemu-devel] [PATCH 5/8] Implement device tree support needed for Bamboo emulation
  2008-12-15 16:44 ` Hollis Blanchard
@ 2008-12-15 16:44     ` Hollis Blanchard
  -1 siblings, 0 replies; 31+ messages in thread
From: Hollis Blanchard @ 2008-12-15 16:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

To implement the -kernel, -initrd, and -append options, 4xx board emulation
must load the guest kernel as if firmware had loaded it. Where u-boot would be
the firmware, we must load the flat device tree into memory and set key fields
such as /chosen/bootargs.

This patch introduces a dependency on libfdt for flat device tree support.

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
---
 Makefile.target |    4 ++
 configure       |   18 +++++++++
 device_tree.c   |  114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 device_tree.h   |   26 ++++++++++++
 libfdt_env.h    |   41 ++++++++++++++++++++
 5 files changed, 203 insertions(+), 0 deletions(-)
 create mode 100644 device_tree.c
 create mode 100644 device_tree.h
 create mode 100644 libfdt_env.h

diff --git a/Makefile.target b/Makefile.target
index 8229b4f..d80ce2c 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -655,6 +655,10 @@ OBJS+= heathrow_pic.o grackle_pci.o ppc_oldworld.o
 OBJS+= unin_pci.o ppc_chrp.o
 # PowerPC 4xx boards
 OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
+ifdef FDT_LIBS
+OBJS+= device_tree.o
+LIBS+= $(FDT_LIBS)
+endif
 # virtio support
 OBJS+= virtio.o virtio-blk.o virtio-balloon.o
 endif
diff --git a/configure b/configure
index 455dbef..562f113 100755
--- a/configure
+++ b/configure
@@ -119,6 +119,7 @@ kvm="yes"
 kerneldir=""
 aix="no"
 blobs="yes"
+fdt="yes"
 
 # OS specific
 targetos=`uname -s`
@@ -966,6 +967,18 @@ if $cc $ARCH_CFLAGS -o $TMPE $TMPC > /dev/null 2> /dev/null ; then
   iovec=yes
 fi
 
+##########################################
+# fdt probe
+if test "$fdt" = "yes" ; then
+    fdt=no
+    cat > $TMPC << EOF
+int main(void) { return 0; }
+EOF
+  if $cc $ARCH_CFLAGS -o $TMPE ${OS_CFLAGS} $TMPC -lfdt 2> /dev/null ; then
+    fdt=yes
+  fi
+fi
+
 # Check if tools are available to build documentation.
 if [ -x "`which texi2html 2>/dev/null`" ] && \
    [ -x "`which pod2man 2>/dev/null`" ]; then
@@ -1061,6 +1074,7 @@ echo "vde support       $vde"
 echo "AIO support       $aio"
 echo "Install blobs     $blobs"
 echo "KVM support       $kvm"
+echo "fdt support       $kvm"
 
 if test $sdl_too_old = "yes"; then
 echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -1350,6 +1364,10 @@ fi
 if test "$iovec" = "yes" ; then
   echo "#define HAVE_IOVEC 1" >> $config_h
 fi
+if test "$fdt" = "yes" ; then
+  echo "#define HAVE_FDT 1" >> $config_h
+  echo "FDT_LIBS=-lfdt" >> $config_mak
+fi
 
 # XXX: suppress that
 if [ "$bsd" = "yes" ] ; then
diff --git a/device_tree.c b/device_tree.c
new file mode 100644
index 0000000..2238682
--- /dev/null
+++ b/device_tree.c
@@ -0,0 +1,114 @@
+/*
+ * Functions to help device tree manipulation using libfdt.
+ * It also provides functions to read entries from device tree proc
+ * interface.
+ *
+ * Copyright 2008 IBM Corporation.
+ * Authors: Jerone Young <jyoung5@us.ibm.com>
+ *          Hollis Blanchard <hollisb@us.ibm.com>
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "config.h"
+#include "qemu-common.h"
+#include "sysemu.h"
+#include "device_tree.h"
+
+#include <libfdt.h>
+
+void *load_device_tree(const char *filename_path, void *load_addr)
+{
+    int dt_file_size;
+    int dt_file_load_size;
+    int new_dt_size;
+    int ret;
+    void *dt_file = NULL;
+    void *fdt;
+
+    dt_file_size = get_image_size(filename_path);
+    if (dt_file_size < 0) {
+        printf("Unable to get size of device tree file '%s'\n",
+            filename_path);
+        goto fail;
+    }
+
+    /* First allocate space in qemu for device tree */
+    dt_file = qemu_mallocz(dt_file_size);
+    if (dt_file == NULL) {
+        printf("Unable to allocate memory in qemu for device tree\n");
+        goto fail;
+    }
+
+    dt_file_load_size = load_image(filename_path, dt_file);
+
+    /* Second we place new copy of 2x size in guest memory
+     * This give us enough room for manipulation.
+     */
+    new_dt_size = dt_file_size * 2;
+
+    fdt = load_addr;
+    ret = fdt_open_into(dt_file, fdt, new_dt_size);
+    if (ret) {
+        printf("Unable to copy device tree in memory\n");
+        goto fail;
+    }
+
+    /* Check sanity of device tree */
+    if (fdt_check_header(fdt)) {
+        printf ("Device tree file loaded into memory is invalid: %s\n",
+            filename_path);
+        goto fail;
+    }
+    /* free qemu memory with old device tree */
+    qemu_free(dt_file);
+    return fdt;
+
+fail:
+    qemu_free(dt_file);
+    return NULL;
+}
+
+int qemu_devtree_setprop(void *fdt, const char *node_path,
+                         const char *property, uint32_t *val_array, int size)
+{
+    int offset;
+
+    offset = fdt_path_offset(fdt, node_path);
+    if (offset < 0)
+        return offset;
+
+    return fdt_setprop(fdt, offset, property, val_array, size);
+}
+
+int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
+                              const char *property, uint32_t val)
+{
+    int offset;
+
+    offset = fdt_path_offset(fdt, node_path);
+    if (offset < 0)
+        return offset;
+
+    return fdt_setprop_cell(fdt, offset, property, val);
+}
+
+int qemu_devtree_setprop_string(void *fdt, const char *node_path,
+                                const char *property, const char *string)
+{
+    int offset;
+
+    offset = fdt_path_offset(fdt, node_path);
+    if (offset < 0)
+        return offset;
+
+    return fdt_setprop_string(fdt, offset, property, string);
+}
diff --git a/device_tree.h b/device_tree.h
new file mode 100644
index 0000000..9e6ef3d
--- /dev/null
+++ b/device_tree.h
@@ -0,0 +1,26 @@
+/*
+ * Header with function prototypes to help device tree manipulation using
+ * libfdt. It also provides functions to read entries from device tree proc
+ * interface.
+ *
+ * Copyright 2008 IBM Corporation.
+ * Authors: Jerone Young <jyoung5@us.ibm.com>
+ *          Hollis Blanchard <hollisb@us.ibm.com>
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+#ifndef __DEVICE_TREE_H__
+#define __DEVICE_TREE_H__
+
+void *load_device_tree(const char *filename_path, void *load_addr);
+
+int qemu_devtree_setprop(void *fdt, const char *node_path,
+                         const char *property, uint32_t *val_array, int size);
+int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
+                              const char *property, uint32_t val);
+int qemu_devtree_setprop_string(void *fdt, const char *node_path,
+                                const char *property, const char *string);
+
+#endif /* __DEVICE_TREE_H__ */
diff --git a/libfdt_env.h b/libfdt_env.h
new file mode 100644
index 0000000..e154b8e
--- /dev/null
+++ b/libfdt_env.h
@@ -0,0 +1,41 @@
+/*
+ * 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, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2008
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ *
+ */
+
+#ifndef _LIBFDT_ENV_H
+#define _LIBFDT_ENV_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <endian.h>
+#include <byteswap.h>
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define fdt32_to_cpu(x)		(x)
+#define cpu_to_fdt32(x)		(x)
+#define fdt64_to_cpu(x)		(x)
+#define cpu_to_fdt64(x)		(x)
+#else
+#define fdt32_to_cpu(x)		(bswap_32((x)))
+#define cpu_to_fdt32(x)		(bswap_32((x)))
+#define fdt64_to_cpu(x)		(bswap_64((x)))
+#define cpu_to_fdt64(x)		(bswap_64((x)))
+#endif
+
+#endif /* _LIBFDT_ENV_H */
-- 
1.5.6.5

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

* [PATCH 5/8] Implement device tree support needed for Bamboo emulation
@ 2008-12-15 16:44     ` Hollis Blanchard
  0 siblings, 0 replies; 31+ messages in thread
From: Hollis Blanchard @ 2008-12-15 16:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

To implement the -kernel, -initrd, and -append options, 4xx board emulation
must load the guest kernel as if firmware had loaded it. Where u-boot would be
the firmware, we must load the flat device tree into memory and set key fields
such as /chosen/bootargs.

This patch introduces a dependency on libfdt for flat device tree support.

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
---
 Makefile.target |    4 ++
 configure       |   18 +++++++++
 device_tree.c   |  114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 device_tree.h   |   26 ++++++++++++
 libfdt_env.h    |   41 ++++++++++++++++++++
 5 files changed, 203 insertions(+), 0 deletions(-)
 create mode 100644 device_tree.c
 create mode 100644 device_tree.h
 create mode 100644 libfdt_env.h

diff --git a/Makefile.target b/Makefile.target
index 8229b4f..d80ce2c 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -655,6 +655,10 @@ OBJS+= heathrow_pic.o grackle_pci.o ppc_oldworld.o
 OBJS+= unin_pci.o ppc_chrp.o
 # PowerPC 4xx boards
 OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
+ifdef FDT_LIBS
+OBJS+= device_tree.o
+LIBS+= $(FDT_LIBS)
+endif
 # virtio support
 OBJS+= virtio.o virtio-blk.o virtio-balloon.o
 endif
diff --git a/configure b/configure
index 455dbef..562f113 100755
--- a/configure
+++ b/configure
@@ -119,6 +119,7 @@ kvm="yes"
 kerneldir=""
 aix="no"
 blobs="yes"
+fdt="yes"
 
 # OS specific
 targetos=`uname -s`
@@ -966,6 +967,18 @@ if $cc $ARCH_CFLAGS -o $TMPE $TMPC > /dev/null 2> /dev/null ; then
   iovec=yes
 fi
 
+##########################################
+# fdt probe
+if test "$fdt" = "yes" ; then
+    fdt=no
+    cat > $TMPC << EOF
+int main(void) { return 0; }
+EOF
+  if $cc $ARCH_CFLAGS -o $TMPE ${OS_CFLAGS} $TMPC -lfdt 2> /dev/null ; then
+    fdt=yes
+  fi
+fi
+
 # Check if tools are available to build documentation.
 if [ -x "`which texi2html 2>/dev/null`" ] && \
    [ -x "`which pod2man 2>/dev/null`" ]; then
@@ -1061,6 +1074,7 @@ echo "vde support       $vde"
 echo "AIO support       $aio"
 echo "Install blobs     $blobs"
 echo "KVM support       $kvm"
+echo "fdt support       $kvm"
 
 if test $sdl_too_old = "yes"; then
 echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -1350,6 +1364,10 @@ fi
 if test "$iovec" = "yes" ; then
   echo "#define HAVE_IOVEC 1" >> $config_h
 fi
+if test "$fdt" = "yes" ; then
+  echo "#define HAVE_FDT 1" >> $config_h
+  echo "FDT_LIBS=-lfdt" >> $config_mak
+fi
 
 # XXX: suppress that
 if [ "$bsd" = "yes" ] ; then
diff --git a/device_tree.c b/device_tree.c
new file mode 100644
index 0000000..2238682
--- /dev/null
+++ b/device_tree.c
@@ -0,0 +1,114 @@
+/*
+ * Functions to help device tree manipulation using libfdt.
+ * It also provides functions to read entries from device tree proc
+ * interface.
+ *
+ * Copyright 2008 IBM Corporation.
+ * Authors: Jerone Young <jyoung5@us.ibm.com>
+ *          Hollis Blanchard <hollisb@us.ibm.com>
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "config.h"
+#include "qemu-common.h"
+#include "sysemu.h"
+#include "device_tree.h"
+
+#include <libfdt.h>
+
+void *load_device_tree(const char *filename_path, void *load_addr)
+{
+    int dt_file_size;
+    int dt_file_load_size;
+    int new_dt_size;
+    int ret;
+    void *dt_file = NULL;
+    void *fdt;
+
+    dt_file_size = get_image_size(filename_path);
+    if (dt_file_size < 0) {
+        printf("Unable to get size of device tree file '%s'\n",
+            filename_path);
+        goto fail;
+    }
+
+    /* First allocate space in qemu for device tree */
+    dt_file = qemu_mallocz(dt_file_size);
+    if (dt_file = NULL) {
+        printf("Unable to allocate memory in qemu for device tree\n");
+        goto fail;
+    }
+
+    dt_file_load_size = load_image(filename_path, dt_file);
+
+    /* Second we place new copy of 2x size in guest memory
+     * This give us enough room for manipulation.
+     */
+    new_dt_size = dt_file_size * 2;
+
+    fdt = load_addr;
+    ret = fdt_open_into(dt_file, fdt, new_dt_size);
+    if (ret) {
+        printf("Unable to copy device tree in memory\n");
+        goto fail;
+    }
+
+    /* Check sanity of device tree */
+    if (fdt_check_header(fdt)) {
+        printf ("Device tree file loaded into memory is invalid: %s\n",
+            filename_path);
+        goto fail;
+    }
+    /* free qemu memory with old device tree */
+    qemu_free(dt_file);
+    return fdt;
+
+fail:
+    qemu_free(dt_file);
+    return NULL;
+}
+
+int qemu_devtree_setprop(void *fdt, const char *node_path,
+                         const char *property, uint32_t *val_array, int size)
+{
+    int offset;
+
+    offset = fdt_path_offset(fdt, node_path);
+    if (offset < 0)
+        return offset;
+
+    return fdt_setprop(fdt, offset, property, val_array, size);
+}
+
+int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
+                              const char *property, uint32_t val)
+{
+    int offset;
+
+    offset = fdt_path_offset(fdt, node_path);
+    if (offset < 0)
+        return offset;
+
+    return fdt_setprop_cell(fdt, offset, property, val);
+}
+
+int qemu_devtree_setprop_string(void *fdt, const char *node_path,
+                                const char *property, const char *string)
+{
+    int offset;
+
+    offset = fdt_path_offset(fdt, node_path);
+    if (offset < 0)
+        return offset;
+
+    return fdt_setprop_string(fdt, offset, property, string);
+}
diff --git a/device_tree.h b/device_tree.h
new file mode 100644
index 0000000..9e6ef3d
--- /dev/null
+++ b/device_tree.h
@@ -0,0 +1,26 @@
+/*
+ * Header with function prototypes to help device tree manipulation using
+ * libfdt. It also provides functions to read entries from device tree proc
+ * interface.
+ *
+ * Copyright 2008 IBM Corporation.
+ * Authors: Jerone Young <jyoung5@us.ibm.com>
+ *          Hollis Blanchard <hollisb@us.ibm.com>
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+#ifndef __DEVICE_TREE_H__
+#define __DEVICE_TREE_H__
+
+void *load_device_tree(const char *filename_path, void *load_addr);
+
+int qemu_devtree_setprop(void *fdt, const char *node_path,
+                         const char *property, uint32_t *val_array, int size);
+int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
+                              const char *property, uint32_t val);
+int qemu_devtree_setprop_string(void *fdt, const char *node_path,
+                                const char *property, const char *string);
+
+#endif /* __DEVICE_TREE_H__ */
diff --git a/libfdt_env.h b/libfdt_env.h
new file mode 100644
index 0000000..e154b8e
--- /dev/null
+++ b/libfdt_env.h
@@ -0,0 +1,41 @@
+/*
+ * 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, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2008
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ *
+ */
+
+#ifndef _LIBFDT_ENV_H
+#define _LIBFDT_ENV_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <endian.h>
+#include <byteswap.h>
+
+#if __BYTE_ORDER = __BIG_ENDIAN
+#define fdt32_to_cpu(x)		(x)
+#define cpu_to_fdt32(x)		(x)
+#define fdt64_to_cpu(x)		(x)
+#define cpu_to_fdt64(x)		(x)
+#else
+#define fdt32_to_cpu(x)		(bswap_32((x)))
+#define cpu_to_fdt32(x)		(bswap_32((x)))
+#define fdt64_to_cpu(x)		(bswap_64((x)))
+#define cpu_to_fdt64(x)		(bswap_64((x)))
+#endif
+
+#endif /* _LIBFDT_ENV_H */
-- 
1.5.6.5


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

* [Qemu-devel] [PATCH 6/8] Enable KVM for ppcemb.
  2008-12-15 16:44 ` Hollis Blanchard
@ 2008-12-15 16:44     ` Hollis Blanchard
  -1 siblings, 0 replies; 31+ messages in thread
From: Hollis Blanchard @ 2008-12-15 16:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

Implement hooks called by generic KVM code.

Also add code that will copy the host's CPU and timebase frequencies to the
guest, which is necessary on KVM because the guest can directly access the
timebase.

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
---
 Makefile.target      |    3 +
 configure            |    6 ++
 target-ppc/helper.c  |    5 +
 target-ppc/kvm.c     |  204 ++++++++++++++++++++++++++++++++++++++++++++++++++
 target-ppc/kvm_ppc.c |  110 +++++++++++++++++++++++++++
 target-ppc/kvm_ppc.h |   15 ++++
 6 files changed, 343 insertions(+), 0 deletions(-)
 create mode 100644 target-ppc/kvm.c
 create mode 100644 target-ppc/kvm_ppc.c
 create mode 100644 target-ppc/kvm_ppc.h

diff --git a/Makefile.target b/Makefile.target
index d80ce2c..cbff562 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -659,6 +659,9 @@ ifdef FDT_LIBS
 OBJS+= device_tree.o
 LIBS+= $(FDT_LIBS)
 endif
+ifdef CONFIG_KVM
+OBJS+= kvm_ppc.o
+endif
 # virtio support
 OBJS+= virtio.o virtio-blk.o virtio-balloon.o
 endif
diff --git a/configure b/configure
index 562f113..0944831 100755
--- a/configure
+++ b/configure
@@ -1491,6 +1491,7 @@ gdb_xml_files=""
 
 # Make sure the target and host cpus are compatible
 if test "$kvm" = "yes" -a ! \( "$target_cpu" = "$cpu" -o \
+  \( "$target_cpu" = "ppcemb" -a "$cpu" = "powerpc" \) -o \
   \( "$target_cpu" = "x86_64" -a "$cpu" = "i386"   \) -o \
   \( "$target_cpu" = "i386"   -a "$cpu" = "x86_64" \) \) ; then
   kvm="no"
@@ -1585,6 +1586,11 @@ case "$target_cpu" in
     echo "#define TARGET_ARCH \"ppcemb\"" >> $config_h
     echo "#define TARGET_PPC 1" >> $config_h
     echo "#define TARGET_PPCEMB 1" >> $config_h
+    if test "$kvm" = "yes" ; then
+      echo "CONFIG_KVM=yes" >> $config_mak
+      echo "KVM_CFLAGS=$kvm_cflags" >> $config_mak
+      echo "#define CONFIG_KVM 1" >> $config_h
+    fi
   ;;
   ppc64)
     echo "TARGET_ARCH=ppc64" >> $config_mak
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 538d9f3..4676d50 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -29,6 +29,7 @@
 #include "exec-all.h"
 #include "helper_regs.h"
 #include "qemu-common.h"
+#include "kvm.h"
 
 //#define DEBUG_MMU
 //#define DEBUG_BATS
@@ -2920,6 +2921,10 @@ CPUPPCState *cpu_ppc_init (const char *cpu_model)
     env->cpu_model_str = cpu_model;
     cpu_ppc_register_internal(env, def);
     cpu_ppc_reset(env);
+
+    if (kvm_enabled())
+        kvm_init_vcpu(env);
+
     return env;
 }
 
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
new file mode 100644
index 0000000..acbb1ab
--- /dev/null
+++ b/target-ppc/kvm.c
@@ -0,0 +1,204 @@
+/*
+ * PowerPC implementation of KVM hooks
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors:
+ *  Jerone Young <jyoung5@us.ibm.com>
+ *  Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
+ *  Hollis Blanchard <hollisb@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <linux/kvm.h>
+
+#include "qemu-common.h"
+#include "qemu-timer.h"
+#include "sysemu.h"
+#include "kvm.h"
+#include "kvm_ppc.h"
+#include "cpu.h"
+#include "device_tree.h"
+
+//#define DEBUG_KVM
+
+#ifdef DEBUG_KVM
+#define dprintf(fmt, ...) \
+    do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+#else
+#define dprintf(fmt, ...) \
+    do { } while (0)
+#endif
+
+int kvm_arch_init(KVMState *s, int smp_cpus)
+{
+    return 0;
+}
+
+int kvm_arch_init_vcpu(CPUState *cenv)
+{
+    return 0;
+}
+
+int kvm_arch_put_registers(CPUState *env)
+{
+    struct kvm_regs regs;
+    int ret;
+    int i;
+
+    ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs);
+    if (ret < 0)
+        return ret;
+
+    regs.ctr = env->ctr;
+    regs.lr  = env->lr;
+    regs.xer = env->xer;
+    regs.msr = env->msr;
+    regs.pc = env->nip;
+
+    regs.srr0 = env->spr[SPR_SRR0];
+    regs.srr1 = env->spr[SPR_SRR1];
+
+    regs.sprg0 = env->spr[SPR_SPRG0];
+    regs.sprg1 = env->spr[SPR_SPRG1];
+    regs.sprg2 = env->spr[SPR_SPRG2];
+    regs.sprg3 = env->spr[SPR_SPRG3];
+    regs.sprg4 = env->spr[SPR_SPRG4];
+    regs.sprg5 = env->spr[SPR_SPRG5];
+    regs.sprg6 = env->spr[SPR_SPRG6];
+    regs.sprg7 = env->spr[SPR_SPRG7];
+
+    for (i = 0;i < 32; i++)
+        regs.gpr[i] = env->gpr[i];
+
+    ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, &regs);
+    if (ret < 0)
+        return ret;
+
+    return ret;
+}
+
+int kvm_arch_get_registers(CPUState *env)
+{
+    struct kvm_regs regs;
+    uint32_t i, ret;
+
+    ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs);
+    if (ret < 0)
+        return ret;
+
+    env->ctr = regs.ctr;
+    env->lr = regs.lr;
+    env->xer = regs.xer;
+    env->msr = regs.msr;
+    env->nip = regs.pc;
+
+    env->spr[SPR_SRR0] = regs.srr0;
+    env->spr[SPR_SRR1] = regs.srr1;
+
+    env->spr[SPR_SPRG0] = regs.sprg0;
+    env->spr[SPR_SPRG1] = regs.sprg1;
+    env->spr[SPR_SPRG2] = regs.sprg2;
+    env->spr[SPR_SPRG3] = regs.sprg3;
+    env->spr[SPR_SPRG4] = regs.sprg4;
+    env->spr[SPR_SPRG5] = regs.sprg5;
+    env->spr[SPR_SPRG6] = regs.sprg6;
+    env->spr[SPR_SPRG7] = regs.sprg7;
+
+    for (i = 0;i < 32; i++)
+        env->gpr[i] = regs.gpr[i];
+
+    return 0;
+}
+
+int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
+{
+    int r;
+    unsigned irq;
+
+    /* PowerPC Qemu tracks the various core input pins (interrupt, critical
+     * interrupt, reset, etc) in PPC-specific env->irq_input_state. */
+    if (run->ready_for_interrupt_injection &&
+        (env->interrupt_request & CPU_INTERRUPT_HARD) &&
+        (env->irq_input_state & (1<<PPC40x_INPUT_INT)))
+    {
+        /* For now KVM disregards the 'irq' argument. However, in the
+         * future KVM could cache it in-kernel to avoid a heavyweight exit
+         * when reading the UIC.
+         */
+        irq = -1U;
+
+        dprintf("injected interrupt %d\n", irq);
+        r = kvm_vcpu_ioctl(env, KVM_INTERRUPT, &irq);
+        if (r < 0)
+            printf("cpu %d fail inject %x\n", env->cpu_index, irq);
+    }
+
+    /* We don't know if there are more interrupts pending after this. However,
+     * the guest will return to userspace in the course of handling this one
+     * anyways, so we will get a chance to deliver the rest. */
+    return 0;
+}
+
+int kvm_arch_post_run(CPUState *env, struct kvm_run *run)
+{
+    return 0;
+}
+
+static int kvmppc_handle_halt(CPUState *env)
+{
+    if (!(env->interrupt_request & CPU_INTERRUPT_HARD) && (msr_ee)) {
+        env->halted = 1;
+        env->exception_index = EXCP_HLT;
+    }
+
+    return 1;
+}
+
+/* map dcr access to existing qemu dcr emulation */
+static int kvmppc_handle_dcr_read(CPUState *env, uint32_t dcrn, uint32_t *data)
+{
+    if (ppc_dcr_read(env->dcr_env, dcrn, data) < 0)
+        fprintf(stderr, "Read to unhandled DCR (0x%x)\n", dcrn);
+
+    return 1;
+}
+
+static int kvmppc_handle_dcr_write(CPUState *env, uint32_t dcrn, uint32_t data)
+{
+    if (ppc_dcr_write(env->dcr_env, dcrn, data) < 0)
+        fprintf(stderr, "Write to unhandled DCR (0x%x)\n", dcrn);
+
+    return 1;
+}
+
+int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
+{
+    int ret = 0;
+
+    switch (run->exit_reason) {
+    case KVM_EXIT_DCR:
+        if (run->dcr.is_write) {
+            dprintf("handle dcr write\n");
+            ret = kvmppc_handle_dcr_write(env, run->dcr.dcrn, run->dcr.data);
+        } else {
+            dprintf("handle dcr read\n");
+            ret = kvmppc_handle_dcr_read(env, run->dcr.dcrn, &run->dcr.data);
+        }
+        break;
+    case KVM_EXIT_HLT:
+        dprintf("handle halt\n");
+        ret = kvmppc_handle_halt(env);
+        break;
+    }
+
+    return ret;
+}
+
diff --git a/target-ppc/kvm_ppc.c b/target-ppc/kvm_ppc.c
new file mode 100644
index 0000000..0caa5b9
--- /dev/null
+++ b/target-ppc/kvm_ppc.c
@@ -0,0 +1,110 @@
+/*
+ * PowerPC KVM support
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * Authors:
+ *  Hollis Blanchard <hollisb@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "qemu-timer.h"
+#include "kvm_ppc.h"
+#include "device_tree.h"
+
+#define PROC_DEVTREE_PATH "/proc/device-tree"
+
+static QEMUTimer *kvmppc_timer;
+static unsigned int kvmppc_timer_rate;
+
+#ifdef HAVE_FDT
+static int kvmppc_read_host_property(const char *node_path, const char *prop,
+                                     void *val, size_t len)
+{
+    char *path;
+    FILE *f;
+    int ret;
+    int pathlen;
+
+    pathlen = snprintf(NULL, 0, "%s/%s/%s", PROC_DEVTREE_PATH, node_path, prop)
+              + 1;
+    path = qemu_malloc(pathlen);
+    if (path == NULL) {
+        ret = -ENOMEM;
+        goto out;
+    }
+
+    snprintf(path, pathlen, "%s/%s/%s", PROC_DEVTREE_PATH, node_path, prop);
+
+    f = fopen(path, "rb");
+    if (f == NULL) {
+        ret = errno;
+        goto free;
+    }
+
+    len = fread(val, len, 1, f);
+    if (len != 1) {
+        ret = ferror(f);
+        goto close;
+    }
+
+close:
+    fclose(f);
+free:
+    free(path);
+out:
+    return ret;
+}
+
+static int kvmppc_copy_host_cell(void *fdt, const char *node, const char *prop)
+{
+    uint32_t cell;
+    int ret;
+
+    ret = kvmppc_read_host_property(node, prop, &cell, sizeof(cell));
+    if (ret < 0) {
+        fprintf(stderr, "couldn't read host %s/%s\n", node, prop);
+        goto out;
+    }
+
+    ret = qemu_devtree_setprop_cell(fdt, node, prop, cell);
+    if (ret < 0) {
+        fprintf(stderr, "couldn't set guest %s/%s\n", node, prop);
+        goto out;
+    }
+
+out:
+    return ret;
+}
+
+void kvmppc_fdt_update(void *fdt)
+{
+    /* 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. */
+    kvmppc_copy_host_cell(fdt, "/cpus/cpu@0", "clock-frequency");
+    kvmppc_copy_host_cell(fdt, "/cpus/cpu@0", "timebase-frequency");
+}
+#endif
+
+static void kvmppc_timer_hack(void *opaque)
+{
+    qemu_service_io();
+    qemu_mod_timer(kvmppc_timer, qemu_get_clock(vm_clock) + kvmppc_timer_rate);
+}
+
+void kvmppc_init(void)
+{
+    /* XXX The only reason KVM yields control back to qemu is device IO. Since
+     * an idle guest does no IO, qemu's device model will never get a chance to
+     * run. So, until Qemu gains IO threads, we create this timer to ensure
+     * that the device model gets a chance to run. */
+    kvmppc_timer_rate = ticks_per_sec / 10;
+    kvmppc_timer = qemu_new_timer(vm_clock, &kvmppc_timer_hack, NULL);
+    qemu_mod_timer(kvmppc_timer, qemu_get_clock(vm_clock) + kvmppc_timer_rate);
+}
+
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
new file mode 100644
index 0000000..e536a88
--- /dev/null
+++ b/target-ppc/kvm_ppc.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2008 IBM Corporation.
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+#ifndef __KVM_PPC_H__
+#define __KVM_PPC_H__
+
+void kvmppc_init(void);
+void kvmppc_fdt_update(void *fdt);
+
+#endif /* __KVM_PPC_H__ */
-- 
1.5.6.5

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

* [PATCH 6/8] Enable KVM for ppcemb.
@ 2008-12-15 16:44     ` Hollis Blanchard
  0 siblings, 0 replies; 31+ messages in thread
From: Hollis Blanchard @ 2008-12-15 16:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

Implement hooks called by generic KVM code.

Also add code that will copy the host's CPU and timebase frequencies to the
guest, which is necessary on KVM because the guest can directly access the
timebase.

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
---
 Makefile.target      |    3 +
 configure            |    6 ++
 target-ppc/helper.c  |    5 +
 target-ppc/kvm.c     |  204 ++++++++++++++++++++++++++++++++++++++++++++++++++
 target-ppc/kvm_ppc.c |  110 +++++++++++++++++++++++++++
 target-ppc/kvm_ppc.h |   15 ++++
 6 files changed, 343 insertions(+), 0 deletions(-)
 create mode 100644 target-ppc/kvm.c
 create mode 100644 target-ppc/kvm_ppc.c
 create mode 100644 target-ppc/kvm_ppc.h

diff --git a/Makefile.target b/Makefile.target
index d80ce2c..cbff562 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -659,6 +659,9 @@ ifdef FDT_LIBS
 OBJS+= device_tree.o
 LIBS+= $(FDT_LIBS)
 endif
+ifdef CONFIG_KVM
+OBJS+= kvm_ppc.o
+endif
 # virtio support
 OBJS+= virtio.o virtio-blk.o virtio-balloon.o
 endif
diff --git a/configure b/configure
index 562f113..0944831 100755
--- a/configure
+++ b/configure
@@ -1491,6 +1491,7 @@ gdb_xml_files=""
 
 # Make sure the target and host cpus are compatible
 if test "$kvm" = "yes" -a ! \( "$target_cpu" = "$cpu" -o \
+  \( "$target_cpu" = "ppcemb" -a "$cpu" = "powerpc" \) -o \
   \( "$target_cpu" = "x86_64" -a "$cpu" = "i386"   \) -o \
   \( "$target_cpu" = "i386"   -a "$cpu" = "x86_64" \) \) ; then
   kvm="no"
@@ -1585,6 +1586,11 @@ case "$target_cpu" in
     echo "#define TARGET_ARCH \"ppcemb\"" >> $config_h
     echo "#define TARGET_PPC 1" >> $config_h
     echo "#define TARGET_PPCEMB 1" >> $config_h
+    if test "$kvm" = "yes" ; then
+      echo "CONFIG_KVM=yes" >> $config_mak
+      echo "KVM_CFLAGS=$kvm_cflags" >> $config_mak
+      echo "#define CONFIG_KVM 1" >> $config_h
+    fi
   ;;
   ppc64)
     echo "TARGET_ARCH=ppc64" >> $config_mak
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 538d9f3..4676d50 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -29,6 +29,7 @@
 #include "exec-all.h"
 #include "helper_regs.h"
 #include "qemu-common.h"
+#include "kvm.h"
 
 //#define DEBUG_MMU
 //#define DEBUG_BATS
@@ -2920,6 +2921,10 @@ CPUPPCState *cpu_ppc_init (const char *cpu_model)
     env->cpu_model_str = cpu_model;
     cpu_ppc_register_internal(env, def);
     cpu_ppc_reset(env);
+
+    if (kvm_enabled())
+        kvm_init_vcpu(env);
+
     return env;
 }
 
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
new file mode 100644
index 0000000..acbb1ab
--- /dev/null
+++ b/target-ppc/kvm.c
@@ -0,0 +1,204 @@
+/*
+ * PowerPC implementation of KVM hooks
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors:
+ *  Jerone Young <jyoung5@us.ibm.com>
+ *  Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
+ *  Hollis Blanchard <hollisb@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <linux/kvm.h>
+
+#include "qemu-common.h"
+#include "qemu-timer.h"
+#include "sysemu.h"
+#include "kvm.h"
+#include "kvm_ppc.h"
+#include "cpu.h"
+#include "device_tree.h"
+
+//#define DEBUG_KVM
+
+#ifdef DEBUG_KVM
+#define dprintf(fmt, ...) \
+    do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+#else
+#define dprintf(fmt, ...) \
+    do { } while (0)
+#endif
+
+int kvm_arch_init(KVMState *s, int smp_cpus)
+{
+    return 0;
+}
+
+int kvm_arch_init_vcpu(CPUState *cenv)
+{
+    return 0;
+}
+
+int kvm_arch_put_registers(CPUState *env)
+{
+    struct kvm_regs regs;
+    int ret;
+    int i;
+
+    ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs);
+    if (ret < 0)
+        return ret;
+
+    regs.ctr = env->ctr;
+    regs.lr  = env->lr;
+    regs.xer = env->xer;
+    regs.msr = env->msr;
+    regs.pc = env->nip;
+
+    regs.srr0 = env->spr[SPR_SRR0];
+    regs.srr1 = env->spr[SPR_SRR1];
+
+    regs.sprg0 = env->spr[SPR_SPRG0];
+    regs.sprg1 = env->spr[SPR_SPRG1];
+    regs.sprg2 = env->spr[SPR_SPRG2];
+    regs.sprg3 = env->spr[SPR_SPRG3];
+    regs.sprg4 = env->spr[SPR_SPRG4];
+    regs.sprg5 = env->spr[SPR_SPRG5];
+    regs.sprg6 = env->spr[SPR_SPRG6];
+    regs.sprg7 = env->spr[SPR_SPRG7];
+
+    for (i = 0;i < 32; i++)
+        regs.gpr[i] = env->gpr[i];
+
+    ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, &regs);
+    if (ret < 0)
+        return ret;
+
+    return ret;
+}
+
+int kvm_arch_get_registers(CPUState *env)
+{
+    struct kvm_regs regs;
+    uint32_t i, ret;
+
+    ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs);
+    if (ret < 0)
+        return ret;
+
+    env->ctr = regs.ctr;
+    env->lr = regs.lr;
+    env->xer = regs.xer;
+    env->msr = regs.msr;
+    env->nip = regs.pc;
+
+    env->spr[SPR_SRR0] = regs.srr0;
+    env->spr[SPR_SRR1] = regs.srr1;
+
+    env->spr[SPR_SPRG0] = regs.sprg0;
+    env->spr[SPR_SPRG1] = regs.sprg1;
+    env->spr[SPR_SPRG2] = regs.sprg2;
+    env->spr[SPR_SPRG3] = regs.sprg3;
+    env->spr[SPR_SPRG4] = regs.sprg4;
+    env->spr[SPR_SPRG5] = regs.sprg5;
+    env->spr[SPR_SPRG6] = regs.sprg6;
+    env->spr[SPR_SPRG7] = regs.sprg7;
+
+    for (i = 0;i < 32; i++)
+        env->gpr[i] = regs.gpr[i];
+
+    return 0;
+}
+
+int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
+{
+    int r;
+    unsigned irq;
+
+    /* PowerPC Qemu tracks the various core input pins (interrupt, critical
+     * interrupt, reset, etc) in PPC-specific env->irq_input_state. */
+    if (run->ready_for_interrupt_injection &&
+        (env->interrupt_request & CPU_INTERRUPT_HARD) &&
+        (env->irq_input_state & (1<<PPC40x_INPUT_INT)))
+    {
+        /* For now KVM disregards the 'irq' argument. However, in the
+         * future KVM could cache it in-kernel to avoid a heavyweight exit
+         * when reading the UIC.
+         */
+        irq = -1U;
+
+        dprintf("injected interrupt %d\n", irq);
+        r = kvm_vcpu_ioctl(env, KVM_INTERRUPT, &irq);
+        if (r < 0)
+            printf("cpu %d fail inject %x\n", env->cpu_index, irq);
+    }
+
+    /* We don't know if there are more interrupts pending after this. However,
+     * the guest will return to userspace in the course of handling this one
+     * anyways, so we will get a chance to deliver the rest. */
+    return 0;
+}
+
+int kvm_arch_post_run(CPUState *env, struct kvm_run *run)
+{
+    return 0;
+}
+
+static int kvmppc_handle_halt(CPUState *env)
+{
+    if (!(env->interrupt_request & CPU_INTERRUPT_HARD) && (msr_ee)) {
+        env->halted = 1;
+        env->exception_index = EXCP_HLT;
+    }
+
+    return 1;
+}
+
+/* map dcr access to existing qemu dcr emulation */
+static int kvmppc_handle_dcr_read(CPUState *env, uint32_t dcrn, uint32_t *data)
+{
+    if (ppc_dcr_read(env->dcr_env, dcrn, data) < 0)
+        fprintf(stderr, "Read to unhandled DCR (0x%x)\n", dcrn);
+
+    return 1;
+}
+
+static int kvmppc_handle_dcr_write(CPUState *env, uint32_t dcrn, uint32_t data)
+{
+    if (ppc_dcr_write(env->dcr_env, dcrn, data) < 0)
+        fprintf(stderr, "Write to unhandled DCR (0x%x)\n", dcrn);
+
+    return 1;
+}
+
+int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
+{
+    int ret = 0;
+
+    switch (run->exit_reason) {
+    case KVM_EXIT_DCR:
+        if (run->dcr.is_write) {
+            dprintf("handle dcr write\n");
+            ret = kvmppc_handle_dcr_write(env, run->dcr.dcrn, run->dcr.data);
+        } else {
+            dprintf("handle dcr read\n");
+            ret = kvmppc_handle_dcr_read(env, run->dcr.dcrn, &run->dcr.data);
+        }
+        break;
+    case KVM_EXIT_HLT:
+        dprintf("handle halt\n");
+        ret = kvmppc_handle_halt(env);
+        break;
+    }
+
+    return ret;
+}
+
diff --git a/target-ppc/kvm_ppc.c b/target-ppc/kvm_ppc.c
new file mode 100644
index 0000000..0caa5b9
--- /dev/null
+++ b/target-ppc/kvm_ppc.c
@@ -0,0 +1,110 @@
+/*
+ * PowerPC KVM support
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * Authors:
+ *  Hollis Blanchard <hollisb@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "qemu-timer.h"
+#include "kvm_ppc.h"
+#include "device_tree.h"
+
+#define PROC_DEVTREE_PATH "/proc/device-tree"
+
+static QEMUTimer *kvmppc_timer;
+static unsigned int kvmppc_timer_rate;
+
+#ifdef HAVE_FDT
+static int kvmppc_read_host_property(const char *node_path, const char *prop,
+                                     void *val, size_t len)
+{
+    char *path;
+    FILE *f;
+    int ret;
+    int pathlen;
+
+    pathlen = snprintf(NULL, 0, "%s/%s/%s", PROC_DEVTREE_PATH, node_path, prop)
+              + 1;
+    path = qemu_malloc(pathlen);
+    if (path = NULL) {
+        ret = -ENOMEM;
+        goto out;
+    }
+
+    snprintf(path, pathlen, "%s/%s/%s", PROC_DEVTREE_PATH, node_path, prop);
+
+    f = fopen(path, "rb");
+    if (f = NULL) {
+        ret = errno;
+        goto free;
+    }
+
+    len = fread(val, len, 1, f);
+    if (len != 1) {
+        ret = ferror(f);
+        goto close;
+    }
+
+close:
+    fclose(f);
+free:
+    free(path);
+out:
+    return ret;
+}
+
+static int kvmppc_copy_host_cell(void *fdt, const char *node, const char *prop)
+{
+    uint32_t cell;
+    int ret;
+
+    ret = kvmppc_read_host_property(node, prop, &cell, sizeof(cell));
+    if (ret < 0) {
+        fprintf(stderr, "couldn't read host %s/%s\n", node, prop);
+        goto out;
+    }
+
+    ret = qemu_devtree_setprop_cell(fdt, node, prop, cell);
+    if (ret < 0) {
+        fprintf(stderr, "couldn't set guest %s/%s\n", node, prop);
+        goto out;
+    }
+
+out:
+    return ret;
+}
+
+void kvmppc_fdt_update(void *fdt)
+{
+    /* 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. */
+    kvmppc_copy_host_cell(fdt, "/cpus/cpu@0", "clock-frequency");
+    kvmppc_copy_host_cell(fdt, "/cpus/cpu@0", "timebase-frequency");
+}
+#endif
+
+static void kvmppc_timer_hack(void *opaque)
+{
+    qemu_service_io();
+    qemu_mod_timer(kvmppc_timer, qemu_get_clock(vm_clock) + kvmppc_timer_rate);
+}
+
+void kvmppc_init(void)
+{
+    /* XXX The only reason KVM yields control back to qemu is device IO. Since
+     * an idle guest does no IO, qemu's device model will never get a chance to
+     * run. So, until Qemu gains IO threads, we create this timer to ensure
+     * that the device model gets a chance to run. */
+    kvmppc_timer_rate = ticks_per_sec / 10;
+    kvmppc_timer = qemu_new_timer(vm_clock, &kvmppc_timer_hack, NULL);
+    qemu_mod_timer(kvmppc_timer, qemu_get_clock(vm_clock) + kvmppc_timer_rate);
+}
+
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
new file mode 100644
index 0000000..e536a88
--- /dev/null
+++ b/target-ppc/kvm_ppc.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2008 IBM Corporation.
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+#ifndef __KVM_PPC_H__
+#define __KVM_PPC_H__
+
+void kvmppc_init(void);
+void kvmppc_fdt_update(void *fdt);
+
+#endif /* __KVM_PPC_H__ */
-- 
1.5.6.5


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

* [Qemu-devel] [PATCH 7/8] PowerPC 440EP SoC emulation
  2008-12-15 16:44 ` Hollis Blanchard
@ 2008-12-15 16:44     ` Hollis Blanchard
  -1 siblings, 0 replies; 31+ messages in thread
From: Hollis Blanchard @ 2008-12-15 16:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

Wire up the system-on-chip devices present on 440EP chips.

This patch is a little unusual in that qemu doesn't actually emulate the 440
core, but we use this board code with KVM (which does). If/when 440 core
emulation is supported, the kvm_enabled() hack can be removed.

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
---
 Makefile.target |    1 +
 hw/ppc440.c     |  103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/ppc440.h     |   20 +++++++++++
 3 files changed, 124 insertions(+), 0 deletions(-)
 create mode 100644 hw/ppc440.c
 create mode 100644 hw/ppc440.h

diff --git a/Makefile.target b/Makefile.target
index cbff562..ef2d25f 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -655,6 +655,7 @@ OBJS+= heathrow_pic.o grackle_pci.o ppc_oldworld.o
 OBJS+= unin_pci.o ppc_chrp.o
 # PowerPC 4xx boards
 OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
+OBJS+= ppc440.o
 ifdef FDT_LIBS
 OBJS+= device_tree.o
 LIBS+= $(FDT_LIBS)
diff --git a/hw/ppc440.c b/hw/ppc440.c
new file mode 100644
index 0000000..00d82e4
--- /dev/null
+++ b/hw/ppc440.c
@@ -0,0 +1,103 @@
+/*
+ * Qemu PowerPC 440 chip emulation
+ *
+ * Copyright 2007 IBM Corporation.
+ * Authors:
+ * 	Jerone Young <jyoung5@us.ibm.com>
+ * 	Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
+ * 	Hollis Blanchard <hollisb@us.ibm.com>
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+#include "hw.h"
+#include "isa.h"
+#include "ppc.h"
+#include "ppc4xx.h"
+#include "ppc440.h"
+#include "ppc405.h"
+#include "sysemu.h"
+#include "kvm.h"
+
+#define PPC440EP_PCI_CONFIG     0xeec00000
+#define PPC440EP_PCI_INTACK     0xeed00000
+#define PPC440EP_PCI_SPECIAL    0xeed00000
+#define PPC440EP_PCI_REGS       0xef400000
+#define PPC440EP_PCI_IO         0xe8000000
+#define PPC440EP_PCI_IOLEN      0x00010000
+
+#define PPC440EP_SDRAM_NR_BANKS 4
+
+static const unsigned int ppc440ep_sdram_bank_sizes[] = {
+    256<<20, 128<<20, 64<<20, 32<<20, 16<<20, 8<<20, 0
+};
+
+CPUState *ppc440ep_init(ram_addr_t *ram_size, PCIBus **pcip,
+                        const unsigned int pci_irq_nrs[4], int do_init)
+{
+    target_phys_addr_t ram_bases[PPC440EP_SDRAM_NR_BANKS];
+    target_phys_addr_t ram_sizes[PPC440EP_SDRAM_NR_BANKS];
+    CPUState *env;
+    ppc4xx_mmio_t *mmio;
+    qemu_irq *pic;
+    qemu_irq *irqs;
+    qemu_irq *pci_irqs;
+
+    env = cpu_ppc_init("440EP");
+    if (!env && kvm_enabled()) {
+        /* XXX Since qemu doesn't yet emulate 440, we just say it's a 405.
+         * Since KVM doesn't use qemu's CPU emulation it seems to be working
+         * OK. */
+        env = cpu_ppc_init("405");
+    }
+    if (!env) {
+        fprintf(stderr, "Unable to initialize CPU!\n");
+        exit(1);
+    }
+
+    ppc_dcr_init(env, NULL, NULL);
+
+    /* interrupt controller */
+    irqs = qemu_mallocz(sizeof(qemu_irq) * 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];
+    pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
+
+    /* SDRAM controller */
+    memset(ram_bases, 0, sizeof(ram_bases));
+    memset(ram_sizes, 0, sizeof(ram_sizes));
+    *ram_size = ppc4xx_sdram_adjust(*ram_size, PPC440EP_SDRAM_NR_BANKS,
+                                    ram_bases, ram_sizes,
+                                    ppc440ep_sdram_bank_sizes);
+    /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
+    ppc4xx_sdram_init(env, pic[14], PPC440EP_SDRAM_NR_BANKS, ram_bases,
+                      ram_sizes, do_init);
+
+    /* PCI */
+    pci_irqs = qemu_malloc(sizeof(qemu_irq) * 4);
+    pci_irqs[0] = pic[pci_irq_nrs[0]];
+    pci_irqs[1] = pic[pci_irq_nrs[1]];
+    pci_irqs[2] = pic[pci_irq_nrs[2]];
+    pci_irqs[3] = pic[pci_irq_nrs[3]];
+    *pcip = ppc4xx_pci_init(env, pci_irqs,
+                            PPC440EP_PCI_CONFIG,
+                            PPC440EP_PCI_INTACK,
+                            PPC440EP_PCI_SPECIAL,
+                            PPC440EP_PCI_REGS);
+    if (!*pcip)
+        printf("couldn't create PCI controller!\n");
+
+    isa_mmio_init(PPC440EP_PCI_IO, PPC440EP_PCI_IOLEN);
+
+    /* MMIO -- most "miscellaneous" devices live above 0xef600000. */
+    mmio = ppc4xx_mmio_init(env, 0xef600000);
+
+    if (serial_hds[0])
+        ppc405_serial_init(env, mmio, 0x300, pic[0], serial_hds[0]);
+
+    if (serial_hds[1])
+        ppc405_serial_init(env, mmio, 0x400, pic[1], serial_hds[1]);
+
+    return env;
+}
diff --git a/hw/ppc440.h b/hw/ppc440.h
new file mode 100644
index 0000000..b6843eb
--- /dev/null
+++ b/hw/ppc440.h
@@ -0,0 +1,20 @@
+/*
+ * Qemu PowerPC 440 board emualtion
+ *
+ * Copyright 2007 IBM Corporation.
+ * Authors: Jerone Young <jyoung5@us.ibm.com>
+ * 	    Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the GNU GPL licence version 2 or later
+ *
+ */
+
+#ifndef QEMU_PPC440_H
+#define QEMU_PPC440_H
+
+#include "hw.h"
+
+CPUState *ppc440ep_init(ram_addr_t *ram_size, PCIBus **pcip,
+                        const unsigned int pci_irq_nrs[4], int do_init);
+
+#endif
-- 
1.5.6.5

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

* [PATCH 7/8] PowerPC 440EP SoC emulation
@ 2008-12-15 16:44     ` Hollis Blanchard
  0 siblings, 0 replies; 31+ messages in thread
From: Hollis Blanchard @ 2008-12-15 16:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

Wire up the system-on-chip devices present on 440EP chips.

This patch is a little unusual in that qemu doesn't actually emulate the 440
core, but we use this board code with KVM (which does). If/when 440 core
emulation is supported, the kvm_enabled() hack can be removed.

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
---
 Makefile.target |    1 +
 hw/ppc440.c     |  103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/ppc440.h     |   20 +++++++++++
 3 files changed, 124 insertions(+), 0 deletions(-)
 create mode 100644 hw/ppc440.c
 create mode 100644 hw/ppc440.h

diff --git a/Makefile.target b/Makefile.target
index cbff562..ef2d25f 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -655,6 +655,7 @@ OBJS+= heathrow_pic.o grackle_pci.o ppc_oldworld.o
 OBJS+= unin_pci.o ppc_chrp.o
 # PowerPC 4xx boards
 OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
+OBJS+= ppc440.o
 ifdef FDT_LIBS
 OBJS+= device_tree.o
 LIBS+= $(FDT_LIBS)
diff --git a/hw/ppc440.c b/hw/ppc440.c
new file mode 100644
index 0000000..00d82e4
--- /dev/null
+++ b/hw/ppc440.c
@@ -0,0 +1,103 @@
+/*
+ * Qemu PowerPC 440 chip emulation
+ *
+ * Copyright 2007 IBM Corporation.
+ * Authors:
+ * 	Jerone Young <jyoung5@us.ibm.com>
+ * 	Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
+ * 	Hollis Blanchard <hollisb@us.ibm.com>
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+#include "hw.h"
+#include "isa.h"
+#include "ppc.h"
+#include "ppc4xx.h"
+#include "ppc440.h"
+#include "ppc405.h"
+#include "sysemu.h"
+#include "kvm.h"
+
+#define PPC440EP_PCI_CONFIG     0xeec00000
+#define PPC440EP_PCI_INTACK     0xeed00000
+#define PPC440EP_PCI_SPECIAL    0xeed00000
+#define PPC440EP_PCI_REGS       0xef400000
+#define PPC440EP_PCI_IO         0xe8000000
+#define PPC440EP_PCI_IOLEN      0x00010000
+
+#define PPC440EP_SDRAM_NR_BANKS 4
+
+static const unsigned int ppc440ep_sdram_bank_sizes[] = {
+    256<<20, 128<<20, 64<<20, 32<<20, 16<<20, 8<<20, 0
+};
+
+CPUState *ppc440ep_init(ram_addr_t *ram_size, PCIBus **pcip,
+                        const unsigned int pci_irq_nrs[4], int do_init)
+{
+    target_phys_addr_t ram_bases[PPC440EP_SDRAM_NR_BANKS];
+    target_phys_addr_t ram_sizes[PPC440EP_SDRAM_NR_BANKS];
+    CPUState *env;
+    ppc4xx_mmio_t *mmio;
+    qemu_irq *pic;
+    qemu_irq *irqs;
+    qemu_irq *pci_irqs;
+
+    env = cpu_ppc_init("440EP");
+    if (!env && kvm_enabled()) {
+        /* XXX Since qemu doesn't yet emulate 440, we just say it's a 405.
+         * Since KVM doesn't use qemu's CPU emulation it seems to be working
+         * OK. */
+        env = cpu_ppc_init("405");
+    }
+    if (!env) {
+        fprintf(stderr, "Unable to initialize CPU!\n");
+        exit(1);
+    }
+
+    ppc_dcr_init(env, NULL, NULL);
+
+    /* interrupt controller */
+    irqs = qemu_mallocz(sizeof(qemu_irq) * 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];
+    pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
+
+    /* SDRAM controller */
+    memset(ram_bases, 0, sizeof(ram_bases));
+    memset(ram_sizes, 0, sizeof(ram_sizes));
+    *ram_size = ppc4xx_sdram_adjust(*ram_size, PPC440EP_SDRAM_NR_BANKS,
+                                    ram_bases, ram_sizes,
+                                    ppc440ep_sdram_bank_sizes);
+    /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
+    ppc4xx_sdram_init(env, pic[14], PPC440EP_SDRAM_NR_BANKS, ram_bases,
+                      ram_sizes, do_init);
+
+    /* PCI */
+    pci_irqs = qemu_malloc(sizeof(qemu_irq) * 4);
+    pci_irqs[0] = pic[pci_irq_nrs[0]];
+    pci_irqs[1] = pic[pci_irq_nrs[1]];
+    pci_irqs[2] = pic[pci_irq_nrs[2]];
+    pci_irqs[3] = pic[pci_irq_nrs[3]];
+    *pcip = ppc4xx_pci_init(env, pci_irqs,
+                            PPC440EP_PCI_CONFIG,
+                            PPC440EP_PCI_INTACK,
+                            PPC440EP_PCI_SPECIAL,
+                            PPC440EP_PCI_REGS);
+    if (!*pcip)
+        printf("couldn't create PCI controller!\n");
+
+    isa_mmio_init(PPC440EP_PCI_IO, PPC440EP_PCI_IOLEN);
+
+    /* MMIO -- most "miscellaneous" devices live above 0xef600000. */
+    mmio = ppc4xx_mmio_init(env, 0xef600000);
+
+    if (serial_hds[0])
+        ppc405_serial_init(env, mmio, 0x300, pic[0], serial_hds[0]);
+
+    if (serial_hds[1])
+        ppc405_serial_init(env, mmio, 0x400, pic[1], serial_hds[1]);
+
+    return env;
+}
diff --git a/hw/ppc440.h b/hw/ppc440.h
new file mode 100644
index 0000000..b6843eb
--- /dev/null
+++ b/hw/ppc440.h
@@ -0,0 +1,20 @@
+/*
+ * Qemu PowerPC 440 board emualtion
+ *
+ * Copyright 2007 IBM Corporation.
+ * Authors: Jerone Young <jyoung5@us.ibm.com>
+ * 	    Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the GNU GPL licence version 2 or later
+ *
+ */
+
+#ifndef QEMU_PPC440_H
+#define QEMU_PPC440_H
+
+#include "hw.h"
+
+CPUState *ppc440ep_init(ram_addr_t *ram_size, PCIBus **pcip,
+                        const unsigned int pci_irq_nrs[4], int do_init);
+
+#endif
-- 
1.5.6.5


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

* [Qemu-devel] [PATCH 8/8] IBM PowerPC 440EP Bamboo reference board emulation
  2008-12-15 16:44 ` Hollis Blanchard
@ 2008-12-15 16:44     ` Hollis Blanchard
  -1 siblings, 0 replies; 31+ messages in thread
From: Hollis Blanchard @ 2008-12-15 16:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

Since most IO devices are integrated into the 440EP chip, "Bamboo support"
mostly entails implementing the -kernel, -initrd, and -append options.

These options are implemented by loading the guest as if u-boot had done it,
i.e. loading a flat device tree, updating it to hold initrd addresses, ram
size, and command line, and passing the FDT address in r3.

Since we use it with KVM, we enable the virtio block driver and include hooks
necessary for KVM support.

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
---
 Makefile             |    2 +-
 Makefile.target      |    2 +-
 hw/boards.h          |    1 +
 hw/ppc440_bamboo.c   |  190 ++++++++++++++++++++++++++++++++++++++++
 pc-bios/bamboo.dtb   |  Bin 0 -> 3163 bytes
 pc-bios/bamboo.dts   |  234 ++++++++++++++++++++++++++++++++++++++++++++++++++
 target-ppc/machine.c |    1 +
 7 files changed, 428 insertions(+), 2 deletions(-)
 create mode 100644 hw/ppc440_bamboo.c
 create mode 100644 pc-bios/bamboo.dtb
 create mode 100644 pc-bios/bamboo.dts

diff --git a/Makefile b/Makefile
index 01f0121..85523d7 100644
--- a/Makefile
+++ b/Makefile
@@ -222,7 +222,7 @@ common  de-ch  es     fo  fr-ca  hu     ja  mk  nl-be      pt  sl     tr
 ifdef INSTALL_BLOBS
 BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
 video.x openbios-sparc32 openbios-sparc64 pxe-ne2k_pci.bin \
-pxe-rtl8139.bin pxe-pcnet.bin pxe-e1000.bin
+pxe-rtl8139.bin pxe-pcnet.bin pxe-e1000.bin bamboo.dtb
 else
 BLOBS=
 endif
diff --git a/Makefile.target b/Makefile.target
index ef2d25f..c4d0f05 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -655,7 +655,7 @@ OBJS+= heathrow_pic.o grackle_pci.o ppc_oldworld.o
 OBJS+= unin_pci.o ppc_chrp.o
 # PowerPC 4xx boards
 OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
-OBJS+= ppc440.o
+OBJS+= ppc440.o ppc440_bamboo.o
 ifdef FDT_LIBS
 OBJS+= device_tree.o
 LIBS+= $(FDT_LIBS)
diff --git a/hw/boards.h b/hw/boards.h
index a7b8126..bff1cf0 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -38,6 +38,7 @@ extern QEMUMachine core99_machine;
 extern QEMUMachine heathrow_machine;
 extern QEMUMachine ref405ep_machine;
 extern QEMUMachine taihu_machine;
+extern QEMUMachine bamboo_machine;
 
 /* mips_r4k.c */
 extern QEMUMachine mips_machine;
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
new file mode 100644
index 0000000..0a3b6e4
--- /dev/null
+++ b/hw/ppc440_bamboo.c
@@ -0,0 +1,190 @@
+/*
+ * Qemu PowerPC 440 board emulation
+ *
+ * Copyright 2007 IBM Corporation.
+ * Authors:
+ * 	Jerone Young <jyoung5@us.ibm.com>
+ * 	Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
+ * 	Hollis Blanchard <hollisb@us.ibm.com>
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+#include "config.h"
+#include "qemu-common.h"
+#include "net.h"
+#include "hw.h"
+#include "pci.h"
+#include "virtio-blk.h"
+#include "boards.h"
+#include "sysemu.h"
+#include "ppc440.h"
+#include "kvm.h"
+#include "kvm_ppc.h"
+#include "device_tree.h"
+
+#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
+
+static void *bamboo_load_device_tree(void *addr,
+                                     uint32_t ramsize,
+                                     target_phys_addr_t initrd_base,
+                                     target_phys_addr_t initrd_size,
+                                     const char *kernel_cmdline)
+{
+    void *fdt = NULL;
+#ifdef HAVE_FDT
+    uint32_t mem_reg_property[] = { 0, 0, ramsize };
+    char *path;
+    int pathlen;
+    int ret;
+
+    pathlen = snprintf(NULL, 0, "%s/%s", bios_dir, BINARY_DEVICE_TREE_FILE) + 1;
+    path = qemu_malloc(pathlen);
+    if (path == NULL)
+        return NULL;
+
+    snprintf(path, pathlen, "%s/%s", bios_dir, BINARY_DEVICE_TREE_FILE);
+
+    fdt = load_device_tree(path, addr);
+    free(path);
+    if (fdt == NULL)
+        goto out;
+
+    /* Manipulate device tree in memory. */
+
+    ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
+                               sizeof(mem_reg_property));
+    if (ret < 0)
+        fprintf(stderr, "couldn't set /memory/reg\n");
+
+    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
+                                    initrd_base);
+    if (ret < 0)
+        fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
+
+    ret = qemu_devtree_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_devtree_setprop_string(fdt, "/chosen", "bootargs",
+                                      kernel_cmdline);
+    if (ret < 0)
+        fprintf(stderr, "couldn't set /chosen/bootargs\n");
+
+    if (kvm_enabled())
+        kvmppc_fdt_update(fdt);
+
+out:
+#endif
+
+    return fdt;
+}
+
+static void bamboo_init(ram_addr_t ram_size, int vga_ram_size,
+                        const char *boot_device, DisplayState *ds,
+                        const char *kernel_filename,
+                        const char *kernel_cmdline,
+                        const char *initrd_filename,
+                        const char *cpu_model)
+{
+    unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
+    NICInfo *nd;
+    PCIBus *pcibus;
+    CPUState *env;
+    uint64_t elf_entry;
+    uint64_t elf_lowaddr;
+    target_ulong entry = 0;
+    target_ulong loadaddr = 0;
+    target_long kernel_size = 0;
+    target_ulong initrd_base = 0;
+    target_long initrd_size = 0;
+    target_ulong dt_base = 0;
+    void *fdt;
+    int i;
+
+    /* Setup CPU. */
+    env = ppc440ep_init(&ram_size, &pcibus, pci_irq_nrs, 1);
+
+    if (pcibus) {
+        int unit_id = 0;
+
+        /* Add virtio block devices. */
+        while ((i = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
+            virtio_blk_init(pcibus, drives_table[i].bdrv);
+            unit_id++;
+        }
+
+        /* Register network interfaces. */
+        for (i = 0; i < nb_nics; i++) {
+            nd = &nd_table[i];
+            if (!nd->model) {
+                /* There are no PCI NICs on the Bamboo board, but there are
+                 * PCI slots, so we can pick model whatever we want. */
+                nd->model = "e1000";
+            }
+            pci_nic_init(pcibus, nd, -1);
+        }
+    }
+
+    /* Load kernel. */
+    if (kernel_filename) {
+        kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
+        if (kernel_size < 0) {
+            kernel_size = load_elf(kernel_filename, 0, &elf_entry, &elf_lowaddr,
+                                   NULL);
+            entry = elf_entry;
+            loadaddr = elf_lowaddr;
+        }
+        /* XXX try again as binary */
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+    }
+
+    /* Load initrd. */
+    if (initrd_filename) {
+        initrd_base = kernel_size + loadaddr;
+        initrd_size = load_image(initrd_filename, phys_ram_base + initrd_base);
+
+        if (initrd_size < 0) {
+            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                    initrd_filename);
+            exit(1);
+        }
+    }
+
+    /* If we're loading a kernel directly, we must load the device tree too. */
+    if (kernel_filename) {
+        if (initrd_base)
+            dt_base = initrd_base + initrd_size;
+        else
+            dt_base = kernel_size + loadaddr;
+
+        fdt = bamboo_load_device_tree(phys_ram_base + dt_base, ram_size,
+                                      initrd_base, initrd_size, kernel_cmdline);
+        if (fdt == NULL) {
+            fprintf(stderr, "couldn't load device tree\n");
+            exit(1);
+        }
+
+        /* Set initial guest state. */
+        env->gpr[1] = (16<<20) - 8;
+        env->gpr[3] = dt_base;
+        env->nip = entry;
+        /* XXX we currently depend on KVM to create some initial TLB entries. */
+    }
+
+    if (kvm_enabled())
+        kvmppc_init();
+}
+
+QEMUMachine bamboo_machine = {
+    .name = "bamboo",
+    .desc = "bamboo",
+    .init = bamboo_init,
+    .ram_require = 8<<20 | RAMSIZE_FIXED,
+};
diff --git a/pc-bios/bamboo.dtb b/pc-bios/bamboo.dtb
new file mode 100644
index 0000000000000000000000000000000000000000..81f971c64745aaf79152e1ed6f09e5d36137e461
GIT binary patch
literal 3163
zcmcImL5mzk6s|Ug7)f*!MATKBWg~i+W+!nr$w>!A=Hg)?!X8Alr@D5hN%wTy-Lvj4
z2qRv-_y<JrBKikB$>K%ul&il$FUf)@1qpuN>#Clb*$IMRL3O?Fy;rZk_o}+9?_GX)
zU#Uy)E2VBL_2ds2UqiowzV`6`kEcon-#|YDUT%R^oWuCIl^?_C@Y9g#LwpH+J<7E1
zj-qUo=YXw#V}+jay6BuAL}?OLrh?eUz6IG|>rHE;F3`nPoIQVtEf>ZnH#YhXdX4OO
z522%m_$l=Do%|D1?!4XY_j~W`&@$(7r-3c6-IsqkPZt+!Klt=;;NfG)9S?u8guha1
z230%%dk<63{bB42=s!=QIyo?q=KjAzX3ba!sYPb8ygUM$&l@i3xHm2jbx~ZKxyht9
zWjQVCQ0J4n%+u7AUag*m>qauly3<65sEsL<MNJIyWcv->)#Go`H24WnWgaK!T-NzO
zl;*J8D~khSfA5(y_f+z&;*yi;%e@nR&{=*oiOsD|pSD)II6D`*N6ls3+POtKa<N~5
zAnQWs)y1Oyrb<A4PC#>cQf54dnWuYyD0c90w%rSVeD)r2fZU=C0vc@{beD6Kd8><G
z*zav)eKh*I8mvKX^N6#^*<XYpv7qxJS#%~2sj64e87s((wjS4jB@T369E)r{Jb&&b
zo6DWpuSLh!f<Dq_c(Sw2Y{%eoBqyFT#%b$!?ytdjz=0WQ45Gh=QFub<@wCYD^!#1@
zu410QZ;a<-pF271+O>Ut=b>l5QoG8ONt6!E-pyX`^`5+O^koji#s;a)Pi;)9>o>Qz
zTR-qpcTPXz6z;LhIk;hUGzbs%?Fq!z{)P&E^6|R>u4c@Yb!2loj(qpX`3&#=f9B1w
z%e+PRXx^ML&tnyD)^?dU;|cHNhHi>|t06s)rG~HpE}oBM;d^J1Js&{M-|hpqO+8~{
zfJ3l~A9;}9BA?s;2OrY<S3d525k4l1ba<R4NmHfRvSR&swudx@a#`#}dVU}AyvX|`
z_W1?jpsg4oJewNZnq4Md{Jv_eu6xpGMC1Cb*|5+Oz+$-{mcJd$!}&uLnfN7i;mGeX
zudtB8c#ZLMZ3A0>48aFh=F28`=7SSR&3RQ1?ukrJ3-ake^n7wn{AUFn5@P#Wp7XH-
zO!9vF-GRoy82B~^<}IgR8fOir-x~Z1rT$#<5FXG6pIhp_o&5Rj$6jFiVxw&x9k%Bd
zEzMrM(AYYwY|l3~IpcD!^f<4~L|n-g_TbAc)O`z=!Pbh8AbdEF{o-a6$EB&NP@6QZ
z)Mk|&8!KmdY*MB3tib=#C^ah9WmrU|nbfL@+Oy+z6`O-Zn-A-w!l=^hE1l;0Zn#&P
zkEdp$k5rvxW`v(lPnCo^(qj{*$;5<QR>fyD&S$~g0C1WAO$oI~YbKJJdYs1!VW)@P
zVjN9kP+#>6rkFC`x7ZxYeDdD(9Hk&-G}*^5bE~e@K~mP!C=DgeX~}YgRbfm#cXCxK
i$|Q^M*T}1WIZ&8I1$uSYn+BETUDa_utr4dltA7BYxVh&5

literal 0
HcmV?d00001

diff --git a/pc-bios/bamboo.dts b/pc-bios/bamboo.dts
new file mode 100644
index 0000000..655442c
--- /dev/null
+++ b/pc-bios/bamboo.dts
@@ -0,0 +1,234 @@
+/*
+ * Device Tree Source for AMCC Bamboo
+ *
+ * Copyright (c) 2006, 2007 IBM Corp.
+ * Josh Boyer <jwboyer@linux.vnet.ibm.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without
+ * any warranty of any kind, whether express or implied.
+ */
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	model = "amcc,bamboo";
+	compatible = "amcc,bamboo";
+	dcr-parent = <&/cpus/cpu@0>;
+
+	aliases {
+		serial0 = &UART0;
+		serial1 = &UART1;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			model = "PowerPC,440EP";
+			reg = <0>;
+			clock-frequency = <1fca0550>;
+			timebase-frequency = <017d7840>;
+			i-cache-line-size = <20>;
+			d-cache-line-size = <20>;
+			i-cache-size = <8000>;
+			d-cache-size = <8000>;
+			dcr-controller;
+			dcr-access-method = "native";
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0 9000000>;
+	};
+
+	UIC0: interrupt-controller0 {
+		compatible = "ibm,uic-440ep","ibm,uic";
+		interrupt-controller;
+		cell-index = <0>;
+		dcr-reg = <0c0 009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+	};
+/*
+	UIC1: interrupt-controller1 {
+		compatible = "ibm,uic-440ep","ibm,uic";
+		interrupt-controller;
+		cell-index = <1>;
+		dcr-reg = <0d0 009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+		interrupts = <1e 4 1f 4>;
+		interrupt-parent = <&UIC0>;
+	};
+*/
+
+	SDR0: sdr {
+		compatible = "ibm,sdr-440ep";
+		dcr-reg = <00e 002>;
+	};
+
+	CPR0: cpr {
+		compatible = "ibm,cpr-440ep";
+		dcr-reg = <00c 002>;
+	};
+
+	plb {
+		compatible = "ibm,plb-440ep", "ibm,plb-440gp", "ibm,plb4";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges;
+		clock-frequency = <07f28154>;
+
+		SDRAM0: sdram {
+			compatible = "ibm,sdram-440ep", "ibm,sdram-405gp";
+			dcr-reg = <010 2>;
+		};
+
+		DMA0: dma {
+			compatible = "ibm,dma-440ep", "ibm,dma-440gp";
+			dcr-reg = <100 027>;
+		};
+
+		POB0: opb {
+			compatible = "ibm,opb-440ep", "ibm,opb-440gp", "ibm,opb";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			/* Bamboo is oddball in the 44x world and doesn't use the ERPN
+			 * bits.
+			 */
+			ranges = <00000000 0 00000000 80000000
+			          80000000 0 80000000 80000000>;
+			/* interrupt-parent = <&UIC1>; */
+			interrupts = <7 4>;
+			clock-frequency = <03f940aa>;
+
+			EBC0: ebc {
+				compatible = "ibm,ebc-440ep", "ibm,ebc-440gp", "ibm,ebc";
+				dcr-reg = <012 2>;
+				#address-cells = <2>;
+				#size-cells = <1>;
+				clock-frequency = <03f940aa>;
+				interrupts = <5 1>;
+			/* interrupt-parent = <&UIC1>; */
+			};
+
+			UART0: serial@ef600300 {
+				device_type = "serial";
+				compatible = "ns16550";
+				reg = <ef600300 8>;
+				virtual-reg = <ef600300>;
+				clock-frequency = <00a8c000>;
+				current-speed = <1c200>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <0 4>;
+			};
+
+			UART1: serial@ef600400 {
+				device_type = "serial";
+				compatible = "ns16550";
+				reg = <ef600400 8>;
+				virtual-reg = <ef600400>;
+				clock-frequency = <00a8c000>;
+				current-speed = <0>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <1 4>;
+			};
+/*
+			UART2: serial@ef600500 {
+				device_type = "serial";
+				compatible = "ns16550";
+				reg = <ef600500 8>;
+				virtual-reg = <ef600500>;
+				clock-frequency = <0>;
+				current-speed = <0>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <3 4>;
+			};
+
+			UART3: serial@ef600600 {
+				device_type = "serial";
+				compatible = "ns16550";
+				reg = <ef600600 8>;
+				virtual-reg = <ef600600>;
+				clock-frequency = <0>;
+				current-speed = <0>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <4 4>;
+			};
+
+*/
+			IIC0: i2c@ef600700 {
+				device_type = "i2c";
+				compatible = "ibm,iic-440ep", "ibm,iic-440gp", "ibm,iic";
+				reg = <ef600700 14>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <2 4>;
+			};
+
+			IIC1: i2c@ef600800 {
+				device_type = "i2c";
+				compatible = "ibm,iic-440ep", "ibm,iic-440gp", "ibm,iic";
+				reg = <ef600800 14>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <7 4>;
+			};
+
+			ZMII0: emac-zmii@ef600d00 {
+				device_type = "zmii-interface";
+				compatible = "ibm,zmii-440ep", "ibm,zmii-440gp", "ibm,zmii";
+				reg = <ef600d00 c>;
+			};
+
+		};
+
+		PCI0: pci@ec000000 {
+			device_type = "pci";
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			compatible = "ibm,plb440ep-pci", "ibm,plb-pci";
+			primary;
+			reg = <0 eec00000 8     /* Config space access */
+			       0 eed00000 4     /* IACK */
+			       0 eed00000 4     /* Special cycle */
+			       0 ef400000 40>;  /* Internal registers */
+
+			/* Outbound ranges, one memory and one IO,
+			 * later cannot be changed. Chip supports a second
+			 * IO range but we don't use it for now
+			 */
+			ranges = <02000000 0 a0000000 0 a0000000 0 20000000
+				  01000000 0 00000000 0 e8000000 0 00010000>;
+
+			/* Inbound 2GB range starting at 0 */
+			dma-ranges = <42000000 0 0 0 0 0 80000000>;
+
+			/* Bamboo has all 4 IRQ pins tied together per slot */
+			interrupt-map-mask = <f800 0 0 0>;
+			interrupt-map = <
+				/* IDSEL 1 */
+				0800 0 0 0 &UIC0 1c 8
+
+				/* IDSEL 2 */
+				1000 0 0 0 &UIC0 1b 8
+
+				/* IDSEL 3 */
+				1800 0 0 0 &UIC0 1a 8
+
+				/* IDSEL 4 */
+				2000 0 0 0 &UIC0 19 8
+			>;
+		};
+
+	};
+
+	chosen {
+		linux,stdout-path = "/plb/opb/serial@ef600300";
+	};
+};
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index be0cbe1..ea2257b 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -8,6 +8,7 @@ void register_machines(void)
     qemu_register_machine(&prep_machine);
     qemu_register_machine(&ref405ep_machine);
     qemu_register_machine(&taihu_machine);
+    qemu_register_machine(&bamboo_machine);
 }
 
 void cpu_save(QEMUFile *f, void *opaque)
-- 
1.5.6.5

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

* [PATCH 8/8] IBM PowerPC 440EP Bamboo reference board emulation
@ 2008-12-15 16:44     ` Hollis Blanchard
  0 siblings, 0 replies; 31+ messages in thread
From: Hollis Blanchard @ 2008-12-15 16:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

Since most IO devices are integrated into the 440EP chip, "Bamboo support"
mostly entails implementing the -kernel, -initrd, and -append options.

These options are implemented by loading the guest as if u-boot had done it,
i.e. loading a flat device tree, updating it to hold initrd addresses, ram
size, and command line, and passing the FDT address in r3.

Since we use it with KVM, we enable the virtio block driver and include hooks
necessary for KVM support.

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
---
 Makefile             |    2 +-
 Makefile.target      |    2 +-
 hw/boards.h          |    1 +
 hw/ppc440_bamboo.c   |  190 ++++++++++++++++++++++++++++++++++++++++
 pc-bios/bamboo.dtb   |  Bin 0 -> 3163 bytes
 pc-bios/bamboo.dts   |  234 ++++++++++++++++++++++++++++++++++++++++++++++++++
 target-ppc/machine.c |    1 +
 7 files changed, 428 insertions(+), 2 deletions(-)
 create mode 100644 hw/ppc440_bamboo.c
 create mode 100644 pc-bios/bamboo.dtb
 create mode 100644 pc-bios/bamboo.dts

diff --git a/Makefile b/Makefile
index 01f0121..85523d7 100644
--- a/Makefile
+++ b/Makefile
@@ -222,7 +222,7 @@ common  de-ch  es     fo  fr-ca  hu     ja  mk  nl-be      pt  sl     tr
 ifdef INSTALL_BLOBS
 BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
 video.x openbios-sparc32 openbios-sparc64 pxe-ne2k_pci.bin \
-pxe-rtl8139.bin pxe-pcnet.bin pxe-e1000.bin
+pxe-rtl8139.bin pxe-pcnet.bin pxe-e1000.bin bamboo.dtb
 else
 BLOBS endif
diff --git a/Makefile.target b/Makefile.target
index ef2d25f..c4d0f05 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -655,7 +655,7 @@ OBJS+= heathrow_pic.o grackle_pci.o ppc_oldworld.o
 OBJS+= unin_pci.o ppc_chrp.o
 # PowerPC 4xx boards
 OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
-OBJS+= ppc440.o
+OBJS+= ppc440.o ppc440_bamboo.o
 ifdef FDT_LIBS
 OBJS+= device_tree.o
 LIBS+= $(FDT_LIBS)
diff --git a/hw/boards.h b/hw/boards.h
index a7b8126..bff1cf0 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -38,6 +38,7 @@ extern QEMUMachine core99_machine;
 extern QEMUMachine heathrow_machine;
 extern QEMUMachine ref405ep_machine;
 extern QEMUMachine taihu_machine;
+extern QEMUMachine bamboo_machine;
 
 /* mips_r4k.c */
 extern QEMUMachine mips_machine;
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
new file mode 100644
index 0000000..0a3b6e4
--- /dev/null
+++ b/hw/ppc440_bamboo.c
@@ -0,0 +1,190 @@
+/*
+ * Qemu PowerPC 440 board emulation
+ *
+ * Copyright 2007 IBM Corporation.
+ * Authors:
+ * 	Jerone Young <jyoung5@us.ibm.com>
+ * 	Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
+ * 	Hollis Blanchard <hollisb@us.ibm.com>
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+#include "config.h"
+#include "qemu-common.h"
+#include "net.h"
+#include "hw.h"
+#include "pci.h"
+#include "virtio-blk.h"
+#include "boards.h"
+#include "sysemu.h"
+#include "ppc440.h"
+#include "kvm.h"
+#include "kvm_ppc.h"
+#include "device_tree.h"
+
+#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
+
+static void *bamboo_load_device_tree(void *addr,
+                                     uint32_t ramsize,
+                                     target_phys_addr_t initrd_base,
+                                     target_phys_addr_t initrd_size,
+                                     const char *kernel_cmdline)
+{
+    void *fdt = NULL;
+#ifdef HAVE_FDT
+    uint32_t mem_reg_property[] = { 0, 0, ramsize };
+    char *path;
+    int pathlen;
+    int ret;
+
+    pathlen = snprintf(NULL, 0, "%s/%s", bios_dir, BINARY_DEVICE_TREE_FILE) + 1;
+    path = qemu_malloc(pathlen);
+    if (path = NULL)
+        return NULL;
+
+    snprintf(path, pathlen, "%s/%s", bios_dir, BINARY_DEVICE_TREE_FILE);
+
+    fdt = load_device_tree(path, addr);
+    free(path);
+    if (fdt = NULL)
+        goto out;
+
+    /* Manipulate device tree in memory. */
+
+    ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
+                               sizeof(mem_reg_property));
+    if (ret < 0)
+        fprintf(stderr, "couldn't set /memory/reg\n");
+
+    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
+                                    initrd_base);
+    if (ret < 0)
+        fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
+
+    ret = qemu_devtree_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_devtree_setprop_string(fdt, "/chosen", "bootargs",
+                                      kernel_cmdline);
+    if (ret < 0)
+        fprintf(stderr, "couldn't set /chosen/bootargs\n");
+
+    if (kvm_enabled())
+        kvmppc_fdt_update(fdt);
+
+out:
+#endif
+
+    return fdt;
+}
+
+static void bamboo_init(ram_addr_t ram_size, int vga_ram_size,
+                        const char *boot_device, DisplayState *ds,
+                        const char *kernel_filename,
+                        const char *kernel_cmdline,
+                        const char *initrd_filename,
+                        const char *cpu_model)
+{
+    unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
+    NICInfo *nd;
+    PCIBus *pcibus;
+    CPUState *env;
+    uint64_t elf_entry;
+    uint64_t elf_lowaddr;
+    target_ulong entry = 0;
+    target_ulong loadaddr = 0;
+    target_long kernel_size = 0;
+    target_ulong initrd_base = 0;
+    target_long initrd_size = 0;
+    target_ulong dt_base = 0;
+    void *fdt;
+    int i;
+
+    /* Setup CPU. */
+    env = ppc440ep_init(&ram_size, &pcibus, pci_irq_nrs, 1);
+
+    if (pcibus) {
+        int unit_id = 0;
+
+        /* Add virtio block devices. */
+        while ((i = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
+            virtio_blk_init(pcibus, drives_table[i].bdrv);
+            unit_id++;
+        }
+
+        /* Register network interfaces. */
+        for (i = 0; i < nb_nics; i++) {
+            nd = &nd_table[i];
+            if (!nd->model) {
+                /* There are no PCI NICs on the Bamboo board, but there are
+                 * PCI slots, so we can pick model whatever we want. */
+                nd->model = "e1000";
+            }
+            pci_nic_init(pcibus, nd, -1);
+        }
+    }
+
+    /* Load kernel. */
+    if (kernel_filename) {
+        kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
+        if (kernel_size < 0) {
+            kernel_size = load_elf(kernel_filename, 0, &elf_entry, &elf_lowaddr,
+                                   NULL);
+            entry = elf_entry;
+            loadaddr = elf_lowaddr;
+        }
+        /* XXX try again as binary */
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+    }
+
+    /* Load initrd. */
+    if (initrd_filename) {
+        initrd_base = kernel_size + loadaddr;
+        initrd_size = load_image(initrd_filename, phys_ram_base + initrd_base);
+
+        if (initrd_size < 0) {
+            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                    initrd_filename);
+            exit(1);
+        }
+    }
+
+    /* If we're loading a kernel directly, we must load the device tree too. */
+    if (kernel_filename) {
+        if (initrd_base)
+            dt_base = initrd_base + initrd_size;
+        else
+            dt_base = kernel_size + loadaddr;
+
+        fdt = bamboo_load_device_tree(phys_ram_base + dt_base, ram_size,
+                                      initrd_base, initrd_size, kernel_cmdline);
+        if (fdt = NULL) {
+            fprintf(stderr, "couldn't load device tree\n");
+            exit(1);
+        }
+
+        /* Set initial guest state. */
+        env->gpr[1] = (16<<20) - 8;
+        env->gpr[3] = dt_base;
+        env->nip = entry;
+        /* XXX we currently depend on KVM to create some initial TLB entries. */
+    }
+
+    if (kvm_enabled())
+        kvmppc_init();
+}
+
+QEMUMachine bamboo_machine = {
+    .name = "bamboo",
+    .desc = "bamboo",
+    .init = bamboo_init,
+    .ram_require = 8<<20 | RAMSIZE_FIXED,
+};
diff --git a/pc-bios/bamboo.dtb b/pc-bios/bamboo.dtb
new file mode 100644
index 0000000000000000000000000000000000000000..81f971c64745aaf79152e1ed6f09e5d36137e461
GIT binary patch
literal 3163
zcmcImL5mzk6s|Ug7)f*!MATKBWg~i+W+!nr$w>!A=Hg)?!X8Alr@D5hN%wTy-Lvj4
z2qRv-_y<JrBKikB$>K%ul&il$FUf)@1qpuN>#Clb*$IMRL3O?Fy;rZk_o}+9?_GX)
zU#Uy)E2VBL_2ds2UqiowzV`6`kEcon-#|YDUT%R^oWuCIl^?_C@Y9g#LwpH+J<7E1
zj-qUo=YXw#V}+jay6BuAL}?OLrh?eUz6IG|>rHE;F3`nPoIQVtEf>ZnH#YhXdX4OO
z522%m_$l=Do%|D1?!4XY_j~W`&@$(7r-3c6-IsqkPZt+!Klt=;;NfG)9S?u8guha1
z230%%dk<63{bB42=s!=QIyo?q=KjAzX3ba!sYPb8ygUM$&l@i3xHm2jbx~ZKxyht9
zWjQVCQ0J4n%+u7AUag*m>qauly3<65sEsL<MNJIyWcv->)#Go`H24WnWgaK!T-NzO
zl;*J8D~khSfA5(y_f+z&;*yi;%e@nR&{=*oiOsD|pSD)II6D`*N6ls3+POtKa<N~5
zAnQWs)y1Oyrb<A4PC#>cQf54dnWuYyD0c90w%rSVeD)r2fZUÀvc@{beD6Kd8><G
z*zav)eKh*I8mvKX^N6#^*<XYpv7qxJS#%~2sj64e87s((wjS4jB@T369E)r{Jb&&b
zo6DWpuSLh!f<Dq_c(Sw2Y{%eoBqyFT#%b$!?ytdjz=0WQ45Gh=QFub<@wCYD^!#1@
zu410QZ;a<-pF271+O>Ut=b>l5QoG8ONt6!E-pyX`^`5+O^koji#s;a)Pi;)9>o>Qz
zTR-qpcTPXz6z;LhIk;hUGzbs%?Fq!z{)P&E^6|R>u4c@Yb!2loj(qpX`3&#ùB1w
z%e+PRXx^ML&tnyD)^?dU;|cHNhHi>|t06s)rG~HpE}oBM;d^J1Js&{M-|hpqO+8~{
zfJ3l~A9;}9BA?s;2OrY<S3d525k4l1ba<R4NmHfRvSR&swudx@a#`#}dVU}AyvX|`
z_W1?jpsg4oJewNZnq4Md{Jv_eu6xpGMC1Cb*|5+Oz+$-{mcJd$!}&uLnfN7i;mGeX
zudtB8c#ZLMZ3A0>48aFhò8`=7SSR&3RQ1?ukrJ3-ake^n7wn{AUFn5@P#Wp7XH-
zO!9vF-GRoy82B~^<}IgR8fOir-x~Z1rT$#<5FXG6pIhp_o&5Rj$6jFiVxw&x9k%Bd
zEzMrM(AYYwY|l3~IpcD!^f<4~L|n-g_TbAc)O`z=!Pbh8AbdEF{o-a6$EB&NP@6QZ
z)Mk|&8!KmdY*MB3tib=#C^ah9WmrU|nbfL@+Oy+z6`O-Zn-A-w!l=^hE1l;0Zn#&P
zkEdp$k5rvxW`v(lPnCo^(qj{*$;5<QR>fyD&S$~g0C1WAO$oI~YbKJJdYs1!VW)@P
zVjN9kP+#>6rkFC`x7ZxYeDdD(9Hk&-G}*^5bE~e@K~mP!C=DgeX~}YgRbfm#cXCxK
i$|Q^M*T}1WIZ&8I1$uSYn+BETUDa_utr4dltA7BYxVh&5

literal 0
HcmV?d00001

diff --git a/pc-bios/bamboo.dts b/pc-bios/bamboo.dts
new file mode 100644
index 0000000..655442c
--- /dev/null
+++ b/pc-bios/bamboo.dts
@@ -0,0 +1,234 @@
+/*
+ * Device Tree Source for AMCC Bamboo
+ *
+ * Copyright (c) 2006, 2007 IBM Corp.
+ * Josh Boyer <jwboyer@linux.vnet.ibm.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without
+ * any warranty of any kind, whether express or implied.
+ */
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	model = "amcc,bamboo";
+	compatible = "amcc,bamboo";
+	dcr-parent = <&/cpus/cpu@0>;
+
+	aliases {
+		serial0 = &UART0;
+		serial1 = &UART1;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			model = "PowerPC,440EP";
+			reg = <0>;
+			clock-frequency = <1fca0550>;
+			timebase-frequency = <017d7840>;
+			i-cache-line-size = <20>;
+			d-cache-line-size = <20>;
+			i-cache-size = <8000>;
+			d-cache-size = <8000>;
+			dcr-controller;
+			dcr-access-method = "native";
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0 9000000>;
+	};
+
+	UIC0: interrupt-controller0 {
+		compatible = "ibm,uic-440ep","ibm,uic";
+		interrupt-controller;
+		cell-index = <0>;
+		dcr-reg = <0c0 009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+	};
+/*
+	UIC1: interrupt-controller1 {
+		compatible = "ibm,uic-440ep","ibm,uic";
+		interrupt-controller;
+		cell-index = <1>;
+		dcr-reg = <0d0 009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+		interrupts = <1e 4 1f 4>;
+		interrupt-parent = <&UIC0>;
+	};
+*/
+
+	SDR0: sdr {
+		compatible = "ibm,sdr-440ep";
+		dcr-reg = <00e 002>;
+	};
+
+	CPR0: cpr {
+		compatible = "ibm,cpr-440ep";
+		dcr-reg = <00c 002>;
+	};
+
+	plb {
+		compatible = "ibm,plb-440ep", "ibm,plb-440gp", "ibm,plb4";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges;
+		clock-frequency = <07f28154>;
+
+		SDRAM0: sdram {
+			compatible = "ibm,sdram-440ep", "ibm,sdram-405gp";
+			dcr-reg = <010 2>;
+		};
+
+		DMA0: dma {
+			compatible = "ibm,dma-440ep", "ibm,dma-440gp";
+			dcr-reg = <100 027>;
+		};
+
+		POB0: opb {
+			compatible = "ibm,opb-440ep", "ibm,opb-440gp", "ibm,opb";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			/* Bamboo is oddball in the 44x world and doesn't use the ERPN
+			 * bits.
+			 */
+			ranges = <00000000 0 00000000 80000000
+			          80000000 0 80000000 80000000>;
+			/* interrupt-parent = <&UIC1>; */
+			interrupts = <7 4>;
+			clock-frequency = <03f940aa>;
+
+			EBC0: ebc {
+				compatible = "ibm,ebc-440ep", "ibm,ebc-440gp", "ibm,ebc";
+				dcr-reg = <012 2>;
+				#address-cells = <2>;
+				#size-cells = <1>;
+				clock-frequency = <03f940aa>;
+				interrupts = <5 1>;
+			/* interrupt-parent = <&UIC1>; */
+			};
+
+			UART0: serial@ef600300 {
+				device_type = "serial";
+				compatible = "ns16550";
+				reg = <ef600300 8>;
+				virtual-reg = <ef600300>;
+				clock-frequency = <00a8c000>;
+				current-speed = <1c200>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <0 4>;
+			};
+
+			UART1: serial@ef600400 {
+				device_type = "serial";
+				compatible = "ns16550";
+				reg = <ef600400 8>;
+				virtual-reg = <ef600400>;
+				clock-frequency = <00a8c000>;
+				current-speed = <0>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <1 4>;
+			};
+/*
+			UART2: serial@ef600500 {
+				device_type = "serial";
+				compatible = "ns16550";
+				reg = <ef600500 8>;
+				virtual-reg = <ef600500>;
+				clock-frequency = <0>;
+				current-speed = <0>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <3 4>;
+			};
+
+			UART3: serial@ef600600 {
+				device_type = "serial";
+				compatible = "ns16550";
+				reg = <ef600600 8>;
+				virtual-reg = <ef600600>;
+				clock-frequency = <0>;
+				current-speed = <0>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <4 4>;
+			};
+
+*/
+			IIC0: i2c@ef600700 {
+				device_type = "i2c";
+				compatible = "ibm,iic-440ep", "ibm,iic-440gp", "ibm,iic";
+				reg = <ef600700 14>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <2 4>;
+			};
+
+			IIC1: i2c@ef600800 {
+				device_type = "i2c";
+				compatible = "ibm,iic-440ep", "ibm,iic-440gp", "ibm,iic";
+				reg = <ef600800 14>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <7 4>;
+			};
+
+			ZMII0: emac-zmii@ef600d00 {
+				device_type = "zmii-interface";
+				compatible = "ibm,zmii-440ep", "ibm,zmii-440gp", "ibm,zmii";
+				reg = <ef600d00 c>;
+			};
+
+		};
+
+		PCI0: pci@ec000000 {
+			device_type = "pci";
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			compatible = "ibm,plb440ep-pci", "ibm,plb-pci";
+			primary;
+			reg = <0 eec00000 8     /* Config space access */
+			       0 eed00000 4     /* IACK */
+			       0 eed00000 4     /* Special cycle */
+			       0 ef400000 40>;  /* Internal registers */
+
+			/* Outbound ranges, one memory and one IO,
+			 * later cannot be changed. Chip supports a second
+			 * IO range but we don't use it for now
+			 */
+			ranges = <02000000 0 a0000000 0 a0000000 0 20000000
+				  01000000 0 00000000 0 e8000000 0 00010000>;
+
+			/* Inbound 2GB range starting at 0 */
+			dma-ranges = <42000000 0 0 0 0 0 80000000>;
+
+			/* Bamboo has all 4 IRQ pins tied together per slot */
+			interrupt-map-mask = <f800 0 0 0>;
+			interrupt-map = <
+				/* IDSEL 1 */
+				0800 0 0 0 &UIC0 1c 8
+
+				/* IDSEL 2 */
+				1000 0 0 0 &UIC0 1b 8
+
+				/* IDSEL 3 */
+				1800 0 0 0 &UIC0 1a 8
+
+				/* IDSEL 4 */
+				2000 0 0 0 &UIC0 19 8
+			>;
+		};
+
+	};
+
+	chosen {
+		linux,stdout-path = "/plb/opb/serial@ef600300";
+	};
+};
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index be0cbe1..ea2257b 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -8,6 +8,7 @@ void register_machines(void)
     qemu_register_machine(&prep_machine);
     qemu_register_machine(&ref405ep_machine);
     qemu_register_machine(&taihu_machine);
+    qemu_register_machine(&bamboo_machine);
 }
 
 void cpu_save(QEMUFile *f, void *opaque)
-- 
1.5.6.5


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

* Re: [Qemu-devel] [PATCH 8/8] IBM PowerPC 440EP Bamboo reference board emulation
  2008-12-15 16:44     ` Hollis Blanchard
  (?)
@ 2008-12-15 17:03     ` Paul Brook
  -1 siblings, 0 replies; 31+ messages in thread
From: Paul Brook @ 2008-12-15 17:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc, Hollis Blanchard

On Monday 15 December 2008, Hollis Blanchard wrote:
> + * Qemu PowerPC 440 board emulation

Is this emulating an actual board, or something you invented. I'm guessing the 
latter, inwhich case you should say which one.

Paul

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

* Re: [Qemu-devel] [PATCH 4/8] kvm: sync vcpu state during initialization
  2008-12-15 16:44     ` Hollis Blanchard
@ 2008-12-15 22:20       ` Anthony Liguori
  -1 siblings, 0 replies; 31+ messages in thread
From: Anthony Liguori @ 2008-12-15 22:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

Hollis Blanchard wrote:
> Currently on x86, qemu initializes CPUState but KVM ignores it and does its
> own vcpu initialization. However, PowerPC KVM needs to be able to set the
> initial register state to support the -kernel and -append options.
>
> Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
>   

Applied.  Thanks.

Regards,

Anthony Liguori

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

* Re: [Qemu-devel] [PATCH 4/8] kvm: sync vcpu state during initialization
@ 2008-12-15 22:20       ` Anthony Liguori
  0 siblings, 0 replies; 31+ messages in thread
From: Anthony Liguori @ 2008-12-15 22:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

Hollis Blanchard wrote:
> Currently on x86, qemu initializes CPUState but KVM ignores it and does its
> own vcpu initialization. However, PowerPC KVM needs to be able to set the
> initial register state to support the -kernel and -append options.
>
> Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
>   

Applied.  Thanks.

Regards,

Anthony Liguori


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

* Re: [Qemu-devel] [PATCH 6/8] Enable KVM for ppcemb.
  2008-12-15 16:44     ` Hollis Blanchard
@ 2008-12-15 22:24       ` Anthony Liguori
  -1 siblings, 0 replies; 31+ messages in thread
From: Anthony Liguori @ 2008-12-15 22:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

Hollis Blanchard wrote:
> Implement hooks called by generic KVM code.
>
> Also add code that will copy the host's CPU and timebase frequencies to the
> guest, which is necessary on KVM because the guest can directly access the
> timebase.
>
> Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
>   

Acked-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori

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

* Re: [Qemu-devel] [PATCH 6/8] Enable KVM for ppcemb.
@ 2008-12-15 22:24       ` Anthony Liguori
  0 siblings, 0 replies; 31+ messages in thread
From: Anthony Liguori @ 2008-12-15 22:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

Hollis Blanchard wrote:
> Implement hooks called by generic KVM code.
>
> Also add code that will copy the host's CPU and timebase frequencies to the
> guest, which is necessary on KVM because the guest can directly access the
> timebase.
>
> Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
>   

Acked-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori


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

* Re: [Qemu-devel] [PATCH 1/8] Move PPC4xx SDRAM controller emulation from ppc405_uc.c to ppc4xx_devs.c
  2008-12-15 16:44   ` Hollis Blanchard
@ 2008-12-15 23:14     ` Aurelien Jarno
  -1 siblings, 0 replies; 31+ messages in thread
From: Aurelien Jarno @ 2008-12-15 23:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

On Mon, Dec 15, 2008 at 10:44:12AM -0600, Hollis Blanchard wrote:
> The SDRAM controller is shared across almost all 405 and 440 embedded
> processors, with some slight differences such as the sizes supported for each
> memory bank.
> 
> Code movement only; no functional changes.
> 
> Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>

Thanks, applied.

> ---
> I think all device emulation should move from ppc405_uc.c to ppc4xx_devs.c,
> since it is shared between all 4xx SoCs (405 and 440). At the moment, the SDRAM
> controller is the only piece I have code for, so I'm only moving it.
> 
> (I can only guess "uc" means "microcontroller"; the file should be renamed as
> well.)
> ---
>  hw/ppc405.h      |    5 -
>  hw/ppc405_uc.c   |  341 ------------------------------------------------------
>  hw/ppc4xx.h      |    5 +
>  hw/ppc4xx_devs.c |  341 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 346 insertions(+), 346 deletions(-)
> 
> diff --git a/hw/ppc405.h b/hw/ppc405.h
> index e032170..eebcef3 100644
> --- a/hw/ppc405.h
> +++ b/hw/ppc405.h
> @@ -66,11 +66,6 @@ void ppc4xx_pob_init (CPUState *env);
>  /* OPB arbitrer */
>  void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio,
>                         target_phys_addr_t offset);
> -/* SDRAM controller */
> -void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
> -                        target_phys_addr_t *ram_bases,
> -                        target_phys_addr_t *ram_sizes,
> -                        int do_init);
>  /* Peripheral controller */
>  void ppc405_ebc_init (CPUState *env);
>  /* DMA controller */
> diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
> index 25bcfd8..7e7fb38 100644
> --- a/hw/ppc405_uc.c
> +++ b/hw/ppc405_uc.c
> @@ -401,347 +401,6 @@ void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio,
>  /* XXX: TODO */
>  
>  /*****************************************************************************/
> -/* SDRAM controller */
> -typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
> -struct ppc4xx_sdram_t {
> -    uint32_t addr;
> -    int nbanks;
> -    target_phys_addr_t ram_bases[4];
> -    target_phys_addr_t ram_sizes[4];
> -    uint32_t besr0;
> -    uint32_t besr1;
> -    uint32_t bear;
> -    uint32_t cfg;
> -    uint32_t status;
> -    uint32_t rtr;
> -    uint32_t pmit;
> -    uint32_t bcr[4];
> -    uint32_t tr;
> -    uint32_t ecccfg;
> -    uint32_t eccesr;
> -    qemu_irq irq;
> -};
> -
> -enum {
> -    SDRAM0_CFGADDR = 0x010,
> -    SDRAM0_CFGDATA = 0x011,
> -};
> -
> -/* XXX: TOFIX: some patches have made this code become inconsistent:
> - *      there are type inconsistencies, mixing target_phys_addr_t, target_ulong
> - *      and uint32_t
> - */
> -static uint32_t sdram_bcr (target_phys_addr_t ram_base,
> -                           target_phys_addr_t ram_size)
> -{
> -    uint32_t bcr;
> -
> -    switch (ram_size) {
> -    case (4 * 1024 * 1024):
> -        bcr = 0x00000000;
> -        break;
> -    case (8 * 1024 * 1024):
> -        bcr = 0x00020000;
> -        break;
> -    case (16 * 1024 * 1024):
> -        bcr = 0x00040000;
> -        break;
> -    case (32 * 1024 * 1024):
> -        bcr = 0x00060000;
> -        break;
> -    case (64 * 1024 * 1024):
> -        bcr = 0x00080000;
> -        break;
> -    case (128 * 1024 * 1024):
> -        bcr = 0x000A0000;
> -        break;
> -    case (256 * 1024 * 1024):
> -        bcr = 0x000C0000;
> -        break;
> -    default:
> -        printf("%s: invalid RAM size " PADDRX "\n", __func__, ram_size);
> -        return 0x00000000;
> -    }
> -    bcr |= ram_base & 0xFF800000;
> -    bcr |= 1;
> -
> -    return bcr;
> -}
> -
> -static always_inline target_phys_addr_t sdram_base (uint32_t bcr)
> -{
> -    return bcr & 0xFF800000;
> -}
> -
> -static target_ulong sdram_size (uint32_t bcr)
> -{
> -    target_ulong size;
> -    int sh;
> -
> -    sh = (bcr >> 17) & 0x7;
> -    if (sh == 7)
> -        size = -1;
> -    else
> -        size = (4 * 1024 * 1024) << sh;
> -
> -    return size;
> -}
> -
> -static void sdram_set_bcr (uint32_t *bcrp, uint32_t bcr, int enabled)
> -{
> -    if (*bcrp & 0x00000001) {
> -        /* Unmap RAM */
> -#ifdef DEBUG_SDRAM
> -        printf("%s: unmap RAM area " PADDRX " " ADDRX "\n",
> -               __func__, sdram_base(*bcrp), sdram_size(*bcrp));
> -#endif
> -        cpu_register_physical_memory(sdram_base(*bcrp), sdram_size(*bcrp),
> -                                     IO_MEM_UNASSIGNED);
> -    }
> -    *bcrp = bcr & 0xFFDEE001;
> -    if (enabled && (bcr & 0x00000001)) {
> -#ifdef DEBUG_SDRAM
> -        printf("%s: Map RAM area " PADDRX " " ADDRX "\n",
> -               __func__, sdram_base(bcr), sdram_size(bcr));
> -#endif
> -        cpu_register_physical_memory(sdram_base(bcr), sdram_size(bcr),
> -                                     sdram_base(bcr) | IO_MEM_RAM);
> -    }
> -}
> -
> -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->bcr[i],
> -                          sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
> -                          1);
> -        } else {
> -            sdram_set_bcr(&sdram->bcr[i], 0x00000000, 0);
> -        }
> -    }
> -}
> -
> -static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram)
> -{
> -    int i;
> -
> -    for (i = 0; i < sdram->nbanks; i++) {
> -#ifdef DEBUG_SDRAM
> -        printf("%s: Unmap RAM area " PADDRX " " ADDRX "\n",
> -               __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
> -#endif
> -        cpu_register_physical_memory(sdram_base(sdram->bcr[i]),
> -                                     sdram_size(sdram->bcr[i]),
> -                                     IO_MEM_UNASSIGNED);
> -    }
> -}
> -
> -static target_ulong dcr_read_sdram (void *opaque, int dcrn)
> -{
> -    ppc4xx_sdram_t *sdram;
> -    target_ulong ret;
> -
> -    sdram = opaque;
> -    switch (dcrn) {
> -    case SDRAM0_CFGADDR:
> -        ret = sdram->addr;
> -        break;
> -    case SDRAM0_CFGDATA:
> -        switch (sdram->addr) {
> -        case 0x00: /* SDRAM_BESR0 */
> -            ret = sdram->besr0;
> -            break;
> -        case 0x08: /* SDRAM_BESR1 */
> -            ret = sdram->besr1;
> -            break;
> -        case 0x10: /* SDRAM_BEAR */
> -            ret = sdram->bear;
> -            break;
> -        case 0x20: /* SDRAM_CFG */
> -            ret = sdram->cfg;
> -            break;
> -        case 0x24: /* SDRAM_STATUS */
> -            ret = sdram->status;
> -            break;
> -        case 0x30: /* SDRAM_RTR */
> -            ret = sdram->rtr;
> -            break;
> -        case 0x34: /* SDRAM_PMIT */
> -            ret = sdram->pmit;
> -            break;
> -        case 0x40: /* SDRAM_B0CR */
> -            ret = sdram->bcr[0];
> -            break;
> -        case 0x44: /* SDRAM_B1CR */
> -            ret = sdram->bcr[1];
> -            break;
> -        case 0x48: /* SDRAM_B2CR */
> -            ret = sdram->bcr[2];
> -            break;
> -        case 0x4C: /* SDRAM_B3CR */
> -            ret = sdram->bcr[3];
> -            break;
> -        case 0x80: /* SDRAM_TR */
> -            ret = -1; /* ? */
> -            break;
> -        case 0x94: /* SDRAM_ECCCFG */
> -            ret = sdram->ecccfg;
> -            break;
> -        case 0x98: /* SDRAM_ECCESR */
> -            ret = sdram->eccesr;
> -            break;
> -        default: /* Error */
> -            ret = -1;
> -            break;
> -        }
> -        break;
> -    default:
> -        /* Avoid gcc warning */
> -        ret = 0x00000000;
> -        break;
> -    }
> -
> -    return ret;
> -}
> -
> -static void dcr_write_sdram (void *opaque, int dcrn, target_ulong val)
> -{
> -    ppc4xx_sdram_t *sdram;
> -
> -    sdram = opaque;
> -    switch (dcrn) {
> -    case SDRAM0_CFGADDR:
> -        sdram->addr = val;
> -        break;
> -    case SDRAM0_CFGDATA:
> -        switch (sdram->addr) {
> -        case 0x00: /* SDRAM_BESR0 */
> -            sdram->besr0 &= ~val;
> -            break;
> -        case 0x08: /* SDRAM_BESR1 */
> -            sdram->besr1 &= ~val;
> -            break;
> -        case 0x10: /* SDRAM_BEAR */
> -            sdram->bear = val;
> -            break;
> -        case 0x20: /* SDRAM_CFG */
> -            val &= 0xFFE00000;
> -            if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
> -#ifdef DEBUG_SDRAM
> -                printf("%s: enable SDRAM controller\n", __func__);
> -#endif
> -                /* validate all RAM mappings */
> -                sdram_map_bcr(sdram);
> -                sdram->status &= ~0x80000000;
> -            } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
> -#ifdef DEBUG_SDRAM
> -                printf("%s: disable SDRAM controller\n", __func__);
> -#endif
> -                /* invalidate all RAM mappings */
> -                sdram_unmap_bcr(sdram);
> -                sdram->status |= 0x80000000;
> -            }
> -            if (!(sdram->cfg & 0x40000000) && (val & 0x40000000))
> -                sdram->status |= 0x40000000;
> -            else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000))
> -                sdram->status &= ~0x40000000;
> -            sdram->cfg = val;
> -            break;
> -        case 0x24: /* SDRAM_STATUS */
> -            /* Read-only register */
> -            break;
> -        case 0x30: /* SDRAM_RTR */
> -            sdram->rtr = val & 0x3FF80000;
> -            break;
> -        case 0x34: /* SDRAM_PMIT */
> -            sdram->pmit = (val & 0xF8000000) | 0x07C00000;
> -            break;
> -        case 0x40: /* SDRAM_B0CR */
> -            sdram_set_bcr(&sdram->bcr[0], val, sdram->cfg & 0x80000000);
> -            break;
> -        case 0x44: /* SDRAM_B1CR */
> -            sdram_set_bcr(&sdram->bcr[1], val, sdram->cfg & 0x80000000);
> -            break;
> -        case 0x48: /* SDRAM_B2CR */
> -            sdram_set_bcr(&sdram->bcr[2], val, sdram->cfg & 0x80000000);
> -            break;
> -        case 0x4C: /* SDRAM_B3CR */
> -            sdram_set_bcr(&sdram->bcr[3], val, sdram->cfg & 0x80000000);
> -            break;
> -        case 0x80: /* SDRAM_TR */
> -            sdram->tr = val & 0x018FC01F;
> -            break;
> -        case 0x94: /* SDRAM_ECCCFG */
> -            sdram->ecccfg = val & 0x00F00000;
> -            break;
> -        case 0x98: /* SDRAM_ECCESR */
> -            val &= 0xFFF0F000;
> -            if (sdram->eccesr == 0 && val != 0)
> -                qemu_irq_raise(sdram->irq);
> -            else if (sdram->eccesr != 0 && val == 0)
> -                qemu_irq_lower(sdram->irq);
> -            sdram->eccesr = val;
> -            break;
> -        default: /* Error */
> -            break;
> -        }
> -        break;
> -    }
> -}
> -
> -static void sdram_reset (void *opaque)
> -{
> -    ppc4xx_sdram_t *sdram;
> -
> -    sdram = opaque;
> -    sdram->addr = 0x00000000;
> -    sdram->bear = 0x00000000;
> -    sdram->besr0 = 0x00000000; /* No error */
> -    sdram->besr1 = 0x00000000; /* No error */
> -    sdram->cfg = 0x00000000;
> -    sdram->ecccfg = 0x00000000; /* No ECC */
> -    sdram->eccesr = 0x00000000; /* No error */
> -    sdram->pmit = 0x07C00000;
> -    sdram->rtr = 0x05F00000;
> -    sdram->tr = 0x00854009;
> -    /* We pre-initialize RAM banks */
> -    sdram->status = 0x00000000;
> -    sdram->cfg = 0x00800000;
> -    sdram_unmap_bcr(sdram);
> -}
> -
> -void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
> -                        target_phys_addr_t *ram_bases,
> -                        target_phys_addr_t *ram_sizes,
> -                        int do_init)
> -{
> -    ppc4xx_sdram_t *sdram;
> -
> -    sdram = qemu_mallocz(sizeof(ppc4xx_sdram_t));
> -    if (sdram != NULL) {
> -        sdram->irq = irq;
> -        sdram->nbanks = nbanks;
> -        memset(sdram->ram_bases, 0, 4 * sizeof(target_phys_addr_t));
> -        memcpy(sdram->ram_bases, ram_bases,
> -               nbanks * sizeof(target_phys_addr_t));
> -        memset(sdram->ram_sizes, 0, 4 * sizeof(target_phys_addr_t));
> -        memcpy(sdram->ram_sizes, ram_sizes,
> -               nbanks * sizeof(target_phys_addr_t));
> -        sdram_reset(sdram);
> -        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);
> -    }
> -}
> -
> -/*****************************************************************************/
>  /* Peripheral controller */
>  typedef struct ppc4xx_ebc_t ppc4xx_ebc_t;
>  struct ppc4xx_ebc_t {
> diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h
> index 88802ae..8c2878a 100644
> --- a/hw/ppc4xx.h
> +++ b/hw/ppc4xx.h
> @@ -48,6 +48,11 @@ enum {
>  qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
>                         uint32_t dcr_base, int has_ssr, int has_vr);
>  
> +void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
> +                        target_phys_addr_t *ram_bases,
> +                        target_phys_addr_t *ram_sizes,
> +                        int do_init);
> +
>  PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
>                          target_phys_addr_t config_space,
>                          target_phys_addr_t int_ack,
> diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
> index ff67011..c6be2d6 100644
> --- a/hw/ppc4xx_devs.c
> +++ b/hw/ppc4xx_devs.c
> @@ -532,3 +532,344 @@ qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
>  
>      return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
>  }
> +
> +/*****************************************************************************/
> +/* SDRAM controller */
> +typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
> +struct ppc4xx_sdram_t {
> +    uint32_t addr;
> +    int nbanks;
> +    target_phys_addr_t ram_bases[4];
> +    target_phys_addr_t ram_sizes[4];
> +    uint32_t besr0;
> +    uint32_t besr1;
> +    uint32_t bear;
> +    uint32_t cfg;
> +    uint32_t status;
> +    uint32_t rtr;
> +    uint32_t pmit;
> +    uint32_t bcr[4];
> +    uint32_t tr;
> +    uint32_t ecccfg;
> +    uint32_t eccesr;
> +    qemu_irq irq;
> +};
> +
> +enum {
> +    SDRAM0_CFGADDR = 0x010,
> +    SDRAM0_CFGDATA = 0x011,
> +};
> +
> +/* XXX: TOFIX: some patches have made this code become inconsistent:
> + *      there are type inconsistencies, mixing target_phys_addr_t, target_ulong
> + *      and uint32_t
> + */
> +static uint32_t sdram_bcr (target_phys_addr_t ram_base,
> +                           target_phys_addr_t ram_size)
> +{
> +    uint32_t bcr;
> +
> +    switch (ram_size) {
> +    case (4 * 1024 * 1024):
> +        bcr = 0x00000000;
> +        break;
> +    case (8 * 1024 * 1024):
> +        bcr = 0x00020000;
> +        break;
> +    case (16 * 1024 * 1024):
> +        bcr = 0x00040000;
> +        break;
> +    case (32 * 1024 * 1024):
> +        bcr = 0x00060000;
> +        break;
> +    case (64 * 1024 * 1024):
> +        bcr = 0x00080000;
> +        break;
> +    case (128 * 1024 * 1024):
> +        bcr = 0x000A0000;
> +        break;
> +    case (256 * 1024 * 1024):
> +        bcr = 0x000C0000;
> +        break;
> +    default:
> +        printf("%s: invalid RAM size " PADDRX "\n", __func__, ram_size);
> +        return 0x00000000;
> +    }
> +    bcr |= ram_base & 0xFF800000;
> +    bcr |= 1;
> +
> +    return bcr;
> +}
> +
> +static always_inline target_phys_addr_t sdram_base (uint32_t bcr)
> +{
> +    return bcr & 0xFF800000;
> +}
> +
> +static target_ulong sdram_size (uint32_t bcr)
> +{
> +    target_ulong size;
> +    int sh;
> +
> +    sh = (bcr >> 17) & 0x7;
> +    if (sh == 7)
> +        size = -1;
> +    else
> +        size = (4 * 1024 * 1024) << sh;
> +
> +    return size;
> +}
> +
> +static void sdram_set_bcr (uint32_t *bcrp, uint32_t bcr, int enabled)
> +{
> +    if (*bcrp & 0x00000001) {
> +        /* Unmap RAM */
> +#ifdef DEBUG_SDRAM
> +        printf("%s: unmap RAM area " PADDRX " " ADDRX "\n",
> +               __func__, sdram_base(*bcrp), sdram_size(*bcrp));
> +#endif
> +        cpu_register_physical_memory(sdram_base(*bcrp), sdram_size(*bcrp),
> +                                     IO_MEM_UNASSIGNED);
> +    }
> +    *bcrp = bcr & 0xFFDEE001;
> +    if (enabled && (bcr & 0x00000001)) {
> +#ifdef DEBUG_SDRAM
> +        printf("%s: Map RAM area " PADDRX " " ADDRX "\n",
> +               __func__, sdram_base(bcr), sdram_size(bcr));
> +#endif
> +        cpu_register_physical_memory(sdram_base(bcr), sdram_size(bcr),
> +                                     sdram_base(bcr) | IO_MEM_RAM);
> +    }
> +}
> +
> +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->bcr[i],
> +                          sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
> +                          1);
> +        } else {
> +            sdram_set_bcr(&sdram->bcr[i], 0x00000000, 0);
> +        }
> +    }
> +}
> +
> +static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram)
> +{
> +    int i;
> +
> +    for (i = 0; i < sdram->nbanks; i++) {
> +#ifdef DEBUG_SDRAM
> +        printf("%s: Unmap RAM area " PADDRX " " ADDRX "\n",
> +               __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
> +#endif
> +        cpu_register_physical_memory(sdram_base(sdram->bcr[i]),
> +                                     sdram_size(sdram->bcr[i]),
> +                                     IO_MEM_UNASSIGNED);
> +    }
> +}
> +
> +static target_ulong dcr_read_sdram (void *opaque, int dcrn)
> +{
> +    ppc4xx_sdram_t *sdram;
> +    target_ulong ret;
> +
> +    sdram = opaque;
> +    switch (dcrn) {
> +    case SDRAM0_CFGADDR:
> +        ret = sdram->addr;
> +        break;
> +    case SDRAM0_CFGDATA:
> +        switch (sdram->addr) {
> +        case 0x00: /* SDRAM_BESR0 */
> +            ret = sdram->besr0;
> +            break;
> +        case 0x08: /* SDRAM_BESR1 */
> +            ret = sdram->besr1;
> +            break;
> +        case 0x10: /* SDRAM_BEAR */
> +            ret = sdram->bear;
> +            break;
> +        case 0x20: /* SDRAM_CFG */
> +            ret = sdram->cfg;
> +            break;
> +        case 0x24: /* SDRAM_STATUS */
> +            ret = sdram->status;
> +            break;
> +        case 0x30: /* SDRAM_RTR */
> +            ret = sdram->rtr;
> +            break;
> +        case 0x34: /* SDRAM_PMIT */
> +            ret = sdram->pmit;
> +            break;
> +        case 0x40: /* SDRAM_B0CR */
> +            ret = sdram->bcr[0];
> +            break;
> +        case 0x44: /* SDRAM_B1CR */
> +            ret = sdram->bcr[1];
> +            break;
> +        case 0x48: /* SDRAM_B2CR */
> +            ret = sdram->bcr[2];
> +            break;
> +        case 0x4C: /* SDRAM_B3CR */
> +            ret = sdram->bcr[3];
> +            break;
> +        case 0x80: /* SDRAM_TR */
> +            ret = -1; /* ? */
> +            break;
> +        case 0x94: /* SDRAM_ECCCFG */
> +            ret = sdram->ecccfg;
> +            break;
> +        case 0x98: /* SDRAM_ECCESR */
> +            ret = sdram->eccesr;
> +            break;
> +        default: /* Error */
> +            ret = -1;
> +            break;
> +        }
> +        break;
> +    default:
> +        /* Avoid gcc warning */
> +        ret = 0x00000000;
> +        break;
> +    }
> +
> +    return ret;
> +}
> +
> +static void dcr_write_sdram (void *opaque, int dcrn, target_ulong val)
> +{
> +    ppc4xx_sdram_t *sdram;
> +
> +    sdram = opaque;
> +    switch (dcrn) {
> +    case SDRAM0_CFGADDR:
> +        sdram->addr = val;
> +        break;
> +    case SDRAM0_CFGDATA:
> +        switch (sdram->addr) {
> +        case 0x00: /* SDRAM_BESR0 */
> +            sdram->besr0 &= ~val;
> +            break;
> +        case 0x08: /* SDRAM_BESR1 */
> +            sdram->besr1 &= ~val;
> +            break;
> +        case 0x10: /* SDRAM_BEAR */
> +            sdram->bear = val;
> +            break;
> +        case 0x20: /* SDRAM_CFG */
> +            val &= 0xFFE00000;
> +            if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
> +#ifdef DEBUG_SDRAM
> +                printf("%s: enable SDRAM controller\n", __func__);
> +#endif
> +                /* validate all RAM mappings */
> +                sdram_map_bcr(sdram);
> +                sdram->status &= ~0x80000000;
> +            } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
> +#ifdef DEBUG_SDRAM
> +                printf("%s: disable SDRAM controller\n", __func__);
> +#endif
> +                /* invalidate all RAM mappings */
> +                sdram_unmap_bcr(sdram);
> +                sdram->status |= 0x80000000;
> +            }
> +            if (!(sdram->cfg & 0x40000000) && (val & 0x40000000))
> +                sdram->status |= 0x40000000;
> +            else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000))
> +                sdram->status &= ~0x40000000;
> +            sdram->cfg = val;
> +            break;
> +        case 0x24: /* SDRAM_STATUS */
> +            /* Read-only register */
> +            break;
> +        case 0x30: /* SDRAM_RTR */
> +            sdram->rtr = val & 0x3FF80000;
> +            break;
> +        case 0x34: /* SDRAM_PMIT */
> +            sdram->pmit = (val & 0xF8000000) | 0x07C00000;
> +            break;
> +        case 0x40: /* SDRAM_B0CR */
> +            sdram_set_bcr(&sdram->bcr[0], val, sdram->cfg & 0x80000000);
> +            break;
> +        case 0x44: /* SDRAM_B1CR */
> +            sdram_set_bcr(&sdram->bcr[1], val, sdram->cfg & 0x80000000);
> +            break;
> +        case 0x48: /* SDRAM_B2CR */
> +            sdram_set_bcr(&sdram->bcr[2], val, sdram->cfg & 0x80000000);
> +            break;
> +        case 0x4C: /* SDRAM_B3CR */
> +            sdram_set_bcr(&sdram->bcr[3], val, sdram->cfg & 0x80000000);
> +            break;
> +        case 0x80: /* SDRAM_TR */
> +            sdram->tr = val & 0x018FC01F;
> +            break;
> +        case 0x94: /* SDRAM_ECCCFG */
> +            sdram->ecccfg = val & 0x00F00000;
> +            break;
> +        case 0x98: /* SDRAM_ECCESR */
> +            val &= 0xFFF0F000;
> +            if (sdram->eccesr == 0 && val != 0)
> +                qemu_irq_raise(sdram->irq);
> +            else if (sdram->eccesr != 0 && val == 0)
> +                qemu_irq_lower(sdram->irq);
> +            sdram->eccesr = val;
> +            break;
> +        default: /* Error */
> +            break;
> +        }
> +        break;
> +    }
> +}
> +
> +static void sdram_reset (void *opaque)
> +{
> +    ppc4xx_sdram_t *sdram;
> +
> +    sdram = opaque;
> +    sdram->addr = 0x00000000;
> +    sdram->bear = 0x00000000;
> +    sdram->besr0 = 0x00000000; /* No error */
> +    sdram->besr1 = 0x00000000; /* No error */
> +    sdram->cfg = 0x00000000;
> +    sdram->ecccfg = 0x00000000; /* No ECC */
> +    sdram->eccesr = 0x00000000; /* No error */
> +    sdram->pmit = 0x07C00000;
> +    sdram->rtr = 0x05F00000;
> +    sdram->tr = 0x00854009;
> +    /* We pre-initialize RAM banks */
> +    sdram->status = 0x00000000;
> +    sdram->cfg = 0x00800000;
> +    sdram_unmap_bcr(sdram);
> +}
> +
> +void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
> +                        target_phys_addr_t *ram_bases,
> +                        target_phys_addr_t *ram_sizes,
> +                        int do_init)
> +{
> +    ppc4xx_sdram_t *sdram;
> +
> +    sdram = qemu_mallocz(sizeof(ppc4xx_sdram_t));
> +    if (sdram != NULL) {
> +        sdram->irq = irq;
> +        sdram->nbanks = nbanks;
> +        memset(sdram->ram_bases, 0, 4 * sizeof(target_phys_addr_t));
> +        memcpy(sdram->ram_bases, ram_bases,
> +               nbanks * sizeof(target_phys_addr_t));
> +        memset(sdram->ram_sizes, 0, 4 * sizeof(target_phys_addr_t));
> +        memcpy(sdram->ram_sizes, ram_sizes,
> +               nbanks * sizeof(target_phys_addr_t));
> +        sdram_reset(sdram);
> +        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);
> +    }
> +}
> -- 
> 1.5.6.5
> 
> 
> 
> 

-- 
  .''`.  Aurelien Jarno	            | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   aurel32@debian.org         | aurelien@aurel32.net
   `-    people.debian.org/~aurel32 | www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 1/8] Move PPC4xx SDRAM controller
@ 2008-12-15 23:14     ` Aurelien Jarno
  0 siblings, 0 replies; 31+ messages in thread
From: Aurelien Jarno @ 2008-12-15 23:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

On Mon, Dec 15, 2008 at 10:44:12AM -0600, Hollis Blanchard wrote:
> The SDRAM controller is shared across almost all 405 and 440 embedded
> processors, with some slight differences such as the sizes supported for each
> memory bank.
> 
> Code movement only; no functional changes.
> 
> Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>

Thanks, applied.

> ---
> I think all device emulation should move from ppc405_uc.c to ppc4xx_devs.c,
> since it is shared between all 4xx SoCs (405 and 440). At the moment, the SDRAM
> controller is the only piece I have code for, so I'm only moving it.
> 
> (I can only guess "uc" means "microcontroller"; the file should be renamed as
> well.)
> ---
>  hw/ppc405.h      |    5 -
>  hw/ppc405_uc.c   |  341 ------------------------------------------------------
>  hw/ppc4xx.h      |    5 +
>  hw/ppc4xx_devs.c |  341 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 346 insertions(+), 346 deletions(-)
> 
> diff --git a/hw/ppc405.h b/hw/ppc405.h
> index e032170..eebcef3 100644
> --- a/hw/ppc405.h
> +++ b/hw/ppc405.h
> @@ -66,11 +66,6 @@ void ppc4xx_pob_init (CPUState *env);
>  /* OPB arbitrer */
>  void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio,
>                         target_phys_addr_t offset);
> -/* SDRAM controller */
> -void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
> -                        target_phys_addr_t *ram_bases,
> -                        target_phys_addr_t *ram_sizes,
> -                        int do_init);
>  /* Peripheral controller */
>  void ppc405_ebc_init (CPUState *env);
>  /* DMA controller */
> diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
> index 25bcfd8..7e7fb38 100644
> --- a/hw/ppc405_uc.c
> +++ b/hw/ppc405_uc.c
> @@ -401,347 +401,6 @@ void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio,
>  /* XXX: TODO */
>  
>  /*****************************************************************************/
> -/* SDRAM controller */
> -typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
> -struct ppc4xx_sdram_t {
> -    uint32_t addr;
> -    int nbanks;
> -    target_phys_addr_t ram_bases[4];
> -    target_phys_addr_t ram_sizes[4];
> -    uint32_t besr0;
> -    uint32_t besr1;
> -    uint32_t bear;
> -    uint32_t cfg;
> -    uint32_t status;
> -    uint32_t rtr;
> -    uint32_t pmit;
> -    uint32_t bcr[4];
> -    uint32_t tr;
> -    uint32_t ecccfg;
> -    uint32_t eccesr;
> -    qemu_irq irq;
> -};
> -
> -enum {
> -    SDRAM0_CFGADDR = 0x010,
> -    SDRAM0_CFGDATA = 0x011,
> -};
> -
> -/* XXX: TOFIX: some patches have made this code become inconsistent:
> - *      there are type inconsistencies, mixing target_phys_addr_t, target_ulong
> - *      and uint32_t
> - */
> -static uint32_t sdram_bcr (target_phys_addr_t ram_base,
> -                           target_phys_addr_t ram_size)
> -{
> -    uint32_t bcr;
> -
> -    switch (ram_size) {
> -    case (4 * 1024 * 1024):
> -        bcr = 0x00000000;
> -        break;
> -    case (8 * 1024 * 1024):
> -        bcr = 0x00020000;
> -        break;
> -    case (16 * 1024 * 1024):
> -        bcr = 0x00040000;
> -        break;
> -    case (32 * 1024 * 1024):
> -        bcr = 0x00060000;
> -        break;
> -    case (64 * 1024 * 1024):
> -        bcr = 0x00080000;
> -        break;
> -    case (128 * 1024 * 1024):
> -        bcr = 0x000A0000;
> -        break;
> -    case (256 * 1024 * 1024):
> -        bcr = 0x000C0000;
> -        break;
> -    default:
> -        printf("%s: invalid RAM size " PADDRX "\n", __func__, ram_size);
> -        return 0x00000000;
> -    }
> -    bcr |= ram_base & 0xFF800000;
> -    bcr |= 1;
> -
> -    return bcr;
> -}
> -
> -static always_inline target_phys_addr_t sdram_base (uint32_t bcr)
> -{
> -    return bcr & 0xFF800000;
> -}
> -
> -static target_ulong sdram_size (uint32_t bcr)
> -{
> -    target_ulong size;
> -    int sh;
> -
> -    sh = (bcr >> 17) & 0x7;
> -    if (sh = 7)
> -        size = -1;
> -    else
> -        size = (4 * 1024 * 1024) << sh;
> -
> -    return size;
> -}
> -
> -static void sdram_set_bcr (uint32_t *bcrp, uint32_t bcr, int enabled)
> -{
> -    if (*bcrp & 0x00000001) {
> -        /* Unmap RAM */
> -#ifdef DEBUG_SDRAM
> -        printf("%s: unmap RAM area " PADDRX " " ADDRX "\n",
> -               __func__, sdram_base(*bcrp), sdram_size(*bcrp));
> -#endif
> -        cpu_register_physical_memory(sdram_base(*bcrp), sdram_size(*bcrp),
> -                                     IO_MEM_UNASSIGNED);
> -    }
> -    *bcrp = bcr & 0xFFDEE001;
> -    if (enabled && (bcr & 0x00000001)) {
> -#ifdef DEBUG_SDRAM
> -        printf("%s: Map RAM area " PADDRX " " ADDRX "\n",
> -               __func__, sdram_base(bcr), sdram_size(bcr));
> -#endif
> -        cpu_register_physical_memory(sdram_base(bcr), sdram_size(bcr),
> -                                     sdram_base(bcr) | IO_MEM_RAM);
> -    }
> -}
> -
> -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->bcr[i],
> -                          sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
> -                          1);
> -        } else {
> -            sdram_set_bcr(&sdram->bcr[i], 0x00000000, 0);
> -        }
> -    }
> -}
> -
> -static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram)
> -{
> -    int i;
> -
> -    for (i = 0; i < sdram->nbanks; i++) {
> -#ifdef DEBUG_SDRAM
> -        printf("%s: Unmap RAM area " PADDRX " " ADDRX "\n",
> -               __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
> -#endif
> -        cpu_register_physical_memory(sdram_base(sdram->bcr[i]),
> -                                     sdram_size(sdram->bcr[i]),
> -                                     IO_MEM_UNASSIGNED);
> -    }
> -}
> -
> -static target_ulong dcr_read_sdram (void *opaque, int dcrn)
> -{
> -    ppc4xx_sdram_t *sdram;
> -    target_ulong ret;
> -
> -    sdram = opaque;
> -    switch (dcrn) {
> -    case SDRAM0_CFGADDR:
> -        ret = sdram->addr;
> -        break;
> -    case SDRAM0_CFGDATA:
> -        switch (sdram->addr) {
> -        case 0x00: /* SDRAM_BESR0 */
> -            ret = sdram->besr0;
> -            break;
> -        case 0x08: /* SDRAM_BESR1 */
> -            ret = sdram->besr1;
> -            break;
> -        case 0x10: /* SDRAM_BEAR */
> -            ret = sdram->bear;
> -            break;
> -        case 0x20: /* SDRAM_CFG */
> -            ret = sdram->cfg;
> -            break;
> -        case 0x24: /* SDRAM_STATUS */
> -            ret = sdram->status;
> -            break;
> -        case 0x30: /* SDRAM_RTR */
> -            ret = sdram->rtr;
> -            break;
> -        case 0x34: /* SDRAM_PMIT */
> -            ret = sdram->pmit;
> -            break;
> -        case 0x40: /* SDRAM_B0CR */
> -            ret = sdram->bcr[0];
> -            break;
> -        case 0x44: /* SDRAM_B1CR */
> -            ret = sdram->bcr[1];
> -            break;
> -        case 0x48: /* SDRAM_B2CR */
> -            ret = sdram->bcr[2];
> -            break;
> -        case 0x4C: /* SDRAM_B3CR */
> -            ret = sdram->bcr[3];
> -            break;
> -        case 0x80: /* SDRAM_TR */
> -            ret = -1; /* ? */
> -            break;
> -        case 0x94: /* SDRAM_ECCCFG */
> -            ret = sdram->ecccfg;
> -            break;
> -        case 0x98: /* SDRAM_ECCESR */
> -            ret = sdram->eccesr;
> -            break;
> -        default: /* Error */
> -            ret = -1;
> -            break;
> -        }
> -        break;
> -    default:
> -        /* Avoid gcc warning */
> -        ret = 0x00000000;
> -        break;
> -    }
> -
> -    return ret;
> -}
> -
> -static void dcr_write_sdram (void *opaque, int dcrn, target_ulong val)
> -{
> -    ppc4xx_sdram_t *sdram;
> -
> -    sdram = opaque;
> -    switch (dcrn) {
> -    case SDRAM0_CFGADDR:
> -        sdram->addr = val;
> -        break;
> -    case SDRAM0_CFGDATA:
> -        switch (sdram->addr) {
> -        case 0x00: /* SDRAM_BESR0 */
> -            sdram->besr0 &= ~val;
> -            break;
> -        case 0x08: /* SDRAM_BESR1 */
> -            sdram->besr1 &= ~val;
> -            break;
> -        case 0x10: /* SDRAM_BEAR */
> -            sdram->bear = val;
> -            break;
> -        case 0x20: /* SDRAM_CFG */
> -            val &= 0xFFE00000;
> -            if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
> -#ifdef DEBUG_SDRAM
> -                printf("%s: enable SDRAM controller\n", __func__);
> -#endif
> -                /* validate all RAM mappings */
> -                sdram_map_bcr(sdram);
> -                sdram->status &= ~0x80000000;
> -            } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
> -#ifdef DEBUG_SDRAM
> -                printf("%s: disable SDRAM controller\n", __func__);
> -#endif
> -                /* invalidate all RAM mappings */
> -                sdram_unmap_bcr(sdram);
> -                sdram->status |= 0x80000000;
> -            }
> -            if (!(sdram->cfg & 0x40000000) && (val & 0x40000000))
> -                sdram->status |= 0x40000000;
> -            else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000))
> -                sdram->status &= ~0x40000000;
> -            sdram->cfg = val;
> -            break;
> -        case 0x24: /* SDRAM_STATUS */
> -            /* Read-only register */
> -            break;
> -        case 0x30: /* SDRAM_RTR */
> -            sdram->rtr = val & 0x3FF80000;
> -            break;
> -        case 0x34: /* SDRAM_PMIT */
> -            sdram->pmit = (val & 0xF8000000) | 0x07C00000;
> -            break;
> -        case 0x40: /* SDRAM_B0CR */
> -            sdram_set_bcr(&sdram->bcr[0], val, sdram->cfg & 0x80000000);
> -            break;
> -        case 0x44: /* SDRAM_B1CR */
> -            sdram_set_bcr(&sdram->bcr[1], val, sdram->cfg & 0x80000000);
> -            break;
> -        case 0x48: /* SDRAM_B2CR */
> -            sdram_set_bcr(&sdram->bcr[2], val, sdram->cfg & 0x80000000);
> -            break;
> -        case 0x4C: /* SDRAM_B3CR */
> -            sdram_set_bcr(&sdram->bcr[3], val, sdram->cfg & 0x80000000);
> -            break;
> -        case 0x80: /* SDRAM_TR */
> -            sdram->tr = val & 0x018FC01F;
> -            break;
> -        case 0x94: /* SDRAM_ECCCFG */
> -            sdram->ecccfg = val & 0x00F00000;
> -            break;
> -        case 0x98: /* SDRAM_ECCESR */
> -            val &= 0xFFF0F000;
> -            if (sdram->eccesr = 0 && val != 0)
> -                qemu_irq_raise(sdram->irq);
> -            else if (sdram->eccesr != 0 && val = 0)
> -                qemu_irq_lower(sdram->irq);
> -            sdram->eccesr = val;
> -            break;
> -        default: /* Error */
> -            break;
> -        }
> -        break;
> -    }
> -}
> -
> -static void sdram_reset (void *opaque)
> -{
> -    ppc4xx_sdram_t *sdram;
> -
> -    sdram = opaque;
> -    sdram->addr = 0x00000000;
> -    sdram->bear = 0x00000000;
> -    sdram->besr0 = 0x00000000; /* No error */
> -    sdram->besr1 = 0x00000000; /* No error */
> -    sdram->cfg = 0x00000000;
> -    sdram->ecccfg = 0x00000000; /* No ECC */
> -    sdram->eccesr = 0x00000000; /* No error */
> -    sdram->pmit = 0x07C00000;
> -    sdram->rtr = 0x05F00000;
> -    sdram->tr = 0x00854009;
> -    /* We pre-initialize RAM banks */
> -    sdram->status = 0x00000000;
> -    sdram->cfg = 0x00800000;
> -    sdram_unmap_bcr(sdram);
> -}
> -
> -void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
> -                        target_phys_addr_t *ram_bases,
> -                        target_phys_addr_t *ram_sizes,
> -                        int do_init)
> -{
> -    ppc4xx_sdram_t *sdram;
> -
> -    sdram = qemu_mallocz(sizeof(ppc4xx_sdram_t));
> -    if (sdram != NULL) {
> -        sdram->irq = irq;
> -        sdram->nbanks = nbanks;
> -        memset(sdram->ram_bases, 0, 4 * sizeof(target_phys_addr_t));
> -        memcpy(sdram->ram_bases, ram_bases,
> -               nbanks * sizeof(target_phys_addr_t));
> -        memset(sdram->ram_sizes, 0, 4 * sizeof(target_phys_addr_t));
> -        memcpy(sdram->ram_sizes, ram_sizes,
> -               nbanks * sizeof(target_phys_addr_t));
> -        sdram_reset(sdram);
> -        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);
> -    }
> -}
> -
> -/*****************************************************************************/
>  /* Peripheral controller */
>  typedef struct ppc4xx_ebc_t ppc4xx_ebc_t;
>  struct ppc4xx_ebc_t {
> diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h
> index 88802ae..8c2878a 100644
> --- a/hw/ppc4xx.h
> +++ b/hw/ppc4xx.h
> @@ -48,6 +48,11 @@ enum {
>  qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
>                         uint32_t dcr_base, int has_ssr, int has_vr);
>  
> +void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
> +                        target_phys_addr_t *ram_bases,
> +                        target_phys_addr_t *ram_sizes,
> +                        int do_init);
> +
>  PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
>                          target_phys_addr_t config_space,
>                          target_phys_addr_t int_ack,
> diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
> index ff67011..c6be2d6 100644
> --- a/hw/ppc4xx_devs.c
> +++ b/hw/ppc4xx_devs.c
> @@ -532,3 +532,344 @@ qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
>  
>      return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
>  }
> +
> +/*****************************************************************************/
> +/* SDRAM controller */
> +typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
> +struct ppc4xx_sdram_t {
> +    uint32_t addr;
> +    int nbanks;
> +    target_phys_addr_t ram_bases[4];
> +    target_phys_addr_t ram_sizes[4];
> +    uint32_t besr0;
> +    uint32_t besr1;
> +    uint32_t bear;
> +    uint32_t cfg;
> +    uint32_t status;
> +    uint32_t rtr;
> +    uint32_t pmit;
> +    uint32_t bcr[4];
> +    uint32_t tr;
> +    uint32_t ecccfg;
> +    uint32_t eccesr;
> +    qemu_irq irq;
> +};
> +
> +enum {
> +    SDRAM0_CFGADDR = 0x010,
> +    SDRAM0_CFGDATA = 0x011,
> +};
> +
> +/* XXX: TOFIX: some patches have made this code become inconsistent:
> + *      there are type inconsistencies, mixing target_phys_addr_t, target_ulong
> + *      and uint32_t
> + */
> +static uint32_t sdram_bcr (target_phys_addr_t ram_base,
> +                           target_phys_addr_t ram_size)
> +{
> +    uint32_t bcr;
> +
> +    switch (ram_size) {
> +    case (4 * 1024 * 1024):
> +        bcr = 0x00000000;
> +        break;
> +    case (8 * 1024 * 1024):
> +        bcr = 0x00020000;
> +        break;
> +    case (16 * 1024 * 1024):
> +        bcr = 0x00040000;
> +        break;
> +    case (32 * 1024 * 1024):
> +        bcr = 0x00060000;
> +        break;
> +    case (64 * 1024 * 1024):
> +        bcr = 0x00080000;
> +        break;
> +    case (128 * 1024 * 1024):
> +        bcr = 0x000A0000;
> +        break;
> +    case (256 * 1024 * 1024):
> +        bcr = 0x000C0000;
> +        break;
> +    default:
> +        printf("%s: invalid RAM size " PADDRX "\n", __func__, ram_size);
> +        return 0x00000000;
> +    }
> +    bcr |= ram_base & 0xFF800000;
> +    bcr |= 1;
> +
> +    return bcr;
> +}
> +
> +static always_inline target_phys_addr_t sdram_base (uint32_t bcr)
> +{
> +    return bcr & 0xFF800000;
> +}
> +
> +static target_ulong sdram_size (uint32_t bcr)
> +{
> +    target_ulong size;
> +    int sh;
> +
> +    sh = (bcr >> 17) & 0x7;
> +    if (sh = 7)
> +        size = -1;
> +    else
> +        size = (4 * 1024 * 1024) << sh;
> +
> +    return size;
> +}
> +
> +static void sdram_set_bcr (uint32_t *bcrp, uint32_t bcr, int enabled)
> +{
> +    if (*bcrp & 0x00000001) {
> +        /* Unmap RAM */
> +#ifdef DEBUG_SDRAM
> +        printf("%s: unmap RAM area " PADDRX " " ADDRX "\n",
> +               __func__, sdram_base(*bcrp), sdram_size(*bcrp));
> +#endif
> +        cpu_register_physical_memory(sdram_base(*bcrp), sdram_size(*bcrp),
> +                                     IO_MEM_UNASSIGNED);
> +    }
> +    *bcrp = bcr & 0xFFDEE001;
> +    if (enabled && (bcr & 0x00000001)) {
> +#ifdef DEBUG_SDRAM
> +        printf("%s: Map RAM area " PADDRX " " ADDRX "\n",
> +               __func__, sdram_base(bcr), sdram_size(bcr));
> +#endif
> +        cpu_register_physical_memory(sdram_base(bcr), sdram_size(bcr),
> +                                     sdram_base(bcr) | IO_MEM_RAM);
> +    }
> +}
> +
> +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->bcr[i],
> +                          sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
> +                          1);
> +        } else {
> +            sdram_set_bcr(&sdram->bcr[i], 0x00000000, 0);
> +        }
> +    }
> +}
> +
> +static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram)
> +{
> +    int i;
> +
> +    for (i = 0; i < sdram->nbanks; i++) {
> +#ifdef DEBUG_SDRAM
> +        printf("%s: Unmap RAM area " PADDRX " " ADDRX "\n",
> +               __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
> +#endif
> +        cpu_register_physical_memory(sdram_base(sdram->bcr[i]),
> +                                     sdram_size(sdram->bcr[i]),
> +                                     IO_MEM_UNASSIGNED);
> +    }
> +}
> +
> +static target_ulong dcr_read_sdram (void *opaque, int dcrn)
> +{
> +    ppc4xx_sdram_t *sdram;
> +    target_ulong ret;
> +
> +    sdram = opaque;
> +    switch (dcrn) {
> +    case SDRAM0_CFGADDR:
> +        ret = sdram->addr;
> +        break;
> +    case SDRAM0_CFGDATA:
> +        switch (sdram->addr) {
> +        case 0x00: /* SDRAM_BESR0 */
> +            ret = sdram->besr0;
> +            break;
> +        case 0x08: /* SDRAM_BESR1 */
> +            ret = sdram->besr1;
> +            break;
> +        case 0x10: /* SDRAM_BEAR */
> +            ret = sdram->bear;
> +            break;
> +        case 0x20: /* SDRAM_CFG */
> +            ret = sdram->cfg;
> +            break;
> +        case 0x24: /* SDRAM_STATUS */
> +            ret = sdram->status;
> +            break;
> +        case 0x30: /* SDRAM_RTR */
> +            ret = sdram->rtr;
> +            break;
> +        case 0x34: /* SDRAM_PMIT */
> +            ret = sdram->pmit;
> +            break;
> +        case 0x40: /* SDRAM_B0CR */
> +            ret = sdram->bcr[0];
> +            break;
> +        case 0x44: /* SDRAM_B1CR */
> +            ret = sdram->bcr[1];
> +            break;
> +        case 0x48: /* SDRAM_B2CR */
> +            ret = sdram->bcr[2];
> +            break;
> +        case 0x4C: /* SDRAM_B3CR */
> +            ret = sdram->bcr[3];
> +            break;
> +        case 0x80: /* SDRAM_TR */
> +            ret = -1; /* ? */
> +            break;
> +        case 0x94: /* SDRAM_ECCCFG */
> +            ret = sdram->ecccfg;
> +            break;
> +        case 0x98: /* SDRAM_ECCESR */
> +            ret = sdram->eccesr;
> +            break;
> +        default: /* Error */
> +            ret = -1;
> +            break;
> +        }
> +        break;
> +    default:
> +        /* Avoid gcc warning */
> +        ret = 0x00000000;
> +        break;
> +    }
> +
> +    return ret;
> +}
> +
> +static void dcr_write_sdram (void *opaque, int dcrn, target_ulong val)
> +{
> +    ppc4xx_sdram_t *sdram;
> +
> +    sdram = opaque;
> +    switch (dcrn) {
> +    case SDRAM0_CFGADDR:
> +        sdram->addr = val;
> +        break;
> +    case SDRAM0_CFGDATA:
> +        switch (sdram->addr) {
> +        case 0x00: /* SDRAM_BESR0 */
> +            sdram->besr0 &= ~val;
> +            break;
> +        case 0x08: /* SDRAM_BESR1 */
> +            sdram->besr1 &= ~val;
> +            break;
> +        case 0x10: /* SDRAM_BEAR */
> +            sdram->bear = val;
> +            break;
> +        case 0x20: /* SDRAM_CFG */
> +            val &= 0xFFE00000;
> +            if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
> +#ifdef DEBUG_SDRAM
> +                printf("%s: enable SDRAM controller\n", __func__);
> +#endif
> +                /* validate all RAM mappings */
> +                sdram_map_bcr(sdram);
> +                sdram->status &= ~0x80000000;
> +            } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
> +#ifdef DEBUG_SDRAM
> +                printf("%s: disable SDRAM controller\n", __func__);
> +#endif
> +                /* invalidate all RAM mappings */
> +                sdram_unmap_bcr(sdram);
> +                sdram->status |= 0x80000000;
> +            }
> +            if (!(sdram->cfg & 0x40000000) && (val & 0x40000000))
> +                sdram->status |= 0x40000000;
> +            else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000))
> +                sdram->status &= ~0x40000000;
> +            sdram->cfg = val;
> +            break;
> +        case 0x24: /* SDRAM_STATUS */
> +            /* Read-only register */
> +            break;
> +        case 0x30: /* SDRAM_RTR */
> +            sdram->rtr = val & 0x3FF80000;
> +            break;
> +        case 0x34: /* SDRAM_PMIT */
> +            sdram->pmit = (val & 0xF8000000) | 0x07C00000;
> +            break;
> +        case 0x40: /* SDRAM_B0CR */
> +            sdram_set_bcr(&sdram->bcr[0], val, sdram->cfg & 0x80000000);
> +            break;
> +        case 0x44: /* SDRAM_B1CR */
> +            sdram_set_bcr(&sdram->bcr[1], val, sdram->cfg & 0x80000000);
> +            break;
> +        case 0x48: /* SDRAM_B2CR */
> +            sdram_set_bcr(&sdram->bcr[2], val, sdram->cfg & 0x80000000);
> +            break;
> +        case 0x4C: /* SDRAM_B3CR */
> +            sdram_set_bcr(&sdram->bcr[3], val, sdram->cfg & 0x80000000);
> +            break;
> +        case 0x80: /* SDRAM_TR */
> +            sdram->tr = val & 0x018FC01F;
> +            break;
> +        case 0x94: /* SDRAM_ECCCFG */
> +            sdram->ecccfg = val & 0x00F00000;
> +            break;
> +        case 0x98: /* SDRAM_ECCESR */
> +            val &= 0xFFF0F000;
> +            if (sdram->eccesr = 0 && val != 0)
> +                qemu_irq_raise(sdram->irq);
> +            else if (sdram->eccesr != 0 && val = 0)
> +                qemu_irq_lower(sdram->irq);
> +            sdram->eccesr = val;
> +            break;
> +        default: /* Error */
> +            break;
> +        }
> +        break;
> +    }
> +}
> +
> +static void sdram_reset (void *opaque)
> +{
> +    ppc4xx_sdram_t *sdram;
> +
> +    sdram = opaque;
> +    sdram->addr = 0x00000000;
> +    sdram->bear = 0x00000000;
> +    sdram->besr0 = 0x00000000; /* No error */
> +    sdram->besr1 = 0x00000000; /* No error */
> +    sdram->cfg = 0x00000000;
> +    sdram->ecccfg = 0x00000000; /* No ECC */
> +    sdram->eccesr = 0x00000000; /* No error */
> +    sdram->pmit = 0x07C00000;
> +    sdram->rtr = 0x05F00000;
> +    sdram->tr = 0x00854009;
> +    /* We pre-initialize RAM banks */
> +    sdram->status = 0x00000000;
> +    sdram->cfg = 0x00800000;
> +    sdram_unmap_bcr(sdram);
> +}
> +
> +void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
> +                        target_phys_addr_t *ram_bases,
> +                        target_phys_addr_t *ram_sizes,
> +                        int do_init)
> +{
> +    ppc4xx_sdram_t *sdram;
> +
> +    sdram = qemu_mallocz(sizeof(ppc4xx_sdram_t));
> +    if (sdram != NULL) {
> +        sdram->irq = irq;
> +        sdram->nbanks = nbanks;
> +        memset(sdram->ram_bases, 0, 4 * sizeof(target_phys_addr_t));
> +        memcpy(sdram->ram_bases, ram_bases,
> +               nbanks * sizeof(target_phys_addr_t));
> +        memset(sdram->ram_sizes, 0, 4 * sizeof(target_phys_addr_t));
> +        memcpy(sdram->ram_sizes, ram_sizes,
> +               nbanks * sizeof(target_phys_addr_t));
> +        sdram_reset(sdram);
> +        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);
> +    }
> +}
> -- 
> 1.5.6.5
> 
> 
> 
> 

-- 
  .''`.  Aurelien Jarno	            | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   aurel32@debian.org         | aurelien@aurel32.net
   `-    people.debian.org/~aurel32 | www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 2/8] Rename ppc405_sdram_init() to ppc4xx_sdram_init()
  2008-12-15 16:44     ` Hollis Blanchard
@ 2008-12-15 23:14       ` Aurelien Jarno
  -1 siblings, 0 replies; 31+ messages in thread
From: Aurelien Jarno @ 2008-12-15 23:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

On Mon, Dec 15, 2008 at 10:44:13AM -0600, Hollis Blanchard wrote:
> The SDRAM controller is shared across almost all 405 and 440 embedded
> processors, with some slight differences such as the sizes supported for each
> memory bank.
> 
> Rename only; no functional changes.
> 
> Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>

Thanks, applied.

> ---
>  hw/ppc405_uc.c   |    4 ++--
>  hw/ppc4xx.h      |    2 +-
>  hw/ppc4xx_devs.c |    2 +-
>  3 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
> index 7e7fb38..9275416 100644
> --- a/hw/ppc405_uc.c
> +++ b/hw/ppc405_uc.c
> @@ -2230,7 +2230,7 @@ CPUState *ppc405cr_init (target_phys_addr_t ram_bases[4],
>      pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
>      *picp = pic;
>      /* SDRAM controller */
> -    ppc405_sdram_init(env, pic[14], 1, ram_bases, ram_sizes, do_init);
> +    ppc4xx_sdram_init(env, pic[14], 1, ram_bases, ram_sizes, do_init);
>      offset = 0;
>      for (i = 0; i < 4; i++)
>          offset += ram_sizes[i];
> @@ -2588,7 +2588,7 @@ CPUState *ppc405ep_init (target_phys_addr_t ram_bases[2],
>      *picp = pic;
>      /* SDRAM controller */
>  	/* XXX 405EP has no ECC interrupt */
> -    ppc405_sdram_init(env, pic[17], 2, ram_bases, ram_sizes, do_init);
> +    ppc4xx_sdram_init(env, pic[17], 2, ram_bases, ram_sizes, do_init);
>      offset = 0;
>      for (i = 0; i < 2; i++)
>          offset += ram_sizes[i];
> diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h
> index 8c2878a..3b98662 100644
> --- a/hw/ppc4xx.h
> +++ b/hw/ppc4xx.h
> @@ -48,7 +48,7 @@ enum {
>  qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
>                         uint32_t dcr_base, int has_ssr, int has_vr);
>  
> -void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
> +void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
>                          target_phys_addr_t *ram_bases,
>                          target_phys_addr_t *ram_sizes,
>                          int do_init);
> diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
> index c6be2d6..2d27e23 100644
> --- a/hw/ppc4xx_devs.c
> +++ b/hw/ppc4xx_devs.c
> @@ -846,7 +846,7 @@ static void sdram_reset (void *opaque)
>      sdram_unmap_bcr(sdram);
>  }
>  
> -void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
> +void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
>                          target_phys_addr_t *ram_bases,
>                          target_phys_addr_t *ram_sizes,
>                          int do_init)
> -- 
> 1.5.6.5
> 
> 
> 
> 

-- 
  .''`.  Aurelien Jarno	            | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   aurel32@debian.org         | aurelien@aurel32.net
   `-    people.debian.org/~aurel32 | www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 2/8] Rename ppc405_sdram_init() to
@ 2008-12-15 23:14       ` Aurelien Jarno
  0 siblings, 0 replies; 31+ messages in thread
From: Aurelien Jarno @ 2008-12-15 23:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

On Mon, Dec 15, 2008 at 10:44:13AM -0600, Hollis Blanchard wrote:
> The SDRAM controller is shared across almost all 405 and 440 embedded
> processors, with some slight differences such as the sizes supported for each
> memory bank.
> 
> Rename only; no functional changes.
> 
> Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>

Thanks, applied.

> ---
>  hw/ppc405_uc.c   |    4 ++--
>  hw/ppc4xx.h      |    2 +-
>  hw/ppc4xx_devs.c |    2 +-
>  3 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
> index 7e7fb38..9275416 100644
> --- a/hw/ppc405_uc.c
> +++ b/hw/ppc405_uc.c
> @@ -2230,7 +2230,7 @@ CPUState *ppc405cr_init (target_phys_addr_t ram_bases[4],
>      pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
>      *picp = pic;
>      /* SDRAM controller */
> -    ppc405_sdram_init(env, pic[14], 1, ram_bases, ram_sizes, do_init);
> +    ppc4xx_sdram_init(env, pic[14], 1, ram_bases, ram_sizes, do_init);
>      offset = 0;
>      for (i = 0; i < 4; i++)
>          offset += ram_sizes[i];
> @@ -2588,7 +2588,7 @@ CPUState *ppc405ep_init (target_phys_addr_t ram_bases[2],
>      *picp = pic;
>      /* SDRAM controller */
>  	/* XXX 405EP has no ECC interrupt */
> -    ppc405_sdram_init(env, pic[17], 2, ram_bases, ram_sizes, do_init);
> +    ppc4xx_sdram_init(env, pic[17], 2, ram_bases, ram_sizes, do_init);
>      offset = 0;
>      for (i = 0; i < 2; i++)
>          offset += ram_sizes[i];
> diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h
> index 8c2878a..3b98662 100644
> --- a/hw/ppc4xx.h
> +++ b/hw/ppc4xx.h
> @@ -48,7 +48,7 @@ enum {
>  qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
>                         uint32_t dcr_base, int has_ssr, int has_vr);
>  
> -void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
> +void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
>                          target_phys_addr_t *ram_bases,
>                          target_phys_addr_t *ram_sizes,
>                          int do_init);
> diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
> index c6be2d6..2d27e23 100644
> --- a/hw/ppc4xx_devs.c
> +++ b/hw/ppc4xx_devs.c
> @@ -846,7 +846,7 @@ static void sdram_reset (void *opaque)
>      sdram_unmap_bcr(sdram);
>  }
>  
> -void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
> +void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
>                          target_phys_addr_t *ram_bases,
>                          target_phys_addr_t *ram_sizes,
>                          int do_init)
> -- 
> 1.5.6.5
> 
> 
> 
> 

-- 
  .''`.  Aurelien Jarno	            | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   aurel32@debian.org         | aurelien@aurel32.net
   `-    people.debian.org/~aurel32 | www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 3/8] Create a helper function to allow more flexible RAM allocation for PPC 4xx
  2008-12-15 16:44     ` Hollis Blanchard
@ 2008-12-15 23:18       ` Aurelien Jarno
  -1 siblings, 0 replies; 31+ messages in thread
From: Aurelien Jarno @ 2008-12-15 23:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

On Mon, Dec 15, 2008 at 10:44:14AM -0600, Hollis Blanchard wrote:
> The 4xx SDRAM controller supports a small number of banks, and each bank must
> be one of a small set of sizes. The number of banks and the supported sizes
> varies by SoC.
> 
> This function uses the user-specified RAM size to fill in the "ram_bases" and
> "ram_sizes" arrays required by ppc4xx_sdram_init().
> 
> Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>

Applied, thanks.

> ---
>  hw/ppc4xx.h      |    5 +++++
>  hw/ppc4xx_devs.c |   42 ++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 47 insertions(+), 0 deletions(-)
> 
> diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h
> index 3b98662..7832cd9 100644
> --- a/hw/ppc4xx.h
> +++ b/hw/ppc4xx.h
> @@ -48,6 +48,11 @@ enum {
>  qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
>                         uint32_t dcr_base, int has_ssr, int has_vr);
>  
> +ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
> +                               target_phys_addr_t ram_bases[],
> +                               target_phys_addr_t ram_sizes[],
> +                               const unsigned int sdram_bank_sizes[]);
> +
>  void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
>                          target_phys_addr_t *ram_bases,
>                          target_phys_addr_t *ram_sizes,
> diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
> index 2d27e23..939e066 100644
> --- a/hw/ppc4xx_devs.c
> +++ b/hw/ppc4xx_devs.c
> @@ -873,3 +873,45 @@ void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
>              sdram_map_bcr(sdram);
>      }
>  }
> +
> +/* Fill in consecutive SDRAM banks with 'ram_size' bytes of memory.
> + *
> + * sdram_bank_sizes[] must be 0-terminated.
> + *
> + * The 4xx SDRAM controller supports a small number of banks, and each bank
> + * must be one of a small set of sizes. The number of banks and the supported
> + * sizes varies by SoC. */
> +ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
> +                               target_phys_addr_t ram_bases[],
> +                               target_phys_addr_t ram_sizes[],
> +                               const unsigned int sdram_bank_sizes[])
> +{
> +    ram_addr_t ram_end = 0;
> +    int i;
> +    int j;
> +
> +    for (i = 0; i < nr_banks; i++) {
> +        for (j = 0; sdram_bank_sizes[j] != 0; j++) {
> +            unsigned int bank_size = sdram_bank_sizes[j];
> +
> +            if (bank_size <= ram_size) {
> +                ram_bases[i] = ram_end;
> +                ram_sizes[i] = bank_size;
> +                ram_end += bank_size;
> +                ram_size -= bank_size;
> +                break;
> +            }
> +        }
> +
> +        if (!ram_size) {
> +            /* No need to use the remaining banks. */
> +            break;
> +        }
> +    }
> +
> +    if (ram_size)
> +        printf("Truncating memory to %d MiB to fit SDRAM controller limits.\n",
> +               (int)(ram_end >> 20));
> +
> +    return ram_end;
> +}
> -- 
> 1.5.6.5
> 
> 
> 
> 

-- 
  .''`.  Aurelien Jarno	            | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   aurel32@debian.org         | aurelien@aurel32.net
   `-    people.debian.org/~aurel32 | www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 3/8] Create a helper function to allow more flexible RAM allocation for PPC
@ 2008-12-15 23:18       ` Aurelien Jarno
  0 siblings, 0 replies; 31+ messages in thread
From: Aurelien Jarno @ 2008-12-15 23:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

On Mon, Dec 15, 2008 at 10:44:14AM -0600, Hollis Blanchard wrote:
> The 4xx SDRAM controller supports a small number of banks, and each bank must
> be one of a small set of sizes. The number of banks and the supported sizes
> varies by SoC.
> 
> This function uses the user-specified RAM size to fill in the "ram_bases" and
> "ram_sizes" arrays required by ppc4xx_sdram_init().
> 
> Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>

Applied, thanks.

> ---
>  hw/ppc4xx.h      |    5 +++++
>  hw/ppc4xx_devs.c |   42 ++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 47 insertions(+), 0 deletions(-)
> 
> diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h
> index 3b98662..7832cd9 100644
> --- a/hw/ppc4xx.h
> +++ b/hw/ppc4xx.h
> @@ -48,6 +48,11 @@ enum {
>  qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
>                         uint32_t dcr_base, int has_ssr, int has_vr);
>  
> +ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
> +                               target_phys_addr_t ram_bases[],
> +                               target_phys_addr_t ram_sizes[],
> +                               const unsigned int sdram_bank_sizes[]);
> +
>  void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
>                          target_phys_addr_t *ram_bases,
>                          target_phys_addr_t *ram_sizes,
> diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
> index 2d27e23..939e066 100644
> --- a/hw/ppc4xx_devs.c
> +++ b/hw/ppc4xx_devs.c
> @@ -873,3 +873,45 @@ void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
>              sdram_map_bcr(sdram);
>      }
>  }
> +
> +/* Fill in consecutive SDRAM banks with 'ram_size' bytes of memory.
> + *
> + * sdram_bank_sizes[] must be 0-terminated.
> + *
> + * The 4xx SDRAM controller supports a small number of banks, and each bank
> + * must be one of a small set of sizes. The number of banks and the supported
> + * sizes varies by SoC. */
> +ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
> +                               target_phys_addr_t ram_bases[],
> +                               target_phys_addr_t ram_sizes[],
> +                               const unsigned int sdram_bank_sizes[])
> +{
> +    ram_addr_t ram_end = 0;
> +    int i;
> +    int j;
> +
> +    for (i = 0; i < nr_banks; i++) {
> +        for (j = 0; sdram_bank_sizes[j] != 0; j++) {
> +            unsigned int bank_size = sdram_bank_sizes[j];
> +
> +            if (bank_size <= ram_size) {
> +                ram_bases[i] = ram_end;
> +                ram_sizes[i] = bank_size;
> +                ram_end += bank_size;
> +                ram_size -= bank_size;
> +                break;
> +            }
> +        }
> +
> +        if (!ram_size) {
> +            /* No need to use the remaining banks. */
> +            break;
> +        }
> +    }
> +
> +    if (ram_size)
> +        printf("Truncating memory to %d MiB to fit SDRAM controller limits.\n",
> +               (int)(ram_end >> 20));
> +
> +    return ram_end;
> +}
> -- 
> 1.5.6.5
> 
> 
> 
> 

-- 
  .''`.  Aurelien Jarno	            | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   aurel32@debian.org         | aurelien@aurel32.net
   `-    people.debian.org/~aurel32 | www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 5/8] Implement device tree support needed for Bamboo emulation
  2008-12-15 16:44     ` Hollis Blanchard
@ 2008-12-15 23:20       ` Aurelien Jarno
  -1 siblings, 0 replies; 31+ messages in thread
From: Aurelien Jarno @ 2008-12-15 23:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

On Mon, Dec 15, 2008 at 10:44:16AM -0600, Hollis Blanchard wrote:
> To implement the -kernel, -initrd, and -append options, 4xx board emulation
> must load the guest kernel as if firmware had loaded it. Where u-boot would be
> the firmware, we must load the flat device tree into memory and set key fields
> such as /chosen/bootargs.
> 
> This patch introduces a dependency on libfdt for flat device tree support.
> 
> Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
> ---
>  Makefile.target |    4 ++
>  configure       |   18 +++++++++
>  device_tree.c   |  114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  device_tree.h   |   26 ++++++++++++
>  libfdt_env.h    |   41 ++++++++++++++++++++
>  5 files changed, 203 insertions(+), 0 deletions(-)
>  create mode 100644 device_tree.c
>  create mode 100644 device_tree.h
>  create mode 100644 libfdt_env.h
> 
> diff --git a/Makefile.target b/Makefile.target
> index 8229b4f..d80ce2c 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -655,6 +655,10 @@ OBJS+= heathrow_pic.o grackle_pci.o ppc_oldworld.o
>  OBJS+= unin_pci.o ppc_chrp.o
>  # PowerPC 4xx boards
>  OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
> +ifdef FDT_LIBS
> +OBJS+= device_tree.o
> +LIBS+= $(FDT_LIBS)
> +endif
>  # virtio support
>  OBJS+= virtio.o virtio-blk.o virtio-balloon.o
>  endif
> diff --git a/configure b/configure
> index 455dbef..562f113 100755
> --- a/configure
> +++ b/configure
> @@ -119,6 +119,7 @@ kvm="yes"
>  kerneldir=""
>  aix="no"
>  blobs="yes"
> +fdt="yes"
>  
>  # OS specific
>  targetos=`uname -s`
> @@ -966,6 +967,18 @@ if $cc $ARCH_CFLAGS -o $TMPE $TMPC > /dev/null 2> /dev/null ; then
>    iovec=yes
>  fi
>  
> +##########################################
> +# fdt probe
> +if test "$fdt" = "yes" ; then
> +    fdt=no
> +    cat > $TMPC << EOF
> +int main(void) { return 0; }
> +EOF
> +  if $cc $ARCH_CFLAGS -o $TMPE ${OS_CFLAGS} $TMPC -lfdt 2> /dev/null ; then
> +    fdt=yes
> +  fi
> +fi
> +
>  # Check if tools are available to build documentation.
>  if [ -x "`which texi2html 2>/dev/null`" ] && \
>     [ -x "`which pod2man 2>/dev/null`" ]; then
> @@ -1061,6 +1074,7 @@ echo "vde support       $vde"
>  echo "AIO support       $aio"
>  echo "Install blobs     $blobs"
>  echo "KVM support       $kvm"
> +echo "fdt support       $kvm"

This looks wrong, should probably be $fdt.
  
>  if test $sdl_too_old = "yes"; then
>  echo "-> Your SDL version is too old - please upgrade to have SDL support"
> @@ -1350,6 +1364,10 @@ fi
>  if test "$iovec" = "yes" ; then
>    echo "#define HAVE_IOVEC 1" >> $config_h
>  fi
> +if test "$fdt" = "yes" ; then
> +  echo "#define HAVE_FDT 1" >> $config_h
> +  echo "FDT_LIBS=-lfdt" >> $config_mak
> +fi
>  
>  # XXX: suppress that
>  if [ "$bsd" = "yes" ] ; then
> diff --git a/device_tree.c b/device_tree.c
> new file mode 100644
> index 0000000..2238682
> --- /dev/null
> +++ b/device_tree.c
> @@ -0,0 +1,114 @@
> +/*
> + * Functions to help device tree manipulation using libfdt.
> + * It also provides functions to read entries from device tree proc
> + * interface.
> + *
> + * Copyright 2008 IBM Corporation.
> + * Authors: Jerone Young <jyoung5@us.ibm.com>
> + *          Hollis Blanchard <hollisb@us.ibm.com>
> + *
> + * This work is licensed under the GNU GPL license version 2 or later.
> + *
> + */
> +
> +#include <stdio.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +
> +#include "config.h"
> +#include "qemu-common.h"
> +#include "sysemu.h"
> +#include "device_tree.h"
> +
> +#include <libfdt.h>
> +
> +void *load_device_tree(const char *filename_path, void *load_addr)
> +{
> +    int dt_file_size;
> +    int dt_file_load_size;
> +    int new_dt_size;
> +    int ret;
> +    void *dt_file = NULL;
> +    void *fdt;
> +
> +    dt_file_size = get_image_size(filename_path);
> +    if (dt_file_size < 0) {
> +        printf("Unable to get size of device tree file '%s'\n",
> +            filename_path);
> +        goto fail;
> +    }
> +
> +    /* First allocate space in qemu for device tree */
> +    dt_file = qemu_mallocz(dt_file_size);
> +    if (dt_file == NULL) {
> +        printf("Unable to allocate memory in qemu for device tree\n");
> +        goto fail;
> +    }
> +
> +    dt_file_load_size = load_image(filename_path, dt_file);
> +
> +    /* Second we place new copy of 2x size in guest memory
> +     * This give us enough room for manipulation.
> +     */
> +    new_dt_size = dt_file_size * 2;
> +
> +    fdt = load_addr;
> +    ret = fdt_open_into(dt_file, fdt, new_dt_size);
> +    if (ret) {
> +        printf("Unable to copy device tree in memory\n");
> +        goto fail;
> +    }
> +
> +    /* Check sanity of device tree */
> +    if (fdt_check_header(fdt)) {
> +        printf ("Device tree file loaded into memory is invalid: %s\n",
> +            filename_path);
> +        goto fail;
> +    }
> +    /* free qemu memory with old device tree */
> +    qemu_free(dt_file);
> +    return fdt;
> +
> +fail:
> +    qemu_free(dt_file);
> +    return NULL;
> +}
> +
> +int qemu_devtree_setprop(void *fdt, const char *node_path,
> +                         const char *property, uint32_t *val_array, int size)
> +{
> +    int offset;
> +
> +    offset = fdt_path_offset(fdt, node_path);
> +    if (offset < 0)
> +        return offset;
> +
> +    return fdt_setprop(fdt, offset, property, val_array, size);
> +}
> +
> +int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
> +                              const char *property, uint32_t val)
> +{
> +    int offset;
> +
> +    offset = fdt_path_offset(fdt, node_path);
> +    if (offset < 0)
> +        return offset;
> +
> +    return fdt_setprop_cell(fdt, offset, property, val);
> +}
> +
> +int qemu_devtree_setprop_string(void *fdt, const char *node_path,
> +                                const char *property, const char *string)
> +{
> +    int offset;
> +
> +    offset = fdt_path_offset(fdt, node_path);
> +    if (offset < 0)
> +        return offset;
> +
> +    return fdt_setprop_string(fdt, offset, property, string);
> +}
> diff --git a/device_tree.h b/device_tree.h
> new file mode 100644
> index 0000000..9e6ef3d
> --- /dev/null
> +++ b/device_tree.h
> @@ -0,0 +1,26 @@
> +/*
> + * Header with function prototypes to help device tree manipulation using
> + * libfdt. It also provides functions to read entries from device tree proc
> + * interface.
> + *
> + * Copyright 2008 IBM Corporation.
> + * Authors: Jerone Young <jyoung5@us.ibm.com>
> + *          Hollis Blanchard <hollisb@us.ibm.com>
> + *
> + * This work is licensed under the GNU GPL license version 2 or later.
> + *
> + */
> +
> +#ifndef __DEVICE_TREE_H__
> +#define __DEVICE_TREE_H__
> +
> +void *load_device_tree(const char *filename_path, void *load_addr);
> +
> +int qemu_devtree_setprop(void *fdt, const char *node_path,
> +                         const char *property, uint32_t *val_array, int size);
> +int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
> +                              const char *property, uint32_t val);
> +int qemu_devtree_setprop_string(void *fdt, const char *node_path,
> +                                const char *property, const char *string);
> +
> +#endif /* __DEVICE_TREE_H__ */
> diff --git a/libfdt_env.h b/libfdt_env.h
> new file mode 100644
> index 0000000..e154b8e
> --- /dev/null
> +++ b/libfdt_env.h
> @@ -0,0 +1,41 @@
> +/*
> + * 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, write to the Free Software
> + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
> + *
> + * Copyright IBM Corp. 2008
> + * Authors: Hollis Blanchard <hollisb@us.ibm.com>
> + *
> + */
> +
> +#ifndef _LIBFDT_ENV_H
> +#define _LIBFDT_ENV_H
> +
> +#include <stddef.h>
> +#include <stdint.h>
> +#include <string.h>
> +#include <endian.h>
> +#include <byteswap.h>
> +
> +#if __BYTE_ORDER == __BIG_ENDIAN
> +#define fdt32_to_cpu(x)		(x)
> +#define cpu_to_fdt32(x)		(x)
> +#define fdt64_to_cpu(x)		(x)
> +#define cpu_to_fdt64(x)		(x)
> +#else
> +#define fdt32_to_cpu(x)		(bswap_32((x)))
> +#define cpu_to_fdt32(x)		(bswap_32((x)))
> +#define fdt64_to_cpu(x)		(bswap_64((x)))
> +#define cpu_to_fdt64(x)		(bswap_64((x)))
> +#endif
> +
> +#endif /* _LIBFDT_ENV_H */
> -- 
> 1.5.6.5
> 
> 
> 
> 

-- 
  .''`.  Aurelien Jarno	            | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   aurel32@debian.org         | aurelien@aurel32.net
   `-    people.debian.org/~aurel32 | www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 5/8] Implement device tree support needed for Bamboo emulation
@ 2008-12-15 23:20       ` Aurelien Jarno
  0 siblings, 0 replies; 31+ messages in thread
From: Aurelien Jarno @ 2008-12-15 23:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm-ppc

On Mon, Dec 15, 2008 at 10:44:16AM -0600, Hollis Blanchard wrote:
> To implement the -kernel, -initrd, and -append options, 4xx board emulation
> must load the guest kernel as if firmware had loaded it. Where u-boot would be
> the firmware, we must load the flat device tree into memory and set key fields
> such as /chosen/bootargs.
> 
> This patch introduces a dependency on libfdt for flat device tree support.
> 
> Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
> ---
>  Makefile.target |    4 ++
>  configure       |   18 +++++++++
>  device_tree.c   |  114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  device_tree.h   |   26 ++++++++++++
>  libfdt_env.h    |   41 ++++++++++++++++++++
>  5 files changed, 203 insertions(+), 0 deletions(-)
>  create mode 100644 device_tree.c
>  create mode 100644 device_tree.h
>  create mode 100644 libfdt_env.h
> 
> diff --git a/Makefile.target b/Makefile.target
> index 8229b4f..d80ce2c 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -655,6 +655,10 @@ OBJS+= heathrow_pic.o grackle_pci.o ppc_oldworld.o
>  OBJS+= unin_pci.o ppc_chrp.o
>  # PowerPC 4xx boards
>  OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
> +ifdef FDT_LIBS
> +OBJS+= device_tree.o
> +LIBS+= $(FDT_LIBS)
> +endif
>  # virtio support
>  OBJS+= virtio.o virtio-blk.o virtio-balloon.o
>  endif
> diff --git a/configure b/configure
> index 455dbef..562f113 100755
> --- a/configure
> +++ b/configure
> @@ -119,6 +119,7 @@ kvm="yes"
>  kerneldir=""
>  aix="no"
>  blobs="yes"
> +fdt="yes"
>  
>  # OS specific
>  targetos=`uname -s`
> @@ -966,6 +967,18 @@ if $cc $ARCH_CFLAGS -o $TMPE $TMPC > /dev/null 2> /dev/null ; then
>    iovec=yes
>  fi
>  
> +##########################################
> +# fdt probe
> +if test "$fdt" = "yes" ; then
> +    fdt=no
> +    cat > $TMPC << EOF
> +int main(void) { return 0; }
> +EOF
> +  if $cc $ARCH_CFLAGS -o $TMPE ${OS_CFLAGS} $TMPC -lfdt 2> /dev/null ; then
> +    fdt=yes
> +  fi
> +fi
> +
>  # Check if tools are available to build documentation.
>  if [ -x "`which texi2html 2>/dev/null`" ] && \
>     [ -x "`which pod2man 2>/dev/null`" ]; then
> @@ -1061,6 +1074,7 @@ echo "vde support       $vde"
>  echo "AIO support       $aio"
>  echo "Install blobs     $blobs"
>  echo "KVM support       $kvm"
> +echo "fdt support       $kvm"

This looks wrong, should probably be $fdt.
  
>  if test $sdl_too_old = "yes"; then
>  echo "-> Your SDL version is too old - please upgrade to have SDL support"
> @@ -1350,6 +1364,10 @@ fi
>  if test "$iovec" = "yes" ; then
>    echo "#define HAVE_IOVEC 1" >> $config_h
>  fi
> +if test "$fdt" = "yes" ; then
> +  echo "#define HAVE_FDT 1" >> $config_h
> +  echo "FDT_LIBS=-lfdt" >> $config_mak
> +fi
>  
>  # XXX: suppress that
>  if [ "$bsd" = "yes" ] ; then
> diff --git a/device_tree.c b/device_tree.c
> new file mode 100644
> index 0000000..2238682
> --- /dev/null
> +++ b/device_tree.c
> @@ -0,0 +1,114 @@
> +/*
> + * Functions to help device tree manipulation using libfdt.
> + * It also provides functions to read entries from device tree proc
> + * interface.
> + *
> + * Copyright 2008 IBM Corporation.
> + * Authors: Jerone Young <jyoung5@us.ibm.com>
> + *          Hollis Blanchard <hollisb@us.ibm.com>
> + *
> + * This work is licensed under the GNU GPL license version 2 or later.
> + *
> + */
> +
> +#include <stdio.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +
> +#include "config.h"
> +#include "qemu-common.h"
> +#include "sysemu.h"
> +#include "device_tree.h"
> +
> +#include <libfdt.h>
> +
> +void *load_device_tree(const char *filename_path, void *load_addr)
> +{
> +    int dt_file_size;
> +    int dt_file_load_size;
> +    int new_dt_size;
> +    int ret;
> +    void *dt_file = NULL;
> +    void *fdt;
> +
> +    dt_file_size = get_image_size(filename_path);
> +    if (dt_file_size < 0) {
> +        printf("Unable to get size of device tree file '%s'\n",
> +            filename_path);
> +        goto fail;
> +    }
> +
> +    /* First allocate space in qemu for device tree */
> +    dt_file = qemu_mallocz(dt_file_size);
> +    if (dt_file = NULL) {
> +        printf("Unable to allocate memory in qemu for device tree\n");
> +        goto fail;
> +    }
> +
> +    dt_file_load_size = load_image(filename_path, dt_file);
> +
> +    /* Second we place new copy of 2x size in guest memory
> +     * This give us enough room for manipulation.
> +     */
> +    new_dt_size = dt_file_size * 2;
> +
> +    fdt = load_addr;
> +    ret = fdt_open_into(dt_file, fdt, new_dt_size);
> +    if (ret) {
> +        printf("Unable to copy device tree in memory\n");
> +        goto fail;
> +    }
> +
> +    /* Check sanity of device tree */
> +    if (fdt_check_header(fdt)) {
> +        printf ("Device tree file loaded into memory is invalid: %s\n",
> +            filename_path);
> +        goto fail;
> +    }
> +    /* free qemu memory with old device tree */
> +    qemu_free(dt_file);
> +    return fdt;
> +
> +fail:
> +    qemu_free(dt_file);
> +    return NULL;
> +}
> +
> +int qemu_devtree_setprop(void *fdt, const char *node_path,
> +                         const char *property, uint32_t *val_array, int size)
> +{
> +    int offset;
> +
> +    offset = fdt_path_offset(fdt, node_path);
> +    if (offset < 0)
> +        return offset;
> +
> +    return fdt_setprop(fdt, offset, property, val_array, size);
> +}
> +
> +int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
> +                              const char *property, uint32_t val)
> +{
> +    int offset;
> +
> +    offset = fdt_path_offset(fdt, node_path);
> +    if (offset < 0)
> +        return offset;
> +
> +    return fdt_setprop_cell(fdt, offset, property, val);
> +}
> +
> +int qemu_devtree_setprop_string(void *fdt, const char *node_path,
> +                                const char *property, const char *string)
> +{
> +    int offset;
> +
> +    offset = fdt_path_offset(fdt, node_path);
> +    if (offset < 0)
> +        return offset;
> +
> +    return fdt_setprop_string(fdt, offset, property, string);
> +}
> diff --git a/device_tree.h b/device_tree.h
> new file mode 100644
> index 0000000..9e6ef3d
> --- /dev/null
> +++ b/device_tree.h
> @@ -0,0 +1,26 @@
> +/*
> + * Header with function prototypes to help device tree manipulation using
> + * libfdt. It also provides functions to read entries from device tree proc
> + * interface.
> + *
> + * Copyright 2008 IBM Corporation.
> + * Authors: Jerone Young <jyoung5@us.ibm.com>
> + *          Hollis Blanchard <hollisb@us.ibm.com>
> + *
> + * This work is licensed under the GNU GPL license version 2 or later.
> + *
> + */
> +
> +#ifndef __DEVICE_TREE_H__
> +#define __DEVICE_TREE_H__
> +
> +void *load_device_tree(const char *filename_path, void *load_addr);
> +
> +int qemu_devtree_setprop(void *fdt, const char *node_path,
> +                         const char *property, uint32_t *val_array, int size);
> +int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
> +                              const char *property, uint32_t val);
> +int qemu_devtree_setprop_string(void *fdt, const char *node_path,
> +                                const char *property, const char *string);
> +
> +#endif /* __DEVICE_TREE_H__ */
> diff --git a/libfdt_env.h b/libfdt_env.h
> new file mode 100644
> index 0000000..e154b8e
> --- /dev/null
> +++ b/libfdt_env.h
> @@ -0,0 +1,41 @@
> +/*
> + * 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, write to the Free Software
> + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
> + *
> + * Copyright IBM Corp. 2008
> + * Authors: Hollis Blanchard <hollisb@us.ibm.com>
> + *
> + */
> +
> +#ifndef _LIBFDT_ENV_H
> +#define _LIBFDT_ENV_H
> +
> +#include <stddef.h>
> +#include <stdint.h>
> +#include <string.h>
> +#include <endian.h>
> +#include <byteswap.h>
> +
> +#if __BYTE_ORDER = __BIG_ENDIAN
> +#define fdt32_to_cpu(x)		(x)
> +#define cpu_to_fdt32(x)		(x)
> +#define fdt64_to_cpu(x)		(x)
> +#define cpu_to_fdt64(x)		(x)
> +#else
> +#define fdt32_to_cpu(x)		(bswap_32((x)))
> +#define cpu_to_fdt32(x)		(bswap_32((x)))
> +#define fdt64_to_cpu(x)		(bswap_64((x)))
> +#define cpu_to_fdt64(x)		(bswap_64((x)))
> +#endif
> +
> +#endif /* _LIBFDT_ENV_H */
> -- 
> 1.5.6.5
> 
> 
> 
> 

-- 
  .''`.  Aurelien Jarno	            | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   aurel32@debian.org         | aurelien@aurel32.net
   `-    people.debian.org/~aurel32 | www.aurel32.net

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

end of thread, other threads:[~2008-12-15 23:20 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-12-15 16:44 [Qemu-devel] KVM PowerPC support Hollis Blanchard
2008-12-15 16:44 ` Hollis Blanchard
2008-12-15 16:44 ` [Qemu-devel] [PATCH 1/8] Move PPC4xx SDRAM controller emulation from ppc405_uc.c to ppc4xx_devs.c Hollis Blanchard
2008-12-15 16:44   ` Hollis Blanchard
2008-12-15 16:44   ` [Qemu-devel] [PATCH 2/8] Rename ppc405_sdram_init() to ppc4xx_sdram_init() Hollis Blanchard
2008-12-15 16:44     ` Hollis Blanchard
2008-12-15 23:14     ` [Qemu-devel] " Aurelien Jarno
2008-12-15 23:14       ` [Qemu-devel] [PATCH 2/8] Rename ppc405_sdram_init() to Aurelien Jarno
2008-12-15 16:44   ` [Qemu-devel] [PATCH 3/8] Create a helper function to allow more flexible RAM allocation for PPC 4xx Hollis Blanchard
2008-12-15 16:44     ` Hollis Blanchard
2008-12-15 23:18     ` [Qemu-devel] " Aurelien Jarno
2008-12-15 23:18       ` [Qemu-devel] [PATCH 3/8] Create a helper function to allow more flexible RAM allocation for PPC Aurelien Jarno
2008-12-15 16:44   ` [Qemu-devel] [PATCH 4/8] kvm: sync vcpu state during initialization Hollis Blanchard
2008-12-15 16:44     ` Hollis Blanchard
2008-12-15 22:20     ` [Qemu-devel] " Anthony Liguori
2008-12-15 22:20       ` Anthony Liguori
2008-12-15 16:44   ` [Qemu-devel] [PATCH 5/8] Implement device tree support needed for Bamboo emulation Hollis Blanchard
2008-12-15 16:44     ` Hollis Blanchard
2008-12-15 23:20     ` [Qemu-devel] " Aurelien Jarno
2008-12-15 23:20       ` Aurelien Jarno
2008-12-15 16:44   ` [Qemu-devel] [PATCH 6/8] Enable KVM for ppcemb Hollis Blanchard
2008-12-15 16:44     ` Hollis Blanchard
2008-12-15 22:24     ` [Qemu-devel] " Anthony Liguori
2008-12-15 22:24       ` Anthony Liguori
2008-12-15 16:44   ` [Qemu-devel] [PATCH 7/8] PowerPC 440EP SoC emulation Hollis Blanchard
2008-12-15 16:44     ` Hollis Blanchard
2008-12-15 16:44   ` [Qemu-devel] [PATCH 8/8] IBM PowerPC 440EP Bamboo reference board emulation Hollis Blanchard
2008-12-15 16:44     ` Hollis Blanchard
2008-12-15 17:03     ` [Qemu-devel] " Paul Brook
2008-12-15 23:14   ` [Qemu-devel] [PATCH 1/8] Move PPC4xx SDRAM controller emulation from ppc405_uc.c to ppc4xx_devs.c Aurelien Jarno
2008-12-15 23:14     ` [Qemu-devel] [PATCH 1/8] Move PPC4xx SDRAM controller Aurelien Jarno

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.