From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LNZg4-0003y1-Cr for qemu-devel@nongnu.org; Thu, 15 Jan 2009 16:23:00 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LNZg3-0003xN-5E for qemu-devel@nongnu.org; Thu, 15 Jan 2009 16:23:00 -0500 Received: from [199.232.76.173] (port=44772 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LNZg2-0003xK-UI for qemu-devel@nongnu.org; Thu, 15 Jan 2009 16:22:58 -0500 Received: from mail-qy0-f20.google.com ([209.85.221.20]:53665) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LNZg2-0006TE-DA for qemu-devel@nongnu.org; Thu, 15 Jan 2009 16:22:58 -0500 Received: by qyk13 with SMTP id 13so1947886qyk.10 for ; Thu, 15 Jan 2009 13:22:58 -0800 (PST) Message-ID: <496FA926.1040205@codemonkey.ws> Date: Thu, 15 Jan 2009 15:22:46 -0600 From: Anthony Liguori MIME-Version: 1.0 Subject: Re: [Qemu-devel] [PATCH 3/9] powerpc/kvm: Enable mpic for E500 platform References: <1232022857-2315-1-git-send-email-yu.liu@freescale.com> <1232022857-2315-2-git-send-email-yu.liu@freescale.com> <1232022857-2315-3-git-send-email-yu.liu@freescale.com> <1232022857-2315-4-git-send-email-yu.liu@freescale.com> In-Reply-To: <1232022857-2315-4-git-send-email-yu.liu@freescale.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Liu Yu , kvm-ppc@vger.kernel.org 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 > --- > 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__) */ >