Re: AST2600 support in QEMU

2022-08-09 Thread Cédric Le Goater

Hello,

On 8/10/22 04:37, Joel Stanley wrote:

Hello Shivi,

I've added others to cc who may have some input.

On Tue, 9 Aug 2022 at 21:38, Shivi Fotedar  wrote:


Hello, we are looking for support for few features for AST2600 in QEMU, 
specifically

PCIe RC support so BMC can talk to downstream devices for management functions.


I haven't seen any PCIe work done yet.


I haven't either. There is clearly a need now that we are moving
away from LPC.


MCTP controller to run MCTP protocol on top of PCIe or I2C.


What work would be required to do this on top of i2c?


I think Jonathan and Klaus worked on this. See :

  https://lore.kernel.org/qemu-devel/20220525121422.3...@huawei.com/


I2C slave so BMC can talk to host CPU QEMU for IPMI


Some support for slave mode was merged in v7.1.


yes.

Peter D. experimented with IPMI. See :

  https://lore.kernel.org/qemu-devel/20220630045133.32251-14...@pjd.dev/

We also merged a new machine including a BMC ast2600 running OpenBMC
and an ast1030 SoC running OpenBIC. Work to interconnect them on the
same I2C bus is in progress.

Thanks,

C.



Re: [PATCH v8 3/3] target/riscv: Add vstimecmp support

2022-08-09 Thread Atish Kumar Patra
On Tue, Aug 9, 2022 at 6:33 PM Weiwei Li  wrote:

>
> 在 2022/8/10 上午3:34, Atish Kumar Patra 写道:
>
>
>
>
> On Tue, Aug 9, 2022 at 12:01 AM Weiwei Li  wrote:
>
>>
>> 在 2022/8/9 上午1:20, Atish Kumar Patra 写道:
>>
>>
>>
>> On Sun, Aug 7, 2022 at 6:50 PM Weiwei Li  wrote:
>>
>>>
>>> 在 2022/8/4 上午9:42, Atish Patra 写道:
>>> > vstimecmp CSR allows the guest OS or to program the next guest timer
>>> > interrupt directly. Thus, hypervisor no longer need to inject the
>>> > timer interrupt to the guest if vstimecmp is used. This was ratified
>>> > as a part of the Sstc extension.
>>> >
>>> > Signed-off-by: Atish Patra 
>>> > ---
>>> >   target/riscv/cpu.h |   4 ++
>>> >   target/riscv/cpu_bits.h|   4 ++
>>> >   target/riscv/cpu_helper.c  |  11 ++--
>>> >   target/riscv/csr.c | 102
>>> -
>>> >   target/riscv/machine.c |   1 +
>>> >   target/riscv/time_helper.c |  16 ++
>>> >   6 files changed, 133 insertions(+), 5 deletions(-)
>>> >
>>> > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
>>> > index 4cda2905661e..1fd382b2717f 100644
>>> > --- a/target/riscv/cpu.h
>>> > +++ b/target/riscv/cpu.h
>>> > @@ -312,6 +312,8 @@ struct CPUArchState {
>>> >   /* Sstc CSRs */
>>> >   uint64_t stimecmp;
>>> >
>>> > +uint64_t vstimecmp;
>>> > +
>>> >   /* physical memory protection */
>>> >   pmp_table_t pmp_state;
>>> >   target_ulong mseccfg;
>>> > @@ -366,6 +368,8 @@ struct CPUArchState {
>>> >
>>> >   /* Fields from here on are preserved across CPU reset. */
>>> >   QEMUTimer *stimer; /* Internal timer for S-mode interrupt */
>>> > +QEMUTimer *vstimer; /* Internal timer for VS-mode interrupt */
>>> > +bool vstime_irq;
>>> >
>>> >   hwaddr kernel_addr;
>>> >   hwaddr fdt_addr;
>>> > diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
>>> > index ac17cf1515c0..095dab19f512 100644
>>> > --- a/target/riscv/cpu_bits.h
>>> > +++ b/target/riscv/cpu_bits.h
>>> > @@ -257,6 +257,10 @@
>>> >   #define CSR_VSIP0x244
>>> >   #define CSR_VSATP   0x280
>>> >
>>> > +/* Sstc virtual CSRs */
>>> > +#define CSR_VSTIMECMP   0x24D
>>> > +#define CSR_VSTIMECMPH  0x25D
>>> > +
>>> >   #define CSR_MTINST  0x34a
>>> >   #define CSR_MTVAL2  0x34b
>>> >
>>> > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
>>> > index 650574accf0a..1e4faa84e839 100644
>>> > --- a/target/riscv/cpu_helper.c
>>> > +++ b/target/riscv/cpu_helper.c
>>> > @@ -345,8 +345,9 @@ uint64_t riscv_cpu_all_pending(CPURISCVState *env)
>>> >   {
>>> >   uint32_t gein = get_field(env->hstatus, HSTATUS_VGEIN);
>>> >   uint64_t vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
>>> > +uint64_t vstip = (env->vstime_irq) ? MIP_VSTIP : 0;
>>> >
>>> > -return (env->mip | vsgein) & env->mie;
>>> > +return (env->mip | vsgein | vstip) & env->mie;
>>> >   }
>>> >
>>> >   int riscv_cpu_mirq_pending(CPURISCVState *env)
>>> > @@ -605,7 +606,7 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu,
>>> uint64_t mask, uint64_t value)
>>> >   {
>>> >   CPURISCVState *env = >env;
>>> >   CPUState *cs = CPU(cpu);
>>> > -uint64_t gein, vsgein = 0, old = env->mip;
>>> > +uint64_t gein, vsgein = 0, vstip = 0, old = env->mip;
>>> >   bool locked = false;
>>> >
>>> >   if (riscv_cpu_virt_enabled(env)) {
>>> > @@ -613,6 +614,10 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu,
>>> uint64_t mask, uint64_t value)
>>> >   vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
>>> >   }
>>> >
>>> > +/* No need to update mip for VSTIP */
>>> > +mask = ((mask == MIP_VSTIP) && env->vstime_irq) ? 0 : mask;
>>> > +vstip = env->vstime_irq ? MIP_VSTIP : 0;
>>> > +
>>> >   if (!qemu_mutex_iothread_locked()) {
>>> >   locked = true;
>>> >   qemu_mutex_lock_iothread();
>>> > @@ -620,7 +625,7 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu,
>>> uint64_t mask, uint64_t value)
>>> >
>>> >   env->mip = (env->mip & ~mask) | (value & mask);
>>> >
>>> > -if (env->mip | vsgein) {
>>> > +if (env->mip | vsgein | vstip) {
>>> >   cpu_interrupt(cs, CPU_INTERRUPT_HARD);
>>> >   } else {
>>> >   cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
>>> > diff --git a/target/riscv/csr.c b/target/riscv/csr.c
>>> > index e18b000700e4..9da4d6515e7b 100644
>>> > --- a/target/riscv/csr.c
>>> > +++ b/target/riscv/csr.c
>>> > @@ -829,17 +829,100 @@ static RISCVException sstc(CPURISCVState *env,
>>> int csrno)
>>> >   return smode(env, csrno);
>>> >   }
>>> >
>>> > +static RISCVException sstc_hmode(CPURISCVState *env, int csrno)
>>> > +{
>>> > +CPUState *cs = env_cpu(env);
>>> > +RISCVCPU *cpu = RISCV_CPU(cs);
>>> > +
>>> > +if (!cpu->cfg.ext_sstc || !env->rdtime_fn) {
>>> > +return RISCV_EXCP_ILLEGAL_INST;
>>> > +}
>>> > +
>>> > +if (env->priv == PRV_M) {
>>> > +return RISCV_EXCP_NONE;
>>> > +}
>>> > +
>>> > +if 

Re: [PATCH v8 10/12] vhost_net: add NetClientState->load() callback

2022-08-09 Thread Jason Wang
On Wed, Aug 10, 2022 at 1:40 AM Eugenio Pérez  wrote:
>
> It allows per-net client operations right after device's successful
> start. In particular, to load the device status.
>
> Vhost-vdpa net will use it to add the CVQ buffers to restore the device
> status.
>
> Signed-off-by: Eugenio Pérez 

Acked-by: Jason Wang 

> ---
> v5: Rename start / load, naming it more specifically.
> ---
>  include/net/net.h  | 2 ++
>  hw/net/vhost_net.c | 7 +++
>  2 files changed, 9 insertions(+)
>
> diff --git a/include/net/net.h b/include/net/net.h
> index 476ad45b9a..81d0b21def 100644
> --- a/include/net/net.h
> +++ b/include/net/net.h
> @@ -45,6 +45,7 @@ typedef struct NICConf {
>  typedef void (NetPoll)(NetClientState *, bool enable);
>  typedef bool (NetCanReceive)(NetClientState *);
>  typedef int (NetStart)(NetClientState *);
> +typedef int (NetLoad)(NetClientState *);
>  typedef void (NetStop)(NetClientState *);
>  typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t);
>  typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int);
> @@ -74,6 +75,7 @@ typedef struct NetClientInfo {
>  NetReceiveIOV *receive_iov;
>  NetCanReceive *can_receive;
>  NetStart *start;
> +NetLoad *load;
>  NetStop *stop;
>  NetCleanup *cleanup;
>  LinkStatusChanged *link_status_changed;
> diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> index 9d4b334453..d28f8b974b 100644
> --- a/hw/net/vhost_net.c
> +++ b/hw/net/vhost_net.c
> @@ -281,6 +281,13 @@ static int vhost_net_start_one(struct vhost_net *net,
>  }
>  }
>  }
> +
> +if (net->nc->info->load) {
> +r = net->nc->info->load(net->nc);
> +if (r < 0) {
> +goto fail;
> +}
> +}
>  return 0;
>  fail:
>  file.fd = -1;
> --
> 2.31.1
>




Re: [PATCH v8 07/12] vdpa: add net_vhost_vdpa_cvq_info NetClientInfo

2022-08-09 Thread Jason Wang
On Wed, Aug 10, 2022 at 1:39 AM Eugenio Pérez  wrote:
>
> Next patches will add a new info callback to restore NIC status through
> CVQ. Since only the CVQ vhost device is needed, create it with a new
> NetClientInfo.
>
> Signed-off-by: Eugenio Pérez 

Acked-by: Jason Wang 

> ---
> v5: Create a new NetClientInfo instead of reusing the dataplane one.
> ---
>  net/vhost-vdpa.c | 12 +++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
> index ac1810723c..55e8a39a56 100644
> --- a/net/vhost-vdpa.c
> +++ b/net/vhost-vdpa.c
> @@ -334,6 +334,16 @@ static bool vhost_vdpa_net_cvq_map_elem(VhostVDPAState 
> *s,
>  return true;
>  }
>
> +static NetClientInfo net_vhost_vdpa_cvq_info = {
> +.type = NET_CLIENT_DRIVER_VHOST_VDPA,
> +.size = sizeof(VhostVDPAState),
> +.receive = vhost_vdpa_receive,
> +.cleanup = vhost_vdpa_cleanup,
> +.has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
> +.has_ufo = vhost_vdpa_has_ufo,
> +.check_peer_type = vhost_vdpa_check_peer_type,
> +};
> +
>  /**
>   * Do not forward commands not supported by SVQ. Otherwise, the device could
>   * accept it and qemu would not know how to update the device model.
> @@ -475,7 +485,7 @@ static NetClientState *net_vhost_vdpa_init(NetClientState 
> *peer,
>  nc = qemu_new_net_client(_vhost_vdpa_info, peer, device,
>   name);
>  } else {
> -nc = qemu_new_net_control_client(_vhost_vdpa_info, peer,
> +nc = qemu_new_net_control_client(_vhost_vdpa_cvq_info, peer,
>   device, name);
>  }
>  snprintf(nc->info_str, sizeof(nc->info_str), TYPE_VHOST_VDPA);
> --
> 2.31.1
>




Re: [PATCH v8 11/12] vdpa: Add virtio-net mac address via CVQ at start

2022-08-09 Thread Jason Wang
On Wed, Aug 10, 2022 at 1:40 AM Eugenio Pérez  wrote:
>
> This is needed so the destination vdpa device see the same state a the
> guest set in the source.
>
> Signed-off-by: Eugenio Pérez 
> ---
> v8:
> * Delete unneeded copy from device's in buffer.
>
> v6:
> * Map and unmap command buffers at the start and end of device usage.
>
> v5:
> * Rename s/start/load/
> * Use independent NetClientInfo to only add load callback on cvq.
> ---
>  net/vhost-vdpa.c | 41 +
>  1 file changed, 41 insertions(+)
>
> diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
> index df85567cff..e775957952 100644
> --- a/net/vhost-vdpa.c
> +++ b/net/vhost-vdpa.c
> @@ -363,11 +363,52 @@ static ssize_t vhost_vdpa_net_cvq_add(VhostVDPAState 
> *s, size_t out_len,
>  return vhost_svq_poll(svq);
>  }
>
> +static int vhost_vdpa_net_load(NetClientState *nc)
> +{
> +VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> +struct vhost_vdpa *v = >vhost_vdpa;
> +VirtIONet *n;
> +uint64_t features;
> +
> +assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
> +
> +if (!v->shadow_vqs_enabled) {
> +return 0;
> +}
> +
> +n = VIRTIO_NET(v->dev->vdev);
> +features = v->dev->vdev->host_features;
> +if (features & BIT_ULL(VIRTIO_NET_F_CTRL_MAC_ADDR)) {
> +const struct virtio_net_ctrl_hdr ctrl = {
> +.class = VIRTIO_NET_CTRL_MAC,
> +.cmd = VIRTIO_NET_CTRL_MAC_ADDR_SET,
> +};
> +char *cursor = s->cvq_cmd_out_buffer;
> +ssize_t dev_written;
> +
> +memcpy(cursor, , sizeof(ctrl));
> +cursor += sizeof(ctrl);
> +memcpy(cursor, n->mac, sizeof(n->mac));
> +cursor += sizeof(n->mac);

I'd cast and initialize directly from the cmd_out_buff. But this could
be done on top.

So

Acked-by: Jason Wang 


> +
> +dev_written = vhost_vdpa_net_cvq_add(s, sizeof(ctrl) + 
> sizeof(n->mac),
> + sizeof(virtio_net_ctrl_ack));
> +if (unlikely(dev_written < 0)) {
> +return dev_written;
> +}
> +
> +return *((virtio_net_ctrl_ack *)s->cvq_cmd_in_buffer) != 
> VIRTIO_NET_OK;
> +}
> +
> +return 0;
> +}
> +
>  static NetClientInfo net_vhost_vdpa_cvq_info = {
>  .type = NET_CLIENT_DRIVER_VHOST_VDPA,
>  .size = sizeof(VhostVDPAState),
>  .receive = vhost_vdpa_receive,
>  .start = vhost_vdpa_net_cvq_start,
> +.load = vhost_vdpa_net_load,
>  .stop = vhost_vdpa_net_cvq_stop,
>  .cleanup = vhost_vdpa_cleanup,
>  .has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
> --
> 2.31.1
>




Re: [PATCH v8 06/12] vhost_net: Add NetClientInfo stop callback

2022-08-09 Thread Jason Wang
On Wed, Aug 10, 2022 at 1:39 AM Eugenio Pérez  wrote:
>
> Used by the backend to perform actions after the device is stopped.
>
> In particular, vdpa net use it to unmap CVQ buffers to the device,
> cleaning the actions performend in prepare().

Should be "performed".

Other than this,

Acked-by: Jason Wang 

>
> Signed-off-by: Eugenio Pérez 
> ---
>  include/net/net.h  | 2 ++
>  hw/net/vhost_net.c | 3 +++
>  2 files changed, 5 insertions(+)
>
> diff --git a/include/net/net.h b/include/net/net.h
> index ad9e80083a..476ad45b9a 100644
> --- a/include/net/net.h
> +++ b/include/net/net.h
> @@ -45,6 +45,7 @@ typedef struct NICConf {
>  typedef void (NetPoll)(NetClientState *, bool enable);
>  typedef bool (NetCanReceive)(NetClientState *);
>  typedef int (NetStart)(NetClientState *);
> +typedef void (NetStop)(NetClientState *);
>  typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t);
>  typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int);
>  typedef void (NetCleanup) (NetClientState *);
> @@ -73,6 +74,7 @@ typedef struct NetClientInfo {
>  NetReceiveIOV *receive_iov;
>  NetCanReceive *can_receive;
>  NetStart *start;
> +NetStop *stop;
>  NetCleanup *cleanup;
>  LinkStatusChanged *link_status_changed;
>  QueryRxFilter *query_rx_filter;
> diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> index 2e0baeba26..9d4b334453 100644
> --- a/hw/net/vhost_net.c
> +++ b/hw/net/vhost_net.c
> @@ -320,6 +320,9 @@ static void vhost_net_stop_one(struct vhost_net *net,
>  net->nc->info->poll(net->nc, true);
>  }
>  vhost_dev_stop(>dev, dev);
> +if (net->nc->info->stop) {
> +net->nc->info->stop(net->nc);
> +}
>  vhost_dev_disable_notifiers(>dev, dev);
>  }
>
> --
> 2.31.1
>




Re: [PATCH v8 08/12] vdpa: Move command buffers map to start of net device

2022-08-09 Thread Jason Wang
On Wed, Aug 10, 2022 at 1:39 AM Eugenio Pérez  wrote:
>
> As this series will reuse them to restore the device state at the end of
> a migration (or a device start), let's allocate only once at the device
> start so we don't duplicate their map and unmap.
>
> Signed-off-by: Eugenio Pérez 

Acked-by: Jason Wang 

> ---
>  net/vhost-vdpa.c | 123 ++-
>  1 file changed, 58 insertions(+), 65 deletions(-)
>
> diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
> index 55e8a39a56..5254b58bdc 100644
> --- a/net/vhost-vdpa.c
> +++ b/net/vhost-vdpa.c
> @@ -263,29 +263,20 @@ static size_t vhost_vdpa_net_cvq_cmd_page_len(void)
>  return ROUND_UP(vhost_vdpa_net_cvq_cmd_len(), 
> qemu_real_host_page_size());
>  }
>
> -/** Copy and map a guest buffer. */
> -static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v,
> -   const struct iovec *out_data,
> -   size_t out_num, size_t data_len, void 
> *buf,
> -   size_t *written, bool write)
> +/** Map CVQ buffer. */
> +static int vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, void *buf, size_t 
> size,
> +  bool write)
>  {
>  DMAMap map = {};
>  int r;
>
> -if (unlikely(!data_len)) {
> -qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid legnth of %s buffer\n",
> -  __func__, write ? "in" : "out");
> -return false;
> -}
> -
> -*written = iov_to_buf(out_data, out_num, 0, buf, data_len);
>  map.translated_addr = (hwaddr)(uintptr_t)buf;
> -map.size = vhost_vdpa_net_cvq_cmd_page_len() - 1;
> +map.size = size - 1;
>  map.perm = write ? IOMMU_RW : IOMMU_RO,
>  r = vhost_iova_tree_map_alloc(v->iova_tree, );
>  if (unlikely(r != IOVA_OK)) {
>  error_report("Cannot map injected element");
> -return false;
> +return r;
>  }
>
>  r = vhost_vdpa_dma_map(v, map.iova, vhost_vdpa_net_cvq_cmd_page_len(), 
> buf,
> @@ -294,50 +285,58 @@ static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v,
>  goto dma_map_err;
>  }
>
> -return true;
> +return 0;
>
>  dma_map_err:
>  vhost_iova_tree_remove(v->iova_tree, );
> -return false;
> +return r;
>  }
>
> -/**
> - * Copy the guest element into a dedicated buffer suitable to be sent to NIC
> - *
> - * @iov: [0] is the out buffer, [1] is the in one
> - */
> -static bool vhost_vdpa_net_cvq_map_elem(VhostVDPAState *s,
> -VirtQueueElement *elem,
> -struct iovec *iov)
> +static int vhost_vdpa_net_cvq_start(NetClientState *nc)
>  {
> -size_t in_copied;
> -bool ok;
> +VhostVDPAState *s;
> +int r;
>
> -iov[0].iov_base = s->cvq_cmd_out_buffer;
> -ok = vhost_vdpa_cvq_map_buf(>vhost_vdpa, elem->out_sg, elem->out_num,
> -vhost_vdpa_net_cvq_cmd_len(), 
> iov[0].iov_base,
> -[0].iov_len, false);
> -if (unlikely(!ok)) {
> -return false;
> +assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
> +
> +s = DO_UPCAST(VhostVDPAState, nc, nc);
> +if (!s->vhost_vdpa.shadow_vqs_enabled) {
> +return 0;
>  }
>
> -iov[1].iov_base = s->cvq_cmd_in_buffer;
> -ok = vhost_vdpa_cvq_map_buf(>vhost_vdpa, NULL, 0,
> -sizeof(virtio_net_ctrl_ack), iov[1].iov_base,
> -_copied, true);
> -if (unlikely(!ok)) {
> +r = vhost_vdpa_cvq_map_buf(>vhost_vdpa, s->cvq_cmd_out_buffer,
> +   vhost_vdpa_net_cvq_cmd_page_len(), false);
> +if (unlikely(r < 0)) {
> +return r;
> +}
> +
> +r = vhost_vdpa_cvq_map_buf(>vhost_vdpa, s->cvq_cmd_in_buffer,
> +   vhost_vdpa_net_cvq_cmd_page_len(), true);
> +if (unlikely(r < 0)) {
>  vhost_vdpa_cvq_unmap_buf(>vhost_vdpa, s->cvq_cmd_out_buffer);
> -return false;
>  }
>
> -iov[1].iov_len = sizeof(virtio_net_ctrl_ack);
> -return true;
> +return r;
> +}
> +
> +static void vhost_vdpa_net_cvq_stop(NetClientState *nc)
> +{
> +VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> +
> +assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
> +
> +if (s->vhost_vdpa.shadow_vqs_enabled) {
> +vhost_vdpa_cvq_unmap_buf(>vhost_vdpa, s->cvq_cmd_out_buffer);
> +vhost_vdpa_cvq_unmap_buf(>vhost_vdpa, s->cvq_cmd_in_buffer);
> +}
>  }
>
>  static NetClientInfo net_vhost_vdpa_cvq_info = {
>  .type = NET_CLIENT_DRIVER_VHOST_VDPA,
>  .size = sizeof(VhostVDPAState),
>  .receive = vhost_vdpa_receive,
> +.start = vhost_vdpa_net_cvq_start,
> +.stop = vhost_vdpa_net_cvq_stop,
>  .cleanup = vhost_vdpa_cleanup,
>  .has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
>  .has_ufo = vhost_vdpa_has_ufo,
> @@ -348,19 +347,17 @@ static NetClientInfo 

Re: [PATCH v8 05/12] vhost_net: Add NetClientInfo prepare callback

2022-08-09 Thread Jason Wang
On Wed, Aug 10, 2022 at 1:39 AM Eugenio Pérez  wrote:
>
> This is used by the backend to perform actions before the device is
> started.
>
> In particular, vdpa net use it to map CVQ buffers to the device, so it
> can send control commands using them.
>
> Signed-off-by: Eugenio Pérez 
> ---

So the title still calls it "prepare".

Other than this.

Acked-by: Jason Wang 

> v8: Rename NetClientInfo prepare callback to start, so it aligns with
> future "stop"
> ---
>  include/net/net.h  | 2 ++
>  hw/net/vhost_net.c | 7 +++
>  2 files changed, 9 insertions(+)
>
> diff --git a/include/net/net.h b/include/net/net.h
> index 523136c7ac..ad9e80083a 100644
> --- a/include/net/net.h
> +++ b/include/net/net.h
> @@ -44,6 +44,7 @@ typedef struct NICConf {
>
>  typedef void (NetPoll)(NetClientState *, bool enable);
>  typedef bool (NetCanReceive)(NetClientState *);
> +typedef int (NetStart)(NetClientState *);
>  typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t);
>  typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int);
>  typedef void (NetCleanup) (NetClientState *);
> @@ -71,6 +72,7 @@ typedef struct NetClientInfo {
>  NetReceive *receive_raw;
>  NetReceiveIOV *receive_iov;
>  NetCanReceive *can_receive;
> +NetStart *start;
>  NetCleanup *cleanup;
>  LinkStatusChanged *link_status_changed;
>  QueryRxFilter *query_rx_filter;
> diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> index ccac5b7a64..2e0baeba26 100644
> --- a/hw/net/vhost_net.c
> +++ b/hw/net/vhost_net.c
> @@ -244,6 +244,13 @@ static int vhost_net_start_one(struct vhost_net *net,
>  struct vhost_vring_file file = { };
>  int r;
>
> +if (net->nc->info->start) {
> +r = net->nc->info->start(net->nc);
> +if (r < 0) {
> +return r;
> +}
> +}
> +
>  r = vhost_dev_enable_notifiers(>dev, dev);
>  if (r < 0) {
>  goto fail_notifiers;
> --
> 2.31.1
>




Re: AST2600 support in QEMU

2022-08-09 Thread Joel Stanley
Hello Shivi,

I've added others to cc who may have some input.

On Tue, 9 Aug 2022 at 21:38, Shivi Fotedar  wrote:
>
> Hello, we are looking for support for few features for AST2600 in QEMU, 
> specifically
>
> PCIe RC support so BMC can talk to downstream devices for management 
> functions.

I haven't seen any PCIe work done yet.

> MCTP controller to run MCTP protocol on top of PCIe or I2C.

What work would be required to do this on top of i2c?

> I2C slave so BMC can talk to host CPU QEMU for IPMI

Some support for slave mode was merged in v7.1.

Cheers,

Joel



Re: [PATCH v8 3/3] target/riscv: Add vstimecmp support

2022-08-09 Thread Weiwei Li


在 2022/8/10 上午3:34, Atish Kumar Patra 写道:




On Tue, Aug 9, 2022 at 12:01 AM Weiwei Li > wrote:



在 2022/8/9 上午1:20, Atish Kumar Patra 写道:



On Sun, Aug 7, 2022 at 6:50 PM Weiwei Li mailto:liwei...@iscas.ac.cn>> wrote:


在 2022/8/4 上午9:42, Atish Patra 写道:
> vstimecmp CSR allows the guest OS or to program the next
guest timer
> interrupt directly. Thus, hypervisor no longer need to
inject the
> timer interrupt to the guest if vstimecmp is used. This was
ratified
> as a part of the Sstc extension.
>
> Signed-off-by: Atish Patra mailto:ati...@rivosinc.com>>
> ---
>   target/riscv/cpu.h         |   4 ++
>   target/riscv/cpu_bits.h    |   4 ++
>   target/riscv/cpu_helper.c  |  11 ++--
>   target/riscv/csr.c         | 102
-
>   target/riscv/machine.c     |   1 +
>   target/riscv/time_helper.c |  16 ++
>   6 files changed, 133 insertions(+), 5 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 4cda2905661e..1fd382b2717f 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -312,6 +312,8 @@ struct CPUArchState {
>       /* Sstc CSRs */
>       uint64_t stimecmp;
>
> +    uint64_t vstimecmp;
> +
>       /* physical memory protection */
>       pmp_table_t pmp_state;
>       target_ulong mseccfg;
> @@ -366,6 +368,8 @@ struct CPUArchState {
>
>       /* Fields from here on are preserved across CPU reset. */
>       QEMUTimer *stimer; /* Internal timer for S-mode
interrupt */
> +    QEMUTimer *vstimer; /* Internal timer for VS-mode
interrupt */
> +    bool vstime_irq;
>
>       hwaddr kernel_addr;
>       hwaddr fdt_addr;
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index ac17cf1515c0..095dab19f512 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -257,6 +257,10 @@
>   #define CSR_VSIP            0x244
>   #define CSR_VSATP           0x280
>
> +/* Sstc virtual CSRs */
> +#define CSR_VSTIMECMP       0x24D
> +#define CSR_VSTIMECMPH      0x25D
> +
>   #define CSR_MTINST          0x34a
>   #define CSR_MTVAL2          0x34b
>
> diff --git a/target/riscv/cpu_helper.c
b/target/riscv/cpu_helper.c
> index 650574accf0a..1e4faa84e839 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -345,8 +345,9 @@ uint64_t
riscv_cpu_all_pending(CPURISCVState *env)
>   {
>       uint32_t gein = get_field(env->hstatus, HSTATUS_VGEIN);
>       uint64_t vsgein = (env->hgeip & (1ULL << gein)) ?
MIP_VSEIP : 0;
> +    uint64_t vstip = (env->vstime_irq) ? MIP_VSTIP : 0;
>
> -    return (env->mip | vsgein) & env->mie;
> +    return (env->mip | vsgein | vstip) & env->mie;
>   }
>
>   int riscv_cpu_mirq_pending(CPURISCVState *env)
> @@ -605,7 +606,7 @@ uint64_t riscv_cpu_update_mip(RISCVCPU
*cpu, uint64_t mask, uint64_t value)
>   {
>       CPURISCVState *env = >env;
>       CPUState *cs = CPU(cpu);
> -    uint64_t gein, vsgein = 0, old = env->mip;
> +    uint64_t gein, vsgein = 0, vstip = 0, old = env->mip;
>       bool locked = false;
>
>       if (riscv_cpu_virt_enabled(env)) {
> @@ -613,6 +614,10 @@ uint64_t riscv_cpu_update_mip(RISCVCPU
*cpu, uint64_t mask, uint64_t value)
>           vsgein = (env->hgeip & (1ULL << gein)) ?
MIP_VSEIP : 0;
>       }
>
> +    /* No need to update mip for VSTIP */
> +    mask = ((mask == MIP_VSTIP) && env->vstime_irq) ? 0 :
mask;
> +    vstip = env->vstime_irq ? MIP_VSTIP : 0;
> +
>       if (!qemu_mutex_iothread_locked()) {
>           locked = true;
>           qemu_mutex_lock_iothread();
> @@ -620,7 +625,7 @@ uint64_t riscv_cpu_update_mip(RISCVCPU
*cpu, uint64_t mask, uint64_t value)
>
>       env->mip = (env->mip & ~mask) | (value & mask);
>
> -    if (env->mip | vsgein) {
> +    if (env->mip | vsgein | vstip) {
>           cpu_interrupt(cs, CPU_INTERRUPT_HARD);
>       } else {
>           cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index e18b000700e4..9da4d6515e7b 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -829,17 +829,100 @@ 

[PATCH for-7.1] cutils: Add missing dyld(3) include on macOS

2022-08-09 Thread Philippe Mathieu-Daudé via
Commit 06680b15b4 moved qemu_*_exec_dir() to cutils but forgot
to move the macOS dyld(3) include, resulting in the following
error (when building with Homebrew GCC on macOS Monterey 12.4):

  [313/1197] Compiling C object libqemuutil.a.p/util_cutils.c.o
  FAILED: libqemuutil.a.p/util_cutils.c.o
  ../../util/cutils.c:1039:13: error: implicit declaration of function 
'_NSGetExecutablePath' [-Werror=implicit-function-declaration]
   1039 | if (_NSGetExecutablePath(fpath, ) == 0) {
| ^~~~
  ../../util/cutils.c:1039:13: error: nested extern declaration of 
'_NSGetExecutablePath' [-Werror=nested-externs]

Fix by moving the include line to cutils.

Fixes: 06680b15b4 ("include: move qemu_*_exec_dir() to cutils")
Signed-off-by: Philippe Mathieu-Daudé 
---
Cc: Marc-André Lureau 
Cc: Markus Armbruster 
---
 util/cutils.c  | 4 
 util/oslib-posix.c | 4 
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/util/cutils.c b/util/cutils.c
index cb43dda213..def9c746ce 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -39,6 +39,10 @@
 #include 
 #endif
 
+#ifdef __APPLE__
+#include 
+#endif
+
 #ifdef G_OS_WIN32
 #include 
 #include 
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index bffec18869..d55af69c11 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -58,10 +58,6 @@
 #include 
 #endif
 
-#ifdef __APPLE__
-#include 
-#endif
-
 #include "qemu/mmap-alloc.h"
 
 #ifdef CONFIG_DEBUG_STACK_USAGE
-- 
2.36.1




Re: [PULL 0/2] Trivial branch for 7.1 patches

2022-08-09 Thread Richard Henderson

On 8/9/22 09:55, Laurent Vivier wrote:

The following changes since commit c669f22f1a47897e8d1d595d6b8a59a572f9158c:

   Merge tag 'pull-la-20220805' of https://gitlab.com/rth7680/qemu into staging 
(2022-08-05 12:55:53 -0700)

are available in the Git repository at:

   https://gitlab.com/laurent_vivier/qemu.git 
tags/trivial-branch-for-7.1-pull-request

for you to fetch changes up to 9390da5ef29a5e0f98e5b482dceeeb287c452f17:

   xlnx_dp: drop unsupported AUXCommand in xlnx_dp_aux_set_command (2022-08-08 
11:40:06 +0200)


Pull request trivial branch 20220809


Applied, thanks.  Please update https://wiki.qemu.org/ChangeLog/7.1 as 
appropriate.


r~






Markus Armbruster (1):
   contrib/vhost-user-blk: Clean up deallocation of VuVirtqElement

Qiang Liu (1):
   xlnx_dp: drop unsupported AUXCommand in xlnx_dp_aux_set_command

  contrib/vhost-user-blk/vhost-user-blk.c | 9 +++--
  hw/display/xlnx_dp.c| 4 ++--
  2 files changed, 5 insertions(+), 8 deletions(-)






AST2600 support in QEMU

2022-08-09 Thread Shivi Fotedar
Hello, we are looking for support for few features for AST2600 in QEMU, 
specifically

  *   PCIe RC support so BMC can talk to downstream devices for management 
functions.
  *   MCTP controller to run MCTP protocol on top of PCIe or I2C.
  *   I2C slave so BMC can talk to host CPU QEMU for IPMI

Can someone let us know if there is effort going on these areas? Appreciate any 
help here.

Thanks


Re: [PATCH v3 3/5] hw/core: use qemu_fdt_setprop_strings()

2022-08-09 Thread Peter Maydell
On Tue, 9 Aug 2022 at 19:50, Ben Dooks  wrote:
>
> On Mon, Aug 01, 2022 at 12:30:22PM +0100, Peter Maydell wrote:
> > On Wed, 27 Jul 2022 at 23:39, Ben Dooks  wrote:
> > >
> > > Change to using the qemu_fdt_setprop_strings() helper in
> > > hw/core code.
> > >
> > > Signed-off-by: Ben Dooks 
> > > ---
> >
> > Reviewed-by: Peter Maydell 
>
> I've had to make a second version, so assuming it'll need
> reviewing again

If you didn't change the specific patch that I gave a reviewed-by
tag for, then you should put that tag into the commit message
next to your signed-off-by line in the patch you send in the v2
series, to indicate it's already been reviewed and doesn't need
re-doing in v2.

thanks
-- PMM



Re: [PATCH v8 3/3] target/riscv: Add vstimecmp support

2022-08-09 Thread Atish Kumar Patra
On Tue, Aug 9, 2022 at 12:01 AM Weiwei Li  wrote:

>
> 在 2022/8/9 上午1:20, Atish Kumar Patra 写道:
>
>
>
> On Sun, Aug 7, 2022 at 6:50 PM Weiwei Li  wrote:
>
>>
>> 在 2022/8/4 上午9:42, Atish Patra 写道:
>> > vstimecmp CSR allows the guest OS or to program the next guest timer
>> > interrupt directly. Thus, hypervisor no longer need to inject the
>> > timer interrupt to the guest if vstimecmp is used. This was ratified
>> > as a part of the Sstc extension.
>> >
>> > Signed-off-by: Atish Patra 
>> > ---
>> >   target/riscv/cpu.h |   4 ++
>> >   target/riscv/cpu_bits.h|   4 ++
>> >   target/riscv/cpu_helper.c  |  11 ++--
>> >   target/riscv/csr.c | 102 -
>> >   target/riscv/machine.c |   1 +
>> >   target/riscv/time_helper.c |  16 ++
>> >   6 files changed, 133 insertions(+), 5 deletions(-)
>> >
>> > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
>> > index 4cda2905661e..1fd382b2717f 100644
>> > --- a/target/riscv/cpu.h
>> > +++ b/target/riscv/cpu.h
>> > @@ -312,6 +312,8 @@ struct CPUArchState {
>> >   /* Sstc CSRs */
>> >   uint64_t stimecmp;
>> >
>> > +uint64_t vstimecmp;
>> > +
>> >   /* physical memory protection */
>> >   pmp_table_t pmp_state;
>> >   target_ulong mseccfg;
>> > @@ -366,6 +368,8 @@ struct CPUArchState {
>> >
>> >   /* Fields from here on are preserved across CPU reset. */
>> >   QEMUTimer *stimer; /* Internal timer for S-mode interrupt */
>> > +QEMUTimer *vstimer; /* Internal timer for VS-mode interrupt */
>> > +bool vstime_irq;
>> >
>> >   hwaddr kernel_addr;
>> >   hwaddr fdt_addr;
>> > diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
>> > index ac17cf1515c0..095dab19f512 100644
>> > --- a/target/riscv/cpu_bits.h
>> > +++ b/target/riscv/cpu_bits.h
>> > @@ -257,6 +257,10 @@
>> >   #define CSR_VSIP0x244
>> >   #define CSR_VSATP   0x280
>> >
>> > +/* Sstc virtual CSRs */
>> > +#define CSR_VSTIMECMP   0x24D
>> > +#define CSR_VSTIMECMPH  0x25D
>> > +
>> >   #define CSR_MTINST  0x34a
>> >   #define CSR_MTVAL2  0x34b
>> >
>> > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
>> > index 650574accf0a..1e4faa84e839 100644
>> > --- a/target/riscv/cpu_helper.c
>> > +++ b/target/riscv/cpu_helper.c
>> > @@ -345,8 +345,9 @@ uint64_t riscv_cpu_all_pending(CPURISCVState *env)
>> >   {
>> >   uint32_t gein = get_field(env->hstatus, HSTATUS_VGEIN);
>> >   uint64_t vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
>> > +uint64_t vstip = (env->vstime_irq) ? MIP_VSTIP : 0;
>> >
>> > -return (env->mip | vsgein) & env->mie;
>> > +return (env->mip | vsgein | vstip) & env->mie;
>> >   }
>> >
>> >   int riscv_cpu_mirq_pending(CPURISCVState *env)
>> > @@ -605,7 +606,7 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu,
>> uint64_t mask, uint64_t value)
>> >   {
>> >   CPURISCVState *env = >env;
>> >   CPUState *cs = CPU(cpu);
>> > -uint64_t gein, vsgein = 0, old = env->mip;
>> > +uint64_t gein, vsgein = 0, vstip = 0, old = env->mip;
>> >   bool locked = false;
>> >
>> >   if (riscv_cpu_virt_enabled(env)) {
>> > @@ -613,6 +614,10 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu,
>> uint64_t mask, uint64_t value)
>> >   vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
>> >   }
>> >
>> > +/* No need to update mip for VSTIP */
>> > +mask = ((mask == MIP_VSTIP) && env->vstime_irq) ? 0 : mask;
>> > +vstip = env->vstime_irq ? MIP_VSTIP : 0;
>> > +
>> >   if (!qemu_mutex_iothread_locked()) {
>> >   locked = true;
>> >   qemu_mutex_lock_iothread();
>> > @@ -620,7 +625,7 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu,
>> uint64_t mask, uint64_t value)
>> >
>> >   env->mip = (env->mip & ~mask) | (value & mask);
>> >
>> > -if (env->mip | vsgein) {
>> > +if (env->mip | vsgein | vstip) {
>> >   cpu_interrupt(cs, CPU_INTERRUPT_HARD);
>> >   } else {
>> >   cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
>> > diff --git a/target/riscv/csr.c b/target/riscv/csr.c
>> > index e18b000700e4..9da4d6515e7b 100644
>> > --- a/target/riscv/csr.c
>> > +++ b/target/riscv/csr.c
>> > @@ -829,17 +829,100 @@ static RISCVException sstc(CPURISCVState *env,
>> int csrno)
>> >   return smode(env, csrno);
>> >   }
>> >
>> > +static RISCVException sstc_hmode(CPURISCVState *env, int csrno)
>> > +{
>> > +CPUState *cs = env_cpu(env);
>> > +RISCVCPU *cpu = RISCV_CPU(cs);
>> > +
>> > +if (!cpu->cfg.ext_sstc || !env->rdtime_fn) {
>> > +return RISCV_EXCP_ILLEGAL_INST;
>> > +}
>> > +
>> > +if (env->priv == PRV_M) {
>> > +return RISCV_EXCP_NONE;
>> > +}
>> > +
>> > +if (!(get_field(env->mcounteren, COUNTEREN_TM) &
>> > +  get_field(env->menvcfg, MENVCFG_STCE))) {
>> > +return RISCV_EXCP_ILLEGAL_INST;
>> > +}
>> > +
>> > +if (riscv_cpu_virt_enabled(env)) {
>> > +if 

Re: [PATCH v3 5/5] hw/arm: change to use qemu_fdt_setprop_strings()

2022-08-09 Thread Mark Cave-Ayland

On 09/08/2022 20:22, Peter Maydell wrote:


On Tue, 9 Aug 2022 at 19:48, Ben Dooks  wrote:


On Mon, Aug 01, 2022 at 12:37:33PM +0100, Peter Maydell wrote:

On Wed, 27 Jul 2022 at 23:44, Ben Dooks  wrote:

@@ -285,8 +280,6 @@ static void fdt_add_gem_nodes(VersalVirt *s)

  static void fdt_add_zdma_nodes(VersalVirt *s)
  {
-const char clocknames[] = "clk_main\0clk_apb";
-const char compat[] = "xlnx,zynqmp-dma-1.0";


This looks suspiciously like a pre-existing bug to me.
Alaistair, Edgar -- shouldn't this be a NUL-separated
'compatible' string, rather than a comma-separated one?


I think the compat[] is fine, I should have probably added I also fixed
up to just call qemu_fdt_setprop_string()


I guess if it's definitely supposed to be one string instead of two that's OK.


FWIW the compat strings look like they are using the older , 
notation similar to SUNW,tcx and SUNW,cgthree so if Xilinx is the manufacturer I 
think they are correct.



ATB,

Mark.



Re: [PATCH v3 5/5] hw/arm: change to use qemu_fdt_setprop_strings()

2022-08-09 Thread Peter Maydell
On Tue, 9 Aug 2022 at 19:48, Ben Dooks  wrote:
>
> On Mon, Aug 01, 2022 at 12:37:33PM +0100, Peter Maydell wrote:
> > On Wed, 27 Jul 2022 at 23:44, Ben Dooks  wrote:
> > > @@ -285,8 +280,6 @@ static void fdt_add_gem_nodes(VersalVirt *s)
> > >
> > >  static void fdt_add_zdma_nodes(VersalVirt *s)
> > >  {
> > > -const char clocknames[] = "clk_main\0clk_apb";
> > > -const char compat[] = "xlnx,zynqmp-dma-1.0";
> >
> > This looks suspiciously like a pre-existing bug to me.
> > Alaistair, Edgar -- shouldn't this be a NUL-separated
> > 'compatible' string, rather than a comma-separated one?
>
> I think the compat[] is fine, I should have probably added I also fixed
> up to just call qemu_fdt_setprop_string()

I guess if it's definitely supposed to be one string instead of two that's OK.

-- PMM



Re: [PULL 0/1] target-arm queue

2022-08-09 Thread Richard Henderson

On 8/9/22 05:13, Peter Maydell wrote:

Just one bugfix patch for this rc:

The following changes since commit ca5f3d4df1b47d7f66a109cdb504e83dfd7ec433:

   Merge tag 'pull-la-20220808' of https://gitlab.com/rth7680/qemu into staging 
(2022-08-08 19:51:12 -0700)

are available in the Git repository at:

   https://git.linaro.org/people/pmaydell/qemu-arm.git 
tags/pull-target-arm-20220809

for you to fetch changes up to c7f26ded6d5065e4116f630f6a490b55f6c5f58e:

   icount: Take iothread lock when running QEMU timers (2022-08-09 10:55:14 
+0100)


target-arm queue:
  * icount: Take iothread lock when running QEMU timers


Applied, thanks.  Please update https://wiki.qemu.org/ChangeLog/7.1 as 
appropriate.


r~





Peter Maydell (1):
   icount: Take iothread lock when running QEMU timers

  accel/tcg/tcg-accel-ops-icount.c | 6 ++
  1 file changed, 6 insertions(+)






[PATCH v4 6/6] hw/arm: change to use qemu_fdt_setprop_strings()

2022-08-09 Thread Ben Dooks
Change to using qemu_fdt_setprop_strings() instead of using
\0 separated string arrays. Note, also there were a few places
where qemu_fdt_setprop_string() can be used in the same areas.

Signed-off-by: Ben Dooks 
---
v4:
 - fixed checkpatch errors with string
 - fixed patch subject
---
 hw/arm/boot.c |  8 +++---
 hw/arm/virt.c | 28 +
 hw/arm/xlnx-versal-virt.c | 51 ---
 3 files changed, 37 insertions(+), 50 deletions(-)

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index ada2717f76..766257cbfb 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -490,11 +490,11 @@ static void fdt_add_psci_node(void *fdt)
 qemu_fdt_add_subnode(fdt, "/psci");
 if (armcpu->psci_version >= QEMU_PSCI_VERSION_0_2) {
 if (armcpu->psci_version < QEMU_PSCI_VERSION_1_0) {
-const char comp[] = "arm,psci-0.2\0arm,psci";
-qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
+qemu_fdt_setprop_strings(fdt, "/psci", "compatible",
+ "arm,psci-0.2", "arm,psci");
 } else {
-const char comp[] = "arm,psci-1.0\0arm,psci-0.2\0arm,psci";
-qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
+qemu_fdt_setprop_strings(fdt, "/psci", "compatible",
+ "arm,psci-1.0", "arm,psci-0.2", 
"arm,psci");
 }
 
 cpu_off_fn = QEMU_PSCI_0_2_FN_CPU_OFF;
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 9633f822f3..2670c13ef1 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -343,9 +343,8 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
 
 armcpu = ARM_CPU(qemu_get_cpu(0));
 if (arm_feature(>env, ARM_FEATURE_V8)) {
-const char compat[] = "arm,armv8-timer\0arm,armv7-timer";
-qemu_fdt_setprop(ms->fdt, "/timer", "compatible",
- compat, sizeof(compat));
+qemu_fdt_setprop_strings(ms->fdt, "/timer", "compatible",
+ "arm,armv8-timer", "arm,armv7-timer");
 } else {
 qemu_fdt_setprop_string(ms->fdt, "/timer", "compatible",
 "arm,armv7-timer");
@@ -843,8 +842,6 @@ static void create_uart(const VirtMachineState *vms, int 
uart,
 hwaddr base = vms->memmap[uart].base;
 hwaddr size = vms->memmap[uart].size;
 int irq = vms->irqmap[uart];
-const char compat[] = "arm,pl011\0arm,primecell";
-const char clocknames[] = "uartclk\0apb_pclk";
 DeviceState *dev = qdev_new(TYPE_PL011);
 SysBusDevice *s = SYS_BUS_DEVICE(dev);
 MachineState *ms = MACHINE(vms);
@@ -858,8 +855,8 @@ static void create_uart(const VirtMachineState *vms, int 
uart,
 nodename = g_strdup_printf("/pl011@%" PRIx64, base);
 qemu_fdt_add_subnode(ms->fdt, nodename);
 /* Note that we can't use setprop_string because of the embedded NUL */
-qemu_fdt_setprop(ms->fdt, nodename, "compatible",
- compat, sizeof(compat));
+qemu_fdt_setprop_strings(ms->fdt, nodename, "compatible",
+ "arm,pl011", "arm,primecell");
 qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
  2, base, 2, size);
 qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
@@ -867,8 +864,8 @@ static void create_uart(const VirtMachineState *vms, int 
uart,
GIC_FDT_IRQ_FLAGS_LEVEL_HI);
 qemu_fdt_setprop_cells(ms->fdt, nodename, "clocks",
vms->clock_phandle, vms->clock_phandle);
-qemu_fdt_setprop(ms->fdt, nodename, "clock-names",
- clocknames, sizeof(clocknames));
+qemu_fdt_setprop_strings(ms->fdt, nodename, "clock-names",
+ "uartclk", "apb_pclk");
 
 if (uart == VIRT_UART) {
 qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", nodename);
@@ -890,14 +887,14 @@ static void create_rtc(const VirtMachineState *vms)
 hwaddr base = vms->memmap[VIRT_RTC].base;
 hwaddr size = vms->memmap[VIRT_RTC].size;
 int irq = vms->irqmap[VIRT_RTC];
-const char compat[] = "arm,pl031\0arm,primecell";
 MachineState *ms = MACHINE(vms);
 
 sysbus_create_simple("pl031", base, qdev_get_gpio_in(vms->gic, irq));
 
 nodename = g_strdup_printf("/pl031@%" PRIx64, base);
 qemu_fdt_add_subnode(ms->fdt, nodename);
-qemu_fdt_setprop(ms->fdt, nodename, "compatible", compat, sizeof(compat));
+qemu_fdt_setprop_strings(ms->fdt, nodename, "compatible",
+ "arm,pl031", "arm,primecell");
 qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
  2, base, 2, size);
 qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
@@ -983,7 +980,6 @@ static void create_gpio_devices(const VirtMachineState 
*vms, int gpio,
 hwaddr base = vms->memmap[gpio].base;
 hwaddr size = 

[PATCH v4 4/6] hw/core: use qemu_fdt_setprop_strings()

2022-08-09 Thread Ben Dooks
Change to using the qemu_fdt_setprop_strings() helper in
hw/core code.

Signed-off-by: Ben Dooks 
---
 hw/core/guest-loader.c | 13 +
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/hw/core/guest-loader.c b/hw/core/guest-loader.c
index c61ebc4144..7b8e32e06f 100644
--- a/hw/core/guest-loader.c
+++ b/hw/core/guest-loader.c
@@ -56,18 +56,15 @@ static void loader_insert_platform_data(GuestLoaderState 
*s, int size,
 qemu_fdt_setprop(fdt, node, "reg", _attr, sizeof(reg_attr));
 
 if (s->kernel) {
-const char *compat[2] = { "multiboot,module", "multiboot,kernel" };
-qemu_fdt_setprop_string_array(fdt, node, "compatible",
-  (char **) ,
-  ARRAY_SIZE(compat));
+qemu_fdt_setprop_strings(fdt, node, "compatible",
+ "multiboot,module", "multiboot,kernel");
+
 if (s->args) {
 qemu_fdt_setprop_string(fdt, node, "bootargs", s->args);
 }
 } else if (s->initrd) {
-const char *compat[2] = { "multiboot,module", "multiboot,ramdisk" };
-qemu_fdt_setprop_string_array(fdt, node, "compatible",
-  (char **) ,
-  ARRAY_SIZE(compat));
+qemu_fdt_setprop_strings(fdt, node, "compatible",
+ "multiboot,module", "multiboot,ramdisk");
 }
 }
 
-- 
2.35.1




Re: add qemu_fdt_setprop_strings() and use it in most places

2022-08-09 Thread Ben Dooks
On Tue, Aug 09, 2022 at 07:56:34PM +0100, Ben Dooks wrote:
> Add a helper for qemu_fdt_setprop_strings() to take a set of strings
> to put into a device-tree, which removes several open-coded methods
> such as setting an char arr[] = {..} or setting char val[] = "str\0str2"; 
>   
> 
> This is for hw/arm, hw/mips and hw/riscv as well as a couple of cores. It
> is not fully tested over all of those, I may not have caught all places
> this is to be replaced.  

I've put a github repo up with this and possibly some other bits I am
working on:

https://github.com/bendooks/qemu/tree/dev/fdt-string-array-v4

> Changes:
> 
> v4:
>  - fix checkpatch issues
>  - remove error checking in hw/core/guest-loader.c
> v3:
>  - fix return value for the call  
>   
>  - add better help text   
>   
> v2:   
>   
>  - fix node/path in comment   
>   
> 
> 
> 

-- 
Ben Dooks, b...@fluff.org, http://www.fluff.org/ben/

Large Hadron Colada: A large Pina Colada that makes the universe disappear.




[PATCH v4 1/6] device_tree: add qemu_fdt_setprop_strings() helper

2022-08-09 Thread Ben Dooks
Add a helper to set a property from a set of strings
to reduce the following code:

static const char * const clint_compat[2] = {
"sifive,clint0", "riscv,clint0"
};

qemu_fdt_setprop_string_array(fdt, nodename, "compatible",
(char **)_compat, ARRAY_SIZE(clint_compat));

Signed-off-by: Ben Dooks 
---
v4:
 - go back to the non-return call, no-one is using the result
v3;
 - fix return value for the call
 - add better help text
v2:
 - fix node/path in comment
---
 include/sysemu/device_tree.h | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h
index ef060a9759..d5c05b5ebb 100644
--- a/include/sysemu/device_tree.h
+++ b/include/sysemu/device_tree.h
@@ -87,6 +87,25 @@ int qemu_fdt_setprop_string(void *fdt, const char *node_path,
 int qemu_fdt_setprop_string_array(void *fdt, const char *node_path,
   const char *prop, char **array, int len);
 
+/**
+ * qemu_fdt_setprop_strings: set a property from a set of strings
+ *
+ * @fdt: pointer to the dt blob
+ * @path: node name
+ * @prop: property array
+ *
+ * This is a helper for the qemu_fdt_setprop_string_array() function
+ * which takes a va-arg set of strings instead of having to setup a
+ * single use string array.
+ */
+#define qemu_fdt_setprop_strings(fdt, path, prop, ...)  \
+do {\
+static const char * const __strs[] = { __VA_ARGS__ };   \
+qemu_fdt_setprop_string_array(fdt, path, prop,  \
+(char **)&__strs, ARRAY_SIZE(__strs));  \
+ } while(0)
+
+
 int qemu_fdt_setprop_phandle(void *fdt, const char *node_path,
  const char *property,
  const char *target_node_path);
-- 
2.35.1




[PATCH v4 2/6] hw/core: don't check return on qemu_fdt_setprop_string_array()

2022-08-09 Thread Ben Dooks
The qemu_fdt_setprop_string_array() does not return error codes and
will call exit() if any of the fdt calls fails (and should print an
error with the node being altered). This is done to prepare for the
change for qemu_fdt_setprop_strings() helper which does not return
any error codes (hw/core/guest-loader.c is the only place where an
return is checked).

Signed-off-by: Ben Dooks 
---
 hw/core/guest-loader.c | 22 +++---
 1 file changed, 7 insertions(+), 15 deletions(-)

diff --git a/hw/core/guest-loader.c b/hw/core/guest-loader.c
index 391c875a29..c61ebc4144 100644
--- a/hw/core/guest-loader.c
+++ b/hw/core/guest-loader.c
@@ -57,25 +57,17 @@ static void loader_insert_platform_data(GuestLoaderState 
*s, int size,
 
 if (s->kernel) {
 const char *compat[2] = { "multiboot,module", "multiboot,kernel" };
-if (qemu_fdt_setprop_string_array(fdt, node, "compatible",
-  (char **) ,
-  ARRAY_SIZE(compat)) < 0) {
-error_setg(errp, "couldn't set %s/compatible", node);
-return;
-}
+qemu_fdt_setprop_string_array(fdt, node, "compatible",
+  (char **) ,
+  ARRAY_SIZE(compat));
 if (s->args) {
-if (qemu_fdt_setprop_string(fdt, node, "bootargs", s->args) < 0) {
-error_setg(errp, "couldn't set %s/bootargs", node);
-}
+qemu_fdt_setprop_string(fdt, node, "bootargs", s->args);
 }
 } else if (s->initrd) {
 const char *compat[2] = { "multiboot,module", "multiboot,ramdisk" };
-if (qemu_fdt_setprop_string_array(fdt, node, "compatible",
-  (char **) ,
-  ARRAY_SIZE(compat)) < 0) {
-error_setg(errp, "couldn't set %s/compatible", node);
-return;
-}
+qemu_fdt_setprop_string_array(fdt, node, "compatible",
+  (char **) ,
+  ARRAY_SIZE(compat));
 }
 }
 
-- 
2.35.1




add qemu_fdt_setprop_strings() and use it in most places

2022-08-09 Thread Ben Dooks
Add a helper for qemu_fdt_setprop_strings() to take a set of strings
to put into a device-tree, which removes several open-coded methods
such as setting an char arr[] = {..} or setting char val[] = "str\0str2";   

This is for hw/arm, hw/mips and hw/riscv as well as a couple of cores. It
is not fully tested over all of those, I may not have caught all places
this is to be replaced.  

Changes:

v4:
 - fix checkpatch issues
 - remove error checking in hw/core/guest-loader.c
v3:
 - fix return value for the call
 - add better help text 
v2: 
 - fix node/path in comment 





[PATCH v4 5/6] hw/mips: use qemu_fdt_setprop_strings()

2022-08-09 Thread Ben Dooks
Change to using qemu_fdt_setprop_strings() helper in hw/mips.

Signed-off-by: Ben Dooks 
Reviewed-by: Peter Maydell 
---
 hw/mips/boston.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/hw/mips/boston.c b/hw/mips/boston.c
index d2ab9da1a0..759f6daafe 100644
--- a/hw/mips/boston.c
+++ b/hw/mips/boston.c
@@ -515,9 +515,6 @@ static const void *create_fdt(BostonState *s,
 MachineState *mc = s->mach;
 uint32_t platreg_ph, gic_ph, clk_ph;
 char *name, *gic_name, *platreg_name, *stdout_name;
-static const char * const syscon_compat[2] = {
-"img,boston-platform-regs", "syscon"
-};
 
 fdt = create_device_tree(dt_size);
 if (!fdt) {
@@ -608,9 +605,8 @@ static const void *create_fdt(BostonState *s,
 platreg_name = g_strdup_printf("/soc/system-controller@%" HWADDR_PRIx,
memmap[BOSTON_PLATREG].base);
 qemu_fdt_add_subnode(fdt, platreg_name);
-qemu_fdt_setprop_string_array(fdt, platreg_name, "compatible",
- (char **)_compat,
- ARRAY_SIZE(syscon_compat));
+qemu_fdt_setprop_strings(fdt, platreg_name, "compatible",
+ "img,boston-platform-regs", "syscon");
 qemu_fdt_setprop_cells(fdt, platreg_name, "reg",
memmap[BOSTON_PLATREG].base,
memmap[BOSTON_PLATREG].size);
-- 
2.35.1




[PATCH v4 3/6] hw/riscv: use qemu_fdt_setprop_strings() for string arrays

2022-08-09 Thread Ben Dooks
Use the qemu_fdt_setprop_strings() in sifve_u.c to simplify the code.

Signed-off-by: Ben Dooks 
---
 hw/riscv/sifive_u.c | 18 +-
 hw/riscv/spike.c|  7 ++-
 hw/riscv/virt.c | 32 
 3 files changed, 15 insertions(+), 42 deletions(-)

diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index e4c814a3ea..dc112a253a 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -103,13 +103,6 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry 
*memmap,
 char *nodename;
 uint32_t plic_phandle, prci_phandle, gpio_phandle, phandle = 1;
 uint32_t hfclk_phandle, rtcclk_phandle, phy_phandle;
-static const char * const ethclk_names[2] = { "pclk", "hclk" };
-static const char * const clint_compat[2] = {
-"sifive,clint0", "riscv,clint0"
-};
-static const char * const plic_compat[2] = {
-"sifive,plic-1.0.0", "riscv,plic0"
-};
 
 if (ms->dtb) {
 fdt = s->fdt = load_device_tree(ms->dtb, >fdt_size);
@@ -221,11 +214,11 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry 
*memmap,
 nodename = g_strdup_printf("/soc/clint@%lx",
 (long)memmap[SIFIVE_U_DEV_CLINT].base);
 qemu_fdt_add_subnode(fdt, nodename);
-qemu_fdt_setprop_string_array(fdt, nodename, "compatible",
-(char **)_compat, ARRAY_SIZE(clint_compat));
 qemu_fdt_setprop_cells(fdt, nodename, "reg",
 0x0, memmap[SIFIVE_U_DEV_CLINT].base,
 0x0, memmap[SIFIVE_U_DEV_CLINT].size);
+qemu_fdt_setprop_strings(fdt, nodename, "compatible",
+ "sifive,clint0", "riscv,clint0");
 qemu_fdt_setprop(fdt, nodename, "interrupts-extended",
 cells, ms->smp.cpus * sizeof(uint32_t) * 4);
 g_free(cells);
@@ -279,8 +272,8 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry 
*memmap,
 (long)memmap[SIFIVE_U_DEV_PLIC].base);
 qemu_fdt_add_subnode(fdt, nodename);
 qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 1);
-qemu_fdt_setprop_string_array(fdt, nodename, "compatible",
-(char **)_compat, ARRAY_SIZE(plic_compat));
+qemu_fdt_setprop_strings(fdt, nodename, "compatbile",
+ "sifive,plic-1.0.0", "riscv,plic0");
 qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0);
 qemu_fdt_setprop(fdt, nodename, "interrupts-extended",
 cells, (ms->smp.cpus * 4 - 2) * sizeof(uint32_t));
@@ -426,8 +419,7 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry 
*memmap,
 qemu_fdt_setprop_cell(fdt, nodename, "interrupts", SIFIVE_U_GEM_IRQ);
 qemu_fdt_setprop_cells(fdt, nodename, "clocks",
 prci_phandle, PRCI_CLK_GEMGXLPLL, prci_phandle, PRCI_CLK_GEMGXLPLL);
-qemu_fdt_setprop_string_array(fdt, nodename, "clock-names",
-(char **)_names, ARRAY_SIZE(ethclk_names));
+qemu_fdt_setprop_strings(fdt, nodename, "clock-names", "pclk", "hclk");
 qemu_fdt_setprop(fdt, nodename, "local-mac-address",
 s->soc.gem.conf.macaddr.a, ETH_ALEN);
 qemu_fdt_setprop_cell(fdt, nodename, "#address-cells", 1);
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index e41b6aa9f0..aa895779cd 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -59,9 +59,6 @@ static void create_fdt(SpikeState *s, const MemMapEntry 
*memmap,
 uint32_t cpu_phandle, intc_phandle, phandle = 1;
 char *name, *mem_name, *clint_name, *clust_name;
 char *core_name, *cpu_name, *intc_name;
-static const char * const clint_compat[2] = {
-"sifive,clint0", "riscv,clint0"
-};
 
 fdt = s->fdt = create_device_tree(>fdt_size);
 if (!fdt) {
@@ -159,8 +156,8 @@ static void create_fdt(SpikeState *s, const MemMapEntry 
*memmap,
 (memmap[SPIKE_CLINT].size * socket);
 clint_name = g_strdup_printf("/soc/clint@%lx", clint_addr);
 qemu_fdt_add_subnode(fdt, clint_name);
-qemu_fdt_setprop_string_array(fdt, clint_name, "compatible",
-(char **)_compat, ARRAY_SIZE(clint_compat));
+qemu_fdt_setprop_strings(fdt, clint_name, "compatible",
+ "sifive,clint0", "riscv,clint0");
 qemu_fdt_setprop_cells(fdt, clint_name, "reg",
 0x0, clint_addr, 0x0, memmap[SPIKE_CLINT].size);
 qemu_fdt_setprop(fdt, clint_name, "interrupts-extended",
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index bc424dd2f5..c6aaa611a6 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -261,11 +261,8 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 intc_phandles[cpu]);
 if (riscv_feature(>soc[socket].harts[cpu].env,
   RISCV_FEATURE_AIA)) {
-static const char * const compat[2] = {
-"riscv,cpu-intc-aia", "riscv,cpu-intc"
-};
-qemu_fdt_setprop_string_array(mc->fdt, intc_name, "compatible",
-  (char **), ARRAY_SIZE(compat));
+

Re: [PATCH v3 3/5] hw/core: use qemu_fdt_setprop_strings()

2022-08-09 Thread Ben Dooks
On Mon, Aug 01, 2022 at 12:30:22PM +0100, Peter Maydell wrote:
> On Wed, 27 Jul 2022 at 23:39, Ben Dooks  wrote:
> >
> > Change to using the qemu_fdt_setprop_strings() helper in
> > hw/core code.
> >
> > Signed-off-by: Ben Dooks 
> > ---
> 
> Reviewed-by: Peter Maydell 

I've had to make a second version, so assuming it'll need
reviewing again

-- 
Ben Dooks, b...@fluff.org, http://www.fluff.org/ben/

Large Hadron Colada: A large Pina Colada that makes the universe disappear.




Re: [PATCH v3 5/5] hw/arm: change to use qemu_fdt_setprop_strings()

2022-08-09 Thread Ben Dooks
On Mon, Aug 01, 2022 at 12:37:33PM +0100, Peter Maydell wrote:
> On Wed, 27 Jul 2022 at 23:44, Ben Dooks  wrote:
> >
> > Change to using qemu_fdt_setprop_strings() instead of using
> > \0 separated string arrays.
> >
> > Signed-off-by: Ben Dooks 
> > ---
> >  hw/arm/boot.c |  8 +++---
> >  hw/arm/virt.c | 28 +
> >  hw/arm/xlnx-versal-virt.c | 51 ---
> >  3 files changed, 37 insertions(+), 50 deletions(-)
> >
> > diff --git a/hw/arm/boot.c b/hw/arm/boot.c
> > index ada2717f76..bf29b7ae60 100644
> > --- a/hw/arm/boot.c
> > +++ b/hw/arm/boot.c
> > @@ -490,11 +490,11 @@ static void fdt_add_psci_node(void *fdt)
> >  qemu_fdt_add_subnode(fdt, "/psci");
> >  if (armcpu->psci_version >= QEMU_PSCI_VERSION_0_2) {
> >  if (armcpu->psci_version < QEMU_PSCI_VERSION_1_0) {
> > -const char comp[] = "arm,psci-0.2\0arm,psci";
> > -qemu_fdt_setprop(fdt, "/psci", "compatible", comp, 
> > sizeof(comp));
> > +qemu_fdt_setprop_strings(fdt, "/psci", "compatible",
> > + "arm,psci-0.2", "arm,psci");
> 
> I think you may have some stray trailing whitespace here.
> checkpatch should be able to tell you.

ok, will check

> > @@ -858,8 +855,8 @@ static void create_uart(const VirtMachineState *vms, 
> > int uart,
> >  nodename = g_strdup_printf("/pl011@%" PRIx64, base);
> >  qemu_fdt_add_subnode(ms->fdt, nodename);
> >  /* Note that we can't use setprop_string because of the embedded NUL */
> 
> With this change, this comment becomes obsolete, and we should delete it too.
> 
> > -qemu_fdt_setprop(ms->fdt, nodename, "compatible",
> > - compat, sizeof(compat));
> > +qemu_fdt_setprop_strings(ms->fdt, nodename, "compatible",
> > + "arm,pl011", "arm,primecell");
> >  qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
> >   2, base, 2, size);
> >  qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
> 
> 
> 
> > @@ -285,8 +280,6 @@ static void fdt_add_gem_nodes(VersalVirt *s)
> >
> >  static void fdt_add_zdma_nodes(VersalVirt *s)
> >  {
> > -const char clocknames[] = "clk_main\0clk_apb";
> > -const char compat[] = "xlnx,zynqmp-dma-1.0";
> 
> This looks suspiciously like a pre-existing bug to me.
> Alaistair, Edgar -- shouldn't this be a NUL-separated
> 'compatible' string, rather than a comma-separated one?

I think the compat[] is fine, I should have probably added I also fixed
up to just call qemu_fdt_setprop_string()

> >  int i;
> >
> >  for (i = XLNX_VERSAL_NR_ADMAS - 1; i >= 0; i--) {
> > @@ -298,22 +291,21 @@ static void fdt_add_zdma_nodes(VersalVirt *s)
> >  qemu_fdt_setprop_cell(s->fdt, name, "xlnx,bus-width", 64);
> >  qemu_fdt_setprop_cells(s->fdt, name, "clocks",
> > s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
> > -qemu_fdt_setprop(s->fdt, name, "clock-names",
> > - clocknames, sizeof(clocknames));
> > +qemu_fdt_setprop_strings(s->fdt, name, "clock-names",
> > + "clk_main", "clk_apb");
> >  qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
> > GIC_FDT_IRQ_TYPE_SPI, VERSAL_ADMA_IRQ_0 + i,
> > GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> >  qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> >   2, addr, 2, 0x1000);
> > -qemu_fdt_setprop(s->fdt, name, "compatible", compat, 
> > sizeof(compat));
> > +qemu_fdt_setprop_string(s->fdt, name, "compatible",
> > +"xlnx,zynqmp-dma-1.0");
> >  g_free(name);
> >  }
> >  }
> >
> >  static void fdt_add_sd_nodes(VersalVirt *s)
> >  {
> > -const char clocknames[] = "clk_xin\0clk_ahb";
> > -const char compat[] = "arasan,sdhci-8.9a";
> 
> Ditto here...
> 
> >  int i;
> >
> >  for (i = ARRAY_SIZE(s->soc.pmc.iou.sd) - 1; i >= 0; i--) {
> > @@ -324,22 +316,21 @@ static void fdt_add_sd_nodes(VersalVirt *s)
> >
> >  qemu_fdt_setprop_cells(s->fdt, name, "clocks",
> > s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
> > -qemu_fdt_setprop(s->fdt, name, "clock-names",
> > - clocknames, sizeof(clocknames));
> > +qemu_fdt_setprop_strings(s->fdt, name, "clock-names",
> > + "clk_xin", "clk_ahb");
> >  qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
> > GIC_FDT_IRQ_TYPE_SPI, VERSAL_SD0_IRQ_0 + i 
> > * 2,
> > GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> >  qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> >   2, addr, 2, MM_PMC_SD0_SIZE);
> > -qemu_fdt_setprop(s->fdt, name, "compatible", compat, 

Re: [PATCH v3 1/2] Update AVX512 support for xbzrle_encode_buffer function

2022-08-09 Thread Richard Henderson

On 8/8/22 00:48, ling xu wrote:

This commit update runtime check of AVX512, and implements avx512 of
xbzrle_encode_buffer function to accelerate xbzrle encoding speed.
Compared with C version of xbzrle_encode_buffer function, avx512 version
can achieve almost 60%-70% performance improvement on unit test provided
by Qemu. In addition, we provide one more unit test called
"test_encode_decode_random", in which dirty data are randomly located in
4K page, and this case can achieve almost 140% performance gain.

Signed-off-by: ling xu 
Co-authored-by: Zhou Zhao 
Co-authored-by: Jun Jin 
---
  meson.build|  16 
  meson_options.txt  |   2 +
  migration/ram.c|  41 ++
  migration/xbzrle.c | 181 +
  migration/xbzrle.h |   4 +
  5 files changed, 244 insertions(+)

diff --git a/meson.build b/meson.build
index 294e9a8f32..4222b77e9f 100644
--- a/meson.build
+++ b/meson.build
@@ -2262,6 +2262,22 @@ config_host_data.set('CONFIG_AVX512F_OPT', 
get_option('avx512f') \
  int main(int argc, char *argv[]) { return bar(argv[0]); }
'''), error_message: 'AVX512F not available').allowed())
  
+config_host_data.set('CONFIG_AVX512BW_OPT', get_option('avx512bw') \

+  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable 
AVX512BW') \
+  .require(cc.links('''
+#pragma GCC push_options
+#pragma GCC target("avx512bw")
+#include 
+#include 
+static int bar(void *a) {
+
+  __m512i x = *(__m512i *)a;
+  __m512i res= _mm512_abs_epi8(x);
+  return res[1];
+}
+int main(int argc, char *argv[]) { return bar(argv[0]); }
+  '''), error_message: 'AVX512BW not available').allowed())
+
  have_pvrdma = get_option('pvrdma') \
.require(rdma.found(), error_message: 'PVRDMA requires OpenFabrics 
libraries') \
.require(cc.compiles(gnu_source_prefix + '''
diff --git a/meson_options.txt b/meson_options.txt
index e58e158396..07194bf680 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -104,6 +104,8 @@ option('avx2', type: 'feature', value: 'auto',
 description: 'AVX2 optimizations')
  option('avx512f', type: 'feature', value: 'disabled',
 description: 'AVX512F optimizations')
+option('avx512bw', type: 'feature', value: 'auto',
+   description: 'AVX512BW optimizations')
  option('keyring', type: 'feature', value: 'auto',
 description: 'Linux keyring support')
  
diff --git a/migration/ram.c b/migration/ram.c

index dc1de9ddbc..d9c1ac2f7a 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -83,6 +83,35 @@
  /* 0x80 is reserved in migration.h start with 0x100 next */
  #define RAM_SAVE_FLAG_COMPRESS_PAGE0x100
  
+#if defined(CONFIG_AVX512BW_OPT)

+static bool IS_CPU_SUPPORT_AVX512BW;
+#include "qemu/cpuid.h"
+static void __attribute__((constructor)) init_cpu_flag(void)
+{
+unsigned max = __get_cpuid_max(0, NULL);
+int a, b, c, d;
+IS_CPU_SUPPORT_AVX512BW = false;
+if (max >= 1) {
+__cpuid(1, a, b, c, d);
+ /* We must check that AVX is not just available, but usable.  */
+if ((c & bit_OSXSAVE) && (c & bit_AVX) && max >= 7) {
+int bv;
+__asm("xgetbv" : "=a"(bv), "=d"(d) : "c"(0));
+__cpuid_count(7, 0, a, b, c, d);
+   /* 0xe6:
+*  XCR0[7:5] = 111b (OPMASK state, upper 256-bit of ZMM0-ZMM15
+*and ZMM16-ZMM31 state are enabled by OS)
+*  XCR0[2:1] = 11b (XMM state and YMM state are enabled by OS)
+*/
+if ((bv & 0xe6) == 0xe6 && (b & bit_AVX512BW)) {
+IS_CPU_SUPPORT_AVX512BW = true;
+}
+}
+}
+return ;
+}
+#endif
+
  XBZRLECacheStats xbzrle_counters;
  
  /* struct contains XBZRLE cache and a static page

@@ -802,9 +831,21 @@ static int save_xbzrle_page(RAMState *rs, uint8_t 
**current_data,
  memcpy(XBZRLE.current_buf, *current_data, TARGET_PAGE_SIZE);
  
  /* XBZRLE encoding (if there is no overflow) */

+#if defined(CONFIG_AVX512BW_OPT)
+if (likely(IS_CPU_SUPPORT_AVX512BW)) {
+encoded_len = xbzrle_encode_buffer_512(prev_cached_page, 
XBZRLE.current_buf,
+   TARGET_PAGE_SIZE, 
XBZRLE.encoded_buf,
+   TARGET_PAGE_SIZE);
+} else {
+encoded_len = xbzrle_encode_buffer(prev_cached_page, 
XBZRLE.current_buf,
+   TARGET_PAGE_SIZE, 
XBZRLE.encoded_buf,
+   TARGET_PAGE_SIZE);
+}
+#else
  encoded_len = xbzrle_encode_buffer(prev_cached_page, XBZRLE.current_buf,
 TARGET_PAGE_SIZE, XBZRLE.encoded_buf,
 TARGET_PAGE_SIZE);
+#endif
  
  /*

   * Update the cache contents, so that it corresponds to the data
diff --git a/migration/xbzrle.c b/migration/xbzrle.c
index 1ba482ded9..4db09fdbdb 

Re: [PATCH v3 2/2] Test code for AVX512 support for xbzrle_encode_buffer

2022-08-09 Thread Richard Henderson

On 8/8/22 00:48, ling xu wrote:

Signed-off-by: ling xu 
Co-authored-by: Zhou Zhao 
Co-authored-by: Jun Jin 
---
  tests/unit/test-xbzrle.c | 307 ---
  1 file changed, 290 insertions(+), 17 deletions(-)

diff --git a/tests/unit/test-xbzrle.c b/tests/unit/test-xbzrle.c
index ef951b6e54..653016826f 100644
--- a/tests/unit/test-xbzrle.c
+++ b/tests/unit/test-xbzrle.c
@@ -38,111 +38,280 @@ static void test_uleb(void)
  g_assert(val == 0);
  }
  
-static void test_encode_decode_zero(void)

+static float *test_encode_decode_zero(void)
  {
  uint8_t *buffer = g_malloc0(XBZRLE_PAGE_SIZE);
  uint8_t *compressed = g_malloc0(XBZRLE_PAGE_SIZE);
+uint8_t *buffer512 = g_malloc0(XBZRLE_PAGE_SIZE);
+uint8_t *compressed512 = g_malloc0(XBZRLE_PAGE_SIZE);
  int i = 0;
-int dlen = 0;
+int dlen = 0, dlen512 = 0;
  int diff_len = g_test_rand_int_range(0, XBZRLE_PAGE_SIZE - 1006);
  
  for (i = diff_len; i > 0; i--) {

  buffer[1000 + i] = i;
+buffer512[1000 + i] = i;
  }
  
  buffer[1000 + diff_len + 3] = 103;

  buffer[1000 + diff_len + 5] = 105;
  
+buffer512[1000 + diff_len + 3] = 103;

+buffer512[1000 + diff_len + 5] = 105;
+
  /* encode zero page */
+time_t t_start, t_end, t_start512, t_end512;
+t_start = clock();
  dlen = xbzrle_encode_buffer(buffer, buffer, XBZRLE_PAGE_SIZE, compressed,
 XBZRLE_PAGE_SIZE);
+t_end = clock();
+float time_val = difftime(t_end, t_start);
  g_assert(dlen == 0);
  
+t_start512 = clock();

+dlen512 = xbzrle_encode_buffer_512(buffer512, buffer512, XBZRLE_PAGE_SIZE,
+   compressed512, XBZRLE_PAGE_SIZE);
+t_end512 = clock();
+float time_val512 = difftime(t_end512, t_start512);
+g_assert(dlen512 == 0);
+
+static float result_zero[2];
+result_zero[0] = time_val;
+result_zero[1] = time_val512;
+
  g_free(buffer);
  g_free(compressed);
+g_free(buffer512);
+g_free(compressed512);
+
+return result_zero;
+}


Why are you returning a pointer to static storage?
I'll note that this isn't so much "testing" as "benchmarking".

Does the speedup from using 512-bit vectors make up for the clock slowdown that is 
enforced on the cpu cluster?  As far as I know, it is still quite rare for avx512 to 
actually pay off.


I suggest you model testing on test_buffer_is_zero_next_accel().



r~



Re: [PATCH v3 1/2] Update AVX512 support for xbzrle_encode_buffer function

2022-08-09 Thread Richard Henderson

On 8/9/22 00:51, Xu, Ling1 wrote:

Hi, Juan,
   Thanks for your advice. We have revised our code including: 1) change 
"IS_CPU_SUPPORT_AVX512BW" to "is_cpu_support_avx512bw" to indicate that 
variable isn't global variable;


You can remove this variable entirely...


2) use a function pointer to simplify code in ram.c;


... because it's redundant with the function pointer.


r~



Re: [PATCH v4 24/24] ppc/ppc405: Add check on minimum RAM size

2022-08-09 Thread BALATON Zoltan

On Tue, 9 Aug 2022, Cédric Le Goater wrote:

The check on invalid RAM size is now performed in the SDRAM controller
but not all values will boot a machine. A minimum of 2*16 is required.


2*16 or 16 MiB? The code has the latter which does not match commit 
message.


Regards,
BALATON Zoltan



Signed-off-by: Cédric Le Goater 
---
hw/ppc/ppc405_boards.c | 7 ++-
1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 4ff6715f3533..9a3fec38cce1 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -251,14 +251,11 @@ static void boot_from_kernel(MachineState *machine, 
PowerPCCPU *cpu)
static void ppc405_init(MachineState *machine)
{
Ppc405MachineState *ppc405 = PPC405_MACHINE(machine);
-MachineClass *mc = MACHINE_GET_CLASS(machine);
const char *kernel_filename = machine->kernel_filename;
MemoryRegion *sysmem = get_system_memory();

-if (machine->ram_size != mc->default_ram_size) {
-char *sz = size_to_str(mc->default_ram_size);
-error_report("Invalid RAM size, should be %s", sz);
-g_free(sz);
+if (machine->ram_size < 16 * MiB) {
+error_report("Not enough RAM !");
exit(EXIT_FAILURE);
}



Re: [PATCH RFC 0/7] hostmem: NUMA-aware memory preallocation using ThreadContext

2022-08-09 Thread David Hildenbrand
On 09.08.22 12:56, Joao Martins wrote:
> On 7/21/22 13:07, David Hildenbrand wrote:
>> This is a follow-up on "util: NUMA aware memory preallocation" [1] by
>> Michal.
>>
>> Setting the CPU affinity of threads from inside QEMU usually isn't
>> easily possible, because we don't want QEMU -- once started and running
>> guest code -- to be able to mess up the system. QEMU disallows relevant
>> syscalls using seccomp, such that any such invocation will fail.
>>
>> Especially for memory preallocation in memory backends, the CPU affinity
>> can significantly increase guest startup time, for example, when running
>> large VMs backed by huge/gigantic pages, because of NUMA effects. For
>> NUMA-aware preallocation, we have to set the CPU affinity, however:
>>
>> (1) Once preallocation threads are created during preallocation, management
>> tools cannot intercept anymore to change the affinity. These threads
>> are created automatically on demand.
>> (2) QEMU cannot easily set the CPU affinity itself.
>> (3) The CPU affinity derived from the NUMA bindings of the memory backend
>> might not necessarily be exactly the CPUs we actually want to use
>> (e.g., CPU-less NUMA nodes, CPUs that are pinned/used for other VMs).
>>
>> There is an easy "workaround". If we have a thread with the right CPU
>> affinity, we can simply create new threads on demand via that prepared
>> context. So, all we have to do is setup and create such a context ahead
>> of time, to then configure preallocation to create new threads via that
>> environment.
>>
>> So, let's introduce a user-creatable "thread-context" object that
>> essentially consists of a context thread used to create new threads.
>> QEMU can either try setting the CPU affinity itself ("cpu-affinity",
>> "node-affinity" property), or upper layers can extract the thread id
>> ("thread-id" property) to configure it externally.
>>
>> Make memory-backends consume a thread-context object
>> (via the "prealloc-context" property) and use it when preallocating to
>> create new threads with the desired CPU affinity. Further, to make it
>> easier to use, allow creation of "thread-context" objects, including
>> setting the CPU affinity directly from QEMU, *before* enabling the
>> sandbox option.
>>
>>
>> Quick test on a system with 2 NUMA nodes:
>>
>> Without CPU affinity:
>> time qemu-system-x86_64 \
>> -object 
>> memory-backend-memfd,id=md1,hugetlb=on,hugetlbsize=2M,size=64G,prealloc-threads=12,prealloc=on,host-nodes=0,policy=bind
>>  \
>> -nographic -monitor stdio
>>
>> real0m5.383s
>> real0m3.499s
>> real0m5.129s
>> real0m4.232s
>> real0m5.220s
>> real0m4.288s
>> real0m3.582s
>> real0m4.305s
>> real0m5.421s
>> real0m4.502s
>>
>> -> It heavily depends on the scheduler CPU selection
>>
>> With CPU affinity:
>> time qemu-system-x86_64 \
>> -object thread-context,id=tc1,node-affinity=0 \
>> -object 
>> memory-backend-memfd,id=md1,hugetlb=on,hugetlbsize=2M,size=64G,prealloc-threads=12,prealloc=on,host-nodes=0,policy=bind,prealloc-context=tc1
>>  \
>> -sandbox enable=on,resourcecontrol=deny \
>> -nographic -monitor stdio
>>
>> real0m1.959s
>> real0m1.942s
>> real0m1.943s
>> real0m1.941s
>> real0m1.948s
>> real0m1.964s
>> real0m1.949s
>> real0m1.948s
>> real0m1.941s
>> real0m1.937s
>>
>> On reasonably large VMs, the speedup can be quite significant.
>>
> Really awesome work!

Thanks!

> 
> I am not sure I picked up this well while reading the series, but it seems to 
> me that
> prealloc is still serialized on per memory-backend when solely configured by 
> command-line
> right?

I think it's serialized in any case, even when preallocation is
triggered manually using prealloc=on. I might be wrong, but any kind of
object creation or property changes should be serialized by the BQL.

In theory, we can "easily" preallocate in our helper --
qemu_prealloc_mem() -- concurrently when we don't have to bother about
handling SIGBUS -- that is, when the kernel supports
MADV_POPULATE_WRITE. Without MADV_POPULATE_WRITE on older kernels, we'll
serialize in there as well.

> 
> Meaning when we start prealloc we wait until the memory-backend 
> thread-context action is
> completed (per-memory-backend) even if other to-be-configured memory-backends 
> will use a
> thread-context on a separate set of pinned CPUs on another node ... and 
> wouldn't in theory
> "need" to wait until the former prealloc finishes?

Yes. This series only takes care of NUMA-aware preallocation, but
doesn't preallocate multiple memory backends in parallel.

In theory, it would be quite easy to preallocate concurrently: simply
create the memory backend objects passed on the QEMU cmdline
concurrently from multiple threads.

In practice, we have to be careful I think with the BQL. But it doesn't
sound 

Re: [PATCH v4 20/24] ppc/ppc405: Use an embedded PPCUIC model in SoC state

2022-08-09 Thread BALATON Zoltan

On Tue, 9 Aug 2022, Cédric Le Goater wrote:

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 


Reviewed-by: BALATON Zoltan 


---
hw/ppc/ppc405.h|  3 ++-
hw/ppc/ppc405_uc.c | 26 +-
2 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 31c94e474209..8e67ad0b72c3 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -27,6 +27,7 @@

#include "qom/object.h"
#include "hw/ppc/ppc4xx.h"
+#include "hw/intc/ppc-uic.h"

#define PPC405EP_SDRAM_BASE 0x
#define PPC405EP_NVRAM_BASE 0xF000
@@ -234,7 +235,7 @@ struct Ppc405SoCState {
hwaddr ram_size;

PowerPCCPU cpu;
-DeviceState *uic;
+PPCUIC uic;
Ppc405CpcState cpc;
Ppc405GptState gpt;
Ppc405OcmState ocm;
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 290cfa352bed..328224bb0620 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1350,6 +1350,8 @@ static void ppc405_soc_instance_init(Object *obj)
object_initialize_child(obj, "cpu", >cpu,
POWERPC_CPU_TYPE_NAME("405ep"));

+object_initialize_child(obj, "uic", >uic, TYPE_PPC_UIC);
+
object_initialize_child(obj, "cpc", >cpc, TYPE_PPC405_CPC);
object_property_add_alias(obj, "sys-clk", OBJECT(>cpc), "sys-clk");

@@ -1415,17 +1417,15 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
sysbus_mmio_map(SYS_BUS_DEVICE(>opba), 0, 0xef600600);

/* Universal interrupt controller */
-s->uic = qdev_new(TYPE_PPC_UIC);
-
-object_property_set_link(OBJECT(s->uic), "cpu", OBJECT(>cpu),
+object_property_set_link(OBJECT(>uic), "cpu", OBJECT(>cpu),
 _fatal);
-if (!sysbus_realize(SYS_BUS_DEVICE(s->uic), errp)) {
+if (!sysbus_realize(SYS_BUS_DEVICE(>uic), errp)) {
return;
}

-sysbus_connect_irq(SYS_BUS_DEVICE(s->uic), PPCUIC_OUTPUT_INT,
+sysbus_connect_irq(SYS_BUS_DEVICE(>uic), PPCUIC_OUTPUT_INT,
   qdev_get_gpio_in(DEVICE(>cpu), PPC40x_INPUT_INT));
-sysbus_connect_irq(SYS_BUS_DEVICE(s->uic), PPCUIC_OUTPUT_CINT,
+sysbus_connect_irq(SYS_BUS_DEVICE(>uic), PPCUIC_OUTPUT_CINT,
   qdev_get_gpio_in(DEVICE(>cpu), PPC40x_INPUT_CINT));

/* SDRAM controller */
@@ -1436,7 +1436,7 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 "ppc405.sdram0", s->dram_mr,
 s->ram_bases[0], s->ram_sizes[0]);

-ppc4xx_sdram_init(env, qdev_get_gpio_in(s->uic, 17), 1,
+ppc4xx_sdram_init(env, qdev_get_gpio_in(DEVICE(>uic), 17), 1,
  s->ram_banks, s->ram_bases, s->ram_sizes,
  s->do_dram_init);

@@ -1452,12 +1452,12 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)

for (i = 0; i < ARRAY_SIZE(s->dma.irqs); i++) {
sysbus_connect_irq(SYS_BUS_DEVICE(>dma), i,
-   qdev_get_gpio_in(s->uic, 5 + i));
+   qdev_get_gpio_in(DEVICE(>uic), 5 + i));
}

/* I2C controller */
sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500,
- qdev_get_gpio_in(s->uic, 2));
+ qdev_get_gpio_in(DEVICE(>uic), 2));

/* GPIO */
if (!sysbus_realize(SYS_BUS_DEVICE(>gpio), errp)) {
@@ -1468,13 +1468,13 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
/* Serial ports */
if (serial_hd(0) != NULL) {
serial_mm_init(get_system_memory(), 0xef600300, 0,
-   qdev_get_gpio_in(s->uic, 0),
+   qdev_get_gpio_in(DEVICE(>uic), 0),
   PPC_SERIAL_MM_BAUDBASE, serial_hd(0),
   DEVICE_BIG_ENDIAN);
}
if (serial_hd(1) != NULL) {
serial_mm_init(get_system_memory(), 0xef600400, 0,
-   qdev_get_gpio_in(s->uic, 1),
+   qdev_get_gpio_in(DEVICE(>uic), 1),
   PPC_SERIAL_MM_BAUDBASE, serial_hd(1),
   DEVICE_BIG_ENDIAN);
}
@@ -1492,7 +1492,7 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)

for (i = 0; i < ARRAY_SIZE(s->gpt.irqs); i++) {
sysbus_connect_irq(SYS_BUS_DEVICE(>gpt), i,
-   qdev_get_gpio_in(s->uic, 19 + i));
+   qdev_get_gpio_in(DEVICE(>uic), 19 + i));
}

/* MAL */
@@ -1504,7 +1504,7 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)

for (i = 0; i < ARRAY_SIZE(s->mal.irqs); i++) {
sysbus_connect_irq(SYS_BUS_DEVICE(>mal), i,
-   qdev_get_gpio_in(s->uic, 11 + i));
+   qdev_get_gpio_in(DEVICE(>uic), 11 + i));
}

/* Ethernet */


[PATCH v8 12/12] vdpa: Delete CVQ migration blocker

2022-08-09 Thread Eugenio Pérez
We can restore the device state in the destination via CVQ now. Remove
the migration blocker.

Signed-off-by: Eugenio Pérez 
Acked-by: Jason Wang 
---
 include/hw/virtio/vhost-vdpa.h |  1 -
 hw/virtio/vhost-vdpa.c | 14 --
 net/vhost-vdpa.c   |  2 --
 3 files changed, 17 deletions(-)

diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h
index d10a89303e..d85643 100644
--- a/include/hw/virtio/vhost-vdpa.h
+++ b/include/hw/virtio/vhost-vdpa.h
@@ -35,7 +35,6 @@ typedef struct vhost_vdpa {
 bool shadow_vqs_enabled;
 /* IOVA mapping used by the Shadow Virtqueue */
 VhostIOVATree *iova_tree;
-Error *migration_blocker;
 GPtrArray *shadow_vqs;
 const VhostShadowVirtqueueOps *shadow_vq_ops;
 void *shadow_vq_ops_opaque;
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 7e28d2f674..4b0cfc0f56 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -1033,13 +1033,6 @@ static bool vhost_vdpa_svqs_start(struct vhost_dev *dev)
 return true;
 }
 
-if (v->migration_blocker) {
-int r = migrate_add_blocker(v->migration_blocker, );
-if (unlikely(r < 0)) {
-return false;
-}
-}
-
 for (i = 0; i < v->shadow_vqs->len; ++i) {
 VirtQueue *vq = virtio_get_queue(dev->vdev, dev->vq_index + i);
 VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i);
@@ -1082,10 +1075,6 @@ err:
 vhost_svq_stop(svq);
 }
 
-if (v->migration_blocker) {
-migrate_del_blocker(v->migration_blocker);
-}
-
 return false;
 }
 
@@ -1105,9 +1094,6 @@ static bool vhost_vdpa_svqs_stop(struct vhost_dev *dev)
 }
 }
 
-if (v->migration_blocker) {
-migrate_del_blocker(v->migration_blocker);
-}
 return true;
 }
 
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index e775957952..188adb00b7 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -556,8 +556,6 @@ static NetClientState *net_vhost_vdpa_init(NetClientState 
*peer,
 
 s->vhost_vdpa.shadow_vq_ops = _vdpa_net_svq_ops;
 s->vhost_vdpa.shadow_vq_ops_opaque = s;
-error_setg(>vhost_vdpa.migration_blocker,
-   "Migration disabled: vhost-vdpa uses CVQ.");
 }
 ret = vhost_vdpa_add(nc, (void *)>vhost_vdpa, queue_pair_index, nvqs);
 if (ret) {
-- 
2.31.1




Re: [PATCH v4 22/24] ppc/ppc4xx: Fix sdram trace events

2022-08-09 Thread BALATON Zoltan

On Tue, 9 Aug 2022, Cédric Le Goater wrote:

Signed-off-by: Cédric Le Goater 


Reviewed-by: BALATON Zoltan 


---
hw/ppc/ppc4xx_devs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 8a8a87b03b28..c06c20b195cd 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -143,7 +143,7 @@ static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i,
}
sdram->bcr[i] = bcr & 0xFFDEE001;
if (enabled && (bcr & 0x0001)) {
-trace_ppc4xx_sdram_unmap(sdram_base(bcr), sdram_size(bcr));
+trace_ppc4xx_sdram_map(sdram_base(bcr), sdram_size(bcr));
memory_region_init(>containers[i], NULL, "sdram-containers",
   sdram_size(bcr));
memory_region_add_subregion(>containers[i], 0,


[PATCH v8 08/12] vdpa: Move command buffers map to start of net device

2022-08-09 Thread Eugenio Pérez
As this series will reuse them to restore the device state at the end of
a migration (or a device start), let's allocate only once at the device
start so we don't duplicate their map and unmap.

Signed-off-by: Eugenio Pérez 
---
 net/vhost-vdpa.c | 123 ++-
 1 file changed, 58 insertions(+), 65 deletions(-)

diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index 55e8a39a56..5254b58bdc 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -263,29 +263,20 @@ static size_t vhost_vdpa_net_cvq_cmd_page_len(void)
 return ROUND_UP(vhost_vdpa_net_cvq_cmd_len(), qemu_real_host_page_size());
 }
 
-/** Copy and map a guest buffer. */
-static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v,
-   const struct iovec *out_data,
-   size_t out_num, size_t data_len, void *buf,
-   size_t *written, bool write)
+/** Map CVQ buffer. */
+static int vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, void *buf, size_t size,
+  bool write)
 {
 DMAMap map = {};
 int r;
 
-if (unlikely(!data_len)) {
-qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid legnth of %s buffer\n",
-  __func__, write ? "in" : "out");
-return false;
-}
-
-*written = iov_to_buf(out_data, out_num, 0, buf, data_len);
 map.translated_addr = (hwaddr)(uintptr_t)buf;
-map.size = vhost_vdpa_net_cvq_cmd_page_len() - 1;
+map.size = size - 1;
 map.perm = write ? IOMMU_RW : IOMMU_RO,
 r = vhost_iova_tree_map_alloc(v->iova_tree, );
 if (unlikely(r != IOVA_OK)) {
 error_report("Cannot map injected element");
-return false;
+return r;
 }
 
 r = vhost_vdpa_dma_map(v, map.iova, vhost_vdpa_net_cvq_cmd_page_len(), buf,
@@ -294,50 +285,58 @@ static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v,
 goto dma_map_err;
 }
 
-return true;
+return 0;
 
 dma_map_err:
 vhost_iova_tree_remove(v->iova_tree, );
-return false;
+return r;
 }
 
-/**
- * Copy the guest element into a dedicated buffer suitable to be sent to NIC
- *
- * @iov: [0] is the out buffer, [1] is the in one
- */
-static bool vhost_vdpa_net_cvq_map_elem(VhostVDPAState *s,
-VirtQueueElement *elem,
-struct iovec *iov)
+static int vhost_vdpa_net_cvq_start(NetClientState *nc)
 {
-size_t in_copied;
-bool ok;
+VhostVDPAState *s;
+int r;
 
-iov[0].iov_base = s->cvq_cmd_out_buffer;
-ok = vhost_vdpa_cvq_map_buf(>vhost_vdpa, elem->out_sg, elem->out_num,
-vhost_vdpa_net_cvq_cmd_len(), iov[0].iov_base,
-[0].iov_len, false);
-if (unlikely(!ok)) {
-return false;
+assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
+
+s = DO_UPCAST(VhostVDPAState, nc, nc);
+if (!s->vhost_vdpa.shadow_vqs_enabled) {
+return 0;
 }
 
-iov[1].iov_base = s->cvq_cmd_in_buffer;
-ok = vhost_vdpa_cvq_map_buf(>vhost_vdpa, NULL, 0,
-sizeof(virtio_net_ctrl_ack), iov[1].iov_base,
-_copied, true);
-if (unlikely(!ok)) {
+r = vhost_vdpa_cvq_map_buf(>vhost_vdpa, s->cvq_cmd_out_buffer,
+   vhost_vdpa_net_cvq_cmd_page_len(), false);
+if (unlikely(r < 0)) {
+return r;
+}
+
+r = vhost_vdpa_cvq_map_buf(>vhost_vdpa, s->cvq_cmd_in_buffer,
+   vhost_vdpa_net_cvq_cmd_page_len(), true);
+if (unlikely(r < 0)) {
 vhost_vdpa_cvq_unmap_buf(>vhost_vdpa, s->cvq_cmd_out_buffer);
-return false;
 }
 
-iov[1].iov_len = sizeof(virtio_net_ctrl_ack);
-return true;
+return r;
+}
+
+static void vhost_vdpa_net_cvq_stop(NetClientState *nc)
+{
+VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
+
+assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
+
+if (s->vhost_vdpa.shadow_vqs_enabled) {
+vhost_vdpa_cvq_unmap_buf(>vhost_vdpa, s->cvq_cmd_out_buffer);
+vhost_vdpa_cvq_unmap_buf(>vhost_vdpa, s->cvq_cmd_in_buffer);
+}
 }
 
 static NetClientInfo net_vhost_vdpa_cvq_info = {
 .type = NET_CLIENT_DRIVER_VHOST_VDPA,
 .size = sizeof(VhostVDPAState),
 .receive = vhost_vdpa_receive,
+.start = vhost_vdpa_net_cvq_start,
+.stop = vhost_vdpa_net_cvq_stop,
 .cleanup = vhost_vdpa_cleanup,
 .has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
 .has_ufo = vhost_vdpa_has_ufo,
@@ -348,19 +347,17 @@ static NetClientInfo net_vhost_vdpa_cvq_info = {
  * Do not forward commands not supported by SVQ. Otherwise, the device could
  * accept it and qemu would not know how to update the device model.
  */
-static bool vhost_vdpa_net_cvq_validate_cmd(const struct iovec *out,
-size_t out_num)
+static bool 

[PATCH v8 07/12] vdpa: add net_vhost_vdpa_cvq_info NetClientInfo

2022-08-09 Thread Eugenio Pérez
Next patches will add a new info callback to restore NIC status through
CVQ. Since only the CVQ vhost device is needed, create it with a new
NetClientInfo.

Signed-off-by: Eugenio Pérez 
---
v5: Create a new NetClientInfo instead of reusing the dataplane one.
---
 net/vhost-vdpa.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index ac1810723c..55e8a39a56 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -334,6 +334,16 @@ static bool vhost_vdpa_net_cvq_map_elem(VhostVDPAState *s,
 return true;
 }
 
+static NetClientInfo net_vhost_vdpa_cvq_info = {
+.type = NET_CLIENT_DRIVER_VHOST_VDPA,
+.size = sizeof(VhostVDPAState),
+.receive = vhost_vdpa_receive,
+.cleanup = vhost_vdpa_cleanup,
+.has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
+.has_ufo = vhost_vdpa_has_ufo,
+.check_peer_type = vhost_vdpa_check_peer_type,
+};
+
 /**
  * Do not forward commands not supported by SVQ. Otherwise, the device could
  * accept it and qemu would not know how to update the device model.
@@ -475,7 +485,7 @@ static NetClientState *net_vhost_vdpa_init(NetClientState 
*peer,
 nc = qemu_new_net_client(_vhost_vdpa_info, peer, device,
  name);
 } else {
-nc = qemu_new_net_control_client(_vhost_vdpa_info, peer,
+nc = qemu_new_net_control_client(_vhost_vdpa_cvq_info, peer,
  device, name);
 }
 snprintf(nc->info_str, sizeof(nc->info_str), TYPE_VHOST_VDPA);
-- 
2.31.1




Re: [PATCH v4 23/24] ppc/ppc405: QOM'ify SDRAM

2022-08-09 Thread BALATON Zoltan

On Tue, 9 Aug 2022, Cédric Le Goater wrote:

This is an initial change of the SDRAM controller preserving the
compatibility with the current modeling. Further cleanup will be
possible after conversion of the ppc4xx_sdram_banks() and
ppc4xx_sdram_init() routines of the sam460ex and bamboo machines.

The size and base address of the RAM banks are now set using QOM
property arrays. RAM is equally distributed on each bank at the SoC
level depending on the number of banks we want to initialize (default
is 2). Each RAM memory region representing a RAM bank is initialized
in the realize routine of the SDRAM model after a minimal check on the
RAM size value with the sdram_bcr() routine. This has the benefit of
reporting an error to the user if the requested RAM size is invalid
for the SDRAM controller.


Haven't looked at it in detail yet but I think we have two versions of 
this (one in ppc4xx_devs.c and another in ppc440_uc.c) that are slightly 
different due to the differences of the memory controllers of later SoCs. 
I'm not sure how to clean this up and forgot most of the details about 
this.


Regards,
BALATON Zoltan


Signed-off-by: Cédric Le Goater 
---
hw/ppc/ppc405.h |   6 +--
include/hw/ppc/ppc4xx.h |  32 
hw/ppc/ppc405_uc.c  |  34 
hw/ppc/ppc4xx_devs.c| 113 
4 files changed, 140 insertions(+), 45 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 56881b181ba1..8c19d167391c 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -228,12 +228,9 @@ struct Ppc405SoCState {
DeviceState parent_obj;

/* Public */
-MemoryRegion ram_banks[2];
-hwaddr ram_bases[2], ram_sizes[2];
-bool do_dram_init;
-
MemoryRegion *dram_mr;
hwaddr ram_size;
+uint32_t nr_banks;

PowerPCCPU cpu;
PPCUIC uic;
@@ -241,6 +238,7 @@ struct Ppc405SoCState {
Ppc405GptState gpt;
Ppc405OcmState ocm;
Ppc405GpioState gpio;
+Ppc4xxSdramState sdram;
Ppc405DmaState dma;
PPC4xxI2CState i2c;
Ppc405EbcState ebc;
diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
index acd096cb2394..b841f6600b55 100644
--- a/include/hw/ppc/ppc4xx.h
+++ b/include/hw/ppc/ppc4xx.h
@@ -87,4 +87,36 @@ struct Ppc4xxMalState {
void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
 qemu_irq irqs[4]);

+/* SDRAM controller */
+#define TYPE_PPC4xx_SDRAM "ppc4xx-sdram"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxSdramState, PPC4xx_SDRAM);
+struct Ppc4xxSdramState {
+Ppc4xxDcrDeviceState parent_obj;
+
+MemoryRegion *dram_mr;
+bool dram_init;
+
+MemoryRegion containers[4]; /* used for clipping */
+MemoryRegion *ram_memories;
+hwaddr *ram_bases;
+hwaddr *ram_sizes;
+uint32_t nb_ram_bases;
+uint32_t nb_ram_sizes;
+uint32_t nbanks; /* Redundant */
+
+uint32_t addr;
+uint32_t besr0;
+uint32_t besr1;
+uint32_t bear;
+uint32_t cfg;
+uint32_t status;
+uint32_t rtr;
+uint32_t pmit;
+uint32_t bcr[4];
+uint32_t tr;
+uint32_t ecccfg;
+uint32_t eccesr;
+qemu_irq irq;
+};
+
#endif /* PPC4XX_H */
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 1045f5f13e6c..fe0c92ba0d54 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1361,6 +1361,9 @@ static void ppc405_soc_instance_init(Object *obj)

object_initialize_child(obj, "gpio", >gpio, TYPE_PPC405_GPIO);

+object_initialize_child(obj, "sdram", >sdram, TYPE_PPC4xx_SDRAM);
+object_property_add_alias(obj, "dram-init", OBJECT(>sdram), 
"dram-init");
+
object_initialize_child(obj, "dma", >dma, TYPE_PPC405_DMA);

object_initialize_child(obj, "i2c", >i2c, TYPE_PPC4xx_I2C);
@@ -1432,15 +1435,28 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)

/* SDRAM controller */
/* XXX 405EP has no ECC interrupt */
-s->ram_bases[0] = 0;
-s->ram_sizes[0] = s->ram_size;
-memory_region_init_alias(>ram_banks[0], OBJECT(s),
- "ppc405.sdram0", s->dram_mr,
- s->ram_bases[0], s->ram_sizes[0]);
+object_property_set_link(OBJECT(>sdram), "dram", OBJECT(s->dram_mr),
+ _abort);
+
+qdev_prop_set_uint32(DEVICE(>sdram), "len-ram-sizes", s->nr_banks);
+qdev_prop_set_uint32(DEVICE(>sdram), "len-ram-bases", s->nr_banks);

-ppc4xx_sdram_init(env, qdev_get_gpio_in(DEVICE(>uic), 17), 1,
-  s->ram_banks, s->ram_bases, s->ram_sizes,
-  s->do_dram_init);
+for (i = 0; i < s->nr_banks; i++) {
+char name[32];
+snprintf(name, sizeof(name), "ram-bases[%d]", i);
+qdev_prop_set_uint32(DEVICE(>sdram), name,
+ i * s->ram_size / s->nr_banks);
+
+snprintf(name, sizeof(name), "ram-sizes[%d]", i);
+qdev_prop_set_uint32(DEVICE(>sdram), name,
+ s->ram_size / s->nr_banks);
+}
+
+if 

[PATCH v8 05/12] vhost_net: Add NetClientInfo prepare callback

2022-08-09 Thread Eugenio Pérez
This is used by the backend to perform actions before the device is
started.

In particular, vdpa net use it to map CVQ buffers to the device, so it
can send control commands using them.

Signed-off-by: Eugenio Pérez 
---
v8: Rename NetClientInfo prepare callback to start, so it aligns with
future "stop"
---
 include/net/net.h  | 2 ++
 hw/net/vhost_net.c | 7 +++
 2 files changed, 9 insertions(+)

diff --git a/include/net/net.h b/include/net/net.h
index 523136c7ac..ad9e80083a 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -44,6 +44,7 @@ typedef struct NICConf {
 
 typedef void (NetPoll)(NetClientState *, bool enable);
 typedef bool (NetCanReceive)(NetClientState *);
+typedef int (NetStart)(NetClientState *);
 typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t);
 typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int);
 typedef void (NetCleanup) (NetClientState *);
@@ -71,6 +72,7 @@ typedef struct NetClientInfo {
 NetReceive *receive_raw;
 NetReceiveIOV *receive_iov;
 NetCanReceive *can_receive;
+NetStart *start;
 NetCleanup *cleanup;
 LinkStatusChanged *link_status_changed;
 QueryRxFilter *query_rx_filter;
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index ccac5b7a64..2e0baeba26 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -244,6 +244,13 @@ static int vhost_net_start_one(struct vhost_net *net,
 struct vhost_vring_file file = { };
 int r;
 
+if (net->nc->info->start) {
+r = net->nc->info->start(net->nc);
+if (r < 0) {
+return r;
+}
+}
+
 r = vhost_dev_enable_notifiers(>dev, dev);
 if (r < 0) {
 goto fail_notifiers;
-- 
2.31.1




Re: [PATCH v4 04/24] ppc/ppc405: Move SRAM under the ref405ep machine

2022-08-09 Thread Cédric Le Goater

On 8/9/22 18:53, BALATON Zoltan wrote:

On Tue, 9 Aug 2022, Cédric Le Goater wrote:

It doesn't belong to the generic machine nor the SoC. Fix a typo in
the name while we are at it.

Signed-off-by: Cédric Le Goater 
---
hw/ppc/ppc405_boards.c | 12 ++--
1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index f4794ba40ce6..381f39aa94cb 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -235,7 +235,6 @@ static void ppc405_init(MachineState *machine)
    MachineClass *mc = MACHINE_GET_CLASS(machine);
    const char *kernel_filename = machine->kernel_filename;
    PowerPCCPU *cpu;
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
    MemoryRegion *ram_memories = g_new(MemoryRegion, 2);
    hwaddr ram_bases[2], ram_sizes[2];
    MemoryRegion *sysmem = get_system_memory();
@@ -260,11 +259,6 @@ static void ppc405_init(MachineState *machine)
    cpu = ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
    , , kernel_filename == NULL ? 0 : 1);

-    /* allocate SRAM */
-    memory_region_init_ram(sram, NULL, "ef405ep.sram", PPC405EP_SRAM_SIZE,
-   _fatal);


Do you need to set an owner while at it? Anyway,


A machine is not a device and :

/* This will assert if owner is neither NULL nor a DeviceState.
 * We only want the owner here for the purposes of defining a
 * unique name for migration. TODO: Ideally we should implement
 * a naming scheme for Objects which are not DeviceStates, in
 * which case we can relax this restriction.
 */
owner_dev = DEVICE(owner);
 


Thanks,

C.



Reviewed-by: BALATON Zoltan 

Regards,
BALATON Zoltan


-    memory_region_add_subregion(sysmem, PPC405EP_SRAM_BASE, sram);
-
    /* allocate and load BIOS */
    if (machine->firmware) {
    MemoryRegion *bios = g_new(MemoryRegion, 1);
@@ -328,9 +322,15 @@ static void ref405ep_init(MachineState *machine)
{
    DeviceState *dev;
    SysBusDevice *s;
+    MemoryRegion *sram = g_new(MemoryRegion, 1);

    ppc405_init(machine);

+    /* allocate SRAM */
+    memory_region_init_ram(sram, NULL, "ref405ep.sram", PPC405EP_SRAM_SIZE,
+   _fatal);
+    memory_region_add_subregion(get_system_memory(), PPC405EP_SRAM_BASE, sram);
+
    /* Register FPGA */
    ref405ep_fpga_init(get_system_memory(), PPC405EP_FPGA_BASE);
    /* Register NVRAM */






Re: [PATCH v4 21/24] ppc/ppc405: Use an explicit I2C object

2022-08-09 Thread BALATON Zoltan

On Tue, 9 Aug 2022, Cédric Le Goater wrote:

Having an explicit I2C model object will help if one day we want to
add I2C devices on the bus from the machine init routine.

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
hw/ppc/ppc405.h|  2 ++
hw/ppc/ppc405_uc.c | 10 --
2 files changed, 10 insertions(+), 2 deletions(-)


This just seems to turn 2 lines into 10 for no apparent reason so I don't 
see what is this patch is good for but I don't really mind. I this is 
really needed to add an i2c device then maybe we have a problem in QEMU 
which makes it more difficult to access things than it should be. There 
should be a way to get a bus without havnig to have a pointer to the 
controller or again we need a way to navigate the qom three here.


But this is only a comment not a complaint as I've said above I don't 
mind.


Regards,
BALATON Zoltan



diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 8e67ad0b72c3..56881b181ba1 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -28,6 +28,7 @@
#include "qom/object.h"
#include "hw/ppc/ppc4xx.h"
#include "hw/intc/ppc-uic.h"
+#include "hw/i2c/ppc4xx_i2c.h"

#define PPC405EP_SDRAM_BASE 0x
#define PPC405EP_NVRAM_BASE 0xF000
@@ -241,6 +242,7 @@ struct Ppc405SoCState {
Ppc405OcmState ocm;
Ppc405GpioState gpio;
Ppc405DmaState dma;
+PPC4xxI2CState i2c;
Ppc405EbcState ebc;
Ppc405OpbaState opba;
Ppc405PobState pob;
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 328224bb0620..1045f5f13e6c 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1363,6 +1363,8 @@ static void ppc405_soc_instance_init(Object *obj)

object_initialize_child(obj, "dma", >dma, TYPE_PPC405_DMA);

+object_initialize_child(obj, "i2c", >i2c, TYPE_PPC4xx_I2C);
+
object_initialize_child(obj, "ebc", >ebc, TYPE_PPC405_EBC);

object_initialize_child(obj, "opba", >opba, TYPE_PPC405_OPBA);
@@ -1456,8 +1458,12 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
}

/* I2C controller */
-sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500,
- qdev_get_gpio_in(DEVICE(>uic), 2));
+if (!sysbus_realize(SYS_BUS_DEVICE(>i2c), errp)) {
+return;
+}
+sysbus_mmio_map(SYS_BUS_DEVICE(>i2c), 0, 0xef600500);
+sysbus_connect_irq(SYS_BUS_DEVICE(>i2c), 0,
+   qdev_get_gpio_in(DEVICE(>uic), 2));

/* GPIO */
if (!sysbus_realize(SYS_BUS_DEVICE(>gpio), errp)) {


[PATCH v8 02/12] vhost: use SVQ element ndescs instead of opaque data for desc validation

2022-08-09 Thread Eugenio Pérez
Since we're going to allow SVQ to add elements without the guest's
knowledge and without its own VirtQueueElement, it's easier to check if
an element is a valid head checking a different thing than the
VirtQueueElement.

Signed-off-by: Eugenio Pérez 
Acked-by: Jason Wang 
---
 hw/virtio/vhost-shadow-virtqueue.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/virtio/vhost-shadow-virtqueue.c 
b/hw/virtio/vhost-shadow-virtqueue.c
index ffd2b2c972..e6eebd0e8d 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -414,7 +414,7 @@ static VirtQueueElement 
*vhost_svq_get_buf(VhostShadowVirtqueue *svq,
 return NULL;
 }
 
-if (unlikely(!svq->desc_state[used_elem.id].elem)) {
+if (unlikely(!svq->desc_state[used_elem.id].ndescs)) {
 qemu_log_mask(LOG_GUEST_ERROR,
 "Device %s says index %u is used, but it was not available",
 svq->vdev->name, used_elem.id);
@@ -422,6 +422,7 @@ static VirtQueueElement 
*vhost_svq_get_buf(VhostShadowVirtqueue *svq,
 }
 
 num = svq->desc_state[used_elem.id].ndescs;
+svq->desc_state[used_elem.id].ndescs = 0;
 last_used_chain = vhost_svq_last_desc_of_chain(svq, num, used_elem.id);
 svq->desc_next[last_used_chain] = svq->free_head;
 svq->free_head = used_elem.id;
-- 
2.31.1




[PATCH v8 11/12] vdpa: Add virtio-net mac address via CVQ at start

2022-08-09 Thread Eugenio Pérez
This is needed so the destination vdpa device see the same state a the
guest set in the source.

Signed-off-by: Eugenio Pérez 
---
v8:
* Delete unneeded copy from device's in buffer.

v6:
* Map and unmap command buffers at the start and end of device usage.

v5:
* Rename s/start/load/
* Use independent NetClientInfo to only add load callback on cvq.
---
 net/vhost-vdpa.c | 41 +
 1 file changed, 41 insertions(+)

diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index df85567cff..e775957952 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -363,11 +363,52 @@ static ssize_t vhost_vdpa_net_cvq_add(VhostVDPAState *s, 
size_t out_len,
 return vhost_svq_poll(svq);
 }
 
+static int vhost_vdpa_net_load(NetClientState *nc)
+{
+VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
+struct vhost_vdpa *v = >vhost_vdpa;
+VirtIONet *n;
+uint64_t features;
+
+assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
+
+if (!v->shadow_vqs_enabled) {
+return 0;
+}
+
+n = VIRTIO_NET(v->dev->vdev);
+features = v->dev->vdev->host_features;
+if (features & BIT_ULL(VIRTIO_NET_F_CTRL_MAC_ADDR)) {
+const struct virtio_net_ctrl_hdr ctrl = {
+.class = VIRTIO_NET_CTRL_MAC,
+.cmd = VIRTIO_NET_CTRL_MAC_ADDR_SET,
+};
+char *cursor = s->cvq_cmd_out_buffer;
+ssize_t dev_written;
+
+memcpy(cursor, , sizeof(ctrl));
+cursor += sizeof(ctrl);
+memcpy(cursor, n->mac, sizeof(n->mac));
+cursor += sizeof(n->mac);
+
+dev_written = vhost_vdpa_net_cvq_add(s, sizeof(ctrl) + sizeof(n->mac),
+ sizeof(virtio_net_ctrl_ack));
+if (unlikely(dev_written < 0)) {
+return dev_written;
+}
+
+return *((virtio_net_ctrl_ack *)s->cvq_cmd_in_buffer) != VIRTIO_NET_OK;
+}
+
+return 0;
+}
+
 static NetClientInfo net_vhost_vdpa_cvq_info = {
 .type = NET_CLIENT_DRIVER_VHOST_VDPA,
 .size = sizeof(VhostVDPAState),
 .receive = vhost_vdpa_receive,
 .start = vhost_vdpa_net_cvq_start,
+.load = vhost_vdpa_net_load,
 .stop = vhost_vdpa_net_cvq_stop,
 .cleanup = vhost_vdpa_cleanup,
 .has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
-- 
2.31.1




[PATCH v8 09/12] vdpa: extract vhost_vdpa_net_cvq_add from vhost_vdpa_net_handle_ctrl_avail

2022-08-09 Thread Eugenio Pérez
So we can reuse it to inject state messages.

Signed-off-by: Eugenio Pérez 
Acked-by: Jason Wang 
--
v7:
* Remove double free error

v6:
* Do not assume in buffer sent to the device is sizeof(virtio_net_ctrl_ack)

v5:
* Do not use an artificial !NULL VirtQueueElement
* Use only out size instead of iovec dev_buffers for these functions.
---
 net/vhost-vdpa.c | 59 +++-
 1 file changed, 38 insertions(+), 21 deletions(-)

diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index 5254b58bdc..df85567cff 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -331,6 +331,38 @@ static void vhost_vdpa_net_cvq_stop(NetClientState *nc)
 }
 }
 
+static ssize_t vhost_vdpa_net_cvq_add(VhostVDPAState *s, size_t out_len,
+  size_t in_len)
+{
+/* Buffers for the device */
+const struct iovec out = {
+.iov_base = s->cvq_cmd_out_buffer,
+.iov_len = out_len,
+};
+const struct iovec in = {
+.iov_base = s->cvq_cmd_in_buffer,
+.iov_len = sizeof(virtio_net_ctrl_ack),
+};
+VhostShadowVirtqueue *svq = g_ptr_array_index(s->vhost_vdpa.shadow_vqs, 0);
+int r;
+
+r = vhost_svq_add(svq, , 1, , 1, NULL);
+if (unlikely(r != 0)) {
+if (unlikely(r == -ENOSPC)) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: No space on device queue\n",
+  __func__);
+}
+return r;
+}
+
+/*
+ * We can poll here since we've had BQL from the time we sent the
+ * descriptor. Also, we need to take the answer before SVQ pulls by itself,
+ * when BQL is released
+ */
+return vhost_svq_poll(svq);
+}
+
 static NetClientInfo net_vhost_vdpa_cvq_info = {
 .type = NET_CLIENT_DRIVER_VHOST_VDPA,
 .size = sizeof(VhostVDPAState),
@@ -387,23 +419,18 @@ static int 
vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq,
 void *opaque)
 {
 VhostVDPAState *s = opaque;
-size_t in_len, dev_written;
+size_t in_len;
 virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
 /* Out buffer sent to both the vdpa device and the device model */
 struct iovec out = {
 .iov_base = s->cvq_cmd_out_buffer,
 };
-/* In buffer sent to the device */
-const struct iovec dev_in = {
-.iov_base = s->cvq_cmd_in_buffer,
-.iov_len = sizeof(virtio_net_ctrl_ack),
-};
 /* in buffer used for device model */
 const struct iovec in = {
 .iov_base = ,
 .iov_len = sizeof(status),
 };
-int r = -EINVAL;
+ssize_t dev_written = -EINVAL;
 bool ok;
 
 out.iov_len = iov_to_buf(elem->out_sg, elem->out_num, 0,
@@ -414,21 +441,11 @@ static int 
vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq,
 goto out;
 }
 
-r = vhost_svq_add(svq, , 1, _in, 1, elem);
-if (unlikely(r != 0)) {
-if (unlikely(r == -ENOSPC)) {
-qemu_log_mask(LOG_GUEST_ERROR, "%s: No space on device queue\n",
-  __func__);
-}
+dev_written = vhost_vdpa_net_cvq_add(s, out.iov_len, sizeof(status));
+if (unlikely(dev_written < 0)) {
 goto out;
 }
 
-/*
- * We can poll here since we've had BQL from the time we sent the
- * descriptor. Also, we need to take the answer before SVQ pulls by itself,
- * when BQL is released
- */
-dev_written = vhost_svq_poll(svq);
 if (unlikely(dev_written < sizeof(status))) {
 error_report("Insufficient written data (%zu)", dev_written);
 goto out;
@@ -436,7 +453,7 @@ static int 
vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq,
 
 memcpy(, s->cvq_cmd_in_buffer, sizeof(status));
 if (status != VIRTIO_NET_OK) {
-goto out;
+return VIRTIO_NET_ERR;
 }
 
 status = VIRTIO_NET_ERR;
@@ -453,7 +470,7 @@ out:
 }
 vhost_svq_push_elem(svq, elem, MIN(in_len, sizeof(status)));
 g_free(elem);
-return r;
+return dev_written < 0 ? dev_written : 0;
 }
 
 static const VhostShadowVirtqueueOps vhost_vdpa_net_svq_ops = {
-- 
2.31.1




[PATCH v8 04/12] vhost: Do not depend on !NULL VirtQueueElement on vhost_svq_flush

2022-08-09 Thread Eugenio Pérez
Since QEMU will be able to inject new elements on CVQ to restore the
state, we need not to depend on a VirtQueueElement to know if a new
element has been used by the device or not. Instead of check that, check
if there are new elements only using used idx on vhost_svq_flush.

Signed-off-by: Eugenio Pérez 
Acked-by: Jason Wang 
---
v6: Change less from the previous function
---
 hw/virtio/vhost-shadow-virtqueue.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/hw/virtio/vhost-shadow-virtqueue.c 
b/hw/virtio/vhost-shadow-virtqueue.c
index 1b49bf54f2..f863b08627 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -499,17 +499,20 @@ static void vhost_svq_flush(VhostShadowVirtqueue *svq,
 size_t vhost_svq_poll(VhostShadowVirtqueue *svq)
 {
 int64_t start_us = g_get_monotonic_time();
+uint32_t len;
+
 do {
-uint32_t len;
-VirtQueueElement *elem = vhost_svq_get_buf(svq, );
-if (elem) {
-return len;
+if (vhost_svq_more_used(svq)) {
+break;
 }
 
 if (unlikely(g_get_monotonic_time() - start_us > 10e6)) {
 return 0;
 }
 } while (true);
+
+vhost_svq_get_buf(svq, );
+return len;
 }
 
 /**
-- 
2.31.1




[PATCH v8 10/12] vhost_net: add NetClientState->load() callback

2022-08-09 Thread Eugenio Pérez
It allows per-net client operations right after device's successful
start. In particular, to load the device status.

Vhost-vdpa net will use it to add the CVQ buffers to restore the device
status.

Signed-off-by: Eugenio Pérez 
---
v5: Rename start / load, naming it more specifically.
---
 include/net/net.h  | 2 ++
 hw/net/vhost_net.c | 7 +++
 2 files changed, 9 insertions(+)

diff --git a/include/net/net.h b/include/net/net.h
index 476ad45b9a..81d0b21def 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -45,6 +45,7 @@ typedef struct NICConf {
 typedef void (NetPoll)(NetClientState *, bool enable);
 typedef bool (NetCanReceive)(NetClientState *);
 typedef int (NetStart)(NetClientState *);
+typedef int (NetLoad)(NetClientState *);
 typedef void (NetStop)(NetClientState *);
 typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t);
 typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int);
@@ -74,6 +75,7 @@ typedef struct NetClientInfo {
 NetReceiveIOV *receive_iov;
 NetCanReceive *can_receive;
 NetStart *start;
+NetLoad *load;
 NetStop *stop;
 NetCleanup *cleanup;
 LinkStatusChanged *link_status_changed;
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 9d4b334453..d28f8b974b 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -281,6 +281,13 @@ static int vhost_net_start_one(struct vhost_net *net,
 }
 }
 }
+
+if (net->nc->info->load) {
+r = net->nc->info->load(net->nc);
+if (r < 0) {
+goto fail;
+}
+}
 return 0;
 fail:
 file.fd = -1;
-- 
2.31.1




[PATCH v8 03/12] vhost: Delete useless read memory barrier

2022-08-09 Thread Eugenio Pérez
As discussed in previous series [1], this memory barrier is useless with
the atomic read of used idx at vhost_svq_more_used. Deleting it.

[1] https://lists.nongnu.org/archive/html/qemu-devel/2022-07/msg02616.html

Signed-off-by: Eugenio Pérez 
Acked-by: Jason Wang 
---
 hw/virtio/vhost-shadow-virtqueue.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/hw/virtio/vhost-shadow-virtqueue.c 
b/hw/virtio/vhost-shadow-virtqueue.c
index e6eebd0e8d..1b49bf54f2 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -509,9 +509,6 @@ size_t vhost_svq_poll(VhostShadowVirtqueue *svq)
 if (unlikely(g_get_monotonic_time() - start_us > 10e6)) {
 return 0;
 }
-
-/* Make sure we read new used_idx */
-smp_rmb();
 } while (true);
 }
 
-- 
2.31.1




[PATCH v8 01/12] vhost: stop transfer elem ownership in vhost_handle_guest_kick

2022-08-09 Thread Eugenio Pérez
It was easier to allow vhost_svq_add to handle the memory. Now that we
will allow qemu to add elements to a SVQ without the guest's knowledge,
it's better to handle it in the caller.

Signed-off-by: Eugenio Pérez 
Acked-by: Jason Wang 
---
 hw/virtio/vhost-shadow-virtqueue.c | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/hw/virtio/vhost-shadow-virtqueue.c 
b/hw/virtio/vhost-shadow-virtqueue.c
index e4956728dd..ffd2b2c972 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -233,9 +233,6 @@ static void vhost_svq_kick(VhostShadowVirtqueue *svq)
 /**
  * Add an element to a SVQ.
  *
- * The caller must check that there is enough slots for the new element. It
- * takes ownership of the element: In case of failure not ENOSPC, it is free.
- *
  * Return -EINVAL if element is invalid, -ENOSPC if dev queue is full
  */
 int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg,
@@ -252,7 +249,6 @@ int vhost_svq_add(VhostShadowVirtqueue *svq, const struct 
iovec *out_sg,
 
 ok = vhost_svq_add_split(svq, out_sg, out_num, in_sg, in_num, _head);
 if (unlikely(!ok)) {
-g_free(elem);
 return -EINVAL;
 }
 
@@ -293,7 +289,7 @@ static void vhost_handle_guest_kick(VhostShadowVirtqueue 
*svq)
 virtio_queue_set_notification(svq->vq, false);
 
 while (true) {
-VirtQueueElement *elem;
+g_autofree VirtQueueElement *elem;
 int r;
 
 if (svq->next_guest_avail_elem) {
@@ -324,12 +320,14 @@ static void vhost_handle_guest_kick(VhostShadowVirtqueue 
*svq)
  * queue the current guest descriptor and ignore kicks
  * until some elements are used.
  */
-svq->next_guest_avail_elem = elem;
+svq->next_guest_avail_elem = g_steal_pointer();
 }
 
 /* VQ is full or broken, just return and ignore kicks */
 return;
 }
+/* elem belongs to SVQ or external caller now */
+elem = NULL;
 }
 
 virtio_queue_set_notification(svq->vq, true);
-- 
2.31.1




[PATCH v8 06/12] vhost_net: Add NetClientInfo stop callback

2022-08-09 Thread Eugenio Pérez
Used by the backend to perform actions after the device is stopped.

In particular, vdpa net use it to unmap CVQ buffers to the device,
cleaning the actions performend in prepare().

Signed-off-by: Eugenio Pérez 
---
 include/net/net.h  | 2 ++
 hw/net/vhost_net.c | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/include/net/net.h b/include/net/net.h
index ad9e80083a..476ad45b9a 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -45,6 +45,7 @@ typedef struct NICConf {
 typedef void (NetPoll)(NetClientState *, bool enable);
 typedef bool (NetCanReceive)(NetClientState *);
 typedef int (NetStart)(NetClientState *);
+typedef void (NetStop)(NetClientState *);
 typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t);
 typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int);
 typedef void (NetCleanup) (NetClientState *);
@@ -73,6 +74,7 @@ typedef struct NetClientInfo {
 NetReceiveIOV *receive_iov;
 NetCanReceive *can_receive;
 NetStart *start;
+NetStop *stop;
 NetCleanup *cleanup;
 LinkStatusChanged *link_status_changed;
 QueryRxFilter *query_rx_filter;
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 2e0baeba26..9d4b334453 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -320,6 +320,9 @@ static void vhost_net_stop_one(struct vhost_net *net,
 net->nc->info->poll(net->nc, true);
 }
 vhost_dev_stop(>dev, dev);
+if (net->nc->info->stop) {
+net->nc->info->stop(net->nc);
+}
 vhost_dev_disable_notifiers(>dev, dev);
 }
 
-- 
2.31.1




[PATCH v8 00/12] NIC vhost-vdpa state restore via Shadow CVQ

2022-08-09 Thread Eugenio Pérez
CVQ of net vhost-vdpa devices can be intercepted since the addition of x-svq.
The virtio-net device model is updated. The migration was blocked because
although the state can be megrated between VMM it was not possible to restore
on the destination NIC.

This series add support for SVQ to inject external messages without the guest's
knowledge, so before the guest is resumed all the guest visible state is
restored. It is done using standard CVQ messages, so the vhost-vdpa device does
not need to learn how to restore it: As long as they have the feature, they
know how to handle it.

This series needs fix [1] to be applied to achieve full live
migration.

Thanks!

[1] https://lists.nongnu.org/archive/html/qemu-devel/2022-08/msg00325.html

v8:
- Rename NetClientInfo load to start, so is symmetrical with stop()
- Delete copy of device's in buffer at vhost_vdpa_net_load

v7:
- Remove accidental double free.

v6:
- Move map and unmap of the buffers to the start and stop of the device. This
  implies more callbacks on NetClientInfo, but simplifies the SVQ CVQ code.
- Not assume that in buffer is sizeof(virtio_net_ctrl_ack) in
  vhost_vdpa_net_cvq_add
- Reduce the number of changes from previous versions
- Delete unused memory barrier

v5:
- Rename s/start/load/
- Use independent NetClientInfo to only add load callback on cvq.
- Accept out sg instead of dev_buffers[] at vhost_vdpa_net_cvq_map_elem
- Use only out size instead of iovec dev_buffers to know if the descriptor is
  effectively available, allowing to delete artificial !NULL VirtQueueElement
  on vhost_svq_add call.

v4:
- Actually use NetClientInfo callback.

v3:
- Route vhost-vdpa start code through NetClientInfo callback.
- Delete extra vhost_net_stop_one() call.

v2:
- Fix SIGSEGV dereferencing SVQ when not in svq mode

v1 from RFC:
- Do not reorder DRIVER_OK & enable patches.
- Delete leftovers

Eugenio Pérez (12):
  vhost: stop transfer elem ownership in vhost_handle_guest_kick
  vhost: use SVQ element ndescs instead of opaque data for desc
validation
  vhost: Delete useless read memory barrier
  vhost: Do not depend on !NULL VirtQueueElement on vhost_svq_flush
  vhost_net: Add NetClientInfo prepare callback
  vhost_net: Add NetClientInfo stop callback
  vdpa: add net_vhost_vdpa_cvq_info NetClientInfo
  vdpa: Move command buffers map to start of net device
  vdpa: extract vhost_vdpa_net_cvq_add from
vhost_vdpa_net_handle_ctrl_avail
  vhost_net: add NetClientState->load() callback
  vdpa: Add virtio-net mac address via CVQ at start
  vdpa: Delete CVQ migration blocker

 include/hw/virtio/vhost-vdpa.h |   1 -
 include/net/net.h  |   6 +
 hw/net/vhost_net.c |  17 +++
 hw/virtio/vhost-shadow-virtqueue.c |  27 ++--
 hw/virtio/vhost-vdpa.c |  14 --
 net/vhost-vdpa.c   | 225 ++---
 6 files changed, 178 insertions(+), 112 deletions(-)

-- 
2.31.1





Re: [PATCH v4 07/24] ppc/ppc405: QOM'ify CPU

2022-08-09 Thread BALATON Zoltan


Since maybe there will be another version, this patch is still misnamed, I 
think it's not QOMifying but embeds the cpu in the soc.


Regards,
BALATON Zoltan

On Tue, 9 Aug 2022, Cédric Le Goater wrote:

Drop the use of ppc4xx_init() and duplicate a bit of code related to
clocks in the SoC realize routine. We will clean that up in the
following patches.

ppc_dcr_init() simply allocates default DCR handlers for the CPU. Maybe
this could be done in model initializer of the CPU families needing it.

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
hw/ppc/ppc405.h |  2 +-
include/hw/ppc/ppc4xx.h |  5 -
hw/ppc/ppc405_boards.c  |  2 +-
hw/ppc/ppc405_uc.c  | 40 ++--
hw/ppc/ppc4xx_devs.c| 32 
5 files changed, 32 insertions(+), 49 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index dc862bc8614c..8cc76cc8b3fe 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -79,7 +79,7 @@ struct Ppc405SoCState {
hwaddr ram_size;

uint32_t sysclk;
-PowerPCCPU *cpu;
+PowerPCCPU cpu;
DeviceState *uic;
};

diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
index 980f964b5a91..591e2421a343 100644
--- a/include/hw/ppc/ppc4xx.h
+++ b/include/hw/ppc/ppc4xx.h
@@ -28,11 +28,6 @@
#include "hw/ppc/ppc.h"
#include "exec/memory.h"

-/* PowerPC 4xx core initialization */
-PowerPCCPU *ppc4xx_init(const char *cpu_model,
-clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
-uint32_t sysclk);
-
void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
MemoryRegion ram_memories[],
hwaddr ram_bases[], hwaddr ram_sizes[],
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index b93e85b5d9bd..3677793adc75 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -313,7 +313,7 @@ static void ppc405_init(MachineState *machine)

/* Load ELF kernel and rootfs.cpio */
} else if (kernel_filename && !machine->firmware) {
-boot_from_kernel(machine, ppc405->soc.cpu);
+boot_from_kernel(machine, >soc.cpu);
}
}

diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index c05ab604367d..14a525b2eb74 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1432,22 +1432,41 @@ static void ppc405ep_cpc_init (CPUPPCState *env, 
clk_setup_t clk_setup[8],
#endif
}

+static void ppc405_soc_instance_init(Object *obj)
+{
+Ppc405SoCState *s = PPC405_SOC(obj);
+
+object_initialize_child(obj, "cpu", >cpu,
+POWERPC_CPU_TYPE_NAME("405ep"));
+}
+
+static void ppc405_reset(void *opaque)
+{
+cpu_reset(CPU(opaque));
+}
+
static void ppc405_soc_realize(DeviceState *dev, Error **errp)
{
Ppc405SoCState *s = PPC405_SOC(dev);
-clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup;
+clk_setup_t clk_setup[PPC405EP_CLK_NB];
qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4];
CPUPPCState *env;

memset(clk_setup, 0, sizeof(clk_setup));

/* init CPUs */
-s->cpu = ppc4xx_init(POWERPC_CPU_TYPE_NAME("405ep"),
-  _setup[PPC405EP_CPU_CLK],
-  _clk_setup, s->sysclk);
-env = >cpu->env;
-clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb;
-clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque;
+if (!qdev_realize(DEVICE(>cpu), NULL, errp)) {
+return;
+}
+qemu_register_reset(ppc405_reset, >cpu);
+
+env = >cpu.env;
+
+clk_setup[PPC405EP_CPU_CLK].cb =
+ppc_40x_timers_init(env, s->sysclk, PPC_INTERRUPT_PIT);
+clk_setup[PPC405EP_CPU_CLK].opaque = env;
+
+ppc_dcr_init(env, NULL, NULL);

/* CPU control */
ppc405ep_cpc_init(env, clk_setup, s->sysclk);
@@ -1464,16 +1483,16 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
/* Universal interrupt controller */
s->uic = qdev_new(TYPE_PPC_UIC);

-object_property_set_link(OBJECT(s->uic), "cpu", OBJECT(s->cpu),
+object_property_set_link(OBJECT(s->uic), "cpu", OBJECT(>cpu),
 _fatal);
if (!sysbus_realize(SYS_BUS_DEVICE(s->uic), errp)) {
return;
}

sysbus_connect_irq(SYS_BUS_DEVICE(s->uic), PPCUIC_OUTPUT_INT,
-   qdev_get_gpio_in(DEVICE(s->cpu), PPC40x_INPUT_INT));
+   qdev_get_gpio_in(DEVICE(>cpu), PPC40x_INPUT_INT));
sysbus_connect_irq(SYS_BUS_DEVICE(s->uic), PPCUIC_OUTPUT_CINT,
-   qdev_get_gpio_in(DEVICE(s->cpu), PPC40x_INPUT_CINT));
+   qdev_get_gpio_in(DEVICE(>cpu), PPC40x_INPUT_CINT));

/* SDRAM controller */
/* XXX 405EP has no ECC interrupt */
@@ -1563,6 +1582,7 @@ static const TypeInfo ppc405_types[] = {
.name   = TYPE_PPC405_SOC,
.parent = TYPE_DEVICE,
.instance_size  = sizeof(Ppc405SoCState),
+.instance_init  = ppc405_soc_instance_init,
.class_init = 

Re: [PATCH v4 19/24] ppc/ppc405: QOM'ify FPGA

2022-08-09 Thread BALATON Zoltan

On Tue, 9 Aug 2022, Cédric Le Goater wrote:

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
hw/ppc/ppc405_boards.c | 55 +-
1 file changed, 38 insertions(+), 17 deletions(-)

diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 3677793adc75..4ff6715f3533 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -71,18 +71,23 @@ struct Ppc405MachineState {
 * - NVRAM (0xF000)
 * - FPGA  (0xF030)
 */
-typedef struct ref405ep_fpga_t ref405ep_fpga_t;
-struct ref405ep_fpga_t {
+
+#define TYPE_REF405EP_FPGA "ref405ep-fpga"
+OBJECT_DECLARE_SIMPLE_TYPE(Ref405epFpgaState, REF405EP_FPGA);
+struct Ref405epFpgaState {
+SysBusDevice parent_obj;
+
+MemoryRegion iomem;
+
uint8_t reg0;
uint8_t reg1;
};

static uint64_t ref405ep_fpga_readb(void *opaque, hwaddr addr, unsigned size)
{
-ref405ep_fpga_t *fpga;
+Ref405epFpgaState *fpga = REF405EP_FPGA(opaque);
uint32_t ret;

-fpga = opaque;
switch (addr) {
case 0x0:
ret = fpga->reg0;
@@ -101,9 +106,8 @@ static uint64_t ref405ep_fpga_readb(void *opaque, hwaddr 
addr, unsigned size)
static void ref405ep_fpga_writeb(void *opaque, hwaddr addr, uint64_t value,
 unsigned size)
{
-ref405ep_fpga_t *fpga;
+Ref405epFpgaState *fpga = REF405EP_FPGA(opaque);

-fpga = opaque;
switch (addr) {
case 0x0:
/* Read only */
@@ -126,27 +130,39 @@ static const MemoryRegionOps ref405ep_fpga_ops = {
.endianness = DEVICE_BIG_ENDIAN,
};

-static void ref405ep_fpga_reset (void *opaque)
+static void ref405ep_fpga_reset(DeviceState *dev)
{
-ref405ep_fpga_t *fpga;
+Ref405epFpgaState *fpga = REF405EP_FPGA(dev);

-fpga = opaque;
fpga->reg0 = 0x00;
fpga->reg1 = 0x0F;
}

-static void ref405ep_fpga_init(MemoryRegion *sysmem, uint32_t base)
+static void ref405ep_fpga_realize(DeviceState *dev, Error **errp)
{
-ref405ep_fpga_t *fpga;
-MemoryRegion *fpga_memory = g_new(MemoryRegion, 1);
+Ref405epFpgaState *s = REF405EP_FPGA(dev);

-fpga = g_new0(ref405ep_fpga_t, 1);
-memory_region_init_io(fpga_memory, NULL, _fpga_ops, fpga,
+memory_region_init_io(>iomem, OBJECT(s), _fpga_ops, s,
  "fpga", 0x0100);
-memory_region_add_subregion(sysmem, base, fpga_memory);
-qemu_register_reset(_fpga_reset, fpga);
+sysbus_init_mmio(SYS_BUS_DEVICE(s), >iomem);
+}
+
+static void ref405ep_fpga_class_init(ObjectClass *oc, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(oc);
+
+dc->realize = ref405ep_fpga_realize;
+dc->user_creatable = false;


Comment missing (and I'd drop unnecessary QOM casts) but otherwise:

Reviewed-by: BALATON Zoltan 

Regards,
BALATON Zoltan


+dc->reset = ref405ep_fpga_reset;
}

+static const TypeInfo ref405ep_fpga_type = {
+.name = TYPE_REF405EP_FPGA,
+.parent = TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(Ref405epFpgaState),
+.class_init = ref405ep_fpga_class_init,
+};
+
/*
 * CPU reset handler when booting directly from a loaded kernel
 */
@@ -331,7 +347,11 @@ static void ref405ep_init(MachineState *machine)
memory_region_add_subregion(get_system_memory(), PPC405EP_SRAM_BASE, sram);

/* Register FPGA */
-ref405ep_fpga_init(get_system_memory(), PPC405EP_FPGA_BASE);
+dev = qdev_new(TYPE_REF405EP_FPGA);
+object_property_add_child(OBJECT(machine), "fpga", OBJECT(dev));
+sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), _fatal);
+sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, PPC405EP_FPGA_BASE);
+
/* Register NVRAM */
dev = qdev_new("sysbus-m48t08");
qdev_prop_set_int32(dev, "base-year", 1968);
@@ -376,6 +396,7 @@ static void ppc405_machine_init(void)
{
type_register_static(_machine_type);
type_register_static(_type);
+type_register_static(_fpga_type);
}

type_init(ppc405_machine_init)


Re: [PATCH v4 18/24] ppc/ppc405: QOM'ify MAL

2022-08-09 Thread BALATON Zoltan

On Tue, 9 Aug 2022, Cédric Le Goater wrote:

The Memory Access Layer (MAL) controller is currently modeled as a DCR
device with 4 IRQs. Also drop the ppc4xx_mal_init() helper and adapt
the sam460ex machine.

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
hw/ppc/ppc405.h |   1 +
include/hw/ppc/ppc4xx.h |  32 +-
hw/ppc/ppc405_uc.c  |  18 --
hw/ppc/ppc4xx_devs.c| 135 ++--
hw/ppc/sam460ex.c   |  16 +++--
5 files changed, 116 insertions(+), 86 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index cb34792daf6b..31c94e474209 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -244,6 +244,7 @@ struct Ppc405SoCState {
Ppc405OpbaState opba;
Ppc405PobState pob;
Ppc405PlbState plb;
+Ppc4xxMalState mal;
};

/* PowerPC 405 core */
diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
index 82e60b0e0742..acd096cb2394 100644
--- a/include/hw/ppc/ppc4xx.h
+++ b/include/hw/ppc/ppc4xx.h
@@ -26,6 +26,7 @@
#define PPC4XX_H

#include "hw/ppc/ppc.h"
+#include "hw/sysbus.h"


This looks odd to me as no line added below seems to need it. Does this 
hunk belong to an earlier patch? (Have you verified that each step 
compiles so it can be bisected?)


Regards,
BALATON Zoltan


#include "exec/memory.h"
#include "hw/sysbus.h"

@@ -40,9 +41,6 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int 
nbanks,
hwaddr *ram_sizes,
int do_init);

-void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
- qemu_irq irqs[4]);
-
#define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost"

/*
@@ -61,4 +59,32 @@ void ppc4xx_dcr_register(Ppc4xxDcrDeviceState *dev, int dcrn,
bool ppc4xx_dcr_realize(Ppc4xxDcrDeviceState *dev, PowerPCCPU *cpu,
Error **errp);

+/* Memory Access Layer (MAL) */
+#define TYPE_PPC4xx_MAL "ppc4xx-mal"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxMalState, PPC4xx_MAL);
+struct Ppc4xxMalState {
+Ppc4xxDcrDeviceState parent_obj;
+
+qemu_irq irqs[4];
+uint32_t cfg;
+uint32_t esr;
+uint32_t ier;
+uint32_t txcasr;
+uint32_t txcarr;
+uint32_t txeobisr;
+uint32_t txdeir;
+uint32_t rxcasr;
+uint32_t rxcarr;
+uint32_t rxeobisr;
+uint32_t rxdeir;
+uint32_t *txctpr;
+uint32_t *rxctpr;
+uint32_t *rcbs;
+uint8_t  txcnum;
+uint8_t  rxcnum;
+};
+
+void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
+ qemu_irq irqs[4]);
+
#endif /* PPC4XX_H */
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 7f4c616da67c..290cfa352bed 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1368,6 +1368,8 @@ static void ppc405_soc_instance_init(Object *obj)
object_initialize_child(obj, "pob", >pob, TYPE_PPC405_POB);

object_initialize_child(obj, "plb", >plb, TYPE_PPC405_PLB);
+
+object_initialize_child(obj, "mal", >mal, TYPE_PPC4xx_MAL);
}

static void ppc405_reset(void *opaque)
@@ -1378,7 +1380,6 @@ static void ppc405_reset(void *opaque)
static void ppc405_soc_realize(DeviceState *dev, Error **errp)
{
Ppc405SoCState *s = PPC405_SOC(dev);
-qemu_irq mal_irqs[4];
CPUPPCState *env;
int i;

@@ -1495,11 +1496,16 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
}

/* MAL */
-mal_irqs[0] = qdev_get_gpio_in(s->uic, 11);
-mal_irqs[1] = qdev_get_gpio_in(s->uic, 12);
-mal_irqs[2] = qdev_get_gpio_in(s->uic, 13);
-mal_irqs[3] = qdev_get_gpio_in(s->uic, 14);
-ppc4xx_mal_init(env, 4, 2, mal_irqs);
+object_property_set_int(OBJECT(>mal), "txc-num", 4, _abort);
+object_property_set_int(OBJECT(>mal), "rxc-num", 2, _abort);
+if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(>mal), >cpu, errp)) {
+return;
+}
+
+for (i = 0; i < ARRAY_SIZE(s->mal.irqs); i++) {
+sysbus_connect_irq(SYS_BUS_DEVICE(>mal), i,
+   qdev_get_gpio_in(s->uic, 11 + i));
+}

/* Ethernet */
/* Uses UIC IRQs 9, 15, 17 */
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index bce7ef461346..8a8a87b03b28 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -459,32 +459,10 @@ enum {
MAL0_RCBS1= 0x1E1,
};

-typedef struct ppc4xx_mal_t ppc4xx_mal_t;
-struct ppc4xx_mal_t {
-qemu_irq irqs[4];
-uint32_t cfg;
-uint32_t esr;
-uint32_t ier;
-uint32_t txcasr;
-uint32_t txcarr;
-uint32_t txeobisr;
-uint32_t txdeir;
-uint32_t rxcasr;
-uint32_t rxcarr;
-uint32_t rxeobisr;
-uint32_t rxdeir;
-uint32_t *txctpr;
-uint32_t *rxctpr;
-uint32_t *rcbs;
-uint8_t  txcnum;
-uint8_t  rxcnum;
-};
-
-static void ppc4xx_mal_reset(void *opaque)
+static void ppc4xx_mal_reset(DeviceState *dev)
{
-ppc4xx_mal_t *mal;
+Ppc4xxMalState *mal = PPC4xx_MAL(dev);

-mal = opaque;
mal->cfg = 0x0007C000;
mal->esr = 0x;
mal->ier = 0x;
@@ 

Re: [PATCH v4 08/24] ppc/ppc4xx: Introduce a DCR device model

2022-08-09 Thread BALATON Zoltan

On Tue, 9 Aug 2022, Cédric Le Goater wrote:

The Device Control Registers (DCR) of on-SoC devices are accessed by
software through the use of the mtdcr and mfdcr instructions. These
are converted in transactions on a side band bus, the DCR bus, which
connects the on-SoC devices to the CPU.

Ideally, we should model these accesses with a DCR namespace and DCR
memory regions but today the DCR handlers are installed in a DCR table
under the CPU. Instead introduce a little device model wrapper to hold
a CPU link and handle registration of DCR handlers.

The DCR device inherits from SysBus because most of these devices also
have MMIO regions and/or IRQs. Being a SysBusDevice makes things easier
to install the device model in the overall SoC.

The "cpu" link should be considered as modeling the piece of HW logic
connecting the device to the DCR bus.

Signed-off-by: Cédric Le Goater 
---
include/hw/ppc/ppc4xx.h | 17 
hw/ppc/ppc4xx_devs.c| 44 +
2 files changed, 61 insertions(+)

diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
index 591e2421a343..82e60b0e0742 100644
--- a/include/hw/ppc/ppc4xx.h
+++ b/include/hw/ppc/ppc4xx.h
@@ -27,6 +27,7 @@

#include "hw/ppc/ppc.h"
#include "exec/memory.h"
+#include "hw/sysbus.h"

void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
MemoryRegion ram_memories[],
@@ -44,4 +45,20 @@ void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, 
uint8_t rxcnum,

#define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost"

+/*
+ * Generic DCR device
+ */
+#define TYPE_PPC4xx_DCR_DEVICE "ppc4xx-dcr-device"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxDcrDeviceState, PPC4xx_DCR_DEVICE);
+struct Ppc4xxDcrDeviceState {
+SysBusDevice parent_obj;
+
+PowerPCCPU *cpu;
+};
+
+void ppc4xx_dcr_register(Ppc4xxDcrDeviceState *dev, int dcrn,
+ dcr_read_cb dcr_read, dcr_write_cb dcr_write);
+bool ppc4xx_dcr_realize(Ppc4xxDcrDeviceState *dev, PowerPCCPU *cpu,
+Error **errp);
+
#endif /* PPC4XX_H */
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 069b51195160..bce7ef461346 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -664,3 +664,47 @@ void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, 
uint8_t rxcnum,
 mal, _read_mal, _write_mal);
}
}
+
+void ppc4xx_dcr_register(Ppc4xxDcrDeviceState *dev, int dcrn,
+ dcr_read_cb dcr_read, dcr_write_cb dcr_write)


I still think this should have a separate void *opaque parameter for the 
callbacks and not pass dev for that as the callbacks could use anything 
they wish for that parameter. (Additionally this allows dropping a lot of 
QOM casts. If you want to see how often these are accessed, you can try 
-trace enable="ppc_dcr*"; on the machines and OS I've tested some are 
read/written frequently so I'd not add unnecessary overhead without a good 
reason.)


Otherwise:

Reviewed-by: BALATON Zoltan 

Regards,
BALATOn Zoltan


+{
+CPUPPCState *env;
+
+assert(dev->cpu);
+
+env = >cpu->env;
+
+ppc_dcr_register(env, dcrn, dev, dcr_read, dcr_write);
+}
+
+bool ppc4xx_dcr_realize(Ppc4xxDcrDeviceState *dev, PowerPCCPU *cpu,
+Error **errp)
+{
+object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), _abort);
+return sysbus_realize(SYS_BUS_DEVICE(dev), errp);
+}
+
+static Property ppc4xx_dcr_properties[] = {
+DEFINE_PROP_LINK("cpu", Ppc4xxDcrDeviceState, cpu, TYPE_POWERPC_CPU,
+ PowerPCCPU *),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ppc4xx_dcr_class_init(ObjectClass *oc, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(oc);
+
+device_class_set_props(dc, ppc4xx_dcr_properties);
+}
+
+static const TypeInfo ppc4xx_types[] = {
+{
+.name   = TYPE_PPC4xx_DCR_DEVICE,
+.parent = TYPE_SYS_BUS_DEVICE,
+.instance_size  = sizeof(Ppc4xxDcrDeviceState),
+.class_init = ppc4xx_dcr_class_init,
+.abstract   = true,
+}
+};
+
+DEFINE_TYPES(ppc4xx_types)


Re: [PATCH v4 06/24] ppc/ppc405: Start QOMification of the SoC

2022-08-09 Thread BALATON Zoltan

On Tue, 9 Aug 2022, Cédric Le Goater wrote:

This moves all the code previously done in the ppc405ep_init() routine
under ppc405_soc_realize(). We can also adjust the number of banks now
that we have control on ppc4xx_sdram_init().

Signed-off-by: Cédric Le Goater 


Reviewed-by: BALATON Zoltan 


---
hw/ppc/ppc405.h|  12 ++--
hw/ppc/ppc405_boards.c |  12 ++--
hw/ppc/ppc405_uc.c | 124 -
3 files changed, 71 insertions(+), 77 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 66dc21cdfed8..dc862bc8614c 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -73,9 +73,14 @@ struct Ppc405SoCState {
/* Public */
MemoryRegion ram_banks[2];
hwaddr ram_bases[2], ram_sizes[2];
+bool do_dram_init;

MemoryRegion *dram_mr;
hwaddr ram_size;
+
+uint32_t sysclk;
+PowerPCCPU *cpu;
+DeviceState *uic;
};

/* PowerPC 405 core */
@@ -84,11 +89,4 @@ ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t 
ram_size);
void ppc4xx_plb_init(CPUPPCState *env);
void ppc405_ebc_init(CPUPPCState *env);

-PowerPCCPU *ppc405ep_init(MemoryRegion *address_space_mem,
-MemoryRegion ram_memories[2],
-hwaddr ram_bases[2],
-hwaddr ram_sizes[2],
-uint32_t sysclk, DeviceState **uicdev,
-int do_init);
-
#endif /* PPC405_H */
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index f029d6f415f6..b93e85b5d9bd 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -237,9 +237,7 @@ static void ppc405_init(MachineState *machine)
Ppc405MachineState *ppc405 = PPC405_MACHINE(machine);
MachineClass *mc = MACHINE_GET_CLASS(machine);
const char *kernel_filename = machine->kernel_filename;
-PowerPCCPU *cpu;
MemoryRegion *sysmem = get_system_memory();
-DeviceState *uicdev;

if (machine->ram_size != mc->default_ram_size) {
char *sz = size_to_str(mc->default_ram_size);
@@ -254,12 +252,12 @@ static void ppc405_init(MachineState *machine)
 machine->ram_size, _fatal);
object_property_set_link(OBJECT(>soc), "dram",
 OBJECT(machine->ram), _abort);
+object_property_set_bool(OBJECT(>soc), "dram-init",
+ kernel_filename != NULL, _abort);
+object_property_set_uint(OBJECT(>soc), "sys-clk", ,
+ _abort);
qdev_realize(DEVICE(>soc), NULL, _fatal);

-cpu = ppc405ep_init(sysmem, ppc405->soc.ram_banks, ppc405->soc.ram_bases,
-ppc405->soc.ram_sizes,
-, , kernel_filename == NULL ? 0 : 1);
-
/* allocate and load BIOS */
if (machine->firmware) {
MemoryRegion *bios = g_new(MemoryRegion, 1);
@@ -315,7 +313,7 @@ static void ppc405_init(MachineState *machine)

/* Load ELF kernel and rootfs.cpio */
} else if (kernel_filename && !machine->firmware) {
-boot_from_kernel(machine, cpu);
+boot_from_kernel(machine, ppc405->soc.cpu);
}
}

diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index adadb3a0ae08..c05ab604367d 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1432,121 +1432,118 @@ static void ppc405ep_cpc_init (CPUPPCState *env, 
clk_setup_t clk_setup[8],
#endif
}

-PowerPCCPU *ppc405ep_init(MemoryRegion *address_space_mem,
-MemoryRegion ram_memories[2],
-hwaddr ram_bases[2],
-hwaddr ram_sizes[2],
-uint32_t sysclk, DeviceState **uicdevp,
-int do_init)
+static void ppc405_soc_realize(DeviceState *dev, Error **errp)
{
+Ppc405SoCState *s = PPC405_SOC(dev);
clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup;
qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4];
-PowerPCCPU *cpu;
CPUPPCState *env;
-DeviceState *uicdev;
-SysBusDevice *uicsbd;

memset(clk_setup, 0, sizeof(clk_setup));
+
/* init CPUs */
-cpu = ppc4xx_init(POWERPC_CPU_TYPE_NAME("405ep"),
+s->cpu = ppc4xx_init(POWERPC_CPU_TYPE_NAME("405ep"),
  _setup[PPC405EP_CPU_CLK],
-  _clk_setup, sysclk);
-env = >env;
+  _clk_setup, s->sysclk);
+env = >cpu->env;
clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb;
clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque;
-/* Internal devices init */
-/* Memory mapped devices registers */
+
+/* CPU control */
+ppc405ep_cpc_init(env, clk_setup, s->sysclk);
+
/* PLB arbitrer */
ppc4xx_plb_init(env);
+
/* PLB to OPB bridge */
ppc4xx_pob_init(env);
+
/* OBP arbitrer */
ppc4xx_opba_init(0xef600600);
+
/* Universal interrupt controller */
-uicdev = qdev_new(TYPE_PPC_UIC);
-uicsbd = SYS_BUS_DEVICE(uicdev);
+s->uic = qdev_new(TYPE_PPC_UIC);

-

Re: [PATCH v4 07/24] ppc/ppc405: QOM'ify CPU

2022-08-09 Thread BALATON Zoltan

On Tue, 9 Aug 2022, Cédric Le Goater wrote:

Drop the use of ppc4xx_init() and duplicate a bit of code related to
clocks in the SoC realize routine. We will clean that up in the
following patches.

ppc_dcr_init() simply allocates default DCR handlers for the CPU. Maybe
this could be done in model initializer of the CPU families needing it.

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 


Reviewed-by: BALATON Zoltan 


---
hw/ppc/ppc405.h |  2 +-
include/hw/ppc/ppc4xx.h |  5 -
hw/ppc/ppc405_boards.c  |  2 +-
hw/ppc/ppc405_uc.c  | 40 ++--
hw/ppc/ppc4xx_devs.c| 32 
5 files changed, 32 insertions(+), 49 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index dc862bc8614c..8cc76cc8b3fe 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -79,7 +79,7 @@ struct Ppc405SoCState {
hwaddr ram_size;

uint32_t sysclk;
-PowerPCCPU *cpu;
+PowerPCCPU cpu;
DeviceState *uic;
};

diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
index 980f964b5a91..591e2421a343 100644
--- a/include/hw/ppc/ppc4xx.h
+++ b/include/hw/ppc/ppc4xx.h
@@ -28,11 +28,6 @@
#include "hw/ppc/ppc.h"
#include "exec/memory.h"

-/* PowerPC 4xx core initialization */
-PowerPCCPU *ppc4xx_init(const char *cpu_model,
-clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
-uint32_t sysclk);
-
void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
MemoryRegion ram_memories[],
hwaddr ram_bases[], hwaddr ram_sizes[],
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index b93e85b5d9bd..3677793adc75 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -313,7 +313,7 @@ static void ppc405_init(MachineState *machine)

/* Load ELF kernel and rootfs.cpio */
} else if (kernel_filename && !machine->firmware) {
-boot_from_kernel(machine, ppc405->soc.cpu);
+boot_from_kernel(machine, >soc.cpu);
}
}

diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index c05ab604367d..14a525b2eb74 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1432,22 +1432,41 @@ static void ppc405ep_cpc_init (CPUPPCState *env, 
clk_setup_t clk_setup[8],
#endif
}

+static void ppc405_soc_instance_init(Object *obj)
+{
+Ppc405SoCState *s = PPC405_SOC(obj);
+
+object_initialize_child(obj, "cpu", >cpu,
+POWERPC_CPU_TYPE_NAME("405ep"));
+}
+
+static void ppc405_reset(void *opaque)
+{
+cpu_reset(CPU(opaque));
+}
+
static void ppc405_soc_realize(DeviceState *dev, Error **errp)
{
Ppc405SoCState *s = PPC405_SOC(dev);
-clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup;
+clk_setup_t clk_setup[PPC405EP_CLK_NB];
qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4];
CPUPPCState *env;

memset(clk_setup, 0, sizeof(clk_setup));

/* init CPUs */
-s->cpu = ppc4xx_init(POWERPC_CPU_TYPE_NAME("405ep"),
-  _setup[PPC405EP_CPU_CLK],
-  _clk_setup, s->sysclk);
-env = >cpu->env;
-clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb;
-clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque;
+if (!qdev_realize(DEVICE(>cpu), NULL, errp)) {
+return;
+}
+qemu_register_reset(ppc405_reset, >cpu);
+
+env = >cpu.env;
+
+clk_setup[PPC405EP_CPU_CLK].cb =
+ppc_40x_timers_init(env, s->sysclk, PPC_INTERRUPT_PIT);
+clk_setup[PPC405EP_CPU_CLK].opaque = env;
+
+ppc_dcr_init(env, NULL, NULL);

/* CPU control */
ppc405ep_cpc_init(env, clk_setup, s->sysclk);
@@ -1464,16 +1483,16 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
/* Universal interrupt controller */
s->uic = qdev_new(TYPE_PPC_UIC);

-object_property_set_link(OBJECT(s->uic), "cpu", OBJECT(s->cpu),
+object_property_set_link(OBJECT(s->uic), "cpu", OBJECT(>cpu),
 _fatal);
if (!sysbus_realize(SYS_BUS_DEVICE(s->uic), errp)) {
return;
}

sysbus_connect_irq(SYS_BUS_DEVICE(s->uic), PPCUIC_OUTPUT_INT,
-   qdev_get_gpio_in(DEVICE(s->cpu), PPC40x_INPUT_INT));
+   qdev_get_gpio_in(DEVICE(>cpu), PPC40x_INPUT_INT));
sysbus_connect_irq(SYS_BUS_DEVICE(s->uic), PPCUIC_OUTPUT_CINT,
-   qdev_get_gpio_in(DEVICE(s->cpu), PPC40x_INPUT_CINT));
+   qdev_get_gpio_in(DEVICE(>cpu), PPC40x_INPUT_CINT));

/* SDRAM controller */
/* XXX 405EP has no ECC interrupt */
@@ -1563,6 +1582,7 @@ static const TypeInfo ppc405_types[] = {
.name   = TYPE_PPC405_SOC,
.parent = TYPE_DEVICE,
.instance_size  = sizeof(Ppc405SoCState),
+.instance_init  = ppc405_soc_instance_init,
.class_init = ppc405_soc_class_init,
}
};
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 737c0896b4f8..069b51195160 100644
--- 

Re: [PATCH v2 2/2] util/aio-win32: Correct the event array size in aio_poll()

2022-08-09 Thread Marc-André Lureau
On Tue, Aug 9, 2022 at 8:43 PM Bin Meng  wrote:

> From: Bin Meng 
>
> WaitForMultipleObjects() can only wait for MAXIMUM_WAIT_OBJECTS
> object handles. Correct the event array size in aio_poll() and
> add a assert() to ensure it does not cause out of bound access.
>
> Signed-off-by: Bin Meng 
> Reviewed-by: Stefan Weil 
>

lgtm
Reviewed-by: Marc-André Lureau 


> ---
>
> Changes in v2:
> - change 'count' to unsigned
>
>  util/aio-win32.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/util/aio-win32.c b/util/aio-win32.c
> index 44003d645e..80cfe012ad 100644
> --- a/util/aio-win32.c
> +++ b/util/aio-win32.c
> @@ -326,9 +326,9 @@ void aio_dispatch(AioContext *ctx)
>  bool aio_poll(AioContext *ctx, bool blocking)
>  {
>  AioHandler *node;
> -HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
> +HANDLE events[MAXIMUM_WAIT_OBJECTS];
>  bool progress, have_select_revents, first;
> -int count;
> +unsigned count;
>  int timeout;
>
>  /*
> @@ -369,6 +369,7 @@ bool aio_poll(AioContext *ctx, bool blocking)
>  QLIST_FOREACH_RCU(node, >aio_handlers, node) {
>  if (!node->deleted && node->io_notify
>  && aio_node_check(ctx, node->is_external)) {
> +assert(count < MAXIMUM_WAIT_OBJECTS);
>  events[count++] = event_notifier_get_handle(node->e);
>  }
>  }
> --
> 2.34.1
>
>

-- 
Marc-André Lureau


Re: [PATCH v4 4/6] vdpa: Add asid parameter to vhost_vdpa_dma_map/unmap

2022-08-09 Thread Eugenio Perez Martin
On Tue, Aug 9, 2022 at 9:21 AM Jason Wang  wrote:
>
> On Sat, Aug 6, 2022 at 12:39 AM Eugenio Pérez  wrote:
> >
> > So the caller can choose which ASID is destined.
> >
> > No need to update the batch functions as they will always be called from
> > memory listener updates at the moment. Memory listener updates will
> > always update ASID 0, as it's the passthrough ASID.
> >
> > All vhost devices's ASID are 0 at this moment.
> >
> > Signed-off-by: Eugenio Pérez 
> > ---
> > v4: Add comment specifying behavior if device does not support _F_ASID
> >
> > v3: Deleted unneeded space
> > ---
> >  include/hw/virtio/vhost-vdpa.h |  8 +---
> >  hw/virtio/vhost-vdpa.c | 25 +++--
> >  net/vhost-vdpa.c   |  6 +++---
> >  hw/virtio/trace-events |  4 ++--
> >  4 files changed, 25 insertions(+), 18 deletions(-)
> >
> > diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h
> > index d85643..6560bb9d78 100644
> > --- a/include/hw/virtio/vhost-vdpa.h
> > +++ b/include/hw/virtio/vhost-vdpa.h
> > @@ -29,6 +29,7 @@ typedef struct vhost_vdpa {
> >  int index;
> >  uint32_t msg_type;
> >  bool iotlb_batch_begin_sent;
> > +uint32_t address_space_id;
> >  MemoryListener listener;
> >  struct vhost_vdpa_iova_range iova_range;
> >  uint64_t acked_features;
> > @@ -42,8 +43,9 @@ typedef struct vhost_vdpa {
> >  VhostVDPAHostNotifier notifier[VIRTIO_QUEUE_MAX];
> >  } VhostVDPA;
> >
> > -int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr iova, hwaddr size,
> > -   void *vaddr, bool readonly);
> > -int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, hwaddr iova, hwaddr size);
> > +int vhost_vdpa_dma_map(struct vhost_vdpa *v, uint32_t asid, hwaddr iova,
> > +   hwaddr size, void *vaddr, bool readonly);
> > +int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, uint32_t asid, hwaddr iova,
> > + hwaddr size);
> >
> >  #endif
> > diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
> > index 34922ec20d..3eb67b27b7 100644
> > --- a/hw/virtio/vhost-vdpa.c
> > +++ b/hw/virtio/vhost-vdpa.c
> > @@ -72,22 +72,24 @@ static bool 
> > vhost_vdpa_listener_skipped_section(MemoryRegionSection *section,
> >  return false;
> >  }
> >
> > -int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr iova, hwaddr size,
> > -   void *vaddr, bool readonly)
> > +int vhost_vdpa_dma_map(struct vhost_vdpa *v, uint32_t asid, hwaddr iova,
> > +   hwaddr size, void *vaddr, bool readonly)
> >  {
> >  struct vhost_msg_v2 msg = {};
> >  int fd = v->device_fd;
> >  int ret = 0;
> >
> >  msg.type = v->msg_type;
> > +msg.asid = asid; /* 0 if vdpa device does not support asid */
>
> So this comment is still kind of confusing.
>
> Does it mean the caller can guarantee that asid is 0 when ASID is not
> supported?

That's right.

> Even if this is true, does it silently depend on the
> behaviour that the asid field is extended from the reserved field of
> the ABI?
>

I don't get this part.

Regarding the ABI, the reserved bytes will be there either the device
support asid or not, since the actual iotlb message is after the
reserved field. And they were already zeroed by msg = {} on top of the
function. So if the caller always sets asid = 0, there is no change on
this part.

> (I still wonder if it's better to avoid using msg.asid if the kernel
> doesn't support that).
>

We can add a conditional on v->dev->backend_features & _F_ASID.

But that is not the only case where ASID will not be used: If the vq
group does not match with the supported configuration (like if CVQ is
not in the independent group). This case is already handled by setting
all vhost_vdpa of the virtio device to asid = 0, so adding that extra
check seems redundant to me.

I'm not against adding it though: It can prevent bugs. Since it would
be a bug of qemu, maybe it's better to add an assertion?

Thanks!

> Thanks
>
> >  msg.iotlb.iova = iova;
> >  msg.iotlb.size = size;
> >  msg.iotlb.uaddr = (uint64_t)(uintptr_t)vaddr;
> >  msg.iotlb.perm = readonly ? VHOST_ACCESS_RO : VHOST_ACCESS_RW;
> >  msg.iotlb.type = VHOST_IOTLB_UPDATE;
> >
> > -   trace_vhost_vdpa_dma_map(v, fd, msg.type, msg.iotlb.iova, 
> > msg.iotlb.size,
> > -msg.iotlb.uaddr, msg.iotlb.perm, 
> > msg.iotlb.type);
> > +trace_vhost_vdpa_dma_map(v, fd, msg.type, msg.asid, msg.iotlb.iova,
> > + msg.iotlb.size, msg.iotlb.uaddr, 
> > msg.iotlb.perm,
> > + msg.iotlb.type);
> >
> >  if (write(fd, , sizeof(msg)) != sizeof(msg)) {
> >  error_report("failed to write, fd=%d, errno=%d (%s)",
> > @@ -98,18 +100,20 @@ int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr 
> > iova, hwaddr size,
> >  return ret;
> >  }
> >
> > -int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, hwaddr iova, hwaddr size)
> > +int 

Re: Re: [RFC] hw/nvme: Use irqfd to send interrupts

2022-08-09 Thread Keith Busch
On Wed, Aug 10, 2022 at 12:48:53AM +0800, 樊金昊 wrote:
>> The driver will create the cq with an allocated vector, but it's not 
>> activated
>> until after the driver wires it up to a handler. I think that's what you're
>> observing with the incomplete MSIx table entry on creation.
> 
> Also, I'm wondering if this is inconsistent with the NVMe spec. In Section 
> 7.6.1
> of the 1.4 spec, it says "After determining the number of I/O Queues, the MSI
> and/or MSI-X registers should be configured;" in Step 8, and CQ creation 
> happens
> in Step 9. Now the driver changes MSI-X registers after CQ creation, is it a
> violation of the spec?

I don't think it's a problem. This is really a more "informative" section of
the spec and doesn't specify any hard requirements. You should be able to rely
on the entry's data being stable after the first queue doorbell ring, though.



Re: [PATCH v2 1/2] util/main-loop: Fix maximum number of wait objects for win32

2022-08-09 Thread Marc-André Lureau
Hi

On Tue, Aug 9, 2022 at 8:43 PM Bin Meng  wrote:

> From: Bin Meng 
>
> The maximum number of wait objects for win32 should be
> MAXIMUM_WAIT_OBJECTS, not MAXIMUM_WAIT_OBJECTS + 1.
>
> Fix the logic in qemu_add_wait_object() to avoid adding
> the same HANDLE twice.
>
>
Please make that a separate patch.


> Signed-off-by: Bin Meng 
> ---
>
> Changes in v2:
> - fix the logic in qemu_add_wait_object() to avoid adding
>   the same HANDLE twice
>
>
Still NACK, did you understand my argument about array bounds?

"if (found)" will access the arrays at position i+1 ==
MAXIMUM_WAIT_OBJECTS. We need the +1 for that logic to work without OOB
access.



>  util/main-loop.c | 43 +++
>  1 file changed, 31 insertions(+), 12 deletions(-)
>
> diff --git a/util/main-loop.c b/util/main-loop.c
> index f00a25451b..66b2ae2800 100644
> --- a/util/main-loop.c
> +++ b/util/main-loop.c
> @@ -363,37 +363,56 @@ void qemu_del_polling_cb(PollingFunc *func, void
> *opaque)
>  /* Wait objects support */
>  typedef struct WaitObjects {
>  int num;
> -int revents[MAXIMUM_WAIT_OBJECTS + 1];
> -HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
> -WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
> -void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
> +int revents[MAXIMUM_WAIT_OBJECTS];
> +HANDLE events[MAXIMUM_WAIT_OBJECTS];
> +WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS];
> +void *opaque[MAXIMUM_WAIT_OBJECTS];
>  } WaitObjects;
>
>  static WaitObjects wait_objects = {0};
>
>  int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void
> *opaque)
>  {
> +int i;
> +bool found = false;
>  WaitObjects *w = _objects;
> +
>  if (w->num >= MAXIMUM_WAIT_OBJECTS) {
>  return -1;
>  }
> -w->events[w->num] = handle;
> -w->func[w->num] = func;
> -w->opaque[w->num] = opaque;
> -w->revents[w->num] = 0;
> -w->num++;
> +
> +for (i = 0; i < w->num; i++) {
> +/* if the same handle is added twice, newer overwrites older */
> +if (w->events[i] == handle) {
> +found = true;
> +break;
> +}
> +}
> +
> +w->events[i] = handle;
> +w->func[i] = func;
> +w->opaque[i] = opaque;
> +w->revents[i] = 0;
> +
> +if (!found) {
> +w->num++;
> +}
> +
>  return 0;
>  }
>
>  void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void
> *opaque)
>  {
> -int i, found;
> +int i;
> +bool found = false;
>  WaitObjects *w = _objects;
>
> -found = 0;
>  for (i = 0; i < w->num; i++) {
>  if (w->events[i] == handle) {
> -found = 1;
> +found = true;
> +}
> +if (i == MAXIMUM_WAIT_OBJECTS - 1) {
> +break;
>  }
>  if (found) {
>  w->events[i] = w->events[i + 1];
> --
> 2.34.1
>
>

-- 
Marc-André Lureau


Re: [PATCH v4 05/24] ppc/ppc405: Introduce a PPC405 SoC

2022-08-09 Thread BALATON Zoltan

On Tue, 9 Aug 2022, Cédric Le Goater wrote:

It is an initial model to start QOMification of the PPC405 board.
QOM'ified devices will be reintroduced one by one. Start with the
memory regions, which name prefix is changed to "ppc405".

Also, initialize only one RAM bank. The second bank is a dummy one
(zero size) which is here to match the hard coded number of banks in
ppc405ep_init().

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 


Reviewed-by: BALATON Zoltan 


---
hw/ppc/ppc405.h| 16 
hw/ppc/ppc405_boards.c | 23 ---
hw/ppc/ppc405_uc.c | 40 
3 files changed, 68 insertions(+), 11 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 83f156f585c8..66dc21cdfed8 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -25,6 +25,7 @@
#ifndef PPC405_H
#define PPC405_H

+#include "qom/object.h"
#include "hw/ppc/ppc4xx.h"

#define PPC405EP_SDRAM_BASE 0x
@@ -62,6 +63,21 @@ struct ppc4xx_bd_info_t {
uint32_t bi_iic_fast[2];
};

+#define TYPE_PPC405_SOC "ppc405-soc"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc405SoCState, PPC405_SOC);
+
+struct Ppc405SoCState {
+/* Private */
+DeviceState parent_obj;
+
+/* Public */
+MemoryRegion ram_banks[2];
+hwaddr ram_bases[2], ram_sizes[2];
+
+MemoryRegion *dram_mr;
+hwaddr ram_size;
+};
+
/* PowerPC 405 core */
ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size);

diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 381f39aa94cb..f029d6f415f6 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -57,6 +57,8 @@ struct Ppc405MachineState {
/* Private */
MachineState parent_obj;
/* Public */
+
+Ppc405SoCState soc;
};

/*/
@@ -232,11 +234,10 @@ static void boot_from_kernel(MachineState *machine, 
PowerPCCPU *cpu)

static void ppc405_init(MachineState *machine)
{
+Ppc405MachineState *ppc405 = PPC405_MACHINE(machine);
MachineClass *mc = MACHINE_GET_CLASS(machine);
const char *kernel_filename = machine->kernel_filename;
PowerPCCPU *cpu;
-MemoryRegion *ram_memories = g_new(MemoryRegion, 2);
-hwaddr ram_bases[2], ram_sizes[2];
MemoryRegion *sysmem = get_system_memory();
DeviceState *uicdev;

@@ -247,16 +248,16 @@ static void ppc405_init(MachineState *machine)
exit(EXIT_FAILURE);
}

-/* XXX: fix this */
-memory_region_init_alias(_memories[0], NULL, "ef405ep.ram.alias",
- machine->ram, 0, machine->ram_size);
-ram_bases[0] = 0;
-ram_sizes[0] = machine->ram_size;
-memory_region_init(_memories[1], NULL, "ef405ep.ram1", 0);
-ram_bases[1] = 0x;
-ram_sizes[1] = 0x;
+object_initialize_child(OBJECT(machine), "soc", >soc,
+TYPE_PPC405_SOC);
+object_property_set_uint(OBJECT(>soc), "ram-size",
+ machine->ram_size, _fatal);
+object_property_set_link(OBJECT(>soc), "dram",
+ OBJECT(machine->ram), _abort);
+qdev_realize(DEVICE(>soc), NULL, _fatal);

-cpu = ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
+cpu = ppc405ep_init(sysmem, ppc405->soc.ram_banks, ppc405->soc.ram_bases,
+ppc405->soc.ram_sizes,
, , kernel_filename == NULL ? 0 : 1);

/* allocate and load BIOS */
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index d6420c88d3a6..adadb3a0ae08 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -30,6 +30,7 @@
#include "hw/ppc/ppc.h"
#include "hw/i2c/ppc4xx_i2c.h"
#include "hw/irq.h"
+#include "hw/qdev-properties.h"
#include "ppc405.h"
#include "hw/char/serial.h"
#include "qemu/timer.h"
@@ -1530,3 +1531,42 @@ PowerPCCPU *ppc405ep_init(MemoryRegion 
*address_space_mem,

return cpu;
}
+
+static void ppc405_soc_realize(DeviceState *dev, Error **errp)
+{
+Ppc405SoCState *s = PPC405_SOC(dev);
+
+/* Initialize only one bank */
+s->ram_bases[0] = 0;
+s->ram_sizes[0] = s->ram_size;
+memory_region_init_alias(>ram_banks[0], OBJECT(s),
+ "ppc405.sdram0", s->dram_mr,
+ s->ram_bases[0], s->ram_sizes[0]);
+}
+
+static Property ppc405_soc_properties[] = {
+DEFINE_PROP_LINK("dram", Ppc405SoCState, dram_mr, TYPE_MEMORY_REGION,
+ MemoryRegion *),
+DEFINE_PROP_UINT64("ram-size", Ppc405SoCState, ram_size, 0),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ppc405_soc_class_init(ObjectClass *oc, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(oc);
+
+dc->realize = ppc405_soc_realize;
+dc->user_creatable = false;
+device_class_set_props(dc, ppc405_soc_properties);
+}
+
+static const TypeInfo ppc405_types[] = {
+{
+.name   = TYPE_PPC405_SOC,
+.parent = TYPE_DEVICE,
+

[PULL 1/2] contrib/vhost-user-blk: Clean up deallocation of VuVirtqElement

2022-08-09 Thread Laurent Vivier
From: Markus Armbruster 

We allocate VuVirtqElement with g_malloc() in
virtqueue_alloc_element(), but free it with free() in
vhost-user-blk.c.  Harmless, but use g_free() anyway.

One of the calls is guarded by a "not null" condition.  Useless,
because it cannot be null (it's dereferenced right before), and even
it it could be, free() and g_free() do the right thing.  Drop the
conditional.

Fixes: Coverity CID 1490290
Signed-off-by: Markus Armbruster 
Reviewed-by: Raphael Norwitz 
Acked-by: Michael S. Tsirkin 
Message-Id: <20220630085219.1305519-1-arm...@redhat.com>
Signed-off-by: Laurent Vivier 
---
 contrib/vhost-user-blk/vhost-user-blk.c | 9 +++--
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/contrib/vhost-user-blk/vhost-user-blk.c 
b/contrib/vhost-user-blk/vhost-user-blk.c
index 9cb78ca1d0df..d6932a264573 100644
--- a/contrib/vhost-user-blk/vhost-user-blk.c
+++ b/contrib/vhost-user-blk/vhost-user-blk.c
@@ -106,10 +106,7 @@ static void vub_req_complete(VubReq *req)
   req->size + 1);
 vu_queue_notify(vu_dev, req->vq);
 
-if (req->elem) {
-free(req->elem);
-}
-
+g_free(req->elem);
 g_free(req);
 }
 
@@ -243,7 +240,7 @@ static int vub_virtio_process_req(VubDev *vdev_blk,
 /* refer to hw/block/virtio_blk.c */
 if (elem->out_num < 1 || elem->in_num < 1) {
 fprintf(stderr, "virtio-blk request missing headers\n");
-free(elem);
+g_free(elem);
 return -1;
 }
 
@@ -325,7 +322,7 @@ static int vub_virtio_process_req(VubDev *vdev_blk,
 return 0;
 
 err:
-free(elem);
+g_free(elem);
 g_free(req);
 return -1;
 }
-- 
2.37.1




[PULL 2/2] xlnx_dp: drop unsupported AUXCommand in xlnx_dp_aux_set_command

2022-08-09 Thread Laurent Vivier
From: Qiang Liu 

In xlnx_dp_aux_set_command, when the command leads to the default
branch, xlxn-dp will abort and then crash.

This patch removes this abort and drops this operation.

Fixes: 58ac482 ("introduce xlnx-dp")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/411
Reported-by: Qiang Liu 
Tested-by: Qiang Liu 
Suggested-by: Thomas Huth 
Signed-off-by: Qiang Liu 
Reviewed-by: Thomas Huth 
Reviewed-by: Frederic Konrad 
Message-Id: <20220808080116.2184881-1-cyruscy...@gmail.com>
Signed-off-by: Laurent Vivier 
---
 hw/display/xlnx_dp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c
index a071c818833b..b0828d65aa86 100644
--- a/hw/display/xlnx_dp.c
+++ b/hw/display/xlnx_dp.c
@@ -532,8 +532,8 @@ static void xlnx_dp_aux_set_command(XlnxDPState *s, 
uint32_t value)
 qemu_log_mask(LOG_UNIMP, "xlnx_dp: Write i2c status not 
implemented\n");
 break;
 default:
-error_report("%s: invalid command: %u", __func__, cmd);
-abort();
+qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid command: %u", __func__, 
cmd);
+return;
 }
 
 s->core_registers[DP_INTERRUPT_SIGNAL_STATE] |= 0x04;
-- 
2.37.1




[PULL 0/2] Trivial branch for 7.1 patches

2022-08-09 Thread Laurent Vivier
The following changes since commit c669f22f1a47897e8d1d595d6b8a59a572f9158c:

  Merge tag 'pull-la-20220805' of https://gitlab.com/rth7680/qemu into staging 
(2022-08-05 12:55:53 -0700)

are available in the Git repository at:

  https://gitlab.com/laurent_vivier/qemu.git 
tags/trivial-branch-for-7.1-pull-request

for you to fetch changes up to 9390da5ef29a5e0f98e5b482dceeeb287c452f17:

  xlnx_dp: drop unsupported AUXCommand in xlnx_dp_aux_set_command (2022-08-08 
11:40:06 +0200)


Pull request trivial branch 20220809



Markus Armbruster (1):
  contrib/vhost-user-blk: Clean up deallocation of VuVirtqElement

Qiang Liu (1):
  xlnx_dp: drop unsupported AUXCommand in xlnx_dp_aux_set_command

 contrib/vhost-user-blk/vhost-user-blk.c | 9 +++--
 hw/display/xlnx_dp.c| 4 ++--
 2 files changed, 5 insertions(+), 8 deletions(-)

-- 
2.37.1




Re: [PATCH v4 04/24] ppc/ppc405: Move SRAM under the ref405ep machine

2022-08-09 Thread BALATON Zoltan

On Tue, 9 Aug 2022, Cédric Le Goater wrote:

It doesn't belong to the generic machine nor the SoC. Fix a typo in
the name while we are at it.

Signed-off-by: Cédric Le Goater 
---
hw/ppc/ppc405_boards.c | 12 ++--
1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index f4794ba40ce6..381f39aa94cb 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -235,7 +235,6 @@ static void ppc405_init(MachineState *machine)
MachineClass *mc = MACHINE_GET_CLASS(machine);
const char *kernel_filename = machine->kernel_filename;
PowerPCCPU *cpu;
-MemoryRegion *sram = g_new(MemoryRegion, 1);
MemoryRegion *ram_memories = g_new(MemoryRegion, 2);
hwaddr ram_bases[2], ram_sizes[2];
MemoryRegion *sysmem = get_system_memory();
@@ -260,11 +259,6 @@ static void ppc405_init(MachineState *machine)
cpu = ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
, , kernel_filename == NULL ? 0 : 1);

-/* allocate SRAM */
-memory_region_init_ram(sram, NULL, "ef405ep.sram", PPC405EP_SRAM_SIZE,
-   _fatal);


Do you need to set an owner while at it? Anyway,

Reviewed-by: BALATON Zoltan 

Regards,
BALATON Zoltan


-memory_region_add_subregion(sysmem, PPC405EP_SRAM_BASE, sram);
-
/* allocate and load BIOS */
if (machine->firmware) {
MemoryRegion *bios = g_new(MemoryRegion, 1);
@@ -328,9 +322,15 @@ static void ref405ep_init(MachineState *machine)
{
DeviceState *dev;
SysBusDevice *s;
+MemoryRegion *sram = g_new(MemoryRegion, 1);

ppc405_init(machine);

+/* allocate SRAM */
+memory_region_init_ram(sram, NULL, "ref405ep.sram", PPC405EP_SRAM_SIZE,
+   _fatal);
+memory_region_add_subregion(get_system_memory(), PPC405EP_SRAM_BASE, sram);
+
/* Register FPGA */
ref405ep_fpga_init(get_system_memory(), PPC405EP_FPGA_BASE);
/* Register NVRAM */


Re: Re: [RFC] hw/nvme: Use irqfd to send interrupts

2022-08-09 Thread 樊金昊
 The driver will create the cq with an allocated vector, but it's not 
activated
 until after the driver wires it up to a handler. I think that's what you're
 observing with the incomplete MSIx table entry on creation.

Also, I'm wondering if this is inconsistent with the NVMe spec. In Section 7.6.1
of the 1.4 spec, it says "After determining the number of I/O Queues, the MSI
and/or MSI-X registers should be configured;" in Step 8, and CQ creation happens
in Step 9. Now the driver changes MSI-X registers after CQ creation, is it a
violation of the spec?


[PATCH v2 2/2] util/aio-win32: Correct the event array size in aio_poll()

2022-08-09 Thread Bin Meng
From: Bin Meng 

WaitForMultipleObjects() can only wait for MAXIMUM_WAIT_OBJECTS
object handles. Correct the event array size in aio_poll() and
add a assert() to ensure it does not cause out of bound access.

Signed-off-by: Bin Meng 
Reviewed-by: Stefan Weil 
---

Changes in v2:
- change 'count' to unsigned

 util/aio-win32.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/util/aio-win32.c b/util/aio-win32.c
index 44003d645e..80cfe012ad 100644
--- a/util/aio-win32.c
+++ b/util/aio-win32.c
@@ -326,9 +326,9 @@ void aio_dispatch(AioContext *ctx)
 bool aio_poll(AioContext *ctx, bool blocking)
 {
 AioHandler *node;
-HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
+HANDLE events[MAXIMUM_WAIT_OBJECTS];
 bool progress, have_select_revents, first;
-int count;
+unsigned count;
 int timeout;
 
 /*
@@ -369,6 +369,7 @@ bool aio_poll(AioContext *ctx, bool blocking)
 QLIST_FOREACH_RCU(node, >aio_handlers, node) {
 if (!node->deleted && node->io_notify
 && aio_node_check(ctx, node->is_external)) {
+assert(count < MAXIMUM_WAIT_OBJECTS);
 events[count++] = event_notifier_get_handle(node->e);
 }
 }
-- 
2.34.1




Re: [PULL] Net patches

2022-08-09 Thread Richard Henderson

On 8/9/22 02:08, Jason Wang wrote:

The following changes since commit ca5f3d4df1b47d7f66a109cdb504e83dfd7ec433:

   Merge tag 'pull-la-20220808' of https://gitlab.com/rth7680/qemu into staging 
(2022-08-08 19:51:12 -0700)

are available in the git repository at:

   https://github.com/jasowang/qemu.git tags/net-pull-request

for you to fetch changes up to 7cf745dd9c25f0740dc1009598b58dd8dd989876:

   hw/net/rocker: Avoid undefined shifts with more than 31 ports (2022-08-09 
17:02:18 +0800)




Peter Maydell (1):
   hw/net/rocker: Avoid undefined shifts with more than 31 ports


Applied, thanks.  Please update https://wiki.qemu.org/ChangeLog/7.1 as 
appropriate.


r~




  hw/net/rocker/rocker.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)








[PATCH v2 1/2] util/main-loop: Fix maximum number of wait objects for win32

2022-08-09 Thread Bin Meng
From: Bin Meng 

The maximum number of wait objects for win32 should be
MAXIMUM_WAIT_OBJECTS, not MAXIMUM_WAIT_OBJECTS + 1.

Fix the logic in qemu_add_wait_object() to avoid adding
the same HANDLE twice.

Signed-off-by: Bin Meng 
---

Changes in v2:
- fix the logic in qemu_add_wait_object() to avoid adding
  the same HANDLE twice

 util/main-loop.c | 43 +++
 1 file changed, 31 insertions(+), 12 deletions(-)

diff --git a/util/main-loop.c b/util/main-loop.c
index f00a25451b..66b2ae2800 100644
--- a/util/main-loop.c
+++ b/util/main-loop.c
@@ -363,37 +363,56 @@ void qemu_del_polling_cb(PollingFunc *func, void *opaque)
 /* Wait objects support */
 typedef struct WaitObjects {
 int num;
-int revents[MAXIMUM_WAIT_OBJECTS + 1];
-HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
-WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
-void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
+int revents[MAXIMUM_WAIT_OBJECTS];
+HANDLE events[MAXIMUM_WAIT_OBJECTS];
+WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS];
+void *opaque[MAXIMUM_WAIT_OBJECTS];
 } WaitObjects;
 
 static WaitObjects wait_objects = {0};
 
 int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
 {
+int i;
+bool found = false;
 WaitObjects *w = _objects;
+
 if (w->num >= MAXIMUM_WAIT_OBJECTS) {
 return -1;
 }
-w->events[w->num] = handle;
-w->func[w->num] = func;
-w->opaque[w->num] = opaque;
-w->revents[w->num] = 0;
-w->num++;
+
+for (i = 0; i < w->num; i++) {
+/* if the same handle is added twice, newer overwrites older */
+if (w->events[i] == handle) {
+found = true;
+break;
+}
+}
+
+w->events[i] = handle;
+w->func[i] = func;
+w->opaque[i] = opaque;
+w->revents[i] = 0;
+
+if (!found) {
+w->num++;
+}
+
 return 0;
 }
 
 void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
 {
-int i, found;
+int i;
+bool found = false;
 WaitObjects *w = _objects;
 
-found = 0;
 for (i = 0; i < w->num; i++) {
 if (w->events[i] == handle) {
-found = 1;
+found = true;
+}
+if (i == MAXIMUM_WAIT_OBJECTS - 1) {
+break;
 }
 if (found) {
 w->events[i] = w->events[i + 1];
-- 
2.34.1




Re: [PATCH 1/2] util/main-loop: Fix maximum number of wait objects for win32

2022-08-09 Thread Bin Meng
On Tue, Aug 9, 2022 at 9:15 PM Marc-André Lureau
 wrote:
>
> Hi
>
> On Fri, Aug 5, 2022 at 6:57 PM Bin Meng  wrote:
>>
>> From: Bin Meng 
>>
>> The maximum number of wait objects for win32 should be
>> MAXIMUM_WAIT_OBJECTS, not MAXIMUM_WAIT_OBJECTS + 1.
>>
>> Signed-off-by: Bin Meng 
>
>
> Nack,
>
> if wait_objects.num reaches MAXIMUM_WAIT_OBJECTS,
>
> then qemu_del_wait_object() will iterate up to it, and then the branch "if 
> (found)" will access the arrays at position i+1 == MAXIMUM_WAIT_OBJECTS.
>
> Note that the add functions should probably learn to avoid adding the same 
> HANDLE twice, otherwise del is a bit broken.
>

Thanks for the review. Will fix in v2.

Regards,
Bin



Re: Re: [RFC] hw/nvme: Use irqfd to send interrupts

2022-08-09 Thread 樊金昊
 The driver will create the cq with an allocated vector, but it's not 
activated
 until after the driver wires it up to a handler. I think that's what you're
 observing with the incomplete MSIx table entry on creation.

Agreed. I digged through pci_request_irq()'s call chain and found 
pci_write_msi_msg() was called in the end.

Now to implement irqfd support, we need to register the (complete) MSI message 
in KVM so that KVM can directly send the interrupt when we signal the irqfd.
My prior implementation delayed each CQ's MSI message registration to its first
nvme_post_cqes(). I'm not sure whether this is a good choice. What do you think
about this approach? 

BTW, since we skip QEMU's MSI-x emulation with irqfd, we need to record the
mask status of each interrupt vector. QEMU provides msix_set_vector_notifiers()
to help us call handlers on each mask and unmask event. But this function works
on a per-device basis. I guess it is best to call msix_set_vector_notifiers()
after all CQs are created. But I think qemu-nvme can't tell when the host has
finished CQ creation. Where do you think is the best place we register the
mask/unmask callbacks? Is it OK to put it at, say, the first nvme_post_cqes()
of the whole device?

Thanks,
Jinhao Fan



Re: [PATCH 2/2] util/aio-win32: Correct the event array size in aio_poll()

2022-08-09 Thread Bin Meng
On Fri, Aug 5, 2022 at 11:09 PM Stefan Weil  wrote:
>
> Am 05.08.22 um 16:56 schrieb Bin Meng:
>
> > From: Bin Meng 
> >
> > WaitForMultipleObjects() can only wait for MAXIMUM_WAIT_OBJECTS
> > object handles. Correct the event array size in aio_poll() and
> > add a assert() to ensure it does not cause out of bound access.
> >
> > Signed-off-by: Bin Meng 
> > ---
> >
> >   util/aio-win32.c | 3 ++-
> >   1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/util/aio-win32.c b/util/aio-win32.c
> > index 44003d645e..8cf5779567 100644
> > --- a/util/aio-win32.c
> > +++ b/util/aio-win32.c
> > @@ -326,7 +326,7 @@ void aio_dispatch(AioContext *ctx)
> >   bool aio_poll(AioContext *ctx, bool blocking)
> >   {
> >   AioHandler *node;
> > -HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
> > +HANDLE events[MAXIMUM_WAIT_OBJECTS];
> >   bool progress, have_select_revents, first;
> >   int count;
> >   int timeout;
> > @@ -369,6 +369,7 @@ bool aio_poll(AioContext *ctx, bool blocking)
> >   QLIST_FOREACH_RCU(node, >aio_handlers, node) {
> >   if (!node->deleted && node->io_notify
> >   && aio_node_check(ctx, node->is_external)) {
> > +assert(count < MAXIMUM_WAIT_OBJECTS);
>
>
> Would using g_assert for new code be better? Currently the rest of that
> file (and most QEMU code) uses assert.

Yeah, I noticed that but didn't do that because I feel it's better to
be consistent, at least in this single file.

Changing to g_assert() could be a future patch, if necessary.

>
> count could also be changed from int to unsigned (which matches better
> to the unsigned DWORD).
>

changed in v2.

> Reviewed-by: Stefan Weil 

Thanks!

Regards,
Bin



Re: [RFC] hw/nvme: Use irqfd to send interrupts

2022-08-09 Thread Keith Busch
On Mon, Aug 08, 2022 at 10:23:03AM +0800, Jinhao Fan wrote:
> at 12:35 PM, Jinhao Fan  wrote:
> 
> > static void nvme_irq_assert(NvmeCtrl *n, NvmeCQueue *cq)
> > {
> > if (cq->irq_enabled) {
> > if (msix_enabled(&(n->parent_obj))) {
> > +/* Initialize CQ irqfd */
> > +if (!cq->irqfd_enabled && n->params.ioeventfd && cq->cqid != 
> > 0) {
> > +int ret = nvme_init_cq_irqfd(cq);
> > +if (ret == 0) {
> > +cq->irqfd_enabled = true;
> > +}
> > +}
> > +
> 
> Another question:
> 
> In this version I left irqfd initialization to the first assertion of an
> irq. But I think it is better to initialize irqfd at cq creation time so we
> won’t bother checking it at each irq assertion. However if I put these code
> in nvme_init_cq(), irqfd does not work properly. After adding some
> tracepoints I found the MSI messages in MSI-X table changed after
> nvme_init_cq(). Specifically, the `data` field does not seem correct at the
> time when nvme_init_cq() is called.
> 
> Keith, you must be familiar with how the nvme driver initializes CQs. Could
> you give some information on when I can safely use the contents in the MSI-X
> table?

The driver will create the cq with an allocated vector, but it's not activated
until after the driver wires it up to a handler. I think that's what you're
observing with the incomplete MSIx table entry on creation.



Re: [BUG] cxl can not create region

2022-08-09 Thread Jonathan Cameron via
On Tue, 9 Aug 2022 21:07:06 +0800
Bobo WL  wrote:

> Hi Jonathan
> 
> Thanks for your reply!
> 
> On Mon, Aug 8, 2022 at 8:37 PM Jonathan Cameron
>  wrote:
> >
> > Probably not related to your problem, but there is a disconnect in QEMU /
> > kernel assumptionsaround the presence of an HDM decoder when a HB only
> > has a single root port. Spec allows it to be provided or not as an 
> > implementation choice.
> > Kernel assumes it isn't provide. Qemu assumes it is.
> >
> > The temporary solution is to throw in a second root port on the HB and not
> > connect anything to it.  Longer term I may special case this so that the 
> > particular
> > decoder defaults to pass through settings in QEMU if there is only one root 
> > port.
> >  
> 
> You are right! After adding an extra HB in qemu, I can create a x1
> region successfully.
> But have some errors in Nvdimm:
> 
> [   74.925838] Unknown online node for memory at 0x100, assuming node > 0
> [   74.925846] Unknown target node for memory at 0x100, assuming node > 0
> [   74.927470] nd_region region0: nmem0: is disabled, failing probe

Ah. I've seen this one, but not chased it down yet.  Was on my todo list to 
chase
down. Once I reach this state I can verify the HDM Decode is correct which is 
what
I've been using to test (Which wasn't true until earlier this week). 
I'm currently testing via devmem, more for historical reasons than because it 
makes
that much sense anymore.  

> 
> And x4 region still failed with same errors, using latest cxl/preview
> branch don't work.
> I have picked "Two CXL emulation fixes" patches in qemu, still not working.
> 
> Bob



[PATCH v4 24/24] ppc/ppc405: Add check on minimum RAM size

2022-08-09 Thread Cédric Le Goater
The check on invalid RAM size is now performed in the SDRAM controller
but not all values will boot a machine. A minimum of 2*16 is required.

Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405_boards.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 4ff6715f3533..9a3fec38cce1 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -251,14 +251,11 @@ static void boot_from_kernel(MachineState *machine, 
PowerPCCPU *cpu)
 static void ppc405_init(MachineState *machine)
 {
 Ppc405MachineState *ppc405 = PPC405_MACHINE(machine);
-MachineClass *mc = MACHINE_GET_CLASS(machine);
 const char *kernel_filename = machine->kernel_filename;
 MemoryRegion *sysmem = get_system_memory();
 
-if (machine->ram_size != mc->default_ram_size) {
-char *sz = size_to_str(mc->default_ram_size);
-error_report("Invalid RAM size, should be %s", sz);
-g_free(sz);
+if (machine->ram_size < 16 * MiB) {
+error_report("Not enough RAM !");
 exit(EXIT_FAILURE);
 }
 
-- 
2.37.1




[PATCH v4 21/24] ppc/ppc405: Use an explicit I2C object

2022-08-09 Thread Cédric Le Goater
Having an explicit I2C model object will help if one day we want to
add I2C devices on the bus from the machine init routine.

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405.h|  2 ++
 hw/ppc/ppc405_uc.c | 10 --
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 8e67ad0b72c3..56881b181ba1 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -28,6 +28,7 @@
 #include "qom/object.h"
 #include "hw/ppc/ppc4xx.h"
 #include "hw/intc/ppc-uic.h"
+#include "hw/i2c/ppc4xx_i2c.h"
 
 #define PPC405EP_SDRAM_BASE 0x
 #define PPC405EP_NVRAM_BASE 0xF000
@@ -241,6 +242,7 @@ struct Ppc405SoCState {
 Ppc405OcmState ocm;
 Ppc405GpioState gpio;
 Ppc405DmaState dma;
+PPC4xxI2CState i2c;
 Ppc405EbcState ebc;
 Ppc405OpbaState opba;
 Ppc405PobState pob;
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 328224bb0620..1045f5f13e6c 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1363,6 +1363,8 @@ static void ppc405_soc_instance_init(Object *obj)
 
 object_initialize_child(obj, "dma", >dma, TYPE_PPC405_DMA);
 
+object_initialize_child(obj, "i2c", >i2c, TYPE_PPC4xx_I2C);
+
 object_initialize_child(obj, "ebc", >ebc, TYPE_PPC405_EBC);
 
 object_initialize_child(obj, "opba", >opba, TYPE_PPC405_OPBA);
@@ -1456,8 +1458,12 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 }
 
 /* I2C controller */
-sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500,
- qdev_get_gpio_in(DEVICE(>uic), 2));
+if (!sysbus_realize(SYS_BUS_DEVICE(>i2c), errp)) {
+return;
+}
+sysbus_mmio_map(SYS_BUS_DEVICE(>i2c), 0, 0xef600500);
+sysbus_connect_irq(SYS_BUS_DEVICE(>i2c), 0,
+   qdev_get_gpio_in(DEVICE(>uic), 2));
 
 /* GPIO */
 if (!sysbus_realize(SYS_BUS_DEVICE(>gpio), errp)) {
-- 
2.37.1




[PATCH v4 23/24] ppc/ppc405: QOM'ify SDRAM

2022-08-09 Thread Cédric Le Goater
This is an initial change of the SDRAM controller preserving the
compatibility with the current modeling. Further cleanup will be
possible after conversion of the ppc4xx_sdram_banks() and
ppc4xx_sdram_init() routines of the sam460ex and bamboo machines.

The size and base address of the RAM banks are now set using QOM
property arrays. RAM is equally distributed on each bank at the SoC
level depending on the number of banks we want to initialize (default
is 2). Each RAM memory region representing a RAM bank is initialized
in the realize routine of the SDRAM model after a minimal check on the
RAM size value with the sdram_bcr() routine. This has the benefit of
reporting an error to the user if the requested RAM size is invalid
for the SDRAM controller.

Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405.h |   6 +--
 include/hw/ppc/ppc4xx.h |  32 
 hw/ppc/ppc405_uc.c  |  34 
 hw/ppc/ppc4xx_devs.c| 113 
 4 files changed, 140 insertions(+), 45 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 56881b181ba1..8c19d167391c 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -228,12 +228,9 @@ struct Ppc405SoCState {
 DeviceState parent_obj;
 
 /* Public */
-MemoryRegion ram_banks[2];
-hwaddr ram_bases[2], ram_sizes[2];
-bool do_dram_init;
-
 MemoryRegion *dram_mr;
 hwaddr ram_size;
+uint32_t nr_banks;
 
 PowerPCCPU cpu;
 PPCUIC uic;
@@ -241,6 +238,7 @@ struct Ppc405SoCState {
 Ppc405GptState gpt;
 Ppc405OcmState ocm;
 Ppc405GpioState gpio;
+Ppc4xxSdramState sdram;
 Ppc405DmaState dma;
 PPC4xxI2CState i2c;
 Ppc405EbcState ebc;
diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
index acd096cb2394..b841f6600b55 100644
--- a/include/hw/ppc/ppc4xx.h
+++ b/include/hw/ppc/ppc4xx.h
@@ -87,4 +87,36 @@ struct Ppc4xxMalState {
 void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
  qemu_irq irqs[4]);
 
+/* SDRAM controller */
+#define TYPE_PPC4xx_SDRAM "ppc4xx-sdram"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxSdramState, PPC4xx_SDRAM);
+struct Ppc4xxSdramState {
+Ppc4xxDcrDeviceState parent_obj;
+
+MemoryRegion *dram_mr;
+bool dram_init;
+
+MemoryRegion containers[4]; /* used for clipping */
+MemoryRegion *ram_memories;
+hwaddr *ram_bases;
+hwaddr *ram_sizes;
+uint32_t nb_ram_bases;
+uint32_t nb_ram_sizes;
+uint32_t nbanks; /* Redundant */
+
+uint32_t addr;
+uint32_t besr0;
+uint32_t besr1;
+uint32_t bear;
+uint32_t cfg;
+uint32_t status;
+uint32_t rtr;
+uint32_t pmit;
+uint32_t bcr[4];
+uint32_t tr;
+uint32_t ecccfg;
+uint32_t eccesr;
+qemu_irq irq;
+};
+
 #endif /* PPC4XX_H */
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 1045f5f13e6c..fe0c92ba0d54 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1361,6 +1361,9 @@ static void ppc405_soc_instance_init(Object *obj)
 
 object_initialize_child(obj, "gpio", >gpio, TYPE_PPC405_GPIO);
 
+object_initialize_child(obj, "sdram", >sdram, TYPE_PPC4xx_SDRAM);
+object_property_add_alias(obj, "dram-init", OBJECT(>sdram), 
"dram-init");
+
 object_initialize_child(obj, "dma", >dma, TYPE_PPC405_DMA);
 
 object_initialize_child(obj, "i2c", >i2c, TYPE_PPC4xx_I2C);
@@ -1432,15 +1435,28 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 
 /* SDRAM controller */
 /* XXX 405EP has no ECC interrupt */
-s->ram_bases[0] = 0;
-s->ram_sizes[0] = s->ram_size;
-memory_region_init_alias(>ram_banks[0], OBJECT(s),
- "ppc405.sdram0", s->dram_mr,
- s->ram_bases[0], s->ram_sizes[0]);
+object_property_set_link(OBJECT(>sdram), "dram", OBJECT(s->dram_mr),
+ _abort);
+
+qdev_prop_set_uint32(DEVICE(>sdram), "len-ram-sizes", s->nr_banks);
+qdev_prop_set_uint32(DEVICE(>sdram), "len-ram-bases", s->nr_banks);
 
-ppc4xx_sdram_init(env, qdev_get_gpio_in(DEVICE(>uic), 17), 1,
-  s->ram_banks, s->ram_bases, s->ram_sizes,
-  s->do_dram_init);
+for (i = 0; i < s->nr_banks; i++) {
+char name[32];
+snprintf(name, sizeof(name), "ram-bases[%d]", i);
+qdev_prop_set_uint32(DEVICE(>sdram), name,
+ i * s->ram_size / s->nr_banks);
+
+snprintf(name, sizeof(name), "ram-sizes[%d]", i);
+qdev_prop_set_uint32(DEVICE(>sdram), name,
+ s->ram_size / s->nr_banks);
+}
+
+if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(>sdram), >cpu, errp)) {
+return;
+}
+sysbus_connect_irq(SYS_BUS_DEVICE(>sdram), 0,
+   qdev_get_gpio_in(DEVICE(>uic), 17));
 
 /* External bus controller */
 if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(>ebc), >cpu, errp)) {
@@ -1520,7 +1536,7 @@ static void 

[PATCH v4 22/24] ppc/ppc4xx: Fix sdram trace events

2022-08-09 Thread Cédric Le Goater
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc4xx_devs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 8a8a87b03b28..c06c20b195cd 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -143,7 +143,7 @@ static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i,
 }
 sdram->bcr[i] = bcr & 0xFFDEE001;
 if (enabled && (bcr & 0x0001)) {
-trace_ppc4xx_sdram_unmap(sdram_base(bcr), sdram_size(bcr));
+trace_ppc4xx_sdram_map(sdram_base(bcr), sdram_size(bcr));
 memory_region_init(>containers[i], NULL, "sdram-containers",
sdram_size(bcr));
 memory_region_add_subregion(>containers[i], 0,
-- 
2.37.1




[PATCH v4 14/24] ppc/ppc405: QOM'ify EBC

2022-08-09 Thread Cédric Le Goater
EBC is currently modeled as a DCR device. Also drop the ppc405_ebc_init()
helper and adapt the sam460ex machine.

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405.h| 17 +-
 hw/ppc/ppc405_uc.c | 57 +++---
 hw/ppc/sam460ex.c  |  4 +++-
 3 files changed, 48 insertions(+), 30 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index c75e4c7cb50a..82bf8dae931f 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -63,6 +63,21 @@ struct ppc4xx_bd_info_t {
 uint32_t bi_iic_fast[2];
 };
 
+/* Peripheral controller */
+#define TYPE_PPC405_EBC "ppc405-ebc"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc405EbcState, PPC405_EBC);
+struct Ppc405EbcState {
+Ppc4xxDcrDeviceState parent_obj;
+
+uint32_t addr;
+uint32_t bcr[8];
+uint32_t bap[8];
+uint32_t bear;
+uint32_t besr0;
+uint32_t besr1;
+uint32_t cfg;
+};
+
 /* DMA controller */
 #define TYPE_PPC405_DMA "ppc405-dma"
 OBJECT_DECLARE_SIMPLE_TYPE(Ppc405DmaState, PPC405_DMA);
@@ -192,12 +207,12 @@ struct Ppc405SoCState {
 Ppc405OcmState ocm;
 Ppc405GpioState gpio;
 Ppc405DmaState dma;
+Ppc405EbcState ebc;
 };
 
 /* PowerPC 405 core */
 ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size);
 
 void ppc4xx_plb_init(CPUPPCState *env);
-void ppc405_ebc_init(CPUPPCState *env);
 
 #endif /* PPC405_H */
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index fdf6dcd71e8d..3722387d6ac8 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -393,17 +393,6 @@ static void ppc4xx_opba_init(hwaddr base)
 
 /*/
 /* Peripheral controller */
-typedef struct ppc4xx_ebc_t ppc4xx_ebc_t;
-struct ppc4xx_ebc_t {
-uint32_t addr;
-uint32_t bcr[8];
-uint32_t bap[8];
-uint32_t bear;
-uint32_t besr0;
-uint32_t besr1;
-uint32_t cfg;
-};
-
 enum {
 EBC0_CFGADDR = 0x012,
 EBC0_CFGDATA = 0x013,
@@ -411,10 +400,9 @@ enum {
 
 static uint32_t dcr_read_ebc (void *opaque, int dcrn)
 {
-ppc4xx_ebc_t *ebc;
+Ppc405EbcState *ebc = PPC405_EBC(opaque);
 uint32_t ret;
 
-ebc = opaque;
 switch (dcrn) {
 case EBC0_CFGADDR:
 ret = ebc->addr;
@@ -496,9 +484,8 @@ static uint32_t dcr_read_ebc (void *opaque, int dcrn)
 
 static void dcr_write_ebc (void *opaque, int dcrn, uint32_t val)
 {
-ppc4xx_ebc_t *ebc;
+Ppc405EbcState *ebc = PPC405_EBC(opaque);
 
-ebc = opaque;
 switch (dcrn) {
 case EBC0_CFGADDR:
 ebc->addr = val;
@@ -554,12 +541,11 @@ static void dcr_write_ebc (void *opaque, int dcrn, 
uint32_t val)
 }
 }
 
-static void ebc_reset (void *opaque)
+static void ppc405_ebc_reset(DeviceState *opaque)
 {
-ppc4xx_ebc_t *ebc;
+Ppc405EbcState *ebc = PPC405_EBC(opaque);
 int i;
 
-ebc = opaque;
 ebc->addr = 0x;
 ebc->bap[0] = 0x7F8FFE80;
 ebc->bcr[0] = 0xFFE28000;
@@ -572,16 +558,22 @@ static void ebc_reset (void *opaque)
 ebc->cfg = 0x8040;
 }
 
-void ppc405_ebc_init(CPUPPCState *env)
+static void ppc405_ebc_realize(DeviceState *dev, Error **errp)
 {
-ppc4xx_ebc_t *ebc;
-
-ebc = g_new0(ppc4xx_ebc_t, 1);
-qemu_register_reset(_reset, ebc);
-ppc_dcr_register(env, EBC0_CFGADDR,
- ebc, _read_ebc, _write_ebc);
-ppc_dcr_register(env, EBC0_CFGDATA,
- ebc, _read_ebc, _write_ebc);
+Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
+
+ppc4xx_dcr_register(dcr, EBC0_CFGADDR, _read_ebc, _write_ebc);
+ppc4xx_dcr_register(dcr, EBC0_CFGDATA, _read_ebc, _write_ebc);
+}
+
+static void ppc405_ebc_class_init(ObjectClass *oc, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(oc);
+
+dc->realize = ppc405_ebc_realize;
+/* Reason: only works as function of a ppc4xx SoC */
+dc->user_creatable = false;
+dc->reset = ppc405_ebc_reset;
 }
 
 /*/
@@ -1372,6 +1364,8 @@ static void ppc405_soc_instance_init(Object *obj)
 object_initialize_child(obj, "gpio", >gpio, TYPE_PPC405_GPIO);
 
 object_initialize_child(obj, "dma", >dma, TYPE_PPC405_DMA);
+
+object_initialize_child(obj, "ebc", >ebc, TYPE_PPC405_EBC);
 }
 
 static void ppc405_reset(void *opaque)
@@ -1437,7 +1431,9 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
   s->do_dram_init);
 
 /* External bus controller */
-ppc405_ebc_init(env);
+if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(>ebc), >cpu, errp)) {
+return;
+}
 
 /* DMA controller */
 if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(>dma), >cpu, errp)) {
@@ -1520,6 +1516,11 @@ static void ppc405_soc_class_init(ObjectClass *oc, void 
*data)
 
 static const TypeInfo ppc405_types[] = {
 {
+.name   = TYPE_PPC405_EBC,
+.parent = TYPE_PPC4xx_DCR_DEVICE,
+.instance_size  = 

[PATCH v4 18/24] ppc/ppc405: QOM'ify MAL

2022-08-09 Thread Cédric Le Goater
The Memory Access Layer (MAL) controller is currently modeled as a DCR
device with 4 IRQs. Also drop the ppc4xx_mal_init() helper and adapt
the sam460ex machine.

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405.h |   1 +
 include/hw/ppc/ppc4xx.h |  32 +-
 hw/ppc/ppc405_uc.c  |  18 --
 hw/ppc/ppc4xx_devs.c| 135 ++--
 hw/ppc/sam460ex.c   |  16 +++--
 5 files changed, 116 insertions(+), 86 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index cb34792daf6b..31c94e474209 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -244,6 +244,7 @@ struct Ppc405SoCState {
 Ppc405OpbaState opba;
 Ppc405PobState pob;
 Ppc405PlbState plb;
+Ppc4xxMalState mal;
 };
 
 /* PowerPC 405 core */
diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
index 82e60b0e0742..acd096cb2394 100644
--- a/include/hw/ppc/ppc4xx.h
+++ b/include/hw/ppc/ppc4xx.h
@@ -26,6 +26,7 @@
 #define PPC4XX_H
 
 #include "hw/ppc/ppc.h"
+#include "hw/sysbus.h"
 #include "exec/memory.h"
 #include "hw/sysbus.h"
 
@@ -40,9 +41,6 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int 
nbanks,
 hwaddr *ram_sizes,
 int do_init);
 
-void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
- qemu_irq irqs[4]);
-
 #define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost"
 
 /*
@@ -61,4 +59,32 @@ void ppc4xx_dcr_register(Ppc4xxDcrDeviceState *dev, int dcrn,
 bool ppc4xx_dcr_realize(Ppc4xxDcrDeviceState *dev, PowerPCCPU *cpu,
 Error **errp);
 
+/* Memory Access Layer (MAL) */
+#define TYPE_PPC4xx_MAL "ppc4xx-mal"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxMalState, PPC4xx_MAL);
+struct Ppc4xxMalState {
+Ppc4xxDcrDeviceState parent_obj;
+
+qemu_irq irqs[4];
+uint32_t cfg;
+uint32_t esr;
+uint32_t ier;
+uint32_t txcasr;
+uint32_t txcarr;
+uint32_t txeobisr;
+uint32_t txdeir;
+uint32_t rxcasr;
+uint32_t rxcarr;
+uint32_t rxeobisr;
+uint32_t rxdeir;
+uint32_t *txctpr;
+uint32_t *rxctpr;
+uint32_t *rcbs;
+uint8_t  txcnum;
+uint8_t  rxcnum;
+};
+
+void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
+ qemu_irq irqs[4]);
+
 #endif /* PPC4XX_H */
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 7f4c616da67c..290cfa352bed 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1368,6 +1368,8 @@ static void ppc405_soc_instance_init(Object *obj)
 object_initialize_child(obj, "pob", >pob, TYPE_PPC405_POB);
 
 object_initialize_child(obj, "plb", >plb, TYPE_PPC405_PLB);
+
+object_initialize_child(obj, "mal", >mal, TYPE_PPC4xx_MAL);
 }
 
 static void ppc405_reset(void *opaque)
@@ -1378,7 +1380,6 @@ static void ppc405_reset(void *opaque)
 static void ppc405_soc_realize(DeviceState *dev, Error **errp)
 {
 Ppc405SoCState *s = PPC405_SOC(dev);
-qemu_irq mal_irqs[4];
 CPUPPCState *env;
 int i;
 
@@ -1495,11 +1496,16 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 }
 
 /* MAL */
-mal_irqs[0] = qdev_get_gpio_in(s->uic, 11);
-mal_irqs[1] = qdev_get_gpio_in(s->uic, 12);
-mal_irqs[2] = qdev_get_gpio_in(s->uic, 13);
-mal_irqs[3] = qdev_get_gpio_in(s->uic, 14);
-ppc4xx_mal_init(env, 4, 2, mal_irqs);
+object_property_set_int(OBJECT(>mal), "txc-num", 4, _abort);
+object_property_set_int(OBJECT(>mal), "rxc-num", 2, _abort);
+if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(>mal), >cpu, errp)) {
+return;
+}
+
+for (i = 0; i < ARRAY_SIZE(s->mal.irqs); i++) {
+sysbus_connect_irq(SYS_BUS_DEVICE(>mal), i,
+   qdev_get_gpio_in(s->uic, 11 + i));
+}
 
 /* Ethernet */
 /* Uses UIC IRQs 9, 15, 17 */
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index bce7ef461346..8a8a87b03b28 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -459,32 +459,10 @@ enum {
 MAL0_RCBS1= 0x1E1,
 };
 
-typedef struct ppc4xx_mal_t ppc4xx_mal_t;
-struct ppc4xx_mal_t {
-qemu_irq irqs[4];
-uint32_t cfg;
-uint32_t esr;
-uint32_t ier;
-uint32_t txcasr;
-uint32_t txcarr;
-uint32_t txeobisr;
-uint32_t txdeir;
-uint32_t rxcasr;
-uint32_t rxcarr;
-uint32_t rxeobisr;
-uint32_t rxdeir;
-uint32_t *txctpr;
-uint32_t *rxctpr;
-uint32_t *rcbs;
-uint8_t  txcnum;
-uint8_t  rxcnum;
-};
-
-static void ppc4xx_mal_reset(void *opaque)
+static void ppc4xx_mal_reset(DeviceState *dev)
 {
-ppc4xx_mal_t *mal;
+Ppc4xxMalState *mal = PPC4xx_MAL(dev);
 
-mal = opaque;
 mal->cfg = 0x0007C000;
 mal->esr = 0x;
 mal->ier = 0x;
@@ -498,10 +476,9 @@ static void ppc4xx_mal_reset(void *opaque)
 
 static uint32_t dcr_read_mal(void *opaque, int dcrn)
 {
-ppc4xx_mal_t *mal;
+Ppc4xxMalState *mal = PPC4xx_MAL(opaque);
 

[PATCH v4 17/24] ppc/ppc405: QOM'ify PLB

2022-08-09 Thread Cédric Le Goater
PLB is currently modeled as a simple DCR device. Also drop the
ppc4xx_plb_init() helper and adapt the sam460ex machine.

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405.h| 14 +--
 hw/ppc/ppc405_uc.c | 59 ++
 hw/ppc/sam460ex.c  |  4 +++-
 3 files changed, 48 insertions(+), 29 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 4140e811d5ec..cb34792daf6b 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -63,6 +63,17 @@ struct ppc4xx_bd_info_t {
 uint32_t bi_iic_fast[2];
 };
 
+/* Peripheral local bus arbitrer */
+#define TYPE_PPC405_PLB "ppc405-plb"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc405PlbState, PPC405_PLB);
+struct Ppc405PlbState {
+Ppc4xxDcrDeviceState parent_obj;
+
+uint32_t acr;
+uint32_t bear;
+uint32_t besr;
+};
+
 /* PLB to OPB bridge */
 #define TYPE_PPC405_POB "ppc405-pob"
 OBJECT_DECLARE_SIMPLE_TYPE(Ppc405PobState, PPC405_POB);
@@ -232,11 +243,10 @@ struct Ppc405SoCState {
 Ppc405EbcState ebc;
 Ppc405OpbaState opba;
 Ppc405PobState pob;
+Ppc405PlbState plb;
 };
 
 /* PowerPC 405 core */
 ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size);
 
-void ppc4xx_plb_init(CPUPPCState *env);
-
 #endif /* PPC405_H */
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 2ea34090de49..7f4c616da67c 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -148,19 +148,11 @@ enum {
 PLB4A1_ACR = 0x089,
 };
 
-typedef struct ppc4xx_plb_t ppc4xx_plb_t;
-struct ppc4xx_plb_t {
-uint32_t acr;
-uint32_t bear;
-uint32_t besr;
-};
-
 static uint32_t dcr_read_plb (void *opaque, int dcrn)
 {
-ppc4xx_plb_t *plb;
+Ppc405PlbState *plb = PPC405_PLB(opaque);
 uint32_t ret;
 
-plb = opaque;
 switch (dcrn) {
 case PLB0_ACR:
 ret = plb->acr;
@@ -182,9 +174,8 @@ static uint32_t dcr_read_plb (void *opaque, int dcrn)
 
 static void dcr_write_plb (void *opaque, int dcrn, uint32_t val)
 {
-ppc4xx_plb_t *plb;
+Ppc405PlbState *plb = PPC405_PLB(opaque);
 
-plb = opaque;
 switch (dcrn) {
 case PLB0_ACR:
 /* We don't care about the actual parameters written as
@@ -202,28 +193,35 @@ static void dcr_write_plb (void *opaque, int dcrn, 
uint32_t val)
 }
 }
 
-static void ppc4xx_plb_reset (void *opaque)
+static void ppc405_plb_reset(DeviceState *opaque)
 {
-ppc4xx_plb_t *plb;
+Ppc405PlbState *plb = PPC405_PLB(opaque);
 
-plb = opaque;
 plb->acr = 0x;
 plb->bear = 0x;
 plb->besr = 0x;
 }
 
-void ppc4xx_plb_init(CPUPPCState *env)
+static void ppc405_plb_realize(DeviceState *dev, Error **errp)
+{
+Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
+
+ppc4xx_dcr_register(dcr, PLB3A0_ACR, _read_plb, _write_plb);
+ppc4xx_dcr_register(dcr, PLB4A0_ACR, _read_plb, _write_plb);
+ppc4xx_dcr_register(dcr, PLB0_ACR, _read_plb, _write_plb);
+ppc4xx_dcr_register(dcr, PLB0_BEAR, _read_plb, _write_plb);
+ppc4xx_dcr_register(dcr, PLB0_BESR, _read_plb, _write_plb);
+ppc4xx_dcr_register(dcr, PLB4A1_ACR, _read_plb, _write_plb);
+}
+
+static void ppc405_plb_class_init(ObjectClass *oc, void *data)
 {
-ppc4xx_plb_t *plb;
-
-plb = g_new0(ppc4xx_plb_t, 1);
-ppc_dcr_register(env, PLB3A0_ACR, plb, _read_plb, _write_plb);
-ppc_dcr_register(env, PLB4A0_ACR, plb, _read_plb, _write_plb);
-ppc_dcr_register(env, PLB0_ACR, plb, _read_plb, _write_plb);
-ppc_dcr_register(env, PLB0_BEAR, plb, _read_plb, _write_plb);
-ppc_dcr_register(env, PLB0_BESR, plb, _read_plb, _write_plb);
-ppc_dcr_register(env, PLB4A1_ACR, plb, _read_plb, _write_plb);
-qemu_register_reset(ppc4xx_plb_reset, plb);
+DeviceClass *dc = DEVICE_CLASS(oc);
+
+dc->realize = ppc405_plb_realize;
+/* Reason: only works as function of a ppc4xx SoC */
+dc->user_creatable = false;
+dc->reset = ppc405_plb_reset;
 }
 
 /*/
@@ -1368,6 +1366,8 @@ static void ppc405_soc_instance_init(Object *obj)
 object_initialize_child(obj, "opba", >opba, TYPE_PPC405_OPBA);
 
 object_initialize_child(obj, "pob", >pob, TYPE_PPC405_POB);
+
+object_initialize_child(obj, "plb", >plb, TYPE_PPC405_PLB);
 }
 
 static void ppc405_reset(void *opaque)
@@ -1398,7 +1398,9 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 }
 
 /* PLB arbitrer */
-ppc4xx_plb_init(env);
+if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(>plb), >cpu, errp)) {
+return;
+}
 
 /* PLB to OPB bridge */
 if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(>pob), >cpu, errp)) {
@@ -1523,6 +1525,11 @@ static void ppc405_soc_class_init(ObjectClass *oc, void 
*data)
 
 static const TypeInfo ppc405_types[] = {
 {
+.name   = TYPE_PPC405_PLB,
+.parent = TYPE_PPC4xx_DCR_DEVICE,
+.instance_size  = sizeof(Ppc405PlbState),
+.class_init

[PATCH v4 19/24] ppc/ppc405: QOM'ify FPGA

2022-08-09 Thread Cédric Le Goater
Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405_boards.c | 55 +-
 1 file changed, 38 insertions(+), 17 deletions(-)

diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 3677793adc75..4ff6715f3533 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -71,18 +71,23 @@ struct Ppc405MachineState {
  * - NVRAM (0xF000)
  * - FPGA  (0xF030)
  */
-typedef struct ref405ep_fpga_t ref405ep_fpga_t;
-struct ref405ep_fpga_t {
+
+#define TYPE_REF405EP_FPGA "ref405ep-fpga"
+OBJECT_DECLARE_SIMPLE_TYPE(Ref405epFpgaState, REF405EP_FPGA);
+struct Ref405epFpgaState {
+SysBusDevice parent_obj;
+
+MemoryRegion iomem;
+
 uint8_t reg0;
 uint8_t reg1;
 };
 
 static uint64_t ref405ep_fpga_readb(void *opaque, hwaddr addr, unsigned size)
 {
-ref405ep_fpga_t *fpga;
+Ref405epFpgaState *fpga = REF405EP_FPGA(opaque);
 uint32_t ret;
 
-fpga = opaque;
 switch (addr) {
 case 0x0:
 ret = fpga->reg0;
@@ -101,9 +106,8 @@ static uint64_t ref405ep_fpga_readb(void *opaque, hwaddr 
addr, unsigned size)
 static void ref405ep_fpga_writeb(void *opaque, hwaddr addr, uint64_t value,
  unsigned size)
 {
-ref405ep_fpga_t *fpga;
+Ref405epFpgaState *fpga = REF405EP_FPGA(opaque);
 
-fpga = opaque;
 switch (addr) {
 case 0x0:
 /* Read only */
@@ -126,27 +130,39 @@ static const MemoryRegionOps ref405ep_fpga_ops = {
 .endianness = DEVICE_BIG_ENDIAN,
 };
 
-static void ref405ep_fpga_reset (void *opaque)
+static void ref405ep_fpga_reset(DeviceState *dev)
 {
-ref405ep_fpga_t *fpga;
+Ref405epFpgaState *fpga = REF405EP_FPGA(dev);
 
-fpga = opaque;
 fpga->reg0 = 0x00;
 fpga->reg1 = 0x0F;
 }
 
-static void ref405ep_fpga_init(MemoryRegion *sysmem, uint32_t base)
+static void ref405ep_fpga_realize(DeviceState *dev, Error **errp)
 {
-ref405ep_fpga_t *fpga;
-MemoryRegion *fpga_memory = g_new(MemoryRegion, 1);
+Ref405epFpgaState *s = REF405EP_FPGA(dev);
 
-fpga = g_new0(ref405ep_fpga_t, 1);
-memory_region_init_io(fpga_memory, NULL, _fpga_ops, fpga,
+memory_region_init_io(>iomem, OBJECT(s), _fpga_ops, s,
   "fpga", 0x0100);
-memory_region_add_subregion(sysmem, base, fpga_memory);
-qemu_register_reset(_fpga_reset, fpga);
+sysbus_init_mmio(SYS_BUS_DEVICE(s), >iomem);
+}
+
+static void ref405ep_fpga_class_init(ObjectClass *oc, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(oc);
+
+dc->realize = ref405ep_fpga_realize;
+dc->user_creatable = false;
+dc->reset = ref405ep_fpga_reset;
 }
 
+static const TypeInfo ref405ep_fpga_type = {
+.name = TYPE_REF405EP_FPGA,
+.parent = TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(Ref405epFpgaState),
+.class_init = ref405ep_fpga_class_init,
+};
+
 /*
  * CPU reset handler when booting directly from a loaded kernel
  */
@@ -331,7 +347,11 @@ static void ref405ep_init(MachineState *machine)
 memory_region_add_subregion(get_system_memory(), PPC405EP_SRAM_BASE, sram);
 
 /* Register FPGA */
-ref405ep_fpga_init(get_system_memory(), PPC405EP_FPGA_BASE);
+dev = qdev_new(TYPE_REF405EP_FPGA);
+object_property_add_child(OBJECT(machine), "fpga", OBJECT(dev));
+sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), _fatal);
+sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, PPC405EP_FPGA_BASE);
+
 /* Register NVRAM */
 dev = qdev_new("sysbus-m48t08");
 qdev_prop_set_int32(dev, "base-year", 1968);
@@ -376,6 +396,7 @@ static void ppc405_machine_init(void)
 {
 type_register_static(_machine_type);
 type_register_static(_type);
+type_register_static(_fpga_type);
 }
 
 type_init(ppc405_machine_init)
-- 
2.37.1




[PATCH v4 13/24] ppc/ppc405: QOM'ify DMA

2022-08-09 Thread Cédric Le Goater
The DMA controller is currently modeled as a DCR device with a couple
of IRQs.

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405.h|  19 ++
 hw/ppc/ppc405_uc.c | 142 -
 2 files changed, 82 insertions(+), 79 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 21f6cb358501..c75e4c7cb50a 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -63,6 +63,24 @@ struct ppc4xx_bd_info_t {
 uint32_t bi_iic_fast[2];
 };
 
+/* DMA controller */
+#define TYPE_PPC405_DMA "ppc405-dma"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc405DmaState, PPC405_DMA);
+struct Ppc405DmaState {
+Ppc4xxDcrDeviceState parent_obj;
+
+qemu_irq irqs[4];
+uint32_t cr[4];
+uint32_t ct[4];
+uint32_t da[4];
+uint32_t sa[4];
+uint32_t sg[4];
+uint32_t sr;
+uint32_t sgc;
+uint32_t slp;
+uint32_t pol;
+};
+
 /* GPIO */
 #define TYPE_PPC405_GPIO "ppc405-gpio"
 OBJECT_DECLARE_SIMPLE_TYPE(Ppc405GpioState, PPC405_GPIO);
@@ -173,6 +191,7 @@ struct Ppc405SoCState {
 Ppc405GptState gpt;
 Ppc405OcmState ocm;
 Ppc405GpioState gpio;
+Ppc405DmaState dma;
 };
 
 /* PowerPC 405 core */
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 1a2cbac2748b..fdf6dcd71e8d 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -613,35 +613,20 @@ enum {
 DMA0_POL = 0x126,
 };
 
-typedef struct ppc405_dma_t ppc405_dma_t;
-struct ppc405_dma_t {
-qemu_irq irqs[4];
-uint32_t cr[4];
-uint32_t ct[4];
-uint32_t da[4];
-uint32_t sa[4];
-uint32_t sg[4];
-uint32_t sr;
-uint32_t sgc;
-uint32_t slp;
-uint32_t pol;
-};
-
-static uint32_t dcr_read_dma (void *opaque, int dcrn)
+static uint32_t dcr_read_dma(void *opaque, int dcrn)
 {
 return 0;
 }
 
-static void dcr_write_dma (void *opaque, int dcrn, uint32_t val)
+static void dcr_write_dma(void *opaque, int dcrn, uint32_t val)
 {
 }
 
-static void ppc405_dma_reset (void *opaque)
+static void ppc405_dma_reset(DeviceState *dev)
 {
-ppc405_dma_t *dma;
+Ppc405DmaState *dma = PPC405_DMA(dev);
 int i;
 
-dma = opaque;
 for (i = 0; i < 4; i++) {
 dma->cr[i] = 0x;
 dma->ct[i] = 0x;
@@ -655,61 +640,50 @@ static void ppc405_dma_reset (void *opaque)
 dma->pol = 0x;
 }
 
-static void ppc405_dma_init(CPUPPCState *env, qemu_irq irqs[4])
+static void ppc405_dma_realize(DeviceState *dev, Error **errp)
 {
-ppc405_dma_t *dma;
-
-dma = g_new0(ppc405_dma_t, 1);
-memcpy(dma->irqs, irqs, 4 * sizeof(qemu_irq));
-qemu_register_reset(_dma_reset, dma);
-ppc_dcr_register(env, DMA0_CR0,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_CT0,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_DA0,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_SA0,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_SG0,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_CR1,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_CT1,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_DA1,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_SA1,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_SG1,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_CR2,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_CT2,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_DA2,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_SA2,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_SG2,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_CR3,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_CT3,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_DA3,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_SA3,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_SG3,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_SR,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_SGC,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_SLP,
- dma, _read_dma, _write_dma);
-ppc_dcr_register(env, DMA0_POL,
- dma, _read_dma, _write_dma);
+Ppc405DmaState *dma = PPC405_DMA(dev);
+Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
+int i;
+
+for (i = 0; i < ARRAY_SIZE(dma->irqs); i++) {
+sysbus_init_irq(SYS_BUS_DEVICE(dma), >irqs[i]);
+}
+
+

[PATCH v4 16/24] ppc/ppc405: QOM'ify POB

2022-08-09 Thread Cédric Le Goater
POB is currently modeled as a simple DCR device.

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405.h| 12 +++
 hw/ppc/ppc405_uc.c | 51 ++
 2 files changed, 41 insertions(+), 22 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index d63c2acdc7b5..4140e811d5ec 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -63,6 +63,17 @@ struct ppc4xx_bd_info_t {
 uint32_t bi_iic_fast[2];
 };
 
+/* PLB to OPB bridge */
+#define TYPE_PPC405_POB "ppc405-pob"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc405PobState, PPC405_POB);
+struct Ppc405PobState {
+Ppc4xxDcrDeviceState parent_obj;
+
+uint32_t bear;
+uint32_t besr0;
+uint32_t besr1;
+};
+
 /* OPB arbitrer */
 #define TYPE_PPC405_OPBA "ppc405-opba"
 OBJECT_DECLARE_SIMPLE_TYPE(Ppc405OpbaState, PPC405_OPBA);
@@ -220,6 +231,7 @@ struct Ppc405SoCState {
 Ppc405DmaState dma;
 Ppc405EbcState ebc;
 Ppc405OpbaState opba;
+Ppc405PobState pob;
 };
 
 /* PowerPC 405 core */
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 447a654a349a..2ea34090de49 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -234,19 +234,11 @@ enum {
 POB0_BEAR  = 0x0A4,
 };
 
-typedef struct ppc4xx_pob_t ppc4xx_pob_t;
-struct ppc4xx_pob_t {
-uint32_t bear;
-uint32_t besr0;
-uint32_t besr1;
-};
-
 static uint32_t dcr_read_pob (void *opaque, int dcrn)
 {
-ppc4xx_pob_t *pob;
+Ppc405PobState *pob = PPC405_POB(opaque);
 uint32_t ret;
 
-pob = opaque;
 switch (dcrn) {
 case POB0_BEAR:
 ret = pob->bear;
@@ -268,9 +260,8 @@ static uint32_t dcr_read_pob (void *opaque, int dcrn)
 
 static void dcr_write_pob (void *opaque, int dcrn, uint32_t val)
 {
-ppc4xx_pob_t *pob;
+Ppc405PobState *pob = PPC405_POB(opaque);
 
-pob = opaque;
 switch (dcrn) {
 case POB0_BEAR:
 /* Read only */
@@ -286,26 +277,33 @@ static void dcr_write_pob (void *opaque, int dcrn, 
uint32_t val)
 }
 }
 
-static void ppc4xx_pob_reset (void *opaque)
+static void ppc405_pob_reset(DeviceState *opaque)
 {
-ppc4xx_pob_t *pob;
+Ppc405PobState *pob = PPC405_POB(opaque);
 
-pob = opaque;
 /* No error */
 pob->bear = 0x;
 pob->besr0 = 0x000;
 pob->besr1 = 0x000;
 }
 
-static void ppc4xx_pob_init(CPUPPCState *env)
+static void ppc405_pob_realize(DeviceState *dev, Error **errp)
+{
+Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
+
+ppc4xx_dcr_register(dcr, POB0_BEAR, _read_pob, _write_pob);
+ppc4xx_dcr_register(dcr, POB0_BESR0, _read_pob, _write_pob);
+ppc4xx_dcr_register(dcr, POB0_BESR1, _read_pob, _write_pob);
+}
+
+static void ppc405_pob_class_init(ObjectClass *oc, void *data)
 {
-ppc4xx_pob_t *pob;
+DeviceClass *dc = DEVICE_CLASS(oc);
 
-pob = g_new0(ppc4xx_pob_t, 1);
-ppc_dcr_register(env, POB0_BEAR, pob, _read_pob, _write_pob);
-ppc_dcr_register(env, POB0_BESR0, pob, _read_pob, _write_pob);
-ppc_dcr_register(env, POB0_BESR1, pob, _read_pob, _write_pob);
-qemu_register_reset(ppc4xx_pob_reset, pob);
+dc->realize = ppc405_pob_realize;
+/* Reason: only works as function of a ppc4xx SoC */
+dc->user_creatable = false;
+dc->reset = ppc405_pob_reset;
 }
 
 /*/
@@ -1368,6 +1366,8 @@ static void ppc405_soc_instance_init(Object *obj)
 object_initialize_child(obj, "ebc", >ebc, TYPE_PPC405_EBC);
 
 object_initialize_child(obj, "opba", >opba, TYPE_PPC405_OPBA);
+
+object_initialize_child(obj, "pob", >pob, TYPE_PPC405_POB);
 }
 
 static void ppc405_reset(void *opaque)
@@ -1401,7 +1401,9 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 ppc4xx_plb_init(env);
 
 /* PLB to OPB bridge */
-ppc4xx_pob_init(env);
+if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(>pob), >cpu, errp)) {
+return;
+}
 
 /* OBP arbitrer */
 if (!sysbus_realize(SYS_BUS_DEVICE(>opba), errp)) {
@@ -1521,6 +1523,11 @@ static void ppc405_soc_class_init(ObjectClass *oc, void 
*data)
 
 static const TypeInfo ppc405_types[] = {
 {
+.name   = TYPE_PPC405_POB,
+.parent = TYPE_PPC4xx_DCR_DEVICE,
+.instance_size  = sizeof(Ppc405PobState),
+.class_init = ppc405_pob_class_init,
+}, {
 .name   = TYPE_PPC405_OPBA,
 .parent = TYPE_SYS_BUS_DEVICE,
 .instance_size  = sizeof(Ppc405OpbaState),
-- 
2.37.1




[PATCH v4 11/24] ppc/ppc405: QOM'ify OCM

2022-08-09 Thread Cédric Le Goater
The OCM controller is currently modeled as a simple DCR device with
a couple of memory regions.

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405.h| 16 ++
 hw/ppc/ppc405_uc.c | 73 +++---
 2 files changed, 53 insertions(+), 36 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index bcf55e4f6b2e..a5b493d3e7bf 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -63,6 +63,21 @@ struct ppc4xx_bd_info_t {
 uint32_t bi_iic_fast[2];
 };
 
+/* On Chip Memory */
+#define TYPE_PPC405_OCM "ppc405-ocm"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc405OcmState, PPC405_OCM);
+struct Ppc405OcmState {
+Ppc4xxDcrDeviceState parent_obj;
+
+MemoryRegion ram;
+MemoryRegion isarc_ram;
+MemoryRegion dsarc_ram;
+uint32_t isarc;
+uint32_t isacntl;
+uint32_t dsarc;
+uint32_t dsacntl;
+};
+
 /* General purpose timers */
 #define TYPE_PPC405_GPT "ppc405-gpt"
 OBJECT_DECLARE_SIMPLE_TYPE(Ppc405GptState, PPC405_GPT);
@@ -136,6 +151,7 @@ struct Ppc405SoCState {
 DeviceState *uic;
 Ppc405CpcState cpc;
 Ppc405GptState gpt;
+Ppc405OcmState ocm;
 };
 
 /* PowerPC 405 core */
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index c4d137073862..8b15132aadc0 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -773,20 +773,9 @@ enum {
 OCM0_DSACNTL = 0x01B,
 };
 
-typedef struct ppc405_ocm_t ppc405_ocm_t;
-struct ppc405_ocm_t {
-MemoryRegion ram;
-MemoryRegion isarc_ram;
-MemoryRegion dsarc_ram;
-uint32_t isarc;
-uint32_t isacntl;
-uint32_t dsarc;
-uint32_t dsacntl;
-};
-
-static void ocm_update_mappings (ppc405_ocm_t *ocm,
- uint32_t isarc, uint32_t isacntl,
- uint32_t dsarc, uint32_t dsacntl)
+static void ocm_update_mappings(Ppc405OcmState *ocm,
+uint32_t isarc, uint32_t isacntl,
+uint32_t dsarc, uint32_t dsacntl)
 {
 trace_ocm_update_mappings(isarc, isacntl, dsarc, dsacntl, ocm->isarc,
   ocm->isacntl, ocm->dsarc, ocm->dsacntl);
@@ -830,10 +819,9 @@ static void ocm_update_mappings (ppc405_ocm_t *ocm,
 
 static uint32_t dcr_read_ocm (void *opaque, int dcrn)
 {
-ppc405_ocm_t *ocm;
+Ppc405OcmState *ocm = PPC405_OCM(opaque);
 uint32_t ret;
 
-ocm = opaque;
 switch (dcrn) {
 case OCM0_ISARC:
 ret = ocm->isarc;
@@ -857,10 +845,9 @@ static uint32_t dcr_read_ocm (void *opaque, int dcrn)
 
 static void dcr_write_ocm (void *opaque, int dcrn, uint32_t val)
 {
-ppc405_ocm_t *ocm;
+Ppc405OcmState *ocm = PPC405_OCM(opaque);
 uint32_t isarc, dsarc, isacntl, dsacntl;
 
-ocm = opaque;
 isarc = ocm->isarc;
 dsarc = ocm->dsarc;
 isacntl = ocm->isacntl;
@@ -886,12 +873,11 @@ static void dcr_write_ocm (void *opaque, int dcrn, 
uint32_t val)
 ocm->dsacntl = dsacntl;
 }
 
-static void ocm_reset (void *opaque)
+static void ppc405_ocm_reset(DeviceState *dev)
 {
-ppc405_ocm_t *ocm;
+Ppc405OcmState *ocm = PPC405_OCM(dev);
 uint32_t isarc, dsarc, isacntl, dsacntl;
 
-ocm = opaque;
 isarc = 0x;
 isacntl = 0x;
 dsarc = 0x;
@@ -903,25 +889,31 @@ static void ocm_reset (void *opaque)
 ocm->dsacntl = dsacntl;
 }
 
-static void ppc405_ocm_init(CPUPPCState *env)
+static void ppc405_ocm_realize(DeviceState *dev, Error **errp)
 {
-ppc405_ocm_t *ocm;
+Ppc405OcmState *ocm = PPC405_OCM(dev);
+Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
 
-ocm = g_new0(ppc405_ocm_t, 1);
 /* XXX: Size is 4096 or 0x0400 */
-memory_region_init_ram(>isarc_ram, NULL, "ppc405.ocm", 4 * KiB,
+memory_region_init_ram(>isarc_ram, OBJECT(ocm), "ppc405.ocm", 4 * KiB,
_fatal);
-memory_region_init_alias(>dsarc_ram, NULL, "ppc405.dsarc",
+memory_region_init_alias(>dsarc_ram, OBJECT(ocm), "ppc405.dsarc",
  >isarc_ram, 0, 4 * KiB);
-qemu_register_reset(_reset, ocm);
-ppc_dcr_register(env, OCM0_ISARC,
- ocm, _read_ocm, _write_ocm);
-ppc_dcr_register(env, OCM0_ISACNTL,
- ocm, _read_ocm, _write_ocm);
-ppc_dcr_register(env, OCM0_DSARC,
- ocm, _read_ocm, _write_ocm);
-ppc_dcr_register(env, OCM0_DSACNTL,
- ocm, _read_ocm, _write_ocm);
+
+ppc4xx_dcr_register(dcr, OCM0_ISARC, _read_ocm, _write_ocm);
+ppc4xx_dcr_register(dcr, OCM0_ISACNTL, _read_ocm, _write_ocm);
+ppc4xx_dcr_register(dcr, OCM0_DSARC, _read_ocm, _write_ocm);
+ppc4xx_dcr_register(dcr, OCM0_DSACNTL, _read_ocm, _write_ocm);
+}
+
+static void ppc405_ocm_class_init(ObjectClass *oc, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(oc);
+
+dc->realize = ppc405_ocm_realize;
+/* Reason: only works as function of a ppc4xx SoC */
+dc->user_creatable = false;
+dc->reset = 

[PATCH v4 12/24] ppc/ppc405: QOM'ify GPIO

2022-08-09 Thread Cédric Le Goater
The GPIO controller is currently modeled as a simple SysBus device
with a unique memory region.

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405.h | 21 +++
 hw/ppc/ppc405_uc.c  | 51 +
 hw/ppc/trace-events |  1 -
 3 files changed, 45 insertions(+), 28 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index a5b493d3e7bf..21f6cb358501 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -63,6 +63,26 @@ struct ppc4xx_bd_info_t {
 uint32_t bi_iic_fast[2];
 };
 
+/* GPIO */
+#define TYPE_PPC405_GPIO "ppc405-gpio"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc405GpioState, PPC405_GPIO);
+struct Ppc405GpioState {
+SysBusDevice parent_obj;
+
+MemoryRegion io;
+uint32_t or;
+uint32_t tcr;
+uint32_t osrh;
+uint32_t osrl;
+uint32_t tsrh;
+uint32_t tsrl;
+uint32_t odr;
+uint32_t ir;
+uint32_t rr1;
+uint32_t isr1h;
+uint32_t isr1l;
+};
+
 /* On Chip Memory */
 #define TYPE_PPC405_OCM "ppc405-ocm"
 OBJECT_DECLARE_SIMPLE_TYPE(Ppc405OcmState, PPC405_OCM);
@@ -152,6 +172,7 @@ struct Ppc405SoCState {
 Ppc405CpcState cpc;
 Ppc405GptState gpt;
 Ppc405OcmState ocm;
+Ppc405GpioState gpio;
 };
 
 /* PowerPC 405 core */
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 8b15132aadc0..1a2cbac2748b 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -713,23 +713,6 @@ static void ppc405_dma_init(CPUPPCState *env, qemu_irq 
irqs[4])
 }
 
 /*/
-/* GPIO */
-typedef struct ppc405_gpio_t ppc405_gpio_t;
-struct ppc405_gpio_t {
-MemoryRegion io;
-uint32_t or;
-uint32_t tcr;
-uint32_t osrh;
-uint32_t osrl;
-uint32_t tsrh;
-uint32_t tsrl;
-uint32_t odr;
-uint32_t ir;
-uint32_t rr1;
-uint32_t isr1h;
-uint32_t isr1l;
-};
-
 static uint64_t ppc405_gpio_read(void *opaque, hwaddr addr, unsigned size)
 {
 trace_ppc405_gpio_read(addr, size);
@@ -748,20 +731,23 @@ static const MemoryRegionOps ppc405_gpio_ops = {
 .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void ppc405_gpio_reset (void *opaque)
+static void ppc405_gpio_realize(DeviceState *dev, Error **errp)
 {
+Ppc405GpioState *s = PPC405_GPIO(dev);
+SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+memory_region_init_io(>io, OBJECT(s), _gpio_ops, s, "gpio",
+  0x038);
+sysbus_init_mmio(sbd, >io);
 }
 
-static void ppc405_gpio_init(hwaddr base)
+static void ppc405_gpio_class_init(ObjectClass *oc, void *data)
 {
-ppc405_gpio_t *gpio;
-
-trace_ppc405_gpio_init(base);
+DeviceClass *dc = DEVICE_CLASS(oc);
 
-gpio = g_new0(ppc405_gpio_t, 1);
-memory_region_init_io(>io, NULL, _gpio_ops, gpio, "pgio", 
0x038);
-memory_region_add_subregion(get_system_memory(), base, >io);
-qemu_register_reset(_gpio_reset, gpio);
+dc->realize = ppc405_gpio_realize;
+/* Reason: only works as function of a ppc4xx SoC */
+dc->user_creatable = false;
 }
 
 /*/
@@ -1408,6 +1394,8 @@ static void ppc405_soc_instance_init(Object *obj)
 object_initialize_child(obj, "gpt", >gpt, TYPE_PPC405_GPT);
 
 object_initialize_child(obj, "ocm", >ocm, TYPE_PPC405_OCM);
+
+object_initialize_child(obj, "gpio", >gpio, TYPE_PPC405_GPIO);
 }
 
 static void ppc405_reset(void *opaque)
@@ -1485,8 +1473,12 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 /* I2C controller */
 sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500,
  qdev_get_gpio_in(s->uic, 2));
+
 /* GPIO */
-ppc405_gpio_init(0xef600700);
+if (!sysbus_realize(SYS_BUS_DEVICE(>gpio), errp)) {
+return;
+}
+sysbus_mmio_map(SYS_BUS_DEVICE(>gpio), 0, 0xef600700);
 
 /* Serial ports */
 if (serial_hd(0) != NULL) {
@@ -1549,6 +1541,11 @@ static void ppc405_soc_class_init(ObjectClass *oc, void 
*data)
 
 static const TypeInfo ppc405_types[] = {
 {
+.name   = TYPE_PPC405_GPIO,
+.parent = TYPE_SYS_BUS_DEVICE,
+.instance_size  = sizeof(Ppc405GpioState),
+.class_init = ppc405_gpio_class_init,
+}, {
 .name   = TYPE_PPC405_OCM,
 .parent = TYPE_PPC4xx_DCR_DEVICE,
 .instance_size  = sizeof(Ppc405OcmState),
diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
index adb45008883a..66fbf0e03525 100644
--- a/hw/ppc/trace-events
+++ b/hw/ppc/trace-events
@@ -154,7 +154,6 @@ opba_init(uint64_t addr) "offet 0x%" PRIx64
 
 ppc405_gpio_read(uint64_t addr, uint32_t size) "addr 0x%" PRIx64 " size %d"
 ppc405_gpio_write(uint64_t addr, uint32_t size, uint64_t val) "addr 0x%" 
PRIx64 " size %d = 0x%" PRIx64
-ppc405_gpio_init(uint64_t addr) "offet 0x%" PRIx64
 
 ocm_update_mappings(uint32_t isarc, uint32_t isacntl, uint32_t dsarc, uint32_t 
dsacntl, uint32_t 

[PATCH v4 15/24] ppc/ppc405: QOM'ify OPBA

2022-08-09 Thread Cédric Le Goater
The OPB arbitrer is currently modeled as a simple SysBus device with a
unique memory region.

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405.h | 12 
 hw/ppc/ppc405_uc.c  | 48 +++--
 hw/ppc/trace-events |  1 -
 3 files changed, 41 insertions(+), 20 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 82bf8dae931f..d63c2acdc7b5 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -63,6 +63,17 @@ struct ppc4xx_bd_info_t {
 uint32_t bi_iic_fast[2];
 };
 
+/* OPB arbitrer */
+#define TYPE_PPC405_OPBA "ppc405-opba"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc405OpbaState, PPC405_OPBA);
+struct Ppc405OpbaState {
+SysBusDevice parent_obj;
+
+MemoryRegion io;
+uint8_t cr;
+uint8_t pr;
+};
+
 /* Peripheral controller */
 #define TYPE_PPC405_EBC "ppc405-ebc"
 OBJECT_DECLARE_SIMPLE_TYPE(Ppc405EbcState, PPC405_EBC);
@@ -208,6 +219,7 @@ struct Ppc405SoCState {
 Ppc405GpioState gpio;
 Ppc405DmaState dma;
 Ppc405EbcState ebc;
+Ppc405OpbaState opba;
 };
 
 /* PowerPC 405 core */
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 3722387d6ac8..447a654a349a 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -310,16 +310,10 @@ static void ppc4xx_pob_init(CPUPPCState *env)
 
 /*/
 /* OPB arbitrer */
-typedef struct ppc4xx_opba_t ppc4xx_opba_t;
-struct ppc4xx_opba_t {
-MemoryRegion io;
-uint8_t cr;
-uint8_t pr;
-};
 
 static uint64_t opba_readb(void *opaque, hwaddr addr, unsigned size)
 {
-ppc4xx_opba_t *opba = opaque;
+Ppc405OpbaState *opba = PPC405_OPBA(opaque);
 uint32_t ret;
 
 switch (addr) {
@@ -341,7 +335,7 @@ static uint64_t opba_readb(void *opaque, hwaddr addr, 
unsigned size)
 static void opba_writeb(void *opaque, hwaddr addr, uint64_t value,
 unsigned size)
 {
-ppc4xx_opba_t *opba = opaque;
+Ppc405OpbaState *opba = PPC405_OPBA(opaque);
 
 trace_opba_writeb(addr, value);
 
@@ -366,25 +360,31 @@ static const MemoryRegionOps opba_ops = {
 .endianness = DEVICE_BIG_ENDIAN,
 };
 
-static void ppc4xx_opba_reset (void *opaque)
+static void ppc405_opba_reset(DeviceState *dev)
 {
-ppc4xx_opba_t *opba;
+Ppc405OpbaState *opba = PPC405_OPBA(dev);
 
-opba = opaque;
 opba->cr = 0x00; /* No dynamic priorities - park disabled */
 opba->pr = 0x11;
 }
 
-static void ppc4xx_opba_init(hwaddr base)
+static void ppc405_opba_realize(DeviceState *dev, Error **errp)
 {
-ppc4xx_opba_t *opba;
+Ppc405OpbaState *s = PPC405_OPBA(dev);
+SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 
-trace_opba_init(base);
+memory_region_init_io(>io, OBJECT(s), _ops, s, "opba", 0x002);
+sysbus_init_mmio(sbd, >io);
+}
+
+static void ppc405_opba_class_init(ObjectClass *oc, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(oc);
 
-opba = g_new0(ppc4xx_opba_t, 1);
-memory_region_init_io(>io, NULL, _ops, opba, "opba", 0x002);
-memory_region_add_subregion(get_system_memory(), base, >io);
-qemu_register_reset(ppc4xx_opba_reset, opba);
+dc->realize = ppc405_opba_realize;
+dc->reset = ppc405_opba_reset;
+/* Reason: only works as function of a ppc4xx SoC */
+dc->user_creatable = false;
 }
 
 /*/
@@ -1366,6 +1366,8 @@ static void ppc405_soc_instance_init(Object *obj)
 object_initialize_child(obj, "dma", >dma, TYPE_PPC405_DMA);
 
 object_initialize_child(obj, "ebc", >ebc, TYPE_PPC405_EBC);
+
+object_initialize_child(obj, "opba", >opba, TYPE_PPC405_OPBA);
 }
 
 static void ppc405_reset(void *opaque)
@@ -1402,7 +1404,10 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 ppc4xx_pob_init(env);
 
 /* OBP arbitrer */
-ppc4xx_opba_init(0xef600600);
+if (!sysbus_realize(SYS_BUS_DEVICE(>opba), errp)) {
+return;
+}
+sysbus_mmio_map(SYS_BUS_DEVICE(>opba), 0, 0xef600600);
 
 /* Universal interrupt controller */
 s->uic = qdev_new(TYPE_PPC_UIC);
@@ -1516,6 +1521,11 @@ static void ppc405_soc_class_init(ObjectClass *oc, void 
*data)
 
 static const TypeInfo ppc405_types[] = {
 {
+.name   = TYPE_PPC405_OPBA,
+.parent = TYPE_SYS_BUS_DEVICE,
+.instance_size  = sizeof(Ppc405OpbaState),
+.class_init = ppc405_opba_class_init,
+}, {
 .name   = TYPE_PPC405_EBC,
 .parent = TYPE_PPC4xx_DCR_DEVICE,
 .instance_size  = sizeof(Ppc405EbcState),
diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
index 66fbf0e03525..38b62e93484f 100644
--- a/hw/ppc/trace-events
+++ b/hw/ppc/trace-events
@@ -150,7 +150,6 @@ ppc440_pcix_reg_write(uint64_t addr, uint32_t val, uint32_t 
size) "addr 0x%" PRI
 # ppc405_boards.c
 opba_readb(uint64_t addr, uint32_t val) "addr 0x%" PRIx64 " = 0x%" PRIx32
 

[PATCH v4 08/24] ppc/ppc4xx: Introduce a DCR device model

2022-08-09 Thread Cédric Le Goater
The Device Control Registers (DCR) of on-SoC devices are accessed by
software through the use of the mtdcr and mfdcr instructions. These
are converted in transactions on a side band bus, the DCR bus, which
connects the on-SoC devices to the CPU.

Ideally, we should model these accesses with a DCR namespace and DCR
memory regions but today the DCR handlers are installed in a DCR table
under the CPU. Instead introduce a little device model wrapper to hold
a CPU link and handle registration of DCR handlers.

The DCR device inherits from SysBus because most of these devices also
have MMIO regions and/or IRQs. Being a SysBusDevice makes things easier
to install the device model in the overall SoC.

The "cpu" link should be considered as modeling the piece of HW logic
connecting the device to the DCR bus.

Signed-off-by: Cédric Le Goater 
---
 include/hw/ppc/ppc4xx.h | 17 
 hw/ppc/ppc4xx_devs.c| 44 +
 2 files changed, 61 insertions(+)

diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
index 591e2421a343..82e60b0e0742 100644
--- a/include/hw/ppc/ppc4xx.h
+++ b/include/hw/ppc/ppc4xx.h
@@ -27,6 +27,7 @@
 
 #include "hw/ppc/ppc.h"
 #include "exec/memory.h"
+#include "hw/sysbus.h"
 
 void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
 MemoryRegion ram_memories[],
@@ -44,4 +45,20 @@ void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, 
uint8_t rxcnum,
 
 #define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost"
 
+/*
+ * Generic DCR device
+ */
+#define TYPE_PPC4xx_DCR_DEVICE "ppc4xx-dcr-device"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxDcrDeviceState, PPC4xx_DCR_DEVICE);
+struct Ppc4xxDcrDeviceState {
+SysBusDevice parent_obj;
+
+PowerPCCPU *cpu;
+};
+
+void ppc4xx_dcr_register(Ppc4xxDcrDeviceState *dev, int dcrn,
+ dcr_read_cb dcr_read, dcr_write_cb dcr_write);
+bool ppc4xx_dcr_realize(Ppc4xxDcrDeviceState *dev, PowerPCCPU *cpu,
+Error **errp);
+
 #endif /* PPC4XX_H */
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 069b51195160..bce7ef461346 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -664,3 +664,47 @@ void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, 
uint8_t rxcnum,
  mal, _read_mal, _write_mal);
 }
 }
+
+void ppc4xx_dcr_register(Ppc4xxDcrDeviceState *dev, int dcrn,
+ dcr_read_cb dcr_read, dcr_write_cb dcr_write)
+{
+CPUPPCState *env;
+
+assert(dev->cpu);
+
+env = >cpu->env;
+
+ppc_dcr_register(env, dcrn, dev, dcr_read, dcr_write);
+}
+
+bool ppc4xx_dcr_realize(Ppc4xxDcrDeviceState *dev, PowerPCCPU *cpu,
+Error **errp)
+{
+object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), _abort);
+return sysbus_realize(SYS_BUS_DEVICE(dev), errp);
+}
+
+static Property ppc4xx_dcr_properties[] = {
+DEFINE_PROP_LINK("cpu", Ppc4xxDcrDeviceState, cpu, TYPE_POWERPC_CPU,
+ PowerPCCPU *),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ppc4xx_dcr_class_init(ObjectClass *oc, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(oc);
+
+device_class_set_props(dc, ppc4xx_dcr_properties);
+}
+
+static const TypeInfo ppc4xx_types[] = {
+{
+.name   = TYPE_PPC4xx_DCR_DEVICE,
+.parent = TYPE_SYS_BUS_DEVICE,
+.instance_size  = sizeof(Ppc4xxDcrDeviceState),
+.class_init = ppc4xx_dcr_class_init,
+.abstract   = true,
+}
+};
+
+DEFINE_TYPES(ppc4xx_types)
-- 
2.37.1




[PATCH v4 10/24] ppc/ppc405: QOM'ify GPT

2022-08-09 Thread Cédric Le Goater
The GPT controller is currently modeled as a SysBus device with a
unique memory region, a couple of IRQs and a timer.

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405.h | 22 +++
 hw/ppc/ppc405_uc.c  | 91 +++--
 hw/ppc/trace-events |  1 -
 3 files changed, 68 insertions(+), 46 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 2ba829988de2..bcf55e4f6b2e 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -63,6 +63,27 @@ struct ppc4xx_bd_info_t {
 uint32_t bi_iic_fast[2];
 };
 
+/* General purpose timers */
+#define TYPE_PPC405_GPT "ppc405-gpt"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc405GptState, PPC405_GPT);
+struct Ppc405GptState {
+SysBusDevice parent_obj;
+
+MemoryRegion iomem;
+
+int64_t tb_offset;
+uint32_t tb_freq;
+QEMUTimer *timer;
+qemu_irq irqs[5];
+uint32_t oe;
+uint32_t ol;
+uint32_t im;
+uint32_t is;
+uint32_t ie;
+uint32_t comp[5];
+uint32_t mask[5];
+};
+
 #define TYPE_PPC405_CPC "ppc405-cpc"
 OBJECT_DECLARE_SIMPLE_TYPE(Ppc405CpcState, PPC405_CPC);
 
@@ -114,6 +135,7 @@ struct Ppc405SoCState {
 PowerPCCPU cpu;
 DeviceState *uic;
 Ppc405CpcState cpc;
+Ppc405GptState gpt;
 };
 
 /* PowerPC 405 core */
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 1f4337ff2fbd..c4d137073862 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -926,34 +926,18 @@ static void ppc405_ocm_init(CPUPPCState *env)
 
 /*/
 /* General purpose timers */
-typedef struct ppc4xx_gpt_t ppc4xx_gpt_t;
-struct ppc4xx_gpt_t {
-MemoryRegion iomem;
-int64_t tb_offset;
-uint32_t tb_freq;
-QEMUTimer *timer;
-qemu_irq irqs[5];
-uint32_t oe;
-uint32_t ol;
-uint32_t im;
-uint32_t is;
-uint32_t ie;
-uint32_t comp[5];
-uint32_t mask[5];
-};
-
-static int ppc4xx_gpt_compare (ppc4xx_gpt_t *gpt, int n)
+static int ppc4xx_gpt_compare(Ppc405GptState *gpt, int n)
 {
 /* XXX: TODO */
 return 0;
 }
 
-static void ppc4xx_gpt_set_output (ppc4xx_gpt_t *gpt, int n, int level)
+static void ppc4xx_gpt_set_output(Ppc405GptState *gpt, int n, int level)
 {
 /* XXX: TODO */
 }
 
-static void ppc4xx_gpt_set_outputs (ppc4xx_gpt_t *gpt)
+static void ppc4xx_gpt_set_outputs(Ppc405GptState *gpt)
 {
 uint32_t mask;
 int i;
@@ -974,7 +958,7 @@ static void ppc4xx_gpt_set_outputs (ppc4xx_gpt_t *gpt)
 }
 }
 
-static void ppc4xx_gpt_set_irqs (ppc4xx_gpt_t *gpt)
+static void ppc4xx_gpt_set_irqs(Ppc405GptState *gpt)
 {
 uint32_t mask;
 int i;
@@ -989,14 +973,14 @@ static void ppc4xx_gpt_set_irqs (ppc4xx_gpt_t *gpt)
 }
 }
 
-static void ppc4xx_gpt_compute_timer (ppc4xx_gpt_t *gpt)
+static void ppc4xx_gpt_compute_timer(Ppc405GptState *gpt)
 {
 /* XXX: TODO */
 }
 
 static uint64_t ppc4xx_gpt_read(void *opaque, hwaddr addr, unsigned size)
 {
-ppc4xx_gpt_t *gpt = opaque;
+Ppc405GptState *gpt = PPC405_GPT(opaque);
 uint32_t ret;
 int idx;
 
@@ -1050,7 +1034,7 @@ static uint64_t ppc4xx_gpt_read(void *opaque, hwaddr 
addr, unsigned size)
 static void ppc4xx_gpt_write(void *opaque, hwaddr addr, uint64_t value,
  unsigned size)
 {
-ppc4xx_gpt_t *gpt = opaque;
+Ppc405GptState *gpt = PPC405_GPT(opaque);
 int idx;
 
 trace_ppc4xx_gpt_write(addr, size, value);
@@ -1116,20 +1100,18 @@ static const MemoryRegionOps gpt_ops = {
 
 static void ppc4xx_gpt_cb (void *opaque)
 {
-ppc4xx_gpt_t *gpt;
+Ppc405GptState *gpt = PPC405_GPT(opaque);
 
-gpt = opaque;
 ppc4xx_gpt_set_irqs(gpt);
 ppc4xx_gpt_set_outputs(gpt);
 ppc4xx_gpt_compute_timer(gpt);
 }
 
-static void ppc4xx_gpt_reset (void *opaque)
+static void ppc405_gpt_reset(DeviceState *dev)
 {
-ppc4xx_gpt_t *gpt;
+Ppc405GptState *gpt = PPC405_GPT(dev);
 int i;
 
-gpt = opaque;
 timer_del(gpt->timer);
 gpt->oe = 0x;
 gpt->ol = 0x;
@@ -1142,21 +1124,29 @@ static void ppc4xx_gpt_reset (void *opaque)
 }
 }
 
-static void ppc4xx_gpt_init(hwaddr base, qemu_irq irqs[5])
+static void ppc405_gpt_realize(DeviceState *dev, Error **errp)
 {
-ppc4xx_gpt_t *gpt;
+Ppc405GptState *s = PPC405_GPT(dev);
+SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 int i;
 
-trace_ppc4xx_gpt_init(base);
+s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, _gpt_cb, s);
+memory_region_init_io(>iomem, OBJECT(s), _ops, s, "gpt", 0x0d4);
+sysbus_init_mmio(sbd, >iomem);
 
-gpt = g_new0(ppc4xx_gpt_t, 1);
-for (i = 0; i < 5; i++) {
-gpt->irqs[i] = irqs[i];
+for (i = 0; i < ARRAY_SIZE(s->irqs); i++) {
+sysbus_init_irq(sbd, >irqs[i]);
 }
-gpt->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, _gpt_cb, gpt);
-memory_region_init_io(>iomem, NULL, _ops, gpt, "gpt", 0x0d4);
-memory_region_add_subregion(get_system_memory(), base, >iomem);
-

[PATCH v4 07/24] ppc/ppc405: QOM'ify CPU

2022-08-09 Thread Cédric Le Goater
Drop the use of ppc4xx_init() and duplicate a bit of code related to
clocks in the SoC realize routine. We will clean that up in the
following patches.

ppc_dcr_init() simply allocates default DCR handlers for the CPU. Maybe
this could be done in model initializer of the CPU families needing it.

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405.h |  2 +-
 include/hw/ppc/ppc4xx.h |  5 -
 hw/ppc/ppc405_boards.c  |  2 +-
 hw/ppc/ppc405_uc.c  | 40 ++--
 hw/ppc/ppc4xx_devs.c| 32 
 5 files changed, 32 insertions(+), 49 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index dc862bc8614c..8cc76cc8b3fe 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -79,7 +79,7 @@ struct Ppc405SoCState {
 hwaddr ram_size;
 
 uint32_t sysclk;
-PowerPCCPU *cpu;
+PowerPCCPU cpu;
 DeviceState *uic;
 };
 
diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
index 980f964b5a91..591e2421a343 100644
--- a/include/hw/ppc/ppc4xx.h
+++ b/include/hw/ppc/ppc4xx.h
@@ -28,11 +28,6 @@
 #include "hw/ppc/ppc.h"
 #include "exec/memory.h"
 
-/* PowerPC 4xx core initialization */
-PowerPCCPU *ppc4xx_init(const char *cpu_model,
-clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
-uint32_t sysclk);
-
 void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
 MemoryRegion ram_memories[],
 hwaddr ram_bases[], hwaddr ram_sizes[],
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index b93e85b5d9bd..3677793adc75 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -313,7 +313,7 @@ static void ppc405_init(MachineState *machine)
 
 /* Load ELF kernel and rootfs.cpio */
 } else if (kernel_filename && !machine->firmware) {
-boot_from_kernel(machine, ppc405->soc.cpu);
+boot_from_kernel(machine, >soc.cpu);
 }
 }
 
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index c05ab604367d..14a525b2eb74 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1432,22 +1432,41 @@ static void ppc405ep_cpc_init (CPUPPCState *env, 
clk_setup_t clk_setup[8],
 #endif
 }
 
+static void ppc405_soc_instance_init(Object *obj)
+{
+Ppc405SoCState *s = PPC405_SOC(obj);
+
+object_initialize_child(obj, "cpu", >cpu,
+POWERPC_CPU_TYPE_NAME("405ep"));
+}
+
+static void ppc405_reset(void *opaque)
+{
+cpu_reset(CPU(opaque));
+}
+
 static void ppc405_soc_realize(DeviceState *dev, Error **errp)
 {
 Ppc405SoCState *s = PPC405_SOC(dev);
-clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup;
+clk_setup_t clk_setup[PPC405EP_CLK_NB];
 qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4];
 CPUPPCState *env;
 
 memset(clk_setup, 0, sizeof(clk_setup));
 
 /* init CPUs */
-s->cpu = ppc4xx_init(POWERPC_CPU_TYPE_NAME("405ep"),
-  _setup[PPC405EP_CPU_CLK],
-  _clk_setup, s->sysclk);
-env = >cpu->env;
-clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb;
-clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque;
+if (!qdev_realize(DEVICE(>cpu), NULL, errp)) {
+return;
+}
+qemu_register_reset(ppc405_reset, >cpu);
+
+env = >cpu.env;
+
+clk_setup[PPC405EP_CPU_CLK].cb =
+ppc_40x_timers_init(env, s->sysclk, PPC_INTERRUPT_PIT);
+clk_setup[PPC405EP_CPU_CLK].opaque = env;
+
+ppc_dcr_init(env, NULL, NULL);
 
 /* CPU control */
 ppc405ep_cpc_init(env, clk_setup, s->sysclk);
@@ -1464,16 +1483,16 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 /* Universal interrupt controller */
 s->uic = qdev_new(TYPE_PPC_UIC);
 
-object_property_set_link(OBJECT(s->uic), "cpu", OBJECT(s->cpu),
+object_property_set_link(OBJECT(s->uic), "cpu", OBJECT(>cpu),
  _fatal);
 if (!sysbus_realize(SYS_BUS_DEVICE(s->uic), errp)) {
 return;
 }
 
 sysbus_connect_irq(SYS_BUS_DEVICE(s->uic), PPCUIC_OUTPUT_INT,
-   qdev_get_gpio_in(DEVICE(s->cpu), PPC40x_INPUT_INT));
+   qdev_get_gpio_in(DEVICE(>cpu), PPC40x_INPUT_INT));
 sysbus_connect_irq(SYS_BUS_DEVICE(s->uic), PPCUIC_OUTPUT_CINT,
-   qdev_get_gpio_in(DEVICE(s->cpu), PPC40x_INPUT_CINT));
+   qdev_get_gpio_in(DEVICE(>cpu), PPC40x_INPUT_CINT));
 
 /* SDRAM controller */
 /* XXX 405EP has no ECC interrupt */
@@ -1563,6 +1582,7 @@ static const TypeInfo ppc405_types[] = {
 .name   = TYPE_PPC405_SOC,
 .parent = TYPE_DEVICE,
 .instance_size  = sizeof(Ppc405SoCState),
+.instance_init  = ppc405_soc_instance_init,
 .class_init = ppc405_soc_class_init,
 }
 };
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 737c0896b4f8..069b51195160 100644
--- a/hw/ppc/ppc4xx_devs.c

[PATCH v4 06/24] ppc/ppc405: Start QOMification of the SoC

2022-08-09 Thread Cédric Le Goater
This moves all the code previously done in the ppc405ep_init() routine
under ppc405_soc_realize(). We can also adjust the number of banks now
that we have control on ppc4xx_sdram_init().

Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405.h|  12 ++--
 hw/ppc/ppc405_boards.c |  12 ++--
 hw/ppc/ppc405_uc.c | 124 -
 3 files changed, 71 insertions(+), 77 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 66dc21cdfed8..dc862bc8614c 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -73,9 +73,14 @@ struct Ppc405SoCState {
 /* Public */
 MemoryRegion ram_banks[2];
 hwaddr ram_bases[2], ram_sizes[2];
+bool do_dram_init;
 
 MemoryRegion *dram_mr;
 hwaddr ram_size;
+
+uint32_t sysclk;
+PowerPCCPU *cpu;
+DeviceState *uic;
 };
 
 /* PowerPC 405 core */
@@ -84,11 +89,4 @@ ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t 
ram_size);
 void ppc4xx_plb_init(CPUPPCState *env);
 void ppc405_ebc_init(CPUPPCState *env);
 
-PowerPCCPU *ppc405ep_init(MemoryRegion *address_space_mem,
-MemoryRegion ram_memories[2],
-hwaddr ram_bases[2],
-hwaddr ram_sizes[2],
-uint32_t sysclk, DeviceState **uicdev,
-int do_init);
-
 #endif /* PPC405_H */
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index f029d6f415f6..b93e85b5d9bd 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -237,9 +237,7 @@ static void ppc405_init(MachineState *machine)
 Ppc405MachineState *ppc405 = PPC405_MACHINE(machine);
 MachineClass *mc = MACHINE_GET_CLASS(machine);
 const char *kernel_filename = machine->kernel_filename;
-PowerPCCPU *cpu;
 MemoryRegion *sysmem = get_system_memory();
-DeviceState *uicdev;
 
 if (machine->ram_size != mc->default_ram_size) {
 char *sz = size_to_str(mc->default_ram_size);
@@ -254,12 +252,12 @@ static void ppc405_init(MachineState *machine)
  machine->ram_size, _fatal);
 object_property_set_link(OBJECT(>soc), "dram",
  OBJECT(machine->ram), _abort);
+object_property_set_bool(OBJECT(>soc), "dram-init",
+ kernel_filename != NULL, _abort);
+object_property_set_uint(OBJECT(>soc), "sys-clk", ,
+ _abort);
 qdev_realize(DEVICE(>soc), NULL, _fatal);
 
-cpu = ppc405ep_init(sysmem, ppc405->soc.ram_banks, ppc405->soc.ram_bases,
-ppc405->soc.ram_sizes,
-, , kernel_filename == NULL ? 0 : 1);
-
 /* allocate and load BIOS */
 if (machine->firmware) {
 MemoryRegion *bios = g_new(MemoryRegion, 1);
@@ -315,7 +313,7 @@ static void ppc405_init(MachineState *machine)
 
 /* Load ELF kernel and rootfs.cpio */
 } else if (kernel_filename && !machine->firmware) {
-boot_from_kernel(machine, cpu);
+boot_from_kernel(machine, ppc405->soc.cpu);
 }
 }
 
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index adadb3a0ae08..c05ab604367d 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1432,121 +1432,118 @@ static void ppc405ep_cpc_init (CPUPPCState *env, 
clk_setup_t clk_setup[8],
 #endif
 }
 
-PowerPCCPU *ppc405ep_init(MemoryRegion *address_space_mem,
-MemoryRegion ram_memories[2],
-hwaddr ram_bases[2],
-hwaddr ram_sizes[2],
-uint32_t sysclk, DeviceState **uicdevp,
-int do_init)
+static void ppc405_soc_realize(DeviceState *dev, Error **errp)
 {
+Ppc405SoCState *s = PPC405_SOC(dev);
 clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup;
 qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4];
-PowerPCCPU *cpu;
 CPUPPCState *env;
-DeviceState *uicdev;
-SysBusDevice *uicsbd;
 
 memset(clk_setup, 0, sizeof(clk_setup));
+
 /* init CPUs */
-cpu = ppc4xx_init(POWERPC_CPU_TYPE_NAME("405ep"),
+s->cpu = ppc4xx_init(POWERPC_CPU_TYPE_NAME("405ep"),
   _setup[PPC405EP_CPU_CLK],
-  _clk_setup, sysclk);
-env = >env;
+  _clk_setup, s->sysclk);
+env = >cpu->env;
 clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb;
 clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque;
-/* Internal devices init */
-/* Memory mapped devices registers */
+
+/* CPU control */
+ppc405ep_cpc_init(env, clk_setup, s->sysclk);
+
 /* PLB arbitrer */
 ppc4xx_plb_init(env);
+
 /* PLB to OPB bridge */
 ppc4xx_pob_init(env);
+
 /* OBP arbitrer */
 ppc4xx_opba_init(0xef600600);
+
 /* Universal interrupt controller */
-uicdev = qdev_new(TYPE_PPC_UIC);
-uicsbd = SYS_BUS_DEVICE(uicdev);
+s->uic = qdev_new(TYPE_PPC_UIC);
 
-object_property_set_link(OBJECT(uicdev), "cpu", 

[PATCH v4 02/24] ppc/ppc405: Introduce a PPC405 generic machine

2022-08-09 Thread Cédric Le Goater
We will use this machine as a base to define the ref405ep and possibly
the PPC405 hotfoot board as found in the Linux kernel.

Reviewed-by: BALATON Zoltan 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405_boards.c | 31 ---
 1 file changed, 28 insertions(+), 3 deletions(-)

diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 1a4e7588c584..96700be74d08 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -50,6 +50,15 @@
 
 #define USE_FLASH_BIOS
 
+#define TYPE_PPC405_MACHINE MACHINE_TYPE_NAME("ppc405")
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc405MachineState, PPC405_MACHINE);
+
+struct Ppc405MachineState {
+/* Private */
+MachineState parent_obj;
+/* Public */
+};
+
 /*/
 /* PPC405EP reference board (IBM) */
 /* Standalone board with:
@@ -332,18 +341,34 @@ static void ref405ep_class_init(ObjectClass *oc, void 
*data)
 
 mc->desc = "ref405ep";
 mc->init = ref405ep_init;
-mc->default_ram_size = 0x0800;
-mc->default_ram_id = "ef405ep.ram";
 }
 
 static const TypeInfo ref405ep_type = {
 .name = MACHINE_TYPE_NAME("ref405ep"),
-.parent = TYPE_MACHINE,
+.parent = TYPE_PPC405_MACHINE,
 .class_init = ref405ep_class_init,
 };
 
+static void ppc405_machine_class_init(ObjectClass *oc, void *data)
+{
+MachineClass *mc = MACHINE_CLASS(oc);
+
+mc->desc = "PPC405 generic machine";
+mc->default_ram_size = 128 * MiB;
+mc->default_ram_id = "ppc405.ram";
+}
+
+static const TypeInfo ppc405_machine_type = {
+.name = TYPE_PPC405_MACHINE,
+.parent = TYPE_MACHINE,
+.instance_size = sizeof(Ppc405MachineState),
+.class_init = ppc405_machine_class_init,
+.abstract = true,
+};
+
 static void ppc405_machine_init(void)
 {
+type_register_static(_machine_type);
 type_register_static(_type);
 }
 
-- 
2.37.1




[PATCH v4 20/24] ppc/ppc405: Use an embedded PPCUIC model in SoC state

2022-08-09 Thread Cédric Le Goater
Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405.h|  3 ++-
 hw/ppc/ppc405_uc.c | 26 +-
 2 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 31c94e474209..8e67ad0b72c3 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -27,6 +27,7 @@
 
 #include "qom/object.h"
 #include "hw/ppc/ppc4xx.h"
+#include "hw/intc/ppc-uic.h"
 
 #define PPC405EP_SDRAM_BASE 0x
 #define PPC405EP_NVRAM_BASE 0xF000
@@ -234,7 +235,7 @@ struct Ppc405SoCState {
 hwaddr ram_size;
 
 PowerPCCPU cpu;
-DeviceState *uic;
+PPCUIC uic;
 Ppc405CpcState cpc;
 Ppc405GptState gpt;
 Ppc405OcmState ocm;
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 290cfa352bed..328224bb0620 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1350,6 +1350,8 @@ static void ppc405_soc_instance_init(Object *obj)
 object_initialize_child(obj, "cpu", >cpu,
 POWERPC_CPU_TYPE_NAME("405ep"));
 
+object_initialize_child(obj, "uic", >uic, TYPE_PPC_UIC);
+
 object_initialize_child(obj, "cpc", >cpc, TYPE_PPC405_CPC);
 object_property_add_alias(obj, "sys-clk", OBJECT(>cpc), "sys-clk");
 
@@ -1415,17 +1417,15 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 sysbus_mmio_map(SYS_BUS_DEVICE(>opba), 0, 0xef600600);
 
 /* Universal interrupt controller */
-s->uic = qdev_new(TYPE_PPC_UIC);
-
-object_property_set_link(OBJECT(s->uic), "cpu", OBJECT(>cpu),
+object_property_set_link(OBJECT(>uic), "cpu", OBJECT(>cpu),
  _fatal);
-if (!sysbus_realize(SYS_BUS_DEVICE(s->uic), errp)) {
+if (!sysbus_realize(SYS_BUS_DEVICE(>uic), errp)) {
 return;
 }
 
-sysbus_connect_irq(SYS_BUS_DEVICE(s->uic), PPCUIC_OUTPUT_INT,
+sysbus_connect_irq(SYS_BUS_DEVICE(>uic), PPCUIC_OUTPUT_INT,
qdev_get_gpio_in(DEVICE(>cpu), PPC40x_INPUT_INT));
-sysbus_connect_irq(SYS_BUS_DEVICE(s->uic), PPCUIC_OUTPUT_CINT,
+sysbus_connect_irq(SYS_BUS_DEVICE(>uic), PPCUIC_OUTPUT_CINT,
qdev_get_gpio_in(DEVICE(>cpu), PPC40x_INPUT_CINT));
 
 /* SDRAM controller */
@@ -1436,7 +1436,7 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
  "ppc405.sdram0", s->dram_mr,
  s->ram_bases[0], s->ram_sizes[0]);
 
-ppc4xx_sdram_init(env, qdev_get_gpio_in(s->uic, 17), 1,
+ppc4xx_sdram_init(env, qdev_get_gpio_in(DEVICE(>uic), 17), 1,
   s->ram_banks, s->ram_bases, s->ram_sizes,
   s->do_dram_init);
 
@@ -1452,12 +1452,12 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 
 for (i = 0; i < ARRAY_SIZE(s->dma.irqs); i++) {
 sysbus_connect_irq(SYS_BUS_DEVICE(>dma), i,
-   qdev_get_gpio_in(s->uic, 5 + i));
+   qdev_get_gpio_in(DEVICE(>uic), 5 + i));
 }
 
 /* I2C controller */
 sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500,
- qdev_get_gpio_in(s->uic, 2));
+ qdev_get_gpio_in(DEVICE(>uic), 2));
 
 /* GPIO */
 if (!sysbus_realize(SYS_BUS_DEVICE(>gpio), errp)) {
@@ -1468,13 +1468,13 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 /* Serial ports */
 if (serial_hd(0) != NULL) {
 serial_mm_init(get_system_memory(), 0xef600300, 0,
-   qdev_get_gpio_in(s->uic, 0),
+   qdev_get_gpio_in(DEVICE(>uic), 0),
PPC_SERIAL_MM_BAUDBASE, serial_hd(0),
DEVICE_BIG_ENDIAN);
 }
 if (serial_hd(1) != NULL) {
 serial_mm_init(get_system_memory(), 0xef600400, 0,
-   qdev_get_gpio_in(s->uic, 1),
+   qdev_get_gpio_in(DEVICE(>uic), 1),
PPC_SERIAL_MM_BAUDBASE, serial_hd(1),
DEVICE_BIG_ENDIAN);
 }
@@ -1492,7 +1492,7 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 
 for (i = 0; i < ARRAY_SIZE(s->gpt.irqs); i++) {
 sysbus_connect_irq(SYS_BUS_DEVICE(>gpt), i,
-   qdev_get_gpio_in(s->uic, 19 + i));
+   qdev_get_gpio_in(DEVICE(>uic), 19 + i));
 }
 
 /* MAL */
@@ -1504,7 +1504,7 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 
 for (i = 0; i < ARRAY_SIZE(s->mal.irqs); i++) {
 sysbus_connect_irq(SYS_BUS_DEVICE(>mal), i,
-   qdev_get_gpio_in(s->uic, 11 + i));
+   qdev_get_gpio_in(DEVICE(>uic), 11 + i));
 }
 
 /* Ethernet */
-- 
2.37.1




[PATCH v4 03/24] ppc/ppc405: Move devices under the ref405ep machine

2022-08-09 Thread Cédric Le Goater
Reviewed-by: Daniel Henrique Barboza 
Reviewed-by: BALATON Zoltan 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405_boards.c | 31 +++
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 96700be74d08..f4794ba40ce6 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -230,13 +230,11 @@ static void boot_from_kernel(MachineState *machine, 
PowerPCCPU *cpu)
 env->load_info = _info;
 }
 
-static void ref405ep_init(MachineState *machine)
+static void ppc405_init(MachineState *machine)
 {
 MachineClass *mc = MACHINE_GET_CLASS(machine);
 const char *kernel_filename = machine->kernel_filename;
 PowerPCCPU *cpu;
-DeviceState *dev;
-SysBusDevice *s;
 MemoryRegion *sram = g_new(MemoryRegion, 1);
 MemoryRegion *ram_memories = g_new(MemoryRegion, 2);
 hwaddr ram_bases[2], ram_sizes[2];
@@ -294,15 +292,6 @@ static void ref405ep_init(MachineState *machine)
 memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios);
 }
 
-/* Register FPGA */
-ref405ep_fpga_init(sysmem, PPC405EP_FPGA_BASE);
-/* Register NVRAM */
-dev = qdev_new("sysbus-m48t08");
-qdev_prop_set_int32(dev, "base-year", 1968);
-s = SYS_BUS_DEVICE(dev);
-sysbus_realize_and_unref(s, _fatal);
-sysbus_mmio_map(s, 0, PPC405EP_NVRAM_BASE);
-
 /* Load kernel and initrd using U-Boot images */
 if (kernel_filename && machine->firmware) {
 target_ulong kernel_base, initrd_base;
@@ -335,6 +324,23 @@ static void ref405ep_init(MachineState *machine)
 }
 }
 
+static void ref405ep_init(MachineState *machine)
+{
+DeviceState *dev;
+SysBusDevice *s;
+
+ppc405_init(machine);
+
+/* Register FPGA */
+ref405ep_fpga_init(get_system_memory(), PPC405EP_FPGA_BASE);
+/* Register NVRAM */
+dev = qdev_new("sysbus-m48t08");
+qdev_prop_set_int32(dev, "base-year", 1968);
+s = SYS_BUS_DEVICE(dev);
+sysbus_realize_and_unref(s, _fatal);
+sysbus_mmio_map(s, 0, PPC405EP_NVRAM_BASE);
+}
+
 static void ref405ep_class_init(ObjectClass *oc, void *data)
 {
 MachineClass *mc = MACHINE_CLASS(oc);
@@ -354,6 +360,7 @@ static void ppc405_machine_class_init(ObjectClass *oc, void 
*data)
 MachineClass *mc = MACHINE_CLASS(oc);
 
 mc->desc = "PPC405 generic machine";
+mc->init = ppc405_init;
 mc->default_ram_size = 128 * MiB;
 mc->default_ram_id = "ppc405.ram";
 }
-- 
2.37.1




[PATCH v4 00/24] ppc: QOM'ify 405 board

2022-08-09 Thread Cédric Le Goater
Hello,

Here is large series QOM'ifying the PPC405 board. It introduces a new
generic machine and SoC models, converts the current device models to
QOM and populates the SoC. The process is quite mechanical without too
much issues to handle. The noisy part is the initial patch introducing
the SoC realize routine.

Thanks,

C.

Changes in v4 :

 - Attempt to QOM'ify SDRAM controller, with 2 initialized banks at
   the SoC level 
 - Report errors to the user for invalid RAM config
 - Moved CPU reset in PPC405 model
 - user_creatable comments
 - Renamed FPGA device model
 - Various small cleanups

Changes in v3 :

 - New device model Ppc4xxDcrDeviceState
 - Removal of ppc4xx_mal_init(), ppc4xx_plb_init() and ppc405_ebc_init()
 - Fixes for some reset issues
 - Kept 2 RAM banks at the Soc level but only one is initialized.
 - Moved SRAM under the machine. It's not part of the SoC according
   to the 405 specs

Changes in v2 :

 - docs/about/removed-features.rst update
 - Fix compile breakage (uic)
 - Fix CPU reset, which breaking u-boot boot
 - Changed prefix of memory regions to "ppc405"
 - Reduced the number of RAM banks to 1. Second was a dummy one to
   please ppc405ep_init()

Cédric Le Goater (24):
  ppc/ppc405: Remove taihu machine
  ppc/ppc405: Introduce a PPC405 generic machine
  ppc/ppc405: Move devices under the ref405ep machine
  ppc/ppc405: Move SRAM under the ref405ep machine
  ppc/ppc405: Introduce a PPC405 SoC
  ppc/ppc405: Start QOMification of the SoC
  ppc/ppc405: QOM'ify CPU
  ppc/ppc4xx: Introduce a DCR device model
  ppc/ppc405: QOM'ify CPC
  ppc/ppc405: QOM'ify GPT
  ppc/ppc405: QOM'ify OCM
  ppc/ppc405: QOM'ify GPIO
  ppc/ppc405: QOM'ify DMA
  ppc/ppc405: QOM'ify EBC
  ppc/ppc405: QOM'ify OPBA
  ppc/ppc405: QOM'ify POB
  ppc/ppc405: QOM'ify PLB
  ppc/ppc405: QOM'ify MAL
  ppc/ppc405: QOM'ify FPGA
  ppc/ppc405: Use an embedded PPCUIC model in SoC state
  ppc/ppc405: Use an explicit I2C object
  ppc/ppc4xx: Fix sdram trace events
  ppc/ppc405: QOM'ify SDRAM
  ppc/ppc405: Add check on minimum RAM size

 docs/about/deprecated.rst   |   9 -
 docs/about/removed-features.rst |   6 +
 docs/system/ppc/embedded.rst|   1 -
 hw/ppc/ppc405.h | 196 +++-
 include/hw/ppc/ppc4xx.h |  82 ++-
 hw/ppc/ppc405_boards.c  | 381 --
 hw/ppc/ppc405_uc.c  | 859 +---
 hw/ppc/ppc4xx_devs.c| 326 +++-
 hw/ppc/sam460ex.c   |  24 +-
 MAINTAINERS |   2 +-
 hw/ppc/trace-events |   3 -
 11 files changed, 1042 insertions(+), 847 deletions(-)

-- 
2.37.1




[PATCH v4 01/24] ppc/ppc405: Remove taihu machine

2022-08-09 Thread Cédric Le Goater
It has been deprecated since 7.0.

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
 docs/about/deprecated.rst   |   9 --
 docs/about/removed-features.rst |   6 +
 docs/system/ppc/embedded.rst|   1 -
 hw/ppc/ppc405_boards.c  | 232 
 MAINTAINERS |   2 +-
 5 files changed, 7 insertions(+), 243 deletions(-)

diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index 7ee26626d5cf..2f9b41aaea48 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -233,15 +233,6 @@ deprecated; use the new name ``dtb-randomness`` instead. 
The new name
 better reflects the way this property affects all random data within
 the device tree blob, not just the ``kaslr-seed`` node.
 
-PPC 405 ``taihu`` machine (since 7.0)
-'
-
-The PPC 405 CPU is a system-on-a-chip, so all 405 machines are very similar,
-except for some external periphery. However, the periphery of the ``taihu``
-machine is hardly emulated at all (e.g. neither the LCD nor the USB part had
-been implemented), so there is not much value added by this board. Use the
-``ref405ep`` machine instead.
-
 ``pc-i440fx-1.4`` up to ``pc-i440fx-1.7`` (since 7.0)
 '
 
diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst
index 925e22016f98..a4aa3dca6987 100644
--- a/docs/about/removed-features.rst
+++ b/docs/about/removed-features.rst
@@ -668,6 +668,12 @@ Aspeed ``swift-bmc`` machine (removed in 7.0)
 This machine was removed because it was unused. Alternative AST2500 based
 OpenPOWER machines are ``witherspoon-bmc`` and ``romulus-bmc``.
 
+ppc ``taihu`` machine (removed in 7.2)
+'
+
+This machine was removed because it was partially emulated and 405
+machines are very similar. Use the ``ref405ep`` machine instead.
+
 linux-user mode CPUs
 
 
diff --git a/docs/system/ppc/embedded.rst b/docs/system/ppc/embedded.rst
index cfffbda24da9..af3b3d9fa460 100644
--- a/docs/system/ppc/embedded.rst
+++ b/docs/system/ppc/embedded.rst
@@ -6,5 +6,4 @@ Embedded family boards
 - ``ppce500``  generic paravirt e500 platform
 - ``ref405ep`` ref405ep
 - ``sam460ex`` aCube Sam460ex
-- ``taihu``taihu
 - ``virtex-ml507`` Xilinx Virtex ML507 reference design
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index a66ad05e3ac3..1a4e7588c584 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -342,241 +342,9 @@ static const TypeInfo ref405ep_type = {
 .class_init = ref405ep_class_init,
 };
 
-/*/
-/* AMCC Taihu evaluation board */
-/* - PowerPC 405EP processor
- * - SDRAM   128 MB at 0x
- * - Boot flash  2 MB   at 0xFFE0
- * - Application flash   32 MB  at 0xFC00
- * - 2 serial ports
- * - 2 ethernet PHY
- * - 1 USB 1.1 device0x5000
- * - 1 LCD display   0x5010
- * - 1 CPLD  0x5010
- * - 1 I2C EEPROM
- * - 1 I2C thermal sensor
- * - a set of LEDs
- * - bit-bang SPI port using GPIOs
- * - 1 EBC interface connector 0 0x5020
- * - 1 cardbus controller + expansion slot.
- * - 1 PCI expansion slot.
- */
-typedef struct taihu_cpld_t taihu_cpld_t;
-struct taihu_cpld_t {
-uint8_t reg0;
-uint8_t reg1;
-};
-
-static uint64_t taihu_cpld_read(void *opaque, hwaddr addr, unsigned size)
-{
-taihu_cpld_t *cpld;
-uint32_t ret;
-
-cpld = opaque;
-switch (addr) {
-case 0x0:
-ret = cpld->reg0;
-break;
-case 0x1:
-ret = cpld->reg1;
-break;
-default:
-ret = 0;
-break;
-}
-
-return ret;
-}
-
-static void taihu_cpld_write(void *opaque, hwaddr addr,
- uint64_t value, unsigned size)
-{
-taihu_cpld_t *cpld;
-
-cpld = opaque;
-switch (addr) {
-case 0x0:
-/* Read only */
-break;
-case 0x1:
-cpld->reg1 = value;
-break;
-default:
-break;
-}
-}
-
-static const MemoryRegionOps taihu_cpld_ops = {
-.read = taihu_cpld_read,
-.write = taihu_cpld_write,
-.impl = {
-.min_access_size = 1,
-.max_access_size = 1,
-},
-.endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void taihu_cpld_reset (void *opaque)
-{
-taihu_cpld_t *cpld;
-
-cpld = opaque;
-cpld->reg0 = 0x01;
-cpld->reg1 = 0x80;
-}
-
-static void taihu_cpld_init(MemoryRegion *sysmem, uint32_t base)
-{
-taihu_cpld_t *cpld;
-MemoryRegion *cpld_memory = g_new(MemoryRegion, 1);
-
-cpld = g_new0(taihu_cpld_t, 1);
-memory_region_init_io(cpld_memory, NULL, _cpld_ops, cpld, "cpld", 
0x100);
-memory_region_add_subregion(sysmem, base, cpld_memory);
-qemu_register_reset(_cpld_reset, cpld);
-}
-
-static void 

[PATCH v4 09/24] ppc/ppc405: QOM'ify CPC

2022-08-09 Thread Cédric Le Goater
The CPC controller is currently modeled as a DCR device.

Now that all clock settings are handled at the CPC level, change the
SoC "sys-clk" property to be an alias on the same property in the CPC
model.

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405.h|  35 -
 hw/ppc/ppc405_uc.c | 123 +++--
 2 files changed, 87 insertions(+), 71 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 8cc76cc8b3fe..2ba829988de2 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -63,6 +63,39 @@ struct ppc4xx_bd_info_t {
 uint32_t bi_iic_fast[2];
 };
 
+#define TYPE_PPC405_CPC "ppc405-cpc"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc405CpcState, PPC405_CPC);
+
+enum {
+PPC405EP_CPU_CLK   = 0,
+PPC405EP_PLB_CLK   = 1,
+PPC405EP_OPB_CLK   = 2,
+PPC405EP_EBC_CLK   = 3,
+PPC405EP_MAL_CLK   = 4,
+PPC405EP_PCI_CLK   = 5,
+PPC405EP_UART0_CLK = 6,
+PPC405EP_UART1_CLK = 7,
+PPC405EP_CLK_NB= 8,
+};
+
+struct Ppc405CpcState {
+Ppc4xxDcrDeviceState parent_obj;
+
+uint32_t sysclk;
+clk_setup_t clk_setup[PPC405EP_CLK_NB];
+uint32_t boot;
+uint32_t epctl;
+uint32_t pllmr[2];
+uint32_t ucr;
+uint32_t srr;
+uint32_t jtagid;
+uint32_t pci;
+/* Clock and power management */
+uint32_t er;
+uint32_t fr;
+uint32_t sr;
+};
+
 #define TYPE_PPC405_SOC "ppc405-soc"
 OBJECT_DECLARE_SIMPLE_TYPE(Ppc405SoCState, PPC405_SOC);
 
@@ -78,9 +111,9 @@ struct Ppc405SoCState {
 MemoryRegion *dram_mr;
 hwaddr ram_size;
 
-uint32_t sysclk;
 PowerPCCPU cpu;
 DeviceState *uic;
+Ppc405CpcState cpc;
 };
 
 /* PowerPC 405 core */
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 14a525b2eb74..1f4337ff2fbd 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1178,36 +1178,7 @@ enum {
 #endif
 };
 
-enum {
-PPC405EP_CPU_CLK   = 0,
-PPC405EP_PLB_CLK   = 1,
-PPC405EP_OPB_CLK   = 2,
-PPC405EP_EBC_CLK   = 3,
-PPC405EP_MAL_CLK   = 4,
-PPC405EP_PCI_CLK   = 5,
-PPC405EP_UART0_CLK = 6,
-PPC405EP_UART1_CLK = 7,
-PPC405EP_CLK_NB= 8,
-};
-
-typedef struct ppc405ep_cpc_t ppc405ep_cpc_t;
-struct ppc405ep_cpc_t {
-uint32_t sysclk;
-clk_setup_t clk_setup[PPC405EP_CLK_NB];
-uint32_t boot;
-uint32_t epctl;
-uint32_t pllmr[2];
-uint32_t ucr;
-uint32_t srr;
-uint32_t jtagid;
-uint32_t pci;
-/* Clock and power management */
-uint32_t er;
-uint32_t fr;
-uint32_t sr;
-};
-
-static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc)
+static void ppc405ep_compute_clocks(Ppc405CpcState *cpc)
 {
 uint32_t CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk;
 uint32_t UART0_clk, UART1_clk;
@@ -1302,10 +1273,9 @@ static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc)
 
 static uint32_t dcr_read_epcpc (void *opaque, int dcrn)
 {
-ppc405ep_cpc_t *cpc;
+Ppc405CpcState *cpc = PPC405_CPC(opaque);
 uint32_t ret;
 
-cpc = opaque;
 switch (dcrn) {
 case PPC405EP_CPC0_BOOT:
 ret = cpc->boot;
@@ -1342,9 +1312,8 @@ static uint32_t dcr_read_epcpc (void *opaque, int dcrn)
 
 static void dcr_write_epcpc (void *opaque, int dcrn, uint32_t val)
 {
-ppc405ep_cpc_t *cpc;
+Ppc405CpcState *cpc = PPC405_CPC(opaque);
 
-cpc = opaque;
 switch (dcrn) {
 case PPC405EP_CPC0_BOOT:
 /* Read-only register */
@@ -1377,9 +1346,9 @@ static void dcr_write_epcpc (void *opaque, int dcrn, 
uint32_t val)
 }
 }
 
-static void ppc405ep_cpc_reset (void *opaque)
+static void ppc405_cpc_reset(DeviceState *opaque)
 {
-ppc405ep_cpc_t *cpc = opaque;
+Ppc405CpcState *cpc = PPC405_CPC(opaque);
 
 cpc->boot = 0x0010; /* Boot from PCI - IIC EEPROM disabled */
 cpc->epctl = 0x;
@@ -1391,45 +1360,57 @@ static void ppc405ep_cpc_reset (void *opaque)
 cpc->er = 0x;
 cpc->fr = 0x;
 cpc->sr = 0x;
+cpc->jtagid = 0x20267049;
 ppc405ep_compute_clocks(cpc);
 }
 
 /* XXX: sysclk should be between 25 and 100 MHz */
-static void ppc405ep_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[8],
-   uint32_t sysclk)
+static void ppc405_cpc_realize(DeviceState *dev, Error **errp)
 {
-ppc405ep_cpc_t *cpc;
+Ppc405CpcState *cpc = PPC405_CPC(dev);
+Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
+CPUPPCState *env;
 
-cpc = g_new0(ppc405ep_cpc_t, 1);
-memcpy(cpc->clk_setup, clk_setup,
-   PPC405EP_CLK_NB * sizeof(clk_setup_t));
-cpc->jtagid = 0x20267049;
-cpc->sysclk = sysclk;
-qemu_register_reset(_cpc_reset, cpc);
-ppc_dcr_register(env, PPC405EP_CPC0_BOOT, cpc,
- _read_epcpc, _write_epcpc);
-ppc_dcr_register(env, PPC405EP_CPC0_EPCTL, cpc,
- _read_epcpc, _write_epcpc);
-ppc_dcr_register(env, PPC405EP_CPC0_PLLMR0, cpc,
- _read_epcpc, _write_epcpc);
-   

[PATCH v4 04/24] ppc/ppc405: Move SRAM under the ref405ep machine

2022-08-09 Thread Cédric Le Goater
It doesn't belong to the generic machine nor the SoC. Fix a typo in
the name while we are at it.

Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405_boards.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index f4794ba40ce6..381f39aa94cb 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -235,7 +235,6 @@ static void ppc405_init(MachineState *machine)
 MachineClass *mc = MACHINE_GET_CLASS(machine);
 const char *kernel_filename = machine->kernel_filename;
 PowerPCCPU *cpu;
-MemoryRegion *sram = g_new(MemoryRegion, 1);
 MemoryRegion *ram_memories = g_new(MemoryRegion, 2);
 hwaddr ram_bases[2], ram_sizes[2];
 MemoryRegion *sysmem = get_system_memory();
@@ -260,11 +259,6 @@ static void ppc405_init(MachineState *machine)
 cpu = ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
 , , kernel_filename == NULL ? 0 : 1);
 
-/* allocate SRAM */
-memory_region_init_ram(sram, NULL, "ef405ep.sram", PPC405EP_SRAM_SIZE,
-   _fatal);
-memory_region_add_subregion(sysmem, PPC405EP_SRAM_BASE, sram);
-
 /* allocate and load BIOS */
 if (machine->firmware) {
 MemoryRegion *bios = g_new(MemoryRegion, 1);
@@ -328,9 +322,15 @@ static void ref405ep_init(MachineState *machine)
 {
 DeviceState *dev;
 SysBusDevice *s;
+MemoryRegion *sram = g_new(MemoryRegion, 1);
 
 ppc405_init(machine);
 
+/* allocate SRAM */
+memory_region_init_ram(sram, NULL, "ref405ep.sram", PPC405EP_SRAM_SIZE,
+   _fatal);
+memory_region_add_subregion(get_system_memory(), PPC405EP_SRAM_BASE, sram);
+
 /* Register FPGA */
 ref405ep_fpga_init(get_system_memory(), PPC405EP_FPGA_BASE);
 /* Register NVRAM */
-- 
2.37.1




[PATCH v4 05/24] ppc/ppc405: Introduce a PPC405 SoC

2022-08-09 Thread Cédric Le Goater
It is an initial model to start QOMification of the PPC405 board.
QOM'ified devices will be reintroduced one by one. Start with the
memory regions, which name prefix is changed to "ppc405".

Also, initialize only one RAM bank. The second bank is a dummy one
(zero size) which is here to match the hard coded number of banks in
ppc405ep_init().

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc405.h| 16 
 hw/ppc/ppc405_boards.c | 23 ---
 hw/ppc/ppc405_uc.c | 40 
 3 files changed, 68 insertions(+), 11 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 83f156f585c8..66dc21cdfed8 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -25,6 +25,7 @@
 #ifndef PPC405_H
 #define PPC405_H
 
+#include "qom/object.h"
 #include "hw/ppc/ppc4xx.h"
 
 #define PPC405EP_SDRAM_BASE 0x
@@ -62,6 +63,21 @@ struct ppc4xx_bd_info_t {
 uint32_t bi_iic_fast[2];
 };
 
+#define TYPE_PPC405_SOC "ppc405-soc"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc405SoCState, PPC405_SOC);
+
+struct Ppc405SoCState {
+/* Private */
+DeviceState parent_obj;
+
+/* Public */
+MemoryRegion ram_banks[2];
+hwaddr ram_bases[2], ram_sizes[2];
+
+MemoryRegion *dram_mr;
+hwaddr ram_size;
+};
+
 /* PowerPC 405 core */
 ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size);
 
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 381f39aa94cb..f029d6f415f6 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -57,6 +57,8 @@ struct Ppc405MachineState {
 /* Private */
 MachineState parent_obj;
 /* Public */
+
+Ppc405SoCState soc;
 };
 
 /*/
@@ -232,11 +234,10 @@ static void boot_from_kernel(MachineState *machine, 
PowerPCCPU *cpu)
 
 static void ppc405_init(MachineState *machine)
 {
+Ppc405MachineState *ppc405 = PPC405_MACHINE(machine);
 MachineClass *mc = MACHINE_GET_CLASS(machine);
 const char *kernel_filename = machine->kernel_filename;
 PowerPCCPU *cpu;
-MemoryRegion *ram_memories = g_new(MemoryRegion, 2);
-hwaddr ram_bases[2], ram_sizes[2];
 MemoryRegion *sysmem = get_system_memory();
 DeviceState *uicdev;
 
@@ -247,16 +248,16 @@ static void ppc405_init(MachineState *machine)
 exit(EXIT_FAILURE);
 }
 
-/* XXX: fix this */
-memory_region_init_alias(_memories[0], NULL, "ef405ep.ram.alias",
- machine->ram, 0, machine->ram_size);
-ram_bases[0] = 0;
-ram_sizes[0] = machine->ram_size;
-memory_region_init(_memories[1], NULL, "ef405ep.ram1", 0);
-ram_bases[1] = 0x;
-ram_sizes[1] = 0x;
+object_initialize_child(OBJECT(machine), "soc", >soc,
+TYPE_PPC405_SOC);
+object_property_set_uint(OBJECT(>soc), "ram-size",
+ machine->ram_size, _fatal);
+object_property_set_link(OBJECT(>soc), "dram",
+ OBJECT(machine->ram), _abort);
+qdev_realize(DEVICE(>soc), NULL, _fatal);
 
-cpu = ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
+cpu = ppc405ep_init(sysmem, ppc405->soc.ram_banks, ppc405->soc.ram_bases,
+ppc405->soc.ram_sizes,
 , , kernel_filename == NULL ? 0 : 1);
 
 /* allocate and load BIOS */
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index d6420c88d3a6..adadb3a0ae08 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -30,6 +30,7 @@
 #include "hw/ppc/ppc.h"
 #include "hw/i2c/ppc4xx_i2c.h"
 #include "hw/irq.h"
+#include "hw/qdev-properties.h"
 #include "ppc405.h"
 #include "hw/char/serial.h"
 #include "qemu/timer.h"
@@ -1530,3 +1531,42 @@ PowerPCCPU *ppc405ep_init(MemoryRegion 
*address_space_mem,
 
 return cpu;
 }
+
+static void ppc405_soc_realize(DeviceState *dev, Error **errp)
+{
+Ppc405SoCState *s = PPC405_SOC(dev);
+
+/* Initialize only one bank */
+s->ram_bases[0] = 0;
+s->ram_sizes[0] = s->ram_size;
+memory_region_init_alias(>ram_banks[0], OBJECT(s),
+ "ppc405.sdram0", s->dram_mr,
+ s->ram_bases[0], s->ram_sizes[0]);
+}
+
+static Property ppc405_soc_properties[] = {
+DEFINE_PROP_LINK("dram", Ppc405SoCState, dram_mr, TYPE_MEMORY_REGION,
+ MemoryRegion *),
+DEFINE_PROP_UINT64("ram-size", Ppc405SoCState, ram_size, 0),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ppc405_soc_class_init(ObjectClass *oc, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(oc);
+
+dc->realize = ppc405_soc_realize;
+dc->user_creatable = false;
+device_class_set_props(dc, ppc405_soc_properties);
+}
+
+static const TypeInfo ppc405_types[] = {
+{
+.name   = TYPE_PPC405_SOC,
+.parent = TYPE_DEVICE,
+.instance_size  = 

  1   2   >