Re: [Qemu-devel] [PATCH 01/17] openpic: debug w/ info_report()

2017-11-26 Thread David Gibson
On Sun, Nov 26, 2017 at 03:58:59PM -0600, Michael Davidsaver wrote:
> Replace *printf() with *_report().
> Remove trailing new lines.
> 
> Signed-off-by: Michael Davidsaver 

Applied to ppc-for-2.12.

> ---
>  hw/intc/openpic.c | 102 
> +++---
>  1 file changed, 51 insertions(+), 51 deletions(-)
> 
> diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c
> index 10d6e871fb..9159a06f07 100644
> --- a/hw/intc/openpic.c
> +++ b/hw/intc/openpic.c
> @@ -46,6 +46,7 @@
>  #include "qapi/qmp/qerror.h"
>  #include "qemu/log.h"
>  #include "qemu/timer.h"
> +#include "qemu/error-report.h"
>  
>  //#define DEBUG_OPENPIC
>  
> @@ -58,8 +59,7 @@ static const int debug_openpic = 0;
>  static int get_current_cpu(void);
>  #define DPRINTF(fmt, ...) do { \
>  if (debug_openpic) { \
> -printf("Core%d: ", get_current_cpu()); \
> -printf(fmt , ## __VA_ARGS__); \
> +info_report("Core%d: " fmt, get_current_cpu(), ## __VA_ARGS__); \
>  } \
>  } while (0)
>  
> @@ -173,7 +173,7 @@ static int inttgt_to_output(int inttgt)
>  }
>  }
>  
> -fprintf(stderr, "%s: unsupported inttgt %d\n", __func__, inttgt);
> +error_report("%s: unsupported inttgt %d", __func__, inttgt);
>  return OPENPIC_OUTPUT_INT;
>  }
>  
> @@ -372,7 +372,7 @@ static void IRQ_check(OpenPICState *opp, IRQQueue *q)
>  break;
>  }
>  
> -DPRINTF("IRQ_check: irq %d set ivpr_pr=%d pr=%d\n",
> +DPRINTF("IRQ_check: irq %d set ivpr_pr=%d pr=%d",
>  irq, IVPR_PRIORITY(opp->src[irq].ivpr), priority);
>  
>  if (IVPR_PRIORITY(opp->src[irq].ivpr) > priority) {
> @@ -403,11 +403,11 @@ static void IRQ_local_pipe(OpenPICState *opp, int 
> n_CPU, int n_IRQ,
>  dst = &opp->dst[n_CPU];
>  src = &opp->src[n_IRQ];
>  
> -DPRINTF("%s: IRQ %d active %d was %d\n",
> +DPRINTF("%s: IRQ %d active %d was %d",
>  __func__, n_IRQ, active, was_active);
>  
>  if (src->output != OPENPIC_OUTPUT_INT) {
> -DPRINTF("%s: output %d irq %d active %d was %d count %d\n",
> +DPRINTF("%s: output %d irq %d active %d was %d count %d",
>  __func__, src->output, n_IRQ, active, was_active,
>  dst->outputs_active[src->output]);
>  
> @@ -417,13 +417,13 @@ static void IRQ_local_pipe(OpenPICState *opp, int 
> n_CPU, int n_IRQ,
>   */
>  if (active) {
>  if (!was_active && dst->outputs_active[src->output]++ == 0) {
> -DPRINTF("%s: Raise OpenPIC output %d cpu %d irq %d\n",
> +DPRINTF("%s: Raise OpenPIC output %d cpu %d irq %d",
>  __func__, src->output, n_CPU, n_IRQ);
>  qemu_irq_raise(dst->irqs[src->output]);
>  }
>  } else {
>  if (was_active && --dst->outputs_active[src->output] == 0) {
> -DPRINTF("%s: Lower OpenPIC output %d cpu %d irq %d\n",
> +DPRINTF("%s: Lower OpenPIC output %d cpu %d irq %d",
>  __func__, src->output, n_CPU, n_IRQ);
>  qemu_irq_lower(dst->irqs[src->output]);
>  }
> @@ -446,7 +446,7 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, 
> int n_IRQ,
>  IRQ_check(opp, &dst->raised);
>  
>  if (active && priority <= dst->ctpr) {
> -DPRINTF("%s: IRQ %d priority %d too low for ctpr %d on CPU %d\n",
> +DPRINTF("%s: IRQ %d priority %d too low for ctpr %d on CPU %d",
>  __func__, n_IRQ, priority, dst->ctpr, n_CPU);
>  active = 0;
>  }
> @@ -454,10 +454,10 @@ static void IRQ_local_pipe(OpenPICState *opp, int 
> n_CPU, int n_IRQ,
>  if (active) {
>  if (IRQ_get_next(opp, &dst->servicing) >= 0 &&
>  priority <= dst->servicing.priority) {
> -DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
> +DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d",
>  __func__, n_IRQ, dst->servicing.next, n_CPU);
>  } else {
> -DPRINTF("%s: Raise OpenPIC INT output cpu %d irq %d/%d\n",
> +DPRINTF("%s: Raise OpenPIC INT output cpu %d irq %d/%d",
>  __func__, n_CPU, n_IRQ, dst->raised.next);
>  qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
>  }
> @@ -465,12 +465,12 @@ static void IRQ_local_pipe(OpenPICState *opp, int 
> n_CPU, int n_IRQ,
>  IRQ_get_next(opp, &dst->servicing);
>  if (dst->raised.priority > dst->ctpr &&
>  dst->raised.priority > dst->servicing.priority) {
> -DPRINTF("%s: IRQ %d inactive, IRQ %d prio %d above %d/%d, CPU 
> %d\n",
> +DPRINTF("%s: IRQ %d inactive, IRQ %d prio %d above %d/%d, CPU 
> %d",
>  __func__, n_IRQ, dst->raised.next, dst->raised.priority,
>  dst->ctpr, dst->servicing.priority, n_CPU);
>   

Re: [Qemu-devel] [PATCH v4 3/3] spapr/rtas: do not reset the MSR in stop-self command

2017-11-26 Thread David Gibson
On Fri, Nov 24, 2017 at 08:05:50AM +0100, Cédric Le Goater wrote:
> When a CPU is stopped with the 'stop-self' RTAS call, its state
> 'halted' is switched to 1 and, in this case, the MSR is not taken into
> account anymore in the cpu_has_work() routine. Only the pending
> hardware interrupts are checked with their LPCR:PECE* enablement bit.
> 
> The CPU is now also protected from the decrementer interrupt by the
> LPCR:PECE* bits which are disabled in the 'stop-self' RTAS
> call. Reseting the MSR is pointless.
> 
> Signed-off-by: Cédric Le Goater 
> Reviewed-by: David Gibson 

Applied to ppc-for-2.12.

> ---
>  hw/ppc/spapr_rtas.c | 10 --
>  1 file changed, 10 deletions(-)
> 
> diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
> index 858adb1bf3a9..4bb939d3d111 100644
> --- a/hw/ppc/spapr_rtas.c
> +++ b/hw/ppc/spapr_rtas.c
> @@ -206,16 +206,6 @@ static void rtas_stop_self(PowerPCCPU *cpu, 
> sPAPRMachineState *spapr,
>  
>  cs->halted = 1;
>  qemu_cpu_kick(cs);
> -/*
> - * While stopping a CPU, the guest calls H_CPPR which
> - * effectively disables interrupts on XICS level.
> - * However decrementer interrupts in TCG can still
> - * wake the CPU up so here we disable interrupts in MSR
> - * as well.
> - * As rtas_start_cpu() resets the whole MSR anyway, there is
> - * no need to bother with specific bits, we just clear it.
> - */
> -env->msr = 0;
>  
>  /* Disable Power-saving mode Exit Cause exceptions for the CPU.
>   * This could deliver an interrupt on a dying CPU and crash the

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [Qemu-devel] [Qemu-ppc] [PATCH 01/25] ppc/xics: introduce an icp_create() helper

2017-11-26 Thread David Gibson
On Fri, Nov 24, 2017 at 10:55:47AM +0100, Greg Kurz wrote:
> On Fri, 24 Nov 2017 13:51:00 +1100
> David Gibson  wrote:
> 
> > On Thu, Nov 23, 2017 at 02:29:31PM +0100, Cédric Le Goater wrote:
> > > The sPAPR and the PowerNV core objects create the interrupt presenter
> > > object of the CPUs in a very similar way. Let's provide a common
> > > routine in which we use the presenter 'type' as a child identifier.
> > > 
> > > Signed-off-by: Cédric Le Goater   
> > 
> > One tiny nit.., apart from that
> > 
> > Reviewed-by: David Gibson 
> > 
> > > ---
> > >  hw/intc/xics.c  | 22 ++
> > >  hw/ppc/pnv_core.c   | 10 +-
> > >  hw/ppc/spapr_cpu_core.c | 13 ++---
> > >  include/hw/ppc/xics.h   |  3 +++
> > >  4 files changed, 28 insertions(+), 20 deletions(-)
> > > 
> > > diff --git a/hw/intc/xics.c b/hw/intc/xics.c
> > > index a1cc0e420c98..e4ccdff8f577 100644
> > > --- a/hw/intc/xics.c
> > > +++ b/hw/intc/xics.c
> > > @@ -384,6 +384,28 @@ static const TypeInfo icp_info = {
> > >  .class_size = sizeof(ICPStateClass),
> > >  };
> > >  
> > > +Object *icp_create(CPUState *cs, const char *type, XICSFabric *xi, Error 
> > > **errp)
> > > +{
> > > +Object *child = OBJECT(cs);  
> > 
> > In the original context 'child' made sense, since it was the child
> > object of the core.  Here, it's misleading, since it's the parent of
> > the xics link.  It's only used in a couple of places, so I suggest you
> 
> Oops yes :)
> 
> > just opencode OBJECT(cs) in each place.
> > 
> 
> or rename child to owner, as it is done with DRCs and TCE tables.

Sure.  Either's fine by me.


-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [Qemu-devel] [PATCH 07/17] e500: fix pci host bridge class/type

2017-11-26 Thread David Gibson
On Sun, Nov 26, 2017 at 03:59:05PM -0600, Michael Davidsaver wrote:
> Correct some confusion wrt. the PCI facing
> side of the PCI host bridge (not PCIe root complex).
> The ref. manual for the mpc8533 (as well as
> mpc8540 and mpc8540) give the class code as
> PCI_CLASS_PROCESSOR_POWERPC.
> While the PCI_HEADER_TYPE field is oddly omitted,
> the tables in the "PCI Configuration Header"
> section shows a type 0 layout using all 6 BAR
> registers (as 2x 32, and 2x 64 bit regions)
> 
> So 997505065dc92e533debf5cb23012ba4e673d387
> seems to be in error.  Although there was
> perhaps some confusion as the mpc8533
> has a separate PCIe root complex.
> With PCIe, a root complex has PCI_HEADER_TYPE=1.
> 
> Neither the PCI host bridge, nor the PCIe
> root complex advertise class PCI_CLASS_BRIDGE_PCI.
> 
> This was confusing Linux guests, which try
> to interpret the host bridge as a pci-pci
> bridge, but get confused and re-enumerate
> the bus when the primary/secondary/subordinate
> bus registers don't have valid values.
> 
> Signed-off-by: Michael Davidsaver 

Applied to ppc-for-2.12.

> ---
>  hw/pci-host/ppce500.c | 5 -
>  1 file changed, 5 deletions(-)
> 
> diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c
> index f2d108bc8a..8073d396ff 100644
> --- a/hw/pci-host/ppce500.c
> +++ b/hw/pci-host/ppce500.c
> @@ -423,11 +423,6 @@ static void e500_pcihost_bridge_realize(PCIDevice *d, 
> Error **errp)
>"/e500-ccsr"));
>  MemoryRegion *ccsr_mr = sysbus_mmio_get_region(ccsr, 0);
>  
> -pci_config_set_class(d->config, PCI_CLASS_BRIDGE_PCI);
> -d->config[PCI_HEADER_TYPE] =
> -(d->config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MULTI_FUNCTION) |
> -PCI_HEADER_TYPE_BRIDGE;
> -
>  memory_region_init_alias(&b->bar0, OBJECT(ccsr), "e500-pci-bar0", 
> ccsr_mr,
>   0, memory_region_size(ccsr_mr));
>  pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &b->bar0);

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [Qemu-devel] [PATCH v4 2/3] spapr/rtas: fix reboot of a a SMP TCG guest

2017-11-26 Thread David Gibson
On Fri, Nov 24, 2017 at 08:05:49AM +0100, Cédric Le Goater wrote:
> Just like for hot unplug CPUs, when a guest is rebooted, the secondary
> CPUs can be awaken by the decrementer and start entering SLOF at the
> same time the boot CPU is.
> 
> To be safe, let's disable on the secondaries all the exceptions which
> can cause an exit while the CPU is in power-saving mode.
> 
> Based on previous work from Nikunj A Dadhania 
> 
> Signed-off-by: Cédric Le Goater 
> Reviewed-by: David Gibson 

Applied to ppc-for-2.12.

> ---
> 
> Changes in v4:
> 
>  - used the 'lpcr_pm' field of PowerPCCPUClass
> 
> Changes in v3:
> 
>  - used the cpu_ppc_papr_pece_bits() helper 
> 
>  hw/ppc/spapr_cpu_core.c | 8 
>  1 file changed, 8 insertions(+)
> 
> diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
> index 3a4c17401226..a2290528542d 100644
> --- a/hw/ppc/spapr_cpu_core.c
> +++ b/hw/ppc/spapr_cpu_core.c
> @@ -26,6 +26,7 @@ static void spapr_cpu_reset(void *opaque)
>  PowerPCCPU *cpu = opaque;
>  CPUState *cs = CPU(cpu);
>  CPUPPCState *env = &cpu->env;
> +PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
>  
>  cpu_reset(cs);
>  
> @@ -35,6 +36,13 @@ static void spapr_cpu_reset(void *opaque)
>  cs->halted = 1;
>  
>  env->spr[SPR_HIOR] = 0;
> +
> +/* Disable Power-saving mode Exit Cause exceptions for the CPU.
> + * This can cause issues when rebooting the guest if a secondary
> + * is awaken */
> +if (cs != first_cpu) {
> +env->spr[SPR_LPCR] &= ~pcc->lpcr_pm;
> +}
>  }
>  
>  static void spapr_cpu_destroy(PowerPCCPU *cpu)

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [Qemu-devel] [PATCH 03/17] i2c: add mpc8540 i2c controller

2017-11-26 Thread David Gibson
On Sun, Nov 26, 2017 at 03:59:01PM -0600, Michael Davidsaver wrote:
> Signed-off-by: Michael Davidsaver 
> ---
>  hw/i2c/Makefile.objs |   1 +
>  hw/i2c/mpc8540_i2c.c | 307 
> +++
>  hw/i2c/trace-events  |   6 +
>  3 files changed, 314 insertions(+)
>  create mode 100644 hw/i2c/mpc8540_i2c.c
> 
> diff --git a/hw/i2c/Makefile.objs b/hw/i2c/Makefile.objs
> index 0594dea3ae..79af1dd901 100644
> --- a/hw/i2c/Makefile.objs
> +++ b/hw/i2c/Makefile.objs
> @@ -9,3 +9,4 @@ common-obj-$(CONFIG_IMX_I2C) += imx_i2c.o
>  common-obj-$(CONFIG_ASPEED_SOC) += aspeed_i2c.o
>  obj-$(CONFIG_OMAP) += omap_i2c.o
>  obj-$(CONFIG_PPC4XX) += ppc4xx_i2c.o
> +obj-$(CONFIG_E500) += mpc8540_i2c.o
> diff --git a/hw/i2c/mpc8540_i2c.c b/hw/i2c/mpc8540_i2c.c
> new file mode 100644
> index 00..b9f5773b35
> --- /dev/null
> +++ b/hw/i2c/mpc8540_i2c.c
> @@ -0,0 +1,307 @@
> +/*
> + * MPC8540 I2C bus interface
> + * As described in
> + * MPC8540 PowerQUICC III Integrated Host Processor Reference Manual, Rev. 1
> + * Part 2 chapter 11
> + *
> + * Compatible I2C controllers are found on other Freescale chips
> + * including mpc8544 and P2010.
> + *
> + * Copyright (c) 2015 Michael Davidsaver
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2.  See
> + * the LICENSE file in the top-level directory.
> + */
> +#include "qemu/osdep.h"
> +#include "qemu/log.h"
> +#include "hw/hw.h"
> +#include "hw/registerfields.h"
> +#include "hw/i2c/i2c.h"
> +#include "hw/sysbus.h"
> +#include "qemu/error-report.h"
> +
> +#include "trace.h"
> +
> +/* #define DEBUG_LVL 0 */
> +
> +#ifdef DEBUG_LVL
> +#define DPRINTK(LVL, FMT, ...) do { \
> +if ((LVL) <= DEBUG_LVL) {\
> +info_report(TYPE_MPC8540_I2C " : " FMT, ## __VA_ARGS__); \
> +} } while (0)
> +#else
> +#define DPRINTK(LVL, FMT, ...) do {} while (0)
> +#endif

So, you have both this DPRINTK stuff, and some trace events, which
seems a bit odd?  Why not just one or the other.

> +
> +#define LOG(MSK, FMT, ...) qemu_log_mask(MSK, TYPE_MPC8540_I2C \
> +" : " FMT "\n", ## __VA_ARGS__)
> +
> +#define TYPE_MPC8540_I2C "mpc8540-i2c"
> +#define MPC8540_I2C(obj) OBJECT_CHECK(MPC8540I2CState, (obj), 
> TYPE_MPC8540_I2C)
> +
> +/* offsets relative to CCSR offset 0x3000 */
> +#define R_I2CADR (0)
> +#define R_I2CFDR (4)
> +#define R_I2CCR  (8)
> +#define R_I2CSR  (0xc)
> +#define R_I2CDR  (0x10)
> +#define R_I2CDFSRR (0x14)
> +
> +FIELD(I2CCR, MEN, 7, 1)
> +FIELD(I2CCR, MIEN, 6, 1)
> +FIELD(I2CCR, MSTA, 5, 1)
> +FIELD(I2CCR, MTX, 4, 1)
> +FIELD(I2CCR, TXAK, 3, 1)
> +FIELD(I2CCR, RSTA, 2, 1)
> +FIELD(I2CCR, BCST, 0, 1)
> +
> +FIELD(I2CSR, MCF, 7, 1)
> +FIELD(I2CSR, MAAS, 6, 1)
> +FIELD(I2CSR, MBB, 5, 1)
> +FIELD(I2CSR, MAL, 4, 1)
> +FIELD(I2CSR, BCSTM, 3, 1)
> +FIELD(I2CSR, SRW, 2, 1)
> +FIELD(I2CSR, MIF, 1, 1)
> +FIELD(I2CSR, RXAK, 0, 1)
> +
> +typedef struct MPC8540I2CState {
> +SysBusDevice parent_obj;
> +
> +I2CBus *bus;
> +
> +uint8_t ctrl, sts;
> +uint8_t freq, filt;
> +/* Reads are pipelined, this is the next data value */
> +uint8_t dbuf, dbuf_valid;
> +
> +qemu_irq irq;
> +
> +MemoryRegion mmio;
> +} MPC8540I2CState;
> +
> +#define I2CCR(BIT) FIELD_EX32(i2c->ctrl, I2CCR, BIT)
> +#define I2CSR(BIT) FIELD_EX32(i2c->sts, I2CSR, BIT)
> +
> +#define I2CSR_SET(BIT, VAL) do {\
> +i2c->sts = FIELD_DP32(i2c->sts, I2CSR, BIT, VAL);\
> +} while (0)
> +
> +static
> +void mpc8540_update_irq(MPC8540I2CState *i2c)
> +{
> +int ena = i2c->ctrl & 0x40,
> +sts = i2c->sts & 0x02,
> +act = !!(ena && sts);
> +
> +DPRINTK(1, "IRQ %c ena %c sts %c",
> +act ? 'X' : '_',
> +ena ? 'X' : '_',
> +sts ? 'X' : '_');
> +
> +qemu_set_irq(i2c->irq, act);
> +}
> +
> +static
> +uint64_t mpc8540_i2c_read(void *opaque, hwaddr addr, unsigned size)
> +{
> +MPC8540I2CState *i2c = opaque;
> +uint32_t val;
> +
> +switch (addr) {
> +case R_I2CADR: /* ADDR */
> +val = 0;
> +break;
> +case R_I2CFDR: /* Freq Div. */
> +val = i2c->freq;
> +break;
> +case R_I2CCR: /* CONTROL */
> +val = i2c->ctrl & ~0x06;
> +break;
> +case R_I2CSR: /* STATUS */
> +val = i2c->sts;
> +break;
> +case R_I2CDR: /* DATA */
> +/* Reads are "pipelined" and so return the previous value of the
> + * register
> + */
> +val = i2c->dbuf;
> +if (I2CCR(MEN) && I2CSR(MBB)) { /* enabled and busy */
> +if (!i2c_bus_busy(i2c->bus) || I2CCR(MTX)) {
> +if (!i2c->dbuf_valid) {
> +LOG(LOG_GUEST_ERROR, "Read during addr or tx");
> +}
> +i2c->dbuf = 0xff;
> +i2c->dbuf_valid = false;
> +} else {
> +int ret = i2c_recv(i2c->bus);
> +i2c->dbuf = (uint8_t)ret;
> +i2c->dbuf_valid = true;
> +trace_mpc8540_i2

Re: [Qemu-devel] [PATCH v4 1/3] spapr/rtas: disable the decrementer interrupt when a CPU is unplugged

2017-11-26 Thread David Gibson
On Fri, Nov 24, 2017 at 08:05:48AM +0100, Cédric Le Goater wrote:
> When a CPU is stopped with the 'stop-self' RTAS call, its state
> 'halted' is switched to 1 and, in this case, the MSR is not taken into
> account anymore in the cpu_has_work() routine. Only the pending
> hardware interrupts are checked with their LPCR:PECE* enablement bit.
> 
> If the DECR timer fires after 'stop-self' is called and before the CPU
> 'stop' state is reached, the nearly-dead CPU will have some work to do
> and the guest will crash. This case happens very frequently with the
> not yet upstream P9 XIVE exploitation mode. In XICS mode, the DECR is
> occasionally fired but after 'stop' state, so no work is to be done
> and the guest survives.
> 
> I suspect there is a race between the QEMU mainloop triggering the
> timers and the TCG CPU thread but I could not quite identify the root
> cause. To be safe, let's disable in the LPCR all the exceptions which
> can cause an exit while the CPU is in power-saving mode and reenable
> them when the CPU is started.
> 
> Signed-off-by: Cédric Le Goater 

Applied to ppc-for-2.12.

> ---
> 
> Changes in v4:
> 
>  - used the 'lpcr_pm' field of PowerPCCPUClass
> 
> Changes in v3:
> 
>  - introduced a cpu_ppc_papr_pece_bits() helper to gather the PECE
>bits depending on the CPU family.   
>  - enabled Power-saving mode Exit Cause exceptions only on the boot CPU.
>  
> Changes in v2:
> 
>  - used a new routine ppc_cpu_pvr_match() to discriminate CPU versions
>  - removed the LPCR:PECE* enablement bit when the CPU is initialized
>if it is a secondary
> 
>  hw/ppc/spapr_rtas.c | 11 +++
>  target/ppc/translate_init.c |  9 ++---
>  2 files changed, 17 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
> index cdf0b607a0a0..858adb1bf3a9 100644
> --- a/hw/ppc/spapr_rtas.c
> +++ b/hw/ppc/spapr_rtas.c
> @@ -162,6 +162,7 @@ static void rtas_start_cpu(PowerPCCPU *cpu_, 
> sPAPRMachineState *spapr,
>  if (cpu != NULL) {
>  CPUState *cs = CPU(cpu);
>  CPUPPCState *env = &cpu->env;
> +PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
>  
>  if (!cs->halted) {
>  rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
> @@ -174,6 +175,10 @@ static void rtas_start_cpu(PowerPCCPU *cpu_, 
> sPAPRMachineState *spapr,
>  kvm_cpu_synchronize_state(cs);
>  
>  env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
> +
> +/* Enable Power-saving mode Exit Cause exceptions for the new CPU */
> +env->spr[SPR_LPCR] |= pcc->lpcr_pm;
> +
>  env->nip = start;
>  env->gpr[3] = r3;
>  cs->halted = 0;
> @@ -197,6 +202,7 @@ static void rtas_stop_self(PowerPCCPU *cpu, 
> sPAPRMachineState *spapr,
>  {
>  CPUState *cs = CPU(cpu);
>  CPUPPCState *env = &cpu->env;
> +PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
>  
>  cs->halted = 1;
>  qemu_cpu_kick(cs);
> @@ -210,6 +216,11 @@ static void rtas_stop_self(PowerPCCPU *cpu, 
> sPAPRMachineState *spapr,
>   * no need to bother with specific bits, we just clear it.
>   */
>  env->msr = 0;
> +
> +/* Disable Power-saving mode Exit Cause exceptions for the CPU.
> + * This could deliver an interrupt on a dying CPU and crash the
> + * guest */
> +env->spr[SPR_LPCR] &= ~pcc->lpcr_pm;
>  }
>  
>  static inline int sysparm_st(target_ulong addr, target_ulong len,
> diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c
> index 828d7e778c3b..78a4a581bab7 100644
> --- a/target/ppc/translate_init.c
> +++ b/target/ppc/translate_init.c
> @@ -8911,6 +8911,7 @@ void cpu_ppc_set_papr(PowerPCCPU *cpu, 
> PPCVirtualHypervisor *vhyp)
>  CPUPPCState *env = &cpu->env;
>  ppc_spr_t *lpcr = &env->spr_cb[SPR_LPCR];
>  ppc_spr_t *amor = &env->spr_cb[SPR_AMOR];
> +CPUState *cs = CPU(cpu);
>  
>  cpu->vhyp = vhyp;
>  
> @@ -8953,10 +8954,12 @@ void cpu_ppc_set_papr(PowerPCCPU *cpu, 
> PPCVirtualHypervisor *vhyp)
>  }
>  }
>  
> -/* Also set the power-saving mode bits which depend on the CPU
> - * family
> +/* Only enable Power-saving mode Exit Cause exceptions on the boot
> + * CPU. The RTAS command start-cpu will enable them on secondaries.
>   */
> -lpcr->default_value |= pcc->lpcr_pm;
> +if (cs == first_cpu) {
> +lpcr->default_value |= pcc->lpcr_pm;
> +}
>  
>  /* We should be followed by a CPU reset but update the active value
>   * just in case...

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [Qemu-devel] [qemu-s390x] [PATCH v3 1/7] s390x/pci: factor out endianess conversion

2017-11-26 Thread Thomas Huth
On 25.11.2017 14:49, Pierre Morel wrote:
> On 24/11/2017 07:19, Yi Min Zhao wrote:
>>
>>
>> 在 2017/11/23 下午8:18, Thomas Huth 写道:
>>> On 23.11.2017 13:07, Yi Min Zhao wrote:

 在 2017/11/23 下午6:33, Cornelia Huck 写道:
> On Thu, 23 Nov 2017 11:25:10 +0100
> Thomas Huth  wrote:
>
>> On 23.11.2017 11:08, Cornelia Huck wrote:
>>> On Thu, 23 Nov 2017 11:01:23 +0100
>>> Thomas Huth  wrote:
 On 23.11.2017 10:49, Cornelia Huck wrote:
> On Thu, 23 Nov 2017 09:48:41 +0100
> Thomas Huth  wrote:
>> On 22.11.2017 23:05, Pierre Morel wrote:
>> [...]
>>> +/**
>>> + * Swap data contained in s390x big endian registers to little
>>> endian
>>> + * PCI bars.
>>> + *
>>> + * @ptr: a pointer to a uint64_t data field
>>> + * @len: the length of the valid data, must be 1,2,4 or 8
>>> + */
>>> +static int zpci_endian_swap(uint64_t *ptr, uint8_t len)
>>> +{
>>> +    uint64_t data = *ptr;
>>> +
>>> +    switch (len) {
>>> +    case 1:
>>> +    break;
>>> +    case 2:
>>> +    data = bswap16(data);
>>> +    break;
>>> +    case 4:
>>> +    data = bswap32(data);
>>> +    break;
>>> +    case 8:
>>> +    data = bswap64(data);
>>> +    break;
>>> +    default:
>>> +    return -EINVAL;
>>> +    }
>>> +    *ptr = data;
>>> +    return 0;
>>> +}
>> While you're at it, I think that should rather be leXX_to_cpu()
>> instead
>> of bswapXX() here,
> I don't think that's correct, as this is supposed to swap BE
> registers
> to LE PCI bars.
 Yes, but for the CPU emulation, the registers are stored in the
 host's
 endianness in the CPUS390XState structure. Or why do we
 byte-swap them
 again with cpu_to_be64() during s390_store_status(), for example?
>>> Gah, endian conversion is eating my brain...
>>>
>>> So, is the content we get BE or not? I thought in our last
>>> discussion
>>> we came to the conclusion that it is.
>> data is read from / written to env->regs[r1], so this is host
>> endian, as
>> far as I know. PCI is little endian, so using le32_to_cpu() /
>> cpu_to_le32() should IMHO be the right way to go here.
>>
>> By the way, if we want to use both, cpu_to_le and le_to_cpu,
>> depending
>> on whether we read from or write to PCI, we should maybe *not* put
>> this
>> code into a separate function?
> Yes, if your assessment is correct, we need two functions (I think
> this
> conversion is used in other places in later patches as well). Or are
> there mechanisms for that already available?
 I have a question, is the data in cpu->regs the guest's endianess?
>>> As far as I know, it's host endianness, so on x86 with TCG emulation,
>>> it's little endian.
>>>
 In our case, the guest is S390. Although the arch is big-endian, the
 data in
 pcilg/stg instructions is little-endian.
>>> PCI memory is always little endian, right.
>>>
 Another question, does 'cpu' in cpu_to_le**() or le**_to_cpu() mean the
 host endianess?
>>> Yes, the "cpu" in cpu_to_le or le_to_cpu means the host, indeed. It's
>>> confusing :-/
>>>
 If the answers to upper two questions are yes, we actually need handle
 two cases.
 1) For pcilg, we need to translate the data to little-endian, thus
 cpu_to_le**().
 2) For pcistg, we need to translate the data to host endianess, thus
 le**_to_cpu().
>>> I think we've got to byte-swap if the host is big endian (s390x), but
>>> not if the host is little endian (x86 with TCG).
> 
> Here is my comprehension of this funny swapping:
> 
> - TCG for a BE guest and a le host swap bytes because if we do (register
> & 0x01) in the zPCI interception code it must work what ever the
> endianess is.

Uhhh, I might have missed that the value has already been byte-swapped
once by TCG for env->regs[r1] ...
Now I'm pretty much completely confused ... sorry for the noise if I was
wrong... I think it's best you ignore my comment for now (i.e. go with
bswapXX() instead of le_to_cpuXX()), and if we later wire up zPCI with
TCG, we still can fix this if necessary.

 Thomas



Re: [Qemu-devel] [PATCH v3 2/7] s390x/pci: rework PCI STORE

2017-11-26 Thread Thomas Huth
On 25.11.2017 11:39, Pierre Morel wrote:
> On 23/11/2017 10:01, Thomas Huth wrote:
>> On 22.11.2017 23:05, Pierre Morel wrote:
>>> Enhance the fault detection, correction of the fault reporting.
>>>
>>> Signed-off-by: Pierre Morel 
>>> Reviewed-by: Yi Min Zhao 
>>> ---
>>>   hw/s390x/s390-pci-inst.c | 39 ++-
>>>   1 file changed, 22 insertions(+), 17 deletions(-)
>>>
>>> diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
>>> index 3e1f1a0..930c197 100644
>>> --- a/hw/s390x/s390-pci-inst.c
>>> +++ b/hw/s390x/s390-pci-inst.c
>>> @@ -470,6 +470,12 @@ int pcistg_service_call(S390CPU *cpu, uint8_t
>>> r1, uint8_t r2)
>>>   pcias = (env->regs[r2] >> 16) & 0xf;
>>>   len = env->regs[r2] & 0xf;
>>>   offset = env->regs[r2 + 1];
>>> +    data = env->regs[r1];
>>> +
>>> +    if (!(fh & FH_MASK_ENABLE)) {
>>> +    setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
>>> +    return 0;
>>> +    }
>>>     pbdev = s390_pci_find_dev_by_fh(s390_get_phb(), fh);
>>>   if (!pbdev) {
>>> @@ -479,12 +485,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t
>>> r1, uint8_t r2)
>>>   }
>>>     switch (pbdev->state) {
>>> -    case ZPCI_FS_RESERVED:
>>> -    case ZPCI_FS_STANDBY:
>>> -    case ZPCI_FS_DISABLED:
>>>   case ZPCI_FS_PERMANENT_ERROR:
>>> -    setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
>>> -    return 0;
>>>   case ZPCI_FS_ERROR:
>>>   setcc(cpu, ZPCI_PCI_LS_ERR);
>>>   s390_set_status_code(env, r2, ZPCI_PCI_ST_BLOCKED);
>>
>> -EMISSINGPUBLICDOCUMENTATION
> 
> Hi Thomas,
> 
> I do not understand what you mean here

Not your fault, I just wanted to express that I can not really review
this part of the patch (and thus not provide a Reviewed-by) since there
is no public documentation available for zPCI :-(

 Thomas



Re: [Qemu-devel] [qemu-s390x] [PATCH v3 1/7] s390x/pci: factor out endianess conversion

2017-11-26 Thread Yi Min Zhao



在 2017/11/25 下午9:49, Pierre Morel 写道:

On 24/11/2017 07:19, Yi Min Zhao wrote:



在 2017/11/23 下午8:18, Thomas Huth 写道:

On 23.11.2017 13:07, Yi Min Zhao wrote:


在 2017/11/23 下午6:33, Cornelia Huck 写道:

On Thu, 23 Nov 2017 11:25:10 +0100
Thomas Huth  wrote:


On 23.11.2017 11:08, Cornelia Huck wrote:

On Thu, 23 Nov 2017 11:01:23 +0100
Thomas Huth  wrote:

On 23.11.2017 10:49, Cornelia Huck wrote:

On Thu, 23 Nov 2017 09:48:41 +0100
Thomas Huth  wrote:

On 22.11.2017 23:05, Pierre Morel wrote:

[...]

+/**
+ * Swap data contained in s390x big endian registers to little
endian
+ * PCI bars.
+ *
+ * @ptr: a pointer to a uint64_t data field
+ * @len: the length of the valid data, must be 1,2,4 or 8
+ */
+static int zpci_endian_swap(uint64_t *ptr, uint8_t len)
+{
+    uint64_t data = *ptr;
+
+    switch (len) {
+    case 1:
+    break;
+    case 2:
+    data = bswap16(data);
+    break;
+    case 4:
+    data = bswap32(data);
+    break;
+    case 8:
+    data = bswap64(data);
+    break;
+    default:
+    return -EINVAL;
+    }
+    *ptr = data;
+    return 0;
+}

While you're at it, I think that should rather be leXX_to_cpu()
instead
of bswapXX() here,

I don't think that's correct, as this is supposed to swap BE
registers
to LE PCI bars.
Yes, but for the CPU emulation, the registers are stored in the 
host's
endianness in the CPUS390XState structure. Or why do we 
byte-swap them

again with cpu_to_be64() during s390_store_status(), for example?

Gah, endian conversion is eating my brain...

So, is the content we get BE or not? I thought in our last 
discussion

we came to the conclusion that it is.
data is read from / written to env->regs[r1], so this is host 
endian, as

far as I know. PCI is little endian, so using le32_to_cpu() /
cpu_to_le32() should IMHO be the right way to go here.

By the way, if we want to use both, cpu_to_le and le_to_cpu, 
depending
on whether we read from or write to PCI, we should maybe *not* 
put this

code into a separate function?
Yes, if your assessment is correct, we need two functions (I think 
this

conversion is used in other places in later patches as well). Or are
there mechanisms for that already available?

I have a question, is the data in cpu->regs the guest's endianess?

As far as I know, it's host endianness, so on x86 with TCG emulation,
it's little endian.


In our case, the guest is S390. Although the arch is big-endian, the
data in
pcilg/stg instructions is little-endian.

PCI memory is always little endian, right.

Another question, does 'cpu' in cpu_to_le**() or le**_to_cpu() mean 
the

host endianess?

Yes, the "cpu" in cpu_to_le or le_to_cpu means the host, indeed. It's
confusing :-/


If the answers to upper two questions are yes, we actually need handle
two cases.
1) For pcilg, we need to translate the data to little-endian, thus
cpu_to_le**().
2) For pcistg, we need to translate the data to host endianess, thus
le**_to_cpu().

I think we've got to byte-swap if the host is big endian (s390x), but
not if the host is little endian (x86 with TCG).




Here is my comprehension of this funny swapping:

- TCG for a BE guest and a le host swap bytes because if we do 
(register & 0x01) in the zPCI interception code it must work what ever 
the endianess is.


- Guest always write data Little Endian because it think it writes to 
PCI.


- Kernel standard PCI code needs to swap endianness for a BE host but 
not for a le host.



So it follows:

Z Guest writes data BE in its register and swap its data to le before 
issuing zPCI

The data in register has been already le. For any zPCI instruction accessing
PCI data, the endianess is little-endian. Although s390 is be, its PCI 
instructions

follow PCI Spec (byte ordering is le).

In kernel, s390 pci code swaps the data to le before it really issues 
pcistg.


QEMU intercepts, receives the data from the register and store it
-> Native: it stores as is: -> le

I think you talked about PCI stg (storing data to PCI device).
The data from the register is le. But we swapped it back to be
because qemu in s390 is be. Then any pci_config write would
transfer data from be to le finally. The process is:
1) data from register : le (because the data in pcistg is in le)
2) pcistg intercept handler in qemu : le->be
3) pci->config_write : be->le

-> TCG: it stores swapping data -> BE

For this case, we only talk about the case that the host is le.
As my understanding, the data in the register should be in
the byte ordering which the guest is.

So, for s390 guest, the data in pcistg is le. Then pcistg intercept
handler swaps the data from le to be, thus the final callback
would write the data with the wrong byte ordering to PCI device
because the host is le and cpu_to_le32() would not swaps the data.


QEMU-PCI swaps the bytes always
-> Native : data is now BE
-> TCG: data is now le

Why is the data le under TCG? Isn't the data stored in register
the same as the guest's endianess?


Q

Re: [Qemu-devel] [RFC v4 21/27] qmp: let migrate-incoming allow out-of-band

2017-11-26 Thread Peter Xu
On Fri, Nov 24, 2017 at 01:14:53PM +, Dr. David Alan Gilbert wrote:
> * Peter Xu (pet...@redhat.com) wrote:
> > So it can get rid of being run on main thread.
> > 
> > Signed-off-by: Peter Xu 
> 
> Last time I asked if you were sure that we didn't do locking,
> and you explained that we end up just setting up a callback
> that happens in the mainloop, and this shouldn't take a lock.
> I confirmed this by:
> 
>   running with -incoming defer
>   breakpointing in hmp_migrate_incoming
>   doing   migrate_incoming tcp:0:
>   once I hit that breakpointing adding two more breakpoints:
>  a) qemu_mutex_lock_iothread
>  b) the end of hmp's handle_hmp_command
> 
>   and indeed it hit the end of handle_hmp_command without
> having hit the qemu_mutex_lock_iothread; so initially that
> looks ok.

I am not sure I fully understand the test above - I think it was
trying to verify the whole OOB thing running without BQL?  If so,
there are possibly two things missing:

Firstly, qemu_mutex_lock_iothread() is actually called before we call
hmp_migrate_incoming(). To verify it is simple: just break at entry of
hmp_migrate_incoming() and do "p iothread_locked", it'll be true (I
would always prefer printing that global variable to know whether
current thread is in a BQL section).

Secondly, HMP will still always take the BQL; this patch only enables
OOB for QMP command "migrate-incoming" rather than the HMP command. So
IMHO what we need to test is QMP command, rather than this HMP one.

To test that QMP command, it's still not that easy (actually awkward).
We need to first enable "OOB" when doing handshake for QMP:

  {"execute": "qmp_capabilities", "arguments": { "enable": [ "oob" ] } }

Then, we need to send the command with proper "id"/"control" field:

  { "execute": "migrate-incoming",
"arguments": { "uri": "tcp:localhost:1234" },
"control": { "run-oob": true },
"id": "test-command" }

Note that here "id" field will be a must now since OOB requires that,
meanwhile the "control" field is a must too to make sure that is run
in OOB format (otherwise this command will still take BQL and run as
usual).  So if you see we do have a lot of protection to make sure we
only run OOB only if we really wanted to... otherwise we'll always run
in compatible and old way.

This time if we break at qmp_migrate_incoming() and then do "p
iothread_locked", we should see a false here.

> 
> But then I added a break on pthread_mutex_lock, and I've got
> this set caused by qemu_start_incoming_migration sending a
> MIGRATION_STATUS_SETUP event:
> 
> #1  0x55ba6eba in qemu_mutex_lock (mutex=mutex@entry=0x563f9ba0 
> )
> at /home/dgilbert/git/qemu/util/qemu-thread-posix.c:65
> #2  0x557f01c1 in monitor_qapi_event_queue 
> (event=QAPI_EVENT_MIGRATION, qdict=0x57d93c00, errp=) at 
> /home/dgilbert/git/qemu/monitor.c:442
> 
> 440   trace_monitor_protocol_event_queue(event, qdict, evconf->rate);
> 441   
> 442   qemu_mutex_lock(&monitor_lock);
> 443   
> 
> #3  0x55b92722 in qapi_event_send_migration 
> (status=status@entry=MIGRATION_STATUS_SETUP, errp=0x56859320 
> ) at qapi-event.c:661
> #4  0x55a6159f in qemu_start_incoming_migration (uri=0x57693f30 
> "tcp:0:", errp=0x7fffc700)
> at /home/dgilbert/git/qemu/migration/migration.c:253
> #5  0x55a641c5 in qmp_migrate_incoming (uri=0x57693f30 
> "tcp:0:", errp=0x7fffc730)
> at /home/dgilbert/git/qemu/migration/migration.c:1321
> 
> is there anything which protects us there?

IIUC you mean what if we e.g. page fault during taking the
monitor_lock?  IMHO it just can't happen - monitor_lock is really used
in limited places and during those critical sections there is no guest
memory access at all (which only protects the monitor logic itself
AFAICT).

Thanks,

> 
> Dave
> 
> > ---
> >  qapi/migration.json | 3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> > 
> > diff --git a/qapi/migration.json b/qapi/migration.json
> > index bbc4671ded..95098072dd 100644
> > --- a/qapi/migration.json
> > +++ b/qapi/migration.json
> > @@ -1063,7 +1063,8 @@
> >  # <- { "return": {} }
> >  #
> >  ##
> > -{ 'command': 'migrate-incoming', 'data': {'uri': 'str' } }
> > +{ 'command': 'migrate-incoming', 'data': {'uri': 'str' },
> > +  'allow-oob': true }
> >  
> >  ##
> >  # @xen-save-devices-state:
> > -- 
> > 2.13.6
> > 
> --
> Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK

-- 
Peter Xu



[Qemu-devel] [PATCH v3 3/3] nvdimm: add 'unarmed' option

2017-11-26 Thread Haozhong Zhang
Currently the only vNVDIMM backend can guarantee the guest write
persistence is device DAX on Linux, because no host-side kernel cache
is involved in the guest access to it. The approach to detect whether
the backend is device DAX needs to access sysfs, which may not work
with SELinux.

Instead, we add the 'unarmed' option to device 'nvdimm', so that users
or management utils, which have enough knowledge about the backend,
can control the unarmed flag in guest ACPI NFIT via this option. The
guest Linux NVDIMM driver, for example, will mark the corresponding
vNVDIMM device read-only if the unarmed flag in guest NFIT is set.

The default value of 'unarmed' option is 'off' in order to keep the
backwards compatibility.

Signed-off-by: Haozhong Zhang 
---
 docs/nvdimm.txt | 15 +++
 hw/acpi/nvdimm.c|  7 +++
 hw/mem/nvdimm.c | 26 ++
 include/hw/mem/nvdimm.h |  9 +
 4 files changed, 57 insertions(+)

diff --git a/docs/nvdimm.txt b/docs/nvdimm.txt
index 21249dd062..e903d8bb09 100644
--- a/docs/nvdimm.txt
+++ b/docs/nvdimm.txt
@@ -138,3 +138,18 @@ backend of vNVDIMM:
 
  -object 
memory-backend-file,id=mem1,share=on,mem-path=/dev/dax0.0,size=4G,align=2M
  -device nvdimm,id=nvdimm1,memdev=mem1
+
+Guest Data Persistence
+--
+
+Though QEMU supports multiple types of vNVDIMM backends on Linux,
+currently the only one that can guarantee the guest write persistence
+is the device DAX on the real NVDIMM device (e.g., /dev/dax0.0), to
+which all guest access do not involve any host-side kernel cache.
+
+When using other types of backends, it's suggested to set 'unarmed'
+option of '-device nvdimm' to 'on', which sets the unarmed flag of the
+guest NVDIMM region mapping structure.  This unarmed flag indicates
+guest software that this vNVDIMM device contains a region that cannot
+accept persistent writes. In result, for example, the guest Linux
+NVDIMM driver, marks such vNVDIMM device as read-only.
diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 6ceea196e7..e55ff2cd12 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -138,6 +138,8 @@ struct NvdimmNfitMemDev {
 } QEMU_PACKED;
 typedef struct NvdimmNfitMemDev NvdimmNfitMemDev;
 
+#define ACPI_NFIT_MEM_NOT_ARMED (1 << 3)
+
 /*
  * NVDIMM Control Region Structure
  *
@@ -284,6 +286,7 @@ static void
 nvdimm_build_structure_memdev(GArray *structures, DeviceState *dev)
 {
 NvdimmNfitMemDev *nfit_memdev;
+NVDIMMDevice *nvdimm = NVDIMM(OBJECT(dev));
 uint64_t size = object_property_get_uint(OBJECT(dev), PC_DIMM_SIZE_PROP,
  NULL);
 int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
@@ -312,6 +315,10 @@ nvdimm_build_structure_memdev(GArray *structures, 
DeviceState *dev)
 
 /* Only one interleave for PMEM. */
 nfit_memdev->interleave_ways = cpu_to_le16(1);
+
+if (nvdimm->unarmed) {
+nfit_memdev->flags |= ACPI_NFIT_MEM_NOT_ARMED;
+}
 }
 
 /*
diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c
index 618c3d677b..61e677f92f 100644
--- a/hw/mem/nvdimm.c
+++ b/hw/mem/nvdimm.c
@@ -25,6 +25,7 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "qapi/visitor.h"
+#include "qapi-visit.h"
 #include "hw/mem/nvdimm.h"
 
 static void nvdimm_get_label_size(Object *obj, Visitor *v, const char *name,
@@ -64,11 +65,36 @@ out:
 error_propagate(errp, local_err);
 }
 
+static bool nvdimm_get_unarmed(Object *obj, Error **errp)
+{
+NVDIMMDevice *nvdimm = NVDIMM(obj);
+
+return nvdimm->unarmed;
+}
+
+static void nvdimm_set_unarmed(Object *obj, bool value, Error **errp)
+{
+NVDIMMDevice *nvdimm = NVDIMM(obj);
+Error *local_err = NULL;
+
+if (memory_region_size(&nvdimm->nvdimm_mr)) {
+error_setg(&local_err, "cannot change property value");
+goto out;
+}
+
+nvdimm->unarmed = value;
+
+ out:
+error_propagate(errp, local_err);
+}
+
 static void nvdimm_init(Object *obj)
 {
 object_property_add(obj, NVDIMM_LABLE_SIZE_PROP, "int",
 nvdimm_get_label_size, nvdimm_set_label_size, NULL,
 NULL, NULL);
+object_property_add_bool(obj, NVDIMM_UNARMED_PROP,
+ nvdimm_get_unarmed, nvdimm_set_unarmed, NULL);
 }
 
 static MemoryRegion *nvdimm_get_memory_region(PCDIMMDevice *dimm, Error **errp)
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
index 28e68ddf59..7fd87c4e1c 100644
--- a/include/hw/mem/nvdimm.h
+++ b/include/hw/mem/nvdimm.h
@@ -49,6 +49,7 @@
TYPE_NVDIMM)
 
 #define NVDIMM_LABLE_SIZE_PROP "label-size"
+#define NVDIMM_UNARMED_PROP"unarmed"
 
 struct NVDIMMDevice {
 /* private */
@@ -74,6 +75,14 @@ struct NVDIMMDevice {
  * guest via ACPI NFIT and _FIT method if NVDIMM hotplug is supported.
  */
 MemoryRegion nvdimm_mr;
+
+/*
+ * The 'on' value results in the unarmed flag set in ACPI NFIT

[Qemu-devel] [PATCH v3 1/3] hostmem-file: add "align" option

2017-11-26 Thread Haozhong Zhang
When mmap(2) the backend files, QEMU uses the host page size
(getpagesize(2)) by default as the alignment of mapping address.
However, some backends may require alignments different than the page
size. For example, mmap a device DAX (e.g., /dev/dax0.0) on Linux
kernel 4.13 to an address, which is 4K-aligned but not 2M-aligned,
fails with a kernel message like

[617494.969768] dax dax0.0: qemu-system-x86: dax_mmap: fail, unaligned vma 
(0x7fa37c579000 - 0x7fa43c579000, 0x1f)

Because there is no common approach to get such alignment requirement,
we add the 'align' option to 'memory-backend-file', so that users or
management utils, which have enough knowledge about the backend, can
specify a proper alignment via this option.

Signed-off-by: Haozhong Zhang 
---
 backends/hostmem-file.c | 41 -
 docs/nvdimm.txt | 16 
 exec.c  |  8 +++-
 include/exec/memory.h   |  3 +++
 memory.c|  2 ++
 numa.c  |  2 +-
 6 files changed, 69 insertions(+), 3 deletions(-)

diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
index e44c319915..e319ec1ad8 100644
--- a/backends/hostmem-file.c
+++ b/backends/hostmem-file.c
@@ -34,6 +34,7 @@ struct HostMemoryBackendFile {
 bool share;
 bool discard_data;
 char *mem_path;
+uint64_t align;
 };
 
 static void
@@ -58,7 +59,7 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error 
**errp)
 path = object_get_canonical_path(OBJECT(backend));
 memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
  path,
- backend->size, fb->share,
+ backend->size, fb->align, fb->share,
  fb->mem_path, errp);
 g_free(path);
 }
@@ -115,6 +116,40 @@ static void file_memory_backend_set_discard_data(Object 
*o, bool value,
 MEMORY_BACKEND_FILE(o)->discard_data = value;
 }
 
+static void file_memory_backend_get_align(Object *o, Visitor *v,
+  const char *name, void *opaque,
+  Error **errp)
+{
+HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
+uint64_t val = fb->align;
+
+visit_type_size(v, name, &val, errp);
+}
+
+static void file_memory_backend_set_align(Object *o, Visitor *v,
+  const char *name, void *opaque,
+  Error **errp)
+{
+HostMemoryBackend *backend = MEMORY_BACKEND(o);
+HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
+Error *local_err = NULL;
+uint64_t val;
+
+if (host_memory_backend_mr_inited(backend)) {
+error_setg(&local_err, "cannot change property value");
+goto out;
+}
+
+visit_type_size(v, name, &val, &local_err);
+if (local_err) {
+goto out;
+}
+fb->align = val;
+
+ out:
+error_propagate(errp, local_err);
+}
+
 static void file_backend_unparent(Object *obj)
 {
 HostMemoryBackend *backend = MEMORY_BACKEND(obj);
@@ -145,6 +180,10 @@ file_backend_class_init(ObjectClass *oc, void *data)
 object_class_property_add_str(oc, "mem-path",
 get_mem_path, set_mem_path,
 &error_abort);
+object_class_property_add(oc, "align", "int",
+file_memory_backend_get_align,
+file_memory_backend_set_align,
+NULL, NULL, &error_abort);
 }
 
 static void file_backend_instance_finalize(Object *o)
diff --git a/docs/nvdimm.txt b/docs/nvdimm.txt
index 2d9f8c0e8c..21249dd062 100644
--- a/docs/nvdimm.txt
+++ b/docs/nvdimm.txt
@@ -122,3 +122,19 @@ Note:
  M >= size of RAM devices +
   size of statically plugged vNVDIMM devices +
   size of hotplugged vNVDIMM devices
+
+Alignment
+-
+
+QEMU uses mmap(2) to maps vNVDIMM backends and aligns the mapping
+address to the page size (getpagesize(2)) by default. However, some
+types of backends may require an alignment different than the page
+size. In that case, QEMU v2.12.0 and later provide 'align' option to
+memory-backend-file to allow users to specify the proper alignment.
+
+For example, device dax require the 2 MB alignment, so we can use
+following QEMU command line options to use it (/dev/dax0.0) as the
+backend of vNVDIMM:
+
+ -object 
memory-backend-file,id=mem1,share=on,mem-path=/dev/dax0.0,size=4G,align=2M
+ -device nvdimm,id=nvdimm1,memdev=mem1
diff --git a/exec.c b/exec.c
index 03238a3449..90440efecd 100644
--- a/exec.c
+++ b/exec.c
@@ -1600,7 +1600,13 @@ static void *file_ram_alloc(RAMBlock *block,
 void *area;
 
 block->page_size = qemu_fd_getpagesize(fd);
-block->mr->align = block->page_size;
+if (block->mr->align % block->page_size) {
+error_setg(errp, "aligment 0x%" PRIx64
+   " must be multiples of page size 0x%" PRIx64,
+   block->mr->align, block->page_size);
+ret

[Qemu-devel] [PATCH v3 2/3] nvdimm: add a macro for property "label-size"

2017-11-26 Thread Haozhong Zhang
Signed-off-by: Haozhong Zhang 
Reviewed-by: Stefan Hajnoczi 
---
 hw/mem/nvdimm.c | 2 +-
 include/hw/mem/nvdimm.h | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c
index 952fce5ec8..618c3d677b 100644
--- a/hw/mem/nvdimm.c
+++ b/hw/mem/nvdimm.c
@@ -66,7 +66,7 @@ out:
 
 static void nvdimm_init(Object *obj)
 {
-object_property_add(obj, "label-size", "int",
+object_property_add(obj, NVDIMM_LABLE_SIZE_PROP, "int",
 nvdimm_get_label_size, nvdimm_set_label_size, NULL,
 NULL, NULL);
 }
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
index 03e1ff9558..28e68ddf59 100644
--- a/include/hw/mem/nvdimm.h
+++ b/include/hw/mem/nvdimm.h
@@ -47,6 +47,9 @@
 #define NVDIMM_CLASS(oc) OBJECT_CLASS_CHECK(NVDIMMClass, (oc), TYPE_NVDIMM)
 #define NVDIMM_GET_CLASS(obj) OBJECT_GET_CLASS(NVDIMMClass, (obj), \
TYPE_NVDIMM)
+
+#define NVDIMM_LABLE_SIZE_PROP "label-size"
+
 struct NVDIMMDevice {
 /* private */
 PCDIMMDevice parent_obj;
-- 
2.14.1




[Qemu-devel] [PATCH-for-2.12 v3 0/3] nvdimm: fixes for (non-)dax backends

2017-11-26 Thread Haozhong Zhang
Previous versions can be found at
  v2: https://lists.gnu.org/archive/html/qemu-devel/2017-06/msg01203.html
  v1: https://lists.gnu.org/archive/html/qemu-devel/2017-05/msg05919.html

Changes in v3:
 * Add an option 'align' to 'memory-backend-file' to address the
   failure when mmap device dax (patch 1).
 * Remove device dax check, which needs to access sysfs and may not
   work with SELinux.
 * Add a boolean option 'unarmed' to '-device nvdimm', which allows
   users to control the unarmed flag in guest ACPI NFIT. I don't make
   it as OnOffAuto, because of the remove of device dax check.
 * Document new options added by this patch series.

Haozhong Zhang (3):
  hostmem-file: add "align" option
  nvdimm: add a macro for property "label-size"
  nvdimm: add 'unarmed' option

 backends/hostmem-file.c | 41 -
 docs/nvdimm.txt | 31 +++
 exec.c  |  8 +++-
 hw/acpi/nvdimm.c|  7 +++
 hw/mem/nvdimm.c | 28 +++-
 include/exec/memory.h   |  3 +++
 include/hw/mem/nvdimm.h | 12 
 memory.c|  2 ++
 numa.c  |  2 +-
 9 files changed, 130 insertions(+), 4 deletions(-)

-- 
2.14.1




[Qemu-devel] [PULL 1/2] target/ppc: Move setting of patb_entry on hash table init

2017-11-26 Thread David Gibson
From: Suraj Jitindar Singh 

The patb_entry is used to store the location of the process table in
guest memory. The msb is also used to indicate the mmu mode of the
guest, that is patb_entry & 1 << 63 ? radix_mode : hash_mode.

Currently we set this to zero in spapr_setup_hpt_and_vrma() since if
this function gets called then we know we're hash. However some code
paths, such as setting up the hpt on incoming migration of a hash guest,
call spapr_reallocate_hpt() directly bypassing this higher level
function. Since we assume radix if the host is capable this results in
the msb in patb_entry being left set so in spapr_post_load() we call
kvmppc_configure_v3_mmu() and tell the host we're radix which as
expected means addresses cannot be translated once we actually run the cpu.

To fix this move the zeroing of patb_entry into spapr_reallocate_hpt().

Signed-off-by: Suraj Jitindar Singh 
Signed-off-by: David Gibson 
---
 hw/ppc/spapr.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 4d0a84f3ec..9efddeaee5 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1373,6 +1373,8 @@ void spapr_reallocate_hpt(sPAPRMachineState *spapr, int 
shift,
 DIRTY_HPTE(HPTE(spapr->htab, i));
 }
 }
+/* We're setting up a hash table, so that means we're not radix */
+spapr->patb_entry = 0;
 }
 
 void spapr_setup_hpt_and_vrma(sPAPRMachineState *spapr)
@@ -1392,8 +1394,6 @@ void spapr_setup_hpt_and_vrma(sPAPRMachineState *spapr)
 spapr->rma_size = kvmppc_rma_size(spapr_node0_size(MACHINE(spapr)),
   spapr->htab_shift);
 }
-/* We're setting up a hash table, so that means we're not radix */
-spapr->patb_entry = 0;
 }
 
 static void find_unknown_sysbus_device(SysBusDevice *sbdev, void *opaque)
-- 
2.14.3




[Qemu-devel] [PULL 0/2] ppc-for-2.11 queue 20171127

2017-11-26 Thread David Gibson
The following changes since commit e7b47c22e2df14d55e3e4426688c929bf8e3f7fb:

  osdep.h: Make TIME_MAX handle different time_t types (2017-11-24 13:23:36 
+)

are available in the Git repository at:

  git://github.com/dgibson/qemu.git tags/ppc-for-2.11-20171127

for you to fetch changes up to e07cc1929515cfb808b5c2fcc60c079e6be110cf:

  target/ppc: Fix setting of cpu->compat_pvr on incoming migration (2017-11-27 
12:20:11 +1100)


ppc patch queue 2017-11-27

This series contains a couple of migration fixes for hash guests on
POWER9 radix MMU hosts.


Suraj Jitindar Singh (2):
  target/ppc: Move setting of patb_entry on hash table init
  target/ppc: Fix setting of cpu->compat_pvr on incoming migration

 hw/ppc/spapr.c   | 4 ++--
 target/ppc/machine.c | 4 +++-
 2 files changed, 5 insertions(+), 3 deletions(-)



[Qemu-devel] [PULL 2/2] target/ppc: Fix setting of cpu->compat_pvr on incoming migration

2017-11-26 Thread David Gibson
From: Suraj Jitindar Singh 

cpu->compat_pvr is used to store the current compat mode of the cpu.

On the receiving side during incoming migration we check compatibility
with the compat mode by calling ppc_set_compat(). However we fail to set
the compat mode with the hypervisor since the "new" compat mode doesn't
differ from the current (due to a "cpu->compat_pvr != compat_pvr" check).
This means that kvm runs the vcpus without a compat mode, which is the
incorrect behaviour. The implication being that a compatibility mode
will never be in effect after migration.

To fix this so that the compat mode is correctly set with the
hypervisor, store the desired compat mode and reset cpu->compat_pvr to
zero before calling ppc_set_compat().

Fixes: 5dfaa532 ("ppc: fix ppc_set_compat() with KVM PR")

Signed-off-by: Suraj Jitindar Singh 
Signed-off-by: David Gibson 
---
 target/ppc/machine.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/target/ppc/machine.c b/target/ppc/machine.c
index 384caee800..24117e8f31 100644
--- a/target/ppc/machine.c
+++ b/target/ppc/machine.c
@@ -237,9 +237,11 @@ static int cpu_post_load(void *opaque, int version_id)
 
 #if defined(TARGET_PPC64)
 if (cpu->compat_pvr) {
+uint32_t compat_pvr = cpu->compat_pvr;
 Error *local_err = NULL;
 
-ppc_set_compat(cpu, cpu->compat_pvr, &local_err);
+cpu->compat_pvr = 0;
+ppc_set_compat(cpu, compat_pvr, &local_err);
 if (local_err) {
 error_report_err(local_err);
 return -1;
-- 
2.14.3




[Qemu-devel] [PATCH v3] gdbstub: add tracing

2017-11-26 Thread Doug Gale
Signed-off-by: Doug Gale 
---
 gdbstub.c| 101 ++-
 trace-events |  21 +
 2 files changed, 87 insertions(+), 35 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 2a94030d3b..86482fa009 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -21,6 +21,7 @@
 #include "qemu/error-report.h"
 #include "qemu/cutils.h"
 #include "cpu.h"
+#include "trace-root.h"
 #ifdef CONFIG_USER_ONLY
 #include "qemu.h"
 #else
@@ -287,21 +288,6 @@ static int gdb_signal_to_target (int sig)
 return -1;
 }
 
-/* #define DEBUG_GDB */
-
-#ifdef DEBUG_GDB
-# define DEBUG_GDB_GATE 1
-#else
-# define DEBUG_GDB_GATE 0
-#endif
-
-#define gdb_debug(fmt, ...) do { \
-if (DEBUG_GDB_GATE) { \
-fprintf(stderr, "%s: " fmt, __func__, ## __VA_ARGS__); \
-} \
-} while (0)
-
-
 typedef struct GDBRegisterState {
 int base_reg;
 int num_regs;
@@ -538,12 +524,48 @@ static void hextomem(uint8_t *mem, const char *buf, int 
len)
 }
 }
 
+static void hexdump(const char *buf, int len,
+void (*trace_fn)(size_t ofs, char const *text))
+{
+char line_buffer[3 * 16 + 4 + 16 + 1];
+
+size_t i;
+for (i = 0; i < len || (i & 0xF); ++i) {
+size_t byte_ofs = i & 15;
+
+if (byte_ofs == 0) {
+memset(line_buffer, ' ', 3 * 16 + 4 + 16);
+line_buffer[3 * 16 + 4 + 16] = 0;
+}
+
+size_t col_group = (i >> 2) & 3;
+size_t hex_col = byte_ofs * 3 + col_group;
+size_t txt_col = 3 * 16 + 4 + byte_ofs;
+
+if (i < len) {
+char value = buf[i];
+
+line_buffer[hex_col + 0] = tohex((value >> 4) & 0xF);
+line_buffer[hex_col + 1] = tohex((value >> 0) & 0xF);
+line_buffer[txt_col + 0] = (value >= ' ' && value < 127)
+? value
+: '.';
+}
+
+if (byte_ofs == 0xF)
+trace_fn(i & -16, line_buffer);
+}
+}
+
 /* return -1 if error, 0 if OK */
-static int put_packet_binary(GDBState *s, const char *buf, int len)
+static int put_packet_binary(GDBState *s, const char *buf, int len, bool dump)
 {
 int csum, i;
 uint8_t *p;
 
+if (TRACE_GDBSTUB_IO_BINARYREPLY_ENABLED && dump)
+hexdump(buf, len, trace_gdbstub_io_binaryreply);
+
 for(;;) {
 p = s->last_packet;
 *(p++) = '$';
@@ -576,9 +598,9 @@ static int put_packet_binary(GDBState *s, const char *buf, 
int len)
 /* return -1 if error, 0 if OK */
 static int put_packet(GDBState *s, const char *buf)
 {
-gdb_debug("reply='%s'\n", buf);
+trace_gdbstub_io_reply(buf);
 
-return put_packet_binary(s, buf, strlen(buf));
+return put_packet_binary(s, buf, strlen(buf), false);
 }
 
 /* Encode data using the encoding for 'x' packets.  */
@@ -975,8 +997,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 uint8_t *registers;
 target_ulong addr, len;
 
-
-gdb_debug("command='%s'\n", line_buf);
+trace_gdbstub_io_command(line_buf);
 
 p = line_buf;
 ch = *p++;
@@ -999,7 +1020,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 s->signal = 0;
 gdb_continue(s);
-   return RS_IDLE;
+return RS_IDLE;
 case 'C':
 s->signal = gdb_signal_to_target (strtoul(p, (char **)&p, 16));
 if (s->signal == -1)
@@ -1045,7 +1066,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 cpu_single_step(s->c_cpu, sstep_flags);
 gdb_continue(s);
-   return RS_IDLE;
+return RS_IDLE;
 case 'F':
 {
 target_ulong ret;
@@ -1267,6 +1288,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 len = snprintf((char *)mem_buf, sizeof(buf) / 2,
"CPU#%d [%s]", cpu->cpu_index,
cpu->halted ? "halted " : "running");
+trace_gdbstub_op_extra_info((char *)mem_buf);
 memtohex(buf, mem_buf, len);
 put_packet(s, buf);
 }
@@ -1350,7 +1372,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 buf[0] = 'l';
 len = memtox(buf + 1, xml + addr, total_len - addr);
 }
-put_packet_binary(s, buf, len + 1);
+put_packet_binary(s, buf, len + 1, true);
 break;
 }
 if (is_query_packet(p, "Attached", ':')) {
@@ -1407,6 +1429,8 @@ static void gdb_vm_state_change(void *opaque, int 
running, RunState state)
 type = "";
 break;
 }
+trace_gdbstub_op_hit_watchpoint(type, cpu_gdb_index(cpu),
+(target_ulong)cpu->watchpoint_hit->vaddr);
 snprintf(buf, sizeof(buf),
  "T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";",
  GDB_SIGNAL_TRAP, cpu_gdb_index(cpu), type,
@@ -1421,6 +1445,7 @@ static voi

[Qemu-devel] [PATCH v2] gdbstub: add tracing

2017-11-26 Thread Doug Gale
Signed-off-by: Doug Gale 
---
 gdbstub.c| 101 ++-
 trace-events |  21 +
 2 files changed, 87 insertions(+), 35 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 2a94030d3b..86482fa009 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -21,6 +21,7 @@
 #include "qemu/error-report.h"
 #include "qemu/cutils.h"
 #include "cpu.h"
+#include "trace-root.h"
 #ifdef CONFIG_USER_ONLY
 #include "qemu.h"
 #else
@@ -287,21 +288,6 @@ static int gdb_signal_to_target (int sig)
 return -1;
 }
 
-/* #define DEBUG_GDB */
-
-#ifdef DEBUG_GDB
-# define DEBUG_GDB_GATE 1
-#else
-# define DEBUG_GDB_GATE 0
-#endif
-
-#define gdb_debug(fmt, ...) do { \
-if (DEBUG_GDB_GATE) { \
-fprintf(stderr, "%s: " fmt, __func__, ## __VA_ARGS__); \
-} \
-} while (0)
-
-
 typedef struct GDBRegisterState {
 int base_reg;
 int num_regs;
@@ -538,12 +524,48 @@ static void hextomem(uint8_t *mem, const char *buf, int 
len)
 }
 }
 
+static void hexdump(const char *buf, int len,
+void (*trace_fn)(size_t ofs, char const *text))
+{
+char line_buffer[3 * 16 + 4 + 16 + 1];
+
+size_t i;
+for (i = 0; i < len || (i & 0xF); ++i) {
+size_t byte_ofs = i & 15;
+
+if (byte_ofs == 0) {
+memset(line_buffer, ' ', 3 * 16 + 4 + 16);
+line_buffer[3 * 16 + 4 + 16] = 0;
+}
+
+size_t col_group = (i >> 2) & 3;
+size_t hex_col = byte_ofs * 3 + col_group;
+size_t txt_col = 3 * 16 + 4 + byte_ofs;
+
+if (i < len) {
+char value = buf[i];
+
+line_buffer[hex_col + 0] = tohex((value >> 4) & 0xF);
+line_buffer[hex_col + 1] = tohex((value >> 0) & 0xF);
+line_buffer[txt_col + 0] = (value >= ' ' && value < 127)
+? value
+: '.';
+}
+
+if (byte_ofs == 0xF)
+trace_fn(i & -16, line_buffer);
+}
+}
+
 /* return -1 if error, 0 if OK */
-static int put_packet_binary(GDBState *s, const char *buf, int len)
+static int put_packet_binary(GDBState *s, const char *buf, int len, bool dump)
 {
 int csum, i;
 uint8_t *p;
 
+if (TRACE_GDBSTUB_IO_BINARYREPLY_ENABLED && dump)
+hexdump(buf, len, trace_gdbstub_io_binaryreply);
+
 for(;;) {
 p = s->last_packet;
 *(p++) = '$';
@@ -576,9 +598,9 @@ static int put_packet_binary(GDBState *s, const char *buf, 
int len)
 /* return -1 if error, 0 if OK */
 static int put_packet(GDBState *s, const char *buf)
 {
-gdb_debug("reply='%s'\n", buf);
+trace_gdbstub_io_reply(buf);
 
-return put_packet_binary(s, buf, strlen(buf));
+return put_packet_binary(s, buf, strlen(buf), false);
 }
 
 /* Encode data using the encoding for 'x' packets.  */
@@ -975,8 +997,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 uint8_t *registers;
 target_ulong addr, len;
 
-
-gdb_debug("command='%s'\n", line_buf);
+trace_gdbstub_io_command(line_buf);
 
 p = line_buf;
 ch = *p++;
@@ -999,7 +1020,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 s->signal = 0;
 gdb_continue(s);
-   return RS_IDLE;
+return RS_IDLE;
 case 'C':
 s->signal = gdb_signal_to_target (strtoul(p, (char **)&p, 16));
 if (s->signal == -1)
@@ -1045,7 +1066,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 cpu_single_step(s->c_cpu, sstep_flags);
 gdb_continue(s);
-   return RS_IDLE;
+return RS_IDLE;
 case 'F':
 {
 target_ulong ret;
@@ -1267,6 +1288,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 len = snprintf((char *)mem_buf, sizeof(buf) / 2,
"CPU#%d [%s]", cpu->cpu_index,
cpu->halted ? "halted " : "running");
+trace_gdbstub_op_extra_info((char *)mem_buf);
 memtohex(buf, mem_buf, len);
 put_packet(s, buf);
 }
@@ -1350,7 +1372,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 buf[0] = 'l';
 len = memtox(buf + 1, xml + addr, total_len - addr);
 }
-put_packet_binary(s, buf, len + 1);
+put_packet_binary(s, buf, len + 1, true);
 break;
 }
 if (is_query_packet(p, "Attached", ':')) {
@@ -1407,6 +1429,8 @@ static void gdb_vm_state_change(void *opaque, int 
running, RunState state)
 type = "";
 break;
 }
+trace_gdbstub_op_hit_watchpoint(type, cpu_gdb_index(cpu),
+(target_ulong)cpu->watchpoint_hit->vaddr);
 snprintf(buf, sizeof(buf),
  "T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";",
  GDB_SIGNAL_TRAP, cpu_gdb_index(cpu), type,
@@ -1421,6 +1445,7 @@ static voi

Re: [Qemu-devel] [PATCH] gdbstub: add tracing

2017-11-26 Thread no-reply
Hi,

This series failed automatic build test. Please find the testing commands and
their output below. If you have docker installed, you can probably reproduce it
locally.

Subject: [Qemu-devel] [PATCH] gdbstub: add tracing
Type: series
Message-id: 20171127041038.22819-1-doug...@gmail.com

=== TEST SCRIPT BEGIN ===
#!/bin/bash
set -e
git submodule update --init dtc
# Let docker tests dump environment info
export SHOW_ENV=1
export J=8
time make docker-test-quick@centos6
time make docker-test-build@min-glib
time make docker-test-mingw@fedora
# iotests is broken now, skip
# time make docker-test-block@fedora
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
5a76dfd86b gdbstub: add tracing

=== OUTPUT BEGIN ===
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into '/var/tmp/patchew-tester-tmp-nmy74n7l/src/dtc'...
Submodule path 'dtc': checked out '558cd81bdd432769b59bff01240c44f82cfb1a9d'
  BUILD   centos6
make[1]: Entering directory '/var/tmp/patchew-tester-tmp-nmy74n7l/src'
  GEN 
/var/tmp/patchew-tester-tmp-nmy74n7l/src/docker-src.2017-11-26-23.14.08.28919/qemu.tar
Cloning into 
'/var/tmp/patchew-tester-tmp-nmy74n7l/src/docker-src.2017-11-26-23.14.08.28919/qemu.tar.vroot'...
done.
Checking out files:  44% (2514/5661)   
Checking out files:  45% (2548/5661)   
Checking out files:  46% (2605/5661)   
Checking out files:  47% (2661/5661)   
Checking out files:  48% (2718/5661)   
Checking out files:  49% (2774/5661)   
Checking out files:  50% (2831/5661)   
Checking out files:  51% (2888/5661)   
Checking out files:  52% (2944/5661)   
Checking out files:  53% (3001/5661)   
Checking out files:  54% (3057/5661)   
Checking out files:  55% (3114/5661)   
Checking out files:  56% (3171/5661)   
Checking out files:  57% (3227/5661)   
Checking out files:  58% (3284/5661)   
Checking out files:  59% (3340/5661)   
Checking out files:  60% (3397/5661)   
Checking out files:  61% (3454/5661)   
Checking out files:  62% (3510/5661)   
Checking out files:  63% (3567/5661)   
Checking out files:  64% (3624/5661)   
Checking out files:  65% (3680/5661)   
Checking out files:  66% (3737/5661)   
Checking out files:  67% (3793/5661)   
Checking out files:  68% (3850/5661)   
Checking out files:  69% (3907/5661)   
Checking out files:  70% (3963/5661)   
Checking out files:  71% (4020/5661)   
Checking out files:  72% (4076/5661)   
Checking out files:  73% (4133/5661)   
Checking out files:  74% (4190/5661)   
Checking out files:  75% (4246/5661)   
Checking out files:  76% (4303/5661)   
Checking out files:  77% (4359/5661)   
Checking out files:  78% (4416/5661)   
Checking out files:  79% (4473/5661)   
Checking out files:  80% (4529/5661)   
Checking out files:  81% (4586/5661)   
Checking out files:  82% (4643/5661)   
Checking out files:  83% (4699/5661)   
Checking out files:  84% (4756/5661)   
Checking out files:  85% (4812/5661)   
Checking out files:  86% (4869/5661)   
Checking out files:  87% (4926/5661)   
Checking out files:  88% (4982/5661)   
Checking out files:  89% (5039/5661)   
Checking out files:  90% (5095/5661)   
Checking out files:  91% (5152/5661)   
Checking out files:  92% (5209/5661)   
Checking out files:  93% (5265/5661)   
Checking out files:  94% (5322/5661)   
Checking out files:  95% (5378/5661)   
Checking out files:  96% (5435/5661)   
Checking out files:  97% (5492/5661)   
Checking out files:  98% (5548/5661)   
Checking out files:  99% (5605/5661)   
Checking out files:  99% (5637/5661)   
Checking out files: 100% (5661/5661)   
Checking out files: 100% (5661/5661), done.
Your branch is up-to-date with 'origin/test'.
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into 
'/var/tmp/patchew-tester-tmp-nmy74n7l/src/docker-src.2017-11-26-23.14.08.28919/qemu.tar.vroot/dtc'...
Submodule path 'dtc': checked out '558cd81bdd432769b59bff01240c44f82cfb1a9d'
Submodule 'ui/keycodemapdb' (git://git.qemu.org/keycodemapdb.git) registered 
for path 'ui/keycodemapdb'
Cloning into 
'/var/tmp/patchew-tester-tmp-nmy74n7l/src/docker-src.2017-11-26-23.14.08.28919/qemu.tar.vroot/ui/keycodemapdb'...
Submodule path 'ui/keycodemapdb': checked out 
'10739aa26051a5d49d88132604539d3ed085e72e'
  COPYRUNNER
RUN test-quick in qemu:centos6 
Packages installed:
SDL-devel-1.2.14-7.el6_7.1.x86_64
bison-2.4.1-5.el6.x86_64
bzip2-devel-1.0.5-7.el6_0.x86_64
ccache-3.1.6-2.el6.x86_64
csnappy-devel-0-6.20150729gitd7bc683.el6.x86_64
flex-2.5.35-9.el6.x86_64
gcc-4.4.7-18.el6.x86_64
gettext-0.17-18.el6.x86_64
git-1.7.1-9.el6_9.x86_64
glib2-devel-2.28.8-9.el6.x86_64
libepoxy-devel-1.2-3.el6.x86_64
libfdt-devel-1.4.0-1.el6.x86_64
librdmacm-devel-1.0.21-0.el6.x86_64
lzo-devel-2.03-3.1.el6_5.1.x86_64
make-3.81-23.el6.x86_64
mesa-libEGL-devel-11.0.7-4.el6.x86_64
mesa-libgbm-devel-11.0.7-4.el6.x86_64
package g++ is not installed
pixman-devel-0.32.8-1.el6.x86_64
spice-glib-devel-0.26-8.el6.

[Qemu-devel] [PATCH] gdbstub: add tracing

2017-11-26 Thread Doug Gale
Signed-off-by: Doug Gale 
---
 gdbstub.c| 100 ++-
 trace-events |  21 +
 2 files changed, 86 insertions(+), 35 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 2a94030d3b..a75f319bd0 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -21,6 +21,7 @@
 #include "qemu/error-report.h"
 #include "qemu/cutils.h"
 #include "cpu.h"
+#include "trace-root.h"
 #ifdef CONFIG_USER_ONLY
 #include "qemu.h"
 #else
@@ -287,21 +288,6 @@ static int gdb_signal_to_target (int sig)
 return -1;
 }
 
-/* #define DEBUG_GDB */
-
-#ifdef DEBUG_GDB
-# define DEBUG_GDB_GATE 1
-#else
-# define DEBUG_GDB_GATE 0
-#endif
-
-#define gdb_debug(fmt, ...) do { \
-if (DEBUG_GDB_GATE) { \
-fprintf(stderr, "%s: " fmt, __func__, ## __VA_ARGS__); \
-} \
-} while (0)
-
-
 typedef struct GDBRegisterState {
 int base_reg;
 int num_regs;
@@ -538,12 +524,47 @@ static void hextomem(uint8_t *mem, const char *buf, int 
len)
 }
 }
 
+static void hexdump(const char *buf, int len,
+void (*trace_fn)(size_t ofs, char const *text))
+{
+char line_buffer[3 * 16 + 4 + 16 + 1];
+
+for (size_t i = 0; i < len || (i & 0xF); ++i) {
+size_t byte_ofs = i & 15;
+
+if (byte_ofs == 0) {
+memset(line_buffer, ' ', 3 * 16 + 4 + 16);
+line_buffer[3 * 16 + 4 + 16] = 0;
+}
+
+size_t col_group = (i >> 2) & 3;
+size_t hex_col = byte_ofs * 3 + col_group;
+size_t txt_col = 3 * 16 + 4 + byte_ofs;
+
+if (i < len) {
+char value = buf[i];
+
+line_buffer[hex_col + 0] = tohex((value >> 4) & 0xF);
+line_buffer[hex_col + 1] = tohex((value >> 0) & 0xF);
+line_buffer[txt_col + 0] = (value >= ' ' && value < 127)
+? value
+: '.';
+}
+
+if (byte_ofs == 0xF)
+trace_fn(i & -16, line_buffer);
+}
+}
+
 /* return -1 if error, 0 if OK */
-static int put_packet_binary(GDBState *s, const char *buf, int len)
+static int put_packet_binary(GDBState *s, const char *buf, int len, bool dump)
 {
 int csum, i;
 uint8_t *p;
 
+if (TRACE_GDBSTUB_IO_BINARYREPLY_ENABLED && dump)
+hexdump(buf, len, trace_gdbstub_io_binaryreply);
+
 for(;;) {
 p = s->last_packet;
 *(p++) = '$';
@@ -576,9 +597,9 @@ static int put_packet_binary(GDBState *s, const char *buf, 
int len)
 /* return -1 if error, 0 if OK */
 static int put_packet(GDBState *s, const char *buf)
 {
-gdb_debug("reply='%s'\n", buf);
+trace_gdbstub_io_reply(buf);
 
-return put_packet_binary(s, buf, strlen(buf));
+return put_packet_binary(s, buf, strlen(buf), false);
 }
 
 /* Encode data using the encoding for 'x' packets.  */
@@ -975,8 +996,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 uint8_t *registers;
 target_ulong addr, len;
 
-
-gdb_debug("command='%s'\n", line_buf);
+trace_gdbstub_io_command(line_buf);
 
 p = line_buf;
 ch = *p++;
@@ -999,7 +1019,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 s->signal = 0;
 gdb_continue(s);
-   return RS_IDLE;
+return RS_IDLE;
 case 'C':
 s->signal = gdb_signal_to_target (strtoul(p, (char **)&p, 16));
 if (s->signal == -1)
@@ -1045,7 +1065,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 cpu_single_step(s->c_cpu, sstep_flags);
 gdb_continue(s);
-   return RS_IDLE;
+return RS_IDLE;
 case 'F':
 {
 target_ulong ret;
@@ -1267,6 +1287,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 len = snprintf((char *)mem_buf, sizeof(buf) / 2,
"CPU#%d [%s]", cpu->cpu_index,
cpu->halted ? "halted " : "running");
+trace_gdbstub_op_extra_info((char *)mem_buf);
 memtohex(buf, mem_buf, len);
 put_packet(s, buf);
 }
@@ -1350,7 +1371,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 buf[0] = 'l';
 len = memtox(buf + 1, xml + addr, total_len - addr);
 }
-put_packet_binary(s, buf, len + 1);
+put_packet_binary(s, buf, len + 1, true);
 break;
 }
 if (is_query_packet(p, "Attached", ':')) {
@@ -1407,6 +1428,8 @@ static void gdb_vm_state_change(void *opaque, int 
running, RunState state)
 type = "";
 break;
 }
+trace_gdbstub_op_hit_watchpoint(type, cpu_gdb_index(cpu),
+(target_ulong)cpu->watchpoint_hit->vaddr);
 snprintf(buf, sizeof(buf),
  "T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";",
  GDB_SIGNAL_TRAP, cpu_gdb_index(cpu), type,
@@ -1421,6 +1444,7 @@ static void gdb_vm

Re: [Qemu-devel] ui: Support non-zero minimum values for absolute input axes

2017-11-26 Thread Simon Gaiser
Philippe Voinov:
> This patch refactors ui/input.c to support absolute axis
> minimum values other than 0. All dependent calls to qemu_input_queue_abs
> have been updated to explicitly supply 0 as the axis minimum value.

Shouldn't the patch also also pass old_value - 1 as the second argument?
Before qemu_input_queue_abs() expected the size and now the maximal
value.



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-devel] [PATCH v9 13/13] xlnx-zcu102: Add support for the ZynqMP QSPI

2017-11-26 Thread Philippe Mathieu-Daudé
On 11/26/2017 08:16 PM, Francisco Iglesias wrote:
> Add support for the ZynqMP QSPI (consisting of the Generic QSPI and Legacy
> QSPI) and connect Numonyx n25q512a11 flashes to it.
> 
> Signed-off-by: Francisco Iglesias 
> Reviewed-by: Alistair Francis 
> Reviewed-by: Edgar E. Iglesias 

Reviewed-by: Philippe Mathieu-Daudé 

> Tested-by: Edgar E. Iglesias 
> ---
>  hw/arm/xlnx-zcu102.c | 23 +++
>  hw/arm/xlnx-zynqmp.c | 26 ++
>  include/hw/arm/xlnx-zynqmp.h |  5 +
>  3 files changed, 54 insertions(+)
> 
> diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
> index bbe7d04..b126cf1 100644
> --- a/hw/arm/xlnx-zcu102.c
> +++ b/hw/arm/xlnx-zcu102.c
> @@ -151,6 +151,29 @@ static void xlnx_zynqmp_init(XlnxZCU102 *s, MachineState 
> *machine)
>  sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.spi[i]), 1, cs_line);
>  }
>  
> +for (i = 0; i < XLNX_ZYNQMP_NUM_QSPI_FLASH; i++) {
> +SSIBus *spi_bus;
> +DeviceState *flash_dev;
> +qemu_irq cs_line;
> +DriveInfo *dinfo = drive_get_next(IF_MTD);
> +int bus = i / XLNX_ZYNQMP_NUM_QSPI_BUS_CS;
> +gchar *bus_name = g_strdup_printf("qspi%d", bus);
> +
> +spi_bus = (SSIBus *)qdev_get_child_bus(DEVICE(&s->soc), bus_name);
> +g_free(bus_name);
> +
> +flash_dev = ssi_create_slave_no_init(spi_bus, "n25q512a11");
> +if (dinfo) {
> +qdev_prop_set_drive(flash_dev, "drive", 
> blk_by_legacy_dinfo(dinfo),
> +&error_fatal);
> +}
> +qdev_init_nofail(flash_dev);
> +
> +cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
> +
> +sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.qspi), i + 1, cs_line);
> +}
> +
>  /* TODO create and connect IDE devices for ide_drive_get() */
>  
>  xlnx_zcu102_binfo.ram_size = ram_size;
> diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
> index c707c66..3256420 100644
> --- a/hw/arm/xlnx-zynqmp.c
> +++ b/hw/arm/xlnx-zynqmp.c
> @@ -40,6 +40,10 @@
>  #define SATA_ADDR   0xFD0C
>  #define SATA_NUM_PORTS  2
>  
> +#define QSPI_ADDR   0xff0f
> +#define LQSPI_ADDR  0xc000
> +#define QSPI_IRQ15
> +
>  #define DP_ADDR 0xfd4a
>  #define DP_IRQ  113
>  
> @@ -171,6 +175,9 @@ static void xlnx_zynqmp_init(Object *obj)
>  qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default());
>  }
>  
> +object_initialize(&s->qspi, sizeof(s->qspi), TYPE_XLNX_ZYNQMP_QSPIPS);
> +qdev_set_parent_bus(DEVICE(&s->qspi), sysbus_get_default());
> +
>  object_initialize(&s->dp, sizeof(s->dp), TYPE_XLNX_DP);
>  qdev_set_parent_bus(DEVICE(&s->dp), sysbus_get_default());
>  
> @@ -411,6 +418,25 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error 
> **errp)
>  g_free(bus_name);
>  }
>  
> +object_property_set_bool(OBJECT(&s->qspi), true, "realized", &err);
> +sysbus_mmio_map(SYS_BUS_DEVICE(&s->qspi), 0, QSPI_ADDR);
> +sysbus_mmio_map(SYS_BUS_DEVICE(&s->qspi), 1, LQSPI_ADDR);
> +sysbus_connect_irq(SYS_BUS_DEVICE(&s->qspi), 0, gic_spi[QSPI_IRQ]);
> +
> +for (i = 0; i < XLNX_ZYNQMP_NUM_QSPI_BUS; i++) {
> +gchar *bus_name;
> +gchar *target_bus;
> +
> +/* Alias controller SPI bus to the SoC itself */
> +bus_name = g_strdup_printf("qspi%d", i);
> +target_bus = g_strdup_printf("spi%d", i);
> +object_property_add_alias(OBJECT(s), bus_name,
> +  OBJECT(&s->qspi), target_bus,
> +  &error_abort);
> +g_free(bus_name);
> +g_free(target_bus);
> +}
> +
>  object_property_set_bool(OBJECT(&s->dp), true, "realized", &err);
>  if (err) {
>  error_propagate(errp, err);
> diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
> index 6eff81a..3e6fb9b 100644
> --- a/include/hw/arm/xlnx-zynqmp.h
> +++ b/include/hw/arm/xlnx-zynqmp.h
> @@ -40,6 +40,10 @@
>  #define XLNX_ZYNQMP_NUM_SDHCI 2
>  #define XLNX_ZYNQMP_NUM_SPIS 2
>  
> +#define XLNX_ZYNQMP_NUM_QSPI_BUS 2
> +#define XLNX_ZYNQMP_NUM_QSPI_BUS_CS 2
> +#define XLNX_ZYNQMP_NUM_QSPI_FLASH 4
> +
>  #define XLNX_ZYNQMP_NUM_OCM_BANKS 4
>  #define XLNX_ZYNQMP_OCM_RAM_0_ADDRESS 0xFFFC
>  #define XLNX_ZYNQMP_OCM_RAM_SIZE 0x1
> @@ -83,6 +87,7 @@ typedef struct XlnxZynqMPState {
>  SysbusAHCIState sata;
>  SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI];
>  XilinxSPIPS spi[XLNX_ZYNQMP_NUM_SPIS];
> +XlnxZynqMPQSPIPS qspi;
>  XlnxDPState dp;
>  XlnxDPDMAState dpdma;
>  
> 



Re: [Qemu-devel] [PATCH v9 08/13] xilinx_spips: Make tx/rx_data_bytes more generic and reusable

2017-11-26 Thread Philippe Mathieu-Daudé
Hi Francisco,

On 11/26/2017 08:16 PM, Francisco Iglesias wrote:
> Make tx/rx_data_bytes more generic so they can be reused (when adding
> support for the Zynqmp Generic QSPI).
> 
> Signed-off-by: Francisco Iglesias 
> Reviewed-by: Edgar E. Iglesias 
> Tested-by: Edgar E. Iglesias 
> ---
>  hw/ssi/xilinx_spips.c | 64 
> +--
>  1 file changed, 37 insertions(+), 27 deletions(-)
> 
> diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
> index 691d48d..4621dbb 100644
> --- a/hw/ssi/xilinx_spips.c
> +++ b/hw/ssi/xilinx_spips.c
> @@ -47,7 +47,7 @@
>  /* config register */
>  #define R_CONFIG(0x00 / 4)
>  #define IFMODE  (1U << 31)
> -#define ENDIAN  (1 << 26)
> +#define R_CONFIG_ENDIAN (1 << 26)
>  #define MODEFAIL_GEN_EN (1 << 17)
>  #define MAN_START_COM   (1 << 16)
>  #define MAN_START_EN(1 << 15)
> @@ -450,13 +450,28 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
>  }
>  }
>  
> -static inline void rx_data_bytes(XilinxSPIPS *s, uint8_t *value, int max)
> +static inline void tx_data_bytes(Fifo8 *fifo, uint32_t value, int num, bool 
> be)
>  {
>  int i;
> +for (i = 0; i < num && !fifo8_is_full(fifo); ++i) {
> +if (be) {
> +fifo8_push(fifo, (uint8_t)(value >> 24));
> +value <<= 8;
> +} else {
> +fifo8_push(fifo, (uint8_t)value);
> +value >>= 8;
> +}
> +}
> +}
>  
> -for (i = 0; i < max && !fifo8_is_empty(&s->rx_fifo); ++i) {
> -value[i] = fifo8_pop(&s->rx_fifo);
> +static inline int rx_data_bytes(Fifo8 *fifo, uint8_t *value, int max)
> +{
> +int i;
> +
> +for (i = 0; i < max && !fifo8_is_empty(fifo); ++i) {
> +value[i] = fifo8_pop(fifo);
>  }
> +return max - i;
>  }
>  
>  static uint64_t xilinx_spips_read(void *opaque, hwaddr addr,
> @@ -466,6 +481,7 @@ static uint64_t xilinx_spips_read(void *opaque, hwaddr 
> addr,
>  uint32_t mask = ~0;
>  uint32_t ret;
>  uint8_t rx_buf[4];
> +int shortfall;
>  
>  addr >>= 2;
>  switch (addr) {
> @@ -496,9 +512,13 @@ static uint64_t xilinx_spips_read(void *opaque, hwaddr 
> addr,
>  break;
>  case R_RX_DATA:
>  memset(rx_buf, 0, sizeof(rx_buf));
> -rx_data_bytes(s, rx_buf, s->num_txrx_bytes);
> -ret = s->regs[R_CONFIG] & ENDIAN ? cpu_to_be32(*(uint32_t *)rx_buf)
> -: cpu_to_le32(*(uint32_t *)rx_buf);
> +shortfall = rx_data_bytes(&s->rx_fifo, rx_buf, s->num_txrx_bytes);

About this part,

> +ret = s->regs[R_CONFIG] & R_CONFIG_ENDIAN ?
> +cpu_to_be32(*(uint32_t *)rx_buf) :
> +cpu_to_le32(*(uint32_t *)rx_buf);
> +if (!(s->regs[R_CONFIG] & R_CONFIG_ENDIAN)) {
> +ret <<= 8 * shortfall;
> +}

The following looks easier to read to me, probably matter of taste, but
you don't have to wonder the cpu <-> device direction and it remove the
casts:

   if (s->regs[R_CONFIG] & R_CONFIG_ENDIAN) {
   ret = ldl_be_p(rx_buf);
   } else {
   ret = ldl_le_p(rx_buf) << (8 * shortfall);
   }

What do you think? (before respining)

>  DB_PRINT_L(0, "addr=" TARGET_FMT_plx " = %x\n", addr * 4, ret);
>  xilinx_spips_update_ixr(s);
>  return ret;
> @@ -509,20 +529,6 @@ static uint64_t xilinx_spips_read(void *opaque, hwaddr 
> addr,
>  
>  }
>  
> -static inline void tx_data_bytes(XilinxSPIPS *s, uint32_t value, int num)
> -{
> -int i;
> -for (i = 0; i < num && !fifo8_is_full(&s->tx_fifo); ++i) {
> -if (s->regs[R_CONFIG] & ENDIAN) {
> -fifo8_push(&s->tx_fifo, (uint8_t)(value >> 24));
> -value <<= 8;
> -} else {
> -fifo8_push(&s->tx_fifo, (uint8_t)value);
> -value >>= 8;
> -}
> -}
> -}
> -
>  static void xilinx_spips_write(void *opaque, hwaddr addr,
>  uint64_t value, unsigned size)
>  {
> @@ -563,16 +569,20 @@ static void xilinx_spips_write(void *opaque, hwaddr 
> addr,
>  mask = 0;
>  break;
>  case R_TX_DATA:
> -tx_data_bytes(s, (uint32_t)value, s->num_txrx_bytes);
> +tx_data_bytes(&s->tx_fifo, (uint32_t)value, s->num_txrx_bytes,
> +  s->regs[R_CONFIG] & R_CONFIG_ENDIAN);
>  goto no_reg_update;
>  case R_TXD1:
> -tx_data_bytes(s, (uint32_t)value, 1);
> +tx_data_bytes(&s->tx_fifo, (uint32_t)value, 1,
> +  s->regs[R_CONFIG] & R_CONFIG_ENDIAN);
>  goto no_reg_update;
>  case R_TXD2:
> -tx_data_bytes(s, (uint32_t)value, 2);
> +tx_data_bytes(&s->tx_fifo, (uint32_t)value, 2,
> +  s->regs[R_CONFIG] & R_CONFIG_ENDIAN);
>  goto no_reg_update;
>  case R_TXD3:
> -tx_data_bytes(s, (uint32_t)value, 3);
> +tx_data_bytes(&s->tx_fifo

Re: [Qemu-devel] [PATCH v9 02/13] m25p80: Add support for SST READ ID 0x90/0xAB commands

2017-11-26 Thread Philippe Mathieu-Daudé
On 11/26/2017 08:16 PM, Francisco Iglesias wrote:
> Add support for SST READ ID 0x90/0xAB commands for reading out the flash
> manufacturer ID and device ID.
> 
> Signed-off-by: Francisco Iglesias 

Reviewed-by: Philippe Mathieu-Daudé 

> ---
>  hw/block/m25p80.c | 32 
>  1 file changed, 32 insertions(+)
> 
> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
> index d50acc1..092c0c6 100644
> --- a/hw/block/m25p80.c
> +++ b/hw/block/m25p80.c
> @@ -355,6 +355,8 @@ typedef enum {
>  DPP = 0xa2,
>  QPP = 0x32,
>  QPP_4 = 0x34,
> +RDID_90 = 0x90,
> +RDID_AB = 0xab,
>  
>  ERASE_4K = 0x20,
>  ERASE4_4K = 0x21,
> @@ -405,6 +407,7 @@ typedef enum {
>  MAN_MACRONIX,
>  MAN_NUMONYX,
>  MAN_WINBOND,
> +MAN_SST,
>  MAN_GENERIC,
>  } Manufacturer;
>  
> @@ -476,6 +479,8 @@ static inline Manufacturer get_man(Flash *s)
>  return MAN_SPANSION;
>  case 0xC2:
>  return MAN_MACRONIX;
> +case 0xBF:
> +return MAN_SST;
>  default:
>  return MAN_GENERIC;
>  }
> @@ -711,6 +716,31 @@ static void complete_collecting_data(Flash *s)
>  case WEVCR:
>  s->enh_volatile_cfg = s->data[0];
>  break;
> +case RDID_90:
> +case RDID_AB:
> +if (get_man(s) == MAN_SST) {
> +if (s->cur_addr <= 1) {
> +if (s->cur_addr) {
> +s->data[0] = s->pi->id[2];
> +s->data[1] = s->pi->id[0];
> +} else {
> +s->data[0] = s->pi->id[0];
> +s->data[1] = s->pi->id[2];
> +}
> +s->pos = 0;
> +s->len = 2;
> +s->data_read_loop = true;
> +s->state = STATE_READING_DATA;
> +} else {
> +qemu_log_mask(LOG_GUEST_ERROR,
> +  "M25P80: Invalid read id address\n");
> +}
> +} else {
> +qemu_log_mask(LOG_GUEST_ERROR,
> +  "M25P80: Read id (command 0x90/0xAB) is not 
> supported"
> +  " by device\n");
> +}
> +break;
>  default:
>  break;
>  }
> @@ -926,6 +956,8 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>  case PP4:
>  case PP4_4:
>  case DIE_ERASE:
> +case RDID_90:
> +case RDID_AB:
>  s->needed_bytes = get_addr_length(s);
>  s->pos = 0;
>  s->len = 0;
> 



Re: [Qemu-devel] [PATCH for 2.11] virtio-net: don't touch virtqueue if vm is stopped

2017-11-26 Thread Jason Wang



On 2017年11月24日 18:44, Stefan Hajnoczi wrote:

On Fri, Nov 24, 2017 at 10:57:11AM +0800, Jason Wang wrote:

On 2017年11月23日 18:59, Stefan Hajnoczi wrote:

On Thu, Nov 23, 2017 at 11:37:46AM +0800, Jason Wang wrote:

Guest state should not be touched if VM is stopped, unfortunately we
didn't check running state and tried to drain tx queue unconditionally
in virtio_net_set_status(). A crash was then noticed as a migration
destination when user type quit after virtqueue state is loaded but
before region cache is initialized. In this case,
virtio_net_drop_tx_queue_data() tries to access the uninitialized
region cache.

Fix this by only dropping tx queue data when vm is running.

hw/virtio/virtio.c:virtio_load() does the following:

for (i = 0; i < num; i++) {
if (vdev->vq[i].vring.desc) {
uint16_t nheads;

/*
 * VIRTIO-1 devices migrate desc, used, and avail ring addresses so
 * only the region cache needs to be set up.  Legacy devices need
 * to calculate used and avail ring addresses based on the desc
 * address.
 */
if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
virtio_init_region_cache(vdev, i);
} else {
virtio_queue_update_rings(vdev, i);
}

So the region caches should be initialized after virtqueue state is
loaded.

It's unclear to me which code path triggers this issue.  Can you add a
backtrace or an explanation?

Thanks,
Stefan

Migration coroutine was yield before region cache was initialized. The
backtrace looks like:

[...]

#16 0x55b1c199 in vmstate_load_state (f=0x56f7c010,
vmsd=0x562b8160 , opaque=0x57d68610, version_id=1)
     at migration/vmstate.c:160
#17 0x55865cc3 in virtio_load (vdev=0x57d68610,
f=0x56f7c010, version_id=11) at
/home/devel/git/qemu/hw/virtio/virtio.c:2110

Reviewed-by: Stefan Hajnoczi 

Thanks for the backtrace!  Your patch is fine but I have a larger
concern:

The backtrace shows that the virtio code is re-entrant during savevm
load.  That's probably a bad thing because set_status() and other APIs
are probably not intended to run while we are half-way through savevm
load.  The virtqueue is only partially set up at this point :(.  I
wonder if a more general cleanup is necessary to avoid problems like
this in the future...

Stefan


Yes, this needs some thought. An idea is to guarantee the atomicity of 
the virtio state and don't expose partial state. But looks like this 
needs lots of changes.


Anyway, I will apply this patch first.

Thanks




Re: [Qemu-devel] [PATCH v3] rcu: reduce more than 7MB heap memory by malloc_trim()

2017-11-26 Thread Zhong Yang
On Sun, Nov 26, 2017 at 02:17:18PM +0800, Shannon Zhao wrote:
> Hi,
> 
> On 2017/11/24 14:30, Yang Zhong wrote:
> > Since there are some issues in memory alloc/free machenism
> > in glibc for little chunk memory, if Qemu frequently
> > alloc/free little chunk memory, the glibc doesn't alloc
> > little chunk memory from free list of glibc and still
> > allocate from OS, which make the heap size bigger and bigger.
> > 
> > This patch introduce malloc_trim(), which will free heap memory.
> > 
> > Below are test results from smaps file.
> > (1)without patch
> > 55f0783e1000-55f07992a000 rw-p  00:00 0  [heap]
> > Size:  21796 kB
> > Rss:   14260 kB
> > Pss:   14260 kB
> > 
> > (2)with patch
> > 55cc5fadf000-55cc61008000 rw-p  00:00 0  [heap]
> > Size:  21668 kB
> > Rss:6940 kB
> > Pss:6940 kB
> > 
> > Signed-off-by: Yang Zhong 
> > ---
> >  configure  | 29 +
> >  util/rcu.c |  6 ++
> >  2 files changed, 35 insertions(+)
> > 
> > diff --git a/configure b/configure
> > index 0c6e757..6292ab0 100755
> > --- a/configure
> > +++ b/configure
> > @@ -426,6 +426,7 @@ vxhs=""
> >  supported_cpu="no"
> >  supported_os="no"
> >  bogus_os="no"
> > +malloc_trim="yes"
> >  
> >  # parse CC options first
> >  for opt do
> > @@ -3857,6 +3858,30 @@ if test "$tcmalloc" = "yes" && test "$jemalloc" = 
> > "yes" ; then
> >  exit 1
> >  fi
> >  
> > +# Even if malloc_trim() is available, these non-libc memory allocators
> > +# do not support it.
> > +if test "$tcmalloc" = "yes" || test "$jemalloc" = "yes" ; then
> > +if test "$malloc_trim" = "yes" ; then
> > +echo "Disabling malloc_trim with non-libc memory allocator"
> > +fi
> > +malloc_trim="no"
> > +fi
> > +
> > +###
> > +# malloc_trim
> > +
> > +if test "$malloc_trim" != "no" ; then
> > +cat > $TMPC << EOF
> > +#include 
> > +int main(void) { malloc_trim(0); return 0; }
> > +EOF
> > +if compile_prog "" "" ; then
> > +malloc_trim="yes"
> > +else
> > +malloc_trim="no"
> > +fi
> > +fi
> > +
> >  ##
> >  # tcmalloc probe
> >  
> > @@ -6012,6 +6037,10 @@ if test "$opengl" = "yes" ; then
> >fi
> >  fi
> >  
> > +if test "$malloc_trim" = "yes" ; then
> > +  echo "CONFIG_MALLOC_TRIM=y" >> $config_host_mak
> > +fi
> > +
> >  if test "$avx2_opt" = "yes" ; then
> >echo "CONFIG_AVX2_OPT=y" >> $config_host_mak
> >  fi
> > diff --git a/util/rcu.c b/util/rcu.c
> > index ca5a63e..f403b77 100644
> > --- a/util/rcu.c
> > +++ b/util/rcu.c
> > @@ -32,6 +32,9 @@
> >  #include "qemu/atomic.h"
> >  #include "qemu/thread.h"
> >  #include "qemu/main-loop.h"
> > +#if defined(CONFIG_MALLOC_TRIM)
> > +#include 
> > +#endif
> >  
> >  /*
> >   * Global grace period counter.  Bit 0 is always one in rcu_gp_ctr.
> > @@ -272,6 +275,9 @@ static void *call_rcu_thread(void *opaque)
> >  node->func(node);
> >  }
> >  qemu_mutex_unlock_iothread();
> > +#if defined(CONFIG_MALLOC_TRIM)
> > +malloc_trim(4 * 1024 * 1024);
> > +#endif
> >  }
> >  abort();
> >  }
> > 
> 
> Looks like this patch introduces a performance regression. With this
> patch the time of booting a VM with 60 scsi disks on ARM64 is increased
> by 200+ seconds.
> 
  Hello Shannon,

  Thanks for your reply!
  As for your concerns, i did VM bootup compared tests, and results as below:

  #test command
  ./qemu-system-x86_64 -enable-kvm -cpu host -m 2G -smp cpus=4,cores=4,\
   threads=1,sockets=1 -drive format=raw,\
   file=test.img,index=0,media=disk -nographic

  #without patch
  root@intel-internal-corei7-64:~# systemd-analyze
  Startup finished in 4.979s (kernel) + 1.214s (userspace) = 6.193s

  root@intel-internal-corei7-64:~# systemd-analyze
  Startup finished in 4.922s (kernel) + 1.175s (userspace) = 6.097s

  root@intel-internal-corei7-64:~# systemd-analyze
  Startup finished in 4.990s (kernel) + 1.301s (userspace) = 6.291s

  root@intel-internal-corei7-64:~# systemd-analyze
  Startup finished in 5.063s (kernel) + 1.336s (userspace) = 6.400s

  root@intel-internal-corei7-64:~# systemd-analyze
  Startup finished in 4.820s (kernel) + 1.237s (userspace) = 6.057s

  avg: kernel 4.9548, userspace 1.2526


  #with this patch
  root@intel-internal-corei7-64:~# systemd-analyze
  Startup finished in 5.099s (kernel) + 1.579s (userspace) = 6.679s

  root@intel-internal-corei7-64:~# systemd-analyze
  Startup finished in 5.003s (kernel) + 1.343s (userspace) = 6.347s

  root@intel-internal-corei7-64:~# systemd-analyze
  Startup finished in 4.853s (kernel) + 1.220s (userspace) = 6.074s

  root@intel-internal-corei7-64:~# systemd-analyze
  Startup finished in 4.836s (kernel) + 1.111s (userspace) = 5.948s

  root@intel-internal-corei7-64:~# systemd-analyze
  Startup finished in 4.917s (kernel) + 1.166s (userspace) = 6

Re: [Qemu-devel] [RFC v4 23/27] monitor: enable IO thread for (qmp & !mux) typed

2017-11-26 Thread Peter Xu
On Fri, Nov 24, 2017 at 11:01:49AM +, Dr. David Alan Gilbert wrote:
> * Peter Xu (pet...@redhat.com) wrote:
> > Start to use dedicate IO thread for QMP monitors that are not using
> > MUXed chardev.
> > 
> > Signed-off-by: Peter Xu 
> 
> Reviewed-by: Dr. David Alan Gilbert 

Thanks!

> 
> I guess another way to do this would be to have a property on the
> Chardev something like 'can use iothread' and clear that for Mux.

Yeh we can.  Though I would still prefer to put that in Monitor struct
since current IOThread is really tailored only for monitors.  IOW not
all Chardevs can be run in the IOThread (or say, the thread currently
named as "mon_iothread") safely.  Thanks,

-- 
Peter Xu



Re: [Qemu-devel] [PATCH v2 3/6] ppc: e500: Allow only supported dynamic sysbus devices

2017-11-26 Thread David Gibson
On Sat, Nov 25, 2017 at 01:16:07PM -0200, Eduardo Habkost wrote:
> platform_bus_create_devtree() already rejects all dynamic sysbus
> devices except TYPE_ETSEC_COMMON, so register it as the only
> allowed dynamic sysbus device for the ppce500 machine-type.
> 
> Cc: Alexander Graf 
> Cc: David Gibson 
> Cc: qemu-...@nongnu.org
> Signed-off-by: Eduardo Habkost 

Acked-by: David Gibson 

Do you need me to take this through my tree (for 2.12), or do you have
another merge patch in mind?

> ---
> Changes series v1 -> v2:
> * New patch added to series
> ---
>  hw/ppc/e500plat.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c
> index 438118c29b..81d03e1038 100644
> --- a/hw/ppc/e500plat.c
> +++ b/hw/ppc/e500plat.c
> @@ -12,6 +12,7 @@
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
>  #include "e500.h"
> +#include "hw/net/fsl_etsec/etsec.h"
>  #include "hw/boards.h"
>  #include "sysemu/device_tree.h"
>  #include "sysemu/kvm.h"
> @@ -64,8 +65,7 @@ static void e500plat_machine_init(MachineClass *mc)
>  mc->desc = "generic paravirt e500 platform";
>  mc->init = e500plat_init;
>  mc->max_cpus = 32;
> -/*TODO: allow only sysbus devices that really work with this machine */
> -machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SYS_BUS_DEVICE);
> +machine_class_allow_dynamic_sysbus_dev(mc, TYPE_ETSEC_COMMON);
>  mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("e500v2_v30");
>  }
>  

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [Qemu-devel] [RFC PATCH 1/1] s390x/css: unresrict cssids

2017-11-26 Thread Dong Jia Shi
* Halil Pasic  [2017-11-24 17:39:04 +0100]:

> 
> 
> On 11/24/2017 05:15 PM, Cornelia Huck wrote:
> >>> In theory this should work. 
> >>>
> >>> In reality it seems more complicated. A per-device property is easy and 
> >>> can be
> >>> inspected on the command line (e.g. -device virtio-blk-ccw,help), while a 
> >>> new 
> >>> machine property would require to change the qemu help output and 
> >>> qemu-options 
> >>> file (which makes it visible for all architectures).  
> >> And then we have the fun of describing, that this property is weird, and 
> >> can
> >> not be set, and it's value does not matter.
> > Well, that's the case for both, no?
> 
> 
> I don't think we have to document _device_ properites in qemu-options.hx
> I don't see any documented neither for virtio-ccw nor for vfio-ccw. The
> machine properties, on the contrary, are documented in this file.
Is it sane and possible to reuse the existing s390-squash-mcss property
to achieve the goal?  I mean, when it is false (which is the default
value), can we treat it as "we are allowed to put devices everywhere"?
Then we'd have the way to use a property of the -M to tell libvirt that
devices can be everywhere?

However then we can not drop it completely I guess, since Libvirt will
depends on it. But we can ignore the operation of setting it's value to
true.

> > 
> > (Unless we simply make this a "default cssid" prop after all - then it
> > would be more than just a simple indication for libvirt...)
> > 
> 
> We are now talking about the "cssid-unrestricted" property. The default
> cssid is not something I would like to do any time soon.

-- 
Dong Jia Shi




Re: [Qemu-devel] [PATCH v2 1/6] machine: Replace has_dynamic_sysbus with list of allowed devices

2017-11-26 Thread David Gibson
On Sat, Nov 25, 2017 at 01:16:05PM -0200, Eduardo Habkost wrote:
> The existing has_dynamic_sysbus flag makes the machine accept
> every user-creatable sysbus device type on the command-line.
> Replace it with a list of allowed device types, so machines can
> easily accept some sysbus devices while rejecting others.
> 
> To keep exactly the same behavior as before, the existing
> has_dynamic_sysbus=true assignments are replaced with a
> TYPE_SYS_BUS_DEVICE entry on the allowed list.  Other patches
> will replace the TYPE_SYS_BUS_DEVICE entries with more specific
> lists of devices.
> 
> Cc: Peter Maydell 
> Cc: Marcel Apfelbaum 
> Cc: "Michael S. Tsirkin" 
> Cc: Alexander Graf 
> Cc: David Gibson 
> Cc: Stefano Stabellini 
> Cc: Anthony Perard 
> Cc: qemu-...@nongnu.org
> Cc: qemu-...@nongnu.org
> Cc: xen-de...@lists.xenproject.org
> Signed-off-by: Eduardo Habkost 

Reviewed-by: David Gibson 

> ---
> Changes v1 -> v2:
> * Replace "dynamic sysbus whitelist" with "allowed sysbus devices"
> * Simply add TYPE_SYS_BUS_DEVICE to the list on existing
>   has_dynamic_sysbus=true machines, and make machine-types more
>   strict in separate patches
> ---
>  include/hw/boards.h  |  5 -
>  hw/arm/virt.c|  3 ++-
>  hw/core/machine.c| 43 +--
>  hw/i386/pc_q35.c |  3 ++-
>  hw/ppc/e500plat.c|  4 +++-
>  hw/ppc/spapr.c   |  3 ++-
>  hw/xen/xen_backend.c |  7 ++-
>  7 files changed, 48 insertions(+), 20 deletions(-)
> 
> diff --git a/include/hw/boards.h b/include/hw/boards.h
> index 156b16f7a6..041bc08971 100644
> --- a/include/hw/boards.h
> +++ b/include/hw/boards.h
> @@ -76,6 +76,9 @@ void machine_set_cpu_numa_node(MachineState *machine,
> const CpuInstanceProperties *props,
> Error **errp);
>  
> +void machine_class_allow_dynamic_sysbus_dev(MachineClass *mc, const char 
> *type);
> +
> +
>  /**
>   * CPUArchId:
>   * @arch_id - architecture-dependent CPU ID of present or possible CPU
> @@ -179,7 +182,6 @@ struct MachineClass {
>  no_floppy:1,
>  no_cdrom:1,
>  no_sdcard:1,
> -has_dynamic_sysbus:1,
>  pci_allow_0_address:1,
>  legacy_fw_cfg_order:1;
>  int is_default;
> @@ -197,6 +199,7 @@ struct MachineClass {
>  bool ignore_memory_transaction_failures;
>  int numa_mem_align_shift;
>  const char **valid_cpu_types;
> +strList *allowed_dynamic_sysbus_devices;
>  bool auto_enable_numa_with_memhp;
>  void (*numa_auto_assign_ram)(MachineClass *mc, NodeInfo *nodes,
>   int nb_nodes, ram_addr_t size);
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 9e18b410d7..fa6dc15fcd 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -1591,7 +1591,8 @@ static void virt_machine_class_init(ObjectClass *oc, 
> void *data)
>   * configuration of the particular instance.
>   */
>  mc->max_cpus = 255;
> -mc->has_dynamic_sysbus = true;
> +/*TODO: allow only sysbus devices that really work with this machine */
> +machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SYS_BUS_DEVICE);
>  mc->block_default_type = IF_VIRTIO;
>  mc->no_cdrom = 1;
>  mc->pci_allow_0_address = true;
> diff --git a/hw/core/machine.c b/hw/core/machine.c
> index 36c2fb069c..ab2ec292f3 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c
> @@ -335,29 +335,44 @@ static bool machine_get_enforce_config_section(Object 
> *obj, Error **errp)
>  return ms->enforce_config_section;
>  }
>  
> -static void error_on_sysbus_device(SysBusDevice *sbdev, void *opaque)
> +void machine_class_allow_dynamic_sysbus_dev(MachineClass *mc, const char 
> *type)
>  {
> -error_report("Option '-device %s' cannot be handled by this machine",
> - object_class_get_name(object_get_class(OBJECT(sbdev;
> -exit(1);
> +strList *item = g_new0(strList, 1);
> +
> +item->value = g_strdup(type);
> +item->next = mc->allowed_dynamic_sysbus_devices;
> +mc->allowed_dynamic_sysbus_devices = item;
>  }
>  
> -static void machine_init_notify(Notifier *notifier, void *data)
> +static void validate_sysbus_device(SysBusDevice *sbdev, void *opaque)
>  {
> -Object *machine = qdev_get_machine();
> -ObjectClass *oc = object_get_class(machine);
> -MachineClass *mc = MACHINE_CLASS(oc);
> +MachineState *machine = opaque;
> +MachineClass *mc = MACHINE_GET_CLASS(machine);
> +bool allowed = false;
> +strList *wl;
>  
> -if (mc->has_dynamic_sysbus) {
> -/* Our machine can handle dynamic sysbus devices, we're all good */
> -return;
> +for (wl = mc->allowed_dynamic_sysbus_devices;
> + !allowed && wl;
> + wl = wl->next) {
> +allowed |= !!object_dynamic_cast(OBJECT(sbdev), wl->value);
>  }
>  
> +if (!allowed) {
> +error_report("Option '-device %s' cannot be handled by this machine",
> + object_

Re: [Qemu-devel] [PATCH v2 4/6] spapr: Allow only supported dynamic sysbus devices

2017-11-26 Thread David Gibson
On Sat, Nov 25, 2017 at 01:16:08PM -0200, Eduardo Habkost wrote:
> TYPE_SPAPR_PCI_HOST_BRIDGE is the only dynamic sysbus device not
> rejected by ppc_spapr_reset(), so it can be the only entry on the
> allowed list.
> 
> Cc: David Gibson 
> Cc: Alexander Graf 
> Cc: qemu-...@nongnu.org
> Signed-off-by: Eduardo Habkost 

Acked-by: David Gibson 

Again, do you need me to take this through my tree?

> ---
> Changes series v1 -> v2:
> * New patch added to series
> ---
>  hw/ppc/spapr.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 82040cc5d1..3c6d6f2cea 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -3603,8 +3603,7 @@ static void spapr_machine_class_init(ObjectClass *oc, 
> void *data)
>  mc->default_boot_order = "";
>  mc->default_ram_size = 512 * M_BYTE;
>  mc->kvm_type = spapr_kvm_type;
> -/*TODO: allow only sysbus devices that really work with this machine */
> -machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SYS_BUS_DEVICE);
> +machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SPAPR_PCI_HOST_BRIDGE);
>  mc->pci_allow_0_address = true;
>  mc->get_hotplug_handler = spapr_get_hotplug_handler;
>  hc->pre_plug = spapr_machine_device_pre_plug;

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


[Qemu-devel] [PATCH v9 10/13] xilinx_spips: Add support for 4 byte addresses in the LQSPI

2017-11-26 Thread Francisco Iglesias
Add support for 4 byte addresses in the LQSPI and correct LQSPI_CFG_SEP_BUS.

Signed-off-by: Francisco Iglesias 
Reviewed-by: Alistair Francis 
Reviewed-by: Edgar E. Iglesias 
Tested-by: Edgar E. Iglesias 
---
 hw/ssi/xilinx_spips.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 878b17e..ab54da8 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -92,8 +92,9 @@
 #define R_LQSPI_CFG_RESET   0x03A002EB
 #define LQSPI_CFG_LQ_MODE   (1U << 31)
 #define LQSPI_CFG_TWO_MEM   (1 << 30)
-#define LQSPI_CFG_SEP_BUS   (1 << 30)
+#define LQSPI_CFG_SEP_BUS   (1 << 29)
 #define LQSPI_CFG_U_PAGE(1 << 28)
+#define LQSPI_CFG_ADDR4 (1 << 27)
 #define LQSPI_CFG_MODE_EN   (1 << 25)
 #define LQSPI_CFG_MODE_WIDTH8
 #define LQSPI_CFG_MODE_SHIFT16
@@ -702,6 +703,9 @@ static void lqspi_load_cache(void *opaque, hwaddr addr)
 fifo8_push(&s->tx_fifo, s->regs[R_LQSPI_CFG] & LQSPI_CFG_INST_CODE);
 /* read address */
 DB_PRINT_L(0, "pushing read address %06x\n", flash_addr);
+if (s->regs[R_LQSPI_CFG] & LQSPI_CFG_ADDR4) {
+fifo8_push(&s->tx_fifo, (uint8_t)(flash_addr >> 24));
+}
 fifo8_push(&s->tx_fifo, (uint8_t)(flash_addr >> 16));
 fifo8_push(&s->tx_fifo, (uint8_t)(flash_addr >> 8));
 fifo8_push(&s->tx_fifo, (uint8_t)flash_addr);
-- 
2.9.3




[Qemu-devel] [PATCH v9 09/13] xilinx_spips: Add support for zero pumping

2017-11-26 Thread Francisco Iglesias
Add support for zero pumping according to the transfer size register.

Signed-off-by: Francisco Iglesias 
Reviewed-by: Edgar E. Iglesias 
Tested-by: Edgar E. Iglesias 
---
 hw/ssi/xilinx_spips.c | 47 ---
 include/hw/ssi/xilinx_spips.h |  2 ++
 2 files changed, 42 insertions(+), 7 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 4621dbb..878b17e 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -109,6 +109,7 @@
 FIELD(CMND, DUMMY_CYCLES, 2, 6)
 #define R_CMND_DMA_EN (1 << 1)
 #define R_CMND_PUSH_WAIT  (1 << 0)
+#define R_TRANSFER_SIZE (0xc4 / 4)
 #define R_LQSPI_STS (0xA4 / 4)
 #define LQSPI_STS_WR_RECVD  (1 << 1)
 
@@ -227,6 +228,7 @@ static void xilinx_spips_reset(DeviceState *d)
 s->link_state_next_when = 0;
 s->snoop_state = SNOOP_CHECKING;
 s->cmd_dummies = 0;
+s->man_start_com = false;
 xilinx_spips_update_ixr(s);
 xilinx_spips_update_cs_lines(s);
 }
@@ -464,6 +466,41 @@ static inline void tx_data_bytes(Fifo8 *fifo, uint32_t 
value, int num, bool be)
 }
 }
 
+static void xilinx_spips_check_zero_pump(XilinxSPIPS *s)
+{
+if (!s->regs[R_TRANSFER_SIZE]) {
+return;
+}
+if (!fifo8_is_empty(&s->tx_fifo) && s->regs[R_CMND] & R_CMND_PUSH_WAIT) {
+return;
+}
+/*
+ * The zero pump must never fill tx fifo such that rx overflow is
+ * possible
+ */
+while (s->regs[R_TRANSFER_SIZE] &&
+   s->rx_fifo.num + s->tx_fifo.num < RXFF_A_Q - 3) {
+/* endianess just doesn't matter when zero pumping */
+tx_data_bytes(&s->tx_fifo, 0, 4, false);
+s->regs[R_TRANSFER_SIZE] &= ~0x03ull;
+s->regs[R_TRANSFER_SIZE] -= 4;
+}
+}
+
+static void xilinx_spips_check_flush(XilinxSPIPS *s)
+{
+if (s->man_start_com ||
+(!fifo8_is_empty(&s->tx_fifo) &&
+ !(s->regs[R_CONFIG] & MAN_START_EN))) {
+xilinx_spips_check_zero_pump(s);
+xilinx_spips_flush_txfifo(s);
+}
+if (fifo8_is_empty(&s->tx_fifo) && !s->regs[R_TRANSFER_SIZE]) {
+s->man_start_com = false;
+}
+xilinx_spips_update_ixr(s);
+}
+
 static inline int rx_data_bytes(Fifo8 *fifo, uint8_t *value, int max)
 {
 int i;
@@ -533,7 +570,6 @@ static void xilinx_spips_write(void *opaque, hwaddr addr,
 uint64_t value, unsigned size)
 {
 int mask = ~0;
-int man_start_com = 0;
 XilinxSPIPS *s = opaque;
 
 DB_PRINT_L(0, "addr=" TARGET_FMT_plx " = %x\n", addr, (unsigned)value);
@@ -541,8 +577,8 @@ static void xilinx_spips_write(void *opaque, hwaddr addr,
 switch (addr) {
 case R_CONFIG:
 mask = ~(R_CONFIG_RSVD | MAN_START_COM);
-if (value & MAN_START_COM) {
-man_start_com = 1;
+if ((value & MAN_START_COM) && (s->regs[R_CONFIG] & MAN_START_EN)) {
+s->man_start_com = true;
 }
 break;
 case R_INTR_STATUS:
@@ -588,10 +624,7 @@ static void xilinx_spips_write(void *opaque, hwaddr addr,
 s->regs[addr] = (s->regs[addr] & ~mask) | (value & mask);
 no_reg_update:
 xilinx_spips_update_cs_lines(s);
-if ((man_start_com && s->regs[R_CONFIG] & MAN_START_EN) ||
-(fifo8_is_empty(&s->tx_fifo) && s->regs[R_CONFIG] & MAN_START_EN)) 
{
-xilinx_spips_flush_txfifo(s);
-}
+xilinx_spips_check_flush(s);
 xilinx_spips_update_cs_lines(s);
 xilinx_spips_update_ixr(s);
 }
diff --git a/include/hw/ssi/xilinx_spips.h b/include/hw/ssi/xilinx_spips.h
index bac90a5..ad2175a 100644
--- a/include/hw/ssi/xilinx_spips.h
+++ b/include/hw/ssi/xilinx_spips.h
@@ -76,6 +76,8 @@ struct XilinxSPIPS {
 uint32_t rx_discard;
 
 uint32_t regs[XLNX_SPIPS_R_MAX];
+
+bool man_start_com;
 };
 
 typedef struct {
-- 
2.9.3




[Qemu-devel] [PATCH v9 08/13] xilinx_spips: Make tx/rx_data_bytes more generic and reusable

2017-11-26 Thread Francisco Iglesias
Make tx/rx_data_bytes more generic so they can be reused (when adding
support for the Zynqmp Generic QSPI).

Signed-off-by: Francisco Iglesias 
Reviewed-by: Edgar E. Iglesias 
Tested-by: Edgar E. Iglesias 
---
 hw/ssi/xilinx_spips.c | 64 +--
 1 file changed, 37 insertions(+), 27 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 691d48d..4621dbb 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -47,7 +47,7 @@
 /* config register */
 #define R_CONFIG(0x00 / 4)
 #define IFMODE  (1U << 31)
-#define ENDIAN  (1 << 26)
+#define R_CONFIG_ENDIAN (1 << 26)
 #define MODEFAIL_GEN_EN (1 << 17)
 #define MAN_START_COM   (1 << 16)
 #define MAN_START_EN(1 << 15)
@@ -450,13 +450,28 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
 }
 }
 
-static inline void rx_data_bytes(XilinxSPIPS *s, uint8_t *value, int max)
+static inline void tx_data_bytes(Fifo8 *fifo, uint32_t value, int num, bool be)
 {
 int i;
+for (i = 0; i < num && !fifo8_is_full(fifo); ++i) {
+if (be) {
+fifo8_push(fifo, (uint8_t)(value >> 24));
+value <<= 8;
+} else {
+fifo8_push(fifo, (uint8_t)value);
+value >>= 8;
+}
+}
+}
 
-for (i = 0; i < max && !fifo8_is_empty(&s->rx_fifo); ++i) {
-value[i] = fifo8_pop(&s->rx_fifo);
+static inline int rx_data_bytes(Fifo8 *fifo, uint8_t *value, int max)
+{
+int i;
+
+for (i = 0; i < max && !fifo8_is_empty(fifo); ++i) {
+value[i] = fifo8_pop(fifo);
 }
+return max - i;
 }
 
 static uint64_t xilinx_spips_read(void *opaque, hwaddr addr,
@@ -466,6 +481,7 @@ static uint64_t xilinx_spips_read(void *opaque, hwaddr addr,
 uint32_t mask = ~0;
 uint32_t ret;
 uint8_t rx_buf[4];
+int shortfall;
 
 addr >>= 2;
 switch (addr) {
@@ -496,9 +512,13 @@ static uint64_t xilinx_spips_read(void *opaque, hwaddr 
addr,
 break;
 case R_RX_DATA:
 memset(rx_buf, 0, sizeof(rx_buf));
-rx_data_bytes(s, rx_buf, s->num_txrx_bytes);
-ret = s->regs[R_CONFIG] & ENDIAN ? cpu_to_be32(*(uint32_t *)rx_buf)
-: cpu_to_le32(*(uint32_t *)rx_buf);
+shortfall = rx_data_bytes(&s->rx_fifo, rx_buf, s->num_txrx_bytes);
+ret = s->regs[R_CONFIG] & R_CONFIG_ENDIAN ?
+cpu_to_be32(*(uint32_t *)rx_buf) :
+cpu_to_le32(*(uint32_t *)rx_buf);
+if (!(s->regs[R_CONFIG] & R_CONFIG_ENDIAN)) {
+ret <<= 8 * shortfall;
+}
 DB_PRINT_L(0, "addr=" TARGET_FMT_plx " = %x\n", addr * 4, ret);
 xilinx_spips_update_ixr(s);
 return ret;
@@ -509,20 +529,6 @@ static uint64_t xilinx_spips_read(void *opaque, hwaddr 
addr,
 
 }
 
-static inline void tx_data_bytes(XilinxSPIPS *s, uint32_t value, int num)
-{
-int i;
-for (i = 0; i < num && !fifo8_is_full(&s->tx_fifo); ++i) {
-if (s->regs[R_CONFIG] & ENDIAN) {
-fifo8_push(&s->tx_fifo, (uint8_t)(value >> 24));
-value <<= 8;
-} else {
-fifo8_push(&s->tx_fifo, (uint8_t)value);
-value >>= 8;
-}
-}
-}
-
 static void xilinx_spips_write(void *opaque, hwaddr addr,
 uint64_t value, unsigned size)
 {
@@ -563,16 +569,20 @@ static void xilinx_spips_write(void *opaque, hwaddr addr,
 mask = 0;
 break;
 case R_TX_DATA:
-tx_data_bytes(s, (uint32_t)value, s->num_txrx_bytes);
+tx_data_bytes(&s->tx_fifo, (uint32_t)value, s->num_txrx_bytes,
+  s->regs[R_CONFIG] & R_CONFIG_ENDIAN);
 goto no_reg_update;
 case R_TXD1:
-tx_data_bytes(s, (uint32_t)value, 1);
+tx_data_bytes(&s->tx_fifo, (uint32_t)value, 1,
+  s->regs[R_CONFIG] & R_CONFIG_ENDIAN);
 goto no_reg_update;
 case R_TXD2:
-tx_data_bytes(s, (uint32_t)value, 2);
+tx_data_bytes(&s->tx_fifo, (uint32_t)value, 2,
+  s->regs[R_CONFIG] & R_CONFIG_ENDIAN);
 goto no_reg_update;
 case R_TXD3:
-tx_data_bytes(s, (uint32_t)value, 3);
+tx_data_bytes(&s->tx_fifo, (uint32_t)value, 3,
+  s->regs[R_CONFIG] & R_CONFIG_ENDIAN);
 goto no_reg_update;
 }
 s->regs[addr] = (s->regs[addr] & ~mask) | (value & mask);
@@ -682,11 +692,11 @@ static void lqspi_load_cache(void *opaque, hwaddr addr)
 
 while (cache_entry < LQSPI_CACHE_SIZE) {
 for (i = 0; i < 64; ++i) {
-tx_data_bytes(s, 0, 1);
+tx_data_bytes(&s->tx_fifo, 0, 1, false);
 }
 xilinx_spips_flush_txfifo(s);
 for (i = 0; i < 64; ++i) {
-rx_data_bytes(s, &q->lqspi_buf[cache_entry++], 1);
+rx_data_bytes(&s->rx_fifo, &q->lqspi_buf[cache_entry++], 1);
 }
 }

[Qemu-devel] [PATCH v9 07/13] xilinx_spips: Add support for RX discard and RX drain

2017-11-26 Thread Francisco Iglesias
Add support for the RX discard and RX drain functionality. Also transmit
one byte per dummy cycle (to the flash memories) with commands that require
these.

Signed-off-by: Francisco Iglesias 
Reviewed-by: Edgar E. Iglesias 
Tested-by: Edgar E. Iglesias 
---
 hw/ssi/xilinx_spips.c | 167 +-
 include/hw/ssi/xilinx_spips.h |   6 ++
 2 files changed, 155 insertions(+), 18 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 231aa5b..691d48d 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -30,6 +30,7 @@
 #include "qemu/bitops.h"
 #include "hw/ssi/xilinx_spips.h"
 #include "qapi/error.h"
+#include "hw/register.h"
 #include "migration/blocker.h"
 
 #ifndef XILINX_SPIPS_ERR_DEBUG
@@ -100,6 +101,14 @@
 #define LQSPI_CFG_DUMMY_SHIFT   8
 #define LQSPI_CFG_INST_CODE 0xFF
 
+#define R_CMND(0xc0 / 4)
+#define R_CMND_RXFIFO_DRAIN   (1 << 19)
+FIELD(CMND, PARTIAL_BYTE_LEN, 16, 3)
+#define R_CMND_EXT_ADD(1 << 15)
+FIELD(CMND, RX_DISCARD, 8, 7)
+FIELD(CMND, DUMMY_CYCLES, 2, 6)
+#define R_CMND_DMA_EN (1 << 1)
+#define R_CMND_PUSH_WAIT  (1 << 0)
 #define R_LQSPI_STS (0xA4 / 4)
 #define LQSPI_STS_WR_RECVD  (1 << 1)
 
@@ -116,7 +125,8 @@
 #define LQSPI_ADDRESS_BITS 24
 
 #define SNOOP_CHECKING 0xFF
-#define SNOOP_NONE 0xFE
+#define SNOOP_ADDR 0xF0
+#define SNOOP_NONE 0xEE
 #define SNOOP_STRIPING 0
 
 static inline int num_effective_busses(XilinxSPIPS *s)
@@ -146,9 +156,14 @@ static void xilinx_spips_update_cs_lines(XilinxSPIPS *s)
 if (xilinx_spips_cs_is_set(s, i, field) && !found) {
 DB_PRINT_L(0, "selecting slave %d\n", i);
 qemu_set_irq(s->cs_lines[cs_to_set], 0);
+if (s->cs_lines_state[cs_to_set]) {
+s->cs_lines_state[cs_to_set] = false;
+s->rx_discard = ARRAY_FIELD_EX32(s->regs, CMND, 
RX_DISCARD);
+}
 } else {
 DB_PRINT_L(0, "deselecting slave %d\n", i);
 qemu_set_irq(s->cs_lines[cs_to_set], 1);
+s->cs_lines_state[cs_to_set] = true;
 }
 }
 if (xilinx_spips_cs_is_set(s, i, field)) {
@@ -157,6 +172,10 @@ static void xilinx_spips_update_cs_lines(XilinxSPIPS *s)
 }
 if (!found) {
 s->snoop_state = SNOOP_CHECKING;
+s->cmd_dummies = 0;
+s->link_state = 1;
+s->link_state_next = 1;
+s->link_state_next_when = 0;
 DB_PRINT_L(1, "moving to snoop check state\n");
 }
 }
@@ -203,7 +222,11 @@ static void xilinx_spips_reset(DeviceState *d)
 /* FIXME: move magic number definition somewhere sensible */
 s->regs[R_MOD_ID] = 0x01090106;
 s->regs[R_LQSPI_CFG] = R_LQSPI_CFG_RESET;
+s->link_state = 1;
+s->link_state_next = 1;
+s->link_state_next_when = 0;
 s->snoop_state = SNOOP_CHECKING;
+s->cmd_dummies = 0;
 xilinx_spips_update_ixr(s);
 xilinx_spips_update_cs_lines(s);
 }
@@ -238,14 +261,69 @@ static inline void stripe8(uint8_t *x, int num, bool dir)
 memcpy(x, r, sizeof(uint8_t) * num);
 }
 
+static int xilinx_spips_num_dummies(XilinxQSPIPS *qs, uint8_t command)
+{
+if (!qs) {
+/* The SPI device is not a QSPI device */
+return -1;
+}
+
+switch (command) { /* check for dummies */
+case READ: /* no dummy bytes/cycles */
+case PP:
+case DPP:
+case QPP:
+case READ_4:
+case PP_4:
+case QPP_4:
+return 0;
+case FAST_READ:
+case DOR:
+case QOR:
+case DOR_4:
+case QOR_4:
+return 1;
+case DIOR:
+case FAST_READ_4:
+case DIOR_4:
+return 2;
+case QIOR:
+case QIOR_4:
+return 5;
+default:
+return -1;
+}
+}
+
+static inline uint8_t get_addr_length(XilinxSPIPS *s, uint8_t cmd)
+{
+   switch (cmd) {
+   case PP_4:
+   case QPP_4:
+   case READ_4:
+   case QIOR_4:
+   case FAST_READ_4:
+   case DOR_4:
+   case QOR_4:
+   case DIOR_4:
+   return 4;
+   default:
+   return (s->regs[R_CMND] & R_CMND_EXT_ADD) ? 4 : 3;
+   }
+}
+
 static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
 {
 int debug_level = 0;
+XilinxQSPIPS *q = (XilinxQSPIPS *) object_dynamic_cast(OBJECT(s),
+   TYPE_XILINX_QSPIPS);
 
 for (;;) {
 int i;
 uint8_t tx = 0;
 uint8_t tx_rx[num_effective_busses(s)];
+uint8_t dummy_cycles = 0;
+uint8_t addr_length;
 
 if (fifo8_is_empty(&s->tx_fifo)) {
 if (!(s->regs[R_LQSPI_CFG] & LQSPI_CFG_LQ_MODE)) {
@@ -258,54 +336,102 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
 tx_rx[i] = fifo8_pop(&s->tx_fifo);
 }
 stripe8(tx_rx, num_effective_busses(s), false);
-} else {
+} else if (s->snoop_state >= SNOOP_ADDR) {
 tx = fifo8_pop(&s->tx_fifo);
 fo

[Qemu-devel] [PATCH v9 11/13] xilinx_spips: Don't set TX FIFO UNDERFLOW at cmd done

2017-11-26 Thread Francisco Iglesias
Don't set TX FIFO UNDERFLOW interrupt after transmitting the commands.
Also update interrupts after reading out the interrupt status.

Signed-off-by: Francisco Iglesias 
Acked-by: Alistair Francis 
Reviewed-by: Edgar E. Iglesias 
Tested-by: Edgar E. Iglesias 
---
 hw/ssi/xilinx_spips.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index ab54da8..3805d8b 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -329,9 +329,6 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
 uint8_t addr_length;
 
 if (fifo8_is_empty(&s->tx_fifo)) {
-if (!(s->regs[R_LQSPI_CFG] & LQSPI_CFG_LQ_MODE)) {
-s->regs[R_INTR_STATUS] |= IXR_TX_FIFO_UNDERFLOW;
-}
 xilinx_spips_update_ixr(s);
 return;
 } else if (s->snoop_state == SNOOP_STRIPING) {
@@ -530,6 +527,7 @@ static uint64_t xilinx_spips_read(void *opaque, hwaddr addr,
 ret = s->regs[addr] & IXR_ALL;
 s->regs[addr] = 0;
 DB_PRINT_L(0, "addr=" TARGET_FMT_plx " = %x\n", addr * 4, ret);
+xilinx_spips_update_ixr(s);
 return ret;
 case R_INTR_MASK:
 mask = IXR_ALL;
-- 
2.9.3




[Qemu-devel] [PATCH v9 05/13] xilinx_spips: Move FlashCMD, XilinxQSPIPS and XilinxSPIPSClass

2017-11-26 Thread Francisco Iglesias
Move the FlashCMD enum, XilinxQSPIPS and XilinxSPIPSClass structures to the
header for consistency (struct XilinxSPIPS is found there). Also move out
a define and remove two double included headers (while touching the code).
Finally, add 4 byte address commands to the FlashCMD enum.

Signed-off-by: Francisco Iglesias 
Reviewed-by: Alistair Francis 
Reviewed-by: Edgar E. Iglesias 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Edgar E. Iglesias 
---
 hw/ssi/xilinx_spips.c | 35 ---
 include/hw/ssi/xilinx_spips.h | 34 ++
 2 files changed, 34 insertions(+), 35 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index ef56d35..559fa79 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -27,8 +27,6 @@
 #include "sysemu/sysemu.h"
 #include "hw/ptimer.h"
 #include "qemu/log.h"
-#include "qemu/fifo8.h"
-#include "hw/ssi/ssi.h"
 #include "qemu/bitops.h"
 #include "hw/ssi/xilinx_spips.h"
 #include "qapi/error.h"
@@ -116,44 +114,11 @@
 
 /* 16MB per linear region */
 #define LQSPI_ADDRESS_BITS 24
-/* Bite off 4k chunks at a time */
-#define LQSPI_CACHE_SIZE 1024
 
 #define SNOOP_CHECKING 0xFF
 #define SNOOP_NONE 0xFE
 #define SNOOP_STRIPING 0
 
-typedef enum {
-READ = 0x3,
-FAST_READ = 0xb,
-DOR = 0x3b,
-QOR = 0x6b,
-DIOR = 0xbb,
-QIOR = 0xeb,
-
-PP = 0x2,
-DPP = 0xa2,
-QPP = 0x32,
-} FlashCMD;
-
-typedef struct {
-XilinxSPIPS parent_obj;
-
-uint8_t lqspi_buf[LQSPI_CACHE_SIZE];
-hwaddr lqspi_cached_addr;
-Error *migration_blocker;
-bool mmio_execution_enabled;
-} XilinxQSPIPS;
-
-typedef struct XilinxSPIPSClass {
-SysBusDeviceClass parent_class;
-
-const MemoryRegionOps *reg_ops;
-
-uint32_t rx_fifo_size;
-uint32_t tx_fifo_size;
-} XilinxSPIPSClass;
-
 static inline int num_effective_busses(XilinxSPIPS *s)
 {
 return (s->regs[R_LQSPI_CFG] & LQSPI_CFG_SEP_BUS &&
diff --git a/include/hw/ssi/xilinx_spips.h b/include/hw/ssi/xilinx_spips.h
index 06aa096..7f9e2fc 100644
--- a/include/hw/ssi/xilinx_spips.h
+++ b/include/hw/ssi/xilinx_spips.h
@@ -32,6 +32,22 @@ typedef struct XilinxSPIPS XilinxSPIPS;
 
 #define XLNX_SPIPS_R_MAX(0x100 / 4)
 
+/* Bite off 4k chunks at a time */
+#define LQSPI_CACHE_SIZE 1024
+
+typedef enum {
+READ = 0x3, READ_4 = 0x13,
+FAST_READ = 0xb,FAST_READ_4 = 0x0c,
+DOR = 0x3b, DOR_4 = 0x3c,
+QOR = 0x6b, QOR_4 = 0x6c,
+DIOR = 0xbb,DIOR_4 = 0xbc,
+QIOR = 0xeb,QIOR_4 = 0xec,
+
+PP = 0x2,   PP_4 = 0x12,
+DPP = 0xa2,
+QPP = 0x32, QPP_4 = 0x34,
+} FlashCMD;
+
 struct XilinxSPIPS {
 SysBusDevice parent_obj;
 
@@ -56,6 +72,24 @@ struct XilinxSPIPS {
 uint32_t regs[XLNX_SPIPS_R_MAX];
 };
 
+typedef struct {
+XilinxSPIPS parent_obj;
+
+uint8_t lqspi_buf[LQSPI_CACHE_SIZE];
+hwaddr lqspi_cached_addr;
+Error *migration_blocker;
+bool mmio_execution_enabled;
+} XilinxQSPIPS;
+
+typedef struct XilinxSPIPSClass {
+SysBusDeviceClass parent_class;
+
+const MemoryRegionOps *reg_ops;
+
+uint32_t rx_fifo_size;
+uint32_t tx_fifo_size;
+} XilinxSPIPSClass;
+
 #define TYPE_XILINX_SPIPS "xlnx.ps7-spi"
 #define TYPE_XILINX_QSPIPS "xlnx.ps7-qspi"
 
-- 
2.9.3




[Qemu-devel] [PATCH v9 12/13] xilinx_spips: Add support for the ZynqMP Generic QSPI

2017-11-26 Thread Francisco Iglesias
Add support for the Zynq Ultrascale MPSoc Generic QSPI.

Signed-off-by: Francisco Iglesias 
Reviewed-by: Edgar E. Iglesias 
Tested-by: Edgar E. Iglesias 
---
 default-configs/arm-softmmu.mak |   2 +-
 hw/ssi/xilinx_spips.c   | 579 
 include/hw/ssi/xilinx_spips.h   |  32 ++-
 3 files changed, 564 insertions(+), 49 deletions(-)

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index d37edc4..b0d6e65 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -130,5 +130,5 @@ CONFIG_SMBIOS=y
 CONFIG_ASPEED_SOC=y
 CONFIG_GPIO_KEY=y
 CONFIG_MSF2=y
-
 CONFIG_FW_CFG_DMA=y
+CONFIG_XILINX_AXI=y
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 3805d8b..ad1b2ba 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -31,6 +31,7 @@
 #include "hw/ssi/xilinx_spips.h"
 #include "qapi/error.h"
 #include "hw/register.h"
+#include "sysemu/dma.h"
 #include "migration/blocker.h"
 
 #ifndef XILINX_SPIPS_ERR_DEBUG
@@ -69,13 +70,30 @@
 #define R_INTR_DIS  (0x0C / 4)
 #define R_INTR_MASK (0x10 / 4)
 #define IXR_TX_FIFO_UNDERFLOW   (1 << 6)
+/* Poll timeout not implemented */
+#define IXR_RX_FIFO_EMPTY   (1 << 11)
+#define IXR_GENERIC_FIFO_FULL   (1 << 10)
+#define IXR_GENERIC_FIFO_NOT_FULL (1 << 9)
+#define IXR_TX_FIFO_EMPTY   (1 << 8)
+#define IXR_GENERIC_FIFO_EMPTY  (1 << 7)
 #define IXR_RX_FIFO_FULL(1 << 5)
 #define IXR_RX_FIFO_NOT_EMPTY   (1 << 4)
 #define IXR_TX_FIFO_FULL(1 << 3)
 #define IXR_TX_FIFO_NOT_FULL(1 << 2)
 #define IXR_TX_FIFO_MODE_FAIL   (1 << 1)
 #define IXR_RX_FIFO_OVERFLOW(1 << 0)
-#define IXR_ALL ((IXR_TX_FIFO_UNDERFLOW<<1)-1)
+#define IXR_ALL ((1 << 13) - 1)
+#define GQSPI_IXR_MASK  0xFBE
+#define IXR_SELF_CLEAR \
+(IXR_GENERIC_FIFO_EMPTY \
+| IXR_GENERIC_FIFO_FULL  \
+| IXR_GENERIC_FIFO_NOT_FULL \
+| IXR_TX_FIFO_EMPTY \
+| IXR_TX_FIFO_FULL  \
+| IXR_TX_FIFO_NOT_FULL \
+| IXR_RX_FIFO_EMPTY \
+| IXR_RX_FIFO_FULL  \
+| IXR_RX_FIFO_NOT_EMPTY)
 
 #define R_EN(0x14 / 4)
 #define R_DELAY (0x18 / 4)
@@ -116,9 +134,54 @@
 
 #define R_MOD_ID(0xFC / 4)
 
+#define R_GQSPI_SELECT  (0x144 / 4)
+FIELD(GQSPI_SELECT, GENERIC_QSPI_EN, 0, 1)
+#define R_GQSPI_ISR (0x104 / 4)
+#define R_GQSPI_IER (0x108 / 4)
+#define R_GQSPI_IDR (0x10c / 4)
+#define R_GQSPI_IMR (0x110 / 4)
+#define R_GQSPI_TX_THRESH   (0x128 / 4)
+#define R_GQSPI_RX_THRESH   (0x12c / 4)
+#define R_GQSPI_CNFG(0x100 / 4)
+FIELD(GQSPI_CNFG, MODE_EN, 30, 2)
+FIELD(GQSPI_CNFG, GEN_FIFO_START_MODE, 29, 1)
+FIELD(GQSPI_CNFG, GEN_FIFO_START, 28, 1)
+FIELD(GQSPI_CNFG, ENDIAN, 26, 1)
+/* Poll timeout not implemented */
+FIELD(GQSPI_CNFG, EN_POLL_TIMEOUT, 20, 1)
+/* QEMU doesnt care about any of these last three */
+FIELD(GQSPI_CNFG, BR, 3, 3)
+FIELD(GQSPI_CNFG, CPH, 2, 1)
+FIELD(GQSPI_CNFG, CPL, 1, 1)
+#define R_GQSPI_GEN_FIFO(0x140 / 4)
+#define R_GQSPI_TXD (0x11c / 4)
+#define R_GQSPI_RXD (0x120 / 4)
+#define R_GQSPI_FIFO_CTRL   (0x14c / 4)
+FIELD(GQSPI_FIFO_CTRL, RX_FIFO_RESET, 2, 1)
+FIELD(GQSPI_FIFO_CTRL, TX_FIFO_RESET, 1, 1)
+FIELD(GQSPI_FIFO_CTRL, GENERIC_FIFO_RESET, 0, 1)
+#define R_GQSPI_GFIFO_THRESH(0x150 / 4)
+#define R_GQSPI_DATA_STS (0x15c / 4)
+/* We use the snapshot register to hold the core state for the currently
+ * or most recently executed command. So the generic fifo format is defined
+ * for the snapshot register
+ */
+#define R_GQSPI_GF_SNAPSHOT (0x160 / 4)
+FIELD(GQSPI_GF_SNAPSHOT, POLL, 19, 1)
+FIELD(GQSPI_GF_SNAPSHOT, STRIPE, 18, 1)
+FIELD(GQSPI_GF_SNAPSHOT, RECIEVE, 17, 1)
+FIELD(GQSPI_GF_SNAPSHOT, TRANSMIT, 16, 1)
+FIELD(GQSPI_GF_SNAPSHOT, DATA_BUS_SELECT, 14, 2)
+FIELD(GQSPI_GF_SNAPSHOT, CHIP_SELECT, 12, 2)
+FIELD(GQSPI_GF_SNAPSHOT, SPI_MODE, 10, 2)
+FIELD(GQSPI_GF_SNAPSHOT, EXPONENT, 9, 1)
+FIELD(GQSPI_GF_SNAPSHOT, DATA_XFER, 8, 1)
+FIELD(GQSPI_GF_SNAPSHOT, IMMEDIATE_DATA, 0, 8)
+#define R_GQSPI_MOD_ID(0x168 / 4)
+#define R_GQSPI_MOD_ID_VALUE  0x010A
 /* size of TXRX FIFOs */
-#define RXFF_A  32
-#define TXFF_A  32
+#define RXFF_A  (128)
+#define TXFF_A  (128)
 
 #define RXFF_A_Q  (64 * 4)
 #define TXFF_A_Q  (64 * 4)
@@ -137,42 +200,22 @@ static inline int num_effective_busses(XilinxSPIPS *s)
 s->regs[R_LQSPI_CFG] & LQSPI_CFG_TWO_MEM) ? s->num_busses : 1;
 }
 
-static inline bool xilinx_spips_cs_is_set(XilinxSPIPS *s, int i, int field)
-{
-return ~field & (1 << i) && (s->regs[R_CONFIG] & MANUAL_CS
-|| !fifo8_is_empty(&s->tx_fifo));
-}
-
-static void xilinx_spips_update_cs_lines(XilinxSPIPS *s)
+static void xilinx_spips_update_cs(XilinxSPIPS *s, int field)
 {
-int i, j;
-bool found = false;
-int field =

[Qemu-devel] [PATCH v9 13/13] xlnx-zcu102: Add support for the ZynqMP QSPI

2017-11-26 Thread Francisco Iglesias
Add support for the ZynqMP QSPI (consisting of the Generic QSPI and Legacy
QSPI) and connect Numonyx n25q512a11 flashes to it.

Signed-off-by: Francisco Iglesias 
Reviewed-by: Alistair Francis 
Reviewed-by: Edgar E. Iglesias 
Tested-by: Edgar E. Iglesias 
---
 hw/arm/xlnx-zcu102.c | 23 +++
 hw/arm/xlnx-zynqmp.c | 26 ++
 include/hw/arm/xlnx-zynqmp.h |  5 +
 3 files changed, 54 insertions(+)

diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
index bbe7d04..b126cf1 100644
--- a/hw/arm/xlnx-zcu102.c
+++ b/hw/arm/xlnx-zcu102.c
@@ -151,6 +151,29 @@ static void xlnx_zynqmp_init(XlnxZCU102 *s, MachineState 
*machine)
 sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.spi[i]), 1, cs_line);
 }
 
+for (i = 0; i < XLNX_ZYNQMP_NUM_QSPI_FLASH; i++) {
+SSIBus *spi_bus;
+DeviceState *flash_dev;
+qemu_irq cs_line;
+DriveInfo *dinfo = drive_get_next(IF_MTD);
+int bus = i / XLNX_ZYNQMP_NUM_QSPI_BUS_CS;
+gchar *bus_name = g_strdup_printf("qspi%d", bus);
+
+spi_bus = (SSIBus *)qdev_get_child_bus(DEVICE(&s->soc), bus_name);
+g_free(bus_name);
+
+flash_dev = ssi_create_slave_no_init(spi_bus, "n25q512a11");
+if (dinfo) {
+qdev_prop_set_drive(flash_dev, "drive", blk_by_legacy_dinfo(dinfo),
+&error_fatal);
+}
+qdev_init_nofail(flash_dev);
+
+cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
+
+sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.qspi), i + 1, cs_line);
+}
+
 /* TODO create and connect IDE devices for ide_drive_get() */
 
 xlnx_zcu102_binfo.ram_size = ram_size;
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index c707c66..3256420 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -40,6 +40,10 @@
 #define SATA_ADDR   0xFD0C
 #define SATA_NUM_PORTS  2
 
+#define QSPI_ADDR   0xff0f
+#define LQSPI_ADDR  0xc000
+#define QSPI_IRQ15
+
 #define DP_ADDR 0xfd4a
 #define DP_IRQ  113
 
@@ -171,6 +175,9 @@ static void xlnx_zynqmp_init(Object *obj)
 qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default());
 }
 
+object_initialize(&s->qspi, sizeof(s->qspi), TYPE_XLNX_ZYNQMP_QSPIPS);
+qdev_set_parent_bus(DEVICE(&s->qspi), sysbus_get_default());
+
 object_initialize(&s->dp, sizeof(s->dp), TYPE_XLNX_DP);
 qdev_set_parent_bus(DEVICE(&s->dp), sysbus_get_default());
 
@@ -411,6 +418,25 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error 
**errp)
 g_free(bus_name);
 }
 
+object_property_set_bool(OBJECT(&s->qspi), true, "realized", &err);
+sysbus_mmio_map(SYS_BUS_DEVICE(&s->qspi), 0, QSPI_ADDR);
+sysbus_mmio_map(SYS_BUS_DEVICE(&s->qspi), 1, LQSPI_ADDR);
+sysbus_connect_irq(SYS_BUS_DEVICE(&s->qspi), 0, gic_spi[QSPI_IRQ]);
+
+for (i = 0; i < XLNX_ZYNQMP_NUM_QSPI_BUS; i++) {
+gchar *bus_name;
+gchar *target_bus;
+
+/* Alias controller SPI bus to the SoC itself */
+bus_name = g_strdup_printf("qspi%d", i);
+target_bus = g_strdup_printf("spi%d", i);
+object_property_add_alias(OBJECT(s), bus_name,
+  OBJECT(&s->qspi), target_bus,
+  &error_abort);
+g_free(bus_name);
+g_free(target_bus);
+}
+
 object_property_set_bool(OBJECT(&s->dp), true, "realized", &err);
 if (err) {
 error_propagate(errp, err);
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
index 6eff81a..3e6fb9b 100644
--- a/include/hw/arm/xlnx-zynqmp.h
+++ b/include/hw/arm/xlnx-zynqmp.h
@@ -40,6 +40,10 @@
 #define XLNX_ZYNQMP_NUM_SDHCI 2
 #define XLNX_ZYNQMP_NUM_SPIS 2
 
+#define XLNX_ZYNQMP_NUM_QSPI_BUS 2
+#define XLNX_ZYNQMP_NUM_QSPI_BUS_CS 2
+#define XLNX_ZYNQMP_NUM_QSPI_FLASH 4
+
 #define XLNX_ZYNQMP_NUM_OCM_BANKS 4
 #define XLNX_ZYNQMP_OCM_RAM_0_ADDRESS 0xFFFC
 #define XLNX_ZYNQMP_OCM_RAM_SIZE 0x1
@@ -83,6 +87,7 @@ typedef struct XlnxZynqMPState {
 SysbusAHCIState sata;
 SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI];
 XilinxSPIPS spi[XLNX_ZYNQMP_NUM_SPIS];
+XlnxZynqMPQSPIPS qspi;
 XlnxDPState dp;
 XlnxDPDMAState dpdma;
 
-- 
2.9.3




[Qemu-devel] [PATCH v9 03/13] m25p80: Add support for BRRD/BRWR and BULK_ERASE (0x60)

2017-11-26 Thread Francisco Iglesias
Add support for the bank address register access commands (BRRD/BRWR) and
the BULK_ERASE (0x60) command.

Signed-off-by: Francisco Iglesias 
Acked-by: Marcin Krzemiński 
Reviewed-by: Edgar E. Iglesias 
Tested-by: Edgar E. Iglesias 
---
 hw/block/m25p80.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index 092c0c6..35efdf0 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -331,7 +331,10 @@ typedef enum {
 WRDI = 0x4,
 RDSR = 0x5,
 WREN = 0x6,
+BRRD = 0x16,
+BRWR = 0x17,
 JEDEC_READ = 0x9f,
+BULK_ERASE_60 = 0x60,
 BULK_ERASE = 0xc7,
 READ_FSR = 0x70,
 RDCR = 0x15,
@@ -704,6 +707,7 @@ static void complete_collecting_data(Flash *s)
 s->write_enable = false;
 }
 break;
+case BRWR:
 case EXTEND_ADDR_WRITE:
 s->ear = s->data[0];
 break;
@@ -1050,6 +1054,7 @@ static void decode_new_cmd(Flash *s, uint32_t value)
 s->state = STATE_READING_DATA;
 break;
 
+case BULK_ERASE_60:
 case BULK_ERASE:
 if (s->write_enable) {
 DB_PRINT_L(0, "chip erase\n");
@@ -1067,12 +1072,14 @@ static void decode_new_cmd(Flash *s, uint32_t value)
 case EX_4BYTE_ADDR:
 s->four_bytes_address_mode = false;
 break;
+case BRRD:
 case EXTEND_ADDR_READ:
 s->data[0] = s->ear;
 s->pos = 0;
 s->len = 1;
 s->state = STATE_READING_DATA;
 break;
+case BRWR:
 case EXTEND_ADDR_WRITE:
 if (s->write_enable) {
 s->needed_bytes = 1;
-- 
2.9.3




[Qemu-devel] [PATCH v9 04/13] m25p80: Add support for n25q512a11 and n25q512a13

2017-11-26 Thread Francisco Iglesias
Add support for Micron (Numonyx) n25q512a11 and n25q512a13 flashes.

Signed-off-by: Francisco Iglesias 
Acked-by: Marcin Krzemiński 
Reviewed-by: Alistair Francis 
Reviewed-by: Edgar E. Iglesias 
Tested-by: Edgar E. Iglesias 
---
 hw/block/m25p80.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index 35efdf0..ea14216 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -240,6 +240,8 @@ static const FlashPartInfo known_devices[] = {
 { INFO("n25q128a13",  0x20ba18,  0,  64 << 10, 256, ER_4K) },
 { INFO("n25q256a11",  0x20bb19,  0,  64 << 10, 512, ER_4K) },
 { INFO("n25q256a13",  0x20ba19,  0,  64 << 10, 512, ER_4K) },
+{ INFO("n25q512a11",  0x20bb20,  0,  64 << 10, 1024, ER_4K) },
+{ INFO("n25q512a13",  0x20ba20,  0,  64 << 10, 1024, ER_4K) },
 { INFO("n25q128", 0x20ba18,  0,  64 << 10, 256, 0) },
 { INFO("n25q256a",0x20ba19,  0,  64 << 10, 512, ER_4K) },
 { INFO("n25q512a",0x20ba20,  0,  64 << 10, 1024, ER_4K) },
-- 
2.9.3




[Qemu-devel] [PATCH v9 02/13] m25p80: Add support for SST READ ID 0x90/0xAB commands

2017-11-26 Thread Francisco Iglesias
Add support for SST READ ID 0x90/0xAB commands for reading out the flash
manufacturer ID and device ID.

Signed-off-by: Francisco Iglesias 
---
 hw/block/m25p80.c | 32 
 1 file changed, 32 insertions(+)

diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index d50acc1..092c0c6 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -355,6 +355,8 @@ typedef enum {
 DPP = 0xa2,
 QPP = 0x32,
 QPP_4 = 0x34,
+RDID_90 = 0x90,
+RDID_AB = 0xab,
 
 ERASE_4K = 0x20,
 ERASE4_4K = 0x21,
@@ -405,6 +407,7 @@ typedef enum {
 MAN_MACRONIX,
 MAN_NUMONYX,
 MAN_WINBOND,
+MAN_SST,
 MAN_GENERIC,
 } Manufacturer;
 
@@ -476,6 +479,8 @@ static inline Manufacturer get_man(Flash *s)
 return MAN_SPANSION;
 case 0xC2:
 return MAN_MACRONIX;
+case 0xBF:
+return MAN_SST;
 default:
 return MAN_GENERIC;
 }
@@ -711,6 +716,31 @@ static void complete_collecting_data(Flash *s)
 case WEVCR:
 s->enh_volatile_cfg = s->data[0];
 break;
+case RDID_90:
+case RDID_AB:
+if (get_man(s) == MAN_SST) {
+if (s->cur_addr <= 1) {
+if (s->cur_addr) {
+s->data[0] = s->pi->id[2];
+s->data[1] = s->pi->id[0];
+} else {
+s->data[0] = s->pi->id[0];
+s->data[1] = s->pi->id[2];
+}
+s->pos = 0;
+s->len = 2;
+s->data_read_loop = true;
+s->state = STATE_READING_DATA;
+} else {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "M25P80: Invalid read id address\n");
+}
+} else {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "M25P80: Read id (command 0x90/0xAB) is not 
supported"
+  " by device\n");
+}
+break;
 default:
 break;
 }
@@ -926,6 +956,8 @@ static void decode_new_cmd(Flash *s, uint32_t value)
 case PP4:
 case PP4_4:
 case DIE_ERASE:
+case RDID_90:
+case RDID_AB:
 s->needed_bytes = get_addr_length(s);
 s->pos = 0;
 s->len = 0;
-- 
2.9.3




[Qemu-devel] [PATCH v9 06/13] xilinx_spips: Update striping to be big-endian bit order

2017-11-26 Thread Francisco Iglesias
Update striping functionality to be big-endian bit order (as according to
the Zynq-7000 Technical Reference Manual). Output thereafter the even bits
into the flash memory connected to the lower QSPI bus and the odd bits into
the flash memory connected to the upper QSPI bus.

Signed-off-by: Francisco Iglesias 
Acked-by: Alistair Francis 
Reviewed-by: Edgar E. Iglesias 
Tested-by: Edgar E. Iglesias 
---
 hw/ssi/xilinx_spips.c | 19 ++-
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 559fa79..231aa5b 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -208,14 +208,14 @@ static void xilinx_spips_reset(DeviceState *d)
 xilinx_spips_update_cs_lines(s);
 }
 
-/* N way (num) in place bit striper. Lay out row wise bits (LSB to MSB)
+/* N way (num) in place bit striper. Lay out row wise bits (MSB to LSB)
  * column wise (from element 0 to N-1). num is the length of x, and dir
  * reverses the direction of the transform. Best illustrated by example:
  * Each digit in the below array is a single bit (num == 3):
  *
- * {{ 76543210, }  - stripe (dir == false) -> {{ FCheb630, }
- *  { hgfedcba, }  { GDAfc741, }
- *  { HGFEDCBA, }} < upstripe (dir == true) -  { HEBgda52, }}
+ * {{ 76543210, }  - stripe (dir == false) -> {{ 741gdaFC, }
+ *  { hgfedcba, }  { 630fcHEB, }
+ *  { HGFEDCBA, }} < upstripe (dir == true) -  { 52hebGDA, }}
  */
 
 static inline void stripe8(uint8_t *x, int num, bool dir)
@@ -223,15 +223,15 @@ static inline void stripe8(uint8_t *x, int num, bool dir)
 uint8_t r[num];
 memset(r, 0, sizeof(uint8_t) * num);
 int idx[2] = {0, 0};
-int bit[2] = {0, 0};
+int bit[2] = {0, 7};
 int d = dir;
 
 for (idx[0] = 0; idx[0] < num; ++idx[0]) {
-for (bit[0] = 0; bit[0] < 8; ++bit[0]) {
-r[idx[d]] |= x[idx[!d]] & 1 << bit[!d] ? 1 << bit[d] : 0;
+for (bit[0] = 7; bit[0] >= 0; bit[0]--) {
+r[idx[!d]] |= x[idx[d]] & 1 << bit[d] ? 1 << bit[!d] : 0;
 idx[1] = (idx[1] + 1) % num;
 if (!idx[1]) {
-bit[1]++;
+bit[1]--;
 }
 }
 }
@@ -266,8 +266,9 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
 }
 
 for (i = 0; i < num_effective_busses(s); ++i) {
+int bus = num_effective_busses(s) - 1 - i;
 DB_PRINT_L(debug_level, "tx = %02x\n", tx_rx[i]);
-tx_rx[i] = ssi_transfer(s->spi[i], (uint32_t)tx_rx[i]);
+tx_rx[i] = ssi_transfer(s->spi[bus], (uint32_t)tx_rx[i]);
 DB_PRINT_L(debug_level, "rx = %02x\n", tx_rx[i]);
 }
 
-- 
2.9.3




[Qemu-devel] [PATCH v9 01/13] m25p80: Add support for continuous read out of RDSR and READ_FSR

2017-11-26 Thread Francisco Iglesias
Add support for continuous read out of the RDSR and READ_FSR status
registers until the chip select is deasserted. This feature is supported
by amongst others 1 or more flashtypes manufactured by Numonyx (Micron),
Windbond, SST, Gigadevice, Eon and Macronix.

Signed-off-by: Francisco Iglesias 
Acked-by: Marcin Krzemiński
Reviewed-by: Edgar E. Iglesias 
Tested-by: Edgar E. Iglesias 
---
 hw/block/m25p80.c | 39 ++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index a2438b9..d50acc1 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -423,6 +423,7 @@ typedef struct Flash {
 uint8_t data[M25P80_INTERNAL_DATA_BUFFER_SZ];
 uint32_t len;
 uint32_t pos;
+bool data_read_loop;
 uint8_t needed_bytes;
 uint8_t cmd_in_progress;
 uint32_t cur_addr;
@@ -983,6 +984,7 @@ static void decode_new_cmd(Flash *s, uint32_t value)
 }
 s->pos = 0;
 s->len = 1;
+s->data_read_loop = true;
 s->state = STATE_READING_DATA;
 break;
 
@@ -993,6 +995,7 @@ static void decode_new_cmd(Flash *s, uint32_t value)
 }
 s->pos = 0;
 s->len = 1;
+s->data_read_loop = true;
 s->state = STATE_READING_DATA;
 break;
 
@@ -1133,6 +1136,7 @@ static int m25p80_cs(SSISlave *ss, bool select)
 s->pos = 0;
 s->state = STATE_IDLE;
 flash_sync_dirty(s, -1);
+s->data_read_loop = false;
 }
 
 DB_PRINT_L(0, "%sselect\n", select ? "de" : "");
@@ -1198,7 +1202,9 @@ static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t 
tx)
 s->pos++;
 if (s->pos == s->len) {
 s->pos = 0;
-s->state = STATE_IDLE;
+if (!s->data_read_loop) {
+s->state = STATE_IDLE;
+}
 }
 break;
 
@@ -1269,11 +1275,38 @@ static Property m25p80_properties[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static int m25p80_pre_load(void *opaque)
+{
+Flash *s = (Flash *)opaque;
+
+s->data_read_loop = false;
+return 0;
+}
+
+static bool m25p80_data_read_loop_needed(void *opaque)
+{
+Flash *s = (Flash *)opaque;
+
+return s->data_read_loop;
+}
+
+static const VMStateDescription vmstate_m25p80_data_read_loop = {
+.name = "m25p80/data_read_loop",
+.version_id = 1,
+.minimum_version_id = 1,
+.needed = m25p80_data_read_loop_needed,
+.fields = (VMStateField[]) {
+VMSTATE_BOOL(data_read_loop, Flash),
+VMSTATE_END_OF_LIST()
+}
+};
+
 static const VMStateDescription vmstate_m25p80 = {
 .name = "m25p80",
 .version_id = 0,
 .minimum_version_id = 0,
 .pre_save = m25p80_pre_save,
+.pre_load = m25p80_pre_load,
 .fields = (VMStateField[]) {
 VMSTATE_UINT8(state, Flash),
 VMSTATE_UINT8_ARRAY(data, Flash, M25P80_INTERNAL_DATA_BUFFER_SZ),
@@ -1295,6 +1328,10 @@ static const VMStateDescription vmstate_m25p80 = {
 VMSTATE_UINT8(spansion_cr3nv, Flash),
 VMSTATE_UINT8(spansion_cr4nv, Flash),
 VMSTATE_END_OF_LIST()
+},
+.subsections = (const VMStateDescription * []) {
+&vmstate_m25p80_data_read_loop,
+NULL
 }
 };
 
-- 
2.9.3




[Qemu-devel] [PATCH v9 00/13] Add support for the ZynqMP Generic QSPI

2017-11-26 Thread Francisco Iglesias
Hi,

This patch series is an attempt to add support for the ZynqMP QSPI (consisting
of the Generic QSPI and the legacy QSPI) to the xlnx-zcu102 board and connect 
Numonyx n25q512a11 flashes to the QSPI. Also some functionality is added to
m25p80.

The series starts by adding support in m25p80 for continous read out of status
registers, SST flash READ ID commands, bank address register accesses, bulk
erase (0x60) and two Numonyx flashes (n25q512a11 and n25q512a13). Thereafter it
updates the striping behaviour to be bit big endiann in the Xilinx QSPI model
and adds support for RX discard, zero pumping according transfer register and 4
byte LQSPI addresses. Finally it adds support for the ZynqMP Generic QSPI and
adds the ZynqMP QSPI to the xlnx-zcu102 board.

Best regards,
Francisco Iglesias

Changelog:
v8 -> v9
  * Improved guest error logging in patch 'm25p80: Add support for SST READ ID
0x90/0xAB commands' and removed acked-by lines in the commit message
because of this update.

v7 -> v8
  * Corrected commit messages in the patches 'xilinx_spips: Don't set TX FIFO
UNDERFLOW at cmd done' and 'xilinx_spips: Move FlashCMD, XilinxQSPIPS and
XilinxSPIPSClass'.
  * Changed a for loop and a variable decrease for improving readability in
patch 'xilinx_spips: Update striping to be big-endian bit order'.

v6 -> v7
  * Moved data_read_loop into a vmstate subsection in patch 'm25p80: Add support
for continuous read out of RDSR and READ_FSR' for not breaking compatibility
against older vmstate versions unless necessary.
  * Minor tweaks in patch 'xilinx_spips: Add support for the ZynqMP Generic
QSPI'.

v5 -> v6
  * Added data_read_loop to vmstate_m25p80 in patch 'm25p80: Add support for
continuous read out of RDSR and READ_FSR'. Also removed acked-by lines in 
the commit message because of this update.
  * Reworked patch 'xilinx_spips: Add support for the ZynqMP Generic QSPI'.
  * Tweaked commit messages 

v4 -> v5
  * Added newlines in patch 'xlnx-zcu102: Add support for the ZynqMP QSPI'

v3 -> v4
  * Corrected patch 'Add support for SST READ ID 0x90/0xAB commands'
  * Corrected patch 'Add support Add support for BRRD/BRWR and BULK_ERASE'
  * Minor tweaks in the ZynqMP GQSPI patch for reducing the patch 


Francisco Iglesias (13):
  m25p80: Add support for continuous read out of RDSR and READ_FSR
  m25p80: Add support for SST READ ID 0x90/0xAB commands
  m25p80: Add support for BRRD/BRWR and BULK_ERASE (0x60)
  m25p80: Add support for n25q512a11 and n25q512a13
  xilinx_spips: Move FlashCMD, XilinxQSPIPS and XilinxSPIPSClass
  xilinx_spips: Update striping to be big-endian bit order
  xilinx_spips: Add support for RX discard and RX drain
  xilinx_spips: Make tx/rx_data_bytes more generic and reusable
  xilinx_spips: Add support for zero pumping
  xilinx_spips: Add support for 4 byte addresses in the LQSPI
  xilinx_spips: Don't set TX FIFO UNDERFLOW at cmd done
  xilinx_spips: Add support for the ZynqMP Generic QSPI
  xlnx-zcu102: Add support for the ZynqMP QSPI

 default-configs/arm-softmmu.mak |   2 +-
 hw/arm/xlnx-zcu102.c|  23 +
 hw/arm/xlnx-zynqmp.c|  26 ++
 hw/block/m25p80.c   |  80 +++-
 hw/ssi/xilinx_spips.c   | 899 ++--
 include/hw/arm/xlnx-zynqmp.h|   5 +
 include/hw/ssi/xilinx_spips.h   |  74 +++-
 7 files changed, 970 insertions(+), 139 deletions(-)

-- 
2.9.3




Re: [Qemu-devel] [PATCH v8 02/13] m25p80: Add support for SST READ ID 0x90/0xAB commands

2017-11-26 Thread francisco iglesias
On 26 November 2017 at 01:45, Philippe Mathieu-Daudé 
wrote:

> Hi Francisco,
>
> On 11/24/2017 06:29 PM, Francisco Iglesias wrote:
> > Add support for SST READ ID 0x90/0xAB commands for reading out the flash
> > manufacuter ID and device ID.
> >
> > Signed-off-by: Francisco Iglesias 
> > Acked-by: Alistair Francis 
> > Acked-by: Marcin Krzemiński 
> > ---
> >  hw/block/m25p80.c | 23 +++
> >  1 file changed, 23 insertions(+)
> >
> > diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
> > index d50acc1..9d20120 100644
> > --- a/hw/block/m25p80.c
> > +++ b/hw/block/m25p80.c
> > @@ -355,6 +355,8 @@ typedef enum {
> >  DPP = 0xa2,
> >  QPP = 0x32,
> >  QPP_4 = 0x34,
> > +RDID_90 = 0x90,
> > +RDID_AB = 0xab,
> >
> >  ERASE_4K = 0x20,
> >  ERASE4_4K = 0x21,
> > @@ -405,6 +407,7 @@ typedef enum {
> >  MAN_MACRONIX,
> >  MAN_NUMONYX,
> >  MAN_WINBOND,
> > +MAN_SST,
> >  MAN_GENERIC,
> >  } Manufacturer;
> >
> > @@ -476,6 +479,8 @@ static inline Manufacturer get_man(Flash *s)
> >  return MAN_SPANSION;
> >  case 0xC2:
> >  return MAN_MACRONIX;
> > +case 0xBF:
> > +return MAN_SST;
> >  default:
> >  return MAN_GENERIC;
> >  }
> > @@ -711,6 +716,22 @@ static void complete_collecting_data(Flash *s)
> >  case WEVCR:
> >  s->enh_volatile_cfg = s->data[0];
> >  break;
> > +case RDID_90:
> > +case RDID_AB:
> > +if (get_man(s) == MAN_SST && s->cur_addr <= 1) {
>
> What about reporting if guest access this address when not an SST flash?
>
>if (get_man(s) == MAN_SST) {
>if (s->cur_addr <= 1) {
>
> > +if (s->cur_addr) {
> > +s->data[0] = s->pi->id[2];
> > +s->data[1] = s->pi->id[0];
> > +} else {
> > +s->data[0] = s->pi->id[0];
> > +s->data[1] = s->pi->id[2];
> > +}
> > +s->pos = 0;
> > +s->len = 2;
> > +s->data_read_loop = true;
> > +s->state = STATE_READING_DATA;
>
>} else {
> // LOG_UNIMP?
>}
>} else {
>qemu_log_mask(LOG_GUEST_ERROR, ...);
>

Dear Philippe,

Thank you very much for reviewing! I will add the logs in the next version
of the patch series (v9).

Best regards,
Francisco Iglesias




>
> > +}
> > +break;
> >  default:
> >  break;
> >  }
> > @@ -926,6 +947,8 @@ static void decode_new_cmd(Flash *s, uint32_t value)
> >  case PP4:
> >  case PP4_4:
> >  case DIE_ERASE:
> > +case RDID_90:
> > +case RDID_AB:
> >  s->needed_bytes = get_addr_length(s);
> >  s->pos = 0;
> >  s->len = 0;
>
> Regards,
>
> Phil.
>


[Qemu-devel] [PATCH 16/17] tests: run ds-rtc-i2c-test w/ ppc/mvme3100

2017-11-26 Thread Michael Davidsaver
Signed-off-by: Michael Davidsaver 
---
 tests/Makefile.include  | 3 ++-
 tests/ds-rtc-i2c-test.c | 8 
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/tests/Makefile.include b/tests/Makefile.include
index 56045cdf09..062d4e5b7b 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -308,6 +308,7 @@ check-qtest-ppc-y += tests/boot-order-test$(EXESUF)
 check-qtest-ppc-y += tests/prom-env-test$(EXESUF)
 check-qtest-ppc-y += tests/drive_del-test$(EXESUF)
 check-qtest-ppc-y += tests/boot-serial-test$(EXESUF)
+check-qtest-ppc-y += tests/ds-rtc-i2c-test$(EXESUF)
 
 check-qtest-ppc64-y = tests/spapr-phb-test$(EXESUF)
 gcov-files-ppc64-y = ppc64-softmmu/hw/ppc/spapr_pci.c
@@ -745,7 +746,7 @@ tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o \
tests/boot-sector.o tests/acpi-utils.o $(libqos-obj-y)
 tests/pxe-test$(EXESUF): tests/pxe-test.o tests/boot-sector.o $(libqos-obj-y)
 tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
-tests/ds-rtc-i2c-test$(EXESUF): tests/ds-rtc-i2c-test.o $(libqos-imx-obj-y)
+tests/ds-rtc-i2c-test$(EXESUF): tests/ds-rtc-i2c-test.o $(libqos-imx-obj-y) 
$(libqos-e500-obj-y)
 tests/m25p80-test$(EXESUF): tests/m25p80-test.o
 tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
 tests/q35-test$(EXESUF): tests/q35-test.o $(libqos-pc-obj-y)
diff --git a/tests/ds-rtc-i2c-test.c b/tests/ds-rtc-i2c-test.c
index 0586dbd467..f7dab1863e 100644
--- a/tests/ds-rtc-i2c-test.c
+++ b/tests/ds-rtc-i2c-test.c
@@ -18,6 +18,9 @@
 #define IMX25_I2C_0_BASE 0x43F8
 #define DS1338_ADDR 0x68
 
+#define E500_CCSR_BASE 0xff70
+#define DS1375_ADDR 0xd0
+
 static I2CAdapter *i2c;
 static uint8_t addr;
 static bool use_century;
@@ -148,6 +151,11 @@ int main(int argc, char *argv[])
 addr = DS1338_ADDR;
 use_century = false;
 
+} else if (strcmp(arch, "ppc") == 0) {
+qtest_start("-machine mvme3100-1152");
+i2c = e500_i2c_create(E500_CCSR_BASE);
+addr = DS1375_ADDR;
+use_century = true;
 }
 
 qtest_add_data_func("/ds-rtc-i2c/set24", test_time_24, test_rtc_set);
-- 
2.11.0




[Qemu-devel] [PATCH 15/17] ppc: add mvme3100 machine

2017-11-26 Thread Michael Davidsaver
Signed-off-by: Michael Davidsaver 
---
 default-configs/ppc-softmmu.mak |   1 +
 hw/ppc/Makefile.objs|   1 +
 hw/ppc/mvme3100.c   | 740 
 hw/ppc/mvme3100_cpld.c  | 192 +++
 4 files changed, 934 insertions(+)
 create mode 100644 hw/ppc/mvme3100.c
 create mode 100644 hw/ppc/mvme3100_cpld.c

diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index bb225c6e46..3777194a4a 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -52,3 +52,4 @@ CONFIG_SERIAL_ISA=y
 CONFIG_MC146818RTC=y
 CONFIG_ISA_TESTDEV=y
 CONFIG_RS6000_MC=y
+CONFIG_DSRTCI2C=y
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index c1a63d0c39..c1118aaa42 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -26,5 +26,6 @@ obj-$(CONFIG_MAC) += mac_newworld.o
 obj-$(CONFIG_E500) += e500.o mpc8544ds.o e500plat.o
 obj-$(CONFIG_E500) += ppce500_spin.o
 obj-$(CONFIG_E500) += e500_ccsr.o
+obj-$(CONFIG_E500) += mvme3100.o mvme3100_cpld.o
 # PowerPC 440 Xilinx ML507 reference board.
 obj-$(CONFIG_XILINX) += virtex_ml507.o
diff --git a/hw/ppc/mvme3100.c b/hw/ppc/mvme3100.c
new file mode 100644
index 00..8eb6a3a9a4
--- /dev/null
+++ b/hw/ppc/mvme3100.c
@@ -0,0 +1,740 @@
+/*
+ * MVME3100 board emulation
+ *
+ * Copyright (c) 2015 Michael Davidsaver
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the LICENSE file in the top-level directory.
+ *
+ * This model was developed according to the
+ * MVME3100 Single Board Computer Programmer's Reference
+ * P/N: 6806800G37B
+ * July 2014
+ *
+ * mvme3100-1152
+ *   677MHz core, 256MB ram, 64MB flash
+ * mvme3100-1263
+ *   833MHz core, 512MB ram, 128MB flash
+ *
+ * MOTLoad on mvme3100-1152 says:
+ *   MPU-Type =MPC8540
+ *   MPU-Int Clock Speed  =666MHz
+ *   MPU-CCB Clock Speed  =333MHz
+ *   MPU-DDR Clock Speed  =166MHz
+ *   MPU-PCI Clock Speed  =66MHz, PCI, 64-bit
+ *   MPU-Int Cache(L2) Enabled, 256KB, L2CTL =A8000300
+ *   Reset/Boot Vector=Flash0
+ *   Local Memory Found   =1000 (&268435456)
+ *
+ * MOTLoad on mvme3100-1263 says:
+ *   MPU-Type =MPC8540
+ *   MPU-Int Clock Speed  =833MHz
+ *   MPU-CCB Clock Speed  =333MHz
+ *   MPU-DDR Clock Speed  =166MHz
+ *   MPU-PCI Clock Speed  =66MHz, PCI, 64-bit
+ *   MPU-Int Cache(L2) Enabled, 256KB, L2CTL =A8000300
+ *   Reset/Boot Vector=Flash0
+ *   Local Memory Found   =2000 (&536870912)
+ *
+ * Clock ratios
+ *   CCB/PCI  -> 5/1
+ *   core/CCB -> 2/1 (-1152)
+ *-> 5/2 (-1263)
+ *
+ * The overall memory map is determined by the Local Address Windows.
+ * We do not model the LAWs explicitly.
+ *
+ * MOTLoad configures as follows (a super set of table 1-4)
+ *   (MOTLoad RTOS Version 2.0,  PAL Version 1.2 RM04)
+ * LAW 0, 7 - disabled
+ * LAW 1 - 0x -> 0x7fff - RAM 2G
+ * LAW 2 - 0x8000 -> 0xbfff - PCI 1G
+ * LAW 3 - 0xc000 -> 0xdfff - PCI 512MB
+ * LAW 4 - 0xe000 -> 0xe0ff - PCI 16MB
+ * gap   - 0xe100 -> 0xbfff - CCSR @ 0xe100
+ * LAW 5 - 0xe200 -> 0xe2ff - LBC 16MB
+ * gap   - 0xe300 -> 0xefff
+ * LAW 6 - 0xf000 -> 0x - LBC 256MB
+ *
+ * And validated against the RTEMS 4.9.6 mvme3100 BSP
+ */
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "qapi/visitor.h"
+#include "e500.h"
+#include "cpu.h"
+#include "qemu-common.h"
+#include "cpu-qom.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/dma.h"
+#include "sysemu/block-backend.h"
+#include "hw/loader.h"
+#include "hw/pci/pci.h"
+#include "hw/boards.h"
+#include "hw/ppc/ppc.h"
+#include "hw/net/fsl_etsec/etsec.h"
+#include "sysemu/device_tree.h"
+#include "sysemu/qtest.h"
+#include "hw/ppc/openpic.h"
+#include "qemu/error-report.h"
+
+/* Same as prep.c and other PPC boards */
+#define CFG_ADDR 0xf510
+
+#define TYPE_MVME3100 MACHINE_TYPE_NAME("mvme3100")
+#define MVME3100(obj) OBJECT_CHECK(MVME3100State, (obj), TYPE_MVME3100)
+#define MVME3100_GET_CLASS(obj) \
+OBJECT_GET_CLASS(MVME3100Class, (obj), TYPE_MVME3100)
+#define MVME3100_CLASS(klass) \
+OBJECT_CLASS_CHECK(MVME3100Class, (klass), TYPE_MVME3100)
+
+#define E500_TSEC_OFFSET(N) (0x24000 + (N) * 0x1000)
+
+/* Complex Core Bus frequency */
+#define CCB_FREQ (3u)
+
+typedef struct mvme3100_info {
+const char *desc;
+uint32_t cpu_freq;
+uint32_t porpllsr;
+uint32_t ram_size;
+} mvme3100_info;
+
+typedef struct MVME3100Class {
+/*< private >*/
+MachineClass parent_class;
+/*< public >*/
+
+const mvme3100_info *info;
+} MVME3100Class;
+
+typedef struct MVME3100State {
+/*< private >*/
+MachineState parent_obj;
+/*< public >*/
+
+uint32_t load_address,
+ entry_address;
+
+MemoryRegion ram;
+} MVME3100State;
+
+
+/* motload "global environment" variables */
+static
+const char *gev[] = {
+/* TODO: somehow snoop in slirp

[Qemu-devel] [PATCH 12/17] e500: add i2c controller to CCSR

2017-11-26 Thread Michael Davidsaver
Add i2c controller found on mpc8540,
mpc8544, and P2010 (newer ppc, unmodeled).

Signed-off-by: Michael Davidsaver 
---
 hw/ppc/e500_ccsr.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/hw/ppc/e500_ccsr.c b/hw/ppc/e500_ccsr.c
index c479ed91ee..cd8216daaf 100644
--- a/hw/ppc/e500_ccsr.c
+++ b/hw/ppc/e500_ccsr.c
@@ -46,6 +46,8 @@
 #define E500_ERR_DETECT  (0x2e40)
 #define E500_ERR_DISABLE (0x2e44)
 
+#define E500_I2C_OFFSET  (0x3000)
+
 #define E500_DUART_OFFSET(N) (0x4500 + (N) * 0x100)
 
 #define E500_PORPLLSR(0xE)
@@ -72,6 +74,7 @@ typedef struct {
 uint32_t ccb_freq;
 
 DeviceState *pic;
+DeviceState *i2c;
 } CCSRState;
 
 #define TYPE_E500_CCSR "e500-ccsr"
@@ -272,6 +275,18 @@ static void e500_ccsr_realize(DeviceState *dev, Error 
**errp)
 sysbus_mmio_get_region(pic, 0));
 /* Note: MPIC internal interrupts are offset by 16 */
 
+/* attach I2C controller */
+ccsr->i2c = qdev_create(NULL, "mpc8540-i2c");
+object_property_add_child(qdev_get_machine(), "i2c[*]",
+  OBJECT(ccsr->i2c), NULL);
+qdev_init_nofail(ccsr->i2c);
+memory_region_add_subregion(&ccsr->iomem, E500_I2C_OFFSET,
+sysbus_mmio_get_region(
+SYS_BUS_DEVICE(ccsr->i2c), 0));
+sysbus_connect_irq(SYS_BUS_DEVICE(ccsr->i2c), 0,
+  qdev_get_gpio_in(ccsr->pic, 16 + 27));
+
+
 /* DUARTS */
 /* for mpc8540, mpc8544, and P2010 (unmodeled), the DUART reference clock
  * is the CCB clock divided by 16.
-- 
2.11.0




[Qemu-devel] [PATCH 17/17] tests: add mvme3100-test

2017-11-26 Thread Michael Davidsaver
Exercise some features of the mvme3100 CPLD logic
and read from the eeprom w/ VPD.

Signed-off-by: Michael Davidsaver 
---
 tests/Makefile.include |  3 ++
 tests/mvme3100-test.c  | 79 ++
 2 files changed, 82 insertions(+)
 create mode 100644 tests/mvme3100-test.c

diff --git a/tests/Makefile.include b/tests/Makefile.include
index 062d4e5b7b..97bce77ee4 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -373,6 +373,8 @@ check-qtest-s390x-y += tests/virtio-balloon-test$(EXESUF)
 check-qtest-s390x-y += tests/virtio-console-test$(EXESUF)
 check-qtest-s390x-y += tests/virtio-serial-test$(EXESUF)
 
+check-qtest-ppc-$(CONFIG_E500) += tests/mvme3100-test$(EXESUF)
+
 check-qtest-generic-y += tests/qom-test$(EXESUF)
 check-qtest-generic-y += tests/test-hmp$(EXESUF)
 
@@ -782,6 +784,7 @@ tests/i82801b11-test$(EXESUF): tests/i82801b11-test.o
 tests/ac97-test$(EXESUF): tests/ac97-test.o
 tests/es1370-test$(EXESUF): tests/es1370-test.o
 tests/intel-hda-test$(EXESUF): tests/intel-hda-test.o
+tests/mvme3100-test$(EXESUF): tests/mvme3100-test.o $(libqos-e500-obj-y)
 tests/ioh3420-test$(EXESUF): tests/ioh3420-test.o
 tests/usb-hcd-ohci-test$(EXESUF): tests/usb-hcd-ohci-test.o $(libqos-usb-obj-y)
 tests/usb-hcd-uhci-test$(EXESUF): tests/usb-hcd-uhci-test.o $(libqos-usb-obj-y)
diff --git a/tests/mvme3100-test.c b/tests/mvme3100-test.c
new file mode 100644
index 00..6dde8d1d29
--- /dev/null
+++ b/tests/mvme3100-test.c
@@ -0,0 +1,79 @@
+#include 
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+#include "libqos/libqos.h"
+#include "libqos/i2c.h"
+
+#define assert_equal(A, B) g_assert_cmphex((A), ==, (B))
+
+static
+I2CAdapter *i2c;
+
+static
+void test_ccsr(void)
+{
+/* CCSRBAR is self referential */
+assert_equal(readl(0xff70), 0x000ff700);
+
+/* introspect memory size */
+assert_equal(readl(0xff702080), 0x8000);
+/* value is (ram_size-1)>>24 */
+assert_equal(readl(0xff702000), 15);
+}
+
+static
+void test_cpld(void)
+{
+/* read/write to test register */
+assert_equal(readl(0xe210), 0x);
+assert_equal(readl(0xe214), 0x);
+
+writel(0xe210, 0x12345678);
+
+assert_equal(readl(0xe210), 0x12345678);
+assert_equal(readl(0xe214), 0x12345678 ^ 0x);
+}
+
+static
+void test_eeprom(void)
+{
+char buf[] = "\x00\x00MOTOROLA";
+
+/* 1. zero address pointer
+ * 2. write 8 bytes,
+ * 3. re-zero address pointer
+ */
+i2c_send(i2c, 0xa8, (uint8_t *)buf, 10);
+i2c_send(i2c, 0xa8, (uint8_t *)buf, 2);
+
+/* read 8 bytes */
+i2c_recv(i2c, 0xa8, (uint8_t *)buf, 8);
+buf[8] = '\0';
+
+/* Read header for Motorola VPD info */
+g_assert_cmpstr(buf, ==, "MOTOROLA");
+}
+
+int main(int argc, char *argv[])
+{
+int ret;
+g_test_init(&argc, &argv, NULL);
+
+qtest_start("-machine mvme3100-1152");
+
+i2c = e500_i2c_create(0xff70);
+
+qtest_add_func("/mvme3100/ccsr", test_ccsr);
+qtest_add_func("/mvme3100/cpld", test_cpld);
+qtest_add_func("/mvme3100/eeprom", test_eeprom);
+
+ret = g_test_run();
+
+printf("Tests done\n");
+
+qtest_end();
+printf("Tests end\n");
+
+return ret;
+}
-- 
2.11.0




[Qemu-devel] [PATCH 14/17] e500: split mpc8544ds specific initialization

2017-11-26 Thread Michael Davidsaver
split off the remaining board specific parts
of e500_init() as mpc85xx_init() which
will be used by the existing
mpc8544ds and generic e500 boards.

Signed-off-by: Michael Davidsaver 
---
 hw/ppc/e500.c  | 49 -
 hw/ppc/e500.h  |  3 ++-
 hw/ppc/e500plat.c  |  2 +-
 hw/ppc/mpc8544ds.c |  2 +-
 4 files changed, 36 insertions(+), 20 deletions(-)

diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index b0c8495aef..0ac7cdf6a1 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -690,7 +690,32 @@ static void ppce500_power_off(void *opaque, int line, int 
on)
 }
 }
 
-void ppce500_init(MachineState *machine, PPCE500Params *params)
+
+void ppce500_init(MachineState *machine, uint32_t decrementer_freq)
+{
+int i;
+for (i = 0; i < smp_cpus; i++) {
+PowerPCCPU *cpu;
+CPUState *cs;
+CPUPPCState *env;
+
+cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
+env = &cpu->env;
+cs = CPU(cpu);
+
+if (env->mmu_model != POWERPC_MMU_BOOKE206) {
+error_report("MMU model %i not supported by this machine.",
+ env->mmu_model);
+exit(1);
+}
+
+env->spr_cb[SPR_BOOKE_PIR].default_value = cs->cpu_index = i;
+
+ppc_booke_timers_init(cpu, decrementer_freq, PPC_TIMER_E500);
+}
+}
+
+void mpc85xx_init(MachineState *machine, PPCE500Params *params)
 {
 MemoryRegion *address_space_mem = get_system_memory();
 MemoryRegion *ram = g_new(MemoryRegion, 1);
@@ -716,31 +741,21 @@ void ppce500_init(MachineState *machine, PPCE500Params 
*params)
 CPUPPCState *firstenv = NULL;
 MemoryRegion *ccsr_addr_space;
 SysBusDevice *s;
+CPUState *cs;
 
-for (i = 0; i < smp_cpus; i++) {
+ppce500_init(machine, 4);
+
+CPU_FOREACH(cs) {
 PowerPCCPU *cpu;
-CPUState *cs;
 
-cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
+cpu = POWERPC_CPU(cs);
 env = &cpu->env;
-cs = CPU(cpu);
 
-if (env->mmu_model != POWERPC_MMU_BOOKE206) {
-fprintf(stderr, "MMU model %i not supported by this machine.\n",
-env->mmu_model);
-exit(1);
-}
 
+/* Register reset handler */
 if (!firstenv) {
 firstenv = env;
-}
 
-env->spr_cb[SPR_BOOKE_PIR].default_value = cs->cpu_index = i;
-
-ppc_booke_timers_init(cpu, 4, PPC_TIMER_E500);
-
-/* Register reset handler */
-if (!i) {
 /* Primary CPU */
 struct boot_info *boot_info;
 boot_info = g_malloc0(sizeof(struct boot_info));
diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h
index 70ba1d8f4f..350be17462 100644
--- a/hw/ppc/e500.h
+++ b/hw/ppc/e500.h
@@ -24,7 +24,8 @@ typedef struct PPCE500Params {
 hwaddr spin_base;
 } PPCE500Params;
 
-void ppce500_init(MachineState *machine, PPCE500Params *params);
+void ppce500_init(MachineState *machine, uint32_t decrementer_freq);
+void mpc85xx_init(MachineState *machine, PPCE500Params *params);
 
 hwaddr booke206_page_size_to_tlb(uint64_t size);
 
diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c
index e59e80fb9e..103efc68c2 100644
--- a/hw/ppc/e500plat.c
+++ b/hw/ppc/e500plat.c
@@ -55,7 +55,7 @@ static void e500plat_init(MachineState *machine)
 params.mpic_version = OPENPIC_MODEL_FSL_MPIC_20;
 }
 
-ppce500_init(machine, ¶ms);
+mpc85xx_init(machine, ¶ms);
 }
 
 static void e500plat_machine_init(MachineClass *mc)
diff --git a/hw/ppc/mpc8544ds.c b/hw/ppc/mpc8544ds.c
index 1717953ec7..7de4ed8ae2 100644
--- a/hw/ppc/mpc8544ds.c
+++ b/hw/ppc/mpc8544ds.c
@@ -47,7 +47,7 @@ static void mpc8544ds_init(MachineState *machine)
 exit(1);
 }
 
-ppce500_init(machine, ¶ms);
+mpc85xx_init(machine, ¶ms);
 }
 
 
-- 
2.11.0




[Qemu-devel] [PATCH 05/17] timer: generalize Dallas/Maxim RTC i2c devices

2017-11-26 Thread Michael Davidsaver
Support for: ds1307, ds1337, ds1338, ds1339,
ds1340, ds1375, ds1388, and ds3231.

Tested with ds1338 and ds1375.

Signed-off-by: Michael Davidsaver 
---
 default-configs/arm-softmmu.mak |   2 +-
 hw/timer/Makefile.objs  |   2 +-
 hw/timer/ds-rtc-i2c.c   | 461 
 hw/timer/ds1338.c   | 239 -
 4 files changed, 463 insertions(+), 241 deletions(-)
 create mode 100644 hw/timer/ds-rtc-i2c.c
 delete mode 100644 hw/timer/ds1338.c

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index d37edc4312..b857823681 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -31,7 +31,7 @@ CONFIG_SMC91C111=y
 CONFIG_ALLWINNER_EMAC=y
 CONFIG_IMX_FEC=y
 CONFIG_FTGMAC100=y
-CONFIG_DS1338=y
+CONFIG_DSRTCI2C=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_PFLASH_CFI02=y
 CONFIG_MICRODRIVE=y
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
index 8c19eac3b6..290015ebec 100644
--- a/hw/timer/Makefile.objs
+++ b/hw/timer/Makefile.objs
@@ -3,7 +3,7 @@ common-obj-$(CONFIG_ARM_MPTIMER) += arm_mptimer.o
 common-obj-$(CONFIG_ARM_V7M) += armv7m_systick.o
 common-obj-$(CONFIG_A9_GTIMER) += a9gtimer.o
 common-obj-$(CONFIG_CADENCE) += cadence_ttc.o
-common-obj-$(CONFIG_DS1338) += ds1338.o
+common-obj-$(CONFIG_DSRTCI2C) += ds-rtc-i2c.o
 common-obj-$(CONFIG_HPET) += hpet.o
 common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
 common-obj-$(CONFIG_M48T59) += m48t59.o
diff --git a/hw/timer/ds-rtc-i2c.c b/hw/timer/ds-rtc-i2c.c
new file mode 100644
index 00..ad2f8f2a68
--- /dev/null
+++ b/hw/timer/ds-rtc-i2c.c
@@ -0,0 +1,461 @@
+/* Emulation of various Dallas/Maxim RTCs accessed via I2C bus
+ *
+ * Copyright (c) 2017 Michael Davidsaver
+ * Copyright (c) 2009 CodeSourcery
+ *
+ * Authors: Michael Davidsaver
+ *  Paul Brook
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the LICENSE file in the top-level directory.
+ *
+ * Models real time read/set and NVRAM.
+ * Does not model alarms, or control/status registers.
+ *
+ * Generalized register map is:
+ *   [Current time]
+ *   [Alarm settings] (optional)
+ *   [Control/Status] (optional)
+ *   [Non-volatile memory] (optional)
+ *
+ * The current time registers are almost always the same,
+ * with the exception being that some have a CENTURY bit
+ * in the month register.
+ */
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/timer.h"
+#include "qemu/bcd.h"
+#include "hw/hw.h"
+#include "hw/registerfields.h"
+#include "hw/i2c/i2c.h"
+#include "sysemu/qtest.h"
+#include "qemu/error-report.h"
+
+/* #define DEBUG_DSRTC */
+
+#ifdef DEBUG_DSRTC
+#define DPRINTK(FMT, ...) info_report(TYPE_DSRTC " : " FMT, ## __VA_ARGS__)
+#else
+#define DPRINTK(FMT, ...) do {} while (0)
+#endif
+
+#define LOG(MSK, FMT, ...) qemu_log_mask(MSK, TYPE_DSRTC " : " FMT "\n", \
+## __VA_ARGS__)
+
+#define DSRTC_REGSIZE (0x40)
+
+/* values stored in BCD */
+/* 00-59 */
+#define R_SEC   (0x0)
+/* 00-59 */
+#define R_MIN   (0x1)
+#define R_HOUR  (0x2)
+/* 1-7 */
+#define R_WDAY  (0x3)
+/* 0-31 */
+#define R_DATE  (0x4)
+#define R_MONTH (0x5)
+/* 0-99 */
+#define R_YEAR  (0x6)
+
+/* use 12 hour mode when set */
+FIELD(HOUR, SET12, 6, 1)
+/* 00-23 */
+FIELD(HOUR, HOUR24, 0, 6)
+FIELD(HOUR, AMPM, 5, 1)
+/* 1-12 (not 0-11!) */
+FIELD(HOUR, HOUR12, 0, 5)
+
+/* 1-12 */
+FIELD(MONTH, MONTH, 0, 5)
+FIELD(MONTH, CENTURY, 7, 1)
+
+typedef struct DSRTCInfo {
+/* if bit 7 of the Month register is set after Y2K */
+bool has_century;
+/* address of first non-volatile memory cell.
+ * nv_start >= reg_end means no NV memory.
+ */
+uint8_t nv_start;
+/* total size of register range.  When address counter rolls over. */
+uint8_t reg_size;
+} DSRTCInfo;
+
+typedef struct DSRTCState {
+I2CSlave parent_obj;
+
+const DSRTCInfo *info;
+
+qemu_irq alarm_irq;
+
+/* register address counter */
+uint8_t addr;
+/* when writing, whether the address has been sent */
+bool addrd;
+
+int64_t time_offset;
+int8_t wday_offset;
+
+uint8_t regs[DSRTC_REGSIZE];
+} DSRTCState;
+
+typedef struct DSRTCClass {
+I2CSlaveClass parent_class;
+
+const DSRTCInfo *info;
+} DSRTCClass;
+
+#define TYPE_DSRTC "ds-rtc-i2c"
+#define DSRTC(obj) OBJECT_CHECK(DSRTCState, (obj), TYPE_DSRTC)
+#define DSRTC_GET_CLASS(obj) \
+OBJECT_GET_CLASS(DSRTCClass, obj, TYPE_DSRTC)
+#define DSRTC_CLASS(klass) \
+OBJECT_CLASS_CHECK(DSRTCClass, klass, TYPE_DSRTC)
+
+static const VMStateDescription vmstate_dsrtc = {
+.name = TYPE_DSRTC,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_I2C_SLAVE(parent_obj, DSRTCState),
+VMSTATE_INT64(time_offset, DSRTCState),
+VMSTATE_INT8_V(wday_offset, DSRTCState, 2),
+VMSTATE_UINT8_ARRAY(regs, DSRTCState, DSRTC_REGSIZE),
+VMSTATE_UINT8(addr, DSRTCState),
+V

[Qemu-devel] [PATCH 09/17] e500: move mpic under CCSR

2017-11-26 Thread Michael Davidsaver
Start moving code out of ppce500_init()

Existing ppce500_init_mpic() suggests that MPIC may not be created w/ KVM.
However, ppce500_init() used mpicdev unconditionally, and would
fail if the MPIC isn't created.  So require creation.

Not tested with KVM for lack of hardware.

Signed-off-by: Michael Davidsaver 
---
 hw/ppc/e500.c  | 102 +++--
 hw/ppc/e500_ccsr.c |  85 +---
 2 files changed, 84 insertions(+), 103 deletions(-)

diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index e22919f4f1..1872bb8eaa 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -29,7 +29,6 @@
 #include "sysemu/kvm.h"
 #include "kvm_ppc.h"
 #include "sysemu/device_tree.h"
-#include "hw/ppc/openpic.h"
 #include "hw/ppc/ppc.h"
 #include "hw/loader.h"
 #include "elf.h"
@@ -679,92 +678,6 @@ static void ppce500_cpu_reset(void *opaque)
 mmubooke_create_initial_mapping(env);
 }
 
-static DeviceState *ppce500_init_mpic_qemu(PPCE500Params *params,
-   qemu_irq **irqs)
-{
-DeviceState *dev;
-SysBusDevice *s;
-int i, j, k;
-
-dev = qdev_create(NULL, TYPE_OPENPIC);
-object_property_add_child(qdev_get_machine(), "pic", OBJECT(dev),
-  &error_fatal);
-qdev_prop_set_uint32(dev, "model", params->mpic_version);
-qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus);
-
-qdev_init_nofail(dev);
-s = SYS_BUS_DEVICE(dev);
-
-k = 0;
-for (i = 0; i < smp_cpus; i++) {
-for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
-sysbus_connect_irq(s, k++, irqs[i][j]);
-}
-}
-
-return dev;
-}
-
-static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params,
-  qemu_irq **irqs, Error **errp)
-{
-Error *err = NULL;
-DeviceState *dev;
-CPUState *cs;
-
-dev = qdev_create(NULL, TYPE_KVM_OPENPIC);
-qdev_prop_set_uint32(dev, "model", params->mpic_version);
-
-object_property_set_bool(OBJECT(dev), true, "realized", &err);
-if (err) {
-error_propagate(errp, err);
-object_unparent(OBJECT(dev));
-return NULL;
-}
-
-CPU_FOREACH(cs) {
-if (kvm_openpic_connect_vcpu(dev, cs)) {
-fprintf(stderr, "%s: failed to connect vcpu to irqchip\n",
-__func__);
-abort();
-}
-}
-
-return dev;
-}
-
-static DeviceState *ppce500_init_mpic(MachineState *machine,
-  PPCE500Params *params,
-  MemoryRegion *ccsr,
-  qemu_irq **irqs)
-{
-DeviceState *dev = NULL;
-SysBusDevice *s;
-
-if (kvm_enabled()) {
-Error *err = NULL;
-
-if (machine_kernel_irqchip_allowed(machine)) {
-dev = ppce500_init_mpic_kvm(params, irqs, &err);
-}
-if (machine_kernel_irqchip_required(machine) && !dev) {
-error_reportf_err(err,
-  "kernel_irqchip requested but unavailable: ");
-exit(1);
-}
-}
-
-if (!dev) {
-dev = ppce500_init_mpic_qemu(params, irqs);
-}
-
-s = SYS_BUS_DEVICE(dev);
-memory_region_add_subregion(ccsr, MPC8544_MPIC_REGS_OFFSET,
-s->mmio[0].memory);
-
-return dev;
-}
-
 static void ppce500_power_off(void *opaque, int line, int on)
 {
 if (on) {
@@ -794,18 +707,14 @@ void ppce500_init(MachineState *machine, PPCE500Params 
*params)
 /* irq num for pin INTA, INTB, INTC and INTD is 1, 2, 3 and
  * 4 respectively */
 unsigned int pci_irq_nrs[PCI_NUM_PINS] = {1, 2, 3, 4};
-qemu_irq **irqs;
 DeviceState *dev, *mpicdev;
 CPUPPCState *firstenv = NULL;
 MemoryRegion *ccsr_addr_space;
 SysBusDevice *s;
 
-irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
-irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
 for (i = 0; i < smp_cpus; i++) {
 PowerPCCPU *cpu;
 CPUState *cs;
-qemu_irq *input;
 
 cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
 env = &cpu->env;
@@ -821,13 +730,7 @@ void ppce500_init(MachineState *machine, PPCE500Params 
*params)
 firstenv = env;
 }
 
-irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB);
-input = (qemu_irq *)env->irq_inputs;
-irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
-irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
 env->spr_cb[SPR_BOOKE_PIR].default_value = cs->cpu_index = i;
-env->mpic_iack = params->ccsrbar_base +
- MPC8544_MPIC_REGS_OFFSET + 0xa0;
 
 ppc_booke_timers_init(cpu, 4, PPC_TIMER_E500);
 
@@ -857,12 +760,15 @@ void ppce500_init(MachineState *machine, PPCE500Params 
*params)
 dev = qdev_create(NULL, "e500-ccsr");
 object_property_add_child(qdev_get_machine(), "e500-ccsr",

[Qemu-devel] [PATCH 13/17] e500: move PCI host bridge into CCSR

2017-11-26 Thread Michael Davidsaver
Signed-off-by: Michael Davidsaver 
---
 hw/ppc/e500.c  | 13 -
 hw/ppc/e500_ccsr.c | 27 +++
 2 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index cfd5ed0152..b0c8495aef 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -769,6 +769,8 @@ void ppce500_init(MachineState *machine, PPCE500Params 
*params)
 qdev_prop_set_uint32(dev, "mpic-model", params->mpic_version);
 qdev_prop_set_uint32(dev, "base", params->ccsrbar_base);
 qdev_prop_set_uint32(dev, "ram-size", ram_size);
+qdev_prop_set_uint32(dev, "pci_first_slot", params->pci_first_slot);
+qdev_prop_set_uint32(dev, "pci_first_pin_irq", pci_irq_nrs[0]);
 qdev_init_nofail(dev);
 ccsr_addr_space = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
 
@@ -778,20 +780,13 @@ void ppce500_init(MachineState *machine, PPCE500Params 
*params)
 
 
 /* PCI */
-dev = qdev_create(NULL, "e500-pcihost");
-object_property_add_child(qdev_get_machine(), "pci-host", OBJECT(dev),
-  &error_abort);
-qdev_prop_set_uint32(dev, "first_slot", params->pci_first_slot);
-qdev_prop_set_uint32(dev, "first_pin_irq", pci_irq_nrs[0]);
-qdev_init_nofail(dev);
+dev = DEVICE(object_resolve_path("/machine/pci-host", 0));
+assert(dev);
 s = SYS_BUS_DEVICE(dev);
 for (i = 0; i < PCI_NUM_PINS; i++) {
 sysbus_connect_irq(s, i, qdev_get_gpio_in(mpicdev, pci_irq_nrs[i]));
 }
 
-memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET,
-sysbus_mmio_get_region(s, 0));
-
 pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
 if (!pci_bus)
 printf("couldn't create PCI controller!\n");
diff --git a/hw/ppc/e500_ccsr.c b/hw/ppc/e500_ccsr.c
index cd8216daaf..4ec8f7524d 100644
--- a/hw/ppc/e500_ccsr.c
+++ b/hw/ppc/e500_ccsr.c
@@ -50,6 +50,8 @@
 
 #define E500_DUART_OFFSET(N) (0x4500 + (N) * 0x100)
 
+#define E500_PCI_OFFSET  (0x8000ULL)
+
 #define E500_PORPLLSR(0xE)
 #define E500_PVR (0xE00A0)
 #define E500_SVR (0xE00A4)
@@ -75,6 +77,7 @@ typedef struct {
 
 DeviceState *pic;
 DeviceState *i2c;
+DeviceState *pcihost;
 } CCSRState;
 
 #define TYPE_E500_CCSR "e500-ccsr"
@@ -201,6 +204,7 @@ static void e500_ccsr_init(Object *obj)
 DeviceState *dev = DEVICE(obj);
 CCSRState *ccsr = E500_CCSR(dev);
 
+/* prepare MPIC */
 assert(current_machine);
 if (kvm_enabled()) {
 
@@ -228,6 +232,18 @@ static void e500_ccsr_init(Object *obj)
 object_property_add_alias(obj, "mpic-model",
   OBJECT(ccsr->pic), "model",
   &error_fatal);
+
+/* prepare PCI host bridge */
+ccsr->pcihost = qdev_create(NULL, "e500-pcihost");
+object_property_add_child(qdev_get_machine(), "pci-host", 
OBJECT(ccsr->pcihost),
+  &error_abort);
+
+object_property_add_alias(obj, "pci_first_slot",
+  OBJECT(ccsr->pcihost), "first_slot",
+  &error_fatal);
+object_property_add_alias(obj, "pci_first_pin_irq",
+  OBJECT(ccsr->pcihost), "first_pin_irq",
+  &error_fatal);
 }
 
 static void e500_ccsr_realize(DeviceState *dev, Error **errp)
@@ -240,6 +256,7 @@ static void e500_ccsr_realize(DeviceState *dev, Error 
**errp)
   ccsr, "e500-ccsr", 1024 * 1024);
 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &ccsr->iomem);
 
+/* realize MPIC */
 qdev_init_nofail(ccsr->pic);
 pic = SYS_BUS_DEVICE(ccsr->pic);
 
@@ -275,6 +292,13 @@ static void e500_ccsr_realize(DeviceState *dev, Error 
**errp)
 sysbus_mmio_get_region(pic, 0));
 /* Note: MPIC internal interrupts are offset by 16 */
 
+/* realize PCI host bridge*/
+qdev_init_nofail(ccsr->pcihost);
+
+memory_region_add_subregion(&ccsr->iomem, E500_PCI_OFFSET,
+sysbus_mmio_get_region(
+SYS_BUS_DEVICE(ccsr->pcihost), 0));
+
 /* attach I2C controller */
 ccsr->i2c = qdev_create(NULL, "mpc8540-i2c");
 object_property_add_child(qdev_get_machine(), "i2c[*]",
@@ -314,6 +338,9 @@ static Property e500_ccsr_props[] = {
 DEFINE_PROP_UINT32("porpllsr", CCSRState, porpllsr, 0),
 DEFINE_PROP_UINT32("ccb-freq", CCSRState, ccb_freq, 3u),
 /* "mpic-model" aliased from MPIC */
+/* "pci_first_slot"
+ * "pci_first_pin_irq" aliased from PCI host bridge
+ */
 DEFINE_PROP_END_OF_LIST()
 };
 
-- 
2.11.0




[Qemu-devel] [PATCH 07/17] e500: fix pci host bridge class/type

2017-11-26 Thread Michael Davidsaver
Correct some confusion wrt. the PCI facing
side of the PCI host bridge (not PCIe root complex).
The ref. manual for the mpc8533 (as well as
mpc8540 and mpc8540) give the class code as
PCI_CLASS_PROCESSOR_POWERPC.
While the PCI_HEADER_TYPE field is oddly omitted,
the tables in the "PCI Configuration Header"
section shows a type 0 layout using all 6 BAR
registers (as 2x 32, and 2x 64 bit regions)

So 997505065dc92e533debf5cb23012ba4e673d387
seems to be in error.  Although there was
perhaps some confusion as the mpc8533
has a separate PCIe root complex.
With PCIe, a root complex has PCI_HEADER_TYPE=1.

Neither the PCI host bridge, nor the PCIe
root complex advertise class PCI_CLASS_BRIDGE_PCI.

This was confusing Linux guests, which try
to interpret the host bridge as a pci-pci
bridge, but get confused and re-enumerate
the bus when the primary/secondary/subordinate
bus registers don't have valid values.

Signed-off-by: Michael Davidsaver 
---
 hw/pci-host/ppce500.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c
index f2d108bc8a..8073d396ff 100644
--- a/hw/pci-host/ppce500.c
+++ b/hw/pci-host/ppce500.c
@@ -423,11 +423,6 @@ static void e500_pcihost_bridge_realize(PCIDevice *d, 
Error **errp)
   "/e500-ccsr"));
 MemoryRegion *ccsr_mr = sysbus_mmio_get_region(ccsr, 0);
 
-pci_config_set_class(d->config, PCI_CLASS_BRIDGE_PCI);
-d->config[PCI_HEADER_TYPE] =
-(d->config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MULTI_FUNCTION) |
-PCI_HEADER_TYPE_BRIDGE;
-
 memory_region_init_alias(&b->bar0, OBJECT(ccsr), "e500-pci-bar0", ccsr_mr,
  0, memory_region_size(ccsr_mr));
 pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &b->bar0);
-- 
2.11.0




[Qemu-devel] [PATCH 08/17] e500: additional CCSR registers

2017-11-26 Thread Michael Davidsaver
Add CCSRBAR to allow CCSR region to be relocated.

Guest memory size introspection via RAM config
registers.

Dummy RAM error controls.

Clock introspection via Power on Reset PLL
Status Register.

Signed-off-by: Michael Davidsaver 

ccsrbase also update iack
---
 hw/ppc/e500.c  |  5 ++-
 hw/ppc/e500_ccsr.c | 93 --
 2 files changed, 95 insertions(+), 3 deletions(-)

diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index b90f4231a6..e22919f4f1 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -51,7 +51,9 @@
 
 #define RAM_SIZES_ALIGN(64UL << 20)
 
-/* TODO: parameterize */
+/* TODO: parameterize
+ * Some CCSR offsets duplicated in e500_ccsr.c
+ */
 #define MPC8544_CCSRBAR_SIZE   0x0010ULL
 #define MPC8544_MPIC_REGS_OFFSET   0x4ULL
 #define MPC8544_MSI_REGS_OFFSET   0x41600ULL
@@ -856,6 +858,7 @@ void ppce500_init(MachineState *machine, PPCE500Params 
*params)
 object_property_add_child(qdev_get_machine(), "e500-ccsr",
   OBJECT(dev), NULL);
 qdev_prop_set_uint32(dev, "base", params->ccsrbar_base);
+qdev_prop_set_uint32(dev, "ram-size", ram_size);
 qdev_init_nofail(dev);
 ccsr_addr_space = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
 
diff --git a/hw/ppc/e500_ccsr.c b/hw/ppc/e500_ccsr.c
index 1b586c3f42..9400d7cf13 100644
--- a/hw/ppc/e500_ccsr.c
+++ b/hw/ppc/e500_ccsr.c
@@ -30,13 +30,26 @@
 #include "hw/sysbus.h"
 
 /* E500_ denotes registers common to all */
+/* Some CCSR offsets duplicated in e500.c */
 
+#define E500_CCSRBAR (0)
+
+#define E500_CS0_BNDS(0x2000)
+
+#define E500_CS0_CONFIG  (0x2080)
+
+#define E500_ERR_DETECT  (0x2e40)
+#define E500_ERR_DISABLE (0x2e44)
+
+#define E500_PORPLLSR(0xE)
 #define E500_PVR (0xE00A0)
 #define E500_SVR (0xE00A4)
 
 #define MPC8544_RSTCR   (0xE00B0)
 #define MPC8544_RSTCR_RESET  (0x02)
 
+#define E500_MPIC_OFFSET   (0x4ULL)
+
 typedef struct {
 /*< private >*/
 SysBusDevice parent_obj;
@@ -44,19 +57,59 @@ typedef struct {
 
 MemoryRegion iomem;
 
-uint32_t defbase;
+uint32_t defbase, base;
+uint32_t ram_size;
+uint32_t merrd;
+
+uint32_t porpllsr;
+
+DeviceState *pic;
 } CCSRState;
 
 #define TYPE_E500_CCSR "e500-ccsr"
 #define E500_CCSR(obj) OBJECT_CHECK(CCSRState, (obj), TYPE_E500_CCSR)
 
+/* call after changing CCSRState::base */
+static void e500_ccsr_post_move(CCSRState *ccsr)
+{
+CPUState *cs;
+
+CPU_FOREACH(cs) {
+PowerPCCPU *cpu = POWERPC_CPU(cs);
+CPUPPCState *env = &cpu->env;
+
+env->mpic_iack = ccsr->base +
+ E500_MPIC_OFFSET + 0xa0;
+}
+
+sysbus_mmio_map(SYS_BUS_DEVICE(ccsr), 0, ccsr->base);
+}
+
 static uint64_t e500_ccsr_read(void *opaque, hwaddr addr,
   unsigned size)
 {
+CCSRState *ccsr = opaque;
 PowerPCCPU *cpu = POWERPC_CPU(current_cpu);
 CPUPPCState *env = &cpu->env;
 
 switch (addr) {
+case E500_CCSRBAR:
+return ccsr->base >> 12;
+case E500_CS0_BNDS:
+/* we model all RAM in a single chip with addresses [0, ram_size) */
+return (ccsr->ram_size - 1) >> 24;
+case E500_CS0_CONFIG:
+return 1 << 31;
+case E500_ERR_DETECT:
+return 0; /* (errors not modeled) */
+case E500_ERR_DISABLE:
+return ccsr->merrd;
+case E500_PORPLLSR:
+if (!ccsr->porpllsr) {
+qemu_log_mask(LOG_UNIMP,
+  "Machine does not provide valid PORPLLSR\n");
+}
+return ccsr->porpllsr;
 case E500_PVR:
 return env->spr[SPR_PVR];
 case E500_SVR:
@@ -72,10 +125,22 @@ static uint64_t e500_ccsr_read(void *opaque, hwaddr addr,
 static void e500_ccsr_write(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
 {
+CCSRState *ccsr = opaque;
 PowerPCCPU *cpu = POWERPC_CPU(current_cpu);
 CPUPPCState *env = &cpu->env;
 uint32_t svr = env->spr[SPR_E500_SVR] >> 16;
 
+switch (addr) {
+case E500_CCSRBAR:
+value &= 0x000fff00;
+ccsr->base = value << 12;
+e500_ccsr_post_move(ccsr);
+return;
+case E500_ERR_DISABLE:
+ccsr->merrd = value & 0xd;
+return;
+}
+
 switch (svr) {
 case 0: /* generic.  assumed to be mpc8544ds or e500plat board */
 case 0x8034: /* mpc8544 */
@@ -104,11 +169,20 @@ static const MemoryRegionOps e500_ccsr_ops = {
 }
 };
 
+static int e500_ccsr_post_load(void *opaque, int version_id)
+{
+CCSRState *ccsr = opaque;
+
+e500_ccsr_post_move(ccsr);
+return 0;
+}
+
 static void e500_ccsr_reset(DeviceState *dev)
 {
 CCSRState *ccsr = E500_CCSR(dev);
 
-sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, ccsr->defbase);
+ccsr->base = ccsr->defbase;
+e500_ccsr_post_move(ccsr);
 }
 
 static void e500_ccsr_initfn(Object *obj)
@@ -123,15 +197,30 @@ static void e500_ccsr_initfn(Object *obj)
 
 stat

[Qemu-devel] [PATCH 03/17] i2c: add mpc8540 i2c controller

2017-11-26 Thread Michael Davidsaver
Signed-off-by: Michael Davidsaver 
---
 hw/i2c/Makefile.objs |   1 +
 hw/i2c/mpc8540_i2c.c | 307 +++
 hw/i2c/trace-events  |   6 +
 3 files changed, 314 insertions(+)
 create mode 100644 hw/i2c/mpc8540_i2c.c

diff --git a/hw/i2c/Makefile.objs b/hw/i2c/Makefile.objs
index 0594dea3ae..79af1dd901 100644
--- a/hw/i2c/Makefile.objs
+++ b/hw/i2c/Makefile.objs
@@ -9,3 +9,4 @@ common-obj-$(CONFIG_IMX_I2C) += imx_i2c.o
 common-obj-$(CONFIG_ASPEED_SOC) += aspeed_i2c.o
 obj-$(CONFIG_OMAP) += omap_i2c.o
 obj-$(CONFIG_PPC4XX) += ppc4xx_i2c.o
+obj-$(CONFIG_E500) += mpc8540_i2c.o
diff --git a/hw/i2c/mpc8540_i2c.c b/hw/i2c/mpc8540_i2c.c
new file mode 100644
index 00..b9f5773b35
--- /dev/null
+++ b/hw/i2c/mpc8540_i2c.c
@@ -0,0 +1,307 @@
+/*
+ * MPC8540 I2C bus interface
+ * As described in
+ * MPC8540 PowerQUICC III Integrated Host Processor Reference Manual, Rev. 1
+ * Part 2 chapter 11
+ *
+ * Compatible I2C controllers are found on other Freescale chips
+ * including mpc8544 and P2010.
+ *
+ * Copyright (c) 2015 Michael Davidsaver
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the LICENSE file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "hw/hw.h"
+#include "hw/registerfields.h"
+#include "hw/i2c/i2c.h"
+#include "hw/sysbus.h"
+#include "qemu/error-report.h"
+
+#include "trace.h"
+
+/* #define DEBUG_LVL 0 */
+
+#ifdef DEBUG_LVL
+#define DPRINTK(LVL, FMT, ...) do { \
+if ((LVL) <= DEBUG_LVL) {\
+info_report(TYPE_MPC8540_I2C " : " FMT, ## __VA_ARGS__); \
+} } while (0)
+#else
+#define DPRINTK(LVL, FMT, ...) do {} while (0)
+#endif
+
+#define LOG(MSK, FMT, ...) qemu_log_mask(MSK, TYPE_MPC8540_I2C \
+" : " FMT "\n", ## __VA_ARGS__)
+
+#define TYPE_MPC8540_I2C "mpc8540-i2c"
+#define MPC8540_I2C(obj) OBJECT_CHECK(MPC8540I2CState, (obj), TYPE_MPC8540_I2C)
+
+/* offsets relative to CCSR offset 0x3000 */
+#define R_I2CADR (0)
+#define R_I2CFDR (4)
+#define R_I2CCR  (8)
+#define R_I2CSR  (0xc)
+#define R_I2CDR  (0x10)
+#define R_I2CDFSRR (0x14)
+
+FIELD(I2CCR, MEN, 7, 1)
+FIELD(I2CCR, MIEN, 6, 1)
+FIELD(I2CCR, MSTA, 5, 1)
+FIELD(I2CCR, MTX, 4, 1)
+FIELD(I2CCR, TXAK, 3, 1)
+FIELD(I2CCR, RSTA, 2, 1)
+FIELD(I2CCR, BCST, 0, 1)
+
+FIELD(I2CSR, MCF, 7, 1)
+FIELD(I2CSR, MAAS, 6, 1)
+FIELD(I2CSR, MBB, 5, 1)
+FIELD(I2CSR, MAL, 4, 1)
+FIELD(I2CSR, BCSTM, 3, 1)
+FIELD(I2CSR, SRW, 2, 1)
+FIELD(I2CSR, MIF, 1, 1)
+FIELD(I2CSR, RXAK, 0, 1)
+
+typedef struct MPC8540I2CState {
+SysBusDevice parent_obj;
+
+I2CBus *bus;
+
+uint8_t ctrl, sts;
+uint8_t freq, filt;
+/* Reads are pipelined, this is the next data value */
+uint8_t dbuf, dbuf_valid;
+
+qemu_irq irq;
+
+MemoryRegion mmio;
+} MPC8540I2CState;
+
+#define I2CCR(BIT) FIELD_EX32(i2c->ctrl, I2CCR, BIT)
+#define I2CSR(BIT) FIELD_EX32(i2c->sts, I2CSR, BIT)
+
+#define I2CSR_SET(BIT, VAL) do {\
+i2c->sts = FIELD_DP32(i2c->sts, I2CSR, BIT, VAL);\
+} while (0)
+
+static
+void mpc8540_update_irq(MPC8540I2CState *i2c)
+{
+int ena = i2c->ctrl & 0x40,
+sts = i2c->sts & 0x02,
+act = !!(ena && sts);
+
+DPRINTK(1, "IRQ %c ena %c sts %c",
+act ? 'X' : '_',
+ena ? 'X' : '_',
+sts ? 'X' : '_');
+
+qemu_set_irq(i2c->irq, act);
+}
+
+static
+uint64_t mpc8540_i2c_read(void *opaque, hwaddr addr, unsigned size)
+{
+MPC8540I2CState *i2c = opaque;
+uint32_t val;
+
+switch (addr) {
+case R_I2CADR: /* ADDR */
+val = 0;
+break;
+case R_I2CFDR: /* Freq Div. */
+val = i2c->freq;
+break;
+case R_I2CCR: /* CONTROL */
+val = i2c->ctrl & ~0x06;
+break;
+case R_I2CSR: /* STATUS */
+val = i2c->sts;
+break;
+case R_I2CDR: /* DATA */
+/* Reads are "pipelined" and so return the previous value of the
+ * register
+ */
+val = i2c->dbuf;
+if (I2CCR(MEN) && I2CSR(MBB)) { /* enabled and busy */
+if (!i2c_bus_busy(i2c->bus) || I2CCR(MTX)) {
+if (!i2c->dbuf_valid) {
+LOG(LOG_GUEST_ERROR, "Read during addr or tx");
+}
+i2c->dbuf = 0xff;
+i2c->dbuf_valid = false;
+} else {
+int ret = i2c_recv(i2c->bus);
+i2c->dbuf = (uint8_t)ret;
+i2c->dbuf_valid = true;
+trace_mpc8540_i2c_read(i2c->dbuf);
+I2CSR_SET(MIF, 1);
+I2CSR_SET(RXAK, 0);
+mpc8540_update_irq(i2c);
+}
+} else {
+i2c->dbuf = 0xff;
+i2c->dbuf_valid = false;
+LOG(LOG_GUEST_ERROR, "Read when not enabled or busy");
+}
+break;
+case R_I2CDFSRR: /* FILTER */
+val = i2c->filt;
+break;
+default:
+val = 0xff;
+}
+
+DPRINTK(addr == 0xc ? 2 : 1, " read %08x -> %08x",
+   

[Qemu-devel] [PATCH 06/17] tests: rewrite testing for DS RTC devices

2017-11-26 Thread Michael Davidsaver
Replace existing ds1338-test with more thorough
test of time read and set.

Signed-off-by: Michael Davidsaver 
---
 tests/Makefile.include  |   4 +-
 tests/ds-rtc-i2c-test.c | 162 
 tests/ds1338-test.c |  77 ---
 3 files changed, 164 insertions(+), 79 deletions(-)
 create mode 100644 tests/ds-rtc-i2c-test.c
 delete mode 100644 tests/ds1338-test.c

diff --git a/tests/Makefile.include b/tests/Makefile.include
index ad1c219423..56045cdf09 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -348,7 +348,7 @@ check-qtest-sparc64-y = tests/endianness-test$(EXESUF)
 check-qtest-sparc64-y += tests/prom-env-test$(EXESUF)
 
 check-qtest-arm-y = tests/tmp105-test$(EXESUF)
-check-qtest-arm-y += tests/ds1338-test$(EXESUF)
+check-qtest-arm-y += tests/ds-rtc-i2c-test$(EXESUF)
 check-qtest-arm-y += tests/m25p80-test$(EXESUF)
 gcov-files-arm-y += hw/misc/tmp105.c
 check-qtest-arm-y += tests/virtio-blk-test$(EXESUF)
@@ -745,7 +745,7 @@ tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o \
tests/boot-sector.o tests/acpi-utils.o $(libqos-obj-y)
 tests/pxe-test$(EXESUF): tests/pxe-test.o tests/boot-sector.o $(libqos-obj-y)
 tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
-tests/ds1338-test$(EXESUF): tests/ds1338-test.o $(libqos-imx-obj-y)
+tests/ds-rtc-i2c-test$(EXESUF): tests/ds-rtc-i2c-test.o $(libqos-imx-obj-y)
 tests/m25p80-test$(EXESUF): tests/m25p80-test.o
 tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
 tests/q35-test$(EXESUF): tests/q35-test.o $(libqos-pc-obj-y)
diff --git a/tests/ds-rtc-i2c-test.c b/tests/ds-rtc-i2c-test.c
new file mode 100644
index 00..0586dbd467
--- /dev/null
+++ b/tests/ds-rtc-i2c-test.c
@@ -0,0 +1,162 @@
+/* Testing of Dallas/Maxim I2C bus RTC devices
+ *
+ * Copyright (c) 2017 Michael Davidsaver
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the LICENSE file in the top-level directory.
+ */
+#include 
+
+#include "qemu/osdep.h"
+#include "qemu/bcd.h"
+#include "qemu/cutils.h"
+#include "qemu/timer.h"
+#include "libqtest.h"
+#include "libqos/libqos.h"
+#include "libqos/i2c.h"
+
+#define IMX25_I2C_0_BASE 0x43F8
+#define DS1338_ADDR 0x68
+
+static I2CAdapter *i2c;
+static uint8_t addr;
+static bool use_century;
+
+static
+time_t rtc_gettime(void)
+{
+struct tm parts;
+uint8_t buf[7];
+
+buf[0] = 0;
+i2c_send(i2c, addr, buf, 1);
+i2c_recv(i2c, addr, buf, 7);
+
+parts.tm_sec = from_bcd(buf[0]);
+parts.tm_min = from_bcd(buf[1]);
+if (buf[2] & 0x40) {
+/* 12 hour */
+parts.tm_hour = from_bcd(buf[2] & 0x1f) % 12u;
+if (buf[2] & 0x20) {
+parts.tm_hour += 12u;
+}
+} else {
+/* 24 hour */
+parts.tm_hour = from_bcd(buf[2] & 0x3f);
+}
+parts.tm_wday = from_bcd(buf[3]);
+parts.tm_mday = from_bcd(buf[4]);
+parts.tm_mon =  from_bcd((buf[5] & 0x1f) - 1u);
+parts.tm_year = from_bcd(buf[6]);
+if (!use_century || (buf[5] & 0x80)) {
+parts.tm_year += 100u;
+}
+
+return mktimegm(&parts);
+}
+
+/* read back and compare with current system time */
+static
+void test_rtc_current(void)
+{
+uint8_t buf;
+time_t expected, actual;
+
+/* magic address to zero RTC time offset
+ * as tests may be run in any order
+ */
+buf = 0xff;
+i2c_send(i2c, addr, &buf, 1);
+
+actual = time(NULL);
+/* new second may start here */
+expected = rtc_gettime();
+g_assert_cmpuint(expected, <=, actual + 1);
+g_assert_cmpuint(expected, >=, actual);
+}
+
+
+static uint8_t test_time_24[8] = {
+0, /* address */
+/* Wed, 22 Nov 2017 18:30:53 + */
+0x53,
+0x30,
+0x18, /* 6 PM in 24 hour mode */
+0x03, /* monday is our day 1 */
+0x22,
+0x11 | 0x80,
+0x17,
+};
+
+static uint8_t test_time_12[8] = {
+0, /* address */
+/* Wed, 22 Nov 2017 18:30:53 + */
+0x53,
+0x30,
+0x67, /* 6 PM in 12 hour mode */
+0x03, /* monday is our day 1 */
+0x22,
+0x11 | 0x80,
+0x17,
+};
+
+/* write in and read back known time */
+static
+void test_rtc_set(const void *raw)
+{
+const uint8_t *testtime = raw;
+uint8_t buf[7];
+unsigned retry = 2;
+
+for (; retry; retry--) {
+i2c_send(i2c, addr, testtime, 8);
+/* new second may start here */
+i2c_send(i2c, addr, testtime, 1);
+i2c_recv(i2c, addr, buf, 7);
+
+if (testtime[1] == buf[0]) {
+break;
+}
+/* we raced start of second, retry */
+};
+
+g_assert_cmpuint(testtime[1], ==, buf[0]);
+g_assert_cmpuint(testtime[2], ==, buf[1]);
+g_assert_cmpuint(testtime[3], ==, buf[2]);
+g_assert_cmpuint(testtime[4], ==, buf[3]);
+g_assert_cmpuint(testtime[5], ==, buf[4]);
+if (use_century) {
+g_assert_cmpuint(testtime[6], ==, buf[5]);
+} else {
+g_assert_cmpuint(testtime[6] & 

[Qemu-devel] [PATCH 11/17] e500: derive baud from CCB clock

2017-11-26 Thread Michael Davidsaver
The CCB (Complex Core Bus) clock is the reference for the DUARTs
with an extra divide by 16.

>From the mpc8540, mpc8544, and P2010 ref manuals.
CCB=333MHz, with divider=0x87a gives ~9600 baud.
333e6 Hz/(16*0x87a) = 9591 Hz.
This is verified with a real mpc8540.

The existing value for the mpc8544ds boards is replaced.
Previously the uart "clock-frequency" device tree node
was left as zero, and at some point either u-boot or Linux
picks a value inconsistent with the frequency
given to serial_mm_init().
The FIFO timeout calculated from this was incorrect.

Now use an arbitrary (valid) CCB frequency of 333MHz
in the device tree and for the UART.

Signed-off-by: Michael Davidsaver 
---
 hw/ppc/e500.c  |  9 -
 hw/ppc/e500_ccsr.c | 16 
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 2d87d91582..cfd5ed0152 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -49,6 +49,12 @@
 
 #define RAM_SIZES_ALIGN(64UL << 20)
 
+/* Somewhat arbitrarily choosen Complex Core Bus frequency
+ * for our simulation (real freq of mpc8544ds board unknown)
+ * Used in baud rate calculations.
+ */
+#define CCB_FREQ (3)
+
 /* TODO: parameterize
  * Some CCSR offsets duplicated in e500_ccsr.c
  */
@@ -113,7 +119,7 @@ static void dt_serial_create(void *fdt, unsigned long long 
offset,
 qemu_fdt_setprop_string(fdt, ser, "compatible", "ns16550");
 qemu_fdt_setprop_cells(fdt, ser, "reg", offset, 0x100);
 qemu_fdt_setprop_cell(fdt, ser, "cell-index", idx);
-qemu_fdt_setprop_cell(fdt, ser, "clock-frequency", 0);
+qemu_fdt_setprop_cell(fdt, ser, "clock-frequency", CCB_FREQ);
 qemu_fdt_setprop_cells(fdt, ser, "interrupts", 42, 2);
 qemu_fdt_setprop_phandle(fdt, ser, "interrupt-parent", mpic);
 qemu_fdt_setprop_string(fdt, "/aliases", alias, ser);
@@ -759,6 +765,7 @@ void ppce500_init(MachineState *machine, PPCE500Params 
*params)
 dev = qdev_create(NULL, "e500-ccsr");
 object_property_add_child(qdev_get_machine(), "e500-ccsr",
   OBJECT(dev), NULL);
+qdev_prop_set_uint32(dev, "ccb-freq", CCB_FREQ);
 qdev_prop_set_uint32(dev, "mpic-model", params->mpic_version);
 qdev_prop_set_uint32(dev, "base", params->ccsrbar_base);
 qdev_prop_set_uint32(dev, "ram-size", ram_size);
diff --git a/hw/ppc/e500_ccsr.c b/hw/ppc/e500_ccsr.c
index f1adba4e54..c479ed91ee 100644
--- a/hw/ppc/e500_ccsr.c
+++ b/hw/ppc/e500_ccsr.c
@@ -69,6 +69,7 @@ typedef struct {
 uint32_t merrd;
 
 uint32_t porpllsr;
+uint32_t ccb_freq;
 
 DeviceState *pic;
 } CCSRState;
@@ -272,15 +273,21 @@ static void e500_ccsr_realize(DeviceState *dev, Error 
**errp)
 /* Note: MPIC internal interrupts are offset by 16 */
 
 /* DUARTS */
+/* for mpc8540, mpc8544, and P2010 (unmodeled), the DUART reference clock
+ * is the CCB clock divided by 16.
+ * So baud rate is CCB/(16*divider)
+ */
 if (serial_hds[0]) {
-serial_mm_init(&ccsr->iomem, E500_DUART_OFFSET(0),
-   0, qdev_get_gpio_in(ccsr->pic, 16 + 26), 399193,
+serial_mm_init(&ccsr->iomem, E500_DUART_OFFSET(0), 0,
+   qdev_get_gpio_in(ccsr->pic, 16 + 26),
+   ccsr->ccb_freq / 16u,
serial_hds[0], DEVICE_BIG_ENDIAN);
 }
 
 if (serial_hds[1]) {
-serial_mm_init(&ccsr->iomem, E500_DUART_OFFSET(1),
-   0, qdev_get_gpio_in(ccsr->pic, 16 + 26), 399193,
+serial_mm_init(&ccsr->iomem, E500_DUART_OFFSET(1), 0,
+   qdev_get_gpio_in(ccsr->pic, 16 + 26),
+   ccsr->ccb_freq / 16u,
serial_hds[1], DEVICE_BIG_ENDIAN);
 }
 
@@ -290,6 +297,7 @@ static Property e500_ccsr_props[] = {
 DEFINE_PROP_UINT32("base", CCSRState, defbase, 0xff70),
 DEFINE_PROP_UINT32("ram-size", CCSRState, ram_size, 0),
 DEFINE_PROP_UINT32("porpllsr", CCSRState, porpllsr, 0),
+DEFINE_PROP_UINT32("ccb-freq", CCSRState, ccb_freq, 3u),
 /* "mpic-model" aliased from MPIC */
 DEFINE_PROP_END_OF_LIST()
 };
-- 
2.11.0




[Qemu-devel] [PATCH 01/17] openpic: debug w/ info_report()

2017-11-26 Thread Michael Davidsaver
Replace *printf() with *_report().
Remove trailing new lines.

Signed-off-by: Michael Davidsaver 
---
 hw/intc/openpic.c | 102 +++---
 1 file changed, 51 insertions(+), 51 deletions(-)

diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c
index 10d6e871fb..9159a06f07 100644
--- a/hw/intc/openpic.c
+++ b/hw/intc/openpic.c
@@ -46,6 +46,7 @@
 #include "qapi/qmp/qerror.h"
 #include "qemu/log.h"
 #include "qemu/timer.h"
+#include "qemu/error-report.h"
 
 //#define DEBUG_OPENPIC
 
@@ -58,8 +59,7 @@ static const int debug_openpic = 0;
 static int get_current_cpu(void);
 #define DPRINTF(fmt, ...) do { \
 if (debug_openpic) { \
-printf("Core%d: ", get_current_cpu()); \
-printf(fmt , ## __VA_ARGS__); \
+info_report("Core%d: " fmt, get_current_cpu(), ## __VA_ARGS__); \
 } \
 } while (0)
 
@@ -173,7 +173,7 @@ static int inttgt_to_output(int inttgt)
 }
 }
 
-fprintf(stderr, "%s: unsupported inttgt %d\n", __func__, inttgt);
+error_report("%s: unsupported inttgt %d", __func__, inttgt);
 return OPENPIC_OUTPUT_INT;
 }
 
@@ -372,7 +372,7 @@ static void IRQ_check(OpenPICState *opp, IRQQueue *q)
 break;
 }
 
-DPRINTF("IRQ_check: irq %d set ivpr_pr=%d pr=%d\n",
+DPRINTF("IRQ_check: irq %d set ivpr_pr=%d pr=%d",
 irq, IVPR_PRIORITY(opp->src[irq].ivpr), priority);
 
 if (IVPR_PRIORITY(opp->src[irq].ivpr) > priority) {
@@ -403,11 +403,11 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, 
int n_IRQ,
 dst = &opp->dst[n_CPU];
 src = &opp->src[n_IRQ];
 
-DPRINTF("%s: IRQ %d active %d was %d\n",
+DPRINTF("%s: IRQ %d active %d was %d",
 __func__, n_IRQ, active, was_active);
 
 if (src->output != OPENPIC_OUTPUT_INT) {
-DPRINTF("%s: output %d irq %d active %d was %d count %d\n",
+DPRINTF("%s: output %d irq %d active %d was %d count %d",
 __func__, src->output, n_IRQ, active, was_active,
 dst->outputs_active[src->output]);
 
@@ -417,13 +417,13 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, 
int n_IRQ,
  */
 if (active) {
 if (!was_active && dst->outputs_active[src->output]++ == 0) {
-DPRINTF("%s: Raise OpenPIC output %d cpu %d irq %d\n",
+DPRINTF("%s: Raise OpenPIC output %d cpu %d irq %d",
 __func__, src->output, n_CPU, n_IRQ);
 qemu_irq_raise(dst->irqs[src->output]);
 }
 } else {
 if (was_active && --dst->outputs_active[src->output] == 0) {
-DPRINTF("%s: Lower OpenPIC output %d cpu %d irq %d\n",
+DPRINTF("%s: Lower OpenPIC output %d cpu %d irq %d",
 __func__, src->output, n_CPU, n_IRQ);
 qemu_irq_lower(dst->irqs[src->output]);
 }
@@ -446,7 +446,7 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, 
int n_IRQ,
 IRQ_check(opp, &dst->raised);
 
 if (active && priority <= dst->ctpr) {
-DPRINTF("%s: IRQ %d priority %d too low for ctpr %d on CPU %d\n",
+DPRINTF("%s: IRQ %d priority %d too low for ctpr %d on CPU %d",
 __func__, n_IRQ, priority, dst->ctpr, n_CPU);
 active = 0;
 }
@@ -454,10 +454,10 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, 
int n_IRQ,
 if (active) {
 if (IRQ_get_next(opp, &dst->servicing) >= 0 &&
 priority <= dst->servicing.priority) {
-DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
+DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d",
 __func__, n_IRQ, dst->servicing.next, n_CPU);
 } else {
-DPRINTF("%s: Raise OpenPIC INT output cpu %d irq %d/%d\n",
+DPRINTF("%s: Raise OpenPIC INT output cpu %d irq %d/%d",
 __func__, n_CPU, n_IRQ, dst->raised.next);
 qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
 }
@@ -465,12 +465,12 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, 
int n_IRQ,
 IRQ_get_next(opp, &dst->servicing);
 if (dst->raised.priority > dst->ctpr &&
 dst->raised.priority > dst->servicing.priority) {
-DPRINTF("%s: IRQ %d inactive, IRQ %d prio %d above %d/%d, CPU 
%d\n",
+DPRINTF("%s: IRQ %d inactive, IRQ %d prio %d above %d/%d, CPU %d",
 __func__, n_IRQ, dst->raised.next, dst->raised.priority,
 dst->ctpr, dst->servicing.priority, n_CPU);
 /* IRQ line stays asserted */
 } else {
-DPRINTF("%s: IRQ %d inactive, current prio %d/%d, CPU %d\n",
+DPRINTF("%s: IRQ %d inactive, current prio %d/%d, CPU %d",
 __func__, n_IRQ, dst->ctpr, dst->servicing.priority, 
n_CPU);
 qemu_irq_lower(opp->dst[n_CPU].irq

[Qemu-devel] [PATCH 04/17] qtest: add e500_i2c_create()

2017-11-26 Thread Michael Davidsaver
Add interface for testing i2c devices
with PPC e500.

Signed-off-by: Michael Davidsaver 
---
 tests/Makefile.include  |  1 +
 tests/libqos/i2c-e500.c | 66 +
 tests/libqos/i2c.h  |  3 +++
 3 files changed, 70 insertions(+)
 create mode 100644 tests/libqos/i2c-e500.c

diff --git a/tests/Makefile.include b/tests/Makefile.include
index c002352134..ad1c219423 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -721,6 +721,7 @@ libqos-pc-obj-y += tests/libqos/malloc-pc.o 
tests/libqos/libqos-pc.o
 libqos-pc-obj-y += tests/libqos/ahci.o
 libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o
 libqos-imx-obj-y = $(libqos-obj-y) tests/libqos/i2c-imx.o
+libqos-e500-obj-y = $(libqos-obj-y) tests/libqos/i2c-e500.o
 libqos-usb-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/libqos/usb.o
 libqos-virtio-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) 
tests/libqos/virtio.o tests/libqos/virtio-pci.o tests/libqos/virtio-mmio.o 
tests/libqos/malloc-generic.o
 
diff --git a/tests/libqos/i2c-e500.c b/tests/libqos/i2c-e500.c
new file mode 100644
index 00..4272ada0a5
--- /dev/null
+++ b/tests/libqos/i2c-e500.c
@@ -0,0 +1,66 @@
+/*
+ * QTest I2C driver
+ *
+ * Copyright (c) 2016 Michael Davidsaver
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "libqos/i2c.h"
+
+
+#include "qemu/bswap.h"
+#include "libqtest.h"
+
+typedef struct E500I2C {
+I2CAdapter parent;
+
+uint64_t addr;
+} E500I2C;
+
+static void e500_i2c_send(I2CAdapter *i2c, uint8_t addr,
+  const uint8_t *buf, uint16_t len)
+{
+E500I2C *s = (E500I2C *)i2c;
+
+writeb(s->addr + 0x8, 0xb0); /* Enable and START a write */
+writeb(s->addr + 0x10, addr & 0xfe); /* Send address for write */
+
+while (len--) {
+writeb(s->addr + 0x10, *buf++);
+}
+
+writeb(s->addr + 0x8, 0x80); /* STOP but leave enabled */
+}
+
+static void e500_i2c_recv(I2CAdapter *i2c, uint8_t addr,
+  uint8_t *buf, uint16_t len)
+{
+E500I2C *s = (E500I2C *)i2c;
+
+writeb(s->addr + 0x8, 0xa0); /* Enable and START a read */
+writeb(s->addr + 0x10, addr | 1); /* Send address for read */
+
+/* reads are "pipelined" so the initial value is junk */
+readb(s->addr + 0x10);
+
+while (len--) {
+*buf++ = readb(s->addr + 0x10);
+}
+
+writeb(s->addr + 0x8, 0x80); /* STOP but leave enabled */
+}
+
+I2CAdapter *e500_i2c_create(uint64_t ccsr_base)
+{
+E500I2C *s = g_malloc0(sizeof(*s));
+I2CAdapter *i2c = (I2CAdapter *)s;
+
+s->addr = ccsr_base + 0x3000;
+
+i2c->send = e500_i2c_send;
+i2c->recv = e500_i2c_recv;
+
+return i2c;
+}
diff --git a/tests/libqos/i2c.h b/tests/libqos/i2c.h
index 6e648f922a..40c59a7997 100644
--- a/tests/libqos/i2c.h
+++ b/tests/libqos/i2c.h
@@ -29,4 +29,7 @@ I2CAdapter *omap_i2c_create(uint64_t addr);
 /* libi2c-imx.c */
 I2CAdapter *imx_i2c_create(uint64_t addr);
 
+/* i2c-e500.c */
+I2CAdapter *e500_i2c_create(uint64_t ccsr_base);
+
 #endif
-- 
2.11.0




[Qemu-devel] [PATCH 10/17] e500: move uarts CCSR

2017-11-26 Thread Michael Davidsaver
Signed-off-by: Michael Davidsaver 
---
 hw/ppc/e500.c  | 13 -
 hw/ppc/e500_ccsr.c | 18 ++
 2 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 1872bb8eaa..2d87d91582 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -22,7 +22,6 @@
 #include "net/net.h"
 #include "qemu/config-file.h"
 #include "hw/hw.h"
-#include "hw/char/serial.h"
 #include "hw/pci/pci.h"
 #include "hw/boards.h"
 #include "sysemu/sysemu.h"
@@ -770,18 +769,6 @@ void ppce500_init(MachineState *machine, PPCE500Params 
*params)
 mpicdev = DEVICE(object_resolve_path("/machine/pic", 0));
 assert(mpicdev);
 
-/* Serial */
-if (serial_hds[0]) {
-serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET,
-   0, qdev_get_gpio_in(mpicdev, 42), 399193,
-   serial_hds[0], DEVICE_BIG_ENDIAN);
-}
-
-if (serial_hds[1]) {
-serial_mm_init(ccsr_addr_space, MPC8544_SERIAL1_REGS_OFFSET,
-   0, qdev_get_gpio_in(mpicdev, 42), 399193,
-   serial_hds[1], DEVICE_BIG_ENDIAN);
-}
 
 /* PCI */
 dev = qdev_create(NULL, "e500-pcihost");
diff --git a/hw/ppc/e500_ccsr.c b/hw/ppc/e500_ccsr.c
index 68d952794e..f1adba4e54 100644
--- a/hw/ppc/e500_ccsr.c
+++ b/hw/ppc/e500_ccsr.c
@@ -31,6 +31,7 @@
 #include "sysemu/sysemu.h"
 #include "sysemu/kvm.h"
 #include "hw/sysbus.h"
+#include "hw/char/serial.h"
 #include "hw/ppc/openpic.h"
 
 /* E500_ denotes registers common to all */
@@ -45,6 +46,8 @@
 #define E500_ERR_DETECT  (0x2e40)
 #define E500_ERR_DISABLE (0x2e44)
 
+#define E500_DUART_OFFSET(N) (0x4500 + (N) * 0x100)
+
 #define E500_PORPLLSR(0xE)
 #define E500_PVR (0xE00A0)
 #define E500_SVR (0xE00A4)
@@ -266,6 +269,21 @@ static void e500_ccsr_realize(DeviceState *dev, Error 
**errp)
 
 memory_region_add_subregion(&ccsr->iomem, E500_MPIC_OFFSET,
 sysbus_mmio_get_region(pic, 0));
+/* Note: MPIC internal interrupts are offset by 16 */
+
+/* DUARTS */
+if (serial_hds[0]) {
+serial_mm_init(&ccsr->iomem, E500_DUART_OFFSET(0),
+   0, qdev_get_gpio_in(ccsr->pic, 16 + 26), 399193,
+   serial_hds[0], DEVICE_BIG_ENDIAN);
+}
+
+if (serial_hds[1]) {
+serial_mm_init(&ccsr->iomem, E500_DUART_OFFSET(1),
+   0, qdev_get_gpio_in(ccsr->pic, 16 + 26), 399193,
+   serial_hds[1], DEVICE_BIG_ENDIAN);
+}
+
 }
 
 static Property e500_ccsr_props[] = {
-- 
2.11.0




[Qemu-devel] [PATCH 02/17] i2c: start trace-events

2017-11-26 Thread Michael Davidsaver
Signed-off-by: Michael Davidsaver 
---
 Makefile.objs   | 1 +
 hw/i2c/trace-events | 1 +
 2 files changed, 2 insertions(+)
 create mode 100644 hw/i2c/trace-events

diff --git a/Makefile.objs b/Makefile.objs
index 285c6f3c15..984ae8ecba 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -155,6 +155,7 @@ trace-events-subdirs += hw/arm
 trace-events-subdirs += hw/alpha
 trace-events-subdirs += hw/xen
 trace-events-subdirs += hw/ide
+trace-events-subdirs += hw/i2c
 trace-events-subdirs += ui
 trace-events-subdirs += audio
 trace-events-subdirs += net
diff --git a/hw/i2c/trace-events b/hw/i2c/trace-events
new file mode 100644
index 00..9284b1fbad
--- /dev/null
+++ b/hw/i2c/trace-events
@@ -0,0 +1 @@
+# See docs/devel/tracing.txt for syntax documentation.
-- 
2.11.0




[Qemu-devel] [PATCH 00/17] Add MVME3100 PPC SBC v2

2017-11-26 Thread Michael Davidsaver
Changes since previous iteration.

openpic: debug w/ info_report()

  New

i2c: start trace-events
i2c: add mpc8540 i2c controller

  Debugging cleanup and fix a spurious warning triggered by Linux guests.

qtest: add e500_i2c_create()

  Unchanged

timer: generalize Dallas/Maxim RTC i2c devices
tests: rewrite testing for DS RTC devices

  Combined models of ds1338 and ds1375 RTCs, along with untested support
  for some similar chips.
  Test case for setting time to exercise offset calculation.

e500: fix pci host bridge class/type

  After further investigation, revert the change which caused the host bridge
  to be identified as a pci-pci bridge.

e500: additional CCSR registers

  Also update CPUPPCState::mpic_iack when changing CCSRBAR.

e500: additional CCSR registers
e500: move mpic under CCSR
e500: move uarts CCSR
e500: derive baud from CCB clock
e500: add i2c controller to CCSR
e500: move PCI host bridge into CCSR

  Moved MPIC, UARTS, and PCI host bridge under CCSR device.
  Many of the PPCE500Params members become properties of the CCSR device.

e500: split mpc8544ds specific initialization

  Split ppce500_init() to create mpc85xx_init().
  mpc85xx_init() has all the bits used by the exist mpc8544ds and ppce500 
machines,
  but not by the new mvme3100 machine (which doesn't use PPCE500Params).

ppc: add mvme3100 machine

  Minor changes related to ppce500_init() changes

tests: run ds-rtc-i2c-test w/ ppc/mvme3100

  New

tests: add mvme3100-test

  Unchanged

Michael Davidsaver (17):
  openpic: debug w/ info_report()
  i2c: start trace-events
  i2c: add mpc8540 i2c controller
  qtest: add e500_i2c_create()
  timer: generalize Dallas/Maxim RTC i2c devices
  tests: rewrite testing for DS RTC devices
  e500: fix pci host bridge class/type
  e500: additional CCSR registers
  e500: move mpic under CCSR
  e500: move uarts CCSR
  e500: derive baud from CCB clock
  e500: add i2c controller to CCSR
  e500: move PCI host bridge into CCSR
  e500: split mpc8544ds specific initialization
  ppc: add mvme3100 machine
  tests: run ds-rtc-i2c-test w/ ppc/mvme3100
  tests: add mvme3100-test

 Makefile.objs   |   1 +
 default-configs/arm-softmmu.mak |   2 +-
 default-configs/ppc-softmmu.mak |   1 +
 hw/i2c/Makefile.objs|   1 +
 hw/i2c/mpc8540_i2c.c| 307 +
 hw/i2c/trace-events |   7 +
 hw/intc/openpic.c   | 102 +++---
 hw/pci-host/ppce500.c   |   5 -
 hw/ppc/Makefile.objs|   1 +
 hw/ppc/e500.c   | 175 +++---
 hw/ppc/e500.h   |   3 +-
 hw/ppc/e500_ccsr.c  | 246 -
 hw/ppc/e500plat.c   |   2 +-
 hw/ppc/mpc8544ds.c  |   2 +-
 hw/ppc/mvme3100.c   | 740 
 hw/ppc/mvme3100_cpld.c  | 192 +++
 hw/timer/Makefile.objs  |   2 +-
 hw/timer/ds-rtc-i2c.c   | 461 +
 hw/timer/ds1338.c   | 239 -
 tests/Makefile.include  |   9 +-
 tests/ds-rtc-i2c-test.c | 170 +
 tests/ds1338-test.c |  77 -
 tests/libqos/i2c-e500.c |  66 
 tests/libqos/i2c.h  |   3 +
 tests/mvme3100-test.c   |  79 +
 25 files changed, 2376 insertions(+), 517 deletions(-)
 create mode 100644 hw/i2c/mpc8540_i2c.c
 create mode 100644 hw/i2c/trace-events
 create mode 100644 hw/ppc/mvme3100.c
 create mode 100644 hw/ppc/mvme3100_cpld.c
 create mode 100644 hw/timer/ds-rtc-i2c.c
 delete mode 100644 hw/timer/ds1338.c
 create mode 100644 tests/ds-rtc-i2c-test.c
 delete mode 100644 tests/ds1338-test.c
 create mode 100644 tests/libqos/i2c-e500.c
 create mode 100644 tests/mvme3100-test.c

-- 
2.11.0




Re: [Qemu-devel] [PATCH 13/25] spapr: introduce the XIVE Event Queues

2017-11-26 Thread Benjamin Herrenschmidt
On Fri, 2017-11-24 at 09:15 +0100, Cédric Le Goater wrote:
> So The Linux driver is expected to choose priority 6. The priority
> validity is then checked in each hcall returning H_P4/H_P3 in case of 
> failure.  
> 
> But it is true that we scale the arrays with :
>  
> #define XIVE_PRIORITY_MAX  7
> 
> Do you want QEMU to completely remove prio 7 ? 

I'd like qemu to be consistent, at least make sure it errors out if the
OS tries to configue prio 7 or route an irq to it.

Cheers,
Ben.



[Qemu-devel] [PATCH] configure: Fix curses probe for older ncurses

2017-11-26 Thread Brad Smith
Fix the curses probe with older ncurses (.e.g. 5.7, as used by OpenBSD).

ncurses 5.7 requires _XOPEN_SOURCE_EXTENDED to be defined for WACS_* constants.

Signed-off-by: Brad Smith 


diff --git a/configure b/configure
index 0c6e7572db..9715b9c2cc 100755
--- a/configure
+++ b/configure
@@ -3186,7 +3186,7 @@ EOF
   IFS=:
   for curses_inc in $curses_inc_list; do
 # Make sure we get the wide character prototypes
-curses_inc="-DNCURSES_WIDECHAR $curses_inc"
+curses_inc="-DNCURSES_WIDECHAR -D_XOPEN_SOURCE_EXTENDED $curses_inc"
 IFS=:
 for curses_lib in $curses_lib_list; do
   unset IFS



[Qemu-devel] [Bug 1673976] Re: linux-user clone() can't handle glibc posix_spawn() (causes locale-gen to assert)

2017-11-26 Thread John Paul Adrian Glaubitz
Interestingly, this also affects Microsoft Windows Services For Linux,
i.e. Microsoft's Linux emulation layer.

> https://github.com/Microsoft/WSL/issues/1878

** Bug watch added: github.com/Microsoft/WSL/issues #1878
   https://github.com/Microsoft/WSL/issues/1878

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1673976

Title:
  linux-user clone() can't handle glibc posix_spawn() (causes locale-gen
  to assert)

Status in QEMU:
  New

Bug description:
  I'm running a command (locale-gen) inside of an armv7h chroot mounted
  on my x86_64 desktop by putting qemu-arm-static into /usr/bin/ of the
  chroot file system and I get a core dump.

  locale-gen
  Generating locales...
    en_US.UTF-8...localedef: ../sysdeps/unix/sysv/linux/spawni.c:360: 
__spawnix: Assertion `ec >= 0' failed.
  qemu: uncaught target signal 6 (Aborted) - core dumped
  /usr/bin/locale-gen: line 41:34 Aborted (core dumped) 
localedef -i $input -c -f $charset -A /usr/share/locale/locale.alias $locale

  I've done this same thing successfully for years, but this breakage
  has appeared some time in the last 3 or so months. Possibly with the
  update to qemu version 2.8.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1673976/+subscriptions



Re: [Qemu-devel] glibc "linux: spawni.c: simplify error reporting to parent" breaks qemu-user/Windows Service For Linux

2017-11-26 Thread John Paul Adrian Glaubitz
On 11/26/2017 09:28 PM, John Paul Adrian Glaubitz wrote:
> I'm not sure yet what the actual problem is but I thought it should be 
> necessary
> to point you at the problem.

Ok, there is already a QEMU bug report for this [1].

Adrian

> [1] https://bugs.launchpad.net/qemu/+bug/1673976

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaub...@debian.org
`. `'   Freie Universitaet Berlin - glaub...@physik.fu-berlin.de
  `-GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913



[Qemu-devel] glibc "linux: spawni.c: simplify error reporting to parent" breaks qemu-user/Windows Service For Linux

2017-11-26 Thread John Paul Adrian Glaubitz
Hi Rasmus!

Your recent commit "linux: spawni.c: simplify error reporting to parent" 
apparently
broke both qemu-user and Microsoft's Windows Services for Linux which both fail
with:

dpkg: warning: ignoring pre-dependency problem!
Preparing to unpack .../archives/bash_4.4-5_m68k.deb ...
preinst: ../sysdeps/unix/sysv/linux/spawni.c:366: __spawnix: Assertion `ec >= 
0' failed.
qemu: uncaught target signal 6 (Aborted) - core dumped
dpkg: error processing archive /var/cache/apt/archives/bash_4.4-5_m68k.deb 
(--unpack):
 new bash package pre-installation script subprocess was killed by signal 
(Aborted)
Selecting previously unselected package bsdutils.
dpkg: regarding .../bsdutils_1%3a2.30.2-0.1_m68k.deb containing bsdutils, 
pre-dependency problem:
 bsdutils pre-depends on libsystemd0
  libsystemd0 is not installed.

I'm not sure yet what the actual problem is but I thought it should be necessary
to point you at the problem.

Cheers,
Adrian

> [1] 
> https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=4b4d4056bb154603f36c6f8845757c1012758158;hp=8d3bd947483f50b57aee7c35c07dc1927d6e8a27
> [2] https://github.com/Microsoft/WSL/issues/1878

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaub...@debian.org
`. `'   Freie Universitaet Berlin - glaub...@physik.fu-berlin.de
  `-GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913



Re: [Qemu-devel] [PATCH 7/8] sun4u_iommu: convert from IOMMU_DPRINTF to trace-events

2017-11-26 Thread Philippe Mathieu-Daudé
On 11/26/2017 10:35 AM, Mark Cave-Ayland wrote:
> Signed-off-by: Mark Cave-Ayland 

Reviewed-by: Philippe Mathieu-Daudé 

> ---
>  hw/sparc64/sun4u_iommu.c |   17 +++--
>  hw/sparc64/trace-events  |4 
>  2 files changed, 7 insertions(+), 14 deletions(-)
> 
> diff --git a/hw/sparc64/sun4u_iommu.c b/hw/sparc64/sun4u_iommu.c
> index 612fec4..51fbc39 100644
> --- a/hw/sparc64/sun4u_iommu.c
> +++ b/hw/sparc64/sun4u_iommu.c
> @@ -30,16 +30,7 @@
>  #include "exec/address-spaces.h"
>  #include "qapi/error.h"
>  #include "qemu/log.h"
> -
> -/* debug IOMMU */
> -//#define DEBUG_IOMMU
> -
> -#ifdef DEBUG_IOMMU
> -#define IOMMU_DPRINTF(fmt, ...) \
> -do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0)
> -#else
> -#define IOMMU_DPRINTF(fmt, ...)
> -#endif
> +#include "trace.h"
>  
>  
>  #define IOMMU_PAGE_SIZE_8K  (1ULL << 13)
> @@ -201,8 +192,7 @@ static void iommu_mem_write(void *opaque, hwaddr addr,
>  {
>  IOMMUState *is = opaque;
>  
> -IOMMU_DPRINTF("IOMMU config write: 0x%" HWADDR_PRIx " val: %" PRIx64
> -  " size: %d\n", addr, val, size);
> +trace_sun4u_iommu_mem_write(addr, val, size);
>  
>  switch (addr) {
>  case IOMMU_CTRL:
> @@ -280,8 +270,7 @@ static uint64_t iommu_mem_read(void *opaque, hwaddr addr, 
> unsigned size)
>  break;
>  }
>  
> -IOMMU_DPRINTF("IOMMU config read: 0x%" HWADDR_PRIx " val: %" PRIx64
> -  " size: %d\n", addr, val, size);
> +trace_sun4u_iommu_mem_read(addr, val, size);
>  
>  return val;
>  }
> diff --git a/hw/sparc64/trace-events b/hw/sparc64/trace-events
> index 04d80b7..052352f 100644
> --- a/hw/sparc64/trace-events
> +++ b/hw/sparc64/trace-events
> @@ -2,3 +2,7 @@
>  
>  # hw/sparc64/sun4u.c
>  ebus_isa_irq_handler(int n, int level) "Set ISA IRQ %d level %d"
> +
> +# hw/sparc64/sun4u_iommu.c
> +sun4u_iommu_mem_read(uint64_t addr, uint64_t val, int size) "addr: 
> 0x%"PRIx64" val: 0x%"PRIx64" size: %d"
> +sun4u_iommu_mem_write(uint64_t addr, uint64_t val, int size) "addr: 
> 0x%"PRIx64" val: 0x%"PRIx64" size: %d"
> 



Re: [Qemu-devel] [PATCH 2/8] sun4m: move IOMMU declarations from sun4m.h to sun4m_iommu.h

2017-11-26 Thread Philippe Mathieu-Daudé
On 11/26/2017 10:35 AM, Mark Cave-Ayland wrote:
> Also updating the relevant .c files as required.
> 
> Signed-off-by: Mark Cave-Ayland 

Reviewed-by: Philippe Mathieu-Daudé 

> ---
>  hw/dma/sparc32_dma.c   |1 +
>  hw/sparc/sun4m.c   |1 +
>  hw/sparc/sun4m_iommu.c |1 +
>  include/hw/sparc/sun4m.h   |   21 -
>  include/hw/sparc/sun4m_iommu.h |   51 
> 
>  5 files changed, 54 insertions(+), 21 deletions(-)
>  create mode 100644 include/hw/sparc/sun4m_iommu.h
> 
> diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c
> index 01afb75..c04ad79 100644
> --- a/hw/dma/sparc32_dma.c
> +++ b/hw/dma/sparc32_dma.c
> @@ -29,6 +29,7 @@
>  #include "hw/hw.h"
>  #include "hw/sparc/sparc32_dma.h"
>  #include "hw/sparc/sun4m.h"
> +#include "hw/sparc/sun4m_iommu.h"
>  #include "hw/sysbus.h"
>  #include "sysemu/dma.h"
>  #include "qapi/error.h"
> diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
> index 24c2b8a..a3ba92f 100644
> --- a/hw/sparc/sun4m.c
> +++ b/hw/sparc/sun4m.c
> @@ -29,6 +29,7 @@
>  #include "qemu/error-report.h"
>  #include "qemu/timer.h"
>  #include "hw/sparc/sun4m.h"
> +#include "hw/sparc/sun4m_iommu.h"
>  #include "hw/timer/m48t59.h"
>  #include "hw/sparc/sparc32_dma.h"
>  #include "hw/block/fdc.h"
> diff --git a/hw/sparc/sun4m_iommu.c b/hw/sparc/sun4m_iommu.c
> index 72a9af5..311c82d 100644
> --- a/hw/sparc/sun4m_iommu.c
> +++ b/hw/sparc/sun4m_iommu.c
> @@ -24,6 +24,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "hw/sparc/sun4m.h"
> +#include "hw/sparc/sun4m_iommu.h"
>  #include "hw/sysbus.h"
>  #include "exec/address-spaces.h"
>  #include "trace.h"
> diff --git a/include/hw/sparc/sun4m.h b/include/hw/sparc/sun4m.h
> index c557b0d..9e06467 100644
> --- a/include/hw/sparc/sun4m.h
> +++ b/include/hw/sparc/sun4m.h
> @@ -8,27 +8,6 @@
>  
>  /* Devices used by sparc32 system.  */
>  
> -/* iommu.c */
> -#define TYPE_SUN4M_IOMMU "sun4m-iommu"
> -#define SUN4M_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4M_IOMMU)
> -
> -#define TYPE_SUN4M_IOMMU_MEMORY_REGION "sun4m-iommu-memory-region"
> -
> -#define IOMMU_NREGS (4 * 4096 / 4)
> -
> -typedef struct IOMMUState {
> -SysBusDevice parent_obj;
> -
> -AddressSpace iommu_as;
> -IOMMUMemoryRegion iommu;
> -
> -MemoryRegion iomem;
> -uint32_t regs[IOMMU_NREGS];
> -hwaddr iostart;
> -qemu_irq irq;
> -uint32_t version;
> -} IOMMUState;
> -
>  /* sparc32_dma.c */
>  #include "hw/sparc/sparc32_dma.h"
>  
> diff --git a/include/hw/sparc/sun4m_iommu.h b/include/hw/sparc/sun4m_iommu.h
> new file mode 100644
> index 000..938937eb
> --- /dev/null
> +++ b/include/hw/sparc/sun4m_iommu.h
> @@ -0,0 +1,51 @@
> +/*
> + * QEMU Sun4m iommu emulation
> + *
> + * Copyright (c) 2003-2005 Fabrice Bellard
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a 
> copy
> + * of this software and associated documentation files (the "Software"), to 
> deal
> + * in the Software without restriction, including without limitation the 
> rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
> FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#ifndef SUN4M_IOMMU_H
> +#define SUN4M_IOMMU_H
> +
> +#include "qemu-common.h"
> +#include "hw/sysbus.h"
> +
> +#define IOMMU_NREGS (4 * 4096 / 4)
> +
> +typedef struct IOMMUState {
> +SysBusDevice parent_obj;
> +
> +AddressSpace iommu_as;
> +IOMMUMemoryRegion iommu;
> +
> +MemoryRegion iomem;
> +uint32_t regs[IOMMU_NREGS];
> +hwaddr iostart;
> +qemu_irq irq;
> +uint32_t version;
> +} IOMMUState;
> +
> +#define TYPE_SUN4M_IOMMU "sun4m-iommu"
> +#define SUN4M_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4M_IOMMU)
> +
> +#define TYPE_SUN4M_IOMMU_MEMORY_REGION "sun4m-iommu-memory-region"
> +
> +#endif
> 



Re: [Qemu-devel] [PATCH 6/8] sun4u_iommu: update to reflect IOMMU is no longer part of the APB device

2017-11-26 Thread Philippe Mathieu-Daudé
On 11/26/2017 10:35 AM, Mark Cave-Ayland wrote:
> Signed-off-by: Mark Cave-Ayland 

Reviewed-by: Philippe Mathieu-Daudé 

> ---
>  hw/sparc64/sun4u_iommu.c   |   35 ++-
>  include/hw/sparc/sun4u_iommu.h |2 +-
>  2 files changed, 19 insertions(+), 18 deletions(-)
> 
> diff --git a/hw/sparc64/sun4u_iommu.c b/hw/sparc64/sun4u_iommu.c
> index e5aa817..612fec4 100644
> --- a/hw/sparc64/sun4u_iommu.c
> +++ b/hw/sparc64/sun4u_iommu.c
> @@ -81,8 +81,9 @@ do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0)
>  
>  
>  /* Called from RCU critical section */
> -static IOMMUTLBEntry pbm_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr 
> addr,
> - IOMMUAccessFlags flag)
> +static IOMMUTLBEntry sun4u_translate_iommu(IOMMUMemoryRegion *iommu,
> +   hwaddr addr,
> +   IOMMUAccessFlags flag)
>  {
>  IOMMUState *is = container_of(iommu, IOMMUState, iommu);
>  hwaddr baseaddr, offset;
> @@ -233,7 +234,7 @@ static void iommu_mem_write(void *opaque, hwaddr addr,
>  break;
>  default:
>  qemu_log_mask(LOG_UNIMP,
> -  "apb iommu: Unimplemented register write "
> +  "sun4u-iommu: Unimplemented register write "
>"reg 0x%" HWADDR_PRIx " size 0x%x value 0x%" PRIx64 "\n",
>addr, size, val);
>  break;
> @@ -272,7 +273,7 @@ static uint64_t iommu_mem_read(void *opaque, hwaddr addr, 
> unsigned size)
>  break;
>  default:
>  qemu_log_mask(LOG_UNIMP,
> -  "apb iommu: Unimplemented register read "
> +  "sun4u-iommu: Unimplemented register read "
>"reg 0x%" HWADDR_PRIx " size 0x%x\n",
>addr, size);
>  val = 0;
> @@ -304,9 +305,9 @@ static void iommu_init(Object *obj)
>  SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
>  
>  memory_region_init_iommu(&s->iommu, sizeof(s->iommu),
> - TYPE_APB_IOMMU_MEMORY_REGION, OBJECT(s),
> - "iommu-apb", UINT64_MAX);
> -address_space_init(&s->iommu_as, MEMORY_REGION(&s->iommu), "pbm-as");
> + TYPE_SUN4U_IOMMU_MEMORY_REGION, OBJECT(s),
> + "iommu-sun4u", UINT64_MAX);
> +address_space_init(&s->iommu_as, MEMORY_REGION(&s->iommu), "iommu-as");
>  
>  memory_region_init_io(&s->iomem, obj, &iommu_mem_ops, s, "iommu",
>IOMMU_NREGS * sizeof(uint64_t));
> @@ -320,7 +321,7 @@ static void iommu_class_init(ObjectClass *klass, void 
> *data)
>  dc->reset = iommu_reset;
>  }
>  
> -static const TypeInfo pbm_iommu_info = {
> +static const TypeInfo iommu_info = {
>  .name  = TYPE_SUN4U_IOMMU,
>  .parent= TYPE_SYS_BUS_DEVICE,
>  .instance_size = sizeof(IOMMUState),
> @@ -328,23 +329,23 @@ static const TypeInfo pbm_iommu_info = {
>  .class_init= iommu_class_init,
>  };
>  
> -static void pbm_iommu_memory_region_class_init(ObjectClass *klass, void 
> *data)
> +static void sun4u_iommu_memory_region_class_init(ObjectClass *klass, void 
> *data)
>  {
>  IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
>  
> -imrc->translate = pbm_translate_iommu;
> +imrc->translate = sun4u_translate_iommu;
>  }
>  
> -static const TypeInfo pbm_iommu_memory_region_info = {
> +static const TypeInfo sun4u_iommu_memory_region_info = {
>  .parent = TYPE_IOMMU_MEMORY_REGION,
> -.name = TYPE_APB_IOMMU_MEMORY_REGION,
> -.class_init = pbm_iommu_memory_region_class_init,
> +.name = TYPE_SUN4U_IOMMU_MEMORY_REGION,
> +.class_init = sun4u_iommu_memory_region_class_init,
>  };
>  
> -static void pbm_register_types(void)
> +static void iommu_register_types(void)
>  {
> -type_register_static(&pbm_iommu_info);
> -type_register_static(&pbm_iommu_memory_region_info);
> +type_register_static(&iommu_info);
> +type_register_static(&sun4u_iommu_memory_region_info);
>  }
>  
> -type_init(pbm_register_types)
> +type_init(iommu_register_types)
> diff --git a/include/hw/sparc/sun4u_iommu.h b/include/hw/sparc/sun4u_iommu.h
> index bc4506b..a760172 100644
> --- a/include/hw/sparc/sun4u_iommu.h
> +++ b/include/hw/sparc/sun4u_iommu.h
> @@ -45,6 +45,6 @@ typedef struct IOMMUState {
>  #define TYPE_SUN4U_IOMMU "sun4u-iommu"
>  #define SUN4U_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4U_IOMMU)
>  
> -#define TYPE_APB_IOMMU_MEMORY_REGION "pbm-iommu-memory-region"
> +#define TYPE_SUN4U_IOMMU_MEMORY_REGION "sun4u-iommu-memory-region"
>  
>  #endif
> 



Re: [Qemu-devel] [PATCH 3/8] sun4m: remove include/hw/sparc/sun4m.h and all references to it

2017-11-26 Thread Philippe Mathieu-Daudé
On 11/26/2017 10:35 AM, Mark Cave-Ayland wrote:
> With the previous commit there is now nothing left in sun4m.h so it can be
> removed, along with all remaining references to it.

Nice!

> 
> Signed-off-by: Mark Cave-Ayland 

Reviewed-by: Philippe Mathieu-Daudé 

> ---
>  hw/dma/sparc32_dma.c |1 -
>  hw/intc/slavio_intctl.c  |1 -
>  hw/net/lance.c   |2 +-
>  hw/sparc/sun4m.c |1 -
>  hw/sparc/sun4m_iommu.c   |1 -
>  hw/timer/slavio_timer.c  |1 -
>  include/hw/sparc/sun4m.h |   14 --
>  7 files changed, 1 insertion(+), 20 deletions(-)
>  delete mode 100644 include/hw/sparc/sun4m.h
> 
> diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c
> index c04ad79..7b00a27 100644
> --- a/hw/dma/sparc32_dma.c
> +++ b/hw/dma/sparc32_dma.c
> @@ -28,7 +28,6 @@
>  #include "qemu/osdep.h"
>  #include "hw/hw.h"
>  #include "hw/sparc/sparc32_dma.h"
> -#include "hw/sparc/sun4m.h"
>  #include "hw/sparc/sun4m_iommu.h"
>  #include "hw/sysbus.h"
>  #include "sysemu/dma.h"
> diff --git a/hw/intc/slavio_intctl.c b/hw/intc/slavio_intctl.c
> index 84e0bee..817e026 100644
> --- a/hw/intc/slavio_intctl.c
> +++ b/hw/intc/slavio_intctl.c
> @@ -23,7 +23,6 @@
>   */
>  
>  #include "qemu/osdep.h"
> -#include "hw/sparc/sun4m.h"
>  #include "monitor/monitor.h"
>  #include "hw/sysbus.h"
>  #include "hw/intc/intc.h"
> diff --git a/hw/net/lance.c b/hw/net/lance.c
> index 23929fd..0028bc5 100644
> --- a/hw/net/lance.c
> +++ b/hw/net/lance.c
> @@ -40,7 +40,7 @@
>  #include "net/net.h"
>  #include "qemu/timer.h"
>  #include "qemu/sockets.h"
> -#include "hw/sparc/sun4m.h"
> +#include "hw/sparc/sparc32_dma.h"
>  #include "hw/net/lance.h"
>  #include "trace.h"
>  #include "sysemu/sysemu.h"
> diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
> index a3ba92f..9723d6f 100644
> --- a/hw/sparc/sun4m.c
> +++ b/hw/sparc/sun4m.c
> @@ -28,7 +28,6 @@
>  #include "hw/sysbus.h"
>  #include "qemu/error-report.h"
>  #include "qemu/timer.h"
> -#include "hw/sparc/sun4m.h"
>  #include "hw/sparc/sun4m_iommu.h"
>  #include "hw/timer/m48t59.h"
>  #include "hw/sparc/sparc32_dma.h"
> diff --git a/hw/sparc/sun4m_iommu.c b/hw/sparc/sun4m_iommu.c
> index 311c82d..b677601 100644
> --- a/hw/sparc/sun4m_iommu.c
> +++ b/hw/sparc/sun4m_iommu.c
> @@ -23,7 +23,6 @@
>   */
>  
>  #include "qemu/osdep.h"
> -#include "hw/sparc/sun4m.h"
>  #include "hw/sparc/sun4m_iommu.h"
>  #include "hw/sysbus.h"
>  #include "exec/address-spaces.h"
> diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c
> index a8cc9c0..4694b65 100644
> --- a/hw/timer/slavio_timer.c
> +++ b/hw/timer/slavio_timer.c
> @@ -23,7 +23,6 @@
>   */
>  
>  #include "qemu/osdep.h"
> -#include "hw/sparc/sun4m.h"
>  #include "qemu/timer.h"
>  #include "hw/ptimer.h"
>  #include "hw/sysbus.h"
> diff --git a/include/hw/sparc/sun4m.h b/include/hw/sparc/sun4m.h
> deleted file mode 100644
> index 9e06467..000
> --- a/include/hw/sparc/sun4m.h
> +++ /dev/null
> @@ -1,14 +0,0 @@
> -#ifndef SUN4M_H
> -#define SUN4M_H
> -
> -#include "qemu-common.h"
> -#include "exec/hwaddr.h"
> -#include "qapi/qmp/types.h"
> -#include "hw/sysbus.h"
> -
> -/* Devices used by sparc32 system.  */
> -
> -/* sparc32_dma.c */
> -#include "hw/sparc/sparc32_dma.h"
> -
> -#endif
> 



Re: [Qemu-devel] [PATCH v8 05/13] xilinx_spips: Move FlashCMD, XilinxQSPIPS and XilinxSPIPSClass

2017-11-26 Thread Philippe Mathieu-Daudé
On 11/24/2017 06:29 PM, Francisco Iglesias wrote:
> Move the FlashCMD enum, XilinxQSPIPS and XilinxSPIPSClass structures to the
> header for consistency (struct XilinxSPIPS is found there). Also move out
> a define and remove two double included headers (while touching the code).
> Finally, add 4 byte address commands to the FlashCMD enum.
> 
> Signed-off-by: Francisco Iglesias 
> Reviewed-by: Alistair Francis 

Reviewed-by: Philippe Mathieu-Daudé 

> ---
>  hw/ssi/xilinx_spips.c | 35 ---
>  include/hw/ssi/xilinx_spips.h | 34 ++
>  2 files changed, 34 insertions(+), 35 deletions(-)
> 
> diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
> index ef56d35..559fa79 100644
> --- a/hw/ssi/xilinx_spips.c
> +++ b/hw/ssi/xilinx_spips.c
> @@ -27,8 +27,6 @@
>  #include "sysemu/sysemu.h"
>  #include "hw/ptimer.h"
>  #include "qemu/log.h"
> -#include "qemu/fifo8.h"
> -#include "hw/ssi/ssi.h"
>  #include "qemu/bitops.h"
>  #include "hw/ssi/xilinx_spips.h"
>  #include "qapi/error.h"
> @@ -116,44 +114,11 @@
>  
>  /* 16MB per linear region */
>  #define LQSPI_ADDRESS_BITS 24
> -/* Bite off 4k chunks at a time */
> -#define LQSPI_CACHE_SIZE 1024
>  
>  #define SNOOP_CHECKING 0xFF
>  #define SNOOP_NONE 0xFE
>  #define SNOOP_STRIPING 0
>  
> -typedef enum {
> -READ = 0x3,
> -FAST_READ = 0xb,
> -DOR = 0x3b,
> -QOR = 0x6b,
> -DIOR = 0xbb,
> -QIOR = 0xeb,
> -
> -PP = 0x2,
> -DPP = 0xa2,
> -QPP = 0x32,
> -} FlashCMD;
> -
> -typedef struct {
> -XilinxSPIPS parent_obj;
> -
> -uint8_t lqspi_buf[LQSPI_CACHE_SIZE];
> -hwaddr lqspi_cached_addr;
> -Error *migration_blocker;
> -bool mmio_execution_enabled;
> -} XilinxQSPIPS;
> -
> -typedef struct XilinxSPIPSClass {
> -SysBusDeviceClass parent_class;
> -
> -const MemoryRegionOps *reg_ops;
> -
> -uint32_t rx_fifo_size;
> -uint32_t tx_fifo_size;
> -} XilinxSPIPSClass;
> -
>  static inline int num_effective_busses(XilinxSPIPS *s)
>  {
>  return (s->regs[R_LQSPI_CFG] & LQSPI_CFG_SEP_BUS &&
> diff --git a/include/hw/ssi/xilinx_spips.h b/include/hw/ssi/xilinx_spips.h
> index 06aa096..7f9e2fc 100644
> --- a/include/hw/ssi/xilinx_spips.h
> +++ b/include/hw/ssi/xilinx_spips.h
> @@ -32,6 +32,22 @@ typedef struct XilinxSPIPS XilinxSPIPS;
>  
>  #define XLNX_SPIPS_R_MAX(0x100 / 4)
>  
> +/* Bite off 4k chunks at a time */
> +#define LQSPI_CACHE_SIZE 1024
> +
> +typedef enum {
> +READ = 0x3, READ_4 = 0x13,
> +FAST_READ = 0xb,FAST_READ_4 = 0x0c,
> +DOR = 0x3b, DOR_4 = 0x3c,
> +QOR = 0x6b, QOR_4 = 0x6c,
> +DIOR = 0xbb,DIOR_4 = 0xbc,
> +QIOR = 0xeb,QIOR_4 = 0xec,
> +
> +PP = 0x2,   PP_4 = 0x12,
> +DPP = 0xa2,
> +QPP = 0x32, QPP_4 = 0x34,
> +} FlashCMD;
> +
>  struct XilinxSPIPS {
>  SysBusDevice parent_obj;
>  
> @@ -56,6 +72,24 @@ struct XilinxSPIPS {
>  uint32_t regs[XLNX_SPIPS_R_MAX];
>  };
>  
> +typedef struct {
> +XilinxSPIPS parent_obj;
> +
> +uint8_t lqspi_buf[LQSPI_CACHE_SIZE];
> +hwaddr lqspi_cached_addr;
> +Error *migration_blocker;
> +bool mmio_execution_enabled;
> +} XilinxQSPIPS;
> +
> +typedef struct XilinxSPIPSClass {
> +SysBusDeviceClass parent_class;
> +
> +const MemoryRegionOps *reg_ops;
> +
> +uint32_t rx_fifo_size;
> +uint32_t tx_fifo_size;
> +} XilinxSPIPSClass;
> +
>  #define TYPE_XILINX_SPIPS "xlnx.ps7-spi"
>  #define TYPE_XILINX_QSPIPS "xlnx.ps7-qspi"
>  
> 



Re: [Qemu-devel] [PATCH v8 02/13] m25p80: Add support for SST READ ID 0x90/0xAB commands

2017-11-26 Thread Philippe Mathieu-Daudé
Hi Francisco,

On 11/24/2017 06:29 PM, Francisco Iglesias wrote:
> Add support for SST READ ID 0x90/0xAB commands for reading out the flash
> manufacuter ID and device ID.
> 
> Signed-off-by: Francisco Iglesias 
> Acked-by: Alistair Francis 
> Acked-by: Marcin Krzemiński 
> ---
>  hw/block/m25p80.c | 23 +++
>  1 file changed, 23 insertions(+)
> 
> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
> index d50acc1..9d20120 100644
> --- a/hw/block/m25p80.c
> +++ b/hw/block/m25p80.c
> @@ -355,6 +355,8 @@ typedef enum {
>  DPP = 0xa2,
>  QPP = 0x32,
>  QPP_4 = 0x34,
> +RDID_90 = 0x90,
> +RDID_AB = 0xab,
>  
>  ERASE_4K = 0x20,
>  ERASE4_4K = 0x21,
> @@ -405,6 +407,7 @@ typedef enum {
>  MAN_MACRONIX,
>  MAN_NUMONYX,
>  MAN_WINBOND,
> +MAN_SST,
>  MAN_GENERIC,
>  } Manufacturer;
>  
> @@ -476,6 +479,8 @@ static inline Manufacturer get_man(Flash *s)
>  return MAN_SPANSION;
>  case 0xC2:
>  return MAN_MACRONIX;
> +case 0xBF:
> +return MAN_SST;
>  default:
>  return MAN_GENERIC;
>  }
> @@ -711,6 +716,22 @@ static void complete_collecting_data(Flash *s)
>  case WEVCR:
>  s->enh_volatile_cfg = s->data[0];
>  break;
> +case RDID_90:
> +case RDID_AB:
> +if (get_man(s) == MAN_SST && s->cur_addr <= 1) {

What about reporting if guest access this address when not an SST flash?

   if (get_man(s) == MAN_SST) {
   if (s->cur_addr <= 1) {

> +if (s->cur_addr) {
> +s->data[0] = s->pi->id[2];
> +s->data[1] = s->pi->id[0];
> +} else {
> +s->data[0] = s->pi->id[0];
> +s->data[1] = s->pi->id[2];
> +}
> +s->pos = 0;
> +s->len = 2;
> +s->data_read_loop = true;
> +s->state = STATE_READING_DATA;

   } else {
// LOG_UNIMP?
   }
   } else {
   qemu_log_mask(LOG_GUEST_ERROR, ...);

> +}
> +break;
>  default:
>  break;
>  }
> @@ -926,6 +947,8 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>  case PP4:
>  case PP4_4:
>  case DIE_ERASE:
> +case RDID_90:
> +case RDID_AB:
>  s->needed_bytes = get_addr_length(s);
>  s->pos = 0;
>  s->len = 0;

Regards,

Phil.



[Qemu-devel] [PATCH 8/8] sun4u_iommu: add trace event for IOMMU translations

2017-11-26 Thread Mark Cave-Ayland
Signed-off-by: Mark Cave-Ayland 
---
 hw/sparc64/sun4u_iommu.c |2 ++
 hw/sparc64/trace-events  |1 +
 2 files changed, 3 insertions(+)

diff --git a/hw/sparc64/sun4u_iommu.c b/hw/sparc64/sun4u_iommu.c
index 51fbc39..4cf8e69 100644
--- a/hw/sparc64/sun4u_iommu.c
+++ b/hw/sparc64/sun4u_iommu.c
@@ -184,6 +184,8 @@ static IOMMUTLBEntry 
sun4u_translate_iommu(IOMMUMemoryRegion *iommu,
 ret.addr_mask = (IOMMU_PAGE_SIZE_8K - 1);
 }
 
+trace_sun4u_iommu_translate(ret.iova, ret.translated_addr, tte);
+
 return ret;
 }
 
diff --git a/hw/sparc64/trace-events b/hw/sparc64/trace-events
index 052352f..2ee2d75 100644
--- a/hw/sparc64/trace-events
+++ b/hw/sparc64/trace-events
@@ -6,3 +6,4 @@ ebus_isa_irq_handler(int n, int level) "Set ISA IRQ %d level %d"
 # hw/sparc64/sun4u_iommu.c
 sun4u_iommu_mem_read(uint64_t addr, uint64_t val, int size) "addr: 0x%"PRIx64" 
val: 0x%"PRIx64" size: %d"
 sun4u_iommu_mem_write(uint64_t addr, uint64_t val, int size) "addr: 
0x%"PRIx64" val: 0x%"PRIx64" size: %d"
+sun4u_iommu_translate(uint64_t addr, uint64_t trans_addr, uint64_t tte) "xlate 
0x%"PRIx64" => pa 0x%"PRIx64" tte: 0x%"PRIx64
-- 
1.7.10.4




[Qemu-devel] [PATCH 1/8] sun4m: move sun4m_iommu.c from hw/dma to hw/sparc

2017-11-26 Thread Mark Cave-Ayland
This seems more appropriate and brings sun4m in line with the other
architectures.

Signed-off-by: Mark Cave-Ayland 
---
 hw/dma/Makefile.objs   |1 -
 hw/dma/sun4m_iommu.c   |  406 ---
 hw/dma/trace-events|   10 --
 hw/sparc/Makefile.objs |2 +-
 hw/sparc/sun4m_iommu.c |  407 
 hw/sparc/trace-events  |   10 ++
 6 files changed, 418 insertions(+), 418 deletions(-)
 delete mode 100644 hw/dma/sun4m_iommu.c
 create mode 100644 hw/sparc/sun4m_iommu.c

diff --git a/hw/dma/Makefile.objs b/hw/dma/Makefile.objs
index 087c8e6..0b3a009 100644
--- a/hw/dma/Makefile.objs
+++ b/hw/dma/Makefile.objs
@@ -8,7 +8,6 @@ common-obj-$(CONFIG_XILINX_AXI) += xilinx_axidma.o
 common-obj-$(CONFIG_ZYNQ_DEVCFG) += xlnx-zynq-devcfg.o
 common-obj-$(CONFIG_ETRAXFS) += etraxfs_dma.o
 common-obj-$(CONFIG_STP2000) += sparc32_dma.o
-common-obj-$(CONFIG_SUN4M) += sun4m_iommu.o
 obj-$(CONFIG_XLNX_ZYNQMP) += xlnx_dpdma.o
 
 obj-$(CONFIG_OMAP) += omap_dma.o soc_dma.o
diff --git a/hw/dma/sun4m_iommu.c b/hw/dma/sun4m_iommu.c
deleted file mode 100644
index 30a05e8..000
--- a/hw/dma/sun4m_iommu.c
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * QEMU Sun4m iommu emulation
- *
- * Copyright (c) 2003-2005 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to 
deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu/osdep.h"
-#include "hw/sparc/sun4m.h"
-#include "hw/sysbus.h"
-#include "exec/address-spaces.h"
-#include "trace.h"
-
-/*
- * I/O MMU used by Sun4m systems
- *
- * Chipset docs:
- * "Sun-4M System Architecture (revision 2.0) by Chuck Narad", 950-1373-01,
- * 
http://mediacast.sun.com/users/Barton808/media/Sun4M_SystemArchitecture_edited2.pdf
- */
-
-#define IOMMU_CTRL  (0x >> 2)
-#define IOMMU_CTRL_IMPL 0xf000 /* Implementation */
-#define IOMMU_CTRL_VERS 0x0f00 /* Version */
-#define IOMMU_CTRL_RNGE 0x001c /* Mapping RANGE */
-#define IOMMU_RNGE_16MB 0x /* 0xff00 -> 0x */
-#define IOMMU_RNGE_32MB 0x0004 /* 0xfe00 -> 0x */
-#define IOMMU_RNGE_64MB 0x0008 /* 0xfc00 -> 0x */
-#define IOMMU_RNGE_128MB0x000c /* 0xf800 -> 0x */
-#define IOMMU_RNGE_256MB0x0010 /* 0xf000 -> 0x */
-#define IOMMU_RNGE_512MB0x0014 /* 0xe000 -> 0x */
-#define IOMMU_RNGE_1GB  0x0018 /* 0xc000 -> 0x */
-#define IOMMU_RNGE_2GB  0x001c /* 0x8000 -> 0x */
-#define IOMMU_CTRL_ENAB 0x0001 /* IOMMU Enable */
-#define IOMMU_CTRL_MASK 0x001d
-
-#define IOMMU_BASE  (0x0004 >> 2)
-#define IOMMU_BASE_MASK 0x07fffc00
-
-#define IOMMU_TLBFLUSH  (0x0014 >> 2)
-#define IOMMU_TLBFLUSH_MASK 0x
-
-#define IOMMU_PGFLUSH   (0x0018 >> 2)
-#define IOMMU_PGFLUSH_MASK  0x
-
-#define IOMMU_AFSR  (0x1000 >> 2)
-#define IOMMU_AFSR_ERR  0x8000 /* LE, TO, or BE asserted */
-#define IOMMU_AFSR_LE   0x4000 /* SBUS reports error after
-  transaction */
-#define IOMMU_AFSR_TO   0x2000 /* Write access took more than
-  12.8 us. */
-#define IOMMU_AFSR_BE   0x1000 /* Write access received error
-  acknowledge */
-#define IOMMU_AFSR_SIZE 0x0e00 /* Size of transaction causing error */
-#define IOMMU_AFSR_S0x0100 /* Sparc was in supervisor mode */
-#define IOMMU_AFSR_RESV 0x0080 /* Reserved, forced to 0x8 by
-  hardware */
-#define IOMMU_AFSR_ME   0x0008 /* Multiple errors occurred */
-#define IOMMU_AFSR_RD   0x0004 /* A read operation was in progress */
-#define IOMMU_AFSR_FAV  0x0002 /* IOMMU afar has valid contents */
-#define IOMMU_AFSR_MASK 0xff0f
-
-#define IOMMU_AFAR  (0x1004 >> 2)
-
-#define 

[Qemu-devel] [PATCH 4/8] apb: QOMify IOMMU

2017-11-26 Thread Mark Cave-Ayland
This is in preparation to split the IOMMU device out of the APB. As part of
this commit we also enforce separation of the IOMMU and APB devices by using
a QOM object link to pass the IOMMU reference and accessing the IOMMU registers
via a separate memory region mapped into the APB config space rather than
directly.

Signed-off-by: Mark Cave-Ayland 
---
 hw/pci-host/apb.c |   77 +
 hw/sparc64/sun4u.c|7 -
 include/hw/pci-host/apb.h |8 -
 3 files changed, 70 insertions(+), 22 deletions(-)

diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 54ab899..7eb5ce0 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -36,6 +36,7 @@
 #include "hw/pci-host/apb.h"
 #include "sysemu/sysemu.h"
 #include "exec/address-spaces.h"
+#include "qapi/error.h"
 #include "qemu/log.h"
 
 /* debug APB */
@@ -250,8 +251,8 @@ static IOMMUTLBEntry pbm_translate_iommu(IOMMUMemoryRegion 
*iommu, hwaddr addr,
 return ret;
 }
 
-static void iommu_config_write(void *opaque, hwaddr addr,
-   uint64_t val, unsigned size)
+static void iommu_mem_write(void *opaque, hwaddr addr,
+uint64_t val, unsigned size)
 {
 IOMMUState *is = opaque;
 
@@ -295,7 +296,7 @@ static void iommu_config_write(void *opaque, hwaddr addr,
 }
 }
 
-static uint64_t iommu_config_read(void *opaque, hwaddr addr, unsigned size)
+static uint64_t iommu_mem_read(void *opaque, hwaddr addr, unsigned size)
 {
 IOMMUState *is = opaque;
 uint64_t val;
@@ -344,7 +345,6 @@ static void apb_config_writel (void *opaque, hwaddr addr,
uint64_t val, unsigned size)
 {
 APBState *s = opaque;
-IOMMUState *is = &s->iommu;
 
 APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, 
addr, val);
 
@@ -352,9 +352,6 @@ static void apb_config_writel (void *opaque, hwaddr addr,
 case 0x30 ... 0x4f: /* DMA error registers */
 /* XXX: not implemented yet */
 break;
-case 0x200 ... 0x217: /* IOMMU */
-iommu_config_write(is, (addr & 0x1f), val, size);
-break;
 case 0xc00 ... 0xc3f: /* PCI interrupt control */
 if (addr & 4) {
 unsigned int ino = (addr & 0x3f) >> 3;
@@ -426,7 +423,6 @@ static uint64_t apb_config_readl (void *opaque,
   hwaddr addr, unsigned size)
 {
 APBState *s = opaque;
-IOMMUState *is = &s->iommu;
 uint32_t val;
 
 switch (addr & 0x) {
@@ -434,9 +430,6 @@ static uint64_t apb_config_readl (void *opaque,
 val = 0;
 /* XXX: not implemented yet */
 break;
-case 0x200 ... 0x217: /* IOMMU */
-val = iommu_config_read(is, (addr & 0x1f), size);
-break;
 case 0xc00 ... 0xc3f: /* PCI interrupt control */
 if (addr & 4) {
 val = s->pci_irq_map[(addr & 0x3f) >> 3];
@@ -641,7 +634,6 @@ static void pci_pbm_realize(DeviceState *dev, Error **errp)
 PCIHostState *phb = PCI_HOST_BRIDGE(dev);
 SysBusDevice *sbd = SYS_BUS_DEVICE(s);
 PCIDevice *pci_dev;
-IOMMUState *is;
 
 /* apb_config */
 sysbus_mmio_map(sbd, 0, s->special_base);
@@ -657,14 +649,9 @@ static void pci_pbm_realize(DeviceState *dev, Error **errp)
 pci_create_simple(phb->bus, 0, "pbm-pci");
 
 /* APB IOMMU */
-is = &s->iommu;
-memset(is, 0, sizeof(IOMMUState));
-
-memory_region_init_iommu(&is->iommu, sizeof(is->iommu),
- TYPE_APB_IOMMU_MEMORY_REGION, OBJECT(dev),
- "iommu-apb", UINT64_MAX);
-address_space_init(&is->iommu_as, MEMORY_REGION(&is->iommu), "pbm-as");
-pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, is);
+memory_region_add_subregion_overlap(&s->apb_config, 0x200,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(s->iommu), 0), 1);
+pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, s->iommu);
 
 /* APB secondary busses */
 pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true,
@@ -707,6 +694,12 @@ static void pci_pbm_init(Object *obj)
 s->irq_request = NO_IRQ_REQUEST;
 s->pci_irq_in = 0ULL;
 
+/* IOMMU */
+object_property_add_link(obj, "iommu", TYPE_SUN4U_IOMMU,
+ (Object **) &s->iommu,
+ qdev_prop_allow_set_link_before_realize,
+ 0, NULL);
+
 /* apb_config */
 memory_region_init_io(&s->apb_config, OBJECT(s), &apb_config_ops, s,
   "apb-config", 0x1);
@@ -813,6 +806,49 @@ static const TypeInfo pbm_pci_bridge_info = {
 },
 };
 
+static const MemoryRegionOps iommu_mem_ops = {
+.read = iommu_mem_read,
+.write = iommu_mem_write,
+.endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void iommu_reset(DeviceState *d)
+{
+IOMMUState *s = SUN4U_IOMMU(d);
+
+memset(s->regs, 0, IOMMU_NREGS * sizeof(uint64_t));
+}
+
+static void iommu_init(Object *obj)
+{
+IO

[Qemu-devel] [PATCH 6/8] sun4u_iommu: update to reflect IOMMU is no longer part of the APB device

2017-11-26 Thread Mark Cave-Ayland
Signed-off-by: Mark Cave-Ayland 
---
 hw/sparc64/sun4u_iommu.c   |   35 ++-
 include/hw/sparc/sun4u_iommu.h |2 +-
 2 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/hw/sparc64/sun4u_iommu.c b/hw/sparc64/sun4u_iommu.c
index e5aa817..612fec4 100644
--- a/hw/sparc64/sun4u_iommu.c
+++ b/hw/sparc64/sun4u_iommu.c
@@ -81,8 +81,9 @@ do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0)
 
 
 /* Called from RCU critical section */
-static IOMMUTLBEntry pbm_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr,
- IOMMUAccessFlags flag)
+static IOMMUTLBEntry sun4u_translate_iommu(IOMMUMemoryRegion *iommu,
+   hwaddr addr,
+   IOMMUAccessFlags flag)
 {
 IOMMUState *is = container_of(iommu, IOMMUState, iommu);
 hwaddr baseaddr, offset;
@@ -233,7 +234,7 @@ static void iommu_mem_write(void *opaque, hwaddr addr,
 break;
 default:
 qemu_log_mask(LOG_UNIMP,
-  "apb iommu: Unimplemented register write "
+  "sun4u-iommu: Unimplemented register write "
   "reg 0x%" HWADDR_PRIx " size 0x%x value 0x%" PRIx64 "\n",
   addr, size, val);
 break;
@@ -272,7 +273,7 @@ static uint64_t iommu_mem_read(void *opaque, hwaddr addr, 
unsigned size)
 break;
 default:
 qemu_log_mask(LOG_UNIMP,
-  "apb iommu: Unimplemented register read "
+  "sun4u-iommu: Unimplemented register read "
   "reg 0x%" HWADDR_PRIx " size 0x%x\n",
   addr, size);
 val = 0;
@@ -304,9 +305,9 @@ static void iommu_init(Object *obj)
 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 
 memory_region_init_iommu(&s->iommu, sizeof(s->iommu),
- TYPE_APB_IOMMU_MEMORY_REGION, OBJECT(s),
- "iommu-apb", UINT64_MAX);
-address_space_init(&s->iommu_as, MEMORY_REGION(&s->iommu), "pbm-as");
+ TYPE_SUN4U_IOMMU_MEMORY_REGION, OBJECT(s),
+ "iommu-sun4u", UINT64_MAX);
+address_space_init(&s->iommu_as, MEMORY_REGION(&s->iommu), "iommu-as");
 
 memory_region_init_io(&s->iomem, obj, &iommu_mem_ops, s, "iommu",
   IOMMU_NREGS * sizeof(uint64_t));
@@ -320,7 +321,7 @@ static void iommu_class_init(ObjectClass *klass, void *data)
 dc->reset = iommu_reset;
 }
 
-static const TypeInfo pbm_iommu_info = {
+static const TypeInfo iommu_info = {
 .name  = TYPE_SUN4U_IOMMU,
 .parent= TYPE_SYS_BUS_DEVICE,
 .instance_size = sizeof(IOMMUState),
@@ -328,23 +329,23 @@ static const TypeInfo pbm_iommu_info = {
 .class_init= iommu_class_init,
 };
 
-static void pbm_iommu_memory_region_class_init(ObjectClass *klass, void *data)
+static void sun4u_iommu_memory_region_class_init(ObjectClass *klass, void 
*data)
 {
 IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
 
-imrc->translate = pbm_translate_iommu;
+imrc->translate = sun4u_translate_iommu;
 }
 
-static const TypeInfo pbm_iommu_memory_region_info = {
+static const TypeInfo sun4u_iommu_memory_region_info = {
 .parent = TYPE_IOMMU_MEMORY_REGION,
-.name = TYPE_APB_IOMMU_MEMORY_REGION,
-.class_init = pbm_iommu_memory_region_class_init,
+.name = TYPE_SUN4U_IOMMU_MEMORY_REGION,
+.class_init = sun4u_iommu_memory_region_class_init,
 };
 
-static void pbm_register_types(void)
+static void iommu_register_types(void)
 {
-type_register_static(&pbm_iommu_info);
-type_register_static(&pbm_iommu_memory_region_info);
+type_register_static(&iommu_info);
+type_register_static(&sun4u_iommu_memory_region_info);
 }
 
-type_init(pbm_register_types)
+type_init(iommu_register_types)
diff --git a/include/hw/sparc/sun4u_iommu.h b/include/hw/sparc/sun4u_iommu.h
index bc4506b..a760172 100644
--- a/include/hw/sparc/sun4u_iommu.h
+++ b/include/hw/sparc/sun4u_iommu.h
@@ -45,6 +45,6 @@ typedef struct IOMMUState {
 #define TYPE_SUN4U_IOMMU "sun4u-iommu"
 #define SUN4U_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4U_IOMMU)
 
-#define TYPE_APB_IOMMU_MEMORY_REGION "pbm-iommu-memory-region"
+#define TYPE_SUN4U_IOMMU_MEMORY_REGION "sun4u-iommu-memory-region"
 
 #endif
-- 
1.7.10.4




[Qemu-devel] [PATCH 3/8] sun4m: remove include/hw/sparc/sun4m.h and all references to it

2017-11-26 Thread Mark Cave-Ayland
With the previous commit there is now nothing left in sun4m.h so it can be
removed, along with all remaining references to it.

Signed-off-by: Mark Cave-Ayland 
---
 hw/dma/sparc32_dma.c |1 -
 hw/intc/slavio_intctl.c  |1 -
 hw/net/lance.c   |2 +-
 hw/sparc/sun4m.c |1 -
 hw/sparc/sun4m_iommu.c   |1 -
 hw/timer/slavio_timer.c  |1 -
 include/hw/sparc/sun4m.h |   14 --
 7 files changed, 1 insertion(+), 20 deletions(-)
 delete mode 100644 include/hw/sparc/sun4m.h

diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c
index c04ad79..7b00a27 100644
--- a/hw/dma/sparc32_dma.c
+++ b/hw/dma/sparc32_dma.c
@@ -28,7 +28,6 @@
 #include "qemu/osdep.h"
 #include "hw/hw.h"
 #include "hw/sparc/sparc32_dma.h"
-#include "hw/sparc/sun4m.h"
 #include "hw/sparc/sun4m_iommu.h"
 #include "hw/sysbus.h"
 #include "sysemu/dma.h"
diff --git a/hw/intc/slavio_intctl.c b/hw/intc/slavio_intctl.c
index 84e0bee..817e026 100644
--- a/hw/intc/slavio_intctl.c
+++ b/hw/intc/slavio_intctl.c
@@ -23,7 +23,6 @@
  */
 
 #include "qemu/osdep.h"
-#include "hw/sparc/sun4m.h"
 #include "monitor/monitor.h"
 #include "hw/sysbus.h"
 #include "hw/intc/intc.h"
diff --git a/hw/net/lance.c b/hw/net/lance.c
index 23929fd..0028bc5 100644
--- a/hw/net/lance.c
+++ b/hw/net/lance.c
@@ -40,7 +40,7 @@
 #include "net/net.h"
 #include "qemu/timer.h"
 #include "qemu/sockets.h"
-#include "hw/sparc/sun4m.h"
+#include "hw/sparc/sparc32_dma.h"
 #include "hw/net/lance.h"
 #include "trace.h"
 #include "sysemu/sysemu.h"
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index a3ba92f..9723d6f 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -28,7 +28,6 @@
 #include "hw/sysbus.h"
 #include "qemu/error-report.h"
 #include "qemu/timer.h"
-#include "hw/sparc/sun4m.h"
 #include "hw/sparc/sun4m_iommu.h"
 #include "hw/timer/m48t59.h"
 #include "hw/sparc/sparc32_dma.h"
diff --git a/hw/sparc/sun4m_iommu.c b/hw/sparc/sun4m_iommu.c
index 311c82d..b677601 100644
--- a/hw/sparc/sun4m_iommu.c
+++ b/hw/sparc/sun4m_iommu.c
@@ -23,7 +23,6 @@
  */
 
 #include "qemu/osdep.h"
-#include "hw/sparc/sun4m.h"
 #include "hw/sparc/sun4m_iommu.h"
 #include "hw/sysbus.h"
 #include "exec/address-spaces.h"
diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c
index a8cc9c0..4694b65 100644
--- a/hw/timer/slavio_timer.c
+++ b/hw/timer/slavio_timer.c
@@ -23,7 +23,6 @@
  */
 
 #include "qemu/osdep.h"
-#include "hw/sparc/sun4m.h"
 #include "qemu/timer.h"
 #include "hw/ptimer.h"
 #include "hw/sysbus.h"
diff --git a/include/hw/sparc/sun4m.h b/include/hw/sparc/sun4m.h
deleted file mode 100644
index 9e06467..000
--- a/include/hw/sparc/sun4m.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef SUN4M_H
-#define SUN4M_H
-
-#include "qemu-common.h"
-#include "exec/hwaddr.h"
-#include "qapi/qmp/types.h"
-#include "hw/sysbus.h"
-
-/* Devices used by sparc32 system.  */
-
-/* sparc32_dma.c */
-#include "hw/sparc/sparc32_dma.h"
-
-#endif
-- 
1.7.10.4




[Qemu-devel] [PATCH 2/8] sun4m: move IOMMU declarations from sun4m.h to sun4m_iommu.h

2017-11-26 Thread Mark Cave-Ayland
Also updating the relevant .c files as required.

Signed-off-by: Mark Cave-Ayland 
---
 hw/dma/sparc32_dma.c   |1 +
 hw/sparc/sun4m.c   |1 +
 hw/sparc/sun4m_iommu.c |1 +
 include/hw/sparc/sun4m.h   |   21 -
 include/hw/sparc/sun4m_iommu.h |   51 
 5 files changed, 54 insertions(+), 21 deletions(-)
 create mode 100644 include/hw/sparc/sun4m_iommu.h

diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c
index 01afb75..c04ad79 100644
--- a/hw/dma/sparc32_dma.c
+++ b/hw/dma/sparc32_dma.c
@@ -29,6 +29,7 @@
 #include "hw/hw.h"
 #include "hw/sparc/sparc32_dma.h"
 #include "hw/sparc/sun4m.h"
+#include "hw/sparc/sun4m_iommu.h"
 #include "hw/sysbus.h"
 #include "sysemu/dma.h"
 #include "qapi/error.h"
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 24c2b8a..a3ba92f 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -29,6 +29,7 @@
 #include "qemu/error-report.h"
 #include "qemu/timer.h"
 #include "hw/sparc/sun4m.h"
+#include "hw/sparc/sun4m_iommu.h"
 #include "hw/timer/m48t59.h"
 #include "hw/sparc/sparc32_dma.h"
 #include "hw/block/fdc.h"
diff --git a/hw/sparc/sun4m_iommu.c b/hw/sparc/sun4m_iommu.c
index 72a9af5..311c82d 100644
--- a/hw/sparc/sun4m_iommu.c
+++ b/hw/sparc/sun4m_iommu.c
@@ -24,6 +24,7 @@
 
 #include "qemu/osdep.h"
 #include "hw/sparc/sun4m.h"
+#include "hw/sparc/sun4m_iommu.h"
 #include "hw/sysbus.h"
 #include "exec/address-spaces.h"
 #include "trace.h"
diff --git a/include/hw/sparc/sun4m.h b/include/hw/sparc/sun4m.h
index c557b0d..9e06467 100644
--- a/include/hw/sparc/sun4m.h
+++ b/include/hw/sparc/sun4m.h
@@ -8,27 +8,6 @@
 
 /* Devices used by sparc32 system.  */
 
-/* iommu.c */
-#define TYPE_SUN4M_IOMMU "sun4m-iommu"
-#define SUN4M_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4M_IOMMU)
-
-#define TYPE_SUN4M_IOMMU_MEMORY_REGION "sun4m-iommu-memory-region"
-
-#define IOMMU_NREGS (4 * 4096 / 4)
-
-typedef struct IOMMUState {
-SysBusDevice parent_obj;
-
-AddressSpace iommu_as;
-IOMMUMemoryRegion iommu;
-
-MemoryRegion iomem;
-uint32_t regs[IOMMU_NREGS];
-hwaddr iostart;
-qemu_irq irq;
-uint32_t version;
-} IOMMUState;
-
 /* sparc32_dma.c */
 #include "hw/sparc/sparc32_dma.h"
 
diff --git a/include/hw/sparc/sun4m_iommu.h b/include/hw/sparc/sun4m_iommu.h
new file mode 100644
index 000..938937eb
--- /dev/null
+++ b/include/hw/sparc/sun4m_iommu.h
@@ -0,0 +1,51 @@
+/*
+ * QEMU Sun4m iommu emulation
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef SUN4M_IOMMU_H
+#define SUN4M_IOMMU_H
+
+#include "qemu-common.h"
+#include "hw/sysbus.h"
+
+#define IOMMU_NREGS (4 * 4096 / 4)
+
+typedef struct IOMMUState {
+SysBusDevice parent_obj;
+
+AddressSpace iommu_as;
+IOMMUMemoryRegion iommu;
+
+MemoryRegion iomem;
+uint32_t regs[IOMMU_NREGS];
+hwaddr iostart;
+qemu_irq irq;
+uint32_t version;
+} IOMMUState;
+
+#define TYPE_SUN4M_IOMMU "sun4m-iommu"
+#define SUN4M_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4M_IOMMU)
+
+#define TYPE_SUN4M_IOMMU_MEMORY_REGION "sun4m-iommu-memory-region"
+
+#endif
-- 
1.7.10.4




[Qemu-devel] [PATCH 7/8] sun4u_iommu: convert from IOMMU_DPRINTF to trace-events

2017-11-26 Thread Mark Cave-Ayland
Signed-off-by: Mark Cave-Ayland 
---
 hw/sparc64/sun4u_iommu.c |   17 +++--
 hw/sparc64/trace-events  |4 
 2 files changed, 7 insertions(+), 14 deletions(-)

diff --git a/hw/sparc64/sun4u_iommu.c b/hw/sparc64/sun4u_iommu.c
index 612fec4..51fbc39 100644
--- a/hw/sparc64/sun4u_iommu.c
+++ b/hw/sparc64/sun4u_iommu.c
@@ -30,16 +30,7 @@
 #include "exec/address-spaces.h"
 #include "qapi/error.h"
 #include "qemu/log.h"
-
-/* debug IOMMU */
-//#define DEBUG_IOMMU
-
-#ifdef DEBUG_IOMMU
-#define IOMMU_DPRINTF(fmt, ...) \
-do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define IOMMU_DPRINTF(fmt, ...)
-#endif
+#include "trace.h"
 
 
 #define IOMMU_PAGE_SIZE_8K  (1ULL << 13)
@@ -201,8 +192,7 @@ static void iommu_mem_write(void *opaque, hwaddr addr,
 {
 IOMMUState *is = opaque;
 
-IOMMU_DPRINTF("IOMMU config write: 0x%" HWADDR_PRIx " val: %" PRIx64
-  " size: %d\n", addr, val, size);
+trace_sun4u_iommu_mem_write(addr, val, size);
 
 switch (addr) {
 case IOMMU_CTRL:
@@ -280,8 +270,7 @@ static uint64_t iommu_mem_read(void *opaque, hwaddr addr, 
unsigned size)
 break;
 }
 
-IOMMU_DPRINTF("IOMMU config read: 0x%" HWADDR_PRIx " val: %" PRIx64
-  " size: %d\n", addr, val, size);
+trace_sun4u_iommu_mem_read(addr, val, size);
 
 return val;
 }
diff --git a/hw/sparc64/trace-events b/hw/sparc64/trace-events
index 04d80b7..052352f 100644
--- a/hw/sparc64/trace-events
+++ b/hw/sparc64/trace-events
@@ -2,3 +2,7 @@
 
 # hw/sparc64/sun4u.c
 ebus_isa_irq_handler(int n, int level) "Set ISA IRQ %d level %d"
+
+# hw/sparc64/sun4u_iommu.c
+sun4u_iommu_mem_read(uint64_t addr, uint64_t val, int size) "addr: 0x%"PRIx64" 
val: 0x%"PRIx64" size: %d"
+sun4u_iommu_mem_write(uint64_t addr, uint64_t val, int size) "addr: 
0x%"PRIx64" val: 0x%"PRIx64" size: %d"
-- 
1.7.10.4




[Qemu-devel] [PATCH 0/8] sparc: IOMMU tidy-up and reorganisation

2017-11-26 Thread Mark Cave-Ayland
Following on from the previous sun4u patchset, here is the next step of
IOMMU-related updates for 2.12.

This patchset does 2 main things: firstly it moves the sun4m IOMMU
device out of hw/dma and into hw/sparc to match existing architectures.
With this (and the previous sun4m DMA rework) the old sun4m.h header can
now be completely removed.

Secondly in a similar manner, we split the sun4u IOMMU functionality out
from the APB device into a new sun4u-iommu device in hw/sparc64, adding in
a conversion from DPRINTF macros to trace-events for good measure while
we are here.

Signed-off-by: Mark Cave-Ayland 
Based-on: 1511699686-12605-1-git-send-email-mark.cave-ayl...@ilande.co.uk 
([PATCHv2 00/15] sun4u: tidy-up CPU, APB and ebus)


Mark Cave-Ayland (8):
  sun4m: move sun4m_iommu.c from hw/dma to hw/sparc
  sun4m: move IOMMU declarations from sun4m.h to sun4m_iommu.h
  sun4m: remove include/hw/sparc/sun4m.h and all references to it
  apb: QOMify IOMMU
  sun4u: split IOMMU device out from apb.c to sun4u_iommu.c
  sun4u_iommu: update to reflect IOMMU is no longer part of the APB
device
  sun4u_iommu: convert from IOMMU_DPRINTF to trace-events
  sun4u_iommu: add trace event for IOMMU translations

 hw/dma/Makefile.objs   |1 -
 hw/dma/sparc32_dma.c   |2 +-
 hw/dma/sun4m_iommu.c   |  406 ---
 hw/dma/trace-events|   10 -
 hw/intc/slavio_intctl.c|1 -
 hw/net/lance.c |2 +-
 hw/pci-host/apb.c  |  256 +
 hw/sparc/Makefile.objs |2 +-
 hw/sparc/sun4m.c   |2 +-
 hw/sparc/sun4m_iommu.c |  407 
 hw/sparc/trace-events  |   10 +
 hw/sparc64/Makefile.objs   |1 +
 hw/sparc64/sun4u.c |8 +-
 hw/sparc64/sun4u_iommu.c   |  342 +
 hw/sparc64/trace-events|5 +
 hw/timer/slavio_timer.c|1 -
 include/hw/pci-host/apb.h  |   53 +-
 include/hw/sparc/sun4m.h   |   35 
 include/hw/sparc/sun4m_iommu.h |   51 +
 include/hw/sparc/sun4u_iommu.h |   50 +
 20 files changed, 889 insertions(+), 756 deletions(-)
 delete mode 100644 hw/dma/sun4m_iommu.c
 create mode 100644 hw/sparc/sun4m_iommu.c
 create mode 100644 hw/sparc64/sun4u_iommu.c
 delete mode 100644 include/hw/sparc/sun4m.h
 create mode 100644 include/hw/sparc/sun4m_iommu.h
 create mode 100644 include/hw/sparc/sun4u_iommu.h

-- 
1.7.10.4




[Qemu-devel] [PATCH 5/8] sun4u: split IOMMU device out from apb.c to sun4u_iommu.c

2017-11-26 Thread Mark Cave-Ayland
By separating the sun4u IOMMU device into new sun4u_iommu.c and sun4m_iommu.h
files we noticeably simplify apb.c whilst bringing sun4u in line with all the
other IOMMU-supporting architectures.

Signed-off-by: Mark Cave-Ayland 
---
 hw/pci-host/apb.c  |  273 ---
 hw/sparc64/Makefile.objs   |1 +
 hw/sparc64/sun4u.c |1 +
 hw/sparc64/sun4u_iommu.c   |  350 
 include/hw/pci-host/apb.h  |   57 +--
 include/hw/sparc/sun4u_iommu.h |   50 ++
 6 files changed, 403 insertions(+), 329 deletions(-)
 create mode 100644 hw/sparc64/sun4u_iommu.c
 create mode 100644 include/hw/sparc/sun4u_iommu.h

diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 7eb5ce0..516dc28 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -49,16 +49,6 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
 #define APB_DPRINTF(fmt, ...)
 #endif
 
-/* debug IOMMU */
-//#define DEBUG_IOMMU
-
-#ifdef DEBUG_IOMMU
-#define IOMMU_DPRINTF(fmt, ...) \
-do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define IOMMU_DPRINTF(fmt, ...)
-#endif
-
 /*
  * Chipset docs:
  * PBM: "UltraSPARC IIi User's Manual",
@@ -136,211 +126,6 @@ static AddressSpace *pbm_pci_dma_iommu(PCIBus *bus, void 
*opaque, int devfn)
 return &is->iommu_as;
 }
 
-/* Called from RCU critical section */
-static IOMMUTLBEntry pbm_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr,
- IOMMUAccessFlags flag)
-{
-IOMMUState *is = container_of(iommu, IOMMUState, iommu);
-hwaddr baseaddr, offset;
-uint64_t tte;
-uint32_t tsbsize;
-IOMMUTLBEntry ret = {
-.target_as = &address_space_memory,
-.iova = 0,
-.translated_addr = 0,
-.addr_mask = ~(hwaddr)0,
-.perm = IOMMU_NONE,
-};
-
-if (!(is->regs[IOMMU_CTRL >> 3] & IOMMU_CTRL_MMU_EN)) {
-/* IOMMU disabled, passthrough using standard 8K page */
-ret.iova = addr & IOMMU_PAGE_MASK_8K;
-ret.translated_addr = addr;
-ret.addr_mask = IOMMU_PAGE_MASK_8K;
-ret.perm = IOMMU_RW;
-
-return ret;
-}
-
-baseaddr = is->regs[IOMMU_BASE >> 3];
-tsbsize = (is->regs[IOMMU_CTRL >> 3] >> IOMMU_CTRL_TSB_SHIFT) & 0x7;
-
-if (is->regs[IOMMU_CTRL >> 3] & IOMMU_CTRL_TBW_SIZE) {
-/* 64K */
-switch (tsbsize) {
-case 0:
-offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_64M) >> 13;
-break;
-case 1:
-offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_128M) >> 13;
-break;
-case 2:
-offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_256M) >> 13;
-break;
-case 3:
-offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_512M) >> 13;
-break;
-case 4:
-offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_1G) >> 13;
-break;
-case 5:
-offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_2G) >> 13;
-break;
-default:
-/* Not implemented, error */
-return ret;
-}
-} else {
-/* 8K */
-switch (tsbsize) {
-case 0:
-offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_8M) >> 10;
-break;
-case 1:
-offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_16M) >> 10;
-break;
-case 2:
-offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_32M) >> 10;
-break;
-case 3:
-offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_64M) >> 10;
-break;
-case 4:
-offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_128M) >> 10;
-break;
-case 5:
-offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_256M) >> 10;
-break;
-case 6:
-offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_512M) >> 10;
-break;
-case 7:
-offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_1G) >> 10;
-break;
-}
-}
-
-tte = address_space_ldq_be(&address_space_memory, baseaddr + offset,
-   MEMTXATTRS_UNSPECIFIED, NULL);
-
-if (!(tte & IOMMU_TTE_DATA_V)) {
-/* Invalid mapping */
-return ret;
-}
-
-if (tte & IOMMU_TTE_DATA_W) {
-/* Writeable */
-ret.perm = IOMMU_RW;
-} else {
-ret.perm = IOMMU_RO;
-}
-
-/* Extract phys */
-if (tte & IOMMU_TTE_DATA_SIZE) {
-/* 64K */
-ret.iova = addr & IOMMU_PAGE_MASK_64K;
-ret.translated_addr = tte & IOMMU_TTE_PHYS_MASK_64K;
-ret.addr_mask = (IOMMU_PAGE_SIZE_64K - 1);
-} else {
-/* 8K */
-ret.iova = addr & IOMMU_PAGE_MASK_8K;
-ret.translated_addr = tte & IOMMU_TTE_PHYS_MASK_8K;
-ret.addr_mask = (IOMMU_PAGE_SIZE_8K - 1);
-}
-
-return ret;
-}
-
-static void iommu_mem_write(void *opaque, hwaddr addr,
-uint64_t v

[Qemu-devel] [PATCHv2 10/15] apb: remove pci_apb_init() and instantiate APB device using qdev

2017-11-26 Thread Mark Cave-Ayland
By making the special_base and mem_base values qdev properties, we can move
the remaining parts of pci_apb_init() into the pbm init() and realize()
functions.

This finally allows us to instantiate the APB directly using standard qdev
create/init functions in sun4u.c.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Artyom Tarasenko 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/pci-host/apb.c |  123 ++---
 hw/sparc64/sun4u.c|6 ++-
 include/hw/pci-host/apb.h |4 +-
 3 files changed, 68 insertions(+), 65 deletions(-)

diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 823661a..6c20285 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -611,41 +611,56 @@ static void apb_pci_bridge_realize(PCIDevice *dev, Error 
**errp)
 pci_bridge_update_mappings(PCI_BRIDGE(br));
 }
 
-APBState *pci_apb_init(hwaddr special_base,
-   hwaddr mem_base)
+static void pci_pbm_reset(DeviceState *d)
 {
-DeviceState *dev;
-SysBusDevice *s;
-PCIHostState *phb;
-APBState *d;
-IOMMUState *is;
+unsigned int i;
+APBState *s = APB_DEVICE(d);
+
+for (i = 0; i < 8; i++) {
+s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
+}
+for (i = 0; i < 32; i++) {
+s->obio_irq_map[i] &= PBM_PCI_IMR_MASK;
+}
+
+s->irq_request = NO_IRQ_REQUEST;
+s->pci_irq_in = 0ULL;
+
+if (s->nr_resets++ == 0) {
+/* Power on reset */
+s->reset_control = POR;
+}
+}
+
+static const MemoryRegionOps pci_config_ops = {
+.read = apb_pci_config_read,
+.write = apb_pci_config_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void pci_pbm_realize(DeviceState *dev, Error **errp)
+{
+APBState *s = APB_DEVICE(dev);
+PCIHostState *phb = PCI_HOST_BRIDGE(dev);
+SysBusDevice *sbd = SYS_BUS_DEVICE(s);
 PCIDevice *pci_dev;
+IOMMUState *is;
 
-/* Ultrasparc PBM main bus */
-dev = qdev_create(NULL, TYPE_APB);
-d = APB_DEVICE(dev);
-phb = PCI_HOST_BRIDGE(dev);
-phb->bus = pci_register_bus(DEVICE(phb), "pci",
-pci_apb_set_irq, pci_apb_map_irq, d,
-&d->pci_mmio,
-&d->pci_ioport,
-0, 32, TYPE_PCI_BUS);
-qdev_init_nofail(dev);
-s = SYS_BUS_DEVICE(dev);
 /* apb_config */
-sysbus_mmio_map(s, 0, special_base);
+sysbus_mmio_map(sbd, 0, s->special_base);
 /* PCI configuration space */
-sysbus_mmio_map(s, 1, special_base + 0x100ULL);
+sysbus_mmio_map(sbd, 1, s->special_base + 0x100ULL);
 /* pci_ioport */
-sysbus_mmio_map(s, 2, special_base + 0x200ULL);
+sysbus_mmio_map(sbd, 2, s->special_base + 0x200ULL);
 
-memory_region_init(&d->pci_mmio, OBJECT(s), "pci-mmio", 0x1ULL);
-memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio);
+memory_region_init(&s->pci_mmio, OBJECT(s), "pci-mmio", 0x1ULL);
+memory_region_add_subregion(get_system_memory(), s->mem_base,
+&s->pci_mmio);
 
 pci_create_simple(phb->bus, 0, "pbm-pci");
 
 /* APB IOMMU */
-is = &d->iommu;
+is = &s->iommu;
 memset(is, 0, sizeof(IOMMUState));
 
 memory_region_init_iommu(&is->iommu, sizeof(is->iommu),
@@ -657,52 +672,30 @@ APBState *pci_apb_init(hwaddr special_base,
 /* APB secondary busses */
 pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true,
TYPE_PBM_PCI_BRIDGE);
-d->bridgeB = PCI_BRIDGE(pci_dev);
-pci_bridge_map_irq(d->bridgeB, "pciB", pci_pbm_map_irq);
+s->bridgeB = PCI_BRIDGE(pci_dev);
+pci_bridge_map_irq(s->bridgeB, "pciB", pci_pbm_map_irq);
 qdev_init_nofail(&pci_dev->qdev);
 
 pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 1), true,
TYPE_PBM_PCI_BRIDGE);
-d->bridgeA = PCI_BRIDGE(pci_dev);
-pci_bridge_map_irq(d->bridgeA, "pciA", pci_pbm_map_irq);
+s->bridgeA = PCI_BRIDGE(pci_dev);
+pci_bridge_map_irq(s->bridgeA, "pciA", pci_pbm_map_irq);
 qdev_prop_set_bit(DEVICE(pci_dev), "busA", true);
 qdev_init_nofail(&pci_dev->qdev);
-
-return d;
 }
 
-static void pci_pbm_reset(DeviceState *d)
+static void pci_pbm_init(Object *obj)
 {
+APBState *s = APB_DEVICE(obj);
+PCIHostState *phb = PCI_HOST_BRIDGE(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 unsigned int i;
-APBState *s = APB_DEVICE(d);
-
-for (i = 0; i < 8; i++) {
-s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
-}
-for (i = 0; i < 32; i++) {
-s->obio_irq_map[i] &= PBM_PCI_IMR_MASK;
-}
-
-s->irq_request = NO_IRQ_REQUEST;
-s->pci_irq_in = 0ULL;
-
-if (s->nr_resets++ == 0) {
-/* Power on reset */
-s->reset_control = POR;
-}
-}
 
-static const MemoryRegionOps pci_config_ops = {
-.read = apb_pci_config_read,
-.write = apb_pci_conf

[Qemu-devel] [PATCHv2 14/15] sparc64: introduce trace-events for hw/sparc64

2017-11-26 Thread Mark Cave-Ayland
This is in preparation for switching code in hw/sparc64 from DPRINTF over to
trace events.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Artyom Tarasenko 
Reviewed-by: Philippe Mathieu-Daudé 
---
 Makefile.objs   |1 +
 hw/sparc64/trace-events |1 +
 2 files changed, 2 insertions(+)
 create mode 100644 hw/sparc64/trace-events

diff --git a/Makefile.objs b/Makefile.objs
index 285c6f3..c8b1bba 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -140,6 +140,7 @@ trace-events-subdirs += hw/input
 trace-events-subdirs += hw/timer
 trace-events-subdirs += hw/dma
 trace-events-subdirs += hw/sparc
+trace-events-subdirs += hw/sparc64
 trace-events-subdirs += hw/sd
 trace-events-subdirs += hw/isa
 trace-events-subdirs += hw/mem
diff --git a/hw/sparc64/trace-events b/hw/sparc64/trace-events
new file mode 100644
index 000..9284b1f
--- /dev/null
+++ b/hw/sparc64/trace-events
@@ -0,0 +1 @@
+# See docs/devel/tracing.txt for syntax documentation.
-- 
1.7.10.4




[Qemu-devel] [PATCHv2 12/15] ebus: wire up OBIO interrupts to APB pbm via qdev GPIOs

2017-11-26 Thread Mark Cave-Ayland
This enables us to remove the static array mapping in the ISA IRQ
handler (and the embedded reference to the APB device) by formalising
the interrupt wiring via the qdev GPIO API.

For more clarity we replace the APB OBIO interrupt numbers with constants
designating the interrupt source, and rename isa_irq_handler() to
ebus_isa_irq_handler().

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Artyom Tarasenko 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/pci-host/apb.c |2 +-
 hw/sparc64/sun4u.c|   49 +++--
 include/hw/pci-host/apb.h |8 +++-
 3 files changed, 33 insertions(+), 26 deletions(-)

diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index d260db3..7b066fd 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -702,7 +702,7 @@ static void pci_pbm_init(Object *obj)
 for (i = 0; i < 32; i++) {
 s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i;
 }
-s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC);
+qdev_init_gpio_in_named(DEVICE(s), pci_apb_set_irq, "pbm-irq", MAX_IVEC);
 qdev_init_gpio_out_named(DEVICE(s), s->ivec_irqs, "ivec-irq", MAX_IVEC);
 s->irq_request = NO_IRQ_REQUEST;
 s->pci_irq_in = 0ULL;
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 0a30fb8..1456c33 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -86,6 +86,7 @@ typedef struct EbusState {
 PCIDevice parent_obj;
 
 ISABus *isa_bus;
+qemu_irq isa_bus_irqs[ISA_NUM_IRQS];
 uint64_t console_serial_base;
 MemoryRegion bar0;
 MemoryRegion bar1;
@@ -211,23 +212,15 @@ typedef struct ResetData {
 uint64_t prom_addr;
 } ResetData;
 
-static void isa_irq_handler(void *opaque, int n, int level)
+static void ebus_isa_irq_handler(void *opaque, int n, int level)
 {
-static const int isa_irq_to_ivec[16] = {
-[1] = 0x29, /* keyboard */
-[4] = 0x2b, /* serial */
-[6] = 0x27, /* floppy */
-[7] = 0x22, /* parallel */
-[12] = 0x2a, /* mouse */
-};
-qemu_irq *irqs = opaque;
-int ivec;
-
-assert(n < ARRAY_SIZE(isa_irq_to_ivec));
-ivec = isa_irq_to_ivec[n];
-EBUS_DPRINTF("Set ISA IRQ %d level %d -> ivec 0x%x\n", n, level, ivec);
-if (ivec) {
-qemu_set_irq(irqs[ivec], level);
+EbusState *s = EBUS(opaque);
+qemu_irq irq = s->isa_bus_irqs[n];
+
+/* Pass ISA bus IRQs onto their gpio equivalent */
+EBUS_DPRINTF("Set ISA IRQ %d level %d\n", n, level);
+if (irq) {
+qemu_set_irq(irq, level);
 }
 }
 
@@ -235,7 +228,6 @@ static void isa_irq_handler(void *opaque, int n, int level)
 static void ebus_realize(PCIDevice *pci_dev, Error **errp)
 {
 EbusState *s = EBUS(pci_dev);
-APBState *apb;
 DeviceState *dev;
 qemu_irq *isa_irq;
 DriveInfo *fd[MAX_FD];
@@ -248,14 +240,11 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp)
 return;
 }
 
-apb = APB_DEVICE(object_resolve_path_type("", TYPE_APB, NULL));
-if (!apb) {
-error_setg(errp, "unable to locate APB PCI host bridge");
-return;
-}
-
-isa_irq = qemu_allocate_irqs(isa_irq_handler, apb->pbm_irqs, 16);
+/* ISA bus */
+isa_irq = qemu_allocate_irqs(ebus_isa_irq_handler, s, ISA_NUM_IRQS);
 isa_bus_irqs(s->isa_bus, isa_irq);
+qdev_init_gpio_out_named(DEVICE(s), s->isa_bus_irqs, "isa-irq",
+ ISA_NUM_IRQS);
 
 /* Serial ports */
 i = 0;
@@ -530,6 +519,18 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
  hwdef->console_serial_base);
 qdev_init_nofail(DEVICE(ebus));
 
+/* Wire up "well-known" ISA IRQs to APB legacy obio IRQs */
+qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 7,
+qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_LPT_IRQ));
+qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 6,
+qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_FDD_IRQ));
+qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 1,
+qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_KBD_IRQ));
+qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 12,
+qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_MSE_IRQ));
+qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 4,
+qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_SER_IRQ));
+
 pci_dev = pci_create_simple(pci_busA, PCI_DEVFN(2, 0), "VGA");
 
 memset(&macaddr, 0, sizeof(MACAddr));
diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h
index dd49437..09ebd53 100644
--- a/include/hw/pci-host/apb.h
+++ b/include/hw/pci-host/apb.h
@@ -52,6 +52,13 @@ typedef struct IOMMUState {
 
 #define MAX_IVEC 0x40
 
+/* OBIO IVEC IRQs */
+#define OBIO_LPT_IRQ 0x22
+#define OBIO_FDD_IRQ 0x27
+#define OBIO_KBD_IRQ 0x29
+#define OBIO_MSE_IRQ 0x2a
+#define OBIO_SER_IRQ 0x2b
+
 #define TYPE_APB "pbm"
 
 #define APB_DEVICE(obj) \
@@ -76,7 +83,6 @@ typedef 

[Qemu-devel] [PATCHv2 11/15] apb: split pci_pbm_map_irq() into separate functions for bus A and bus B

2017-11-26 Thread Mark Cave-Ayland
After the previous refactoring it is now possible to use separate functions
to improve clarity of the interrupt paths. Similarly by checking the PCI
devnfn to identify busA during apb_pci_bridge_realize() it becomes possible
to completely remove the busA property from the PBMPCIBridge state.

Signed-off-by: Mark Cave-Ayland 
---
 hw/pci-host/apb.c |   60 +++--
 include/hw/pci-host/apb.h |3 ---
 2 files changed, 25 insertions(+), 38 deletions(-)

diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 6c20285..d260db3 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -517,32 +517,27 @@ static int pci_apb_map_irq(PCIDevice *pci_dev, int 
irq_num)
 return irq_num;
 }
 
-static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
+static int pci_pbmA_map_irq(PCIDevice *pci_dev, int irq_num)
 {
-PBMPCIBridge *br = PBM_PCI_BRIDGE(pci_bridge_get_device(
-   PCI_BUS(qdev_get_parent_bus(DEVICE(pci_dev);
-
-int bus_offset;
-if (br->busA) {
-bus_offset = 0x0;
+/* The on-board devices have fixed (legacy) OBIO intnos */
+switch (PCI_SLOT(pci_dev->devfn)) {
+case 1:
+/* Onboard NIC */
+return 0x21;
+case 3:
+/* Onboard IDE */
+return 0x20;
+default:
+/* Normal intno, fall through */
+break;
+}
 
-/* The on-board devices have fixed (legacy) OBIO intnos */
-switch (PCI_SLOT(pci_dev->devfn)) {
-case 1:
-/* Onboard NIC */
-return 0x21;
-case 3:
-/* Onboard IDE */
-return 0x20;
+return ((PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f;
+}
 
-default:
-/* Normal intno, fall through */
-break;
-}
-} else {
-bus_offset = 0x10;
-}
-return (bus_offset + (PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f;
+static int pci_pbmB_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+return (0x10 + (PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f;
 }
 
 static void pci_apb_set_irq(void *opaque, int irq_num, int level)
@@ -591,9 +586,11 @@ static void apb_pci_bridge_realize(PCIDevice *dev, Error 
**errp)
 
 pci_bridge_initfn(dev, TYPE_PCI_BUS);
 
-/* If initialising busA, ensure that we allow IO transactions so that
-   we get the early serial console until OpenBIOS configures the bridge */
-if (br->busA) {
+/* If this is the busA PCI bridge which contains the on-board devices
+ * attached to the ebus, ensure that we initially allow IO transactions
+ * so that we get the early serial console until OpenBIOS can properly
+ * configure the PCI bridge itself */
+if (dev->devfn == PCI_DEVFN(1, 1)) {
 cmd |= PCI_COMMAND_IO;
 }
 
@@ -673,14 +670,13 @@ static void pci_pbm_realize(DeviceState *dev, Error 
**errp)
 pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true,
TYPE_PBM_PCI_BRIDGE);
 s->bridgeB = PCI_BRIDGE(pci_dev);
-pci_bridge_map_irq(s->bridgeB, "pciB", pci_pbm_map_irq);
+pci_bridge_map_irq(s->bridgeB, "pciB", pci_pbmB_map_irq);
 qdev_init_nofail(&pci_dev->qdev);
 
 pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 1), true,
TYPE_PBM_PCI_BRIDGE);
 s->bridgeA = PCI_BRIDGE(pci_dev);
-pci_bridge_map_irq(s->bridgeA, "pciA", pci_pbm_map_irq);
-qdev_prop_set_bit(DEVICE(pci_dev), "busA", true);
+pci_bridge_map_irq(s->bridgeA, "pciA", pci_pbmA_map_irq);
 qdev_init_nofail(&pci_dev->qdev);
 }
 
@@ -789,11 +785,6 @@ static const TypeInfo pbm_host_info = {
 .class_init= pbm_host_class_init,
 };
 
-static Property pbm_pci_properties[] = {
-DEFINE_PROP_BOOL("busA", PBMPCIBridge, busA, false),
-DEFINE_PROP_END_OF_LIST(),
-};
-
 static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -809,7 +800,6 @@ static void pbm_pci_bridge_class_init(ObjectClass *klass, 
void *data)
 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
 dc->reset = pci_bridge_reset;
 dc->vmsd = &vmstate_pci_device;
-dc->props = pbm_pci_properties;
 }
 
 static const TypeInfo pbm_pci_bridge_info = {
diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h
index f0074f7..dd49437 100644
--- a/include/hw/pci-host/apb.h
+++ b/include/hw/pci-host/apb.h
@@ -86,9 +86,6 @@ typedef struct APBState {
 typedef struct PBMPCIBridge {
 /*< private >*/
 PCIBridge parent_obj;
-
-/* Is this busA with in-built devices (ebus)? */
-bool busA;
 } PBMPCIBridge;
 
 #define TYPE_PBM_PCI_BRIDGE "pbm-bridge"
-- 
1.7.10.4




[Qemu-devel] [PATCHv2 13/15] apb: replace OBIO interrupt numbers in pci_pbmA_map_irq() with constants

2017-11-26 Thread Mark Cave-Ayland
Following on from the previous commit, we can also do the same with
with legacy OBIO interrupts in pci_pbmA_map_irq().

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Artyom Tarasenko 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/pci-host/apb.c |4 ++--
 include/hw/pci-host/apb.h |2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 7b066fd..54ab899 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -523,10 +523,10 @@ static int pci_pbmA_map_irq(PCIDevice *pci_dev, int 
irq_num)
 switch (PCI_SLOT(pci_dev->devfn)) {
 case 1:
 /* Onboard NIC */
-return 0x21;
+return OBIO_NIC_IRQ;
 case 3:
 /* Onboard IDE */
-return 0x20;
+return OBIO_HDD_IRQ;
 default:
 /* Normal intno, fall through */
 break;
diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h
index 09ebd53..6194c8c 100644
--- a/include/hw/pci-host/apb.h
+++ b/include/hw/pci-host/apb.h
@@ -53,6 +53,8 @@ typedef struct IOMMUState {
 #define MAX_IVEC 0x40
 
 /* OBIO IVEC IRQs */
+#define OBIO_HDD_IRQ 0x20
+#define OBIO_NIC_IRQ 0x21
 #define OBIO_LPT_IRQ 0x22
 #define OBIO_FDD_IRQ 0x27
 #define OBIO_KBD_IRQ 0x29
-- 
1.7.10.4




[Qemu-devel] [PATCHv2 15/15] sun4u: switch from EBUS_DPRINTF() macro to trace-events

2017-11-26 Thread Mark Cave-Ayland
Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/sparc64/sun4u.c  |   12 ++--
 hw/sparc64/trace-events |3 +++
 2 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 1456c33..5d802bd 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -47,17 +47,9 @@
 #include "hw/ide/pci.h"
 #include "hw/loader.h"
 #include "elf.h"
+#include "trace.h"
 #include "qemu/cutils.h"
 
-//#define DEBUG_EBUS
-
-#ifdef DEBUG_EBUS
-#define EBUS_DPRINTF(fmt, ...)  \
-do { printf("EBUS: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define EBUS_DPRINTF(fmt, ...)
-#endif
-
 #define KERNEL_LOAD_ADDR 0x00404000
 #define CMDLINE_ADDR 0x003ff000
 #define PROM_SIZE_MAX(4 * 1024 * 1024)
@@ -218,7 +210,7 @@ static void ebus_isa_irq_handler(void *opaque, int n, int 
level)
 qemu_irq irq = s->isa_bus_irqs[n];
 
 /* Pass ISA bus IRQs onto their gpio equivalent */
-EBUS_DPRINTF("Set ISA IRQ %d level %d\n", n, level);
+trace_ebus_isa_irq_handler(n, level);
 if (irq) {
 qemu_set_irq(irq, level);
 }
diff --git a/hw/sparc64/trace-events b/hw/sparc64/trace-events
index 9284b1f..04d80b7 100644
--- a/hw/sparc64/trace-events
+++ b/hw/sparc64/trace-events
@@ -1 +1,4 @@
 # See docs/devel/tracing.txt for syntax documentation.
+
+# hw/sparc64/sun4u.c
+ebus_isa_irq_handler(int n, int level) "Set ISA IRQ %d level %d"
-- 
1.7.10.4




[Qemu-devel] [PATCHv2 09/15] apb: move the two secondary PCI bridges objects into APBState

2017-11-26 Thread Mark Cave-Ayland
This enables us to remove these parameters from pci_apb_init().

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Artyom Tarasenko 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/pci-host/apb.c |   14 +-
 hw/sparc64/sun4u.c|5 -
 include/hw/pci-host/apb.h |5 +++--
 3 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index c0b97e4..823661a 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -612,8 +612,7 @@ static void apb_pci_bridge_realize(PCIDevice *dev, Error 
**errp)
 }
 
 APBState *pci_apb_init(hwaddr special_base,
-   hwaddr mem_base,
-   PCIBus **busA, PCIBus **busB)
+   hwaddr mem_base)
 {
 DeviceState *dev;
 SysBusDevice *s;
@@ -621,7 +620,6 @@ APBState *pci_apb_init(hwaddr special_base,
 APBState *d;
 IOMMUState *is;
 PCIDevice *pci_dev;
-PCIBridge *br;
 
 /* Ultrasparc PBM main bus */
 dev = qdev_create(NULL, TYPE_APB);
@@ -659,18 +657,16 @@ APBState *pci_apb_init(hwaddr special_base,
 /* APB secondary busses */
 pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true,
TYPE_PBM_PCI_BRIDGE);
-br = PCI_BRIDGE(pci_dev);
-pci_bridge_map_irq(br, "pciB", pci_pbm_map_irq);
+d->bridgeB = PCI_BRIDGE(pci_dev);
+pci_bridge_map_irq(d->bridgeB, "pciB", pci_pbm_map_irq);
 qdev_init_nofail(&pci_dev->qdev);
-*busB = pci_bridge_get_sec_bus(br);
 
 pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 1), true,
TYPE_PBM_PCI_BRIDGE);
-br = PCI_BRIDGE(pci_dev);
-pci_bridge_map_irq(br, "pciA", pci_pbm_map_irq);
+d->bridgeA = PCI_BRIDGE(pci_dev);
+pci_bridge_map_irq(d->bridgeA, "pciA", pci_pbm_map_irq);
 qdev_prop_set_bit(DEVICE(pci_dev), "busA", true);
 qdev_init_nofail(&pci_dev->qdev);
-*busA = pci_bridge_get_sec_bus(br);
 
 return d;
 }
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 2afd3f2..47952be 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -27,6 +27,7 @@
 #include "cpu.h"
 #include "hw/hw.h"
 #include "hw/pci/pci.h"
+#include "hw/pci/pci_bridge.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/pci-host/apb.h"
 #include "hw/i386/pc.h"
@@ -501,7 +502,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
 
 prom_init(hwdef->prom_addr, bios_name);
 
-apb = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, &pci_busA, &pci_busB);
+apb = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE);
 
 /* Wire up PCI interrupts to CPU */
 for (i = 0; i < IVEC_MAX; i++) {
@@ -510,6 +511,8 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
 }
 
 pci_bus = PCI_HOST_BRIDGE(apb)->bus;
+pci_busA = pci_bridge_get_sec_bus(apb->bridgeA);
+pci_busB = pci_bridge_get_sec_bus(apb->bridgeB);
 
 /* Only in-built Simba PBMs can exist on the root bus, slot 0 on busA is
reserved (leaving no slots free after on-board devices) however slots
diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h
index f7ead68..ae15d8c 100644
--- a/include/hw/pci-host/apb.h
+++ b/include/hw/pci-host/apb.h
@@ -68,6 +68,8 @@ typedef struct APBState {
 MemoryRegion pci_ioport;
 uint64_t pci_irq_in;
 IOMMUState iommu;
+PCIBridge *bridgeA;
+PCIBridge *bridgeB;
 uint32_t pci_control[16];
 uint32_t pci_irq_map[8];
 uint32_t pci_err_irq_map[4];
@@ -92,6 +94,5 @@ typedef struct PBMPCIBridge {
 OBJECT_CHECK(PBMPCIBridge, (obj), TYPE_PBM_PCI_BRIDGE)
 
 APBState *pci_apb_init(hwaddr special_base,
-   hwaddr mem_base,
-   PCIBus **bus2, PCIBus **bus3);
+   hwaddr mem_base);
 #endif
-- 
1.7.10.4




[Qemu-devel] [PATCHv2 05/15] sun4u: move initialisation of all ISABus devices into ebus_realize()

2017-11-26 Thread Mark Cave-Ayland
This belongs in the PCI-ISA bridge rather than at the machine level.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/sparc64/sun4u.c |   78 +++-
 1 file changed, 46 insertions(+), 32 deletions(-)

diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index f3203ea..b441f1e 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -85,6 +85,7 @@ typedef struct EbusState {
 PCIDevice parent_obj;
 
 ISABus *isa_bus;
+uint64_t console_serial_base;
 MemoryRegion bar0;
 MemoryRegion bar1;
 } EbusState;
@@ -234,7 +235,10 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp)
 {
 EbusState *s = EBUS(pci_dev);
 APBState *apb;
+DeviceState *dev;
 qemu_irq *isa_irq;
+DriveInfo *fd[MAX_FD];
+int i;
 
 s->isa_bus = isa_bus_new(DEVICE(pci_dev), get_system_memory(),
  pci_address_space_io(pci_dev), errp);
@@ -252,6 +256,38 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp)
 isa_irq = qemu_allocate_irqs(isa_irq_handler, apb->pbm_irqs, 16);
 isa_bus_irqs(s->isa_bus, isa_irq);
 
+/* Serial ports */
+i = 0;
+if (s->console_serial_base) {
+serial_mm_init(pci_address_space(pci_dev), s->console_serial_base,
+   0, NULL, 115200, serial_hds[i], DEVICE_BIG_ENDIAN);
+i++;
+}
+serial_hds_isa_init(s->isa_bus, i, MAX_SERIAL_PORTS);
+
+/* Parallel ports */
+parallel_hds_isa_init(s->isa_bus, MAX_PARALLEL_PORTS);
+
+/* Keyboard */
+isa_create_simple(s->isa_bus, "i8042");
+
+/* Floppy */
+for (i = 0; i < MAX_FD; i++) {
+fd[i] = drive_get(IF_FLOPPY, 0, i);
+}
+dev = DEVICE(isa_create(s->isa_bus, TYPE_ISA_FDC));
+if (fd[0]) {
+qdev_prop_set_drive(dev, "driveA", blk_by_legacy_dinfo(fd[0]),
+&error_abort);
+}
+if (fd[1]) {
+qdev_prop_set_drive(dev, "driveB", blk_by_legacy_dinfo(fd[1]),
+&error_abort);
+}
+qdev_prop_set_uint32(dev, "dma", -1);
+qdev_init_nofail(dev);
+
+/* PCI */
 pci_dev->config[0x04] = 0x06; // command = bus master, pci mem
 pci_dev->config[0x05] = 0x00;
 pci_dev->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no 
error
@@ -267,15 +303,23 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp)
 pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->bar1);
 }
 
+static Property ebus_properties[] = {
+DEFINE_PROP_UINT64("console-serial-base", EbusState,
+   console_serial_base, 0),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static void ebus_class_init(ObjectClass *klass, void *data)
 {
 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+DeviceClass *dc = DEVICE_CLASS(klass);
 
 k->realize = ebus_realize;
 k->vendor_id = PCI_VENDOR_ID_SUN;
 k->device_id = PCI_DEVICE_ID_SUN_EBUS;
 k->revision = 0x01;
 k->class_id = PCI_CLASS_BRIDGE_OTHER;
+dc->props = ebus_properties;
 }
 
 static const TypeInfo ebus_info = {
@@ -440,11 +484,9 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
 uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry;
 PCIBus *pci_bus, *pci_busA, *pci_busB;
 PCIDevice *ebus, *pci_dev;
-ISABus *isa_bus;
 SysBusDevice *s;
 qemu_irq *ivec_irqs;
 DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-DriveInfo *fd[MAX_FD];
 DeviceState *dev;
 FWCfgState *fw_cfg;
 NICInfo *nd;
@@ -471,20 +513,10 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
 pci_busB->slot_reserved_mask = 0xfff0;
 
 ebus = pci_create_multifunction(pci_busA, PCI_DEVFN(1, 0), true, 
TYPE_EBUS);
+qdev_prop_set_uint64(DEVICE(ebus), "console-serial-base",
+ hwdef->console_serial_base);
 qdev_init_nofail(DEVICE(ebus));
 
-isa_bus = EBUS(ebus)->isa_bus;
-
-i = 0;
-if (hwdef->console_serial_base) {
-serial_mm_init(address_space_mem, hwdef->console_serial_base, 0,
-   NULL, 115200, serial_hds[i], DEVICE_BIG_ENDIAN);
-i++;
-}
-
-serial_hds_isa_init(isa_bus, i, MAX_SERIAL_PORTS);
-parallel_hds_isa_init(isa_bus, MAX_PARALLEL_PORTS);
-
 pci_dev = pci_create_simple(pci_busA, PCI_DEVFN(2, 0), "VGA");
 
 memset(&macaddr, 0, sizeof(MACAddr));
@@ -523,24 +555,6 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
 qdev_init_nofail(&pci_dev->qdev);
 pci_ide_create_devs(pci_dev, hd);
 
-isa_create_simple(isa_bus, "i8042");
-
-/* Floppy */
-for(i = 0; i < MAX_FD; i++) {
-fd[i] = drive_get(IF_FLOPPY, 0, i);
-}
-dev = DEVICE(isa_create(isa_bus, TYPE_ISA_FDC));
-if (fd[0]) {
-qdev_prop_set_drive(dev, "driveA", blk_by_legacy_dinfo(fd[0]),
-&error_abort);
-}
-if (fd[1]) {
-qdev_prop_set_drive(dev, "driveB", blk_by_legacy_dinfo(fd[1]),
-  

[Qemu-devel] [PATCHv2 06/15] apb: APB QOMify tidy-up

2017-11-26 Thread Mark Cave-Ayland
Use DeviceClass rather than SysBusDeviceClass in pbm_host_class_init() and
adjust pci_pbm_init_device() accordingly.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/pci-host/apb.c |   17 -
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index b0f80f6..c7837ef 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -705,12 +705,12 @@ static const MemoryRegionOps pci_config_ops = {
 .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
-static int pci_pbm_init_device(SysBusDevice *dev)
+static int pci_pbm_init_device(DeviceState *dev)
 {
-APBState *s;
+APBState *s = APB_DEVICE(dev);
+SysBusDevice *sbd = SYS_BUS_DEVICE(s);
 unsigned int i;
 
-s = APB_DEVICE(dev);
 for (i = 0; i < 8; i++) {
 s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
 }
@@ -728,18 +728,18 @@ static int pci_pbm_init_device(SysBusDevice *dev)
 memory_region_init_io(&s->apb_config, OBJECT(s), &apb_config_ops, s,
   "apb-config", 0x1);
 /* at region 0 */
-sysbus_init_mmio(dev, &s->apb_config);
+sysbus_init_mmio(sbd, &s->apb_config);
 
 memory_region_init_io(&s->pci_config, OBJECT(s), &pci_config_ops, s,
   "apb-pci-config", 0x100);
 /* at region 1 */
-sysbus_init_mmio(dev, &s->pci_config);
+sysbus_init_mmio(sbd, &s->pci_config);
 
 /* pci_ioport */
 memory_region_init(&s->pci_ioport, OBJECT(s), "apb-pci-ioport", 0x100);
 
 /* at region 2 */
-sysbus_init_mmio(dev, &s->pci_ioport);
+sysbus_init_mmio(sbd, &s->pci_ioport);
 
 return 0;
 }
@@ -783,11 +783,10 @@ static const TypeInfo pbm_pci_host_info = {
 static void pbm_host_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
-SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-k->init = pci_pbm_init_device;
-set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
+dc->init = pci_pbm_init_device;
 dc->reset = pci_pbm_reset;
+set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
 }
 
 static const TypeInfo pbm_host_info = {
-- 
1.7.10.4




[Qemu-devel] [PATCHv2 08/15] apb: use gpios to wire up the apb device to the SPARC CPU IRQs

2017-11-26 Thread Mark Cave-Ayland
Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/pci-host/apb.c  |6 ++
 hw/sparc64/sparc64.c   |2 ++
 hw/sparc64/sun4u.c |   12 
 include/hw/pci-host/apb.h  |6 --
 include/hw/sparc/sparc64.h |2 ++
 5 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 0c70999..c0b97e4 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -79,7 +79,6 @@ do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0)
 #define RESET_WCMASK 0x9800
 #define RESET_WMASK  0x6000
 
-#define MAX_IVEC 0x40
 #define NO_IRQ_REQUEST (MAX_IVEC + 1)
 
 static inline void pbm_set_request(APBState *s, unsigned int irq_num)
@@ -614,7 +613,7 @@ static void apb_pci_bridge_realize(PCIDevice *dev, Error 
**errp)
 
 APBState *pci_apb_init(hwaddr special_base,
hwaddr mem_base,
-   qemu_irq *ivec_irqs, PCIBus **busA, PCIBus **busB)
+   PCIBus **busA, PCIBus **busB)
 {
 DeviceState *dev;
 SysBusDevice *s;
@@ -645,8 +644,6 @@ APBState *pci_apb_init(hwaddr special_base,
 memory_region_init(&d->pci_mmio, OBJECT(s), "pci-mmio", 0x1ULL);
 memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio);
 
-d->ivec_irqs = ivec_irqs;
-
 pci_create_simple(phb->bus, 0, "pbm-pci");
 
 /* APB IOMMU */
@@ -721,6 +718,7 @@ static int pci_pbm_init_device(DeviceState *dev)
 s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i;
 }
 s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC);
+qdev_init_gpio_out_named(DEVICE(s), s->ivec_irqs, "ivec-irq", MAX_IVEC);
 s->irq_request = NO_IRQ_REQUEST;
 s->pci_irq_in = 0ULL;
 
diff --git a/hw/sparc64/sparc64.c b/hw/sparc64/sparc64.c
index 9453e2c..95a06f0 100644
--- a/hw/sparc64/sparc64.c
+++ b/hw/sparc64/sparc64.c
@@ -350,6 +350,8 @@ SPARCCPU *sparc64_cpu_devinit(const char *cpu_type, 
uint64_t prom_addr)
 uint32_t hstick_frequency = 100 * 100;
 
 cpu = SPARC_CPU(cpu_create(cpu_type));
+qdev_init_gpio_in_named(DEVICE(cpu), sparc64_cpu_set_ivec_irq,
+"ivec-irq", IVEC_MAX);
 env = &cpu->env;
 
 env->tick = cpu_timer_create("tick", cpu, tick_irq,
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index a64ddc5..2afd3f2 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -486,7 +486,6 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
 PCIBus *pci_bus, *pci_busA, *pci_busB;
 PCIDevice *ebus, *pci_dev;
 SysBusDevice *s;
-qemu_irq *ivec_irqs;
 DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
 DeviceState *dev;
 FWCfgState *fw_cfg;
@@ -502,9 +501,14 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
 
 prom_init(hwdef->prom_addr, bios_name);
 
-ivec_irqs = qemu_allocate_irqs(sparc64_cpu_set_ivec_irq, cpu, IVEC_MAX);
-apb = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_busA,
-   &pci_busB);
+apb = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, &pci_busA, &pci_busB);
+
+/* Wire up PCI interrupts to CPU */
+for (i = 0; i < IVEC_MAX; i++) {
+qdev_connect_gpio_out_named(DEVICE(apb), "ivec-irq", i,
+qdev_get_gpio_in_named(DEVICE(cpu), "ivec-irq", i));
+}
+
 pci_bus = PCI_HOST_BRIDGE(apb)->bus;
 
 /* Only in-built Simba PBMs can exist on the root bus, slot 0 on busA is
diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h
index a4ef51a..f7ead68 100644
--- a/include/hw/pci-host/apb.h
+++ b/include/hw/pci-host/apb.h
@@ -50,6 +50,8 @@ typedef struct IOMMUState {
 uint64_t regs[IOMMU_NREGS];
 } IOMMUState;
 
+#define MAX_IVEC 0x40
+
 #define TYPE_APB "pbm"
 
 #define APB_DEVICE(obj) \
@@ -71,7 +73,7 @@ typedef struct APBState {
 uint32_t pci_err_irq_map[4];
 uint32_t obio_irq_map[32];
 qemu_irq *pbm_irqs;
-qemu_irq *ivec_irqs;
+qemu_irq ivec_irqs[MAX_IVEC];
 unsigned int irq_request;
 uint32_t reset_control;
 unsigned int nr_resets;
@@ -91,5 +93,5 @@ typedef struct PBMPCIBridge {
 
 APBState *pci_apb_init(hwaddr special_base,
hwaddr mem_base,
-   qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3);
+   PCIBus **bus2, PCIBus **bus3);
 #endif
diff --git a/include/hw/sparc/sparc64.h b/include/hw/sparc/sparc64.h
index ca3bb4b..5af4344 100644
--- a/include/hw/sparc/sparc64.h
+++ b/include/hw/sparc/sparc64.h
@@ -1,4 +1,6 @@
 
+#define IVEC_MAX 0x40
+
 SPARCCPU *sparc64_cpu_devinit(const char *cpu_type, uint64_t prom_addr);
 
 void sparc64_cpu_set_ivec_irq(void *opaque, int irq, int level);
-- 
1.7.10.4




[Qemu-devel] [PATCHv2 04/15] sun4u: remove pci_ebus_init() function

2017-11-26 Thread Mark Cave-Ayland
This is initialisation that should really take place in the ebus realize
function. As part of this we also rework the ebus IRQ mapping so that
instead of having to pass in the array of pbm_irqs, we obtain a reference
to them by looking up the APB device during ebus realize.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Artyom Tarasenko 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/pci-host/apb.c |4 +---
 hw/sparc64/sun4u.c|   29 ++---
 include/hw/pci-host/apb.h |3 +--
 3 files changed, 16 insertions(+), 20 deletions(-)

diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index f743a4e..b0f80f6 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -614,8 +614,7 @@ static void apb_pci_bridge_realize(PCIDevice *dev, Error 
**errp)
 
 PCIBus *pci_apb_init(hwaddr special_base,
  hwaddr mem_base,
- qemu_irq *ivec_irqs, PCIBus **busA, PCIBus **busB,
- qemu_irq **pbm_irqs)
+ qemu_irq *ivec_irqs, PCIBus **busA, PCIBus **busB)
 {
 DeviceState *dev;
 SysBusDevice *s;
@@ -646,7 +645,6 @@ PCIBus *pci_apb_init(hwaddr special_base,
 memory_region_init(&d->pci_mmio, OBJECT(s), "pci-mmio", 0x1ULL);
 memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio);
 
-*pbm_irqs = d->pbm_irqs;
 d->ivec_irqs = ivec_irqs;
 
 pci_create_simple(phb->bus, 0, "pbm-pci");
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 63b4aaa..f3203ea 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -230,21 +230,11 @@ static void isa_irq_handler(void *opaque, int n, int 
level)
 }
 
 /* EBUS (Eight bit bus) bridge */
-static ISABus *
-pci_ebus_init(PCIDevice *pci_dev, qemu_irq *irqs)
-{
-qemu_irq *isa_irq;
-ISABus *isa_bus;
-
-isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(pci_dev), "isa.0"));
-isa_irq = qemu_allocate_irqs(isa_irq_handler, irqs, 16);
-isa_bus_irqs(isa_bus, isa_irq);
-return isa_bus;
-}
-
 static void ebus_realize(PCIDevice *pci_dev, Error **errp)
 {
 EbusState *s = EBUS(pci_dev);
+APBState *apb;
+qemu_irq *isa_irq;
 
 s->isa_bus = isa_bus_new(DEVICE(pci_dev), get_system_memory(),
  pci_address_space_io(pci_dev), errp);
@@ -253,6 +243,15 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp)
 return;
 }
 
+apb = APB_DEVICE(object_resolve_path_type("", TYPE_APB, NULL));
+if (!apb) {
+error_setg(errp, "unable to locate APB PCI host bridge");
+return;
+}
+
+isa_irq = qemu_allocate_irqs(isa_irq_handler, apb->pbm_irqs, 16);
+isa_bus_irqs(s->isa_bus, isa_irq);
+
 pci_dev->config[0x04] = 0x06; // command = bus master, pci mem
 pci_dev->config[0x05] = 0x00;
 pci_dev->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no 
error
@@ -443,7 +442,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
 PCIDevice *ebus, *pci_dev;
 ISABus *isa_bus;
 SysBusDevice *s;
-qemu_irq *ivec_irqs, *pbm_irqs;
+qemu_irq *ivec_irqs;
 DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
 DriveInfo *fd[MAX_FD];
 DeviceState *dev;
@@ -462,7 +461,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
 
 ivec_irqs = qemu_allocate_irqs(sparc64_cpu_set_ivec_irq, cpu, IVEC_MAX);
 pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, 
&pci_busA,
-   &pci_busB, &pbm_irqs);
+   &pci_busB);
 
 /* Only in-built Simba PBMs can exist on the root bus, slot 0 on busA is
reserved (leaving no slots free after on-board devices) however slots
@@ -474,7 +473,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
 ebus = pci_create_multifunction(pci_busA, PCI_DEVFN(1, 0), true, 
TYPE_EBUS);
 qdev_init_nofail(DEVICE(ebus));
 
-isa_bus = pci_ebus_init(ebus, pbm_irqs);
+isa_bus = EBUS(ebus)->isa_bus;
 
 i = 0;
 if (hwdef->console_serial_base) {
diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h
index 5d39c03..35d7d5a 100644
--- a/include/hw/pci-host/apb.h
+++ b/include/hw/pci-host/apb.h
@@ -91,6 +91,5 @@ typedef struct PBMPCIBridge {
 
 PCIBus *pci_apb_init(hwaddr special_base,
  hwaddr mem_base,
- qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3,
- qemu_irq **pbm_irqs);
+ qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3);
 #endif
-- 
1.7.10.4




[Qemu-devel] [PATCHv2 03/15] sun4u: move ISABus inside of EBusState

2017-11-26 Thread Mark Cave-Ayland
Since the EBus is effectively a PCI-ISA bridge then the underlying ISA bus
should be contained within the PCI bridge itself.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Artyom Tarasenko 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/sparc64/sun4u.c |7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 394b7d6..63b4aaa 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -84,6 +84,7 @@ typedef struct EbusState {
 /*< private >*/
 PCIDevice parent_obj;
 
+ISABus *isa_bus;
 MemoryRegion bar0;
 MemoryRegion bar1;
 } EbusState;
@@ -245,8 +246,10 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp)
 {
 EbusState *s = EBUS(pci_dev);
 
-if (!isa_bus_new(DEVICE(pci_dev), get_system_memory(),
- pci_address_space_io(pci_dev), errp)) {
+s->isa_bus = isa_bus_new(DEVICE(pci_dev), get_system_memory(),
+ pci_address_space_io(pci_dev), errp);
+if (!s->isa_bus) {
+error_setg(errp, "unable to instantiate EBUS ISA bus");
 return;
 }
 
-- 
1.7.10.4




[Qemu-devel] [PATCHv2 01/15] apb: move QOM macros and typedefs from apb.c to apb.h

2017-11-26 Thread Mark Cave-Ayland
This also includes the related IOMMUState typedef and defines.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Artyom Tarasenko 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/pci-host/apb.c |   85 
 include/hw/pci-host/apb.h |   86 +
 2 files changed, 86 insertions(+), 85 deletions(-)

diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 64025cd..f743a4e 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -82,91 +82,6 @@ do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0)
 #define MAX_IVEC 0x40
 #define NO_IRQ_REQUEST (MAX_IVEC + 1)
 
-#define IOMMU_PAGE_SIZE_8K  (1ULL << 13)
-#define IOMMU_PAGE_MASK_8K  (~(IOMMU_PAGE_SIZE_8K - 1))
-#define IOMMU_PAGE_SIZE_64K (1ULL << 16)
-#define IOMMU_PAGE_MASK_64K (~(IOMMU_PAGE_SIZE_64K - 1))
-
-#define IOMMU_NREGS 3
-
-#define IOMMU_CTRL  0x0
-#define IOMMU_CTRL_TBW_SIZE (1ULL << 2)
-#define IOMMU_CTRL_MMU_EN   (1ULL)
-
-#define IOMMU_CTRL_TSB_SHIFT16
-
-#define IOMMU_BASE  0x8
-#define IOMMU_FLUSH 0x10
-
-#define IOMMU_TTE_DATA_V(1ULL << 63)
-#define IOMMU_TTE_DATA_SIZE (1ULL << 61)
-#define IOMMU_TTE_DATA_W(1ULL << 1)
-
-#define IOMMU_TTE_PHYS_MASK_8K  0x1ffe000ULL
-#define IOMMU_TTE_PHYS_MASK_64K 0x1ff8000ULL
-
-#define IOMMU_TSB_8K_OFFSET_MASK_8M0x007fe000ULL
-#define IOMMU_TSB_8K_OFFSET_MASK_16M   0x00ffe000ULL
-#define IOMMU_TSB_8K_OFFSET_MASK_32M   0x01ffe000ULL
-#define IOMMU_TSB_8K_OFFSET_MASK_64M   0x03ffe000ULL
-#define IOMMU_TSB_8K_OFFSET_MASK_128M  0x07ffe000ULL
-#define IOMMU_TSB_8K_OFFSET_MASK_256M  0x0fffe000ULL
-#define IOMMU_TSB_8K_OFFSET_MASK_512M  0x1fffe000ULL
-#define IOMMU_TSB_8K_OFFSET_MASK_1G0x3fffe000ULL
-
-#define IOMMU_TSB_64K_OFFSET_MASK_64M  0x03ffULL
-#define IOMMU_TSB_64K_OFFSET_MASK_128M 0x07ffULL
-#define IOMMU_TSB_64K_OFFSET_MASK_256M 0x0fffULL
-#define IOMMU_TSB_64K_OFFSET_MASK_512M 0x1fffULL
-#define IOMMU_TSB_64K_OFFSET_MASK_1G   0x3fffULL
-#define IOMMU_TSB_64K_OFFSET_MASK_2G   0x7fffULL
-
-typedef struct IOMMUState {
-AddressSpace iommu_as;
-IOMMUMemoryRegion iommu;
-
-uint64_t regs[IOMMU_NREGS];
-} IOMMUState;
-
-#define TYPE_APB "pbm"
-
-#define APB_DEVICE(obj) \
-OBJECT_CHECK(APBState, (obj), TYPE_APB)
-
-#define TYPE_APB_IOMMU_MEMORY_REGION "pbm-iommu-memory-region"
-
-typedef struct APBState {
-PCIHostState parent_obj;
-
-MemoryRegion apb_config;
-MemoryRegion pci_config;
-MemoryRegion pci_mmio;
-MemoryRegion pci_ioport;
-uint64_t pci_irq_in;
-IOMMUState iommu;
-uint32_t pci_control[16];
-uint32_t pci_irq_map[8];
-uint32_t pci_err_irq_map[4];
-uint32_t obio_irq_map[32];
-qemu_irq *pbm_irqs;
-qemu_irq *ivec_irqs;
-unsigned int irq_request;
-uint32_t reset_control;
-unsigned int nr_resets;
-} APBState;
-
-#define TYPE_PBM_PCI_BRIDGE "pbm-bridge"
-#define PBM_PCI_BRIDGE(obj) \
-OBJECT_CHECK(PBMPCIBridge, (obj), TYPE_PBM_PCI_BRIDGE)
-
-typedef struct PBMPCIBridge {
-/*< private >*/
-PCIBridge parent_obj;
-
-/* Is this busA with in-built devices (ebus)? */
-bool busA;
-} PBMPCIBridge;
-
 static inline void pbm_set_request(APBState *s, unsigned int irq_num)
 {
 APB_DPRINTF("%s: request irq %d\n", __func__, irq_num);
diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h
index b19bd55..5d39c03 100644
--- a/include/hw/pci-host/apb.h
+++ b/include/hw/pci-host/apb.h
@@ -2,6 +2,92 @@
 #define PCI_HOST_APB_H
 
 #include "qemu-common.h"
+#include "hw/pci/pci_host.h"
+
+#define IOMMU_NREGS 3
+
+#define IOMMU_PAGE_SIZE_8K  (1ULL << 13)
+#define IOMMU_PAGE_MASK_8K  (~(IOMMU_PAGE_SIZE_8K - 1))
+#define IOMMU_PAGE_SIZE_64K (1ULL << 16)
+#define IOMMU_PAGE_MASK_64K (~(IOMMU_PAGE_SIZE_64K - 1))
+
+#define IOMMU_CTRL  0x0
+#define IOMMU_CTRL_TBW_SIZE (1ULL << 2)
+#define IOMMU_CTRL_MMU_EN   (1ULL)
+
+#define IOMMU_CTRL_TSB_SHIFT16
+
+#define IOMMU_BASE  0x8
+#define IOMMU_FLUSH 0x10
+
+#define IOMMU_TTE_DATA_V(1ULL << 63)
+#define IOMMU_TTE_DATA_SIZE (1ULL << 61)
+#define IOMMU_TTE_DATA_W(1ULL << 1)
+
+#define IOMMU_TTE_PHYS_MASK_8K  0x1ffe000ULL
+#define IOMMU_TTE_PHYS_MASK_64K 0x1ff8000ULL
+
+#define IOMMU_TSB_8K_OFFSET_MASK_8M0x007fe000ULL
+#define IOMMU_TSB_8K_OFFSET_MASK_16M   0x00ffe000ULL
+#define IOMMU_TSB_8K_OFFSET_MASK_32M   0x01ffe000ULL
+#define IOMMU_TSB_8K_OFFSET_MASK_64M   0x03ffe000ULL
+#define IOMMU_TSB_8K_OFFSET_MASK_128M  0x07ffe000ULL
+#define IOMMU_TSB_8K_OFFSET_MASK_256M  0x0fffe000ULL
+#define IOMMU_TSB_8K_OFFSET_MASK_512M  0x1fffe000ULL
+#define IOMMU_TSB_8K_OFFSET_MASK_1G0x3fffe000UL

[Qemu-devel] [PATCHv2 07/15] apb: return APBState from pci_apb_init() rather than PCIBus

2017-11-26 Thread Mark Cave-Ayland
This is a first step towards removing pci_apb_init() completely.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/pci-host/apb.c |8 
 hw/sparc64/sun4u.c|6 --
 include/hw/pci-host/apb.h |6 +++---
 3 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index c7837ef..0c70999 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -612,9 +612,9 @@ static void apb_pci_bridge_realize(PCIDevice *dev, Error 
**errp)
 pci_bridge_update_mappings(PCI_BRIDGE(br));
 }
 
-PCIBus *pci_apb_init(hwaddr special_base,
- hwaddr mem_base,
- qemu_irq *ivec_irqs, PCIBus **busA, PCIBus **busB)
+APBState *pci_apb_init(hwaddr special_base,
+   hwaddr mem_base,
+   qemu_irq *ivec_irqs, PCIBus **busA, PCIBus **busB)
 {
 DeviceState *dev;
 SysBusDevice *s;
@@ -675,7 +675,7 @@ PCIBus *pci_apb_init(hwaddr special_base,
 qdev_init_nofail(&pci_dev->qdev);
 *busA = pci_bridge_get_sec_bus(br);
 
-return phb->bus;
+return d;
 }
 
 static void pci_pbm_reset(DeviceState *d)
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index b441f1e..a64ddc5 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -482,6 +482,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
 Nvram *nvram;
 unsigned int i;
 uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry;
+APBState *apb;
 PCIBus *pci_bus, *pci_busA, *pci_busB;
 PCIDevice *ebus, *pci_dev;
 SysBusDevice *s;
@@ -502,8 +503,9 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
 prom_init(hwdef->prom_addr, bios_name);
 
 ivec_irqs = qemu_allocate_irqs(sparc64_cpu_set_ivec_irq, cpu, IVEC_MAX);
-pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, 
&pci_busA,
-   &pci_busB);
+apb = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_busA,
+   &pci_busB);
+pci_bus = PCI_HOST_BRIDGE(apb)->bus;
 
 /* Only in-built Simba PBMs can exist on the root bus, slot 0 on busA is
reserved (leaving no slots free after on-board devices) however slots
diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h
index 35d7d5a..a4ef51a 100644
--- a/include/hw/pci-host/apb.h
+++ b/include/hw/pci-host/apb.h
@@ -89,7 +89,7 @@ typedef struct PBMPCIBridge {
 #define PBM_PCI_BRIDGE(obj) \
 OBJECT_CHECK(PBMPCIBridge, (obj), TYPE_PBM_PCI_BRIDGE)
 
-PCIBus *pci_apb_init(hwaddr special_base,
- hwaddr mem_base,
- qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3);
+APBState *pci_apb_init(hwaddr special_base,
+   hwaddr mem_base,
+   qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3);
 #endif
-- 
1.7.10.4




  1   2   >