qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/6] kvm/powerpc: Add emulation for MPC85xx in KVM mode
@ 2009-01-22 10:14 Liu Yu
  2009-01-22 10:14 ` [Qemu-devel] [PATCH 1/6] kvm/powerpc: Enable MPIC for MPC85xx platform Liu Yu
  2009-01-22 16:13 ` [Qemu-devel] Re: [PATCH 0/6] kvm/powerpc: Add emulation for MPC85xx in KVM mode Hollis Blanchard
  0 siblings, 2 replies; 17+ messages in thread
From: Liu Yu @ 2009-01-22 10:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: hollisb, kvm-ppc

This patch set enable another KVM PowerPC platform E500.
Like the 440 core, the MMU and a few other bits are not currently
emulated in Qemu itself,
so right now it's only functional in conjunction with KVM.

The emulation of MPC85xx boards (which use E500 as its core) 
can be run on any MPC85xx hosts.
The code has been tested on MPC8544DS and MPC8572DS.

Patch 1: enable the MPIC for MPC85xx platform
Patch 2: add emulation of freescale PCI controller for MPC85xx platform
Patch 3: add IRQ support for E500 core
Patch 4: extern one function for MPC85xx code use
Patch 5: add MPC85xx board emulation
Patch 6: flat device tree of MPC85xx

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

* [Qemu-devel] [PATCH 1/6] kvm/powerpc: Enable MPIC for MPC85xx platform
  2009-01-22 10:14 [Qemu-devel] [PATCH 0/6] kvm/powerpc: Add emulation for MPC85xx in KVM mode Liu Yu
@ 2009-01-22 10:14 ` Liu Yu
  2009-01-22 10:14   ` [Qemu-devel] [PATCH 2/6] kvm/powerpc: Add freescale pci controller's support Liu Yu
  2009-01-22 16:13 ` [Qemu-devel] Re: [PATCH 0/6] kvm/powerpc: Add emulation for MPC85xx in KVM mode Hollis Blanchard
  1 sibling, 1 reply; 17+ messages in thread
From: Liu Yu @ 2009-01-22 10:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Liu Yu, hollisb, kvm-ppc

This patch add MPIC support for MPC85xx platform.

MPIC and OpenPIC have very similar design.
So a lot of code can be reused.

Since no other TCG and KVM platforms uses OpenPIC for now,
the modification makes the code only support MPIC.

Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
 hw/openpic.c |  383 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 hw/openpic.h |   19 +++
 hw/ppc_mac.h |   14 +--
 3 files changed, 388 insertions(+), 28 deletions(-)
 create mode 100644 hw/openpic.h

diff --git a/hw/openpic.c b/hw/openpic.c
index b8da4d7..2b4b9d3 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -35,6 +35,7 @@
 #include "hw.h"
 #include "ppc_mac.h"
 #include "pci.h"
+#include "openpic.h"
 
 //#define DEBUG_OPENPIC
 
@@ -45,7 +46,7 @@
 #endif
 #define ERROR(fmr, args...) do { printf("ERROR: " fmr , ##args); } while (0)
 
-#define USE_MPCxxx /* Intel model is broken, for now */
+#define USE_MPC85xx /* Intel model and mac99 are broken, for now */
 
 #if defined (USE_INTEL_GW80314)
 /* Intel GW80314 I/O Companion chip */
@@ -84,15 +85,6 @@ enum {
 #define OPENPIC_LITTLE_ENDIAN 1
 #define OPENPIC_BIG_ENDIAN    0
 
-#else
-#error "Please select which OpenPic implementation is to be emulated"
-#endif
-
-#if (OPENPIC_BIG_ENDIAN && !TARGET_WORDS_BIGENDIAN) || \
-    (OPENPIC_LITTLE_ENDIAN && TARGET_WORDS_BIGENDIAN)
-#define OPENPIC_SWAP
-#endif
-
 /* Interrupt definitions */
 #define IRQ_FE     (EXT_IRQ)     /* Internal functional IRQ */
 #define IRQ_ERR    (EXT_IRQ + 1) /* Error IRQ */
@@ -105,6 +97,61 @@ enum {
 #define IRQ_MBX0   (IRQ_DBL0 + MAX_DBL) /* First mailbox IRQ */
 #endif
 
+#elif defined(USE_MPC85xx)
+
+#define MPIC_MAP_SIZE	0x40000
+
+#define MAX_CPU     1
+#define MAX_EXT    12
+#define MAX_INT    64
+#define MAX_DBL     0
+#define MAX_MBX     0
+#define MAX_TMR     4
+#define MAX_MSG     4
+#define MAX_MSI     8
+#define MAX_IPI     4
+#define MAX_IRQ    (MAX_EXT + MAX_INT + MAX_TMR + MAX_MSG + MAX_MSI + (MAX_IPI * MAX_CPU))
+
+#define VECTOR_BITS 8
+#define VID         0x0 /* MPIC version ID */
+#define VENI        0x00000000 /* Vendor ID */
+
+enum {
+    IRQ_IPVP = 0,
+    IRQ_IDE,
+};
+
+enum ide_bits {
+    IDR_EP     = 0,
+    IDR_CI0     = 1,
+    IDR_CI1     = 2,
+    IDR_P1     = 30,
+    IDR_P0     = 31,
+};
+
+#define OPENPIC_LITTLE_ENDIAN 0
+#define OPENPIC_BIG_ENDIAN    1
+
+/* Interrupt definitions */
+#define EXT_IRQ		0
+#define INT_IRQ		(EXT_IRQ + MAX_EXT)
+#define TMR_IRQ		(INT_IRQ + MAX_INT)
+#define MSG_IRQ		(TMR_IRQ + MAX_TMR)
+#define MSI_IRQ		(MSG_IRQ + MAX_MSG)
+#define IPI_IRQ		(MSI_IRQ + MAX_MSI)
+
+#define IRQ_IPI0        IPI_IRQ
+#define IRQ_TIM0        TMR_IRQ
+
+#else
+#error "Please select which OpenPic implementation is to be emulated"
+#endif
+
+#if (OPENPIC_BIG_ENDIAN && !TARGET_WORDS_BIGENDIAN) || \
+    (OPENPIC_LITTLE_ENDIAN && TARGET_WORDS_BIGENDIAN)
+#define OPENPIC_SWAP
+#endif
+
 #define BF_WIDTH(_bits_) \
 (((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
 
@@ -157,6 +204,7 @@ enum IPVP_bits {
 #define IPVP_VECTOR(_ipvpr_)   ((_ipvpr_) & IPVP_VECTOR_MASK)
 
 typedef struct IRQ_dst_t {
+    uint32_t tfrr;
     uint32_t pctp; /* CPU current task priority */
     uint32_t pcsr; /* CPU sensitivity register */
     IRQ_queue_t raised;
@@ -200,6 +248,8 @@ typedef struct openpic_t {
 #endif
     /* IRQ out is used when in bypass mode (not implemented) */
     qemu_irq irq_out;
+    void (*reset) (struct openpic_t *);
+    void (*irq_raise) (struct openpic_t *, int, IRQ_src_t *);
 } openpic_t;
 
 static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
@@ -286,7 +336,7 @@ static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
         return;
     }
     DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
-    qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
+    opp->irq_raise(opp, n_CPU, src);
 }
 
 /* update pic state because registers for n_IRQ have changed value */
@@ -551,8 +601,8 @@ static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val)
     case 0x00: /* FREP */
         break;
     case 0x20: /* GLBC */
-        if (val & 0x80000000)
-            openpic_reset(opp);
+        if (val & 0x80000000 && opp->reset)
+            opp->reset(opp);
         opp->glbc = val & ~0x80000000;
 	break;
     case 0x80: /* VENI */
@@ -818,7 +868,7 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val)
              IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
             DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
                     idx, n_IRQ);
-            qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
+            opp->irq_raise(opp, idx, src);
         }
 	break;
     default:
@@ -1001,6 +1051,11 @@ static void openpic_map(PCIDevice *pci_dev, int region_num,
 #endif
 }
 
+static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src)
+{
+    qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
+}
+
 qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
                         qemu_irq **irqs, qemu_irq irq_out)
 {
@@ -1058,9 +1113,307 @@ qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
     for (i = 0; i < nb_cpus; i++)
         opp->dst[i].irqs = irqs[i];
     opp->irq_out = irq_out;
-    openpic_reset(opp);
+
+    opp->irq_raise = openpic_irq_raise;
+    opp->reset = openpic_reset;
+
+    opp->reset(opp);
     if (pmem_index)
         *pmem_index = opp->mem_index;
 
     return qemu_allocate_irqs(openpic_set_irq, opp, MAX_IRQ);
 }
+
+static void mpic_irq_raise(openpic_t *mpp, int n_CPU, IRQ_src_t *src)
+{
+    int n_ci = IDR_CI0 - n_CPU;
+    DPRINTF("%s: cpu:%d irq:%d (testbit idr:%x ci:%d)\n", __func__,
+		    n_CPU, n_IRQ, mpp->src[n_IRQ].ide, n_ci);
+    if(test_bit(&src->ide, n_ci)) {
+        qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
+    }
+    else {
+        qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
+    }
+}
+
+static void mpic_reset (openpic_t *mpp)
+{
+    int i;
+
+    mpp->glbc = 0x80000000;
+    /* Initialise controller registers */
+    mpp->frep = 0x004f0002;
+    mpp->veni = VENI;
+    mpp->pint = 0x00000000;
+    mpp->spve = 0x0000FFFF;
+    /* Initialise IRQ sources */
+    for (i = 0; i < MAX_IRQ; i++) {
+	mpp->src[i].ipvp = 0x80800000;
+	mpp->src[i].ide  = 0x00000001;
+    }
+    /* Initialise IRQ destinations */
+    for (i = 0; i < MAX_CPU; i++) {
+	mpp->dst[i].pctp      = 0x0000000F;
+        mpp->dst[i].tfrr      = 0x00000000;
+	memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t));
+	mpp->dst[i].raised.next = -1;
+	memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
+	mpp->dst[i].servicing.next = -1;
+    }
+    /* Initialise timers */
+    for (i = 0; i < MAX_TMR; i++) {
+	mpp->timers[i].ticc = 0x00000000;
+	mpp->timers[i].tibc = 0x80000000;
+    }
+    /* Go out of RESET state */
+    mpp->glbc = 0x00000000;
+}
+
+static void mpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
+{
+    openpic_t *mpp = opaque;
+    int idx, cpu;
+
+    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
+    if (addr & 0xF)
+        return;
+#if defined MPIC_SWAP
+    val = bswap32(val);
+#endif
+    addr &= 0xFFFF;
+    cpu = addr >> 12;
+    idx = (addr >> 6) & 0x3;
+    switch (addr & 0x30) {
+    case 0x00: /* gtccr */
+        break;
+    case 0x10: /* gtbcr */
+	if ((mpp->timers[idx].ticc & 0x80000000) != 0 &&
+	    (val & 0x80000000) == 0 &&
+            (mpp->timers[idx].tibc & 0x80000000) != 0)
+	    mpp->timers[idx].ticc &= ~0x80000000;
+	mpp->timers[idx].tibc = val;
+	break;
+    case 0x20: /* GTIVPR */
+	write_IRQreg(mpp, TMR_IRQ + idx, IRQ_IPVP, val);
+	break;
+    case 0x30: /* GTIDR & TFRR */
+	if ((addr & 0xF0) == 0xF0)
+            mpp->dst[cpu].tfrr = val;
+	else
+	    write_IRQreg(mpp, TMR_IRQ + idx, IRQ_IDE, val);
+	break;
+    }
+}
+
+static uint32_t mpic_timer_read (void *opaque, uint32_t addr)
+{
+    openpic_t *mpp = opaque;
+    uint32_t retval;
+    int idx, cpu;
+
+    DPRINTF("%s: addr %08x\n", __func__, addr);
+    retval = 0xFFFFFFFF;
+    if (addr & 0xF)
+        return retval;
+    addr &= 0xFFFF;
+    cpu = addr >> 12;
+    idx = (addr >> 6) & 0x3;
+    switch (addr & 0x30) {
+    case 0x00: /* gtccr */
+	retval = mpp->timers[idx].ticc;
+        break;
+    case 0x10: /* gtbcr */
+	retval = mpp->timers[idx].tibc;
+	break;
+    case 0x20: /* TIPV */
+	retval = read_IRQreg(mpp, TMR_IRQ + idx, IRQ_IPVP);
+	break;
+    case 0x30: /* TIDR */
+        if ((addr &0xF0) == 0XF0)
+	    retval = mpp->dst[cpu].tfrr;
+	else
+	    retval = read_IRQreg(mpp, TMR_IRQ + idx, IRQ_IDE);
+	break;
+    }
+    DPRINTF("%s: => %08x\n", __func__, retval);
+#if defined MPIC_SWAP
+    retval = bswap32(retval);
+#endif
+
+    return retval;
+}
+
+static void mpic_src_write (void *opaque, uint32_t addr, uint32_t val)
+{
+    openpic_t *mpp = opaque;
+    int idx;
+
+    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
+    if (addr & 0xF)
+        return;
+#if defined MPIC_SWAP
+    val = tswap32(val);
+#endif
+    addr = addr & 0xFFF0;
+    if (addr < 0x180) {
+	idx = EXT_IRQ;
+    } else if (addr >= 0x200 && addr < 0xa00) {
+	idx = INT_IRQ;
+	addr -= 0x200;
+    } else if (addr >= 0x1600 && addr < 0x1700) {
+	idx = MSG_IRQ;
+	addr -= 0x1600;
+    } else if (addr >= 0x1C00 && addr < 0x1D00) {
+	idx = MSI_IRQ;
+	addr -= 0x1C00;
+    } else {
+	return;
+    }
+    idx += addr >> 5;
+    if (addr & 0x10) {
+        /* EXDE / IFEDE / IEEDE */
+        write_IRQreg(mpp, idx, IRQ_IDE, val);
+    } else {
+        /* EXVP / IFEVP / IEEVP */
+        write_IRQreg(mpp, idx, IRQ_IPVP, val);
+    }
+}
+
+static uint32_t mpic_src_read (void *opaque, uint32_t addr)
+{
+    openpic_t *mpp = opaque;
+    uint32_t retval;
+    int idx;
+
+    DPRINTF("%s: addr %08x\n", __func__, addr);
+    retval = 0xFFFFFFFF;
+    if (addr & 0xF)
+        return retval;
+    addr = addr & 0xFFF0;
+    if (addr < 0x180) {
+	idx = EXT_IRQ;
+    } else if (addr >= 0x200 && addr < 0xa00) {
+	idx = INT_IRQ;
+	addr -= 0x200;
+    } else if (addr >= 0x1600 && addr < 0x1700) {
+	idx = MSG_IRQ;
+	addr -= 0x1600;
+    } else if (addr >= 0x1C00 && addr < 0x1D00) {
+	idx = MSI_IRQ;
+	addr -= 0x1C00;
+    } else {
+	return retval;
+    }
+    idx += addr >> 5;
+    if (addr & 0x10) {
+        /* EXDE / IFEDE / IEEDE */
+        retval = read_IRQreg(mpp, idx, IRQ_IDE);
+    } else {
+        /* EXVP / IFEVP / IEEVP */
+        retval = read_IRQreg(mpp, idx, IRQ_IPVP);
+    }
+    DPRINTF("%s: => %08x\n", __func__, retval);
+#if defined MPIC_SWAP
+    retval = tswap32(retval);
+#endif
+
+    return retval;
+}
+
+static void mpic_writel (void *opaque,
+                            target_phys_addr_t addr, uint32_t val)
+{
+    openpic_t *mpp = opaque;
+
+    addr &= 0x3FFFF;
+    DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val);
+    if (addr < 0x10F0) {
+        /* Global registers */
+        openpic_gbl_write(mpp, addr, val);
+    } else if (addr < 0x10000) {
+        /* Timers registers */
+        mpic_timer_write(mpp, addr, val);
+    } else if (addr < 0x20000) {
+        /* Source registers */
+        mpic_src_write(mpp, addr, val);
+    } else if (addr < 0x30000){
+        /* CPU registers */
+        openpic_cpu_write(mpp, addr, val);
+    } else {
+        DPRINTF("wrong mpic write addr %p\n",addr);
+    }
+}
+
+static uint32_t mpic_readl (void *opaque,target_phys_addr_t addr)
+{
+    openpic_t *mpp = opaque;
+    uint32_t retval = 0;
+
+    addr &= 0x3FFFF;
+    DPRINTF("%s: offset %08x\n", __func__, (int)addr);
+    if (addr < 0x10F0) {
+        /* Global registers */
+	retval = openpic_gbl_read(mpp, addr);
+    } else if (addr < 0x10000) {
+        /* Timers registers */
+        retval = mpic_timer_read(mpp, addr);
+    } else if (addr < 0x20000) {
+        /* Source registers */
+        retval = mpic_src_read(mpp, addr);
+    } else if (addr < 0x30000){
+        /* CPU registers */
+        retval = openpic_cpu_read(mpp, addr);
+    } else {
+        DPRINTF("wrong mpic read addr %p\n",addr);
+    }
+
+    return retval;
+}
+
+static CPUWriteMemoryFunc *mpic_write[] = {
+    &openpic_buggy_write,
+    &openpic_buggy_write,
+    &mpic_writel,
+};
+
+static CPUReadMemoryFunc *mpic_read[] = {
+    &openpic_buggy_read,
+    &openpic_buggy_read,
+    &mpic_readl,
+};
+
+qemu_irq *mpic_init (target_phys_addr_t base, int nb_cpus,
+                        qemu_irq **irqs, qemu_irq irq_out)
+{
+    openpic_t *mpp;
+    int i;
+
+    /* XXX: for now, only one CPU is supported */
+    if (nb_cpus != 1)
+        return NULL;
+
+    mpp = qemu_mallocz(sizeof(openpic_t));
+
+    mpp->mem_index = cpu_register_io_memory(0, mpic_read, mpic_write, mpp);
+    if (mpp->mem_index < 0)
+	goto free;
+    cpu_register_physical_memory(base, MPIC_MAP_SIZE, mpp->mem_index);
+
+    mpp->nb_cpus = nb_cpus;
+
+    for (i = 0; i < nb_cpus; i++)
+        mpp->dst[i].irqs = irqs[i];
+    mpp->irq_out = irq_out;
+
+    mpp->irq_raise = mpic_irq_raise;
+    mpp->reset = mpic_reset;
+
+    mpp->reset(mpp);
+
+    return qemu_allocate_irqs(openpic_set_irq, mpp, MAX_IRQ);
+
+free:
+    qemu_free(mpp);
+    return NULL;
+}
diff --git a/hw/openpic.h b/hw/openpic.h
new file mode 100644
index 0000000..2f85e16
--- /dev/null
+++ b/hw/openpic.h
@@ -0,0 +1,19 @@
+
+#if !defined(OPENPIC_H)
+#define OPENPIC_H
+
+/* OpenPIC have 5 outputs per CPU connected and one IRQ out single output */
+enum {
+    OPENPIC_OUTPUT_INT = 0, /* IRQ                       */
+    OPENPIC_OUTPUT_CINT,    /* critical IRQ              */
+    OPENPIC_OUTPUT_MCK,     /* Machine check event       */
+    OPENPIC_OUTPUT_DEBUG,   /* Inconditional debug event */
+    OPENPIC_OUTPUT_RESET,   /* Core reset event          */
+    OPENPIC_OUTPUT_NB,
+};
+
+qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
+                        qemu_irq **irqs, qemu_irq irq_out);
+qemu_irq *mpic_init (target_phys_addr_t base, int nb_cpus,
+                        qemu_irq **irqs, qemu_irq irq_out);
+#endif /* OPENPIC_H */
diff --git a/hw/ppc_mac.h b/hw/ppc_mac.h
index cc70fb7..bf987b1 100644
--- a/hw/ppc_mac.h
+++ b/hw/ppc_mac.h
@@ -113,17 +113,5 @@ void adb_mouse_init(ADBBusState *bus);
 
 extern ADBBusState adb_bus;
 
-/* openpic.c */
-/* OpenPIC have 5 outputs per CPU connected and one IRQ out single output */
-enum {
-    OPENPIC_OUTPUT_INT = 0, /* IRQ                       */
-    OPENPIC_OUTPUT_CINT,    /* critical IRQ              */
-    OPENPIC_OUTPUT_MCK,     /* Machine check event       */
-    OPENPIC_OUTPUT_DEBUG,   /* Inconditional debug event */
-    OPENPIC_OUTPUT_RESET,   /* Core reset event          */
-    OPENPIC_OUTPUT_NB,
-};
-qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
-                        qemu_irq **irqs, qemu_irq irq_out);
-
+#include "openpic.h"
 #endif /* !defined(__PPC_MAC_H__) */
-- 
1.5.4

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

* [Qemu-devel] [PATCH 2/6] kvm/powerpc: Add freescale pci controller's support
  2009-01-22 10:14 ` [Qemu-devel] [PATCH 1/6] kvm/powerpc: Enable MPIC for MPC85xx platform Liu Yu
@ 2009-01-22 10:14   ` Liu Yu
  2009-01-22 10:14     ` [Qemu-devel] [PATCH 3/6] kvm/powerpc: Add irq support for E500 core Liu Yu
  2009-01-24 16:02     ` [Qemu-devel] [PATCH 2/6] kvm/powerpc: Add freescale pci controller's support Aurelien Jarno
  0 siblings, 2 replies; 17+ messages in thread
From: Liu Yu @ 2009-01-22 10:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Liu Yu, hollisb, kvm-ppc

This patch add the emulation of freescale's pci controller for MPC85xx platform.

Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
 Makefile.target  |    2 +
 hw/ppce500_pci.c |  370 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 372 insertions(+), 0 deletions(-)
 create mode 100644 hw/ppce500_pci.c

diff --git a/Makefile.target b/Makefile.target
index a091ce9..5cae257 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -598,6 +598,8 @@ 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 ppc440_bamboo.o
+# PowerPC E500 boards
+OBJS+= ppce500_pci.o
 ifdef FDT_LIBS
 OBJS+= device_tree.o
 LIBS+= $(FDT_LIBS)
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
new file mode 100644
index 0000000..6325555
--- /dev/null
+++ b/hw/ppce500_pci.c
@@ -0,0 +1,370 @@
+/*
+ * QEMU PowerPC E500 embedded processors pci controller emulation
+ *
+ * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Yu Liu,     <yu.liu@freescale.com>
+ *
+ * This file is derived from hw/ppc4xx_pci.c,
+ * the copyright for that material belongs to the original owners.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of  the GNU General  Public License as published by
+ * the Free Software Foundation;  either version 2 of the  License, or
+ * (at your option) any later version.
+ */
+
+#include "hw.h"
+#include "ppc.h"
+#include "ppce500.h"
+typedef target_phys_addr_t pci_addr_t;
+#include "pci.h"
+#include "pci_host.h"
+#include "bswap.h"
+#include "qemu-log.h"
+
+#ifdef DEBUG_PCI
+#define pci_debug(fmt, arg...) fprintf(stderr, fmt, ##arg)
+#else
+#define pci_debug(fmt, arg...)
+#endif
+
+#define PCIE500_CFGADDR       0x0
+#define PCIE500_CFGDATA       0x4
+#define PCIE500_REG_BASE      0xC00
+#define PCIE500_REG_SIZE      (0x1000 - PCIE500_REG_BASE)
+
+#define PPCE500_PCI_CONFIG_ADDR		0x0
+#define PPCE500_PCI_CONFIG_DATA		0x4
+#define PPCE500_PCI_INTACK		0x8
+
+#define PPCE500_PCI_OW1			(0xC20 - PCIE500_REG_BASE)
+#define PPCE500_PCI_OW2			(0xC40 - PCIE500_REG_BASE)
+#define PPCE500_PCI_OW3			(0xC60 - PCIE500_REG_BASE)
+#define PPCE500_PCI_OW4			(0xC80 - PCIE500_REG_BASE)
+#define PPCE500_PCI_IW3			(0xDA0 - PCIE500_REG_BASE)
+#define PPCE500_PCI_IW2			(0xDC0 - PCIE500_REG_BASE)
+#define PPCE500_PCI_IW1			(0xDE0 - PCIE500_REG_BASE)
+
+#define PPCE500_PCI_GASKET_TIMR		(0xE20 - PCIE500_REG_BASE)
+
+#define PCI_POTAR		0x0
+#define PCI_POTEAR		0x4
+#define PCI_POWBAR		0x8
+#define PCI_POWAR		0x10
+
+#define PCI_PITAR		0x0
+#define PCI_PIWBAR		0x8
+#define PCI_PIWBEAR		0xC
+#define PCI_PIWAR		0x10
+
+#define PPCE500_PCI_NR_POBS 5
+#define PPCE500_PCI_NR_PIBS 3
+
+struct  pci_outbound {
+    uint32_t potar;
+    uint32_t potear;
+    uint32_t powbar;
+    uint32_t powar;
+};
+
+struct pci_inbound {
+    uint32_t pitar;
+    uint32_t piwbar;
+    uint32_t piwbear;
+    uint32_t piwar;
+};
+
+struct PPCE500PCIState {
+    struct pci_outbound pob[PPCE500_PCI_NR_POBS];
+    struct pci_inbound pib[PPCE500_PCI_NR_PIBS];
+    uint32_t gasket_time;
+    PCIHostState pci_state;
+    PCIDevice *pci_dev;
+};
+
+typedef struct PPCE500PCIState PPCE500PCIState;
+
+static uint32_t pcie500_cfgaddr_readl(void *opaque, target_phys_addr_t addr)
+{
+    PPCE500PCIState *pci = opaque;
+
+    pci_debug("%s: (addr:%Lx) -> value:%x\n", __func__, addr,
+		    pci->pci_state.config_reg);
+    return pci->pci_state.config_reg;
+}
+
+static CPUReadMemoryFunc *pcie500_cfgaddr_read[] = {
+    &pcie500_cfgaddr_readl,
+    &pcie500_cfgaddr_readl,
+    &pcie500_cfgaddr_readl,
+};
+
+static void pcie500_cfgaddr_writel(void *opaque, target_phys_addr_t addr,
+                                  uint32_t value)
+{
+    PPCE500PCIState *controller = opaque;
+
+    pci_debug("%s: value:%x -> (addr%Lx)\n", __func__, value, addr);
+    controller->pci_state.config_reg = value & ~0x3;
+}
+
+static CPUWriteMemoryFunc *pcie500_cfgaddr_write[] = {
+    &pcie500_cfgaddr_writel,
+    &pcie500_cfgaddr_writel,
+    &pcie500_cfgaddr_writel,
+};
+
+static CPUReadMemoryFunc *pcie500_cfgdata_read[] = {
+    &pci_host_data_readb,
+    &pci_host_data_readw,
+    &pci_host_data_readl,
+};
+
+static CPUWriteMemoryFunc *pcie500_cfgdata_write[] = {
+    &pci_host_data_writeb,
+    &pci_host_data_writew,
+    &pci_host_data_writel,
+};
+
+static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
+{
+    PPCE500PCIState *pci = opaque;
+    unsigned long win;
+    uint32_t value = 0;
+
+    win = addr & 0xfe0;
+
+    switch (win) {
+    case PPCE500_PCI_OW1:
+    case PPCE500_PCI_OW2:
+    case PPCE500_PCI_OW3:
+    case PPCE500_PCI_OW4:
+	switch (addr & 0xC) {
+	case PCI_POTAR: value = pci->pob[(addr >> 5) & 0x7].potar; break;
+	case PCI_POTEAR: value = pci->pob[(addr >> 5) & 0x7].potear; break;
+	case PCI_POWBAR: value = pci->pob[(addr >> 5) & 0x7].powbar; break;
+	case PCI_POWAR: value = pci->pob[(addr >> 5) & 0x7].powar; break;
+	default: break;
+	}
+	break;
+
+    case PPCE500_PCI_IW3:
+    case PPCE500_PCI_IW2:
+    case PPCE500_PCI_IW1:
+	switch (addr & 0xC) {
+	case PCI_PITAR: value = pci->pib[(addr >> 5) & 0x3].pitar; break;
+	case PCI_PIWBAR: value = pci->pib[(addr >> 5) & 0x3].piwbar; break;
+	case PCI_PIWBEAR: value = pci->pib[(addr >> 5) & 0x3].piwbear; break;
+	case PCI_PIWAR: value = pci->pib[(addr >> 5) & 0x3].piwar; break;
+	default: break;
+	};
+	break;
+
+    case PPCE500_PCI_GASKET_TIMR:
+	value = pci->gasket_time;
+	break;
+
+    default:
+	break;
+    }
+
+    pci_debug("%s: win:%lx(addr:%Lx) -> value:%x\n",__func__,win,addr,value);
+    return value;
+}
+
+static CPUReadMemoryFunc *e500_pci_reg_read[] = {
+    &pci_reg_read4,
+    &pci_reg_read4,
+    &pci_reg_read4,
+};
+
+static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
+                               uint32_t value)
+{
+    PPCE500PCIState *pci = opaque;
+    unsigned long win;
+
+    win = addr & 0xfe0;
+
+    pci_debug("%s: value:%x -> win:%lx(addr:%Lx)\n",__func__,value,win,addr);
+
+    switch (win) {
+    case PPCE500_PCI_OW1:
+    case PPCE500_PCI_OW2:
+    case PPCE500_PCI_OW3:
+    case PPCE500_PCI_OW4:
+	switch (addr & 0xC) {
+	case PCI_POTAR: pci->pob[(addr >> 5) & 0x7].potar = value; break;
+	case PCI_POTEAR: pci->pob[(addr >> 5) & 0x7].potear = value; break;
+	case PCI_POWBAR: pci->pob[(addr >> 5) & 0x7].powbar = value; break;
+	case PCI_POWAR: pci->pob[(addr >> 5) & 0x7].powar = value; break;
+	default: break;
+	};
+	break;
+
+    case PPCE500_PCI_IW3:
+    case PPCE500_PCI_IW2:
+    case PPCE500_PCI_IW1:
+	switch (addr & 0xC) {
+	case PCI_PITAR: pci->pib[(addr >> 5) & 0x3].pitar = value; break;
+	case PCI_PIWBAR: pci->pib[(addr >> 5) & 0x3].piwbar = value; break;
+	case PCI_PIWBEAR: pci->pib[(addr >> 5) & 0x3].piwbear = value; break;
+	case PCI_PIWAR: pci->pib[(addr >> 5) & 0x3].piwar = value; break;
+	default: break;
+	};
+	break;
+
+    case PPCE500_PCI_GASKET_TIMR:
+	pci->gasket_time = value;
+	break;
+
+    default:
+	break;
+    };
+}
+
+static CPUWriteMemoryFunc *e500_pci_reg_write[] = {
+    &pci_reg_write4,
+    &pci_reg_write4,
+    &pci_reg_write4,
+};
+
+static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    int devno = pci_dev->devfn >> 3, ret = 0;
+
+    switch (devno) {
+	/* Two PCI slot */
+	case 0x11:
+	case 0x12:
+	    ret = (irq_num + devno - 0x10) % 4;
+	    break;
+	default:
+	    printf("Error:%s:unknow dev number\n", __func__);
+    }
+
+    pci_debug("%s: devfn %x irq %d -> %d  devno:%x\n", __func__,
+           pci_dev->devfn, irq_num, ret, devno);
+
+    return ret;
+}
+
+static void mpc85xx_pci_set_irq(qemu_irq *pic, int irq_num, int level)
+{
+    pci_debug("%s: PCI irq %d, level:%d\n", __func__, irq_num, level);
+
+    qemu_set_irq(pic[irq_num], level);
+}
+
+static void ppce500_pci_save(QEMUFile *f, void *opaque)
+{
+    PPCE500PCIState *controller = opaque;
+    int i;
+
+    pci_device_save(controller->pci_dev, f);
+
+    for (i = 0; i < PPCE500_PCI_NR_POBS; i++) {
+        qemu_put_be32s(f, &controller->pob[i].potar);
+        qemu_put_be32s(f, &controller->pob[i].potear);
+        qemu_put_be32s(f, &controller->pob[i].powbar);
+        qemu_put_be32s(f, &controller->pob[i].powar);
+    }
+
+    for (i = 0; i < PPCE500_PCI_NR_PIBS; i++) {
+        qemu_put_be32s(f, &controller->pib[i].pitar);
+        qemu_put_be32s(f, &controller->pib[i].piwbar);
+        qemu_put_be32s(f, &controller->pib[i].piwbear);
+        qemu_put_be32s(f, &controller->pib[i].piwar);
+    }
+    qemu_put_be32s(f, &controller->gasket_time);
+}
+
+static int ppce500_pci_load(QEMUFile *f, void *opaque, int version_id)
+{
+    PPCE500PCIState *controller = opaque;
+    int i;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    pci_device_load(controller->pci_dev, f);
+
+    for (i = 0; i < PPCE500_PCI_NR_POBS; i++) {
+        qemu_get_be32s(f, &controller->pob[i].potar);
+        qemu_get_be32s(f, &controller->pob[i].potear);
+        qemu_get_be32s(f, &controller->pob[i].powbar);
+        qemu_get_be32s(f, &controller->pob[i].powar);
+    }
+
+    for (i = 0; i < PPCE500_PCI_NR_PIBS; i++) {
+        qemu_get_be32s(f, &controller->pib[i].pitar);
+        qemu_get_be32s(f, &controller->pib[i].piwbar);
+        qemu_get_be32s(f, &controller->pib[i].piwbear);
+        qemu_get_be32s(f, &controller->pib[i].piwar);
+    }
+    qemu_get_be32s(f, &controller->gasket_time);
+
+    return 0;
+}
+
+PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
+{
+    PPCE500PCIState *controller;
+    PCIDevice *d;
+    int index;
+    static int ppce500_pci_id;
+
+    controller = qemu_mallocz(sizeof(PPCE500PCIState));
+    if (!controller)
+	return NULL;
+
+    controller->pci_state.bus = pci_register_bus(mpc85xx_pci_set_irq,
+                                                 mpc85xx_pci_map_irq,
+                                                 pci_irqs, 0x88, 4);
+    d = pci_register_device(controller->pci_state.bus,
+                            "host bridge", sizeof(PCIDevice),
+                            0, NULL, NULL);
+
+    d->config[0x00] = 0x57; // vendor_id
+    d->config[0x01] = 0x19;
+    d->config[0x02] = 0x30; // device_id
+    d->config[0x03] = 0x00;
+    d->config[0x0a] = 0x20; // class_sub = other bridge type
+    d->config[0x0b] = 0x0B; // class_base = PCI_bridge
+
+    controller->pci_dev = d;
+
+    /* CFGADDR */
+    index = cpu_register_io_memory(0, pcie500_cfgaddr_read,
+                                   pcie500_cfgaddr_write, controller);
+    if (index < 0)
+        goto free;
+    cpu_register_physical_memory(registers + PCIE500_CFGADDR, 4, index);
+
+    /* CFGDATA */
+    index = cpu_register_io_memory(0, pcie500_cfgdata_read,
+                                   pcie500_cfgdata_write,
+                                   &controller->pci_state);
+    if (index < 0)
+        goto free;
+    cpu_register_physical_memory(registers + PCIE500_CFGDATA, 4, index);
+
+    index = cpu_register_io_memory(0, e500_pci_reg_read,
+		                   e500_pci_reg_write, controller);
+    if (index < 0)
+	goto free;
+    cpu_register_physical_memory(registers + PCIE500_REG_BASE,
+                                   PCIE500_REG_SIZE, index);
+
+    /* XXX load/save code not tested. */
+    register_savevm("ppce500_pci", ppce500_pci_id++, 1,
+                    ppce500_pci_save, ppce500_pci_load, controller);
+
+    return controller->pci_state.bus;
+
+free:
+    printf("%s error\n", __func__);
+    qemu_free(controller);
+    return NULL;
+}
-- 
1.5.4

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

* [Qemu-devel] [PATCH 3/6] kvm/powerpc: Add irq support for E500 core
  2009-01-22 10:14   ` [Qemu-devel] [PATCH 2/6] kvm/powerpc: Add freescale pci controller's support Liu Yu
@ 2009-01-22 10:14     ` Liu Yu
  2009-01-22 10:14       ` [Qemu-devel] [PATCH 4/6] kvm/powerpc: extern one function for MPC85xx code use Liu Yu
  2009-01-24 16:32       ` [Qemu-devel] [PATCH 3/6] kvm/powerpc: Add irq support for E500 core Aurelien Jarno
  2009-01-24 16:02     ` [Qemu-devel] [PATCH 2/6] kvm/powerpc: Add freescale pci controller's support Aurelien Jarno
  1 sibling, 2 replies; 17+ messages in thread
From: Liu Yu @ 2009-01-22 10:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Liu Yu, hollisb, kvm-ppc

Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
 hw/ppc.c                    |   89 +++++++++++++++++++++++++++++++++++++++++++
 hw/ppc.h                    |    1 +
 target-ppc/cpu.h            |   10 +++++
 target-ppc/translate_init.c |    6 ++-
 4 files changed, 104 insertions(+), 2 deletions(-)

diff --git a/hw/ppc.c b/hw/ppc.c
index 05e787f..7a44951 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -314,6 +314,95 @@ void ppc40x_irq_init (CPUState *env)
                                                   env, PPC40x_INPUT_NB);
 }
 
+/* PowerPC E500 internal IRQ controller */
+static void ppce500_set_irq (void *opaque, int pin, int level)
+{
+    CPUState *env = opaque;
+    int cur_level;
+
+#if defined(PPC_DEBUG_IRQ)
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
+                env, pin, level);
+    }
+#endif
+    cur_level = (env->irq_input_state >> pin) & 1;
+    /* Don't generate spurious events */
+    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        switch (pin) {
+        case PPCE500_INPUT_MCK:
+            if (level) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: reset the PowerPC system\n",
+                            __func__);
+                }
+#endif
+		fprintf(stderr,"PowerPC E500 reset core\n");
+		qemu_system_reset_request();
+            }
+            break;
+        case PPCE500_INPUT_RESET_CORE:
+            if (level) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: reset the PowerPC core\n", __func__);
+                }
+#endif
+		ppc_set_irq(env, PPC_INTERRUPT_MCK, level);
+            }
+            break;
+        case PPCE500_INPUT_CINT:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the critical IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
+            break;
+        case PPCE500_INPUT_INT:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the core IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
+            break;
+        case PPCE500_INPUT_DEBUG:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the debug pin state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
+            break;
+        default:
+            /* Unknown pin - do nothing */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
+            }
+#endif
+            return;
+        }
+        if (level)
+            env->irq_input_state |= 1 << pin;
+        else
+            env->irq_input_state &= ~(1 << pin);
+    }
+}
+
+void ppce500_irq_init (CPUState *env)
+{
+    env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq,
+					env, PPCE500_INPUT_NB);
+}
 /*****************************************************************************/
 /* PowerPC time base and decrementer emulation */
 struct ppc_tb_t {
diff --git a/hw/ppc.h b/hw/ppc.h
index 75eb11a..2ec4680 100644
--- a/hw/ppc.h
+++ b/hw/ppc.h
@@ -31,6 +31,7 @@ extern CPUReadMemoryFunc *PPC_io_read[];
 void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val);
 
 void ppc40x_irq_init (CPUState *env);
+void ppce500_irq_init (CPUState *env);
 void ppc6xx_irq_init (CPUState *env);
 void ppc970_irq_init (CPUState *env);
 
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index f7a12da..0eb794f 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1352,6 +1352,16 @@ enum {
 };
 
 enum {
+    /* PowerPC E500 input pins */
+    PPCE500_INPUT_RESET_CORE = 0,
+    PPCE500_INPUT_MCK        = 1,
+    PPCE500_INPUT_CINT       = 3,
+    PPCE500_INPUT_INT        = 4,
+    PPCE500_INPUT_DEBUG      = 6,
+    PPCE500_INPUT_NB,
+};
+
+enum {
     /* PowerPC 40x input pins */
     PPC40x_INPUT_RESET_CORE = 0,
     PPC40x_INPUT_RESET_CHIP = 1,
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 5008a3a..7953c69 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -4154,7 +4154,8 @@ static void init_proc_e300 (CPUPPCState *env)
                               POWERPC_FLAG_BUS_CLK)
 #define check_pow_e500       check_pow_hid0
 
-__attribute__ (( unused ))
+extern void ppce500_irq_init (CPUState *env);
+
 static void init_proc_e500 (CPUPPCState *env)
 {
     /* Time base */
@@ -4256,7 +4257,8 @@ static void init_proc_e500 (CPUPPCState *env)
     init_excp_e200(env);
     env->dcache_line_size = 32;
     env->icache_line_size = 32;
-    /* XXX: TODO: allocate internal IRQ controller */
+    /* Allocate hardware IRQ controller */
+    ppce500_irq_init(env);
 }
 
 /* Non-embedded PowerPC                                                      */
-- 
1.5.4

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

* [Qemu-devel] [PATCH 4/6] kvm/powerpc: extern one function for MPC85xx code use
  2009-01-22 10:14     ` [Qemu-devel] [PATCH 3/6] kvm/powerpc: Add irq support for E500 core Liu Yu
@ 2009-01-22 10:14       ` Liu Yu
  2009-01-22 10:14         ` [Qemu-devel] [PATCH 5/6] kvm/powerpc: Add MPC85xx board support Liu Yu
  2009-01-24 16:36         ` [Qemu-devel] [PATCH 4/6] kvm/powerpc: extern one function for MPC85xx code use Aurelien Jarno
  2009-01-24 16:32       ` [Qemu-devel] [PATCH 3/6] kvm/powerpc: Add irq support for E500 core Aurelien Jarno
  1 sibling, 2 replies; 17+ messages in thread
From: Liu Yu @ 2009-01-22 10:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Liu Yu, hollisb, kvm-ppc

Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
 target-ppc/kvm_ppc.c |    2 +-
 target-ppc/kvm_ppc.h |    2 ++
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/target-ppc/kvm_ppc.c b/target-ppc/kvm_ppc.c
index f7ce52b..82c0f42 100644
--- a/target-ppc/kvm_ppc.c
+++ b/target-ppc/kvm_ppc.c
@@ -22,7 +22,7 @@ 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,
+int kvmppc_read_host_property(const char *node_path, const char *prop,
                                      void *val, size_t len)
 {
     char *path;
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index e536a88..3792ef7 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -11,5 +11,7 @@
 
 void kvmppc_init(void);
 void kvmppc_fdt_update(void *fdt);
+int kvmppc_read_host_property(const char *node_path, const char *prop,
+                                     void *val, size_t len);
 
 #endif /* __KVM_PPC_H__ */
-- 
1.5.4

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

* [Qemu-devel] [PATCH 5/6] kvm/powerpc: Add MPC85xx board support
  2009-01-22 10:14       ` [Qemu-devel] [PATCH 4/6] kvm/powerpc: extern one function for MPC85xx code use Liu Yu
@ 2009-01-22 10:14         ` Liu Yu
  2009-01-22 10:14           ` [Qemu-devel] [PATCH 6/6] kvm/powerpc: flat device tree files for MPC85xx Liu Yu
  2009-01-22 16:05           ` [Qemu-devel] Re: [PATCH 5/6] kvm/powerpc: Add MPC85xx board support Hollis Blanchard
  2009-01-24 16:36         ` [Qemu-devel] [PATCH 4/6] kvm/powerpc: extern one function for MPC85xx code use Aurelien Jarno
  1 sibling, 2 replies; 17+ messages in thread
From: Liu Yu @ 2009-01-22 10:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Liu Yu, hollisb, kvm-ppc

All MPC85xx boards use E500v1/v2 core.
This patch add emulation of a virtual MPC85xx board,
so that any MPC85xx host could run this emulation.

Only tested it on MPC8544DS and MPC8572DS hosts,
but it should work on other MPC85xx boards.

Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
 Makefile.target      |    2 +-
 hw/boards.h          |    1 +
 hw/ppce500.h         |   22 +++
 hw/ppce500_mpc85xx.c |  346 ++++++++++++++++++++++++++++++++++++++++++++++++++
 target-ppc/machine.c |    1 +
 5 files changed, 371 insertions(+), 1 deletions(-)
 create mode 100644 hw/ppce500.h
 create mode 100644 hw/ppce500_mpc85xx.c

diff --git a/Makefile.target b/Makefile.target
index 5cae257..3852f53 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -599,7 +599,7 @@ OBJS+= unin_pci.o ppc_chrp.o
 OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
 OBJS+= ppc440.o ppc440_bamboo.o
 # PowerPC E500 boards
-OBJS+= ppce500_pci.o
+OBJS+= ppce500_pci.o ppce500_mpc85xx.o
 ifdef FDT_LIBS
 OBJS+= device_tree.o
 LIBS+= $(FDT_LIBS)
diff --git a/hw/boards.h b/hw/boards.h
index 0577f06..1939f78 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -40,6 +40,7 @@ extern QEMUMachine heathrow_machine;
 extern QEMUMachine ref405ep_machine;
 extern QEMUMachine taihu_machine;
 extern QEMUMachine bamboo_machine;
+extern QEMUMachine mpc85xx_machine;
 
 /* mips_r4k.c */
 extern QEMUMachine mips_machine;
diff --git a/hw/ppce500.h b/hw/ppce500.h
new file mode 100644
index 0000000..24d49bb
--- /dev/null
+++ b/hw/ppce500.h
@@ -0,0 +1,22 @@
+/*
+ * QEMU PowerPC E500 emulation shared definitions
+ *
+ * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Yu Liu,     <yu.liu@freescale.com>
+ *
+ * This file is derived from hw/ppc440.h
+ * the copyright for that material belongs to the original owners.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of  the GNU General  Public License as published by
+ * the Free Software Foundation;  either version 2 of the  License, or
+ * (at your option) any later version.
+ */
+
+#if !defined(PPC_E500_H)
+#define PPC_E500_H
+
+PCIBus *ppce500_pci_init(qemu_irq *pic, target_phys_addr_t registers);
+
+#endif /* !defined(PPC_E500_H) */
diff --git a/hw/ppce500_mpc85xx.c b/hw/ppce500_mpc85xx.c
new file mode 100644
index 0000000..9dd619d
--- /dev/null
+++ b/hw/ppce500_mpc85xx.c
@@ -0,0 +1,346 @@
+/*
+ * Qemu PowerPC MPC85xx board emualtion
+ *
+ * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Yu Liu,     <yu.liu@freescale.com>
+ *
+ * This file is derived from hw/ppc440_bamboo.c,
+ * the copyright for that material belongs to the original owners.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of  the GNU General  Public License as published by
+ * the Free Software Foundation;  either version 2 of the  License, or
+ * (at your option) any later version.
+ */
+
+#include <dirent.h>
+
+#include "config.h"
+#include "qemu-common.h"
+#include "net.h"
+#include "hw.h"
+#include "pc.h"
+#include "pci.h"
+#include "virtio-blk.h"
+#include "boards.h"
+#include "sysemu.h"
+#include "kvm.h"
+#include "kvm_ppc.h"
+#include "device_tree.h"
+#include "openpic.h"
+#include "ppce500.h"
+
+#define BINARY_DEVICE_TREE_FILE  "mpc85xx.dtb"
+#define UIMAGE_LOAD_BASE         0
+#define DTB_LOAD_BASE            0x600000
+#define INITRD_LOAD_BASE         0x2000000
+
+#define RAM_SIZES_ALIGN          (64UL << 20)
+
+#define MPC85xx_CCSRBAR_BASE       0xE0000000
+#define MPC85xx_MPIC_REGS_BASE     (MPC85xx_CCSRBAR_BASE + 0x40000)
+#define MPC85xx_SERIAL0_REGS_BASE  (MPC85xx_CCSRBAR_BASE + 0x4500)
+#define MPC85xx_SERIAL1_REGS_BASE  (MPC85xx_CCSRBAR_BASE + 0x4600)
+#define MPC85xx_PCI_REGS_BASE      (MPC85xx_CCSRBAR_BASE + 0x8000)
+#define MPC85xx_PCI_REGS_SIZE      0x1000
+#define MPC85xx_PCI_IO             0xE1000000
+#define MPC85xx_PCI_IOLEN	   0x10000
+
+struct board {
+    const char *model;
+    const char *compatible;
+};
+
+#define BOARD_DEF(_model, _compatible)   \
+    {                                    \
+        .model       = _model,           \
+        .compatible  = _compatible,      \
+    }
+
+/* Supported host boards */
+static const struct board mpc85xx_table[] = {
+    BOARD_DEF("MPC8544DS",        "MPC8544DS"),         /* MPC8544DS */
+    BOARD_DEF("fsl,MPC8572DS",    "fsl,MPC8572DS"),     /* MPC8572DS */
+    BOARD_DEF("fsl,mpc8536ds",    "fsl,mpc8536ds"),     /* MPC8536DS */
+    BOARD_DEF("MPC8548CDS",       "MPC8548CDS"),        /* MPC8548CDS */
+    BOARD_DEF("MPC8555CDS",       "MPC8555CDS"),        /* MPC8555CDS */
+    BOARD_DEF("MPC8541CDS",       "MPC8541CDS"),        /* MPC8541CDS */
+    BOARD_DEF("MPC8540ADS",       "MPC8540ADS"),        /* MPC8540ADS */
+    BOARD_DEF("MPC8560ADS",       "MPC8560ADS"),        /* MPC8560ADS */
+    BOARD_DEF("MPC8568EMDS",      "MPC8568EMDS"),       /* MPC8568EMDS */
+};
+
+#define BOARDS_NUM       (sizeof(mpc85xx_table)/sizeof(struct board))
+
+static int mpc85xx_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, "/cpus/PowerPC,85xx@0",
+				prop, cell);
+    if (ret < 0) {
+	fprintf(stderr, "couldn't set guest /cpus/PowerPC,85xx@0/%s\n", prop);
+	goto out;
+    }
+
+out:
+    return ret;
+}
+
+static void *mpc85xx_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, 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)
+	goto out;
+
+    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()) {
+	FILE *fp;
+	char *model;
+	char const *compatible = NULL;
+	struct dirent *dirp;
+	DIR *dp;
+	int i;
+	char buf[128];
+
+	if ((fp = fopen("/proc/cpuinfo", "r")) == NULL) {
+	    printf("Can't open file /proc/cpuinfo\n");
+	    goto out;
+	}
+	while (fgets(buf, 128, fp) != NULL) {
+	    if (strncmp(buf, "model", 5) == 0) {
+		model = buf + 9;
+		break;
+	    }
+	}
+	fclose(fp);
+
+	for (i = 0; i < BOARDS_NUM; i++) {
+	    if (strncmp(model, mpc85xx_table[i].model,
+			strlen(mpc85xx_table[i].model)) == 0) {
+		compatible = mpc85xx_table[i].compatible;
+	    }
+	}
+
+	if (compatible == NULL) {
+	    printf("Unknow host board!\n");
+	    goto out;
+	}
+
+	ret = qemu_devtree_setprop_string(fdt, "/", "compatible", compatible);
+	if (ret < 0)
+	    fprintf(stderr, "couldn't set /compatible = %s\n", compatible);
+
+	if ((dp = opendir("/proc/device-tree/cpus/")) == NULL) {
+	    printf("Can't open directory /proc/device-tree/cpus/\n");
+	    goto out;
+	}
+
+	buf[0] = '\0';
+	while ((dirp = readdir(dp)) != NULL) {
+	    if (strncmp(dirp->d_name, "PowerPC", 7) == 0) {
+		sprintf(buf, "/proc/device-tree/cpus/%s", dirp->d_name);
+		break;
+	    }
+	}
+	closedir(dp);
+	if (buf[0] == '\0') {
+	    printf("Unknow host!\n");
+	    goto out;
+	}
+	path = buf + 17;
+
+	mpc85xx_copy_host_cell(fdt, path, "clock-frequency");
+	mpc85xx_copy_host_cell(fdt, path, "timebase-frequency");
+    }
+
+out:
+#endif
+
+    return fdt;
+}
+
+static void mpc85xx_init(ram_addr_t ram_size, int vga_ram_size,
+                         const char *boot_device,
+                         const char *kernel_filename,
+                         const char *kernel_cmdline,
+                         const char *initrd_filename,
+                         const char *cpu_model)
+{
+    PCIBus *pci_bus;
+    CPUState *env;
+    uint64_t elf_entry;
+    uint64_t elf_lowaddr;
+    target_ulong entry=0;
+    target_ulong loadaddr=UIMAGE_LOAD_BASE;
+    target_long kernel_size=0;
+    target_ulong dt_base=DTB_LOAD_BASE;
+    target_ulong initrd_base=INITRD_LOAD_BASE;
+    target_long initrd_size=0;
+    void *fdt;
+    int i=0;
+    unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
+    qemu_irq *irqs, *mpic, *pci_irqs;
+    SerialState * serial[2];
+
+    /* Setup CPU */
+    env = cpu_ppc_init("e500v2_v30");
+    if (!env) {
+	fprintf(stderr, "Unable to initialize CPU!\n");
+	exit(1);
+    }
+
+    /* Fixup Memory size on a alignment boundary */
+    ram_size &= ~(RAM_SIZES_ALIGN - 1);
+
+    /* Register Memory */
+    cpu_register_physical_memory(0, ram_size, 0);
+
+    /* MPIC */
+    irqs = qemu_mallocz(sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
+    irqs[OPENPIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPCE500_INPUT_INT];
+    irqs[OPENPIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPCE500_INPUT_CINT];
+    mpic = mpic_init(MPC85xx_MPIC_REGS_BASE, 1, &irqs, NULL);
+
+    /* Serial */
+    if (serial_hds[0])
+	serial[0] = serial_mm_init(MPC85xx_SERIAL0_REGS_BASE,
+			0, mpic[12+26], 399193,
+			serial_hds[0], 1);
+
+    if (serial_hds[1])
+	serial[0] = serial_mm_init(MPC85xx_SERIAL1_REGS_BASE,
+			0, mpic[12+26], 399193,
+			serial_hds[0], 1);
+
+    /* PCI */
+    pci_irqs = qemu_malloc(sizeof(qemu_irq) * 4);
+    pci_irqs[0] = mpic[pci_irq_nrs[0]];
+    pci_irqs[1] = mpic[pci_irq_nrs[1]];
+    pci_irqs[2] = mpic[pci_irq_nrs[2]];
+    pci_irqs[3] = mpic[pci_irq_nrs[3]];
+    pci_bus = ppce500_pci_init(pci_irqs, MPC85xx_PCI_REGS_BASE);
+    if (!pci_bus)
+	printf("couldn't create PCI controller!\n");
+
+    isa_mmio_init(MPC85xx_PCI_IO, MPC85xx_PCI_IOLEN);
+
+    if (pci_bus) {
+        int unit_id = 0;
+
+        /* Add virtio block devices. */
+        while ((i = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
+            virtio_blk_init(pci_bus, drives_table[i].bdrv);
+            unit_id++;
+        }
+
+        /* Register network interfaces. */
+        for (i = 0; i < nb_nics; i++) {
+            pci_nic_init(pci_bus, &nd_table[i], -1, "virtio");
+        }
+    }
+
+    /* 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_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) {
+        fdt = mpc85xx_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();
+
+    return;
+}
+
+QEMUMachine mpc85xx_machine = {
+    .name = "mpc85xx",
+    .desc = "mpc85xx",
+    .init = mpc85xx_init,
+    .ram_require = 64<<20 | RAMSIZE_FIXED,
+};
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index 4f9a191..eb64232 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -9,6 +9,7 @@ void register_machines(void)
     qemu_register_machine(&ref405ep_machine);
     qemu_register_machine(&taihu_machine);
     qemu_register_machine(&bamboo_machine);
+    qemu_register_machine(&mpc85xx_machine);
 }
 
 void cpu_save(QEMUFile *f, void *opaque)
-- 
1.5.4

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

* [Qemu-devel] [PATCH 6/6] kvm/powerpc: flat device tree files for MPC85xx
  2009-01-22 10:14         ` [Qemu-devel] [PATCH 5/6] kvm/powerpc: Add MPC85xx board support Liu Yu
@ 2009-01-22 10:14           ` Liu Yu
  2009-01-22 15:54             ` [Qemu-devel] " Hollis Blanchard
  2009-01-22 16:05           ` [Qemu-devel] Re: [PATCH 5/6] kvm/powerpc: Add MPC85xx board support Hollis Blanchard
  1 sibling, 1 reply; 17+ messages in thread
From: Liu Yu @ 2009-01-22 10:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Liu Yu, hollisb, kvm-ppc

Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
 pc-bios/mpc85xx.dtb |  Bin 0 -> 12288 bytes
 pc-bios/mpc85xx.dts |  361 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 361 insertions(+), 0 deletions(-)
 create mode 100644 pc-bios/mpc85xx.dtb
 create mode 100644 pc-bios/mpc85xx.dts

diff --git a/pc-bios/mpc85xx.dtb b/pc-bios/mpc85xx.dtb
new file mode 100644
index 0000000000000000000000000000000000000000..a10e29d5bd0d65add2faed921434ff3ac2d16cdd
GIT binary patch
literal 12288
zcmeHL&5z_p6)%%8N%#m$L?XV`(sDpBW_xCPHjCiUD3D7O)Dj}6m59e(Gh?mWc5L@D
zgAkenLL5Qd(HuB&T5fP!{s1I$=G2=6!UZW@5RsyU-|tmDce!UaTC&m#B$xDD_3FKP
zAHRC#uU9|*?mvtf8?@gW^UMVOmqDKdT>_y+|1#$3AG`7Y)HU+aJc9mX9KZ0=i=!83
z&t2a;J|@fgPl2{%ZZi4y_l%cf<mHc|XRfqGeexp^`6$V=q_GW#BKsox?JG^0(!tb@
zUAxlQI!p5DWN$1eu5~B(*1Z<$J_)<uyi%o^*t`z2^yut-0{yorvm*Su3K=V9&#z_4
zrtF2aY+q#`!kQ?pmXZ|4n)5{%Ky0E}`9oXJp4*n3U0}Lq20PSI{stK|<zL2l6!7&1
z|5Ia5G1ck+a)bXhg=lK;caH7&I~)9;!E@i3qvW};i?TiuE!ubtG~1Ya9CI2s6=mJ#
z7E^$xaa@EI{i=M1^{W3-47QqVQROz?_o!2k^|}JNi#utYmv}_rj-T4p+#?r%oR&pf
zmw9gM>8|cAbw3B%I%sn2*JKi(Q-;*V>GK|e73b>bO-v92jpg4MKjr5Hn|wD;lk~`L
zMiA8O7ofk6;erK_v#F08;;|pcKI9{>!!!9aIhkvWFN%|iXzW-M(Z1G0v~fy(z7hA5
zjr?PvnbYG`7vEOV>|ER1lML4}o9{q{=0%S&hV@8%iQQK~K}<&D7A!R;e>VtY(t7$Y
zV|pI$9xSHAyxdRnc-dxo)@HVG_c@q#c@i(#+eL-j;N*IIxNO6FiK{E#(boHkarAjy
zB<Hj~soHXS6-DbyM(}$Ea<SXkboXmJh9xY+pst*4q9iGH`$L>#Z{K6s;jEZ)AGk-#
ze*@!B2mB1<cLRPNef3H1r^H-k>2$IVm^RR&pWveY!a8E@{R%SOcNaIkliV62w3Qy!
z)pl9gB8CSMiM=N<ob{*GkJL2nN?eO3n@)Cm&yw!!x&6T{pveTx1zZTT_T%Fs^yU=A
zTrd~?20dC=M^iAwcm-m+>pJtA?_c-*8@~Um@Bij|);ybH6`ldf<NTvfb$jRY5^Myu
zH;%C`v^xuU=th5VVN*pK&k|!;LG~wOelC;#!el#KH)J}`wb1LW;~eGO*-aVeBtIwn
z1-h=OKX0=qQ-9uOPp1C7-JWd2pJLcM3*2+=C2OBHXpejT7xZlJfjBn?t*F5EM^7A&
zKnz~nT^+bdu4No|9(jBETlAin^FR%ik1$sM)aUu3jKmmktjsC8OCX2g`BxydB{ib9
z&)uK6jz-YbcUULz{Xt?Q?h>1i_x<rZg*J(81aeT3!(md!^%~=y=$*6gL#(`>8ShW_
z@UxIBh6v`K^<F`Sdha!Q<62^`5vT&^NguvIM*oy;T_B?^%6QIbGm<?UW90JSyLkAn
zB?5oZJV)SZL;0{SXg}P$DfktY*-k;>m~$ggm|Qrf+zYvk<l^OfefKJ@aY&6(hjBfm
z8asol`>!!-li0W_%=NAU<0ci``>C<dz?9|<vmdC&7*ZGxdD<j#epANyLOIy3X^l}w
z);`P{JA+dO#&#yx^H^^t<Fo7X>F#6QCt0t?m>20G)!1#gy8jxZHc1+mg}L4qGmyBR
zIdHG;r^firLVUP}R`J~CW2kF%L)kl!;XbzN1Q@7{-&3%0H<YPOzE5HNS}3DE(np-^
z^-#vRDdV>r*8M${sXyNTAbaZ~8Sj6P{qucfd<1t*ZStKE>)!4J7^sZ*V#pruJ@vMC
zite8K&H#JO?SHh)vz@(X_oibfB%Tj?|DVFfiXgB(NNib?On0o9VO-qr8Rj_Q`QH0G
z<s*>p1$mxNh7#oU7T9x*a=vS=KmwIqz_=!0X$)^-j^ijRT3gr4s_lPda|z{N0`WOY
zQzMYn1^Tn~_|aGWnEGhlx60FCW*6BPwJv|jk5fLj9v(bT?%O5P&lb_scT0cXbZzhb
z6WGZ&4DCwX+4b>ccY1A1XK3D^<Q4M7oB2{sJT?E9G3GpJ?tAJGSROK6!}|m0)qaQd
zO?$FmCiUDGs><~}g}nU3sfud$-P!il@m0+D*caupvC|#$;X3sht~&_UN#1pvPM>vI
zZ~DNKfhNT!<JMd&jJa0UA68k(k5ce#v=QjCM9nEk^}{|&kIKdtRFQS~uNl2@?|+ru
ze@(UV#G;(r+@$5AO4@8cx8`y(pVzi&;?(AOV=gz@kMM&?#_k`-*tmYj;Q2S^MMk?E
zT{UxiD@*MU+LOwf+8&y@|HYJNg^g*;Wanm7rzaMs%@%ea|83)g+P<>1MS5cJ=PlsU
zyi9Kfd|{8<IJdWK?!1^fDGu@5cYRE%q_#!7o@fk0TOMy$M@cb9{!BH_in%?OZ|$R`
ziR-3KYvGFJB2J-LSU|)78lH&{vV#(S3z@XXHjS4>);94XX>Q8g+%{>Q;de<L6B{pC
zhqe9*Xf6k{f;+zZ<K$M7<q0+@K9|uVshpqnI!p;rqU#fE+IhKbW9;*hl*@1#5Eu{`
v5Eu{`5Eu{`5Eu{`5Eu{`5Eu{`5Eu{`5Eu{`5Eu{`5Eu{`5Eu~ne?Z_r$iQ#d

literal 0
HcmV?d00001

diff --git a/pc-bios/mpc85xx.dts b/pc-bios/mpc85xx.dts
new file mode 100644
index 0000000..45a9c3d
--- /dev/null
+++ b/pc-bios/mpc85xx.dts
@@ -0,0 +1,361 @@
+/*
+ * MPC85xx DS Device Tree Source
+ *
+ * Copyright 2007-2009 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/dts-v1/;
+/ {
+	model = "KVM MPC85xx";
+	compatible = "MPC8544DS", "MPC85xxDS";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
+		pci3 = &pci3;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,85xx@0 {
+			device_type = "cpu";
+			reg = <0x0>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <0x8000>;		// L1, 32K
+			i-cache-size = <0x8000>;		// L1, 32K
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x0>;	// Filled by U-Boot
+	};
+
+	soc85xx@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "simple-bus";
+
+		ranges = <0x0 0xe0000000 0x100000>;
+		reg = <0xe0000000 0x1000>;	// CCSRBAR 1M
+		bus-frequency = <0>;		// Filled out by uboot.
+
+		memory-controller@2000 {
+			compatible = "fsl,8544-memory-controller";
+			reg = <0x2000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <18 2>;
+		};
+
+		L2: l2-cache-controller@20000 {
+			compatible = "fsl,8544-l2-cache-controller";
+			reg = <0x20000 0x1000>;
+			cache-line-size = <32>;	// 32 bytes
+			cache-size = <0x40000>;	// L2, 256K
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+		};
+
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		global-utilities@e0000 {	//global utilities block
+			compatible = "fsl,mpc8548-guts";
+			reg = <0xe0000 0x1000>;
+			fsl,has-rstcr;
+		};
+
+		crypto@30000 {
+			compatible = "fsl,sec2.1", "fsl,sec2.0";
+			reg = <0x30000 0x10000>;
+			interrupts = <45 2>;
+			interrupt-parent = <&mpic>;
+			fsl,num-channels = <4>;
+			fsl,channel-fifo-len = <24>;
+			fsl,exec-units-mask = <0xfe>;
+			fsl,descriptor-types-mask = <0x12b0ebf>;
+		};
+
+		mpic: pic@40000 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		msi@41600 {
+			compatible = "fsl,mpc8544-msi", "fsl,mpic-msi";
+			reg = <0x41600 0x80>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0
+				0xe1 0
+				0xe2 0
+				0xe3 0
+				0xe4 0
+				0xe5 0
+				0xe6 0
+				0xe7 0>;
+			interrupt-parent = <&mpic>;
+		};
+	};
+
+	pci0: pci@e0008000 {
+		cell-index = <0>;
+		compatible = "fsl,mpc8540-pci";
+		device_type = "pci";
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+
+			/* IDSEL 0x11 J17 Slot 1 */
+			0x8800 0x0 0x0 0x1 &mpic 0x2 0x1
+			0x8800 0x0 0x0 0x2 &mpic 0x3 0x1
+			0x8800 0x0 0x0 0x3 &mpic 0x4 0x1
+			0x8800 0x0 0x0 0x4 &mpic 0x1 0x1
+
+			/* IDSEL 0x12 J16 Slot 2 */
+
+			0x9000 0x0 0x0 0x1 &mpic 0x3 0x1
+			0x9000 0x0 0x0 0x2 &mpic 0x4 0x1
+			0x9000 0x0 0x0 0x3 &mpic 0x2 0x1
+			0x9000 0x0 0x0 0x4 &mpic 0x1 0x1>;
+
+		interrupt-parent = <&mpic>;
+		interrupts = <24 2>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0xc0000000 0xc0000000 0x0 0x20000000
+			  0x1000000 0x0 0x0 0xe1000000 0x0 0x10000>;
+		clock-frequency = <66666666>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xe0008000 0x1000>;
+	};
+
+	pci1: pcie@e0009000 {
+		cell-index = <1>;
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xe0009000 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
+			  0x1000000 0x0 0x0 0xe1010000 0x0 0x10000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <26 2>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0x0 0x0 0x1 &mpic 0x4 0x1
+			0000 0x0 0x0 0x2 &mpic 0x5 0x1
+			0000 0x0 0x0 0x3 &mpic 0x6 0x1
+			0000 0x0 0x0 0x4 &mpic 0x7 0x1
+			>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0x80000000
+				  0x2000000 0x0 0x80000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x10000>;
+		};
+	};
+
+	pci2: pcie@e000a000 {
+		cell-index = <2>;
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xe000a000 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000
+			  0x1000000 0x0 0x0 0xe1020000 0x0 0x10000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <25 2>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0x0 0x0 0x1 &mpic 0x0 0x1
+			0000 0x0 0x0 0x2 &mpic 0x1 0x1
+			0000 0x0 0x0 0x3 &mpic 0x2 0x1
+			0000 0x0 0x0 0x4 &mpic 0x3 0x1
+			>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0xa0000000
+				  0x2000000 0x0 0xa0000000
+				  0x0 0x10000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x10000>;
+		};
+	};
+
+	pci3: pcie@e000b000 {
+		cell-index = <3>;
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xe000b000 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0xb0000000 0xb0000000 0x0 0x100000
+			  0x1000000 0x0 0x0 0xb0100000 0x0 0x100000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <27 2>;
+		interrupt-map-mask = <0xff00 0x0 0x0 0x1>;
+		interrupt-map = <
+			// IDSEL 0x1c  USB
+			0xe000 0x0 0x0 0x1 &i8259 0xc 0x2
+			0xe100 0x0 0x0 0x2 &i8259 0x9 0x2
+			0xe200 0x0 0x0 0x3 &i8259 0xa 0x2
+			0xe300 0x0 0x0 0x4 &i8259 0xb 0x2
+
+			// IDSEL 0x1d  Audio
+			0xe800 0x0 0x0 0x1 &i8259 0x6 0x2
+
+			// IDSEL 0x1e Legacy
+			0xf000 0x0 0x0 0x1 &i8259 0x7 0x2
+			0xf100 0x0 0x0 0x1 &i8259 0x7 0x2
+
+			// IDSEL 0x1f IDE/SATA
+			0xf800 0x0 0x0 0x1 &i8259 0xe 0x2
+			0xf900 0x0 0x0 0x1 &i8259 0x5 0x2
+		>;
+
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0xb0000000
+				  0x2000000 0x0 0xb0000000
+				  0x0 0x100000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+
+			uli1575@0 {
+				reg = <0x0 0x0 0x0 0x0 0x0>;
+				#size-cells = <2>;
+				#address-cells = <3>;
+				ranges = <0x2000000 0x0 0xb0000000
+					  0x2000000 0x0 0xb0000000
+					  0x0 0x100000
+
+					  0x1000000 0x0 0x0
+					  0x1000000 0x0 0x0
+					  0x0 0x100000>;
+				isa@1e {
+					device_type = "isa";
+					#interrupt-cells = <2>;
+					#size-cells = <1>;
+					#address-cells = <2>;
+					reg = <0xf000 0x0 0x0 0x0 0x0>;
+					ranges = <0x1 0x0
+						  0x1000000 0x0 0x0
+						  0x1000>;
+					interrupt-parent = <&i8259>;
+
+					i8259: interrupt-controller@20 {
+						reg = <0x1 0x20 0x2
+						       0x1 0xa0 0x2
+						       0x1 0x4d0 0x2>;
+						interrupt-controller;
+						device_type = "interrupt-controller";
+						#address-cells = <0>;
+						#interrupt-cells = <2>;
+						compatible = "chrp,iic";
+						interrupts = <9 2>;
+						interrupt-parent = <&mpic>;
+					};
+
+					i8042@60 {
+						#size-cells = <0>;
+						#address-cells = <1>;
+						reg = <0x1 0x60 0x1 0x1 0x64 0x1>;
+						interrupts = <1 3 12 3>;
+						interrupt-parent = <&i8259>;
+
+						keyboard@0 {
+							reg = <0x0>;
+							compatible = "pnpPNP,303";
+						};
+
+						mouse@1 {
+							reg = <0x1>;
+							compatible = "pnpPNP,f03";
+						};
+					};
+
+					rtc@70 {
+						compatible = "pnpPNP,b00";
+						reg = <0x1 0x70 0x2>;
+					};
+
+					gpio@400 {
+						reg = <0x1 0x400 0x80>;
+					};
+				};
+			};
+		};
+	};
+	chosen {
+		linux,stdout-path = "/soc85xx@e0000000/serial@4500";
+	};
+};
-- 
1.5.4

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

* [Qemu-devel] Re: [PATCH 6/6] kvm/powerpc: flat device tree files for MPC85xx
  2009-01-22 10:14           ` [Qemu-devel] [PATCH 6/6] kvm/powerpc: flat device tree files for MPC85xx Liu Yu
@ 2009-01-22 15:54             ` Hollis Blanchard
  0 siblings, 0 replies; 17+ messages in thread
From: Hollis Blanchard @ 2009-01-22 15:54 UTC (permalink / raw)
  To: Liu Yu; +Cc: qemu-devel, kvm-ppc

On Thu, 2009-01-22 at 18:14 +0800, Liu Yu wrote:
> 
> diff --git a/pc-bios/mpc85xx.dts b/pc-bios/mpc85xx.dts
> new file mode 100644
> index 0000000..45a9c3d
> --- /dev/null
> +++ b/pc-bios/mpc85xx.dts
> @@ -0,0 +1,361 @@
> +/*
> + * MPC85xx DS Device Tree Source
> + *
> + * Copyright 2007-2009 Freescale Semiconductor Inc.
> + *
> + * This program is free software; you can redistribute  it and/or modify it
> + * under  the terms of  the GNU General  Public License as published by the
> + * Free Software Foundation;  either version 2 of the  License, or (at your
> + * option) any later version.
> + */
> +
> +/dts-v1/;
> +/ {
> +	model = "KVM MPC85xx";
> +	compatible = "MPC8544DS", "MPC85xxDS";
> +	#address-cells = <1>;
> +	#size-cells = <1>;
> +
> +	aliases {
> +		serial0 = &serial0;
> +		serial1 = &serial1;
> +		pci0 = &pci0;
> +		pci1 = &pci1;
> +		pci2 = &pci2;
> +		pci3 = &pci3;
> +	};
> +
> +	cpus {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		PowerPC,85xx@0 {
> +			device_type = "cpu";
> +			reg = <0x0>;
> +			d-cache-line-size = <32>;	// 32 bytes
> +			i-cache-line-size = <32>;	// 32 bytes
> +			d-cache-size = <0x8000>;		// L1, 32K
> +			i-cache-size = <0x8000>;		// L1, 32K
> +			timebase-frequency = <0>;
> +			bus-frequency = <0>;
> +			clock-frequency = <0>;
> +			next-level-cache = <&L2>;
> +		};
> +	};
> +
> +	memory {
> +		device_type = "memory";
> +		reg = <0x0 0x0>;	// Filled by U-Boot
> +	};
> +
> +	soc85xx@e0000000 {
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		device_type = "soc";
> +		compatible = "simple-bus";
> +
> +		ranges = <0x0 0xe0000000 0x100000>;
> +		reg = <0xe0000000 0x1000>;	// CCSRBAR 1M
> +		bus-frequency = <0>;		// Filled out by uboot.
> +
> +		memory-controller@2000 {
> +			compatible = "fsl,8544-memory-controller";
> +			reg = <0x2000 0x1000>;
> +			interrupt-parent = <&mpic>;
> +			interrupts = <18 2>;
> +		};
...

You need to remove devices that are not emulated by qemu.

The device tree is firmware's way of informing the kernel what devices
are present. Since the kernel sees that the memory controller (for
example) is present, it is allowed to try to access it... and since qemu
doesn't emulate it, that's bad.

Same is true for crypto, guts, msi, and all the other devices qemu
doesn't emulate.

-- 
Hollis Blanchard
IBM Linux Technology Center

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

* [Qemu-devel] Re: [PATCH 5/6] kvm/powerpc: Add MPC85xx board support
  2009-01-22 10:14         ` [Qemu-devel] [PATCH 5/6] kvm/powerpc: Add MPC85xx board support Liu Yu
  2009-01-22 10:14           ` [Qemu-devel] [PATCH 6/6] kvm/powerpc: flat device tree files for MPC85xx Liu Yu
@ 2009-01-22 16:05           ` Hollis Blanchard
  1 sibling, 0 replies; 17+ messages in thread
From: Hollis Blanchard @ 2009-01-22 16:05 UTC (permalink / raw)
  To: Liu Yu; +Cc: qemu-devel, kvm-ppc

On Thu, 2009-01-22 at 18:14 +0800, Liu Yu wrote:
> All MPC85xx boards use E500v1/v2 core.
> This patch add emulation of a virtual MPC85xx board,
> so that any MPC85xx host could run this emulation.
> 
> Only tested it on MPC8544DS and MPC8572DS hosts,
> but it should work on other MPC85xx boards.
> 
> Signed-off-by: Liu Yu <yu.liu@freescale.com>
...

> +struct board {
> +    const char *model;
> +    const char *compatible;
> +};
> +
> +#define BOARD_DEF(_model, _compatible)   \
> +    {                                    \
> +        .model       = _model,           \
> +        .compatible  = _compatible,      \
> +    }
> +
> +/* Supported host boards */
> +static const struct board mpc85xx_table[] = {
> +    BOARD_DEF("MPC8544DS",        "MPC8544DS"),         /* MPC8544DS */
> +    BOARD_DEF("fsl,MPC8572DS",    "fsl,MPC8572DS"),     /* MPC8572DS */
> +    BOARD_DEF("fsl,mpc8536ds",    "fsl,mpc8536ds"),     /* MPC8536DS */
> +    BOARD_DEF("MPC8548CDS",       "MPC8548CDS"),        /* MPC8548CDS */
> +    BOARD_DEF("MPC8555CDS",       "MPC8555CDS"),        /* MPC8555CDS */
> +    BOARD_DEF("MPC8541CDS",       "MPC8541CDS"),        /* MPC8541CDS */
> +    BOARD_DEF("MPC8540ADS",       "MPC8540ADS"),        /* MPC8540ADS */
> +    BOARD_DEF("MPC8560ADS",       "MPC8560ADS"),        /* MPC8560ADS */
> +    BOARD_DEF("MPC8568EMDS",      "MPC8568EMDS"),       /* MPC8568EMDS */
> +};
> +
> +#define BOARDS_NUM       (sizeof(mpc85xx_table)/sizeof(struct board))
...
> +static void *mpc85xx_load_device_tree(void *addr,
> +                                     uint32_t ramsize,
> +                                     target_phys_addr_t initrd_base,
> +                                     target_phys_addr_t initrd_size,
> +                                     const char *kernel_cmdline)
> +{
...
> +    if (kvm_enabled()) {
> +	FILE *fp;
> +	char *model;
> +	char const *compatible = NULL;
> +	struct dirent *dirp;
> +	DIR *dp;
> +	int i;
> +	char buf[128];
> +
> +	if ((fp = fopen("/proc/cpuinfo", "r")) == NULL) {
> +	    printf("Can't open file /proc/cpuinfo\n");
> +	    goto out;
> +	}
> +	while (fgets(buf, 128, fp) != NULL) {
> +	    if (strncmp(buf, "model", 5) == 0) {
> +		model = buf + 9;
> +		break;
> +	    }
> +	}
> +	fclose(fp);
> +
> +	for (i = 0; i < BOARDS_NUM; i++) {
> +	    if (strncmp(model, mpc85xx_table[i].model,
> +			strlen(mpc85xx_table[i].model)) == 0) {
> +		compatible = mpc85xx_table[i].compatible;
> +	    }
> +	}
> +
> +	if (compatible == NULL) {
> +	    printf("Unknow host board!\n");
> +	    goto out;
> +	}
> +
> +	ret = qemu_devtree_setprop_string(fdt, "/", "compatible", compatible);
> +	if (ret < 0)
> +	    fprintf(stderr, "couldn't set /compatible = %s\n", compatible);
> +
> +	if ((dp = opendir("/proc/device-tree/cpus/")) == NULL) {
> +	    printf("Can't open directory /proc/device-tree/cpus/\n");
> +	    goto out;
> +	}
> +
> +	buf[0] = '\0';
> +	while ((dirp = readdir(dp)) != NULL) {
> +	    if (strncmp(dirp->d_name, "PowerPC", 7) == 0) {
> +		sprintf(buf, "/proc/device-tree/cpus/%s", dirp->d_name);
> +		break;
> +	    }
> +	}
> +	closedir(dp);
> +	if (buf[0] == '\0') {
> +	    printf("Unknow host!\n");
> +	    goto out;
> +	}
> +	path = buf + 17;

I don't think you should do this at all. As long as the core is "known",
it doesn't matter what the host board is. You *always* emulate the
MPC8544DS board (that's what your device tree says). You should be able
to emulate a MPC8544DS on *any* e500v2 host board or chip.

For comparison, on 440 we have tested with Sequoia (440EPx) and Bamboo
(440EP) hosts, but qemu always emulates a Bamboo guest. The chips aren't
the same, but that's irrelevant because the core is (440 x5).

The rest of this patch looks good.

-- 
Hollis Blanchard
IBM Linux Technology Center

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

* [Qemu-devel] Re: [PATCH 0/6] kvm/powerpc: Add emulation for MPC85xx in KVM mode
  2009-01-22 10:14 [Qemu-devel] [PATCH 0/6] kvm/powerpc: Add emulation for MPC85xx in KVM mode Liu Yu
  2009-01-22 10:14 ` [Qemu-devel] [PATCH 1/6] kvm/powerpc: Enable MPIC for MPC85xx platform Liu Yu
@ 2009-01-22 16:13 ` Hollis Blanchard
  2009-01-27  7:38   ` [Qemu-devel] Regarding ARM11Mpcore MMC kernel panic sathish kumar
  1 sibling, 1 reply; 17+ messages in thread
From: Hollis Blanchard @ 2009-01-22 16:13 UTC (permalink / raw)
  To: Liu Yu; +Cc: Aurelien Jarno, qemu-devel, kvm-ppc

On Thu, 2009-01-22 at 18:14 +0800, Liu Yu wrote:
> This patch set enable another KVM PowerPC platform E500.
> Like the 440 core, the MMU and a few other bits are not currently
> emulated in Qemu itself,
> so right now it's only functional in conjunction with KVM.
> 
> The emulation of MPC85xx boards (which use E500 as its core) 
> can be run on any MPC85xx hosts.
> The code has been tested on MPC8544DS and MPC8572DS.
> 
> Patch 1: enable the MPIC for MPC85xx platform
> Patch 2: add emulation of freescale PCI controller for MPC85xx platform
> Patch 3: add IRQ support for E500 core
> Patch 4: extern one function for MPC85xx code use
> Patch 5: add MPC85xx board emulation
> Patch 6: flat device tree of MPC85xx

Patches 1-4: Acked-by: Hollis Blanchard <hollisb@us.ibm.com>
I've posted some comments on patches 5 and 6.

Aurelian, would you mind reviewing patches 1-3?

-- 
Hollis Blanchard
IBM Linux Technology Center

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

* Re: [Qemu-devel] [PATCH 2/6] kvm/powerpc: Add freescale pci controller's support
  2009-01-22 10:14   ` [Qemu-devel] [PATCH 2/6] kvm/powerpc: Add freescale pci controller's support Liu Yu
  2009-01-22 10:14     ` [Qemu-devel] [PATCH 3/6] kvm/powerpc: Add irq support for E500 core Liu Yu
@ 2009-01-24 16:02     ` Aurelien Jarno
  2009-02-09  8:33       ` [Qemu-devel] [PATCH 2/6] kvm/powerpc: Add freescale pcicontroller's support Liu Yu-B13201
  1 sibling, 1 reply; 17+ messages in thread
From: Aurelien Jarno @ 2009-01-24 16:02 UTC (permalink / raw)
  To: Liu Yu; +Cc: kvm-ppc, qemu-devel, hollisb

On Thu, Jan 22, 2009 at 06:14:12PM +0800, Liu Yu wrote:
> This patch add the emulation of freescale's pci controller for MPC85xx platform.
> 
> Signed-off-by: Liu Yu <yu.liu@freescale.com>

I have one general comment for this patch, QEMU (mostly) uses spaces for
indentation, while this patch uses spaces + tab. Would it be possible to
convert it to spaces only, using 4 spaces?

I also have one minor comment inside. Otherwise the patch looks ok.

>  Makefile.target  |    2 +
>  hw/ppce500_pci.c |  370 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 372 insertions(+), 0 deletions(-)
>  create mode 100644 hw/ppce500_pci.c
> 
> diff --git a/Makefile.target b/Makefile.target
> index a091ce9..5cae257 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -598,6 +598,8 @@ 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 ppc440_bamboo.o
> +# PowerPC E500 boards
> +OBJS+= ppce500_pci.o
>  ifdef FDT_LIBS
>  OBJS+= device_tree.o
>  LIBS+= $(FDT_LIBS)
> diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
> new file mode 100644
> index 0000000..6325555
> --- /dev/null
> +++ b/hw/ppce500_pci.c
> @@ -0,0 +1,370 @@
> +/*
> + * QEMU PowerPC E500 embedded processors pci controller emulation
> + *
> + * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
> + *
> + * Author: Yu Liu,     <yu.liu@freescale.com>
> + *
> + * This file is derived from hw/ppc4xx_pci.c,
> + * the copyright for that material belongs to the original owners.
> + *
> + * This is free software; you can redistribute it and/or modify
> + * it under the terms of  the GNU General  Public License as published by
> + * the Free Software Foundation;  either version 2 of the  License, or
> + * (at your option) any later version.
> + */
> +
> +#include "hw.h"
> +#include "ppc.h"
> +#include "ppce500.h"
> +typedef target_phys_addr_t pci_addr_t;
> +#include "pci.h"
> +#include "pci_host.h"
> +#include "bswap.h"
> +#include "qemu-log.h"
> +
> +#ifdef DEBUG_PCI
> +#define pci_debug(fmt, arg...) fprintf(stderr, fmt, ##arg)
> +#else
> +#define pci_debug(fmt, arg...)
> +#endif
> +
> +#define PCIE500_CFGADDR       0x0
> +#define PCIE500_CFGDATA       0x4
> +#define PCIE500_REG_BASE      0xC00
> +#define PCIE500_REG_SIZE      (0x1000 - PCIE500_REG_BASE)
> +
> +#define PPCE500_PCI_CONFIG_ADDR		0x0
> +#define PPCE500_PCI_CONFIG_DATA		0x4
> +#define PPCE500_PCI_INTACK		0x8
> +
> +#define PPCE500_PCI_OW1			(0xC20 - PCIE500_REG_BASE)
> +#define PPCE500_PCI_OW2			(0xC40 - PCIE500_REG_BASE)
> +#define PPCE500_PCI_OW3			(0xC60 - PCIE500_REG_BASE)
> +#define PPCE500_PCI_OW4			(0xC80 - PCIE500_REG_BASE)
> +#define PPCE500_PCI_IW3			(0xDA0 - PCIE500_REG_BASE)
> +#define PPCE500_PCI_IW2			(0xDC0 - PCIE500_REG_BASE)
> +#define PPCE500_PCI_IW1			(0xDE0 - PCIE500_REG_BASE)
> +
> +#define PPCE500_PCI_GASKET_TIMR		(0xE20 - PCIE500_REG_BASE)
> +
> +#define PCI_POTAR		0x0
> +#define PCI_POTEAR		0x4
> +#define PCI_POWBAR		0x8
> +#define PCI_POWAR		0x10
> +
> +#define PCI_PITAR		0x0
> +#define PCI_PIWBAR		0x8
> +#define PCI_PIWBEAR		0xC
> +#define PCI_PIWAR		0x10
> +
> +#define PPCE500_PCI_NR_POBS 5
> +#define PPCE500_PCI_NR_PIBS 3
> +
> +struct  pci_outbound {
> +    uint32_t potar;
> +    uint32_t potear;
> +    uint32_t powbar;
> +    uint32_t powar;
> +};
> +
> +struct pci_inbound {
> +    uint32_t pitar;
> +    uint32_t piwbar;
> +    uint32_t piwbear;
> +    uint32_t piwar;
> +};
> +
> +struct PPCE500PCIState {
> +    struct pci_outbound pob[PPCE500_PCI_NR_POBS];
> +    struct pci_inbound pib[PPCE500_PCI_NR_PIBS];
> +    uint32_t gasket_time;
> +    PCIHostState pci_state;
> +    PCIDevice *pci_dev;
> +};
> +
> +typedef struct PPCE500PCIState PPCE500PCIState;
> +
> +static uint32_t pcie500_cfgaddr_readl(void *opaque, target_phys_addr_t addr)
> +{
> +    PPCE500PCIState *pci = opaque;
> +
> +    pci_debug("%s: (addr:%Lx) -> value:%x\n", __func__, addr,
> +		    pci->pci_state.config_reg);
> +    return pci->pci_state.config_reg;
> +}
> +
> +static CPUReadMemoryFunc *pcie500_cfgaddr_read[] = {
> +    &pcie500_cfgaddr_readl,
> +    &pcie500_cfgaddr_readl,
> +    &pcie500_cfgaddr_readl,
> +};
> +
> +static void pcie500_cfgaddr_writel(void *opaque, target_phys_addr_t addr,
> +                                  uint32_t value)
> +{
> +    PPCE500PCIState *controller = opaque;
> +
> +    pci_debug("%s: value:%x -> (addr%Lx)\n", __func__, value, addr);
> +    controller->pci_state.config_reg = value & ~0x3;
> +}
> +
> +static CPUWriteMemoryFunc *pcie500_cfgaddr_write[] = {
> +    &pcie500_cfgaddr_writel,
> +    &pcie500_cfgaddr_writel,
> +    &pcie500_cfgaddr_writel,
> +};
> +
> +static CPUReadMemoryFunc *pcie500_cfgdata_read[] = {
> +    &pci_host_data_readb,
> +    &pci_host_data_readw,
> +    &pci_host_data_readl,
> +};
> +
> +static CPUWriteMemoryFunc *pcie500_cfgdata_write[] = {
> +    &pci_host_data_writeb,
> +    &pci_host_data_writew,
> +    &pci_host_data_writel,
> +};
> +
> +static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
> +{
> +    PPCE500PCIState *pci = opaque;
> +    unsigned long win;
> +    uint32_t value = 0;
> +
> +    win = addr & 0xfe0;
> +
> +    switch (win) {
> +    case PPCE500_PCI_OW1:
> +    case PPCE500_PCI_OW2:
> +    case PPCE500_PCI_OW3:
> +    case PPCE500_PCI_OW4:
> +	switch (addr & 0xC) {
> +	case PCI_POTAR: value = pci->pob[(addr >> 5) & 0x7].potar; break;
> +	case PCI_POTEAR: value = pci->pob[(addr >> 5) & 0x7].potear; break;
> +	case PCI_POWBAR: value = pci->pob[(addr >> 5) & 0x7].powbar; break;
> +	case PCI_POWAR: value = pci->pob[(addr >> 5) & 0x7].powar; break;
> +	default: break;
> +	}
> +	break;
> +
> +    case PPCE500_PCI_IW3:
> +    case PPCE500_PCI_IW2:
> +    case PPCE500_PCI_IW1:
> +	switch (addr & 0xC) {
> +	case PCI_PITAR: value = pci->pib[(addr >> 5) & 0x3].pitar; break;
> +	case PCI_PIWBAR: value = pci->pib[(addr >> 5) & 0x3].piwbar; break;
> +	case PCI_PIWBEAR: value = pci->pib[(addr >> 5) & 0x3].piwbear; break;
> +	case PCI_PIWAR: value = pci->pib[(addr >> 5) & 0x3].piwar; break;
> +	default: break;
> +	};
> +	break;
> +
> +    case PPCE500_PCI_GASKET_TIMR:
> +	value = pci->gasket_time;
> +	break;
> +
> +    default:
> +	break;
> +    }
> +
> +    pci_debug("%s: win:%lx(addr:%Lx) -> value:%x\n",__func__,win,addr,value);
> +    return value;
> +}
> +
> +static CPUReadMemoryFunc *e500_pci_reg_read[] = {
> +    &pci_reg_read4,
> +    &pci_reg_read4,
> +    &pci_reg_read4,
> +};
> +
> +static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
> +                               uint32_t value)
> +{
> +    PPCE500PCIState *pci = opaque;
> +    unsigned long win;
> +
> +    win = addr & 0xfe0;
> +
> +    pci_debug("%s: value:%x -> win:%lx(addr:%Lx)\n",__func__,value,win,addr);
> +
> +    switch (win) {
> +    case PPCE500_PCI_OW1:
> +    case PPCE500_PCI_OW2:
> +    case PPCE500_PCI_OW3:
> +    case PPCE500_PCI_OW4:
> +	switch (addr & 0xC) {
> +	case PCI_POTAR: pci->pob[(addr >> 5) & 0x7].potar = value; break;
> +	case PCI_POTEAR: pci->pob[(addr >> 5) & 0x7].potear = value; break;
> +	case PCI_POWBAR: pci->pob[(addr >> 5) & 0x7].powbar = value; break;
> +	case PCI_POWAR: pci->pob[(addr >> 5) & 0x7].powar = value; break;
> +	default: break;
> +	};
> +	break;
> +
> +    case PPCE500_PCI_IW3:
> +    case PPCE500_PCI_IW2:
> +    case PPCE500_PCI_IW1:
> +	switch (addr & 0xC) {
> +	case PCI_PITAR: pci->pib[(addr >> 5) & 0x3].pitar = value; break;
> +	case PCI_PIWBAR: pci->pib[(addr >> 5) & 0x3].piwbar = value; break;
> +	case PCI_PIWBEAR: pci->pib[(addr >> 5) & 0x3].piwbear = value; break;
> +	case PCI_PIWAR: pci->pib[(addr >> 5) & 0x3].piwar = value; break;
> +	default: break;
> +	};
> +	break;
> +
> +    case PPCE500_PCI_GASKET_TIMR:
> +	pci->gasket_time = value;
> +	break;
> +
> +    default:
> +	break;
> +    };
> +}
> +
> +static CPUWriteMemoryFunc *e500_pci_reg_write[] = {
> +    &pci_reg_write4,
> +    &pci_reg_write4,
> +    &pci_reg_write4,
> +};
> +
> +static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
> +{
> +    int devno = pci_dev->devfn >> 3, ret = 0;
> +
> +    switch (devno) {
> +	/* Two PCI slot */
> +	case 0x11:
> +	case 0x12:
> +	    ret = (irq_num + devno - 0x10) % 4;
> +	    break;
> +	default:
> +	    printf("Error:%s:unknow dev number\n", __func__);
> +    }

While I understand that the physical board only supports two PCI
devices, I wonder if we shouldn't actually support more in QEMU. Think
for example to virtio which can quickly takes two slots.

The Linux kernel is supporting IRQ sharing, so supporting more IRQ here
is probably something to do.

> +
> +    pci_debug("%s: devfn %x irq %d -> %d  devno:%x\n", __func__,
> +           pci_dev->devfn, irq_num, ret, devno);
> +
> +    return ret;
> +}
> +
> +static void mpc85xx_pci_set_irq(qemu_irq *pic, int irq_num, int level)
> +{
> +    pci_debug("%s: PCI irq %d, level:%d\n", __func__, irq_num, level);
> +
> +    qemu_set_irq(pic[irq_num], level);
> +}
> +
> +static void ppce500_pci_save(QEMUFile *f, void *opaque)
> +{
> +    PPCE500PCIState *controller = opaque;
> +    int i;
> +
> +    pci_device_save(controller->pci_dev, f);
> +
> +    for (i = 0; i < PPCE500_PCI_NR_POBS; i++) {
> +        qemu_put_be32s(f, &controller->pob[i].potar);
> +        qemu_put_be32s(f, &controller->pob[i].potear);
> +        qemu_put_be32s(f, &controller->pob[i].powbar);
> +        qemu_put_be32s(f, &controller->pob[i].powar);
> +    }
> +
> +    for (i = 0; i < PPCE500_PCI_NR_PIBS; i++) {
> +        qemu_put_be32s(f, &controller->pib[i].pitar);
> +        qemu_put_be32s(f, &controller->pib[i].piwbar);
> +        qemu_put_be32s(f, &controller->pib[i].piwbear);
> +        qemu_put_be32s(f, &controller->pib[i].piwar);
> +    }
> +    qemu_put_be32s(f, &controller->gasket_time);
> +}
> +
> +static int ppce500_pci_load(QEMUFile *f, void *opaque, int version_id)
> +{
> +    PPCE500PCIState *controller = opaque;
> +    int i;
> +
> +    if (version_id != 1)
> +        return -EINVAL;
> +
> +    pci_device_load(controller->pci_dev, f);
> +
> +    for (i = 0; i < PPCE500_PCI_NR_POBS; i++) {
> +        qemu_get_be32s(f, &controller->pob[i].potar);
> +        qemu_get_be32s(f, &controller->pob[i].potear);
> +        qemu_get_be32s(f, &controller->pob[i].powbar);
> +        qemu_get_be32s(f, &controller->pob[i].powar);
> +    }
> +
> +    for (i = 0; i < PPCE500_PCI_NR_PIBS; i++) {
> +        qemu_get_be32s(f, &controller->pib[i].pitar);
> +        qemu_get_be32s(f, &controller->pib[i].piwbar);
> +        qemu_get_be32s(f, &controller->pib[i].piwbear);
> +        qemu_get_be32s(f, &controller->pib[i].piwar);
> +    }
> +    qemu_get_be32s(f, &controller->gasket_time);
> +
> +    return 0;
> +}
> +
> +PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
> +{
> +    PPCE500PCIState *controller;
> +    PCIDevice *d;
> +    int index;
> +    static int ppce500_pci_id;
> +
> +    controller = qemu_mallocz(sizeof(PPCE500PCIState));
> +    if (!controller)
> +	return NULL;
> +
> +    controller->pci_state.bus = pci_register_bus(mpc85xx_pci_set_irq,
> +                                                 mpc85xx_pci_map_irq,
> +                                                 pci_irqs, 0x88, 4);
> +    d = pci_register_device(controller->pci_state.bus,
> +                            "host bridge", sizeof(PCIDevice),
> +                            0, NULL, NULL);
> +
> +    d->config[0x00] = 0x57; // vendor_id
> +    d->config[0x01] = 0x19;
> +    d->config[0x02] = 0x30; // device_id
> +    d->config[0x03] = 0x00;
> +    d->config[0x0a] = 0x20; // class_sub = other bridge type
> +    d->config[0x0b] = 0x0B; // class_base = PCI_bridge
> +
> +    controller->pci_dev = d;
> +
> +    /* CFGADDR */
> +    index = cpu_register_io_memory(0, pcie500_cfgaddr_read,
> +                                   pcie500_cfgaddr_write, controller);
> +    if (index < 0)
> +        goto free;
> +    cpu_register_physical_memory(registers + PCIE500_CFGADDR, 4, index);
> +
> +    /* CFGDATA */
> +    index = cpu_register_io_memory(0, pcie500_cfgdata_read,
> +                                   pcie500_cfgdata_write,
> +                                   &controller->pci_state);
> +    if (index < 0)
> +        goto free;
> +    cpu_register_physical_memory(registers + PCIE500_CFGDATA, 4, index);
> +
> +    index = cpu_register_io_memory(0, e500_pci_reg_read,
> +		                   e500_pci_reg_write, controller);
> +    if (index < 0)
> +	goto free;
> +    cpu_register_physical_memory(registers + PCIE500_REG_BASE,
> +                                   PCIE500_REG_SIZE, index);
> +
> +    /* XXX load/save code not tested. */
> +    register_savevm("ppce500_pci", ppce500_pci_id++, 1,
> +                    ppce500_pci_save, ppce500_pci_load, controller);
> +
> +    return controller->pci_state.bus;
> +
> +free:
> +    printf("%s error\n", __func__);
> +    qemu_free(controller);
> +    return NULL;
> +}
> -- 
> 1.5.4
> 
> 
> 
> 

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 3/6] kvm/powerpc: Add irq support for E500 core
  2009-01-22 10:14     ` [Qemu-devel] [PATCH 3/6] kvm/powerpc: Add irq support for E500 core Liu Yu
  2009-01-22 10:14       ` [Qemu-devel] [PATCH 4/6] kvm/powerpc: extern one function for MPC85xx code use Liu Yu
@ 2009-01-24 16:32       ` Aurelien Jarno
  2009-02-09  8:34         ` [Qemu-devel] [PATCH 3/6] kvm/powerpc: Add irq support for E500core Liu Yu-B13201
  1 sibling, 1 reply; 17+ messages in thread
From: Aurelien Jarno @ 2009-01-24 16:32 UTC (permalink / raw)
  To: Liu Yu; +Cc: kvm-ppc, qemu-devel, hollisb

On Thu, Jan 22, 2009 at 06:14:13PM +0800, Liu Yu wrote:
> Signed-off-by: Liu Yu <yu.liu@freescale.com>
> ---
>  hw/ppc.c                    |   89 +++++++++++++++++++++++++++++++++++++++++++
>  hw/ppc.h                    |    1 +
>  target-ppc/cpu.h            |   10 +++++
>  target-ppc/translate_init.c |    6 ++-
>  4 files changed, 104 insertions(+), 2 deletions(-)

The same comment for indentation as in the previous patch also applies
here, though it concerns very few lines here. I also have a few minor
comments below, but otherwise the patch is ok.

> diff --git a/hw/ppc.c b/hw/ppc.c
> index 05e787f..7a44951 100644
> --- a/hw/ppc.c
> +++ b/hw/ppc.c
> @@ -314,6 +314,95 @@ void ppc40x_irq_init (CPUState *env)
>                                                    env, PPC40x_INPUT_NB);
>  }
>  
> +/* PowerPC E500 internal IRQ controller */
> +static void ppce500_set_irq (void *opaque, int pin, int level)
> +{
> +    CPUState *env = opaque;
> +    int cur_level;
> +
> +#if defined(PPC_DEBUG_IRQ)
> +    if (loglevel & CPU_LOG_INT) {
> +        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
> +                env, pin, level);
> +    }
> +#endif
> +    cur_level = (env->irq_input_state >> pin) & 1;
> +    /* Don't generate spurious events */
> +    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
> +        switch (pin) {
> +        case PPCE500_INPUT_MCK:
> +            if (level) {
> +#if defined(PPC_DEBUG_IRQ)
> +                if (loglevel & CPU_LOG_INT) {
> +                    fprintf(logfile, "%s: reset the PowerPC system\n",
> +                            __func__);
> +                }
> +#endif

You should probably use LOG_IRQ() instead here which does exactly the
same as the code between the #if and #endif.

> +		fprintf(stderr,"PowerPC E500 reset core\n");
> +		qemu_system_reset_request();
> +            }
> +            break;
> +        case PPCE500_INPUT_RESET_CORE:
> +            if (level) {
> +#if defined(PPC_DEBUG_IRQ)
> +                if (loglevel & CPU_LOG_INT) {
> +                    fprintf(logfile, "%s: reset the PowerPC core\n", __func__);
> +                }
> +#endif
> +		ppc_set_irq(env, PPC_INTERRUPT_MCK, level);
> +            }
> +            break;
> +        case PPCE500_INPUT_CINT:
> +            /* Level sensitive - active high */
> +#if defined(PPC_DEBUG_IRQ)
> +            if (loglevel & CPU_LOG_INT) {
> +                fprintf(logfile, "%s: set the critical IRQ state to %d\n",
> +                        __func__, level);
> +            }
> +#endif

Same here.

> +            ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
> +            break;
> +        case PPCE500_INPUT_INT:
> +            /* Level sensitive - active high */
> +#if defined(PPC_DEBUG_IRQ)
> +            if (loglevel & CPU_LOG_INT) {
> +                fprintf(logfile, "%s: set the core IRQ state to %d\n",
> +                        __func__, level);
> +            }
> +#endif

Same here.

> +            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
> +            break;
> +        case PPCE500_INPUT_DEBUG:
> +            /* Level sensitive - active high */
> +#if defined(PPC_DEBUG_IRQ)
> +            if (loglevel & CPU_LOG_INT) {
> +                fprintf(logfile, "%s: set the debug pin state to %d\n",
> +                        __func__, level);
> +            }
> +#endif

Same here.

> +            ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
> +            break;
> +        default:
> +            /* Unknown pin - do nothing */
> +#if defined(PPC_DEBUG_IRQ)
> +            if (loglevel & CPU_LOG_INT) {
> +                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
> +            }
> +#endif

Same here.

> +            return;
> +        }
> +        if (level)
> +            env->irq_input_state |= 1 << pin;
> +        else
> +            env->irq_input_state &= ~(1 << pin);
> +    }
> +}
> +
> +void ppce500_irq_init (CPUState *env)
> +{
> +    env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq,
> +					env, PPCE500_INPUT_NB);
> +}
>  /*****************************************************************************/
>  /* PowerPC time base and decrementer emulation */
>  struct ppc_tb_t {
> diff --git a/hw/ppc.h b/hw/ppc.h
> index 75eb11a..2ec4680 100644
> --- a/hw/ppc.h
> +++ b/hw/ppc.h
> @@ -31,6 +31,7 @@ extern CPUReadMemoryFunc *PPC_io_read[];
>  void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val);
>  
>  void ppc40x_irq_init (CPUState *env);
> +void ppce500_irq_init (CPUState *env);
>  void ppc6xx_irq_init (CPUState *env);
>  void ppc970_irq_init (CPUState *env);
>  
> diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
> index f7a12da..0eb794f 100644
> --- a/target-ppc/cpu.h
> +++ b/target-ppc/cpu.h
> @@ -1352,6 +1352,16 @@ enum {
>  };
>  
>  enum {
> +    /* PowerPC E500 input pins */
> +    PPCE500_INPUT_RESET_CORE = 0,
> +    PPCE500_INPUT_MCK        = 1,
> +    PPCE500_INPUT_CINT       = 3,
> +    PPCE500_INPUT_INT        = 4,
> +    PPCE500_INPUT_DEBUG      = 6,
> +    PPCE500_INPUT_NB,
> +};
> +
> +enum {
>      /* PowerPC 40x input pins */
>      PPC40x_INPUT_RESET_CORE = 0,
>      PPC40x_INPUT_RESET_CHIP = 1,
> diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
> index 5008a3a..7953c69 100644
> --- a/target-ppc/translate_init.c
> +++ b/target-ppc/translate_init.c
> @@ -4154,7 +4154,8 @@ static void init_proc_e300 (CPUPPCState *env)
>                                POWERPC_FLAG_BUS_CLK)
>  #define check_pow_e500       check_pow_hid0
>  
> -__attribute__ (( unused ))
> +extern void ppce500_irq_init (CPUState *env);
> +

You should use PPC_IRQ_INIT_FN(e500) instead, see at the beginning of
translate_init.c.

>  static void init_proc_e500 (CPUPPCState *env)
>  {
>      /* Time base */
> @@ -4256,7 +4257,8 @@ static void init_proc_e500 (CPUPPCState *env)
>      init_excp_e200(env);
>      env->dcache_line_size = 32;
>      env->icache_line_size = 32;
> -    /* XXX: TODO: allocate internal IRQ controller */
> +    /* Allocate hardware IRQ controller */
> +    ppce500_irq_init(env);
>  }
>  
>  /* Non-embedded PowerPC                                                      */
> -- 
> 1.5.4
> 
> 
> 
> 

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 4/6] kvm/powerpc: extern one function for MPC85xx code use
  2009-01-22 10:14       ` [Qemu-devel] [PATCH 4/6] kvm/powerpc: extern one function for MPC85xx code use Liu Yu
  2009-01-22 10:14         ` [Qemu-devel] [PATCH 5/6] kvm/powerpc: Add MPC85xx board support Liu Yu
@ 2009-01-24 16:36         ` Aurelien Jarno
  1 sibling, 0 replies; 17+ messages in thread
From: Aurelien Jarno @ 2009-01-24 16:36 UTC (permalink / raw)
  To: Liu Yu; +Cc: kvm-ppc, qemu-devel, hollisb

On Thu, Jan 22, 2009 at 06:14:14PM +0800, Liu Yu wrote:
> Signed-off-by: Liu Yu <yu.liu@freescale.com>
> ---
>  target-ppc/kvm_ppc.c |    2 +-
>  target-ppc/kvm_ppc.h |    2 ++
>  2 files changed, 3 insertions(+), 1 deletions(-)

Thanks, applied.

> diff --git a/target-ppc/kvm_ppc.c b/target-ppc/kvm_ppc.c
> index f7ce52b..82c0f42 100644
> --- a/target-ppc/kvm_ppc.c
> +++ b/target-ppc/kvm_ppc.c
> @@ -22,7 +22,7 @@ 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,
> +int kvmppc_read_host_property(const char *node_path, const char *prop,
>                                       void *val, size_t len)
>  {
>      char *path;
> diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
> index e536a88..3792ef7 100644
> --- a/target-ppc/kvm_ppc.h
> +++ b/target-ppc/kvm_ppc.h
> @@ -11,5 +11,7 @@
>  
>  void kvmppc_init(void);
>  void kvmppc_fdt_update(void *fdt);
> +int kvmppc_read_host_property(const char *node_path, const char *prop,
> +                                     void *val, size_t len);
>  
>  #endif /* __KVM_PPC_H__ */
> -- 
> 1.5.4
> 
> 
> 
> 

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* [Qemu-devel] Regarding ARM11Mpcore MMC kernel panic.
  2009-01-22 16:13 ` [Qemu-devel] Re: [PATCH 0/6] kvm/powerpc: Add emulation for MPC85xx in KVM mode Hollis Blanchard
@ 2009-01-27  7:38   ` sathish kumar
  0 siblings, 0 replies; 17+ messages in thread
From: sathish kumar @ 2009-01-27  7:38 UTC (permalink / raw)
  To: qemu-devel

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

Hi,
i'm working getting MMC device working on Qemu with linux-2.6.24-arm Mpcore kernel.
But when i try to use MMC partition as root file system (Qemu command line .. -sd <mmc image> -append "root=/dev/mmcblk0 rw .."), i get kernel panic.

if anyone is working on Qemu ARM11mpcore, please provide some assistance regarding this MMC issue?

Regards,
Sathish.




________________________________


      Connect with friends all over the world. Get Yahoo! India Messenger at http://in.messenger.yahoo.com/?wm=n/

[-- Attachment #2: Type: text/html, Size: 1011 bytes --]

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

* RE: [Qemu-devel] [PATCH 2/6] kvm/powerpc: Add freescale pcicontroller's support
  2009-01-24 16:02     ` [Qemu-devel] [PATCH 2/6] kvm/powerpc: Add freescale pci controller's support Aurelien Jarno
@ 2009-02-09  8:33       ` Liu Yu-B13201
  2009-02-09 10:28         ` Aurelien Jarno
  0 siblings, 1 reply; 17+ messages in thread
From: Liu Yu-B13201 @ 2009-02-09  8:33 UTC (permalink / raw)
  To: Aurelien Jarno; +Cc: kvm-ppc, qemu-devel, hollisb

> -----Original Message-----
> From: Aurelien Jarno [mailto:aurelien@aurel32.net] 
> Sent: Sunday, January 25, 2009 12:03 AM
> To: Liu Yu-B13201
> Cc: hollisb@us.ibm.com; qemu-devel@nongnu.org; kvm-ppc@vger.kernel.org
> Subject: Re: [Qemu-devel] [PATCH 2/6] kvm/powerpc: Add 
> freescale pcicontroller's support
> 
> On Thu, Jan 22, 2009 at 06:14:12PM +0800, Liu Yu wrote:
> > This patch add the emulation of freescale's pci controller 
> for MPC85xx platform.
> > 
> > Signed-off-by: Liu Yu <yu.liu@freescale.com>
> 
> I have one general comment for this patch, QEMU (mostly) uses 
> spaces for
> indentation, while this patch uses spaces + tab. Would it be 
> possible to
> convert it to spaces only, using 4 spaces?

Fixed.

> 
> I also have one minor comment inside. Otherwise the patch looks ok.
> 
> >  Makefile.target  |    2 +
> >  hw/ppce500_pci.c |  370 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 372 insertions(+), 0 deletions(-)
> >  create mode 100644 hw/ppce500_pci.c
> > 
> > diff --git a/Makefile.target b/Makefile.target
> > index a091ce9..5cae257 100644
> > --- a/Makefile.target
> > +++ b/Makefile.target
> > @@ -598,6 +598,8 @@ 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 ppc440_bamboo.o
> > +# PowerPC E500 boards
> > +OBJS+= ppce500_pci.o
> >  ifdef FDT_LIBS
> >  OBJS+= device_tree.o
> >  LIBS+= $(FDT_LIBS)
> > diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
> > new file mode 100644
> > index 0000000..6325555
> > --- /dev/null
> > +++ b/hw/ppce500_pci.c
> > @@ -0,0 +1,370 @@
> > +/*
> > + * QEMU PowerPC E500 embedded processors pci controller emulation
> > + *
> > + * Copyright (C) 2009 Freescale Semiconductor, Inc. All 
> rights reserved.
> > + *
> > + * Author: Yu Liu,     <yu.liu@freescale.com>
> > + *
> > + * This file is derived from hw/ppc4xx_pci.c,
> > + * the copyright for that material belongs to the original owners.
> > + *
> > + * This is free software; you can redistribute it and/or modify
> > + * it under the terms of  the GNU General  Public License 
> as published by
> > + * the Free Software Foundation;  either version 2 of the  
> License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#include "hw.h"
> > +#include "ppc.h"
> > +#include "ppce500.h"
> > +typedef target_phys_addr_t pci_addr_t;
> > +#include "pci.h"
> > +#include "pci_host.h"
> > +#include "bswap.h"
> > +#include "qemu-log.h"
> > +
> > +#ifdef DEBUG_PCI
> > +#define pci_debug(fmt, arg...) fprintf(stderr, fmt, ##arg)
> > +#else
> > +#define pci_debug(fmt, arg...)
> > +#endif
> > +
> > +#define PCIE500_CFGADDR       0x0
> > +#define PCIE500_CFGDATA       0x4
> > +#define PCIE500_REG_BASE      0xC00
> > +#define PCIE500_REG_SIZE      (0x1000 - PCIE500_REG_BASE)
> > +
> > +#define PPCE500_PCI_CONFIG_ADDR		0x0
> > +#define PPCE500_PCI_CONFIG_DATA		0x4
> > +#define PPCE500_PCI_INTACK		0x8
> > +
> > +#define PPCE500_PCI_OW1			(0xC20 - 
> PCIE500_REG_BASE)
> > +#define PPCE500_PCI_OW2			(0xC40 - 
> PCIE500_REG_BASE)
> > +#define PPCE500_PCI_OW3			(0xC60 - 
> PCIE500_REG_BASE)
> > +#define PPCE500_PCI_OW4			(0xC80 - 
> PCIE500_REG_BASE)
> > +#define PPCE500_PCI_IW3			(0xDA0 - 
> PCIE500_REG_BASE)
> > +#define PPCE500_PCI_IW2			(0xDC0 - 
> PCIE500_REG_BASE)
> > +#define PPCE500_PCI_IW1			(0xDE0 - 
> PCIE500_REG_BASE)
> > +
> > +#define PPCE500_PCI_GASKET_TIMR		(0xE20 - 
> PCIE500_REG_BASE)
> > +
> > +#define PCI_POTAR		0x0
> > +#define PCI_POTEAR		0x4
> > +#define PCI_POWBAR		0x8
> > +#define PCI_POWAR		0x10
> > +
> > +#define PCI_PITAR		0x0
> > +#define PCI_PIWBAR		0x8
> > +#define PCI_PIWBEAR		0xC
> > +#define PCI_PIWAR		0x10
> > +
> > +#define PPCE500_PCI_NR_POBS 5
> > +#define PPCE500_PCI_NR_PIBS 3
> > +
> > +struct  pci_outbound {
> > +    uint32_t potar;
> > +    uint32_t potear;
> > +    uint32_t powbar;
> > +    uint32_t powar;
> > +};
> > +
> > +struct pci_inbound {
> > +    uint32_t pitar;
> > +    uint32_t piwbar;
> > +    uint32_t piwbear;
> > +    uint32_t piwar;
> > +};
> > +
> > +struct PPCE500PCIState {
> > +    struct pci_outbound pob[PPCE500_PCI_NR_POBS];
> > +    struct pci_inbound pib[PPCE500_PCI_NR_PIBS];
> > +    uint32_t gasket_time;
> > +    PCIHostState pci_state;
> > +    PCIDevice *pci_dev;
> > +};
> > +
> > +typedef struct PPCE500PCIState PPCE500PCIState;
> > +
> > +static uint32_t pcie500_cfgaddr_readl(void *opaque, 
> target_phys_addr_t addr)
> > +{
> > +    PPCE500PCIState *pci = opaque;
> > +
> > +    pci_debug("%s: (addr:%Lx) -> value:%x\n", __func__, addr,
> > +		    pci->pci_state.config_reg);
> > +    return pci->pci_state.config_reg;
> > +}
> > +
> > +static CPUReadMemoryFunc *pcie500_cfgaddr_read[] = {
> > +    &pcie500_cfgaddr_readl,
> > +    &pcie500_cfgaddr_readl,
> > +    &pcie500_cfgaddr_readl,
> > +};
> > +
> > +static void pcie500_cfgaddr_writel(void *opaque, 
> target_phys_addr_t addr,
> > +                                  uint32_t value)
> > +{
> > +    PPCE500PCIState *controller = opaque;
> > +
> > +    pci_debug("%s: value:%x -> (addr%Lx)\n", __func__, 
> value, addr);
> > +    controller->pci_state.config_reg = value & ~0x3;
> > +}
> > +
> > +static CPUWriteMemoryFunc *pcie500_cfgaddr_write[] = {
> > +    &pcie500_cfgaddr_writel,
> > +    &pcie500_cfgaddr_writel,
> > +    &pcie500_cfgaddr_writel,
> > +};
> > +
> > +static CPUReadMemoryFunc *pcie500_cfgdata_read[] = {
> > +    &pci_host_data_readb,
> > +    &pci_host_data_readw,
> > +    &pci_host_data_readl,
> > +};
> > +
> > +static CPUWriteMemoryFunc *pcie500_cfgdata_write[] = {
> > +    &pci_host_data_writeb,
> > +    &pci_host_data_writew,
> > +    &pci_host_data_writel,
> > +};
> > +
> > +static uint32_t pci_reg_read4(void *opaque, 
> target_phys_addr_t addr)
> > +{
> > +    PPCE500PCIState *pci = opaque;
> > +    unsigned long win;
> > +    uint32_t value = 0;
> > +
> > +    win = addr & 0xfe0;
> > +
> > +    switch (win) {
> > +    case PPCE500_PCI_OW1:
> > +    case PPCE500_PCI_OW2:
> > +    case PPCE500_PCI_OW3:
> > +    case PPCE500_PCI_OW4:
> > +	switch (addr & 0xC) {
> > +	case PCI_POTAR: value = pci->pob[(addr >> 5) & 
> 0x7].potar; break;
> > +	case PCI_POTEAR: value = pci->pob[(addr >> 5) & 
> 0x7].potear; break;
> > +	case PCI_POWBAR: value = pci->pob[(addr >> 5) & 
> 0x7].powbar; break;
> > +	case PCI_POWAR: value = pci->pob[(addr >> 5) & 
> 0x7].powar; break;
> > +	default: break;
> > +	}
> > +	break;
> > +
> > +    case PPCE500_PCI_IW3:
> > +    case PPCE500_PCI_IW2:
> > +    case PPCE500_PCI_IW1:
> > +	switch (addr & 0xC) {
> > +	case PCI_PITAR: value = pci->pib[(addr >> 5) & 
> 0x3].pitar; break;
> > +	case PCI_PIWBAR: value = pci->pib[(addr >> 5) & 
> 0x3].piwbar; break;
> > +	case PCI_PIWBEAR: value = pci->pib[(addr >> 5) & 
> 0x3].piwbear; break;
> > +	case PCI_PIWAR: value = pci->pib[(addr >> 5) & 
> 0x3].piwar; break;
> > +	default: break;
> > +	};
> > +	break;
> > +
> > +    case PPCE500_PCI_GASKET_TIMR:
> > +	value = pci->gasket_time;
> > +	break;
> > +
> > +    default:
> > +	break;
> > +    }
> > +
> > +    pci_debug("%s: win:%lx(addr:%Lx) -> 
> value:%x\n",__func__,win,addr,value);
> > +    return value;
> > +}
> > +
> > +static CPUReadMemoryFunc *e500_pci_reg_read[] = {
> > +    &pci_reg_read4,
> > +    &pci_reg_read4,
> > +    &pci_reg_read4,
> > +};
> > +
> > +static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
> > +                               uint32_t value)
> > +{
> > +    PPCE500PCIState *pci = opaque;
> > +    unsigned long win;
> > +
> > +    win = addr & 0xfe0;
> > +
> > +    pci_debug("%s: value:%x -> 
> win:%lx(addr:%Lx)\n",__func__,value,win,addr);
> > +
> > +    switch (win) {
> > +    case PPCE500_PCI_OW1:
> > +    case PPCE500_PCI_OW2:
> > +    case PPCE500_PCI_OW3:
> > +    case PPCE500_PCI_OW4:
> > +	switch (addr & 0xC) {
> > +	case PCI_POTAR: pci->pob[(addr >> 5) & 0x7].potar = 
> value; break;
> > +	case PCI_POTEAR: pci->pob[(addr >> 5) & 0x7].potear = 
> value; break;
> > +	case PCI_POWBAR: pci->pob[(addr >> 5) & 0x7].powbar = 
> value; break;
> > +	case PCI_POWAR: pci->pob[(addr >> 5) & 0x7].powar = 
> value; break;
> > +	default: break;
> > +	};
> > +	break;
> > +
> > +    case PPCE500_PCI_IW3:
> > +    case PPCE500_PCI_IW2:
> > +    case PPCE500_PCI_IW1:
> > +	switch (addr & 0xC) {
> > +	case PCI_PITAR: pci->pib[(addr >> 5) & 0x3].pitar = 
> value; break;
> > +	case PCI_PIWBAR: pci->pib[(addr >> 5) & 0x3].piwbar = 
> value; break;
> > +	case PCI_PIWBEAR: pci->pib[(addr >> 5) & 0x3].piwbear = 
> value; break;
> > +	case PCI_PIWAR: pci->pib[(addr >> 5) & 0x3].piwar = 
> value; break;
> > +	default: break;
> > +	};
> > +	break;
> > +
> > +    case PPCE500_PCI_GASKET_TIMR:
> > +	pci->gasket_time = value;
> > +	break;
> > +
> > +    default:
> > +	break;
> > +    };
> > +}
> > +
> > +static CPUWriteMemoryFunc *e500_pci_reg_write[] = {
> > +    &pci_reg_write4,
> > +    &pci_reg_write4,
> > +    &pci_reg_write4,
> > +};
> > +
> > +static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
> > +{
> > +    int devno = pci_dev->devfn >> 3, ret = 0;
> > +
> > +    switch (devno) {
> > +	/* Two PCI slot */
> > +	case 0x11:
> > +	case 0x12:
> > +	    ret = (irq_num + devno - 0x10) % 4;
> > +	    break;
> > +	default:
> > +	    printf("Error:%s:unknow dev number\n", __func__);
> > +    }
> 
> While I understand that the physical board only supports two PCI
> devices, I wonder if we shouldn't actually support more in QEMU. Think
> for example to virtio which can quickly takes two slots.

Certainly it could support more.
Here only support two is because MPC8544.dts says so, kernel will access pci device according to dts file.

The dts file in this patchset is copied from MPC8544's dts file, so we must keep it consistent here.

If we need more pci devices, I'd prefer to do it in a isolated patch, as we need modify both here and dts file.

> 
> The Linux kernel is supporting IRQ sharing, so supporting 
> more IRQ here
> is probably something to do.
> 

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

* RE: [Qemu-devel] [PATCH 3/6] kvm/powerpc: Add irq support for E500core
  2009-01-24 16:32       ` [Qemu-devel] [PATCH 3/6] kvm/powerpc: Add irq support for E500 core Aurelien Jarno
@ 2009-02-09  8:34         ` Liu Yu-B13201
  0 siblings, 0 replies; 17+ messages in thread
From: Liu Yu-B13201 @ 2009-02-09  8:34 UTC (permalink / raw)
  To: Aurelien Jarno; +Cc: kvm-ppc, qemu-devel, hollisb


> -----Original Message-----
> From: Aurelien Jarno [mailto:aurelien@aurel32.net] 
> Sent: Sunday, January 25, 2009 12:32 AM
> To: Liu Yu-B13201
> Cc: qemu-devel@nongnu.org; hollisb@us.ibm.com; kvm-ppc@vger.kernel.org
> Subject: Re: [Qemu-devel] [PATCH 3/6] kvm/powerpc: Add irq 
> support for E500core
> 
> On Thu, Jan 22, 2009 at 06:14:13PM +0800, Liu Yu wrote:
> > Signed-off-by: Liu Yu <yu.liu@freescale.com>
> > ---
> >  hw/ppc.c                    |   89 
> +++++++++++++++++++++++++++++++++++++++++++
> >  hw/ppc.h                    |    1 +
> >  target-ppc/cpu.h            |   10 +++++
> >  target-ppc/translate_init.c |    6 ++-
> >  4 files changed, 104 insertions(+), 2 deletions(-)
> 
> The same comment for indentation as in the previous patch also applies
> here, though it concerns very few lines here. I also have a few minor
> comments below, but otherwise the patch is ok.

Fixed.

> 
> > diff --git a/hw/ppc.c b/hw/ppc.c
> > index 05e787f..7a44951 100644
> > --- a/hw/ppc.c
> > +++ b/hw/ppc.c
> > @@ -314,6 +314,95 @@ void ppc40x_irq_init (CPUState *env)
> >                                                    env, 
> PPC40x_INPUT_NB);
> >  }
> >  
> > +/* PowerPC E500 internal IRQ controller */
> > +static void ppce500_set_irq (void *opaque, int pin, int level)
> > +{
> > +    CPUState *env = opaque;
> > +    int cur_level;
> > +
> > +#if defined(PPC_DEBUG_IRQ)
> > +    if (loglevel & CPU_LOG_INT) {
> > +        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
> > +                env, pin, level);
> > +    }
> > +#endif
> > +    cur_level = (env->irq_input_state >> pin) & 1;
> > +    /* Don't generate spurious events */
> > +    if ((cur_level == 1 && level == 0) || (cur_level == 0 
> && level != 0)) {
> > +        switch (pin) {
> > +        case PPCE500_INPUT_MCK:
> > +            if (level) {
> > +#if defined(PPC_DEBUG_IRQ)
> > +                if (loglevel & CPU_LOG_INT) {
> > +                    fprintf(logfile, "%s: reset the 
> PowerPC system\n",
> > +                            __func__);
> > +                }
> > +#endif
> 
> You should probably use LOG_IRQ() instead here which does exactly the
> same as the code between the #if and #endif.

Fixed.

> 
> > +		fprintf(stderr,"PowerPC E500 reset core\n");
> > +		qemu_system_reset_request();
> > +            }
> > +            break;
> > +        case PPCE500_INPUT_RESET_CORE:
> > +            if (level) {
> > +#if defined(PPC_DEBUG_IRQ)
> > +                if (loglevel & CPU_LOG_INT) {
> > +                    fprintf(logfile, "%s: reset the 
> PowerPC core\n", __func__);
> > +                }
> > +#endif
> > +		ppc_set_irq(env, PPC_INTERRUPT_MCK, level);
> > +            }
> > +            break;
> > +        case PPCE500_INPUT_CINT:
> > +            /* Level sensitive - active high */
> > +#if defined(PPC_DEBUG_IRQ)
> > +            if (loglevel & CPU_LOG_INT) {
> > +                fprintf(logfile, "%s: set the critical IRQ 
> state to %d\n",
> > +                        __func__, level);
> > +            }
> > +#endif
> 
> Same here.

Fixed.

> 
> > +            ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
> > +            break;
> > +        case PPCE500_INPUT_INT:
> > +            /* Level sensitive - active high */
> > +#if defined(PPC_DEBUG_IRQ)
> > +            if (loglevel & CPU_LOG_INT) {
> > +                fprintf(logfile, "%s: set the core IRQ 
> state to %d\n",
> > +                        __func__, level);
> > +            }
> > +#endif
> 
> Same here.

Fixed.

> 
> > +            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
> > +            break;
> > +        case PPCE500_INPUT_DEBUG:
> > +            /* Level sensitive - active high */
> > +#if defined(PPC_DEBUG_IRQ)
> > +            if (loglevel & CPU_LOG_INT) {
> > +                fprintf(logfile, "%s: set the debug pin 
> state to %d\n",
> > +                        __func__, level);
> > +            }
> > +#endif
> 
> Same here.

Fixed.

> 
> > +            ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
> > +            break;
> > +        default:
> > +            /* Unknown pin - do nothing */
> > +#if defined(PPC_DEBUG_IRQ)
> > +            if (loglevel & CPU_LOG_INT) {
> > +                fprintf(logfile, "%s: unknown IRQ pin 
> %d\n", __func__, pin);
> > +            }
> > +#endif
> 
> Same here.

Fixed.

> 
> > +            return;
> > +        }
> > +        if (level)
> > +            env->irq_input_state |= 1 << pin;
> > +        else
> > +            env->irq_input_state &= ~(1 << pin);
> > +    }
> > +}
> > +
> > +void ppce500_irq_init (CPUState *env)
> > +{
> > +    env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq,
> > +					env, PPCE500_INPUT_NB);
> > +}
> >  
> /*************************************************************
> ****************/
> >  /* PowerPC time base and decrementer emulation */
> >  struct ppc_tb_t {
> > diff --git a/hw/ppc.h b/hw/ppc.h
> > index 75eb11a..2ec4680 100644
> > --- a/hw/ppc.h
> > +++ b/hw/ppc.h
> > @@ -31,6 +31,7 @@ extern CPUReadMemoryFunc *PPC_io_read[];
> >  void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val);
> >  
> >  void ppc40x_irq_init (CPUState *env);
> > +void ppce500_irq_init (CPUState *env);
> >  void ppc6xx_irq_init (CPUState *env);
> >  void ppc970_irq_init (CPUState *env);
> >  
> > diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
> > index f7a12da..0eb794f 100644
> > --- a/target-ppc/cpu.h
> > +++ b/target-ppc/cpu.h
> > @@ -1352,6 +1352,16 @@ enum {
> >  };
> >  
> >  enum {
> > +    /* PowerPC E500 input pins */
> > +    PPCE500_INPUT_RESET_CORE = 0,
> > +    PPCE500_INPUT_MCK        = 1,
> > +    PPCE500_INPUT_CINT       = 3,
> > +    PPCE500_INPUT_INT        = 4,
> > +    PPCE500_INPUT_DEBUG      = 6,
> > +    PPCE500_INPUT_NB,
> > +};
> > +
> > +enum {
> >      /* PowerPC 40x input pins */
> >      PPC40x_INPUT_RESET_CORE = 0,
> >      PPC40x_INPUT_RESET_CHIP = 1,
> > diff --git a/target-ppc/translate_init.c 
> b/target-ppc/translate_init.c
> > index 5008a3a..7953c69 100644
> > --- a/target-ppc/translate_init.c
> > +++ b/target-ppc/translate_init.c
> > @@ -4154,7 +4154,8 @@ static void init_proc_e300 (CPUPPCState *env)
> >                                POWERPC_FLAG_BUS_CLK)
> >  #define check_pow_e500       check_pow_hid0
> >  
> > -__attribute__ (( unused ))
> > +extern void ppce500_irq_init (CPUState *env);
> > +
> 
> You should use PPC_IRQ_INIT_FN(e500) instead, see at the beginning of
> translate_init.c.

Fixed.

> 
> >  static void init_proc_e500 (CPUPPCState *env)
> >  {
> >      /* Time base */
> > @@ -4256,7 +4257,8 @@ static void init_proc_e500 (CPUPPCState *env)
> >      init_excp_e200(env);
> >      env->dcache_line_size = 32;
> >      env->icache_line_size = 32;
> > -    /* XXX: TODO: allocate internal IRQ controller */
> > +    /* Allocate hardware IRQ controller */
> > +    ppce500_irq_init(env);
> >  }
> >  
> >  /* Non-embedded PowerPC                                    
>                   */
> > -- 
> > 1.5.4
> > 
> > 
> > 
> > 
> 
> -- 
> Aurelien Jarno	                        GPG: 1024D/F1BCDB73
> aurelien@aurel32.net                 http://www.aurel32.net
> 
> 

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

* Re: [Qemu-devel] [PATCH 2/6] kvm/powerpc: Add freescale pcicontroller's support
  2009-02-09  8:33       ` [Qemu-devel] [PATCH 2/6] kvm/powerpc: Add freescale pcicontroller's support Liu Yu-B13201
@ 2009-02-09 10:28         ` Aurelien Jarno
  0 siblings, 0 replies; 17+ messages in thread
From: Aurelien Jarno @ 2009-02-09 10:28 UTC (permalink / raw)
  To: Liu Yu-B13201; +Cc: kvm-ppc, qemu-devel, hollisb

On Mon, Feb 09, 2009 at 04:33:25PM +0800, Liu Yu-B13201 wrote:
> > -----Original Message-----
> > From: Aurelien Jarno [mailto:aurelien@aurel32.net] 
> > Sent: Sunday, January 25, 2009 12:03 AM
> > To: Liu Yu-B13201
> > Cc: hollisb@us.ibm.com; qemu-devel@nongnu.org; kvm-ppc@vger.kernel.org
> > Subject: Re: [Qemu-devel] [PATCH 2/6] kvm/powerpc: Add 
> > freescale pcicontroller's support
> > 
> > On Thu, Jan 22, 2009 at 06:14:12PM +0800, Liu Yu wrote:
> > > This patch add the emulation of freescale's pci controller 
> > for MPC85xx platform.
> > > 
> > > Signed-off-by: Liu Yu <yu.liu@freescale.com>
> > 
> > I have one general comment for this patch, QEMU (mostly) uses 
> > spaces for
> > indentation, while this patch uses spaces + tab. Would it be 
> > possible to
> > convert it to spaces only, using 4 spaces?
> 
> Fixed.
> 
> > 
> > I also have one minor comment inside. Otherwise the patch looks ok.
> > 
> > >  Makefile.target  |    2 +
> > >  hw/ppce500_pci.c |  370 
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >  2 files changed, 372 insertions(+), 0 deletions(-)
> > >  create mode 100644 hw/ppce500_pci.c
> > > 
> > > diff --git a/Makefile.target b/Makefile.target
> > > index a091ce9..5cae257 100644
> > > --- a/Makefile.target
> > > +++ b/Makefile.target
> > > @@ -598,6 +598,8 @@ 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 ppc440_bamboo.o
> > > +# PowerPC E500 boards
> > > +OBJS+= ppce500_pci.o
> > >  ifdef FDT_LIBS
> > >  OBJS+= device_tree.o
> > >  LIBS+= $(FDT_LIBS)
> > > diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
> > > new file mode 100644
> > > index 0000000..6325555
> > > --- /dev/null
> > > +++ b/hw/ppce500_pci.c
> > > @@ -0,0 +1,370 @@
> > > +/*
> > > + * QEMU PowerPC E500 embedded processors pci controller emulation
> > > + *
> > > + * Copyright (C) 2009 Freescale Semiconductor, Inc. All 
> > rights reserved.
> > > + *
> > > + * Author: Yu Liu,     <yu.liu@freescale.com>
> > > + *
> > > + * This file is derived from hw/ppc4xx_pci.c,
> > > + * the copyright for that material belongs to the original owners.
> > > + *
> > > + * This is free software; you can redistribute it and/or modify
> > > + * it under the terms of  the GNU General  Public License 
> > as published by
> > > + * the Free Software Foundation;  either version 2 of the  
> > License, or
> > > + * (at your option) any later version.
> > > + */
> > > +
> > > +#include "hw.h"
> > > +#include "ppc.h"
> > > +#include "ppce500.h"
> > > +typedef target_phys_addr_t pci_addr_t;
> > > +#include "pci.h"
> > > +#include "pci_host.h"
> > > +#include "bswap.h"
> > > +#include "qemu-log.h"
> > > +
> > > +#ifdef DEBUG_PCI
> > > +#define pci_debug(fmt, arg...) fprintf(stderr, fmt, ##arg)
> > > +#else
> > > +#define pci_debug(fmt, arg...)
> > > +#endif
> > > +
> > > +#define PCIE500_CFGADDR       0x0
> > > +#define PCIE500_CFGDATA       0x4
> > > +#define PCIE500_REG_BASE      0xC00
> > > +#define PCIE500_REG_SIZE      (0x1000 - PCIE500_REG_BASE)
> > > +
> > > +#define PPCE500_PCI_CONFIG_ADDR		0x0
> > > +#define PPCE500_PCI_CONFIG_DATA		0x4
> > > +#define PPCE500_PCI_INTACK		0x8
> > > +
> > > +#define PPCE500_PCI_OW1			(0xC20 - 
> > PCIE500_REG_BASE)
> > > +#define PPCE500_PCI_OW2			(0xC40 - 
> > PCIE500_REG_BASE)
> > > +#define PPCE500_PCI_OW3			(0xC60 - 
> > PCIE500_REG_BASE)
> > > +#define PPCE500_PCI_OW4			(0xC80 - 
> > PCIE500_REG_BASE)
> > > +#define PPCE500_PCI_IW3			(0xDA0 - 
> > PCIE500_REG_BASE)
> > > +#define PPCE500_PCI_IW2			(0xDC0 - 
> > PCIE500_REG_BASE)
> > > +#define PPCE500_PCI_IW1			(0xDE0 - 
> > PCIE500_REG_BASE)
> > > +
> > > +#define PPCE500_PCI_GASKET_TIMR		(0xE20 - 
> > PCIE500_REG_BASE)
> > > +
> > > +#define PCI_POTAR		0x0
> > > +#define PCI_POTEAR		0x4
> > > +#define PCI_POWBAR		0x8
> > > +#define PCI_POWAR		0x10
> > > +
> > > +#define PCI_PITAR		0x0
> > > +#define PCI_PIWBAR		0x8
> > > +#define PCI_PIWBEAR		0xC
> > > +#define PCI_PIWAR		0x10
> > > +
> > > +#define PPCE500_PCI_NR_POBS 5
> > > +#define PPCE500_PCI_NR_PIBS 3
> > > +
> > > +struct  pci_outbound {
> > > +    uint32_t potar;
> > > +    uint32_t potear;
> > > +    uint32_t powbar;
> > > +    uint32_t powar;
> > > +};
> > > +
> > > +struct pci_inbound {
> > > +    uint32_t pitar;
> > > +    uint32_t piwbar;
> > > +    uint32_t piwbear;
> > > +    uint32_t piwar;
> > > +};
> > > +
> > > +struct PPCE500PCIState {
> > > +    struct pci_outbound pob[PPCE500_PCI_NR_POBS];
> > > +    struct pci_inbound pib[PPCE500_PCI_NR_PIBS];
> > > +    uint32_t gasket_time;
> > > +    PCIHostState pci_state;
> > > +    PCIDevice *pci_dev;
> > > +};
> > > +
> > > +typedef struct PPCE500PCIState PPCE500PCIState;
> > > +
> > > +static uint32_t pcie500_cfgaddr_readl(void *opaque, 
> > target_phys_addr_t addr)
> > > +{
> > > +    PPCE500PCIState *pci = opaque;
> > > +
> > > +    pci_debug("%s: (addr:%Lx) -> value:%x\n", __func__, addr,
> > > +		    pci->pci_state.config_reg);
> > > +    return pci->pci_state.config_reg;
> > > +}
> > > +
> > > +static CPUReadMemoryFunc *pcie500_cfgaddr_read[] = {
> > > +    &pcie500_cfgaddr_readl,
> > > +    &pcie500_cfgaddr_readl,
> > > +    &pcie500_cfgaddr_readl,
> > > +};
> > > +
> > > +static void pcie500_cfgaddr_writel(void *opaque, 
> > target_phys_addr_t addr,
> > > +                                  uint32_t value)
> > > +{
> > > +    PPCE500PCIState *controller = opaque;
> > > +
> > > +    pci_debug("%s: value:%x -> (addr%Lx)\n", __func__, 
> > value, addr);
> > > +    controller->pci_state.config_reg = value & ~0x3;
> > > +}
> > > +
> > > +static CPUWriteMemoryFunc *pcie500_cfgaddr_write[] = {
> > > +    &pcie500_cfgaddr_writel,
> > > +    &pcie500_cfgaddr_writel,
> > > +    &pcie500_cfgaddr_writel,
> > > +};
> > > +
> > > +static CPUReadMemoryFunc *pcie500_cfgdata_read[] = {
> > > +    &pci_host_data_readb,
> > > +    &pci_host_data_readw,
> > > +    &pci_host_data_readl,
> > > +};
> > > +
> > > +static CPUWriteMemoryFunc *pcie500_cfgdata_write[] = {
> > > +    &pci_host_data_writeb,
> > > +    &pci_host_data_writew,
> > > +    &pci_host_data_writel,
> > > +};
> > > +
> > > +static uint32_t pci_reg_read4(void *opaque, 
> > target_phys_addr_t addr)
> > > +{
> > > +    PPCE500PCIState *pci = opaque;
> > > +    unsigned long win;
> > > +    uint32_t value = 0;
> > > +
> > > +    win = addr & 0xfe0;
> > > +
> > > +    switch (win) {
> > > +    case PPCE500_PCI_OW1:
> > > +    case PPCE500_PCI_OW2:
> > > +    case PPCE500_PCI_OW3:
> > > +    case PPCE500_PCI_OW4:
> > > +	switch (addr & 0xC) {
> > > +	case PCI_POTAR: value = pci->pob[(addr >> 5) & 
> > 0x7].potar; break;
> > > +	case PCI_POTEAR: value = pci->pob[(addr >> 5) & 
> > 0x7].potear; break;
> > > +	case PCI_POWBAR: value = pci->pob[(addr >> 5) & 
> > 0x7].powbar; break;
> > > +	case PCI_POWAR: value = pci->pob[(addr >> 5) & 
> > 0x7].powar; break;
> > > +	default: break;
> > > +	}
> > > +	break;
> > > +
> > > +    case PPCE500_PCI_IW3:
> > > +    case PPCE500_PCI_IW2:
> > > +    case PPCE500_PCI_IW1:
> > > +	switch (addr & 0xC) {
> > > +	case PCI_PITAR: value = pci->pib[(addr >> 5) & 
> > 0x3].pitar; break;
> > > +	case PCI_PIWBAR: value = pci->pib[(addr >> 5) & 
> > 0x3].piwbar; break;
> > > +	case PCI_PIWBEAR: value = pci->pib[(addr >> 5) & 
> > 0x3].piwbear; break;
> > > +	case PCI_PIWAR: value = pci->pib[(addr >> 5) & 
> > 0x3].piwar; break;
> > > +	default: break;
> > > +	};
> > > +	break;
> > > +
> > > +    case PPCE500_PCI_GASKET_TIMR:
> > > +	value = pci->gasket_time;
> > > +	break;
> > > +
> > > +    default:
> > > +	break;
> > > +    }
> > > +
> > > +    pci_debug("%s: win:%lx(addr:%Lx) -> 
> > value:%x\n",__func__,win,addr,value);
> > > +    return value;
> > > +}
> > > +
> > > +static CPUReadMemoryFunc *e500_pci_reg_read[] = {
> > > +    &pci_reg_read4,
> > > +    &pci_reg_read4,
> > > +    &pci_reg_read4,
> > > +};
> > > +
> > > +static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
> > > +                               uint32_t value)
> > > +{
> > > +    PPCE500PCIState *pci = opaque;
> > > +    unsigned long win;
> > > +
> > > +    win = addr & 0xfe0;
> > > +
> > > +    pci_debug("%s: value:%x -> 
> > win:%lx(addr:%Lx)\n",__func__,value,win,addr);
> > > +
> > > +    switch (win) {
> > > +    case PPCE500_PCI_OW1:
> > > +    case PPCE500_PCI_OW2:
> > > +    case PPCE500_PCI_OW3:
> > > +    case PPCE500_PCI_OW4:
> > > +	switch (addr & 0xC) {
> > > +	case PCI_POTAR: pci->pob[(addr >> 5) & 0x7].potar = 
> > value; break;
> > > +	case PCI_POTEAR: pci->pob[(addr >> 5) & 0x7].potear = 
> > value; break;
> > > +	case PCI_POWBAR: pci->pob[(addr >> 5) & 0x7].powbar = 
> > value; break;
> > > +	case PCI_POWAR: pci->pob[(addr >> 5) & 0x7].powar = 
> > value; break;
> > > +	default: break;
> > > +	};
> > > +	break;
> > > +
> > > +    case PPCE500_PCI_IW3:
> > > +    case PPCE500_PCI_IW2:
> > > +    case PPCE500_PCI_IW1:
> > > +	switch (addr & 0xC) {
> > > +	case PCI_PITAR: pci->pib[(addr >> 5) & 0x3].pitar = 
> > value; break;
> > > +	case PCI_PIWBAR: pci->pib[(addr >> 5) & 0x3].piwbar = 
> > value; break;
> > > +	case PCI_PIWBEAR: pci->pib[(addr >> 5) & 0x3].piwbear = 
> > value; break;
> > > +	case PCI_PIWAR: pci->pib[(addr >> 5) & 0x3].piwar = 
> > value; break;
> > > +	default: break;
> > > +	};
> > > +	break;
> > > +
> > > +    case PPCE500_PCI_GASKET_TIMR:
> > > +	pci->gasket_time = value;
> > > +	break;
> > > +
> > > +    default:
> > > +	break;
> > > +    };
> > > +}
> > > +
> > > +static CPUWriteMemoryFunc *e500_pci_reg_write[] = {
> > > +    &pci_reg_write4,
> > > +    &pci_reg_write4,
> > > +    &pci_reg_write4,
> > > +};
> > > +
> > > +static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
> > > +{
> > > +    int devno = pci_dev->devfn >> 3, ret = 0;
> > > +
> > > +    switch (devno) {
> > > +	/* Two PCI slot */
> > > +	case 0x11:
> > > +	case 0x12:
> > > +	    ret = (irq_num + devno - 0x10) % 4;
> > > +	    break;
> > > +	default:
> > > +	    printf("Error:%s:unknow dev number\n", __func__);
> > > +    }
> > 
> > While I understand that the physical board only supports two PCI
> > devices, I wonder if we shouldn't actually support more in QEMU. Think
> > for example to virtio which can quickly takes two slots.
> 
> Certainly it could support more.
> Here only support two is because MPC8544.dts says so, kernel will access pci device according to dts file.
> 
> The dts file in this patchset is copied from MPC8544's dts file, so we must keep it consistent here.
> 
> If we need more pci devices, I'd prefer to do it in a isolated patch, as we need modify both here and dts file.
> 

I see, then it's fine with me.

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

end of thread, other threads:[~2009-02-09 15:15 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-22 10:14 [Qemu-devel] [PATCH 0/6] kvm/powerpc: Add emulation for MPC85xx in KVM mode Liu Yu
2009-01-22 10:14 ` [Qemu-devel] [PATCH 1/6] kvm/powerpc: Enable MPIC for MPC85xx platform Liu Yu
2009-01-22 10:14   ` [Qemu-devel] [PATCH 2/6] kvm/powerpc: Add freescale pci controller's support Liu Yu
2009-01-22 10:14     ` [Qemu-devel] [PATCH 3/6] kvm/powerpc: Add irq support for E500 core Liu Yu
2009-01-22 10:14       ` [Qemu-devel] [PATCH 4/6] kvm/powerpc: extern one function for MPC85xx code use Liu Yu
2009-01-22 10:14         ` [Qemu-devel] [PATCH 5/6] kvm/powerpc: Add MPC85xx board support Liu Yu
2009-01-22 10:14           ` [Qemu-devel] [PATCH 6/6] kvm/powerpc: flat device tree files for MPC85xx Liu Yu
2009-01-22 15:54             ` [Qemu-devel] " Hollis Blanchard
2009-01-22 16:05           ` [Qemu-devel] Re: [PATCH 5/6] kvm/powerpc: Add MPC85xx board support Hollis Blanchard
2009-01-24 16:36         ` [Qemu-devel] [PATCH 4/6] kvm/powerpc: extern one function for MPC85xx code use Aurelien Jarno
2009-01-24 16:32       ` [Qemu-devel] [PATCH 3/6] kvm/powerpc: Add irq support for E500 core Aurelien Jarno
2009-02-09  8:34         ` [Qemu-devel] [PATCH 3/6] kvm/powerpc: Add irq support for E500core Liu Yu-B13201
2009-01-24 16:02     ` [Qemu-devel] [PATCH 2/6] kvm/powerpc: Add freescale pci controller's support Aurelien Jarno
2009-02-09  8:33       ` [Qemu-devel] [PATCH 2/6] kvm/powerpc: Add freescale pcicontroller's support Liu Yu-B13201
2009-02-09 10:28         ` Aurelien Jarno
2009-01-22 16:13 ` [Qemu-devel] Re: [PATCH 0/6] kvm/powerpc: Add emulation for MPC85xx in KVM mode Hollis Blanchard
2009-01-27  7:38   ` [Qemu-devel] Regarding ARM11Mpcore MMC kernel panic sathish kumar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).