qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH 3/9] powerpc/kvm: Enable mpic for E500 platform


From: Anthony Liguori
Subject: Re: [Qemu-devel] [PATCH 3/9] powerpc/kvm: Enable mpic for E500 platform
Date: Thu, 15 Jan 2009 15:22:46 -0600
User-agent: Thunderbird 2.0.0.19 (X11/20090105)

Liu Yu wrote:
The modify is based on original author's method
to switch openpic and mpic by static define,
like the switch between USE_INTEL_GW80314 and USE_MPCxxx.
(Although the support for intel has broken)
So they can't be used at the same time.

I guess it's not the correct way to do this.
but I am not sure is the USE_MPC85xx and openpic are still needed?

Have you tested some of the other (TCG) boards (for instance, with the debian image Aurelien recently posted)?

Regards,

Anthony Liguori

Signed-off-by: Liu Yu <address@hidden>
---
 hw/openpic.c |  384 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 hw/openpic.h |   19 +++
 hw/ppc_mac.h |   14 +--
 3 files changed, 389 insertions(+), 28 deletions(-)
 create mode 100644 hw/openpic.h

diff --git a/hw/openpic.c b/hw/openpic.c
index b8da4d7..bc5f72b 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,8 @@
 #endif
 #define ERROR(fmr, args...) do { printf("ERROR: " fmr , ##args); } while (0)
-#define USE_MPCxxx /* Intel model is broken, for now */
+/*#define USE_MPCxxx |+ Intel model is broken, for now +|*/
+#define USE_MPC85xx /* Intel model is broken, for now */
#if defined (USE_INTEL_GW80314)
 /* Intel GW80314 I/O Companion chip */
@@ -84,15 +86,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 +98,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 +205,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 +249,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 +337,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 +602,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 +869,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 +1052,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 +1114,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__) */





reply via email to

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