Re: [PATCH] hw/qdev-core: Add compatibility for (non)-transitional devs

2021-10-19 Thread Jean-Louis Dupond

On 19/10/2021 17:27, Eduardo Habkost wrote:

On Tue, Oct 12, 2021 at 10:24:28AM +0200, Jean-Louis Dupond wrote:

hw_compat modes only take into account their base name.

What do you mean by "base name"?

virtio-net-pci (without the (non-)transitional extension.

But if a device is created with (non)-transitional, then the compat
values are not used, causing migrating issues.

This commit adds their (non)-transitional entries with the same settings
as the base entry.


Wouldn't it be easier to fix the incorrect compat_props arrays to
use "virtio-*-pci-base" instead?

If a piece of code is supposed to affect/support both
non-transitional and transitional subclasses, that's why
VirtioPCIDeviceTypeInfo.base_name exists.


Thats easier indeed :)

Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1999141

Signed-off-by: Jean-Louis Dupond 
---
  include/hw/qdev-core.h | 34 ++
  1 file changed, 34 insertions(+)

diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 4ff19c714b..5726825c2d 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -293,6 +293,30 @@ typedef struct GlobalProperty {
  bool optional;
  } GlobalProperty;
  
+

+/**
+ * Helper to add (non)transitional compat properties
+ */
+static inline void
+compat_props_add_transitional(GPtrArray *arr, GlobalProperty *prop)
+{
+GlobalProperty *transitional = g_new0(typeof(*transitional), 1);
+transitional->driver = g_strdup_printf("%s-transitional", prop->driver);
+transitional->property = g_strdup(prop->property);
+transitional->value = g_strdup(prop->value);
+transitional->used = prop->used;
+transitional->optional = prop->optional;
+g_ptr_array_add(arr, (void *)transitional);
+
+GlobalProperty *non_transitional = g_new0(typeof(*non_transitional), 1);
+non_transitional->driver = g_strdup_printf("%s-non-transitional", 
prop->driver);
+non_transitional->property = g_strdup(prop->property);
+non_transitional->value = g_strdup(prop->value);
+non_transitional->used = prop->used;
+non_transitional->optional = prop->optional;
+g_ptr_array_add(arr, (void *)non_transitional);
+}
+
  static inline void
  compat_props_add(GPtrArray *arr,
   GlobalProperty props[], size_t nelem)
@@ -300,6 +324,16 @@ compat_props_add(GPtrArray *arr,
  int i;
  for (i = 0; i < nelem; i++) {
  g_ptr_array_add(arr, (void *)&props[i]);
+if (g_str_equal(props[i].driver, "vhost-user-blk-pci") ||
+g_str_equal(props[i].driver, "virtio-scsi-pci") ||
+g_str_equal(props[i].driver, "virtio-blk-pci") ||
+g_str_equal(props[i].driver, "virtio-balloon-pci") ||
+g_str_equal(props[i].driver, "virtio-serial-pci") ||
+g_str_equal(props[i].driver, "virtio-9p-pci") ||
+g_str_equal(props[i].driver, "virtio-net-pci") ||
+g_str_equal(props[i].driver, "virtio-rng-pci")) {
+compat_props_add_transitional(arr, &props[i]);
+}
  }
  }
  
--

2.33.0






Re: [RFC PATCH v4 20/20] vdpa: Add custom IOTLB translations to SVQ

2021-10-19 Thread Eugenio Perez Martin
On Wed, Oct 20, 2021 at 4:07 AM Jason Wang  wrote:
>
> On Wed, Oct 20, 2021 at 10:02 AM Jason Wang  wrote:
> >
> > On Tue, Oct 19, 2021 at 6:29 PM Eugenio Perez Martin
> >  wrote:
> > >
> > > On Tue, Oct 19, 2021 at 11:25 AM Jason Wang  wrote:
> > > >
> > > >
> > > > 在 2021/10/1 下午3:06, Eugenio Pérez 写道:
> > > > > Use translations added in VhostIOVATree in SVQ.
> > > > >
> > > > > Now every element needs to store the previous address also, so 
> > > > > VirtQueue
> > > > > can consume the elements properly. This adds a little overhead per VQ
> > > > > element, having to allocate more memory to stash them. As a possible
> > > > > optimization, this allocation could be avoided if the descriptor is 
> > > > > not
> > > > > a chain but a single one, but this is left undone.
> > > > >
> > > > > TODO: iova range should be queried before, and add logic to fail when
> > > > > GPA is outside of its range and memory listener or svq add it.
> > > > >
> > > > > Signed-off-by: Eugenio Pérez 
> > > > > ---
> > > > >   hw/virtio/vhost-shadow-virtqueue.h |   4 +-
> > > > >   hw/virtio/vhost-shadow-virtqueue.c | 130 
> > > > > -
> > > > >   hw/virtio/vhost-vdpa.c |  40 -
> > > > >   hw/virtio/trace-events |   1 +
> > > > >   4 files changed, 152 insertions(+), 23 deletions(-)
> > > > >
> > > > > diff --git a/hw/virtio/vhost-shadow-virtqueue.h 
> > > > > b/hw/virtio/vhost-shadow-virtqueue.h
> > > > > index b7baa424a7..a0e6b5267a 100644
> > > > > --- a/hw/virtio/vhost-shadow-virtqueue.h
> > > > > +++ b/hw/virtio/vhost-shadow-virtqueue.h
> > > > > @@ -11,6 +11,7 @@
> > > > >   #define VHOST_SHADOW_VIRTQUEUE_H
> > > > >
> > > > >   #include "hw/virtio/vhost.h"
> > > > > +#include "hw/virtio/vhost-iova-tree.h"
> > > > >
> > > > >   typedef struct VhostShadowVirtqueue VhostShadowVirtqueue;
> > > > >
> > > > > @@ -28,7 +29,8 @@ bool vhost_svq_start(struct vhost_dev *dev, 
> > > > > unsigned idx,
> > > > >   void vhost_svq_stop(struct vhost_dev *dev, unsigned idx,
> > > > >   VhostShadowVirtqueue *svq);
> > > > >
> > > > > -VhostShadowVirtqueue *vhost_svq_new(struct vhost_dev *dev, int idx);
> > > > > +VhostShadowVirtqueue *vhost_svq_new(struct vhost_dev *dev, int idx,
> > > > > +VhostIOVATree *iova_map);
> > > > >
> > > > >   void vhost_svq_free(VhostShadowVirtqueue *vq);
> > > > >
> > > > > diff --git a/hw/virtio/vhost-shadow-virtqueue.c 
> > > > > b/hw/virtio/vhost-shadow-virtqueue.c
> > > > > index 2fd0bab75d..9db538547e 100644
> > > > > --- a/hw/virtio/vhost-shadow-virtqueue.c
> > > > > +++ b/hw/virtio/vhost-shadow-virtqueue.c
> > > > > @@ -11,12 +11,19 @@
> > > > >   #include "hw/virtio/vhost-shadow-virtqueue.h"
> > > > >   #include "hw/virtio/vhost.h"
> > > > >   #include "hw/virtio/virtio-access.h"
> > > > > +#include "hw/virtio/vhost-iova-tree.h"
> > > > >
> > > > >   #include "standard-headers/linux/vhost_types.h"
> > > > >
> > > > >   #include "qemu/error-report.h"
> > > > >   #include "qemu/main-loop.h"
> > > > >
> > > > > +typedef struct SVQElement {
> > > > > +VirtQueueElement elem;
> > > > > +void **in_sg_stash;
> > > > > +void **out_sg_stash;
> > > > > +} SVQElement;
> > > > > +
> > > > >   /* Shadow virtqueue to relay notifications */
> > > > >   typedef struct VhostShadowVirtqueue {
> > > > >   /* Shadow vring */
> > > > > @@ -46,8 +53,11 @@ typedef struct VhostShadowVirtqueue {
> > > > >   /* Virtio device */
> > > > >   VirtIODevice *vdev;
> > > > >
> > > > > +/* IOVA mapping if used */
> > > > > +VhostIOVATree *iova_map;
> > > > > +
> > > > >   /* Map for returning guest's descriptors */
> > > > > -VirtQueueElement **ring_id_maps;
> > > > > +SVQElement **ring_id_maps;
> > > > >
> > > > >   /* Next head to expose to device */
> > > > >   uint16_t avail_idx_shadow;
> > > > > @@ -79,13 +89,6 @@ bool vhost_svq_valid_device_features(uint64_t 
> > > > > *dev_features)
> > > > >   continue;
> > > > >
> > > > >   case VIRTIO_F_ACCESS_PLATFORM:
> > > > > -/* SVQ needs this feature disabled. Can't continue */
> > > > > -if (*dev_features & BIT_ULL(b)) {
> > > > > -clear_bit(b, dev_features);
> > > > > -r = false;
> > > > > -}
> > > > > -break;
> > > > > -
> > > > >   case VIRTIO_F_VERSION_1:
> > > > >   /* SVQ needs this feature, so can't continue */
> > > > >   if (!(*dev_features & BIT_ULL(b))) {
> > > > > @@ -126,6 +129,64 @@ static void 
> > > > > vhost_svq_set_notification(VhostShadowVirtqueue *svq, bool enable)
> > > > >   }
> > > > >   }
> > > > >
> > > > > +static void vhost_svq_stash_addr(void ***stash, const struct iovec 
> > > > > *iov,
> > > > > + size_t num)
> > > > > +{
> > > > > +size_t i;
> > > > > +
> > > > > +if (num == 0) {
> > > > > +return;
> > > > > +  

Re: [RFC PATCH v4 11/20] vhost: Route host->guest notification through shadow virtqueue

2021-10-19 Thread Eugenio Perez Martin
On Wed, Oct 20, 2021 at 4:01 AM Jason Wang  wrote:
>
> On Tue, Oct 19, 2021 at 4:40 PM Eugenio Perez Martin
>  wrote:
> >
> > On Fri, Oct 15, 2021 at 6:42 AM Jason Wang  wrote:
> > >
> > >
> > > 在 2021/10/15 上午12:39, Eugenio Perez Martin 写道:
> > > > On Wed, Oct 13, 2021 at 5:47 AM Jason Wang  wrote:
> > > >>
> > > >> 在 2021/10/1 下午3:05, Eugenio Pérez 写道:
> > > >>> This will make qemu aware of the device used buffers, allowing it to
> > > >>> write the guest memory with its contents if needed.
> > > >>>
> > > >>> Since the use of vhost_virtqueue_start can unmasks and discard call
> > > >>> events, vhost_virtqueue_start should be modified in one of these ways:
> > > >>> * Split in two: One of them uses all logic to start a queue with no
> > > >>> side effects for the guest, and another one tha actually assumes 
> > > >>> that
> > > >>> the guest has just started the device. Vdpa should use just the
> > > >>> former.
> > > >>> * Actually store and check if the guest notifier is masked, and do it
> > > >>> conditionally.
> > > >>> * Left as it is, and duplicate all the logic in vhost-vdpa.
> > > >>>
> > > >>> Signed-off-by: Eugenio Pérez 
> > > >>> ---
> > > >>>hw/virtio/vhost-shadow-virtqueue.c | 19 +++
> > > >>>hw/virtio/vhost-vdpa.c | 38 
> > > >>> +-
> > > >>>2 files changed, 56 insertions(+), 1 deletion(-)
> > > >>>
> > > >>> diff --git a/hw/virtio/vhost-shadow-virtqueue.c 
> > > >>> b/hw/virtio/vhost-shadow-virtqueue.c
> > > >>> index 21dc99ab5d..3fe129cf63 100644
> > > >>> --- a/hw/virtio/vhost-shadow-virtqueue.c
> > > >>> +++ b/hw/virtio/vhost-shadow-virtqueue.c
> > > >>> @@ -53,6 +53,22 @@ static void vhost_handle_guest_kick(EventNotifier 
> > > >>> *n)
> > > >>>event_notifier_set(&svq->kick_notifier);
> > > >>>}
> > > >>>
> > > >>> +/* Forward vhost notifications */
> > > >>> +static void vhost_svq_handle_call_no_test(EventNotifier *n)
> > > >>> +{
> > > >>> +VhostShadowVirtqueue *svq = container_of(n, VhostShadowVirtqueue,
> > > >>> + call_notifier);
> > > >>> +
> > > >>> +event_notifier_set(&svq->guest_call_notifier);
> > > >>> +}
> > > >>> +
> > > >>> +static void vhost_svq_handle_call(EventNotifier *n)
> > > >>> +{
> > > >>> +if (likely(event_notifier_test_and_clear(n))) {
> > > >>> +vhost_svq_handle_call_no_test(n);
> > > >>> +}
> > > >>> +}
> > > >>> +
> > > >>>/*
> > > >>> * Obtain the SVQ call notifier, where vhost device notifies SVQ 
> > > >>> that there
> > > >>> * exists pending used buffers.
> > > >>> @@ -180,6 +196,8 @@ VhostShadowVirtqueue *vhost_svq_new(struct 
> > > >>> vhost_dev *dev, int idx)
> > > >>>}
> > > >>>
> > > >>>svq->vq = virtio_get_queue(dev->vdev, vq_idx);
> > > >>> +event_notifier_set_handler(&svq->call_notifier,
> > > >>> +   vhost_svq_handle_call);
> > > >>>return g_steal_pointer(&svq);
> > > >>>
> > > >>>err_init_call_notifier:
> > > >>> @@ -195,6 +213,7 @@ err_init_kick_notifier:
> > > >>>void vhost_svq_free(VhostShadowVirtqueue *vq)
> > > >>>{
> > > >>>event_notifier_cleanup(&vq->kick_notifier);
> > > >>> +event_notifier_set_handler(&vq->call_notifier, NULL);
> > > >>>event_notifier_cleanup(&vq->call_notifier);
> > > >>>g_free(vq);
> > > >>>}
> > > >>> diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
> > > >>> index bc34de2439..6c5f4c98b8 100644
> > > >>> --- a/hw/virtio/vhost-vdpa.c
> > > >>> +++ b/hw/virtio/vhost-vdpa.c
> > > >>> @@ -712,13 +712,40 @@ static bool vhost_vdpa_svq_start_vq(struct 
> > > >>> vhost_dev *dev, unsigned idx)
> > > >>>{
> > > >>>struct vhost_vdpa *v = dev->opaque;
> > > >>>VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, 
> > > >>> idx);
> > > >>> -return vhost_svq_start(dev, idx, svq);
> > > >>> +EventNotifier *vhost_call_notifier = 
> > > >>> vhost_svq_get_svq_call_notifier(svq);
> > > >>> +struct vhost_vring_file vhost_call_file = {
> > > >>> +.index = idx + dev->vq_index,
> > > >>> +.fd = event_notifier_get_fd(vhost_call_notifier),
> > > >>> +};
> > > >>> +int r;
> > > >>> +bool b;
> > > >>> +
> > > >>> +/* Set shadow vq -> guest notifier */
> > > >>> +assert(v->call_fd[idx]);
> > > >>
> > > >> We need aovid the asser() here. On which case we can hit this?
> > > >>
> > > > I would say that there is no way we can actually hit it, so let's 
> > > > remove it.
> > > >
> > > >>> +vhost_svq_set_guest_call_notifier(svq, v->call_fd[idx]);
> > > >>> +
> > > >>> +b = vhost_svq_start(dev, idx, svq);
> > > >>> +if (unlikely(!b)) {
> > > >>> +return false;
> > > >>> +}
> > > >>> +
> > > >>> +/* Set device -> SVQ notifier */
> > > >>> +r = vhost_vdpa_set_vring_dev_call(dev, &vhost_call_file);
> > > >>> +if (unlikely(r)) {
> > > >>> +error_report(

RE: [PATCH V3] net/colo: check vnet_hdr_support flag when using virtio-net

2021-10-19 Thread Zhang, Chen


> -Original Message-
> From: Jason Wang 
> Sent: Wednesday, October 20, 2021 11:13 AM
> To: Zhang, Chen 
> Cc: Eric Blake ; Markus Armbruster
> ; qemu-dev ; Li Zhijian
> ; Lukas Straub 
> Subject: Re: [PATCH V3] net/colo: check vnet_hdr_support flag when using
> virtio-net
> 
> On Wed, Oct 20, 2021 at 10:53 AM Zhang, Chen 
> wrote:
> >
> >
> >
> > > -Original Message-
> > > From: Jason Wang 
> > > Sent: Tuesday, October 19, 2021 3:39 PM
> > > To: Zhang, Chen ; Eric Blake
> > > ; Markus Armbruster 
> > > Cc: qemu-dev ; Li Zhijian
> > > ; Lukas Straub ; Tao
> > > Xu 
> > > Subject: Re: [PATCH V3] net/colo: check vnet_hdr_support flag when
> > > using virtio-net
> > >
> > >
> > > 在 2021/9/18 上午10:04, Zhang Chen 写道:
> > > > When COLO use only one vnet_hdr_support parameter between COLO
> > > network
> > > > filter(filter-mirror, filter-redirector or filter-rewriter and
> > > > colo-compare, packet will not be parsed correctly. Acquire network
> > > > driver related to COLO, if it is nirtio-net,
> > >
> > >
> > > Typo.
> >
> > Oh~ will fix in next version.
> >
> > >
> > >
> > > >   check vnet_hdr_support flag of COLO network filter and colo-compare.
> > > >
> > > > Signed-off-by: Tao Xu 
> > > > Signed-off-by: Zhang Chen 
> > > > ---
> > > >
> > > > Changelog:
> > > > v3:
> > > >  Fix some typos.
> > > >  Rebased for Qemu 6.2.
> > > >
> > > > v2:
> > > >  Detect virtio-net driver and apply vnet_hdr_support
> > > >  automatically. (Jason)
> > > > ---
> > > >   net/colo-compare.c| 57
> > > +++
> > > >   net/colo.c| 20 +++
> > > >   net/colo.h|  4 +++
> > > >   net/filter-mirror.c   | 21 
> > > >   net/filter-rewriter.c | 10 
> > > >   qapi/qom.json |  6 +
> > > >   qemu-options.hx   |  6 +++--
> > > >   7 files changed, 122 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/net/colo-compare.c b/net/colo-compare.c index
> > > > b100e7b51f..870bd05a41 100644
> > > > --- a/net/colo-compare.c
> > > > +++ b/net/colo-compare.c
> > > > @@ -110,6 +110,7 @@ struct CompareState {
> > > >   char *sec_indev;
> > > >   char *outdev;
> > > >   char *notify_dev;
> > > > +char *netdev;
> > > >   CharBackend chr_pri_in;
> > > >   CharBackend chr_sec_in;
> > > >   CharBackend chr_out;
> > > > @@ -838,6 +839,28 @@ static int compare_chr_can_read(void *opaque)
> > > >   return COMPARE_READ_LEN_MAX;
> > > >   }
> > > >
> > > > +static int colo_set_default_netdev(void *opaque, QemuOpts *opts,
> > > > +Error **errp) {
> > > > +const char *colo_obj_type, *netdev_from_filter;
> > > > +char **netdev = (char **)opaque;
> > > > +
> > > > +colo_obj_type = qemu_opt_get(opts, "qom-type");
> > > > +
> > > > +if (colo_obj_type &&
> > > > +(strcmp(colo_obj_type, "filter-mirror") == 0 ||
> > > > + strcmp(colo_obj_type, "filter-redirector") == 0 ||
> > > > + strcmp(colo_obj_type, "filter-rewriter") == 0)) {
> > > > +netdev_from_filter = qemu_opt_get(opts, "netdev");
> > > > +if (*netdev == NULL) {
> > > > +*netdev = g_strdup(netdev_from_filter);
> > > > +} else if (strcmp(*netdev, netdev_from_filter) != 0) {
> > > > +warn_report("%s is using a different netdev from other 
> > > > COLO "
> > > > +"component", colo_obj_type);
> > > > +}
> > > > +}
> > > > +return 0;
> > > > +}
> > > > +
> > > >   /*
> > > >* Called from the main thread on the primary for packets
> > > >* arriving over the socket from the primary.
> > > > @@ -1050,6 +1073,21 @@ static void compare_set_vnet_hdr(Object
> *obj,
> > > >   s->vnet_hdr = value;
> > > >   }
> > > >
> > > > +static char *compare_get_netdev(Object *obj, Error **errp) {
> > > > +CompareState *s = COLO_COMPARE(obj);
> > > > +
> > > > +return g_strdup(s->netdev);
> > > > +}
> > > > +
> > > > +static void compare_set_netdev(Object *obj, const char *value,
> > > > +Error
> > > > +**errp) {
> > > > +CompareState *s = COLO_COMPARE(obj);
> > > > +
> > > > +g_free(s->netdev);
> > > > +s->netdev = g_strdup(value);
> > > > +}
> > > > +
> > > >   static char *compare_get_notify_dev(Object *obj, Error **errp)
> > > >   {
> > > >   CompareState *s = COLO_COMPARE(obj); @@ -1274,6 +1312,12
> @@
> > > > static void colo_compare_complete(UserCreatable *uc, Error **errp)
> > > >   max_queue_size = MAX_QUEUE_SIZE;
> > > >   }
> > > >
> > > > +if (!s->netdev) {
> > > > +/* Set default netdev as the first colo netfilter found */
> > > > +qemu_opts_foreach(qemu_find_opts("object"),
> > > > +  colo_set_default_netdev, &s->netdev, NULL);
> > > > +}
> > > > +
> > > >   if (find_and_check_chardev(&chr, s->pri_indev, errp) ||
> > > >   !qemu_chr_fe_init(&s->chr_pri_in, chr, errp)) {
> > > >   return;
> > > >

Re: [PATCH v5 2/4] qapi/monitor: refactor set/expire_password with enums

2021-10-19 Thread Markus Armbruster
Stefan Reiter  writes:

> 'protocol' and 'connected' are better suited as enums than as strings,
> make use of that. No functional change intended.
>
> Suggested-by: Markus Armbruster 
> Signed-off-by: Stefan Reiter 
> ---
>  monitor/hmp-cmds.c | 17 +++--
>  monitor/qmp-cmds.c | 35 ++-
>  qapi/ui.json   | 37 +++--
>  3 files changed, 60 insertions(+), 29 deletions(-)
>
> diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
> index bcaa41350e..0ff18ebb3c 100644
> --- a/monitor/hmp-cmds.c
> +++ b/monitor/hmp-cmds.c
> @@ -1453,8 +1453,17 @@ void hmp_set_password(Monitor *mon, const QDict *qdict)
>  const char *password  = qdict_get_str(qdict, "password");
>  const char *connected = qdict_get_try_str(qdict, "connected");
>  Error *err = NULL;
> +DisplayProtocol proto;
> +SetPasswordAction conn;
>  
> -qmp_set_password(protocol, password, !!connected, connected, &err);
> +proto = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
> +DISPLAY_PROTOCOL_VNC, &err);
> +if (!!connected) {
> +conn = qapi_enum_parse(&SetPasswordAction_lookup, connected,
> +   SET_PASSWORD_ACTION_KEEP, &err);
> +}

@conn is left uninitialized when @connected is null.

> +
> +qmp_set_password(proto, password, !!connected, conn, &err);
>  hmp_handle_error(mon, err);

Crash bug when more than one of the three functions fail.  See "Receive
and accumulate multiple errors (first one wins):" in qapi/error.h's big
comment.

You need to do something like

   proto = qapi_enum_parse(...);
   if (err) {
   goto out;
   }
   conn = qapi_enum_parse(...);
   if (err) {
   goto out;
   }
   qmp_set_password(...);

   out:
   hmp_handle_error(mon, err);

No need to guard the second qapi_enum_parse(): a null second argument is
fine, and the function returns its third argument then.

>  }
>  
> @@ -1463,8 +1472,12 @@ void hmp_expire_password(Monitor *mon, const QDict 
> *qdict)
>  const char *protocol  = qdict_get_str(qdict, "protocol");
>  const char *whenstr = qdict_get_str(qdict, "time");
>  Error *err = NULL;
> +DisplayProtocol proto;
>  
> -qmp_expire_password(protocol, whenstr, &err);
> +proto = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
> +DISPLAY_PROTOCOL_VNC, &err);
> +
> +qmp_expire_password(proto, whenstr, &err);
>  hmp_handle_error(mon, err);

Similar crash bug.

>  }
>  
> diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
> index 5c0d5e116b..f1746a31fb 100644
> --- a/monitor/qmp-cmds.c
> +++ b/monitor/qmp-cmds.c
> @@ -163,33 +163,26 @@ void qmp_system_wakeup(Error **errp)
>  qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, errp);
>  }
>  
> -void qmp_set_password(const char *protocol, const char *password,
> -  bool has_connected, const char *connected, Error 
> **errp)
> +void qmp_set_password(DisplayProtocol protocol, const char *password,
> +  bool has_connected, SetPasswordAction connected,
> +  Error **errp)
>  {
>  int disconnect_if_connected = 0;
>  int fail_if_connected = 0;
>  int rc;
>  
>  if (has_connected) {
> -if (strcmp(connected, "fail") == 0) {
> -fail_if_connected = 1;
> -} else if (strcmp(connected, "disconnect") == 0) {
> -disconnect_if_connected = 1;
> -} else if (strcmp(connected, "keep") == 0) {
> -/* nothing */
> -} else {
> -error_setg(errp, QERR_INVALID_PARAMETER, "connected");
> -return;
> -}
> +fail_if_connected = connected == SET_PASSWORD_ACTION_FAIL;
> +disconnect_if_connected = connected == 
> SET_PASSWORD_ACTION_DISCONNECT;
>  }
>  
> -if (strcmp(protocol, "spice") == 0) {
> +if (protocol == DISPLAY_PROTOCOL_SPICE) {
>  if (!qemu_using_spice(errp)) {
>  return;
>  }
>  rc = qemu_spice.set_passwd(password, fail_if_connected,
> disconnect_if_connected);
> -} else if (strcmp(protocol, "vnc") == 0) {
> +} else if (protocol == DISPLAY_PROTOCOL_VNC) {
>  if (fail_if_connected || disconnect_if_connected) {
>  /* vnc supports "connected=keep" only */
>  error_setg(errp, QERR_INVALID_PARAMETER, "connected");
> @@ -198,10 +191,6 @@ void qmp_set_password(const char *protocol, const char 
> *password,
>  /* Note that setting an empty password will not disable login through
>   * this interface. */
>  rc = vnc_display_password(NULL, password);
> -} else {
> -error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "protocol",
> -   "'vnc' or 'spice'");
> -return;
>  }
>  
>  if (rc != 0) {
> @@ -209,7 +198,7 @@ void qmp_set_password(const char *pr

Re: [PATCH v8 00/78] support vector extension v1.0

2021-10-19 Thread Alistair Francis
On Mon, Oct 18, 2021 at 7:37 PM LIU Zhiwei  wrote:
>
> Hi Alistair,
>
> Sorry for the  send error.  And I have a question about this patch set.

Hello Zhiwei,

>
> Firstly, I totally support the vector v1.0 upstream.

Great!

>
> The concern is how to deal with the v0.7.1 code on QEMU. There are some
> products based on the vector v0.7.1,
> such as D1 SOC from Allwinner and  Xuantie CPU  from Alibaba. The Linux
> and GCC upstream for D1 is working in progress,
> and eventually these projects will support v0.7.1 in some way, probably
> as "x-thead-v" (the "thead" stands for Alibaba T-Head).

Yep, so QEMU's stance is to only support the latest version of a draft
specification. Once a specification moves from draft to frozen we will
also only support the frozen spec.

I understand that there is hardware with the v0.7.1 of the vector
extension. But in QEMU we don't have the resources for RISC-V to
maintain multiple sets of draft extensions. Especially the vector
extension, which is very different between v0.7.1 and v1.0 (see the 78
patches in this series).

I realise this is disappointing for companies and people who have
invested in v0.7.1 in QEMU, and I hope it doesn't put anyone off
upstream work. Having the v0.7.1 even for a short period of time has
been helpful for the vector extension development and related
software/tools.

>
> Maybe we can
>
> 1. Drop the v0.7.1 support permanently.
>
> 2. Drop the v0.7.1  temporarily and add  it  back later.

If in the future there is broad community support for v0.7.1 and we
can get some more QEMU resources for RISC-V we can re-evaluate v0.7.1
support. But for the time being it will just be dropped.

There are a few QEMU releases with v0.7.1 support, so you can use
those for development. The v0.7.1 has received a few bug fixes in the
upstream code base which will be beneficial for those using it.

Sorry about that

Alistair

>
> 3. Do some compatible work for v0.7.1 in the v1.0 patch set.
>
> Look forward to your idea. Thanks very much.
>
> Best Regards,
> Zhiwei
>
> On 2021/10/18 下午5:01, LIU Zhiwei wrote:
> > Hi Alistair,
> >
> > There is some products based on the vector v0.7.1, such as D1 SOC from
> > Allwinner and  Xuantie CPU  And we have spent a lot of work to
> > support  vector  on QEMU.
> >
> >
> >
> > Allwinner
> >
> >



Re: [PATCH 12/31] target/loongarch: Add timer related instructions support.

2021-10-19 Thread Richard Henderson

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:

This includes:
-RDTIME{L/H}.W
-RDTIME.D

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
  target/loongarch/helper.h |  2 ++
  target/loongarch/insn_trans/trans_core.c  | 23 +
  target/loongarch/insn_trans/trans_extra.c |  2 ++
  target/loongarch/op_helper.c  | 25 +++
  4 files changed, 52 insertions(+)

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 8544771790..b4ed62896f 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -116,4 +116,6 @@ DEF_HELPER_4(lddir, tl, env, tl, tl, i32)
  DEF_HELPER_4(ldpte, void, env, tl, tl, i32)
  DEF_HELPER_1(ertn, void, env)
  DEF_HELPER_1(idle, void, env)
+DEF_HELPER_4(rdtime_w, void, env, tl, tl, i64)
+DEF_HELPER_3(rdtime_d, void, env, tl, tl)
  #endif /* !CONFIG_USER_ONLY */
diff --git a/target/loongarch/insn_trans/trans_core.c 
b/target/loongarch/insn_trans/trans_core.c
index 7fa13e65b9..24eb12b97a 100644
--- a/target/loongarch/insn_trans/trans_core.c
+++ b/target/loongarch/insn_trans/trans_core.c
@@ -276,4 +276,27 @@ static bool trans_idle(DisasContext *ctx, arg_idle *a)
  return true;
  }
  
+static bool trans_rdtimel_w(DisasContext *ctx, arg_rdtimel_w *a)

+{
+TCGv t0 = tcg_constant_tl(a->rd);
+TCGv t1 = tcg_constant_tl(a->rj);
+gen_helper_rdtime_w(cpu_env, t0, t1, tcg_constant_tl(0));
+return true;
+}


Missing icount boilerplate:

if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
ctx->base.is_jmp = DISAS_TOO_MANY;
}

Something similar is probably required before some of the other instructions that always 
result in i/o.



diff --git a/target/loongarch/insn_trans/trans_extra.c 
b/target/loongarch/insn_trans/trans_extra.c
index 8da3b404f3..426b67f154 100644
--- a/target/loongarch/insn_trans/trans_extra.c
+++ b/target/loongarch/insn_trans/trans_extra.c
@@ -36,6 +36,7 @@ static bool trans_asrtgt_d(DisasContext *ctx, arg_asrtgt_d * 
a)
  return true;
  }
  
+#ifdef CONFIG_USER_ONLY

  static bool trans_rdtimel_w(DisasContext *ctx, arg_rdtimel_w *a)
  {
  tcg_gen_movi_tl(cpu_gpr[a->rd], 0);
@@ -53,6 +54,7 @@ static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a)
  tcg_gen_movi_tl(cpu_gpr[a->rd], 0);
  return true;
  }
+#endif


You shouldn't have two copies of these.


+void helper_rdtime_w(CPULoongArchState *env, target_ulong rd,
+ target_ulong rj, target_ulong high)
+{
+if (rd) {
+if (high) {
+env->gpr[rd] = cpu_loongarch_get_stable_counter(env) >> 32;
+} else {
+env->gpr[rd] = cpu_loongarch_get_stable_counter(env) & 0x;
+}


This is incorrect -- the result should be sign-extended in RD.


+void helper_rdtime_d(CPULoongArchState *env, target_ulong rd, target_ulong rj)
+{
+if (rd) {
+env->gpr[rd] = cpu_loongarch_get_stable_counter(env);
+}
+if (rj) {
+env->gpr[rj] = env->CSR_TMID;
+}


You shouldn't need two functions.  Just return the full 64-bit result, placing that into 
RD, then read TMID separately.


rd = gpr_dst(ctx, a->rd, EXT_NONE);
gen_helper_rdtime_d(rd, cpu_env);
if (word) {
tcg_gen_sextract_tl(rd, rd, high ? 32 : 0, 32);
}

rj = gpr_dst(ctx, a->rj, EXT_NONE);
tcg_gen_ld_i64(rj, cpu_env, offsetof(CPULoongArchState, CSR_TMID));


r~



Re: [PATCH 00/31] Add Loongarch softmmu support.

2021-10-19 Thread WANG Xuerui
Hi Xiaojuan,


On 2021/10/20 09:33, 杨小娟 wrote:
> Hi, Xuerui
> Thank you for your advice, I‘ll modify the README and put the binary in 
> the github.
> The remaining patches are send backed, I’ll find the cause and send them 
> again.

Okay, understood; thanks for the quick response.

You may address the several review comments then just send v2. This way
the threading is less likely to be damaged (you need to exactly specify
In-Reply-To headers and such for the re-sent patches to correctly link
to this thread, I think it's not worth the effort).

> 
>
> 本邮件及其附件含有龙芯中科的商业秘密信息,仅限于发送给上面地址中列出的个人或群组。禁止任何其他人以任何形式使用(包括但不限于全部或部分地泄露、复制或散发)本邮件及其附件中的信息。如果您错收本邮件,请您立即电话或邮件通知发件人并删除本邮件。
>  
> This email and its attachments contain confidential information from Loongson 
> Technology , which is intended only for the person or entity whose address is 
> listed above. Any use of the information contained herein in any way 
> (including, but not limited to, total or partial disclosure, reproduction or 
> dissemination) by persons other than the intended recipient(s) is prohibited. 
> If you receive this email in error, please notify the sender by phone or 
> email immediately and delete it. 
BTW really, ask your IT department to fix this nonsense. Multiple
upstreams using mailing lists as primary means of communication
(binutils etc) find problems with the mangling of contents, added
nonsense HTML-like tags and this footer not applicable to public
communication.



Re: [PATCH 10/31] target/loongarch: Add loongarch interrupt and exception handle

2021-10-19 Thread Richard Henderson

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:

This patch Add loongarch interrupt and exception handle.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
  target/loongarch/cpu.c | 293 +
  target/loongarch/cpu.h |   6 +-
  2 files changed, 298 insertions(+), 1 deletion(-)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 7fa3851251..3e3cf233db 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -45,7 +45,10 @@ static const char * const excp_names[EXCP_LAST + 1] = {
  [EXCP_TLBPE] = "TLB priviledged error",
  [EXCP_TLBNX] = "TLB execute-inhibit",
  [EXCP_TLBNR] = "TLB read-inhibit",
+[EXCP_EXT_INTERRUPT] = "interrupt",
  [EXCP_DBP] = "debug breakpoint",
+[EXCP_IBE] = "instruction bus error",
+[EXCP_DBE] = "data bus error",
  };


More incomplete update from before.


+/* Check if there is pending and not masked out interrupt */
+static inline bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env)
+{
+uint32_t pending;
+uint32_t status;
+bool r;
+
+pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
+status  = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE);
+
+r = (pending & status) != 0;
+return r;


Return the expression directly?


+}
+
+static inline unsigned int get_vint_size(CPULoongArchState *env)
+{
+unsigned int size = 0;
+uint64_t vs = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, VS);
+
+switch (vs) {
+case 0:
+break;
+case 1:
+size = 2 * 4;   /* #Insts * inst_size */
+break;
+case 2:
+size = 4 * 4;
+break;
+case 3:
+size = 8 * 4;
+break;
+case 4:
+size = 16 * 4;
+break;
+case 5:
+size = 32 * 4;
+break;
+case 6:
+size = 64 * 4;
+break;
+case 7:
+size = 128 * 4;
+break;


This is a pretty simple expression to turn into a switch.


+#define is_refill(cs, env) (((cs->exception_index == EXCP_TLBL) \
+|| (cs->exception_index == EXCP_TLBS))  \
+&& (env->error_code & EXCP_TLB_NOMATCH))


This should be a function, not a macro.
It's probably worth computing once, not multiple times within 
loongarch_cpu_do_interrupt.


+default:
+qemu_log("Error: exception(%d) '%s' has not been supported\n",
+ cs->exception_index, excp_names[cs->exception_index]);


../qemu/target/loongarch/cpu.c: In function ‘loongarch_cpu_do_interrupt’:
../qemu/target/loongarch/cpu.c:250:9: error: array subscript [0, 16] is outside array 
bounds of ‘const char * const[17]’ [-Werror=array-bounds]

  250 | qemu_log("Error: exception(%d) '%s' has not been supported\n",
  | ^~
  251 |  cs->exception_index, excp_names[cs->exception_index]);
  |  ~
../qemu/target/loongarch/cpu.c:36:27: note: while referencing ‘excp_names’
   36 | static const char * const excp_names[EXCP_LAST + 1] = {
  |   ^~
cc1: all warnings being treated as errors


@@ -223,6 +509,7 @@ static void loongarch_cpu_realizefn(DeviceState *dev, Error 
**errp)
  
  #ifndef CONFIG_USER_ONLY

  ls3a5k_mmu_init(env);
+env->exception_base = 0x1C00;
  #endif


What is exception_base if it's not EENTRY?  Too much copying from MIPS?


r~



Re: [PATCH v2 0/5] aspeed/smc: Improve support for the alternate boot function

2021-10-19 Thread Peter Delevoryas


> On Oct 18, 2021, at 6:26 AM, Cédric Le Goater  wrote:
> 
> Hello,
> 
> The Aspeed SoCs have a dual boot function for firmware fail-over
> recovery. The system auto-reboots from the second flash if the main
> flash does not boot successfully within a certain amount of time. This
> function is called alternate boot (ABR) in the FMC controllers.
> 
> On the AST2600, the ABR registers controlling the 2nd watchdog timer
> were moved from the watchdog register to the FMC controller. To
> control WDT2 through the FMC model register set, this series creates a
> local address space on top of WDT2 memory region.
> 
> To test on the fuji-bmc machine, run :
> 
>devmem 0x1e620064
>devmem 0x1e78504C 
> 
>devmem 0x1e620064 32 0x
>devmem 0x1e620064
>devmem 0x1e78504C

This looks good to me! I looked at the whole
patch series, I think all the changes look right.

By the way, just to make sure I’m understanding correctly:

The AST2400 datasheet shows only 2 watchdog timers, and
the first to be used as the primary system deadlock
reset (but still reboot from the primary flash), and the
second watchdog is designated as an alternate boot
watchdog, which reboots from secondary flash and is
only enabled if there’s a specific hw strap pin enabled,
and the second watchdog is usually disabled once booting
is successful, right?

The AST2600 datasheet shows there’s 8 watchdogs (but
we only have 4 declared in QEMU? I see only the first
four support external reset signals, maybe that’s why?)
but it doesn’t seem to say explicitly that the 2nd
watchdog is the alternate boot watchdog, it’s probably
just implied that the user read the AST2400/AST2500 docs
right? And the FMC registers are just an alias to write
to these watchdog 2 registers? Just curious, is it
strictly necessary to use the FMC registers to disable
the alternate boot watchdog, or could you just use the
old address, 0x1e78504C? In our OpenBMC initialization
for Fuji, we’re using the FMC registers, but would
it still work if we used the old addresses? Just curious,
the more I think about it, it seems odd to me that these
FMC watchdog registers exist if they’re just an alias.

Also, I was wondering: does the alternate boot
watchdog actually switch the flash device or flash
region that we boot from, or does it just reboot from
the primary partition? I don’t see anything in
watchdog_perform_action() that obviously indicates we’re
actually switching to a secondary flash, so I was curious
about that.

Thanks for adding this though! This is very useful, we’re
using QEMU more and more for testing, especially the
boot process, so more accurate emulation of this functionality
is great.

Thanks,
Peter

Reviewed-by: Peter Delevoryas 

> 
> Thanks
> 
> C.
> 
> Changes since v2:
> 
> - introduce a container region for the WDT2 register address space
> - introduce a container region for the flash mmio address space
> 
> Cédric Le Goater (5):
>  aspeed/wdt: Introduce a container for the MMIO region
>  aspeed: Initialize the watchdog device models before the FMC models
>  aspeed/smc: Improve support for the alternate boot function
>  aspeed/smc: Use a container for the flash mmio address space
>  speed/sdhci: Add trace events
> 
> include/hw/ssi/aspeed_smc.h  |  5 +-
> include/hw/watchdog/wdt_aspeed.h |  1 +
> hw/arm/aspeed_ast2600.c  | 38 +++---
> hw/arm/aspeed_soc.c  | 36 ++---
> hw/sd/aspeed_sdhci.c |  5 ++
> hw/ssi/aspeed_smc.c  | 89 +---
> hw/watchdog/wdt_aspeed.c |  6 ++-
> hw/sd/trace-events   |  4 ++
> hw/ssi/trace-events  |  1 +
> 9 files changed, 141 insertions(+), 44 deletions(-)
> 
> -- 
> 2.31.1
> 
> 
> 



[PATCH V5 10/10] vhost-vdpa: multiqueue support

2021-10-19 Thread Jason Wang
This patch implements the multiqueue support for vhost-vdpa. This is
done simply by reading the number of queue pairs from the config space
and initialize the datapath and control path net client.

Signed-off-by: Jason Wang 
---
 hw/virtio/vhost-vdpa.c |   2 +-
 net/vhost-vdpa.c   | 105 +
 2 files changed, 97 insertions(+), 10 deletions(-)

diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 40987188cf..ce0a297481 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -630,7 +630,7 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool 
started)
 vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs);
 }
 
-if (vhost_vdpa_one_time_request(dev)) {
+if (dev->vq_index + dev->nvqs != dev->last_index) {
 return 0;
 }
 
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index 151f60184d..49ab322511 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -18,6 +18,7 @@
 #include "qemu/error-report.h"
 #include "qemu/option.h"
 #include "qapi/error.h"
+#include 
 #include 
 #include 
 #include "standard-headers/linux/virtio_net.h"
@@ -51,6 +52,14 @@ const int vdpa_feature_bits[] = {
 VIRTIO_NET_F_HOST_UFO,
 VIRTIO_NET_F_MRG_RXBUF,
 VIRTIO_NET_F_MTU,
+VIRTIO_NET_F_CTRL_RX,
+VIRTIO_NET_F_CTRL_RX_EXTRA,
+VIRTIO_NET_F_CTRL_VLAN,
+VIRTIO_NET_F_GUEST_ANNOUNCE,
+VIRTIO_NET_F_CTRL_MAC_ADDR,
+VIRTIO_NET_F_RSS,
+VIRTIO_NET_F_MQ,
+VIRTIO_NET_F_CTRL_VQ,
 VIRTIO_F_IOMMU_PLATFORM,
 VIRTIO_F_RING_PACKED,
 VIRTIO_NET_F_RSS,
@@ -81,7 +90,8 @@ static int vhost_vdpa_net_check_device_id(struct vhost_net 
*net)
 return ret;
 }
 
-static int vhost_vdpa_add(NetClientState *ncs, void *be)
+static int vhost_vdpa_add(NetClientState *ncs, void *be,
+  int queue_pair_index, int nvqs)
 {
 VhostNetOptions options;
 struct vhost_net *net = NULL;
@@ -94,7 +104,7 @@ static int vhost_vdpa_add(NetClientState *ncs, void *be)
 options.net_backend = ncs;
 options.opaque  = be;
 options.busyloop_timeout = 0;
-options.nvqs = 2;
+options.nvqs = nvqs;
 
 net = vhost_net_init(&options);
 if (!net) {
@@ -172,18 +182,28 @@ static NetClientInfo net_vhost_vdpa_info = {
 static NetClientState *net_vhost_vdpa_init(NetClientState *peer,
const char *device,
const char *name,
-   int vdpa_device_fd)
+   int vdpa_device_fd,
+   int queue_pair_index,
+   int nvqs,
+   bool is_datapath)
 {
 NetClientState *nc = NULL;
 VhostVDPAState *s;
 int ret = 0;
 assert(name);
-nc = qemu_new_net_client(&net_vhost_vdpa_info, peer, device, name);
+if (is_datapath) {
+nc = qemu_new_net_client(&net_vhost_vdpa_info, peer, device,
+ name);
+} else {
+nc = qemu_new_net_control_client(&net_vhost_vdpa_info, peer,
+ device, name);
+}
 snprintf(nc->info_str, sizeof(nc->info_str), TYPE_VHOST_VDPA);
 s = DO_UPCAST(VhostVDPAState, nc, nc);
 
 s->vhost_vdpa.device_fd = vdpa_device_fd;
-ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa);
+s->vhost_vdpa.index = queue_pair_index;
+ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa, queue_pair_index, nvqs);
 if (ret) {
 qemu_del_net_client(nc);
 return NULL;
@@ -191,12 +211,52 @@ static NetClientState *net_vhost_vdpa_init(NetClientState 
*peer,
 return nc;
 }
 
+static int vhost_vdpa_get_max_queue_pairs(int fd, int *has_cvq, Error **errp)
+{
+unsigned long config_size = offsetof(struct vhost_vdpa_config, buf);
+struct vhost_vdpa_config *config;
+__virtio16 *max_queue_pairs;
+uint64_t features;
+int ret;
+
+ret = ioctl(fd, VHOST_GET_FEATURES, &features);
+if (ret) {
+error_setg(errp, "Fail to query features from vhost-vDPA device");
+return ret;
+}
+
+if (features & (1 << VIRTIO_NET_F_CTRL_VQ)) {
+*has_cvq = 1;
+} else {
+*has_cvq = 0;
+}
+
+if (features & (1 << VIRTIO_NET_F_MQ)) {
+config = g_malloc0(config_size + sizeof(*max_queue_pairs));
+config->off = offsetof(struct virtio_net_config, max_virtqueue_pairs);
+config->len = sizeof(*max_queue_pairs);
+
+ret = ioctl(fd, VHOST_VDPA_GET_CONFIG, config);
+if (ret) {
+error_setg(errp, "Fail to get config from vhost-vDPA device");
+return -ret;
+}
+
+max_queue_pairs = (__virtio16 *)&config->buf;
+
+return lduw_le_p(max_queue_pairs);
+}
+
+return 1;
+}
+
 int net_init_vhost_vdpa(const Netdev *netdev, const char *name,
 NetClientState *peer, E

Re: [PATCH] hw/qdev-core: Add compatibility for (non)-transitional devs

2021-10-19 Thread Jason Wang
On Wed, Oct 20, 2021 at 9:31 AM Jason Wang  wrote:
>
> On Wed, Oct 20, 2021 at 12:56 AM Eduardo Habkost  wrote:
> >
> > On Tue, Oct 19, 2021 at 12:13:17PM -0400, Michael S. Tsirkin wrote:
> > > On Tue, Oct 19, 2021 at 11:29:13AM -0400, Eduardo Habkost wrote:
> > > > On Tue, Oct 19, 2021 at 06:59:09AM -0400, Michael S. Tsirkin wrote:
> > > > > On Tue, Oct 19, 2021 at 11:46:17AM +0100, Stefan Hajnoczi wrote:
> > > > > > On Tue, Oct 12, 2021 at 10:36:01AM +0200, Jean-Louis Dupond wrote:
> > > > > > > Forgot to CC maintainers.
> > > > > >
> > > > > > Also CCing Jason Wang and Michael Tsirkin for VIRTIO.
> > > > > >
> > > > > > Stefan
> > > > >
> > > > > OMG
> > > > > where all compat properties broken all the time?
> > > >
> > > > Compat properties that existed when commit f6e501a28ef9 ("virtio:
> > > > Provide version-specific variants of virtio PCI devices") was
> > > > merged are not broken, because virtio-*-transitional and
> > > > virtio-*-non-transitional were brand new QOM types (so there's no
> > > > compatibility to be kept with old QEMU versions).
> > > >
> > > > Compat properties referencing "virtio-*-pci" instead of
> > > > "virtio-*-pci-base" added after commit f6e501a28ef9 are probably
> > > > broken, yes.
> > > >
> > > > --
> > > > Eduardo
> > >
> > > Oh. So just this one:
> > > { "virtio-net-pci", "vectors", "3"},
> > >
> > > right?
> >
> > I think so.  That's the only post-4.0 virtio-*-pci compat property I see in
> > hw/core/machine.c.
> >
> > pc.c doesn't have any post-4.0 virtio-*-pci compat props.  I didn't see any
> > virtio compat props on spapr.c and s390-virtio-ccw.c.
> >
> > >
> > > about the patch: how do people feel about virtio specific
> > > stuff in qdev core? Ok by everyone?
> >
> > Not OK, if we have a mechanism to avoid that, already (the
> > "virtio-net-pci-base" type name).  I wonder what we can do to
> > make this kind of mistake less likely, though.
> >
> > Jean-Louis, Jason, does the following fix work?
>
> Yes.
>
> Acked-by: Jason Wang 
>
> Thanks
>
> >
> > Signed-off-by: Eduardo Habkost 
> > ---
> > diff --git a/hw/core/machine.c b/hw/core/machine.c
> > index b8d95eec32d..bd9c6156c1a 100644
> > --- a/hw/core/machine.c
> > +++ b/hw/core/machine.c
> > @@ -56,7 +56,7 @@ GlobalProperty hw_compat_5_2[] = {
> >  { "ICH9-LPC", "smm-compat", "on"},
> >  { "PIIX4_PM", "smm-compat", "on"},
> >  { "virtio-blk-device", "report-discard-granularity", "off" },
> > -{ "virtio-net-pci", "vectors", "3"},
> > +{ "virtio-net-pci-base", "vectors", "3"},

Rethink about this, any chance that we can use "virtio-net-pci" as the
base_name? It looks to me this can cause less confusion and consistent
with the existing compat properties.

Thanks

> >  };
> >  const size_t hw_compat_5_2_len = G_N_ELEMENTS(hw_compat_5_2);
> >
> > --
> > Eduardo
> >




[PATCH V5 08/10] vhost: record the last virtqueue index for the virtio device

2021-10-19 Thread Jason Wang
This patch introduces a new field in the vhost_dev structure to record
the last virtqueue index for the virtio device. This will be useful
for the vhost backends with 1:N model to start or stop the device
after all the vhost_dev structures were started or stopped.

Signed-off-by: Jason Wang 
---
 hw/net/vhost_net.c| 12 +---
 include/hw/virtio/vhost.h |  2 ++
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 2b594b4642..3aabab06ea 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -231,9 +231,11 @@ fail:
 return NULL;
 }
 
-static void vhost_net_set_vq_index(struct vhost_net *net, int vq_index)
+static void vhost_net_set_vq_index(struct vhost_net *net, int vq_index,
+   int last_index)
 {
 net->dev.vq_index = vq_index;
+net->dev.last_index = last_index;
 }
 
 static int vhost_net_start_one(struct vhost_net *net,
@@ -324,9 +326,13 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
 VirtIONet *n = VIRTIO_NET(dev);
 int nvhosts = data_queue_pairs + cvq;
 struct vhost_net *net;
-int r, e, i;
+int r, e, i, last_index = data_qps * 2;
 NetClientState *peer;
 
+if (!cvq) {
+last_index -= 1;
+}
+
 if (!k->set_guest_notifiers) {
 error_report("binding does not support guest notifiers");
 return -ENOSYS;
@@ -341,7 +347,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
 }
 
 net = get_vhost_net(peer);
-vhost_net_set_vq_index(net, i * 2);
+vhost_net_set_vq_index(net, i * 2, last_index);
 
 /* Suppress the masking guest notifiers on vhost user
  * because vhost user doesn't interrupt masking/unmasking
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 1a9fc65089..3fa0b554ef 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -74,6 +74,8 @@ struct vhost_dev {
 unsigned int nvqs;
 /* the first virtqueue which would be used by this vhost dev */
 int vq_index;
+/* the last vq index for the virtio device (not vhost) */
+int last_index;
 /* if non-zero, minimum required value for max_queues */
 int num_queues;
 uint64_t features;
-- 
2.25.1




[PATCH V5 07/10] virtio-net: use "queue_pairs" instead of "queues" when possible

2021-10-19 Thread Jason Wang
Most of the time, "queues" really means queue pairs. So this patch
switch to use "queue_pairs" to avoid confusion.

Signed-off-by: Jason Wang 
---
 hw/net/vhost_net.c |   6 +-
 hw/net/virtio-net.c| 150 -
 include/hw/virtio/virtio-net.h |   4 +-
 3 files changed, 80 insertions(+), 80 deletions(-)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index e1e9d1ec89..2b594b4642 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -337,7 +337,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
 if (i < data_queue_pairs) {
 peer = qemu_get_peer(ncs, i);
 } else { /* Control Virtqueue */
-peer = qemu_get_peer(ncs, n->max_queues);
+peer = qemu_get_peer(ncs, n->max_queue_pairs);
 }
 
 net = get_vhost_net(peer);
@@ -362,7 +362,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
 if (i < data_queue_pairs) {
 peer = qemu_get_peer(ncs, i);
 } else {
-peer = qemu_get_peer(ncs, n->max_queues);
+peer = qemu_get_peer(ncs, n->max_queue_pairs);
 }
 r = vhost_net_start_one(get_vhost_net(peer), dev);
 
@@ -412,7 +412,7 @@ void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs,
 if (i < data_queue_pairs) {
 peer = qemu_get_peer(ncs, i);
 } else {
-peer = qemu_get_peer(ncs, n->max_queues);
+peer = qemu_get_peer(ncs, n->max_queue_pairs);
 }
 vhost_net_stop_one(get_vhost_net(peer), dev);
 }
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 5ee6729662..7594f7ea92 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -54,7 +54,7 @@
 #define VIRTIO_NET_RX_QUEUE_DEFAULT_SIZE 256
 #define VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE 256
 
-/* for now, only allow larger queues; with virtio-1, guest can downsize */
+/* for now, only allow larger queue_pairs; with virtio-1, guest can downsize */
 #define VIRTIO_NET_RX_QUEUE_MIN_SIZE VIRTIO_NET_RX_QUEUE_DEFAULT_SIZE
 #define VIRTIO_NET_TX_QUEUE_MIN_SIZE VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE
 
@@ -131,7 +131,7 @@ static void virtio_net_get_config(VirtIODevice *vdev, 
uint8_t *config)
 int ret = 0;
 memset(&netcfg, 0 , sizeof(struct virtio_net_config));
 virtio_stw_p(vdev, &netcfg.status, n->status);
-virtio_stw_p(vdev, &netcfg.max_virtqueue_pairs, n->max_queues);
+virtio_stw_p(vdev, &netcfg.max_virtqueue_pairs, n->max_queue_pairs);
 virtio_stw_p(vdev, &netcfg.mtu, n->net_conf.mtu);
 memcpy(netcfg.mac, n->mac, ETH_ALEN);
 virtio_stl_p(vdev, &netcfg.speed, n->net_conf.speed);
@@ -243,7 +243,7 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t 
status)
 {
 VirtIODevice *vdev = VIRTIO_DEVICE(n);
 NetClientState *nc = qemu_get_queue(n->nic);
-int queues = n->multiqueue ? n->max_queues : 1;
+int queue_pairs = n->multiqueue ? n->max_queue_pairs : 1;
 
 if (!get_vhost_net(nc->peer)) {
 return;
@@ -266,7 +266,7 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t 
status)
 /* Any packets outstanding? Purge them to avoid touching rings
  * when vhost is running.
  */
-for (i = 0;  i < queues; i++) {
+for (i = 0;  i < queue_pairs; i++) {
 NetClientState *qnc = qemu_get_subqueue(n->nic, i);
 
 /* Purge both directions: TX and RX. */
@@ -285,14 +285,14 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t 
status)
 }
 
 n->vhost_started = 1;
-r = vhost_net_start(vdev, n->nic->ncs, queues, 0);
+r = vhost_net_start(vdev, n->nic->ncs, queue_pairs, 0);
 if (r < 0) {
 error_report("unable to start vhost net: %d: "
  "falling back on userspace virtio", -r);
 n->vhost_started = 0;
 }
 } else {
-vhost_net_stop(vdev, n->nic->ncs, queues, 0);
+vhost_net_stop(vdev, n->nic->ncs, queue_pairs, 0);
 n->vhost_started = 0;
 }
 }
@@ -309,11 +309,11 @@ static int virtio_net_set_vnet_endian_one(VirtIODevice 
*vdev,
 }
 
 static bool virtio_net_set_vnet_endian(VirtIODevice *vdev, NetClientState *ncs,
-   int queues, bool enable)
+   int queue_pairs, bool enable)
 {
 int i;
 
-for (i = 0; i < queues; i++) {
+for (i = 0; i < queue_pairs; i++) {
 if (virtio_net_set_vnet_endian_one(vdev, ncs[i].peer, enable) < 0 &&
 enable) {
 while (--i >= 0) {
@@ -330,7 +330,7 @@ static bool virtio_net_set_vnet_endian(VirtIODevice *vdev, 
NetClientState *ncs,
 static void virtio_net_vnet_endian_status(VirtIONet *n, uint8_t status)
 {
 VirtIODevice *vdev = VIRTIO_DEVICE(n);
-int queues = n->multiqueue ? n->max_queues : 1;
+int queue_pairs = n->multiqueue ? n->max_queue_pairs : 1;
 
 if (virtio_net_started(n, status)) {
 /* Before usin

[PATCH V5 09/10] virtio-net: vhost control virtqueue support

2021-10-19 Thread Jason Wang
This patch implements the control virtqueue support for vhost. This
requires virtio-net to figure out the datapath queue pairs and control
virtqueue via is_datapath and pass the number of those two types
of virtqueues to vhost_net_start()/vhost_net_stop().

Signed-off-by: Jason Wang 
---
 hw/net/vhost_net.c |  2 +-
 hw/net/virtio-net.c| 23 +++
 include/hw/virtio/virtio-net.h |  1 +
 3 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 3aabab06ea..0d888f29a6 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -326,7 +326,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
 VirtIONet *n = VIRTIO_NET(dev);
 int nvhosts = data_queue_pairs + cvq;
 struct vhost_net *net;
-int r, e, i, last_index = data_qps * 2;
+int r, e, i, last_index = data_queue_pairs * 2;
 NetClientState *peer;
 
 if (!cvq) {
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 7594f7ea92..f2014d5ea0 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -244,6 +244,7 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t 
status)
 VirtIODevice *vdev = VIRTIO_DEVICE(n);
 NetClientState *nc = qemu_get_queue(n->nic);
 int queue_pairs = n->multiqueue ? n->max_queue_pairs : 1;
+int cvq = n->max_ncs - n->max_queue_pairs;
 
 if (!get_vhost_net(nc->peer)) {
 return;
@@ -285,14 +286,14 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t 
status)
 }
 
 n->vhost_started = 1;
-r = vhost_net_start(vdev, n->nic->ncs, queue_pairs, 0);
+r = vhost_net_start(vdev, n->nic->ncs, queue_pairs, cvq);
 if (r < 0) {
 error_report("unable to start vhost net: %d: "
  "falling back on userspace virtio", -r);
 n->vhost_started = 0;
 }
 } else {
-vhost_net_stop(vdev, n->nic->ncs, queue_pairs, 0);
+vhost_net_stop(vdev, n->nic->ncs, queue_pairs, cvq);
 n->vhost_started = 0;
 }
 }
@@ -3411,9 +3412,23 @@ static void virtio_net_device_realize(DeviceState *dev, 
Error **errp)
 return;
 }
 
-n->max_queue_pairs = MAX(n->nic_conf.peers.queues, 1);
+n->max_ncs = MAX(n->nic_conf.peers.queues, 1);
+
+/*
+ * Figure out the datapath queue pairs since the backend could
+ * provide control queue via peers as well.
+ */
+if (n->nic_conf.peers.queues) {
+for (i = 0; i < n->max_ncs; i++) {
+if (n->nic_conf.peers.ncs[i]->is_datapath) {
+++n->max_queue_pairs;
+}
+}
+}
+n->max_queue_pairs = MAX(n->max_queue_pairs, 1);
+
 if (n->max_queue_pairs * 2 + 1 > VIRTIO_QUEUE_MAX) {
-error_setg(errp, "Invalid number of queue_pairs (= %" PRIu32 "), "
+error_setg(errp, "Invalid number of queue pairs (= %" PRIu32 "), "
"must be a positive integer less than %d.",
n->max_queue_pairs, (VIRTIO_QUEUE_MAX - 1) / 2);
 virtio_cleanup(vdev);
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
index 2903b79a92..eb87032627 100644
--- a/include/hw/virtio/virtio-net.h
+++ b/include/hw/virtio/virtio-net.h
@@ -196,6 +196,7 @@ struct VirtIONet {
 int multiqueue;
 uint16_t max_queue_pairs;
 uint16_t curr_queue_pairs;
+uint16_t max_ncs;
 size_t config_size;
 char *netclient_name;
 char *netclient_type;
-- 
2.25.1




[PATCH V5 06/10] vhost-net: control virtqueue support

2021-10-19 Thread Jason Wang
We assume there's no cvq in the past, this is not true when we need
control virtqueue support for vhost-user backends. So this patch
implements the control virtqueue support for vhost-net. As datapath,
the control virtqueue is also required to be coupled with the
NetClientState. The vhost_net_start/stop() are tweaked to accept the
number of datapath queue pairs plus the the number of control
virtqueue for us to start and stop the vhost device.

Signed-off-by: Jason Wang 
---
 hw/net/vhost_net-stub.c |  4 ++--
 hw/net/vhost_net.c  | 43 ++---
 hw/net/virtio-net.c |  4 ++--
 include/net/vhost_net.h |  6 --
 4 files changed, 40 insertions(+), 17 deletions(-)

diff --git a/hw/net/vhost_net-stub.c b/hw/net/vhost_net-stub.c
index a7f4252630..89d71cfb8e 100644
--- a/hw/net/vhost_net-stub.c
+++ b/hw/net/vhost_net-stub.c
@@ -33,13 +33,13 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
 
 int vhost_net_start(VirtIODevice *dev,
 NetClientState *ncs,
-int total_queues)
+int data_queue_pairs, int cvq)
 {
 return -ENOSYS;
 }
 void vhost_net_stop(VirtIODevice *dev,
 NetClientState *ncs,
-int total_queues)
+int data_queue_pairs, int cvq)
 {
 }
 
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 386ec2eaa2..e1e9d1ec89 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -315,11 +315,14 @@ static void vhost_net_stop_one(struct vhost_net *net,
 }
 
 int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
-int total_queues)
+int data_queue_pairs, int cvq)
 {
 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
 VirtioBusState *vbus = VIRTIO_BUS(qbus);
 VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
+int total_notifiers = data_queue_pairs * 2 + cvq;
+VirtIONet *n = VIRTIO_NET(dev);
+int nvhosts = data_queue_pairs + cvq;
 struct vhost_net *net;
 int r, e, i;
 NetClientState *peer;
@@ -329,9 +332,14 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
 return -ENOSYS;
 }
 
-for (i = 0; i < total_queues; i++) {
+for (i = 0; i < nvhosts; i++) {
+
+if (i < data_queue_pairs) {
+peer = qemu_get_peer(ncs, i);
+} else { /* Control Virtqueue */
+peer = qemu_get_peer(ncs, n->max_queues);
+}
 
-peer = qemu_get_peer(ncs, i);
 net = get_vhost_net(peer);
 vhost_net_set_vq_index(net, i * 2);
 
@@ -344,14 +352,18 @@ int vhost_net_start(VirtIODevice *dev, NetClientState 
*ncs,
 }
  }
 
-r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true);
+r = k->set_guest_notifiers(qbus->parent, total_notifiers, true);
 if (r < 0) {
 error_report("Error binding guest notifier: %d", -r);
 goto err;
 }
 
-for (i = 0; i < total_queues; i++) {
-peer = qemu_get_peer(ncs, i);
+for (i = 0; i < nvhosts; i++) {
+if (i < data_queue_pairs) {
+peer = qemu_get_peer(ncs, i);
+} else {
+peer = qemu_get_peer(ncs, n->max_queues);
+}
 r = vhost_net_start_one(get_vhost_net(peer), dev);
 
 if (r < 0) {
@@ -375,7 +387,7 @@ err_start:
 peer = qemu_get_peer(ncs , i);
 vhost_net_stop_one(get_vhost_net(peer), dev);
 }
-e = k->set_guest_notifiers(qbus->parent, total_queues * 2, false);
+e = k->set_guest_notifiers(qbus->parent, total_notifiers, false);
 if (e < 0) {
 fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", e);
 fflush(stderr);
@@ -385,18 +397,27 @@ err:
 }
 
 void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs,
-int total_queues)
+int data_queue_pairs, int cvq)
 {
 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
 VirtioBusState *vbus = VIRTIO_BUS(qbus);
 VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
+VirtIONet *n = VIRTIO_NET(dev);
+NetClientState *peer;
+int total_notifiers = data_queue_pairs * 2 + cvq;
+int nvhosts = data_queue_pairs + cvq;
 int i, r;
 
-for (i = 0; i < total_queues; i++) {
-vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev);
+for (i = 0; i < nvhosts; i++) {
+if (i < data_queue_pairs) {
+peer = qemu_get_peer(ncs, i);
+} else {
+peer = qemu_get_peer(ncs, n->max_queues);
+}
+vhost_net_stop_one(get_vhost_net(peer), dev);
 }
 
-r = k->set_guest_notifiers(qbus->parent, total_queues * 2, false);
+r = k->set_guest_notifiers(qbus->parent, total_notifiers, false);
 if (r < 0) {
 fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r);
 fflush(stderr);
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 3dd2896ff9..5ee6729662 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -

[PATCH V5 04/10] vhost-vdpa: let net_vhost_vdpa_init() returns NetClientState *

2021-10-19 Thread Jason Wang
This patch switches to let net_vhost_vdpa_init() to return
NetClientState *. This is used for the callers to allocate multiqueue
NetClientState for multiqueue support.

Signed-off-by: Jason Wang 
---
 net/vhost-vdpa.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index fd4ff5a0fb..151f60184d 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -169,8 +169,10 @@ static NetClientInfo net_vhost_vdpa_info = {
 .check_peer_type = vhost_vdpa_check_peer_type,
 };
 
-static int net_vhost_vdpa_init(NetClientState *peer, const char *device,
-   const char *name, int vdpa_device_fd)
+static NetClientState *net_vhost_vdpa_init(NetClientState *peer,
+   const char *device,
+   const char *name,
+   int vdpa_device_fd)
 {
 NetClientState *nc = NULL;
 VhostVDPAState *s;
@@ -184,15 +186,17 @@ static int net_vhost_vdpa_init(NetClientState *peer, 
const char *device,
 ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa);
 if (ret) {
 qemu_del_net_client(nc);
+return NULL;
 }
-return ret;
+return nc;
 }
 
 int net_init_vhost_vdpa(const Netdev *netdev, const char *name,
 NetClientState *peer, Error **errp)
 {
 const NetdevVhostVDPAOptions *opts;
-int vdpa_device_fd, ret;
+int vdpa_device_fd;
+NetClientState *nc;
 
 assert(netdev->type == NET_CLIENT_DRIVER_VHOST_VDPA);
 opts = &netdev->u.vhost_vdpa;
@@ -202,10 +206,11 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char 
*name,
 return -errno;
 }
 
-ret = net_vhost_vdpa_init(peer, TYPE_VHOST_VDPA, name, vdpa_device_fd);
-if (ret) {
+nc = net_vhost_vdpa_init(peer, TYPE_VHOST_VDPA, name, vdpa_device_fd);
+if (!nc) {
 qemu_close(vdpa_device_fd);
+return -1;
 }
 
-return ret;
+return 0;
 }
-- 
2.25.1




[PATCH V5 05/10] net: introduce control client

2021-10-19 Thread Jason Wang
This patch introduces a boolean for the device has control queue which
can accepts control command via network queue.

The first user would be the control virtqueue support for vhost.

Signed-off-by: Jason Wang 
---
 include/net/net.h |  5 +
 net/net.c | 24 +---
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/include/net/net.h b/include/net/net.h
index 986288eb07..523136c7ac 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -105,6 +105,7 @@ struct NetClientState {
 int vnet_hdr_len;
 bool is_netdev;
 bool do_not_pad; /* do not pad to the minimum ethernet frame length */
+bool is_datapath;
 QTAILQ_HEAD(, NetFilterState) filters;
 };
 
@@ -136,6 +137,10 @@ NetClientState *qemu_new_net_client(NetClientInfo *info,
 NetClientState *peer,
 const char *model,
 const char *name);
+NetClientState *qemu_new_net_control_client(NetClientInfo *info,
+NetClientState *peer,
+const char *model,
+const char *name);
 NICState *qemu_new_nic(NetClientInfo *info,
NICConf *conf,
const char *model,
diff --git a/net/net.c b/net/net.c
index 52c99196c6..f0d14dbfc1 100644
--- a/net/net.c
+++ b/net/net.c
@@ -239,7 +239,8 @@ static void qemu_net_client_setup(NetClientState *nc,
   NetClientState *peer,
   const char *model,
   const char *name,
-  NetClientDestructor *destructor)
+  NetClientDestructor *destructor,
+  bool is_datapath)
 {
 nc->info = info;
 nc->model = g_strdup(model);
@@ -258,6 +259,7 @@ static void qemu_net_client_setup(NetClientState *nc,
 
 nc->incoming_queue = qemu_new_net_queue(qemu_deliver_packet_iov, nc);
 nc->destructor = destructor;
+nc->is_datapath = is_datapath;
 QTAILQ_INIT(&nc->filters);
 }
 
@@ -272,7 +274,23 @@ NetClientState *qemu_new_net_client(NetClientInfo *info,
 
 nc = g_malloc0(info->size);
 qemu_net_client_setup(nc, info, peer, model, name,
-  qemu_net_client_destructor);
+  qemu_net_client_destructor, true);
+
+return nc;
+}
+
+NetClientState *qemu_new_net_control_client(NetClientInfo *info,
+NetClientState *peer,
+const char *model,
+const char *name)
+{
+NetClientState *nc;
+
+assert(info->size >= sizeof(NetClientState));
+
+nc = g_malloc0(info->size);
+qemu_net_client_setup(nc, info, peer, model, name,
+  qemu_net_client_destructor, false);
 
 return nc;
 }
@@ -297,7 +315,7 @@ NICState *qemu_new_nic(NetClientInfo *info,
 
 for (i = 0; i < queues; i++) {
 qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, name,
-  NULL);
+  NULL, true);
 nic->ncs[i].queue_index = i;
 }
 
-- 
2.25.1




[PATCH V5 03/10] vhost-vdpa: prepare for the multiqueue support

2021-10-19 Thread Jason Wang
Unlike vhost-kernel, vhost-vdpa adapts a single device multiqueue
model. So we need to simply use virtqueue index as the vhost virtqueue
index. This is a must for multiqueue to work for vhost-vdpa.

Signed-off-by: Jason Wang 
---
 hw/virtio/vhost-vdpa.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 67a3dcf6a5..40987188cf 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -544,8 +544,8 @@ static int vhost_vdpa_get_vq_index(struct vhost_dev *dev, 
int idx)
 {
 assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
 
-trace_vhost_vdpa_get_vq_index(dev, idx, idx - dev->vq_index);
-return idx - dev->vq_index;
+trace_vhost_vdpa_get_vq_index(dev, idx, idx);
+return idx;
 }
 
 static int vhost_vdpa_set_vring_ready(struct vhost_dev *dev)
-- 
2.25.1




[PATCH V5 02/10] vhost-vdpa: classify one time request

2021-10-19 Thread Jason Wang
Vhost-vdpa uses one device multiqueue queue (pairs) model. So we need
to classify the one time request (e.g SET_OWNER) and make sure those
request were only called once per device.

This is used for multiqueue support.

Signed-off-by: Jason Wang 
---
 hw/virtio/vhost-vdpa.c | 53 ++
 include/hw/virtio/vhost-vdpa.h |  1 +
 2 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 7691e904ac..67a3dcf6a5 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -317,6 +317,13 @@ static void vhost_vdpa_get_iova_range(struct vhost_vdpa *v)
 v->iova_range.last);
 }
 
+static bool vhost_vdpa_one_time_request(struct vhost_dev *dev)
+{
+struct vhost_vdpa *v = dev->opaque;
+
+return v->index != 0;
+}
+
 static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque, Error **errp)
 {
 struct vhost_vdpa *v;
@@ -330,6 +337,11 @@ static int vhost_vdpa_init(struct vhost_dev *dev, void 
*opaque, Error **errp)
 v->msg_type = VHOST_IOTLB_MSG_V2;
 
 vhost_vdpa_get_iova_range(v);
+
+if (vhost_vdpa_one_time_request(dev)) {
+return 0;
+}
+
 vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE |
VIRTIO_CONFIG_S_DRIVER);
 
@@ -440,6 +452,10 @@ static int vhost_vdpa_memslots_limit(struct vhost_dev *dev)
 static int vhost_vdpa_set_mem_table(struct vhost_dev *dev,
 struct vhost_memory *mem)
 {
+if (vhost_vdpa_one_time_request(dev)) {
+return 0;
+}
+
 trace_vhost_vdpa_set_mem_table(dev, mem->nregions, mem->padding);
 if (trace_event_get_state_backends(TRACE_VHOST_VDPA_SET_MEM_TABLE) &&
 trace_event_get_state_backends(TRACE_VHOST_VDPA_DUMP_REGIONS)) {
@@ -463,6 +479,11 @@ static int vhost_vdpa_set_features(struct vhost_dev *dev,
uint64_t features)
 {
 int ret;
+
+if (vhost_vdpa_one_time_request(dev)) {
+return 0;
+}
+
 trace_vhost_vdpa_set_features(dev, features);
 ret = vhost_vdpa_call(dev, VHOST_SET_FEATURES, &features);
 uint8_t status = 0;
@@ -487,9 +508,12 @@ static int vhost_vdpa_set_backend_cap(struct vhost_dev 
*dev)
 }
 
 features &= f;
-r = vhost_vdpa_call(dev, VHOST_SET_BACKEND_FEATURES, &features);
-if (r) {
-return -EFAULT;
+
+if (vhost_vdpa_one_time_request(dev)) {
+r = vhost_vdpa_call(dev, VHOST_SET_BACKEND_FEATURES, &features);
+if (r) {
+return -EFAULT;
+}
 }
 
 dev->backend_cap = features;
@@ -598,11 +622,21 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, 
bool started)
 {
 struct vhost_vdpa *v = dev->opaque;
 trace_vhost_vdpa_dev_start(dev, started);
+
 if (started) {
-uint8_t status = 0;
-memory_listener_register(&v->listener, &address_space_memory);
 vhost_vdpa_host_notifiers_init(dev);
 vhost_vdpa_set_vring_ready(dev);
+} else {
+vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs);
+}
+
+if (vhost_vdpa_one_time_request(dev)) {
+return 0;
+}
+
+if (started) {
+uint8_t status = 0;
+memory_listener_register(&v->listener, &address_space_memory);
 vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
 vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &status);
 
@@ -611,7 +645,6 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool 
started)
 vhost_vdpa_reset_device(dev);
 vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE |
VIRTIO_CONFIG_S_DRIVER);
-vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs);
 memory_listener_unregister(&v->listener);
 
 return 0;
@@ -621,6 +654,10 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, 
bool started)
 static int vhost_vdpa_set_log_base(struct vhost_dev *dev, uint64_t base,
  struct vhost_log *log)
 {
+if (vhost_vdpa_one_time_request(dev)) {
+return 0;
+}
+
 trace_vhost_vdpa_set_log_base(dev, base, log->size, log->refcnt, log->fd,
   log->log);
 return vhost_vdpa_call(dev, VHOST_SET_LOG_BASE, &base);
@@ -686,6 +723,10 @@ static int vhost_vdpa_get_features(struct vhost_dev *dev,
 
 static int vhost_vdpa_set_owner(struct vhost_dev *dev)
 {
+if (vhost_vdpa_one_time_request(dev)) {
+return 0;
+}
+
 trace_vhost_vdpa_set_owner(dev);
 return vhost_vdpa_call(dev, VHOST_SET_OWNER, NULL);
 }
diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h
index c288cf7ecb..3ce79a646d 100644
--- a/include/hw/virtio/vhost-vdpa.h
+++ b/include/hw/virtio/vhost-vdpa.h
@@ -22,6 +22,7 @@ typedef struct VhostVDPAHostNotifier {
 
 typedef struct vhost_vdpa {
 int device_fd;
+int index;
 uint32_t msg_type;
 bool iotlb_batch_begin_sent;

[PATCH V5 01/10] vhost-vdpa: open device fd in net_init_vhost_vdpa()

2021-10-19 Thread Jason Wang
This patch switches to open device fd in net_init_vhost_vpda(). This is
used to prepare for the multiqueue support.

Reviewed-by: Stefano Garzarella 
Signed-off-by: Jason Wang 
---
 net/vhost-vdpa.c | 23 +++
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index 6dc68d8677..fd4ff5a0fb 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -170,24 +170,19 @@ static NetClientInfo net_vhost_vdpa_info = {
 };
 
 static int net_vhost_vdpa_init(NetClientState *peer, const char *device,
-   const char *name, const char *vhostdev)
+   const char *name, int vdpa_device_fd)
 {
 NetClientState *nc = NULL;
 VhostVDPAState *s;
-int vdpa_device_fd = -1;
 int ret = 0;
 assert(name);
 nc = qemu_new_net_client(&net_vhost_vdpa_info, peer, device, name);
 snprintf(nc->info_str, sizeof(nc->info_str), TYPE_VHOST_VDPA);
 s = DO_UPCAST(VhostVDPAState, nc, nc);
-vdpa_device_fd = qemu_open_old(vhostdev, O_RDWR);
-if (vdpa_device_fd == -1) {
-return -errno;
-}
+
 s->vhost_vdpa.device_fd = vdpa_device_fd;
 ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa);
 if (ret) {
-qemu_close(vdpa_device_fd);
 qemu_del_net_client(nc);
 }
 return ret;
@@ -197,8 +192,20 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char 
*name,
 NetClientState *peer, Error **errp)
 {
 const NetdevVhostVDPAOptions *opts;
+int vdpa_device_fd, ret;
 
 assert(netdev->type == NET_CLIENT_DRIVER_VHOST_VDPA);
 opts = &netdev->u.vhost_vdpa;
-return net_vhost_vdpa_init(peer, TYPE_VHOST_VDPA, name, opts->vhostdev);
+
+vdpa_device_fd = qemu_open_old(opts->vhostdev, O_RDWR);
+if (vdpa_device_fd == -1) {
+return -errno;
+}
+
+ret = net_vhost_vdpa_init(peer, TYPE_VHOST_VDPA, name, vdpa_device_fd);
+if (ret) {
+qemu_close(vdpa_device_fd);
+}
+
+return ret;
 }
-- 
2.25.1




[PATCH V5 00/10] vhost-vDPA multiqueue

2021-10-19 Thread Jason Wang
Hi All:

This patch implements the multiqueue support for vhost-vDPA. The most
important requirement si the control virtqueue support. The virtio-net
and vhost-net core are tweak to support control virtqueue as if what
data queue pairs are done: a dedicated vhost_net device which is
coupled with the NetClientState is intrdouced so most of the existing
vhost codes could be reused with minor changes. This means the control
virtqueue will bypass the Qemu. With the control virtqueue, vhost-vDPA
are extend to support creating and destroying multiqueue queue pairs
plus the control virtqueue.

For the future, if we want to support live migration, we can either do
shadow cvq on top or introduce new interfaces for reporting device
states.

Tests are done via the vp_vdpa driver in L1 guest.

Changes since V4:
- rebase on top of Michael's pci branch

Changes since V3:
- fix build with vhost disabled

Changes since V2:
- rebase to qemu master
- use "queue_pairs" instead of "qps"
- typo fixes

Changes since V1:
- start and stop vhost devices when all queues were setup
- fix the case when driver doesn't support MQ but device support
- correctly set the batching capability to avoid a map/unmap storm
- various other tweaks

Jason Wang (10):
  vhost-vdpa: open device fd in net_init_vhost_vdpa()
  vhost-vdpa: classify one time request
  vhost-vdpa: prepare for the multiqueue support
  vhost-vdpa: let net_vhost_vdpa_init() returns NetClientState *
  net: introduce control client
  vhost-net: control virtqueue support
  virtio-net: use "queue_pairs" instead of "queues" when possible
  vhost: record the last virtqueue index for the virtio device
  virtio-net: vhost control virtqueue support
  vhost-vdpa: multiqueue support

 hw/net/vhost_net-stub.c|   4 +-
 hw/net/vhost_net.c |  55 ---
 hw/net/virtio-net.c| 165 ++---
 hw/virtio/vhost-vdpa.c |  57 ++--
 include/hw/virtio/vhost-vdpa.h |   1 +
 include/hw/virtio/vhost.h  |   2 +
 include/hw/virtio/virtio-net.h |   5 +-
 include/net/net.h  |   5 +
 include/net/vhost_net.h|   6 +-
 net/net.c  |  24 -
 net/vhost-vdpa.c   | 127 ++---
 11 files changed, 331 insertions(+), 120 deletions(-)

-- 
2.25.1




Re: [PATCH 09/31] target/loongarch: Add other core instructions support

2021-10-19 Thread Richard Henderson

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index afd186abac..7fa3851251 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -45,6 +45,7 @@ static const char * const excp_names[EXCP_LAST + 1] = {
  [EXCP_TLBPE] = "TLB priviledged error",
  [EXCP_TLBNX] = "TLB execute-inhibit",
  [EXCP_TLBNR] = "TLB read-inhibit",
+[EXCP_DBP] = "debug breakpoint",
  };
  
  const char *loongarch_exception_name(int32_t exception)

diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 567fc7620d..d39c618d6b 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -166,10 +166,13 @@ enum {
  EXCP_TLBPE,
  EXCP_TLBNX,
  EXCP_TLBNR,
+EXCP_DBP,
  
-EXCP_LAST = EXCP_TLBNR,

+EXCP_LAST = EXCP_DBP,
  };


These should have been added with the other exceptions earlier.


@@ -173,6 +179,11 @@ static bool trans_iocsrwr_d(DisasContext *ctx, 
arg_iocsrwr_d *a)
  return true;
  }
  
+static bool trans_cacop(DisasContext *ctx, arg_cacop *a)

+{
+return false;
+}


I think you meant to return true here, so that cacop is interpreted as a nop.  You would 
add a comment to that effect.



+static bool trans_ldpte(DisasContext *ctx, arg_ldpte *a)
+{
+TCGv_i32 mem_idx = tcg_constant_i32(ctx->mem_idx);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+gen_helper_ldpte(cpu_env, src1, tcg_constant_tl(a->seq), mem_idx);
+return true;
+}


Missing priv checks again.


+static bool trans_idle(DisasContext *ctx, arg_idle *a)
+{
+ctx->base.pc_next += 4;
+tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
+ctx->base.pc_next -= 4;


Why would you add and subtract like this?


+#ifndef CONFIG_USER_ONLY
+static inline void exception_return(CPULoongArchState *env)
+{
+if (env->CSR_TLBRERA & 0x1) {
+env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PLV,
+   FIELD_EX64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, 
PPLV));
+env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, IE,
+   FIELD_EX64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, 
PIE));
+/* Clear Refill flag and set pc */
+env->CSR_TLBRERA &= (~0x1);
+env->pc = env->CSR_TLBRERA;
+if (qemu_loglevel_mask(CPU_LOG_INT)) {
+qemu_log("%s: TLBRERA 0x%lx\n", __func__, env->CSR_TLBRERA);
+}
+} else {
+env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PLV,
+   FIELD_EX64(env->CSR_PRMD, CSR_PRMD, PPLV));
+env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, IE,
+   FIELD_EX64(env->CSR_PRMD, CSR_PRMD, PIE));
+/* set pc*/
+env->pc = env->CSR_ERA;
+if (qemu_loglevel_mask(CPU_LOG_INT)) {
+qemu_log("%s: ERA 0x%lx\n", __func__, env->CSR_ERA);
+}
+}
+}
+
+void helper_ertn(CPULoongArchState *env)
+{
+exception_return(env);
+env->lladdr = 1;
+}


Any reason to have exception_return be a separate function?


+target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
+  target_ulong level, uint32_t mem_idx)
+{
+target_ulong badvaddr;
+target_ulong index;
+target_ulong vaddr;
+int shift;
+uint64_t dir1_base, dir1_width;
+uint64_t dir3_base, dir3_width;
+
+badvaddr = env->CSR_TLBRBADV;
+
+/* 0:8B, 1:16B, 2:32B, 3:64B */
+shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH);
+shift = (shift + 1) * 3;
+
+switch (level) {
+case 1:
+dir1_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE);
+dir1_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDTH);
+index = (badvaddr >> dir1_base) & ((1 << dir1_width) - 1);
+break;
+case 3:
+dir3_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_BASE);
+dir3_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_WIDTH);
+index = (badvaddr >> dir3_base) & ((1 << dir3_width) - 1);
+break;
+default:
+do_raise_exception(env, EXCP_INE, GETPC());
+return 0;
+}
+
+vaddr = base | index << shift;
+return cpu_ldq_mmuidx_ra(env, vaddr, mem_idx, GETPC());


A load from mem_idx is incorrect -- you have a physical address (thus the name "vaddr" is 
at best misleading). There are two possible solutions:


(1) ldq_phys.

(2) Add a separate MMU_PHYS_IDX, which you could use here.  You would also return this 
value from cpu_mem_index when CRMD.{DA,PG} indicates that direct address translation is 
enabled.



+void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
+  uint32_t mem_idx)
+{

...

+vaddr = base | (odd ? ptoffset1 : ptoffset0);
+tmp0 = cpu_ldq_mmuidx_ra(env, vaddr, mem_idx, GETPC());


Likewise.


r~



Re: [PATCH 08/31] target/loongarch: Add tlb instruction support

2021-10-19 Thread Richard Henderson

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:

This includes:
- TLBSRCH
- TLBRD
- TLBWR
- TLBFILL
- TLBCLR
- TLBFLUSH
- INVTLB

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
  target/loongarch/cpu.c   |  19 +
  target/loongarch/helper.h|   8 +
  target/loongarch/insn_trans/trans_core.c |  54 +++
  target/loongarch/insns.decode|  14 +
  target/loongarch/internals.h |  18 +
  target/loongarch/tlb_helper.c| 468 +++
  6 files changed, 581 insertions(+)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index f145afb603..afd186abac 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -118,6 +118,7 @@ static void set_loongarch_cpucfg(CPULoongArchState *env)
  static void set_loongarch_csr(CPULoongArchState *env)
  {
  uint64_t t;
+CPUState *cs = env_cpu(env);
  
  t = FIELD_DP64(0, CSR_PRCFG1, SAVE_NUM, 8);

  t = FIELD_DP64(t, CSR_PRCFG1, TIMER_BITS, 0x2f);
@@ -145,6 +146,9 @@ static void set_loongarch_csr(CPULoongArchState *env)
  env->CSR_RVACFG = 0x0;
  env->CSR_ASID = 0xa;
  env->CSR_ERA = env->pc;
+env->CSR_CPUID = (cs->cpu_index & 0x1ff);


Any reason to have a copy of cpu_index, as opposed to just using that field?  CSR_CPUID is 
read-only after all.



+env->CSR_EENTRY |= (uint64_t)0x8000;
+env->CSR_TLBRENTRY |= (uint64_t)0x8000;


Are there really a defined reset values?  The documentation doesn't say.  It would appear 
that the kernel must set these before enabling interrupts or turning on paging.



+#ifndef CONFIG_USER_ONLY
+qemu_fprintf(f, "EUEN0x%lx\n", env->CSR_EUEN);
+qemu_fprintf(f, "ESTAT   0x%lx\n", env->CSR_ESTAT);
+qemu_fprintf(f, "ERA 0x%lx\n", env->CSR_ERA);
+qemu_fprintf(f, "CRMD0x%lx\n", env->CSR_CRMD);
+qemu_fprintf(f, "PRMD0x%lx\n", env->CSR_PRMD);
+qemu_fprintf(f, "BadVAddr0x%lx\n", env->CSR_BADV);
+qemu_fprintf(f, "TLB refill ERA  0x%lx\n", env->CSR_TLBRERA);
+qemu_fprintf(f, "TLB refill BadV 0x%lx\n", env->CSR_TLBRBADV);
+qemu_fprintf(f, "EENTRY0x%lx\n", env->CSR_EENTRY);
+qemu_fprintf(f, "BadInstr0x%lx\n", env->CSR_BADI);
+qemu_fprintf(f, "PRCFG10x%lx\nPRCFG2 0x%lx\nPRCFG3 0x%lx\n",
+ env->CSR_PRCFG1, env->CSR_PRCFG3, env->CSR_PRCFG3);
+#endif


This probably belongs to a different patch?


@@ -165,4 +172,51 @@ static bool trans_iocsrwr_d(DisasContext *ctx, 
arg_iocsrwr_d *a)
  gen_helper_iocsr_write(cpu_env, addr, val, tcg_constant_i32(oi));
  return true;
  }
+
+static bool trans_tlbsrch(DisasContext *ctx, arg_tlbsrch *a)
+{
+gen_helper_tlbsrch(cpu_env);
+return true;
+}


Missing priv check, all functions.


+static bool trans_invtlb(DisasContext *ctx, arg_invtlb *a)
+{
+TCGv addr = gpr_src(ctx, a->addr, EXT_NONE);
+TCGv info = gpr_src(ctx, a->info, EXT_NONE);
+TCGv op = tcg_constant_tl(a->invop);
+
+gen_helper_invtlb(cpu_env, addr, info, op);
+return true;
+}


Decode op here -- there are only 7 defined opcodes.

Note that you'll need to end the TB after most TLB instructions, since the translation of 
PC could change between one insn and the next.




+&fmt_invtlb addr info invop
+@fmt_invtlb  .. .. . . . .&fmt_invtlb  
   %addr %info %invop


Why are you using the names addr and info instead of rk and rj?


diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 1251e7f21c..916c675680 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -76,6 +76,14 @@ struct CPULoongArchTLBContext {
  int (*map_address)(struct CPULoongArchState *env, hwaddr *physical,
 int *prot, target_ulong address,
 MMUAccessType access_type);
+void (*helper_tlbwr)(struct CPULoongArchState *env);
+void (*helper_tlbfill)(struct CPULoongArchState *env);
+void (*helper_tlbsrch)(struct CPULoongArchState *env);
+void (*helper_tlbrd)(struct CPULoongArchState *env);
+void (*helper_tlbclr)(struct CPULoongArchState *env);
+void (*helper_tlbflush)(struct CPULoongArchState *env);
+void (*helper_invtlb)(struct CPULoongArchState *env, target_ulong addr,
+  target_ulong info, int op);


Again, function pointers are premature.


+static uint64_t ls3a5k_pagesize_to_mask(int pagesize)
+{
+/* 4KB - 1GB */
+if (pagesize < 12 && pagesize > 30) {
+qemu_log_mask(CPU_LOG_MMU, "unsupported page size %d\n", pagesize);
+exit(-1);


Do not call exit.  Make up something sensible that won't crash qemu.


+/* return random value in [low, high] */
+static uint32_t cpu_loongarch_get_random_ls3a5k_tlb(uint32_t low, uint32_t 
high)
+{
+static uint32_t seed = 5;
+static uint32_t prev_idx;


No static variables like this, as they cannot be migrated

Re: [PATCH] hw/ppc/ppc4xx_pci: Fix ppc4xx_pci_map_irq() for recent Linux kernels

2021-10-19 Thread David Gibson
On Tue, Oct 19, 2021 at 11:18:17AM +0200, Thomas Huth wrote:
65;6402;1c> Recent Linux kernels are accessing the PCI device in slot 0 that
> represents the PCI host bridge. This causes ppc4xx_pci_map_irq()
> to return -1 which causes an assert() later:
> 
>  hw/pci/pci.c:262: pci_bus_change_irq_level: Assertion `irq_num >= 0' failed.
> 
> Thus we should allocate an IRQ line for the device in slot 0, too.
> To avoid changes to the outside of ppc4xx_pci.c, we map it to
> the internal IRQ number 4 which will then happily be ignored since
> ppc440_bamboo.c does not wire it up.
> 
> With these changes it is now possible again to use recent Linux
> kernels for the bamboo board.
> 
> Signed-off-by: Thomas Huth 

Applied to ppc-for-6.2, thanks.

> ---
>  hw/ppc/ppc4xx_pci.c | 8 +---
>  1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c
> index 8147ba6f94..304a29349c 100644
> --- a/hw/ppc/ppc4xx_pci.c
> +++ b/hw/ppc/ppc4xx_pci.c
> @@ -48,12 +48,14 @@ OBJECT_DECLARE_SIMPLE_TYPE(PPC4xxPCIState, 
> PPC4xx_PCI_HOST_BRIDGE)
>  #define PPC4xx_PCI_NR_PMMS 3
>  #define PPC4xx_PCI_NR_PTMS 2
>  
> +#define PPC4xx_PCI_NUM_DEVS 5
> +
>  struct PPC4xxPCIState {
>  PCIHostState parent_obj;
>  
>  struct PCIMasterMap pmm[PPC4xx_PCI_NR_PMMS];
>  struct PCITargetMap ptm[PPC4xx_PCI_NR_PTMS];
> -qemu_irq irq[PCI_NUM_PINS];
> +qemu_irq irq[PPC4xx_PCI_NUM_DEVS];
>  
>  MemoryRegion container;
>  MemoryRegion iomem;
> @@ -246,7 +248,7 @@ static int ppc4xx_pci_map_irq(PCIDevice *pci_dev, int 
> irq_num)
>  
>  trace_ppc4xx_pci_map_irq(pci_dev->devfn, irq_num, slot);
>  
> -return slot - 1;
> +return slot > 0 ? slot - 1 : PPC4xx_PCI_NUM_DEVS - 1;
>  }
>  
>  static void ppc4xx_pci_set_irq(void *opaque, int irq_num, int level)
> @@ -254,7 +256,7 @@ static void ppc4xx_pci_set_irq(void *opaque, int irq_num, 
> int level)
>  qemu_irq *pci_irqs = opaque;
>  
>  trace_ppc4xx_pci_set_irq(irq_num);
> -assert(irq_num >= 0);
> +assert(irq_num >= 0 && irq_num < PPC4xx_PCI_NUM_DEVS);
>  qemu_set_irq(pci_irqs[irq_num], level);
>  }
>  

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


signature.asc
Description: PGP signature


Re: [PATCH v9 05/10] vhost-vdpa: add support for config interrupt call back

2021-10-19 Thread Cindy Lu
On Tue, Oct 19, 2021 at 2:55 PM Michael S. Tsirkin  wrote:
>
> On Thu, Sep 30, 2021 at 10:33:43AM +0800, Cindy Lu wrote:
> > Add new call back function in vhost-vdpa, this call back function will
> > set the fb number to hardware.
> >
> > Signed-off-by: Cindy Lu 
>
> fb being what? you mean fd. said fd doing what exactly?
> all this needs to be in the commit log pls.
>
I will add more information for this
Thanks
> > ---
> >  hw/virtio/trace-events | 2 ++
> >  hw/virtio/vhost-vdpa.c | 7 +++
> >  2 files changed, 9 insertions(+)
> >
> > diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
> > index 8ed19e9d0c..836e73d1f7 100644
> > --- a/hw/virtio/trace-events
> > +++ b/hw/virtio/trace-events
> > @@ -52,6 +52,8 @@ vhost_vdpa_set_vring_call(void *dev, unsigned int index, 
> > int fd) "dev: %p index:
> >  vhost_vdpa_get_features(void *dev, uint64_t features) "dev: %p features: 
> > 0x%"PRIx64
> >  vhost_vdpa_set_owner(void *dev) "dev: %p"
> >  vhost_vdpa_vq_get_addr(void *dev, void *vq, uint64_t desc_user_addr, 
> > uint64_t avail_user_addr, uint64_t used_user_addr) "dev: %p vq: %p 
> > desc_user_addr: 0x%"PRIx64" avail_user_addr: 0x%"PRIx64" used_user_addr: 
> > 0x%"PRIx64
> > +vhost_vdpa_set_config_call(void *dev, int fd)"dev: %p fd: %d"
> > +
> >
> >  # virtio.c
> >  virtqueue_alloc_element(void *elem, size_t sz, unsigned in_num, unsigned 
> > out_num) "elem %p size %zd in_num %u out_num %u"
> > diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
> > index 4fa414feea..73764afc61 100644
> > --- a/hw/virtio/vhost-vdpa.c
> > +++ b/hw/virtio/vhost-vdpa.c
> > @@ -622,6 +622,12 @@ static int vhost_vdpa_set_vring_call(struct vhost_dev 
> > *dev,
> >  trace_vhost_vdpa_set_vring_call(dev, file->index, file->fd);
> >  return vhost_vdpa_call(dev, VHOST_SET_VRING_CALL, file);
> >  }
> > +static int vhost_vdpa_set_config_call(struct vhost_dev *dev,
> > +   int fd)
> > +{
> > +trace_vhost_vdpa_set_config_call(dev, fd);
> > +return vhost_vdpa_call(dev, VHOST_VDPA_SET_CONFIG_CALL, &fd);
> > +}
> >
> >  static int vhost_vdpa_get_features(struct vhost_dev *dev,
> >   uint64_t *features)
> > @@ -688,4 +694,5 @@ const VhostOps vdpa_ops = {
> >  .vhost_get_device_id = vhost_vdpa_get_device_id,
> >  .vhost_vq_get_addr = vhost_vdpa_vq_get_addr,
> >  .vhost_force_iommu = vhost_vdpa_force_iommu,
> > +.vhost_set_config_call = vhost_vdpa_set_config_call,
> >  };
> > --
> > 2.21.3
>




[PATCH v6 15/15] target/riscv: Compute mstatus.sd on demand

2021-10-19 Thread Richard Henderson
The position of this read-only field is dependent on the current xlen.
Rather than having to compute that difference in many places, compute
it only on read.

Reviewed-by: Alistair Francis 
Signed-off-by: Richard Henderson 
---
 target/riscv/cpu_helper.c |  3 +--
 target/riscv/csr.c| 37 ++---
 target/riscv/translate.c  |  5 ++---
 3 files changed, 25 insertions(+), 20 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 429afd1f48..0d1132f39d 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -185,10 +185,9 @@ bool riscv_cpu_fp_enabled(CPURISCVState *env)
 
 void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
 {
-uint64_t sd = riscv_cpu_mxl(env) == MXL_RV32 ? MSTATUS32_SD : MSTATUS64_SD;
 uint64_t mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS |
 MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE |
-MSTATUS64_UXL | sd;
+MSTATUS64_UXL;
 bool current_virt = riscv_cpu_virt_enabled(env);
 
 g_assert(riscv_has_ext(env, RVH));
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index c4a479ddd2..69e4d65fcd 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -477,10 +477,28 @@ static RISCVException read_mhartid(CPURISCVState *env, 
int csrno,
 }
 
 /* Machine Trap Setup */
+
+/* We do not store SD explicitly, only compute it on demand. */
+static uint64_t add_status_sd(RISCVMXL xl, uint64_t status)
+{
+if ((status & MSTATUS_FS) == MSTATUS_FS ||
+(status & MSTATUS_XS) == MSTATUS_XS) {
+switch (xl) {
+case MXL_RV32:
+return status | MSTATUS32_SD;
+case MXL_RV64:
+return status | MSTATUS64_SD;
+default:
+g_assert_not_reached();
+}
+}
+return status;
+}
+
 static RISCVException read_mstatus(CPURISCVState *env, int csrno,
target_ulong *val)
 {
-*val = env->mstatus;
+*val = add_status_sd(riscv_cpu_mxl(env), env->mstatus);
 return RISCV_EXCP_NONE;
 }
 
@@ -498,7 +516,6 @@ static RISCVException write_mstatus(CPURISCVState *env, int 
csrno,
 {
 uint64_t mstatus = env->mstatus;
 uint64_t mask = 0;
-int dirty;
 
 /* flush tlb on mstatus fields that affect VM */
 if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV |
@@ -520,12 +537,7 @@ static RISCVException write_mstatus(CPURISCVState *env, 
int csrno,
 
 mstatus = (mstatus & ~mask) | (val & mask);
 
-dirty = ((mstatus & MSTATUS_FS) == MSTATUS_FS) |
-((mstatus & MSTATUS_XS) == MSTATUS_XS);
-if (riscv_cpu_mxl(env) == MXL_RV32) {
-mstatus = set_field(mstatus, MSTATUS32_SD, dirty);
-} else {
-mstatus = set_field(mstatus, MSTATUS64_SD, dirty);
+if (riscv_cpu_mxl(env) == MXL_RV64) {
 /* SXL and UXL fields are for now read only */
 mstatus = set_field(mstatus, MSTATUS64_SXL, MXL_RV64);
 mstatus = set_field(mstatus, MSTATUS64_UXL, MXL_RV64);
@@ -798,13 +810,8 @@ static RISCVException read_sstatus(CPURISCVState *env, int 
csrno,
 {
 target_ulong mask = (sstatus_v1_10_mask);
 
-if (riscv_cpu_mxl(env) == MXL_RV32) {
-mask |= SSTATUS32_SD;
-} else {
-mask |= SSTATUS64_SD;
-}
-
-*val = env->mstatus & mask;
+/* TODO: Use SXL not MXL. */
+*val = add_status_sd(riscv_cpu_mxl(env), env->mstatus & mask);
 return RISCV_EXCP_NONE;
 }
 
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 0b3da060fd..1d6bf01a48 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -305,7 +305,6 @@ static void gen_jal(DisasContext *ctx, int rd, target_ulong 
imm)
 static void mark_fs_dirty(DisasContext *ctx)
 {
 TCGv tmp;
-target_ulong sd = get_xl(ctx) == MXL_RV32 ? MSTATUS32_SD : MSTATUS64_SD;
 
 if (ctx->mstatus_fs != MSTATUS_FS) {
 /* Remember the state change for the rest of the TB. */
@@ -313,7 +312,7 @@ static void mark_fs_dirty(DisasContext *ctx)
 
 tmp = tcg_temp_new();
 tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
-tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
+tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
 tcg_temp_free(tmp);
 }
@@ -324,7 +323,7 @@ static void mark_fs_dirty(DisasContext *ctx)
 
 tmp = tcg_temp_new();
 tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
-tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
+tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
 tcg_temp_free(tmp);
 }
-- 
2.25.1




[PATCH v6 04/15] target/riscv: Replace riscv_cpu_is_32bit with riscv_cpu_mxl

2021-10-19 Thread Richard Henderson
Shortly, the set of supported XL will not be just 32 and 64,
and representing that properly using the enumeration will be
imperative.

Two places, booting and gdb, intentionally use misa_mxl_max
to emphasize the use of the reset value of misa.mxl, and not
the current cpu state.

Reviewed-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Signed-off-by: Richard Henderson 
---
 target/riscv/cpu.h|  9 -
 hw/riscv/boot.c   |  2 +-
 semihosting/arm-compat-semi.c |  2 +-
 target/riscv/cpu.c| 24 ++--
 target/riscv/cpu_helper.c | 12 ++--
 target/riscv/csr.c| 24 
 target/riscv/gdbstub.c|  2 +-
 target/riscv/monitor.c|  4 ++--
 8 files changed, 45 insertions(+), 34 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index e708fcc168..d0e82135a9 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -396,7 +396,14 @@ FIELD(TB_FLAGS, VILL, 8, 1)
 FIELD(TB_FLAGS, HLSX, 9, 1)
 FIELD(TB_FLAGS, MSTATUS_HS_FS, 10, 2)
 
-bool riscv_cpu_is_32bit(CPURISCVState *env);
+#ifdef TARGET_RISCV32
+#define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
+#else
+static inline RISCVMXL riscv_cpu_mxl(CPURISCVState *env)
+{
+return env->misa_mxl;
+}
+#endif
 
 /*
  * A simplification for VLMAX
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 993bf89064..d1ffc7b56c 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -35,7 +35,7 @@
 
 bool riscv_is_32bit(RISCVHartArrayState *harts)
 {
-return riscv_cpu_is_32bit(&harts->harts[0].env);
+return harts->harts[0].env.misa_mxl_max == MXL_RV32;
 }
 
 target_ulong riscv_calc_kernel_start_addr(RISCVHartArrayState *harts,
diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c
index 01badea99c..37963becae 100644
--- a/semihosting/arm-compat-semi.c
+++ b/semihosting/arm-compat-semi.c
@@ -775,7 +775,7 @@ static inline bool is_64bit_semihosting(CPUArchState *env)
 #if defined(TARGET_ARM)
 return is_a64(env);
 #elif defined(TARGET_RISCV)
-return !riscv_cpu_is_32bit(env);
+return riscv_cpu_mxl(env) != MXL_RV32;
 #else
 #error un-handled architecture
 #endif
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index ca4c9cc9d1..bce8fe7ebb 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -108,11 +108,6 @@ const char *riscv_cpu_get_trap_name(target_ulong cause, 
bool async)
 }
 }
 
-bool riscv_cpu_is_32bit(CPURISCVState *env)
-{
-return env->misa_mxl == MXL_RV32;
-}
-
 static void set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext)
 {
 env->misa_mxl_max = env->misa_mxl = mxl;
@@ -249,7 +244,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int 
flags)
 #ifndef CONFIG_USER_ONLY
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", 
(target_ulong)env->mstatus);
-if (riscv_cpu_is_32bit(env)) {
+if (riscv_cpu_mxl(env) == MXL_RV32) {
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatush ",
  (target_ulong)(env->mstatus >> 32));
 }
@@ -372,10 +367,16 @@ static void riscv_cpu_reset(DeviceState *dev)
 static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
 {
 RISCVCPU *cpu = RISCV_CPU(s);
-if (riscv_cpu_is_32bit(&cpu->env)) {
+
+switch (riscv_cpu_mxl(&cpu->env)) {
+case MXL_RV32:
 info->print_insn = print_insn_riscv32;
-} else {
+break;
+case MXL_RV64:
 info->print_insn = print_insn_riscv64;
+break;
+default:
+g_assert_not_reached();
 }
 }
 
@@ -631,10 +632,13 @@ static gchar *riscv_gdb_arch_name(CPUState *cs)
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = &cpu->env;
 
-if (riscv_cpu_is_32bit(env)) {
+switch (riscv_cpu_mxl(env)) {
+case MXL_RV32:
 return g_strdup("riscv:rv32");
-} else {
+case MXL_RV64:
 return g_strdup("riscv:rv64");
+default:
+g_assert_not_reached();
 }
 }
 
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 14d1d3cb72..403f54171d 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -152,7 +152,7 @@ bool riscv_cpu_fp_enabled(CPURISCVState *env)
 
 void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
 {
-uint64_t sd = riscv_cpu_is_32bit(env) ? MSTATUS32_SD : MSTATUS64_SD;
+uint64_t sd = riscv_cpu_mxl(env) == MXL_RV32 ? MSTATUS32_SD : MSTATUS64_SD;
 uint64_t mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS |
 MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE |
 MSTATUS64_UXL | sd;
@@ -447,7 +447,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr 
*physical,
 
 if (first_stage == true) {
 if (use_background) {
-if (riscv_cpu_is_32bit(env)) {
+if (riscv_cpu_mxl(env) == MXL_RV32) {
 base = (hwaddr)get_field(env->vsatp, SATP32_PPN) <<

[PATCH v6 13/15] target/riscv: Use gen_shift*_per_ol for RVB, RVI

2021-10-19 Thread Richard Henderson
Most shift instructions require a separate implementation
for RV32 when TARGET_LONG_BITS == 64.

Reviewed-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Signed-off-by: Richard Henderson 
---
 target/riscv/translate.c| 31 +
 target/riscv/insn_trans/trans_rvb.c.inc | 92 ++---
 target/riscv/insn_trans/trans_rvi.c.inc | 26 +++
 3 files changed, 97 insertions(+), 52 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 7286791c0f..0b3da060fd 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -463,6 +463,22 @@ static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift 
*a, DisasExtend ext,
 return true;
 }
 
+static bool gen_shift_imm_fn_per_ol(DisasContext *ctx, arg_shift *a,
+DisasExtend ext,
+void (*f_tl)(TCGv, TCGv, target_long),
+void (*f_32)(TCGv, TCGv, target_long))
+{
+int olen = get_olen(ctx);
+if (olen != TARGET_LONG_BITS) {
+if (olen == 32) {
+f_tl = f_32;
+} else {
+g_assert_not_reached();
+}
+}
+return gen_shift_imm_fn(ctx, a, ext, f_tl);
+}
+
 static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext,
  void (*func)(TCGv, TCGv, TCGv))
 {
@@ -499,6 +515,21 @@ static bool gen_shift(DisasContext *ctx, arg_r *a, 
DisasExtend ext,
 return true;
 }
 
+static bool gen_shift_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext,
+ void (*f_tl)(TCGv, TCGv, TCGv),
+ void (*f_32)(TCGv, TCGv, TCGv))
+{
+int olen = get_olen(ctx);
+if (olen != TARGET_LONG_BITS) {
+if (olen == 32) {
+f_tl = f_32;
+} else {
+g_assert_not_reached();
+}
+}
+return gen_shift(ctx, a, ext, f_tl);
+}
+
 static bool gen_unary(DisasContext *ctx, arg_r2 *a, DisasExtend ext,
   void (*func)(TCGv, TCGv))
 {
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc 
b/target/riscv/insn_trans/trans_rvb.c.inc
index 4eb41756fa..c8d31907c5 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -227,22 +227,70 @@ static bool trans_bexti(DisasContext *ctx, arg_bexti *a)
 return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_bext);
 }
 
+static void gen_rorw(TCGv ret, TCGv arg1, TCGv arg2)
+{
+TCGv_i32 t1 = tcg_temp_new_i32();
+TCGv_i32 t2 = tcg_temp_new_i32();
+
+/* truncate to 32-bits */
+tcg_gen_trunc_tl_i32(t1, arg1);
+tcg_gen_trunc_tl_i32(t2, arg2);
+
+tcg_gen_rotr_i32(t1, t1, t2);
+
+/* sign-extend 64-bits */
+tcg_gen_ext_i32_tl(ret, t1);
+
+tcg_temp_free_i32(t1);
+tcg_temp_free_i32(t2);
+}
+
 static bool trans_ror(DisasContext *ctx, arg_ror *a)
 {
 REQUIRE_ZBB(ctx);
-return gen_shift(ctx, a, EXT_NONE, tcg_gen_rotr_tl);
+return gen_shift_per_ol(ctx, a, EXT_NONE, tcg_gen_rotr_tl, gen_rorw);
+}
+
+static void gen_roriw(TCGv ret, TCGv arg1, target_long shamt)
+{
+TCGv_i32 t1 = tcg_temp_new_i32();
+
+tcg_gen_trunc_tl_i32(t1, arg1);
+tcg_gen_rotri_i32(t1, t1, shamt);
+tcg_gen_ext_i32_tl(ret, t1);
+
+tcg_temp_free_i32(t1);
 }
 
 static bool trans_rori(DisasContext *ctx, arg_rori *a)
 {
 REQUIRE_ZBB(ctx);
-return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_rotri_tl);
+return gen_shift_imm_fn_per_ol(ctx, a, EXT_NONE,
+   tcg_gen_rotri_tl, gen_roriw);
+}
+
+static void gen_rolw(TCGv ret, TCGv arg1, TCGv arg2)
+{
+TCGv_i32 t1 = tcg_temp_new_i32();
+TCGv_i32 t2 = tcg_temp_new_i32();
+
+/* truncate to 32-bits */
+tcg_gen_trunc_tl_i32(t1, arg1);
+tcg_gen_trunc_tl_i32(t2, arg2);
+
+tcg_gen_rotl_i32(t1, t1, t2);
+
+/* sign-extend 64-bits */
+tcg_gen_ext_i32_tl(ret, t1);
+
+tcg_temp_free_i32(t1);
+tcg_temp_free_i32(t2);
 }
 
 static bool trans_rol(DisasContext *ctx, arg_rol *a)
 {
 REQUIRE_ZBB(ctx);
-return gen_shift(ctx, a, EXT_NONE, tcg_gen_rotl_tl);
+return gen_shift_per_ol(ctx, a, EXT_NONE, tcg_gen_rotl_tl, gen_rolw);
 }
 
 static void gen_rev8_32(TCGv ret, TCGv src1)
@@ -352,24 +400,6 @@ static bool trans_cpopw(DisasContext *ctx, arg_cpopw *a)
 return gen_unary(ctx, a, EXT_ZERO, tcg_gen_ctpop_tl);
 }
 
-static void gen_rorw(TCGv ret, TCGv arg1, TCGv arg2)
-{
-TCGv_i32 t1 = tcg_temp_new_i32();
-TCGv_i32 t2 = tcg_temp_new_i32();
-
-/* truncate to 32-bits */
-tcg_gen_trunc_tl_i32(t1, arg1);
-tcg_gen_trunc_tl_i32(t2, arg2);
-
-tcg_gen_rotr_i32(t1, t1, t2);
-
-/* sign-extend 64-bits */
-tcg_gen_ext_i32_tl(ret, t1);
-
-tcg_temp_free_i32(t1);
-tcg_temp_free_i32(t2);
-}
-
 static bool trans_rorw(DisasContext *ctx, arg_rorw *a)
 {
 REQUIRE_64BIT(ctx);
@@ -383,25 +413,7 @@ static bool trans_roriw(DisasContext *ctx, arg_roriw *a)
 REQUIRE_64BIT(ctx);
 R

[PATCH v6 12/15] target/riscv: Use gen_unary_per_ol for RVB

2021-10-19 Thread Richard Henderson
The count zeros instructions require a separate implementation
for RV32 when TARGET_LONG_BITS == 64.

Reviewed-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Signed-off-by: Richard Henderson 
---
 target/riscv/translate.c| 16 
 target/riscv/insn_trans/trans_rvb.c.inc | 33 -
 2 files changed, 32 insertions(+), 17 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 8f5f39d143..7286791c0f 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -511,6 +511,22 @@ static bool gen_unary(DisasContext *ctx, arg_r2 *a, 
DisasExtend ext,
 return true;
 }
 
+static bool gen_unary_per_ol(DisasContext *ctx, arg_r2 *a, DisasExtend ext,
+ void (*f_tl)(TCGv, TCGv),
+ void (*f_32)(TCGv, TCGv))
+{
+int olen = get_olen(ctx);
+
+if (olen != TARGET_LONG_BITS) {
+if (olen == 32) {
+f_tl = f_32;
+} else {
+g_assert_not_reached();
+}
+}
+return gen_unary(ctx, a, ext, f_tl);
+}
+
 static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
 {
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc 
b/target/riscv/insn_trans/trans_rvb.c.inc
index d6f9e9fc83..4eb41756fa 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -47,10 +47,18 @@ static void gen_clz(TCGv ret, TCGv arg1)
 tcg_gen_clzi_tl(ret, arg1, TARGET_LONG_BITS);
 }
 
+static void gen_clzw(TCGv ret, TCGv arg1)
+{
+TCGv t = tcg_temp_new();
+tcg_gen_shli_tl(t, arg1, 32);
+tcg_gen_clzi_tl(ret, t, 32);
+tcg_temp_free(t);
+}
+
 static bool trans_clz(DisasContext *ctx, arg_clz *a)
 {
 REQUIRE_ZBB(ctx);
-return gen_unary(ctx, a, EXT_ZERO, gen_clz);
+return gen_unary_per_ol(ctx, a, EXT_NONE, gen_clz, gen_clzw);
 }
 
 static void gen_ctz(TCGv ret, TCGv arg1)
@@ -58,10 +66,15 @@ static void gen_ctz(TCGv ret, TCGv arg1)
 tcg_gen_ctzi_tl(ret, arg1, TARGET_LONG_BITS);
 }
 
+static void gen_ctzw(TCGv ret, TCGv arg1)
+{
+tcg_gen_ctzi_tl(ret, arg1, 32);
+}
+
 static bool trans_ctz(DisasContext *ctx, arg_ctz *a)
 {
 REQUIRE_ZBB(ctx);
-return gen_unary(ctx, a, EXT_ZERO, gen_ctz);
+return gen_unary_per_ol(ctx, a, EXT_ZERO, gen_ctz, gen_ctzw);
 }
 
 static bool trans_cpop(DisasContext *ctx, arg_cpop *a)
@@ -317,14 +330,6 @@ static bool trans_zext_h_64(DisasContext *ctx, 
arg_zext_h_64 *a)
 return gen_unary(ctx, a, EXT_NONE, tcg_gen_ext16u_tl);
 }
 
-static void gen_clzw(TCGv ret, TCGv arg1)
-{
-TCGv t = tcg_temp_new();
-tcg_gen_shli_tl(t, arg1, 32);
-tcg_gen_clzi_tl(ret, t, 32);
-tcg_temp_free(t);
-}
-
 static bool trans_clzw(DisasContext *ctx, arg_clzw *a)
 {
 REQUIRE_64BIT(ctx);
@@ -332,17 +337,11 @@ static bool trans_clzw(DisasContext *ctx, arg_clzw *a)
 return gen_unary(ctx, a, EXT_NONE, gen_clzw);
 }
 
-static void gen_ctzw(TCGv ret, TCGv arg1)
-{
-tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32));
-tcg_gen_ctzi_tl(ret, ret, 64);
-}
-
 static bool trans_ctzw(DisasContext *ctx, arg_ctzw *a)
 {
 REQUIRE_64BIT(ctx);
 REQUIRE_ZBB(ctx);
-return gen_unary(ctx, a, EXT_NONE, gen_ctzw);
+return gen_unary(ctx, a, EXT_ZERO, gen_ctzw);
 }
 
 static bool trans_cpopw(DisasContext *ctx, arg_cpopw *a)
-- 
2.25.1




[PATCH v6 07/15] target/riscv: Properly check SEW in amo_op

2021-10-19 Thread Richard Henderson
We're currently assuming SEW <= 3, and the "else" from
the SEW == 3 must be less.  Use a switch and explicitly
bound both SEW and SEQ for all cases.

Reviewed-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Signed-off-by: Richard Henderson 
---
 target/riscv/insn_trans/trans_rvv.c.inc | 26 +
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvv.c.inc 
b/target/riscv/insn_trans/trans_rvv.c.inc
index 61fd82d41a..a102c3687e 100644
--- a/target/riscv/insn_trans/trans_rvv.c.inc
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
@@ -704,18 +704,20 @@ static bool amo_op(DisasContext *s, arg_rwdvm *a, uint8_t 
seq)
 gen_helper_exit_atomic(cpu_env);
 s->base.is_jmp = DISAS_NORETURN;
 return true;
-} else {
-if (s->sew == 3) {
-if (!is_32bit(s)) {
-fn = fnsd[seq];
-} else {
-/* Check done in amo_check(). */
-g_assert_not_reached();
-}
-} else {
-assert(seq < ARRAY_SIZE(fnsw));
-fn = fnsw[seq];
-}
+}
+
+switch (s->sew) {
+case 0 ... 2:
+assert(seq < ARRAY_SIZE(fnsw));
+fn = fnsw[seq];
+break;
+case 3:
+/* XLEN check done in amo_check(). */
+assert(seq < ARRAY_SIZE(fnsd));
+fn = fnsd[seq];
+break;
+default:
+g_assert_not_reached();
 }
 
 data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
-- 
2.25.1




[PATCH v6 02/15] target/riscv: Create RISCVMXL enumeration

2021-10-19 Thread Richard Henderson
Move the MXL_RV* defines to enumerators.

Reviewed-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Signed-off-by: Richard Henderson 
---
 target/riscv/cpu_bits.h | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 999187a9ee..e248c6bf6d 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -364,9 +364,11 @@
 #define MISA32_MXL  0xC000
 #define MISA64_MXL  0xC000ULL
 
-#define MXL_RV321
-#define MXL_RV642
-#define MXL_RV128   3
+typedef enum {
+MXL_RV32  = 1,
+MXL_RV64  = 2,
+MXL_RV128 = 3,
+} RISCVMXL;
 
 /* sstatus CSR bits */
 #define SSTATUS_UIE 0x0001
-- 
2.25.1




[PATCH v6 00/15] target/riscv: Rationalize XLEN and operand length

2021-10-19 Thread Richard Henderson
This is a partial patch set attempting to set things in the
right direction for both the UXL and RV128 patch sets.


r~


Changes for v6:
  * Rebase on riscv-to-apply.next.

Changes for v5:
  * Fix cpu_dump, which asserted for -accel qtest.
Instead of filtering CSRs explicitly in cpu_dump,
let the riscv_csr_operations predicate do the job.
This means we won't dump S-mode registers when RVS
is not enabled, much like we currently filter on RVH.

Changes for v4:
  * Use riscv_csrrw_debug for cpu_dump.
This fixes the issue that Alistair pointed out wrt the
MSTATUS.SD bit not being correct in the dump; note that
gdbstub already uses riscv_csrrw_debug, and so did not
have a problem.
  * Align the registers in cpu_dump.

Changes for v3:
  * Fix CONFIG_ typo.
  * Fix ctzw typo.
  * Mark get_xlen unused (clang werror)
  * Compute MSTATUS_SD on demand.

Changes for v2:
  * Set mxl/sxl/uxl at reset.
  * Set sxl/uxl in write_mstatus.


Richard Henderson (15):
  target/riscv: Move cpu_get_tb_cpu_state out of line
  target/riscv: Create RISCVMXL enumeration
  target/riscv: Split misa.mxl and misa.ext
  target/riscv: Replace riscv_cpu_is_32bit with riscv_cpu_mxl
  target/riscv: Add MXL/SXL/UXL to TB_FLAGS
  target/riscv: Use REQUIRE_64BIT in amo_check64
  target/riscv: Properly check SEW in amo_op
  target/riscv: Replace is_32bit with get_xl/get_xlen
  target/riscv: Replace DisasContext.w with DisasContext.ol
  target/riscv: Use gen_arith_per_ol for RVM
  target/riscv: Adjust trans_rev8_32 for riscv64
  target/riscv: Use gen_unary_per_ol for RVB
  target/riscv: Use gen_shift*_per_ol for RVB, RVI
  target/riscv: Use riscv_csrrw_debug for cpu_dump
  target/riscv: Compute mstatus.sd on demand

 target/riscv/cpu.h  |  73 +++--
 target/riscv/cpu_bits.h |   8 +-
 hw/riscv/boot.c |   2 +-
 linux-user/elfload.c|   2 +-
 linux-user/riscv/cpu_loop.c |   2 +-
 semihosting/arm-compat-semi.c   |   2 +-
 target/riscv/cpu.c  | 195 +---
 target/riscv/cpu_helper.c   |  92 ++-
 target/riscv/csr.c  | 104 -
 target/riscv/gdbstub.c  |  10 +-
 target/riscv/machine.c  |  10 +-
 target/riscv/monitor.c  |   4 +-
 target/riscv/translate.c| 174 +++--
 target/riscv/insn_trans/trans_rvb.c.inc | 140 +
 target/riscv/insn_trans/trans_rvi.c.inc |  44 +++---
 target/riscv/insn_trans/trans_rvm.c.inc |  36 -
 target/riscv/insn_trans/trans_rvv.c.inc |  29 ++--
 17 files changed, 576 insertions(+), 351 deletions(-)

-- 
2.25.1




[PATCH v6 14/15] target/riscv: Use riscv_csrrw_debug for cpu_dump

2021-10-19 Thread Richard Henderson
Use the official debug read interface to the csrs,
rather than referencing the env slots directly.
Put the list of csrs to dump into a table.

Reviewed-by: Alistair Francis 
Signed-off-by: Richard Henderson 
---
 target/riscv/cpu.c | 89 +++---
 1 file changed, 45 insertions(+), 44 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index babe271e53..79071bde4e 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -242,51 +242,52 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, 
int flags)
 #endif
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc  ", env->pc);
 #ifndef CONFIG_USER_ONLY
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", 
(target_ulong)env->mstatus);
-if (riscv_cpu_mxl(env) == MXL_RV32) {
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatush ",
- (target_ulong)(env->mstatus >> 32));
+{
+static const int dump_csrs[] = {
+CSR_MHARTID,
+CSR_MSTATUS,
+CSR_MSTATUSH,
+CSR_HSTATUS,
+CSR_VSSTATUS,
+CSR_MIP,
+CSR_MIE,
+CSR_MIDELEG,
+CSR_HIDELEG,
+CSR_MEDELEG,
+CSR_HEDELEG,
+CSR_MTVEC,
+CSR_STVEC,
+CSR_VSTVEC,
+CSR_MEPC,
+CSR_SEPC,
+CSR_VSEPC,
+CSR_MCAUSE,
+CSR_SCAUSE,
+CSR_VSCAUSE,
+CSR_MTVAL,
+CSR_STVAL,
+CSR_HTVAL,
+CSR_MTVAL2,
+CSR_MSCRATCH,
+CSR_SSCRATCH,
+CSR_SATP,
+};
+
+for (int i = 0; i < ARRAY_SIZE(dump_csrs); ++i) {
+int csrno = dump_csrs[i];
+target_ulong val = 0;
+RISCVException res = riscv_csrrw_debug(env, csrno, &val, 0, 0);
+
+/*
+ * Rely on the smode, hmode, etc, predicates within csr.c
+ * to do the filtering of the registers that are present.
+ */
+if (res == RISCV_EXCP_NONE) {
+qemu_fprintf(f, " %-8s " TARGET_FMT_lx "\n",
+ csr_ops[csrno].name, val);
+}
+}
 }
-if (riscv_has_ext(env, RVH)) {
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus);
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus",
- (target_ulong)env->vsstatus);
-}
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip ", env->mip);
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie ", env->mie);
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mideleg ", env->mideleg);
-if (riscv_has_ext(env, RVH)) {
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hideleg ", env->hideleg);
-}
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "medeleg ", env->medeleg);
-if (riscv_has_ext(env, RVH)) {
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hedeleg ", env->hedeleg);
-}
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtvec   ", env->mtvec);
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stvec   ", env->stvec);
-if (riscv_has_ext(env, RVH)) {
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vstvec  ", env->vstvec);
-}
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mepc", env->mepc);
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "sepc", env->sepc);
-if (riscv_has_ext(env, RVH)) {
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsepc   ", env->vsepc);
-}
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mcause  ", env->mcause);
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "scause  ", env->scause);
-if (riscv_has_ext(env, RVH)) {
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vscause ", env->vscause);
-}
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval   ", env->mtval);
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stval   ", env->stval);
-if (riscv_has_ext(env, RVH)) {
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "htval   ", env->htval);
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval2  ", env->mtval2);
-}
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mscratch", env->mscratch);
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "sscratch", env->sscratch);
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "satp", env->satp);
 #endif
 
 for (i = 0; i < 32; i++) {
-- 
2.25.1




[PATCH v6 10/15] target/riscv: Use gen_arith_per_ol for RVM

2021-10-19 Thread Richard Henderson
The multiply high-part instructions require a separate
implementation for RV32 when TARGET_LONG_BITS == 64.

Reviewed-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Signed-off-by: Richard Henderson 
---
 target/riscv/translate.c| 16 +++
 target/riscv/insn_trans/trans_rvm.c.inc | 26 ++---
 2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 172eea3935..8f5f39d143 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -428,6 +428,22 @@ static bool gen_arith(DisasContext *ctx, arg_r *a, 
DisasExtend ext,
 return true;
 }
 
+static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext,
+ void (*f_tl)(TCGv, TCGv, TCGv),
+ void (*f_32)(TCGv, TCGv, TCGv))
+{
+int olen = get_olen(ctx);
+
+if (olen != TARGET_LONG_BITS) {
+if (olen == 32) {
+f_tl = f_32;
+} else {
+g_assert_not_reached();
+}
+}
+return gen_arith(ctx, a, ext, f_tl);
+}
+
 static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext,
  void (*func)(TCGv, TCGv, target_long))
 {
diff --git a/target/riscv/insn_trans/trans_rvm.c.inc 
b/target/riscv/insn_trans/trans_rvm.c.inc
index 9a1fe3c799..2af0e5c139 100644
--- a/target/riscv/insn_trans/trans_rvm.c.inc
+++ b/target/riscv/insn_trans/trans_rvm.c.inc
@@ -33,10 +33,16 @@ static void gen_mulh(TCGv ret, TCGv s1, TCGv s2)
 tcg_temp_free(discard);
 }
 
+static void gen_mulh_w(TCGv ret, TCGv s1, TCGv s2)
+{
+tcg_gen_mul_tl(ret, s1, s2);
+tcg_gen_sari_tl(ret, ret, 32);
+}
+
 static bool trans_mulh(DisasContext *ctx, arg_mulh *a)
 {
 REQUIRE_EXT(ctx, RVM);
-return gen_arith(ctx, a, EXT_NONE, gen_mulh);
+return gen_arith_per_ol(ctx, a, EXT_SIGN, gen_mulh, gen_mulh_w);
 }
 
 static void gen_mulhsu(TCGv ret, TCGv arg1, TCGv arg2)
@@ -54,10 +60,23 @@ static void gen_mulhsu(TCGv ret, TCGv arg1, TCGv arg2)
 tcg_temp_free(rh);
 }
 
+static void gen_mulhsu_w(TCGv ret, TCGv arg1, TCGv arg2)
+{
+TCGv t1 = tcg_temp_new();
+TCGv t2 = tcg_temp_new();
+
+tcg_gen_ext32s_tl(t1, arg1);
+tcg_gen_ext32u_tl(t2, arg2);
+tcg_gen_mul_tl(ret, t1, t2);
+tcg_temp_free(t1);
+tcg_temp_free(t2);
+tcg_gen_sari_tl(ret, ret, 32);
+}
+
 static bool trans_mulhsu(DisasContext *ctx, arg_mulhsu *a)
 {
 REQUIRE_EXT(ctx, RVM);
-return gen_arith(ctx, a, EXT_NONE, gen_mulhsu);
+return gen_arith_per_ol(ctx, a, EXT_NONE, gen_mulhsu, gen_mulhsu_w);
 }
 
 static void gen_mulhu(TCGv ret, TCGv s1, TCGv s2)
@@ -71,7 +90,8 @@ static void gen_mulhu(TCGv ret, TCGv s1, TCGv s2)
 static bool trans_mulhu(DisasContext *ctx, arg_mulhu *a)
 {
 REQUIRE_EXT(ctx, RVM);
-return gen_arith(ctx, a, EXT_NONE, gen_mulhu);
+/* gen_mulh_w works for either sign as input. */
+return gen_arith_per_ol(ctx, a, EXT_ZERO, gen_mulhu, gen_mulh_w);
 }
 
 static void gen_div(TCGv ret, TCGv source1, TCGv source2)
-- 
2.25.1




[PATCH v6 01/15] target/riscv: Move cpu_get_tb_cpu_state out of line

2021-10-19 Thread Richard Henderson
Move the function to cpu_helper.c, as it is large and growing.

Reviewed-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Signed-off-by: Richard Henderson 
---
 target/riscv/cpu.h| 47 ++-
 target/riscv/cpu_helper.c | 46 ++
 2 files changed, 48 insertions(+), 45 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 9e55b2f5b1..7084efc452 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -413,51 +413,8 @@ static inline uint32_t vext_get_vlmax(RISCVCPU *cpu, 
target_ulong vtype)
 return cpu->cfg.vlen >> (sew + 3 - lmul);
 }
 
-static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
-target_ulong *cs_base, uint32_t 
*pflags)
-{
-uint32_t flags = 0;
-
-*pc = env->pc;
-*cs_base = 0;
-
-if (riscv_has_ext(env, RVV)) {
-uint32_t vlmax = vext_get_vlmax(env_archcpu(env), env->vtype);
-bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl);
-flags = FIELD_DP32(flags, TB_FLAGS, VILL,
-FIELD_EX64(env->vtype, VTYPE, VILL));
-flags = FIELD_DP32(flags, TB_FLAGS, SEW,
-FIELD_EX64(env->vtype, VTYPE, VSEW));
-flags = FIELD_DP32(flags, TB_FLAGS, LMUL,
-FIELD_EX64(env->vtype, VTYPE, VLMUL));
-flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);
-} else {
-flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
-}
-
-#ifdef CONFIG_USER_ONLY
-flags |= TB_FLAGS_MSTATUS_FS;
-#else
-flags |= cpu_mmu_index(env, 0);
-if (riscv_cpu_fp_enabled(env)) {
-flags |= env->mstatus & MSTATUS_FS;
-}
-
-if (riscv_has_ext(env, RVH)) {
-if (env->priv == PRV_M ||
-(env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
-(env->priv == PRV_U && !riscv_cpu_virt_enabled(env) &&
-get_field(env->hstatus, HSTATUS_HU))) {
-flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1);
-}
-
-flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_FS,
-   get_field(env->mstatus_hs, MSTATUS_FS));
-}
-#endif
-
-*pflags = flags;
-}
+void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
+  target_ulong *cs_base, uint32_t *pflags);
 
 RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
target_ulong *ret_value,
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index d41d5cd27c..14d1d3cb72 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -35,6 +35,52 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
 #endif
 }
 
+void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
+  target_ulong *cs_base, uint32_t *pflags)
+{
+uint32_t flags = 0;
+
+*pc = env->pc;
+*cs_base = 0;
+
+if (riscv_has_ext(env, RVV)) {
+uint32_t vlmax = vext_get_vlmax(env_archcpu(env), env->vtype);
+bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl);
+flags = FIELD_DP32(flags, TB_FLAGS, VILL,
+FIELD_EX64(env->vtype, VTYPE, VILL));
+flags = FIELD_DP32(flags, TB_FLAGS, SEW,
+FIELD_EX64(env->vtype, VTYPE, VSEW));
+flags = FIELD_DP32(flags, TB_FLAGS, LMUL,
+FIELD_EX64(env->vtype, VTYPE, VLMUL));
+flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);
+} else {
+flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
+}
+
+#ifdef CONFIG_USER_ONLY
+flags |= TB_FLAGS_MSTATUS_FS;
+#else
+flags |= cpu_mmu_index(env, 0);
+if (riscv_cpu_fp_enabled(env)) {
+flags |= env->mstatus & MSTATUS_FS;
+}
+
+if (riscv_has_ext(env, RVH)) {
+if (env->priv == PRV_M ||
+(env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
+(env->priv == PRV_U && !riscv_cpu_virt_enabled(env) &&
+get_field(env->hstatus, HSTATUS_HU))) {
+flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1);
+}
+
+flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_FS,
+   get_field(env->mstatus_hs, MSTATUS_FS));
+}
+#endif
+
+*pflags = flags;
+}
+
 #ifndef CONFIG_USER_ONLY
 static int riscv_cpu_local_irq_pending(CPURISCVState *env)
 {
-- 
2.25.1




[PATCH v6 08/15] target/riscv: Replace is_32bit with get_xl/get_xlen

2021-10-19 Thread Richard Henderson
In preparation for RV128, replace a simple predicate
with a more versatile test.

Reviewed-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Signed-off-by: Richard Henderson 
---
 target/riscv/translate.c | 33 ++---
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 7e7bb67d15..2624d65fc2 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -91,16 +91,19 @@ static inline bool has_ext(DisasContext *ctx, uint32_t ext)
 }
 
 #ifdef TARGET_RISCV32
-# define is_32bit(ctx)  true
+#define get_xl(ctx)MXL_RV32
 #elif defined(CONFIG_USER_ONLY)
-# define is_32bit(ctx)  false
+#define get_xl(ctx)MXL_RV64
 #else
-static inline bool is_32bit(DisasContext *ctx)
-{
-return ctx->xl == MXL_RV32;
-}
+#define get_xl(ctx)((ctx)->xl)
 #endif
 
+/* The word size for this machine mode. */
+static inline int __attribute__((unused)) get_xlen(DisasContext *ctx)
+{
+return 16 << get_xl(ctx);
+}
+
 /* The word size for this operation. */
 static inline int oper_len(DisasContext *ctx)
 {
@@ -282,7 +285,7 @@ static void gen_jal(DisasContext *ctx, int rd, target_ulong 
imm)
 static void mark_fs_dirty(DisasContext *ctx)
 {
 TCGv tmp;
-target_ulong sd = is_32bit(ctx) ? MSTATUS32_SD : MSTATUS64_SD;
+target_ulong sd = get_xl(ctx) == MXL_RV32 ? MSTATUS32_SD : MSTATUS64_SD;
 
 if (ctx->mstatus_fs != MSTATUS_FS) {
 /* Remember the state change for the rest of the TB. */
@@ -341,16 +344,16 @@ EX_SH(12)
 }  \
 } while (0)
 
-#define REQUIRE_32BIT(ctx) do { \
-if (!is_32bit(ctx)) {   \
-return false;   \
-}   \
+#define REQUIRE_32BIT(ctx) do {\
+if (get_xl(ctx) != MXL_RV32) { \
+return false;  \
+}  \
 } while (0)
 
-#define REQUIRE_64BIT(ctx) do { \
-if (is_32bit(ctx)) {\
-return false;   \
-}   \
+#define REQUIRE_64BIT(ctx) do {\
+if (get_xl(ctx) < MXL_RV64) {  \
+return false;  \
+}  \
 } while (0)
 
 static int ex_rvc_register(DisasContext *ctx, int reg)
-- 
2.25.1




[PATCH v6 11/15] target/riscv: Adjust trans_rev8_32 for riscv64

2021-10-19 Thread Richard Henderson
When target_long is 64-bit, we still want a 32-bit bswap for rev8.
Since this opcode is specific to RV32, we need not conditionalize.

Acked-by: Alistair Francis 
Reviewed-by: LIU Zhiwei 
Signed-off-by: Richard Henderson 
---
 target/riscv/insn_trans/trans_rvb.c.inc | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/target/riscv/insn_trans/trans_rvb.c.inc 
b/target/riscv/insn_trans/trans_rvb.c.inc
index 9ef8ab94ad..d6f9e9fc83 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -232,11 +232,16 @@ static bool trans_rol(DisasContext *ctx, arg_rol *a)
 return gen_shift(ctx, a, EXT_NONE, tcg_gen_rotl_tl);
 }
 
+static void gen_rev8_32(TCGv ret, TCGv src1)
+{
+tcg_gen_bswap32_tl(ret, src1, TCG_BSWAP_OS);
+}
+
 static bool trans_rev8_32(DisasContext *ctx, arg_rev8_32 *a)
 {
 REQUIRE_32BIT(ctx);
 REQUIRE_ZBB(ctx);
-return gen_unary(ctx, a, EXT_NONE, tcg_gen_bswap_tl);
+return gen_unary(ctx, a, EXT_NONE, gen_rev8_32);
 }
 
 static bool trans_rev8_64(DisasContext *ctx, arg_rev8_64 *a)
-- 
2.25.1




[PATCH v6 09/15] target/riscv: Replace DisasContext.w with DisasContext.ol

2021-10-19 Thread Richard Henderson
In preparation for RV128, consider more than just "w" for
operand size modification.  This will be used for the "d"
insns from RV128 as well.

Rename oper_len to get_olen to better match get_xlen.

Reviewed-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Signed-off-by: Richard Henderson 
---
 target/riscv/translate.c| 71 -
 target/riscv/insn_trans/trans_rvb.c.inc |  8 +--
 target/riscv/insn_trans/trans_rvi.c.inc | 18 +++
 target/riscv/insn_trans/trans_rvm.c.inc | 10 ++--
 4 files changed, 63 insertions(+), 44 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 2624d65fc2..172eea3935 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -67,7 +67,7 @@ typedef struct DisasContext {
to any system register, which includes CSR_FRM, so we do not have
to reset this known value.  */
 int frm;
-bool w;
+RISCVMXL ol;
 bool virt_enabled;
 bool ext_ifencei;
 bool hlsx;
@@ -104,12 +104,17 @@ static inline int __attribute__((unused)) 
get_xlen(DisasContext *ctx)
 return 16 << get_xl(ctx);
 }
 
-/* The word size for this operation. */
-static inline int oper_len(DisasContext *ctx)
-{
-return ctx->w ? 32 : TARGET_LONG_BITS;
-}
+/* The operation length, as opposed to the xlen. */
+#ifdef TARGET_RISCV32
+#define get_ol(ctx)MXL_RV32
+#else
+#define get_ol(ctx)((ctx)->ol)
+#endif
 
+static inline int get_olen(DisasContext *ctx)
+{
+return 16 << get_ol(ctx);
+}
 
 /*
  * RISC-V requires NaN-boxing of narrower width floating point values.
@@ -222,24 +227,34 @@ static TCGv get_gpr(DisasContext *ctx, int reg_num, 
DisasExtend ext)
 return ctx->zero;
 }
 
-switch (ctx->w ? ext : EXT_NONE) {
-case EXT_NONE:
-return cpu_gpr[reg_num];
-case EXT_SIGN:
-t = temp_new(ctx);
-tcg_gen_ext32s_tl(t, cpu_gpr[reg_num]);
-return t;
-case EXT_ZERO:
-t = temp_new(ctx);
-tcg_gen_ext32u_tl(t, cpu_gpr[reg_num]);
-return t;
+switch (get_ol(ctx)) {
+case MXL_RV32:
+switch (ext) {
+case EXT_NONE:
+break;
+case EXT_SIGN:
+t = temp_new(ctx);
+tcg_gen_ext32s_tl(t, cpu_gpr[reg_num]);
+return t;
+case EXT_ZERO:
+t = temp_new(ctx);
+tcg_gen_ext32u_tl(t, cpu_gpr[reg_num]);
+return t;
+default:
+g_assert_not_reached();
+}
+break;
+case MXL_RV64:
+break;
+default:
+g_assert_not_reached();
 }
-g_assert_not_reached();
+return cpu_gpr[reg_num];
 }
 
 static TCGv dest_gpr(DisasContext *ctx, int reg_num)
 {
-if (reg_num == 0 || ctx->w) {
+if (reg_num == 0 || get_olen(ctx) < TARGET_LONG_BITS) {
 return temp_new(ctx);
 }
 return cpu_gpr[reg_num];
@@ -248,10 +263,15 @@ static TCGv dest_gpr(DisasContext *ctx, int reg_num)
 static void gen_set_gpr(DisasContext *ctx, int reg_num, TCGv t)
 {
 if (reg_num != 0) {
-if (ctx->w) {
+switch (get_ol(ctx)) {
+case MXL_RV32:
 tcg_gen_ext32s_tl(cpu_gpr[reg_num], t);
-} else {
+break;
+case MXL_RV64:
 tcg_gen_mov_tl(cpu_gpr[reg_num], t);
+break;
+default:
+g_assert_not_reached();
 }
 }
 }
@@ -412,7 +432,7 @@ static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift 
*a, DisasExtend ext,
  void (*func)(TCGv, TCGv, target_long))
 {
 TCGv dest, src1;
-int max_len = oper_len(ctx);
+int max_len = get_olen(ctx);
 
 if (a->shamt >= max_len) {
 return false;
@@ -431,7 +451,7 @@ static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift 
*a, DisasExtend ext,
  void (*func)(TCGv, TCGv, TCGv))
 {
 TCGv dest, src1, src2;
-int max_len = oper_len(ctx);
+int max_len = get_olen(ctx);
 
 if (a->shamt >= max_len) {
 return false;
@@ -455,7 +475,7 @@ static bool gen_shift(DisasContext *ctx, arg_r *a, 
DisasExtend ext,
 TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
 TCGv ext2 = tcg_temp_new();
 
-tcg_gen_andi_tl(ext2, src2, oper_len(ctx) - 1);
+tcg_gen_andi_tl(ext2, src2, get_olen(ctx) - 1);
 func(dest, src1, ext2);
 
 gen_set_gpr(ctx, a->rd, dest);
@@ -555,7 +575,6 @@ static void riscv_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
 ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL);
 ctx->cs = cs;
-ctx->w = false;
 ctx->ntemp = 0;
 memset(ctx->temp, 0, sizeof(ctx->temp));
 
@@ -579,9 +598,9 @@ static void riscv_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cpu)
 CPURISCVState *env = cpu->env_ptr;
 uint16_t opcode16 = translator_lduw(env, &ctx->base, ctx->base.pc_next);
 
+ctx->ol = ctx->xl;
 decode_opc(env, ctx, opcode16);
 ctx->bas

Re: [PATCH V3] net/colo: check vnet_hdr_support flag when using virtio-net

2021-10-19 Thread Jason Wang
On Wed, Oct 20, 2021 at 10:53 AM Zhang, Chen  wrote:
>
>
>
> > -Original Message-
> > From: Jason Wang 
> > Sent: Tuesday, October 19, 2021 3:39 PM
> > To: Zhang, Chen ; Eric Blake ;
> > Markus Armbruster 
> > Cc: qemu-dev ; Li Zhijian
> > ; Lukas Straub ; Tao Xu
> > 
> > Subject: Re: [PATCH V3] net/colo: check vnet_hdr_support flag when using
> > virtio-net
> >
> >
> > 在 2021/9/18 上午10:04, Zhang Chen 写道:
> > > When COLO use only one vnet_hdr_support parameter between COLO
> > network
> > > filter(filter-mirror, filter-redirector or filter-rewriter and
> > > colo-compare, packet will not be parsed correctly. Acquire network
> > > driver related to COLO, if it is nirtio-net,
> >
> >
> > Typo.
>
> Oh~ will fix in next version.
>
> >
> >
> > >   check vnet_hdr_support flag of COLO network filter and colo-compare.
> > >
> > > Signed-off-by: Tao Xu 
> > > Signed-off-by: Zhang Chen 
> > > ---
> > >
> > > Changelog:
> > > v3:
> > >  Fix some typos.
> > >  Rebased for Qemu 6.2.
> > >
> > > v2:
> > >  Detect virtio-net driver and apply vnet_hdr_support
> > >  automatically. (Jason)
> > > ---
> > >   net/colo-compare.c| 57
> > +++
> > >   net/colo.c| 20 +++
> > >   net/colo.h|  4 +++
> > >   net/filter-mirror.c   | 21 
> > >   net/filter-rewriter.c | 10 
> > >   qapi/qom.json |  6 +
> > >   qemu-options.hx   |  6 +++--
> > >   7 files changed, 122 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/net/colo-compare.c b/net/colo-compare.c index
> > > b100e7b51f..870bd05a41 100644
> > > --- a/net/colo-compare.c
> > > +++ b/net/colo-compare.c
> > > @@ -110,6 +110,7 @@ struct CompareState {
> > >   char *sec_indev;
> > >   char *outdev;
> > >   char *notify_dev;
> > > +char *netdev;
> > >   CharBackend chr_pri_in;
> > >   CharBackend chr_sec_in;
> > >   CharBackend chr_out;
> > > @@ -838,6 +839,28 @@ static int compare_chr_can_read(void *opaque)
> > >   return COMPARE_READ_LEN_MAX;
> > >   }
> > >
> > > +static int colo_set_default_netdev(void *opaque, QemuOpts *opts,
> > > +Error **errp) {
> > > +const char *colo_obj_type, *netdev_from_filter;
> > > +char **netdev = (char **)opaque;
> > > +
> > > +colo_obj_type = qemu_opt_get(opts, "qom-type");
> > > +
> > > +if (colo_obj_type &&
> > > +(strcmp(colo_obj_type, "filter-mirror") == 0 ||
> > > + strcmp(colo_obj_type, "filter-redirector") == 0 ||
> > > + strcmp(colo_obj_type, "filter-rewriter") == 0)) {
> > > +netdev_from_filter = qemu_opt_get(opts, "netdev");
> > > +if (*netdev == NULL) {
> > > +*netdev = g_strdup(netdev_from_filter);
> > > +} else if (strcmp(*netdev, netdev_from_filter) != 0) {
> > > +warn_report("%s is using a different netdev from other COLO "
> > > +"component", colo_obj_type);
> > > +}
> > > +}
> > > +return 0;
> > > +}
> > > +
> > >   /*
> > >* Called from the main thread on the primary for packets
> > >* arriving over the socket from the primary.
> > > @@ -1050,6 +1073,21 @@ static void compare_set_vnet_hdr(Object *obj,
> > >   s->vnet_hdr = value;
> > >   }
> > >
> > > +static char *compare_get_netdev(Object *obj, Error **errp) {
> > > +CompareState *s = COLO_COMPARE(obj);
> > > +
> > > +return g_strdup(s->netdev);
> > > +}
> > > +
> > > +static void compare_set_netdev(Object *obj, const char *value, Error
> > > +**errp) {
> > > +CompareState *s = COLO_COMPARE(obj);
> > > +
> > > +g_free(s->netdev);
> > > +s->netdev = g_strdup(value);
> > > +}
> > > +
> > >   static char *compare_get_notify_dev(Object *obj, Error **errp)
> > >   {
> > >   CompareState *s = COLO_COMPARE(obj); @@ -1274,6 +1312,12 @@
> > > static void colo_compare_complete(UserCreatable *uc, Error **errp)
> > >   max_queue_size = MAX_QUEUE_SIZE;
> > >   }
> > >
> > > +if (!s->netdev) {
> > > +/* Set default netdev as the first colo netfilter found */
> > > +qemu_opts_foreach(qemu_find_opts("object"),
> > > +  colo_set_default_netdev, &s->netdev, NULL);
> > > +}
> > > +
> > >   if (find_and_check_chardev(&chr, s->pri_indev, errp) ||
> > >   !qemu_chr_fe_init(&s->chr_pri_in, chr, errp)) {
> > >   return;
> > > @@ -1289,6 +1333,16 @@ static void
> > colo_compare_complete(UserCreatable *uc, Error **errp)
> > >   return;
> > >   }
> > >
> > > +if (!s->vnet_hdr &&
> > > +qemu_opts_foreach(qemu_find_opts("device"),
> > > +  vnet_driver_check, s->netdev, NULL)) {
> > > +/*
> > > + * colo compare needs 'vnet_hdr_support' when it works on 
> > > virtio-net,
> > > + * add 'vnet_hdr_support' automatically
> > > + */
> > > +s->vnet_hdr = true;
> > > +}
> > > +
> > >   net_socket_rs_init(&

[PATCH v6 03/15] target/riscv: Split misa.mxl and misa.ext

2021-10-19 Thread Richard Henderson
The hw representation of misa.mxl is at the high bits of the
misa csr.  Representing this in the same way inside QEMU
results in overly complex code trying to check that field.

Reviewed-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Signed-off-by: Richard Henderson 
---
 target/riscv/cpu.h  | 15 +++
 linux-user/elfload.c|  2 +-
 linux-user/riscv/cpu_loop.c |  2 +-
 target/riscv/cpu.c  | 78 +
 target/riscv/csr.c  | 44 ++---
 target/riscv/gdbstub.c  |  8 ++--
 target/riscv/machine.c  | 10 +++--
 target/riscv/translate.c| 10 +++--
 8 files changed, 100 insertions(+), 69 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 7084efc452..e708fcc168 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -25,6 +25,7 @@
 #include "exec/cpu-defs.h"
 #include "fpu/softfloat-types.h"
 #include "qom/object.h"
+#include "cpu_bits.h"
 
 #define TCG_GUEST_DEFAULT_MO 0
 
@@ -51,9 +52,6 @@
 # define TYPE_RISCV_CPU_BASETYPE_RISCV_CPU_BASE64
 #endif
 
-#define RV32 ((target_ulong)1 << (TARGET_LONG_BITS - 2))
-#define RV64 ((target_ulong)2 << (TARGET_LONG_BITS - 2))
-
 #define RV(x) ((target_ulong)1 << (x - 'A'))
 
 #define RVI RV('I')
@@ -133,8 +131,12 @@ struct CPURISCVState {
 target_ulong priv_ver;
 target_ulong bext_ver;
 target_ulong vext_ver;
-target_ulong misa;
-target_ulong misa_mask;
+
+/* RISCVMXL, but uint32_t for vmstate migration */
+uint32_t misa_mxl;  /* current mxl */
+uint32_t misa_mxl_max;  /* max mxl for this cpu */
+uint32_t misa_ext;  /* current extensions */
+uint32_t misa_ext_mask; /* max ext for this cpu */
 
 uint32_t features;
 
@@ -313,7 +315,7 @@ struct RISCVCPU {
 
 static inline int riscv_has_ext(CPURISCVState *env, target_ulong ext)
 {
-return (env->misa & ext) != 0;
+return (env->misa_ext & ext) != 0;
 }
 
 static inline bool riscv_feature(CPURISCVState *env, int feature)
@@ -322,7 +324,6 @@ static inline bool riscv_feature(CPURISCVState *env, int 
feature)
 }
 
 #include "cpu_user.h"
-#include "cpu_bits.h"
 
 extern const char * const riscv_int_regnames[];
 extern const char * const riscv_fpr_regnames[];
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 2404d482ba..214c1aa40d 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1448,7 +1448,7 @@ static uint32_t get_elf_hwcap(void)
 uint32_t mask = MISA_BIT('I') | MISA_BIT('M') | MISA_BIT('A')
 | MISA_BIT('F') | MISA_BIT('D') | MISA_BIT('C');
 
-return cpu->env.misa & mask;
+return cpu->env.misa_ext & mask;
 #undef MISA_BIT
 }
 
diff --git a/linux-user/riscv/cpu_loop.c b/linux-user/riscv/cpu_loop.c
index 9859a366e4..e5bb6d908a 100644
--- a/linux-user/riscv/cpu_loop.c
+++ b/linux-user/riscv/cpu_loop.c
@@ -133,7 +133,7 @@ void target_cpu_copy_regs(CPUArchState *env, struct 
target_pt_regs *regs)
 env->gpr[xSP] = regs->sp;
 env->elf_flags = info->elf_flags;
 
-if ((env->misa & RVE) && !(env->elf_flags & EF_RISCV_RVE)) {
+if ((env->misa_ext & RVE) && !(env->elf_flags & EF_RISCV_RVE)) {
 error_report("Incompatible ELF: RVE cpu requires RVE ABI binary");
 exit(EXIT_FAILURE);
 }
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 660f9ce131..ca4c9cc9d1 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -110,16 +110,13 @@ const char *riscv_cpu_get_trap_name(target_ulong cause, 
bool async)
 
 bool riscv_cpu_is_32bit(CPURISCVState *env)
 {
-if (env->misa & RV64) {
-return false;
-}
-
-return true;
+return env->misa_mxl == MXL_RV32;
 }
 
-static void set_misa(CPURISCVState *env, target_ulong misa)
+static void set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext)
 {
-env->misa_mask = env->misa = misa;
+env->misa_mxl_max = env->misa_mxl = mxl;
+env->misa_ext_mask = env->misa_ext = ext;
 }
 
 static void set_priv_version(CPURISCVState *env, int priv_ver)
@@ -148,9 +145,9 @@ static void riscv_any_cpu_init(Object *obj)
 {
 CPURISCVState *env = &RISCV_CPU(obj)->env;
 #if defined(TARGET_RISCV32)
-set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVU);
+set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
 #elif defined(TARGET_RISCV64)
-set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVU);
+set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
 #endif
 set_priv_version(env, PRIV_VERSION_1_11_0);
 }
@@ -160,20 +157,20 @@ static void rv64_base_cpu_init(Object *obj)
 {
 CPURISCVState *env = &RISCV_CPU(obj)->env;
 /* We set this in the realise function */
-set_misa(env, RV64);
+set_misa(env, MXL_RV64, 0);
 }
 
 static void rv64_sifive_u_cpu_init(Object *obj)
 {
 CPURISCVState *env = &RISCV_CPU(obj)->env;
-set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
+set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RV

[PATCH v6 06/15] target/riscv: Use REQUIRE_64BIT in amo_check64

2021-10-19 Thread Richard Henderson
Use the same REQUIRE_64BIT check that we use elsewhere,
rather than open-coding the use of is_32bit.

Reviewed-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Signed-off-by: Richard Henderson 
---
 target/riscv/insn_trans/trans_rvv.c.inc | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/target/riscv/insn_trans/trans_rvv.c.inc 
b/target/riscv/insn_trans/trans_rvv.c.inc
index f730bd68d1..61fd82d41a 100644
--- a/target/riscv/insn_trans/trans_rvv.c.inc
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
@@ -743,7 +743,8 @@ static bool amo_check(DisasContext *s, arg_rwdvm* a)
 
 static bool amo_check64(DisasContext *s, arg_rwdvm* a)
 {
-return !is_32bit(s) && amo_check(s, a);
+REQUIRE_64BIT(s);
+return amo_check(s, a);
 }
 
 GEN_VEXT_TRANS(vamoswapw_v, 0, rwdvm, amo_op, amo_check)
-- 
2.25.1




[PATCH v6 05/15] target/riscv: Add MXL/SXL/UXL to TB_FLAGS

2021-10-19 Thread Richard Henderson
Begin adding support for switching XLEN at runtime.  Extract the
effective XLEN from MISA and MSTATUS and store for use during translation.

Reviewed-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Signed-off-by: Richard Henderson 
---
 target/riscv/cpu.h|  2 ++
 target/riscv/cpu.c|  8 
 target/riscv/cpu_helper.c | 33 +
 target/riscv/csr.c|  3 +++
 target/riscv/translate.c  |  2 +-
 5 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index d0e82135a9..c24bc9a039 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -395,6 +395,8 @@ FIELD(TB_FLAGS, VILL, 8, 1)
 /* Is a Hypervisor instruction load/store allowed? */
 FIELD(TB_FLAGS, HLSX, 9, 1)
 FIELD(TB_FLAGS, MSTATUS_HS_FS, 10, 2)
+/* The combination of MXL/SXL/UXL that applies to the current cpu mode. */
+FIELD(TB_FLAGS, XL, 12, 2)
 
 #ifdef TARGET_RISCV32
 #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index bce8fe7ebb..babe271e53 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -355,6 +355,14 @@ static void riscv_cpu_reset(DeviceState *dev)
 env->misa_mxl = env->misa_mxl_max;
 env->priv = PRV_M;
 env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
+if (env->misa_mxl > MXL_RV32) {
+/*
+ * The reset status of SXL/UXL is undefined, but mstatus is WARL
+ * and we must ensure that the value after init is valid for read.
+ */
+env->mstatus = set_field(env->mstatus, MSTATUS64_SXL, env->misa_mxl);
+env->mstatus = set_field(env->mstatus, MSTATUS64_UXL, env->misa_mxl);
+}
 env->mcause = 0;
 env->pc = env->resetvec;
 env->two_stage_lookup = false;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 403f54171d..429afd1f48 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -35,6 +35,37 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
 #endif
 }
 
+static RISCVMXL cpu_get_xl(CPURISCVState *env)
+{
+#if defined(TARGET_RISCV32)
+return MXL_RV32;
+#elif defined(CONFIG_USER_ONLY)
+return MXL_RV64;
+#else
+RISCVMXL xl = riscv_cpu_mxl(env);
+
+/*
+ * When emulating a 32-bit-only cpu, use RV32.
+ * When emulating a 64-bit cpu, and MXL has been reduced to RV32,
+ * MSTATUSH doesn't have UXL/SXL, therefore XLEN cannot be widened
+ * back to RV64 for lower privs.
+ */
+if (xl != MXL_RV32) {
+switch (env->priv) {
+case PRV_M:
+break;
+case PRV_U:
+xl = get_field(env->mstatus, MSTATUS64_UXL);
+break;
+default: /* PRV_S | PRV_H */
+xl = get_field(env->mstatus, MSTATUS64_SXL);
+break;
+}
+}
+return xl;
+#endif
+}
+
 void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
   target_ulong *cs_base, uint32_t *pflags)
 {
@@ -78,6 +109,8 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong 
*pc,
 }
 #endif
 
+flags = FIELD_DP32(flags, TB_FLAGS, XL, cpu_get_xl(env));
+
 *pflags = flags;
 }
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 9c0753bc8b..c4a479ddd2 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -526,6 +526,9 @@ static RISCVException write_mstatus(CPURISCVState *env, int 
csrno,
 mstatus = set_field(mstatus, MSTATUS32_SD, dirty);
 } else {
 mstatus = set_field(mstatus, MSTATUS64_SD, dirty);
+/* SXL and UXL fields are for now read only */
+mstatus = set_field(mstatus, MSTATUS64_SXL, MXL_RV64);
+mstatus = set_field(mstatus, MSTATUS64_UXL, MXL_RV64);
 }
 env->mstatus = mstatus;
 
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 422f8ab8d0..7e7bb67d15 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -539,7 +539,6 @@ static void riscv_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 #else
 ctx->virt_enabled = false;
 #endif
-ctx->xl = env->misa_mxl;
 ctx->misa_ext = env->misa_ext;
 ctx->frm = -1;  /* unknown rounding mode */
 ctx->ext_ifencei = cpu->cfg.ext_ifencei;
@@ -551,6 +550,7 @@ static void riscv_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 ctx->lmul = FIELD_EX32(tb_flags, TB_FLAGS, LMUL);
 ctx->mlen = 1 << (ctx->sew  + 3 - ctx->lmul);
 ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
+ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL);
 ctx->cs = cs;
 ctx->w = false;
 ctx->ntemp = 0;
-- 
2.25.1




[PATCH v4 6/8] target/riscv: zfh: add Zfh cpu property

2021-10-19 Thread frank . chang
From: Frank Chang 

Signed-off-by: Frank Chang 
---
 target/riscv/cpu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1d69d1887e6..8c579dc297b 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -601,6 +601,7 @@ static Property riscv_cpu_properties[] = {
 DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true),
 DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
 DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
+DEFINE_PROP_BOOL("Zfh", RISCVCPU, cfg.ext_zfh, false),
 DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec),
 DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec),
 DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
-- 
2.25.1




[PATCH v4 8/8] target/riscv: zfh: add Zfhmin cpu property

2021-10-19 Thread frank . chang
From: Frank Chang 

Signed-off-by: Frank Chang 
---
 target/riscv/cpu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 8c579dc297b..4c0e6532164 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -602,6 +602,7 @@ static Property riscv_cpu_properties[] = {
 DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
 DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
 DEFINE_PROP_BOOL("Zfh", RISCVCPU, cfg.ext_zfh, false),
+DEFINE_PROP_BOOL("Zfhmin", RISCVCPU, cfg.ext_zfhmin, false),
 DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec),
 DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec),
 DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
-- 
2.25.1




[PATCH v4 3/8] target/riscv: zfh: half-precision convert and move

2021-10-19 Thread frank . chang
From: Kito Cheng 

Signed-off-by: Kito Cheng 
Signed-off-by: Chih-Min Chao 
Signed-off-by: Frank Chang 
Reviewed-by: Richard Henderson 
Acked-by: Alistair Francis 
---
 target/riscv/fpu_helper.c |  67 +
 target/riscv/helper.h |  12 +
 target/riscv/insn32.decode|  19 ++
 target/riscv/insn_trans/trans_rvzfh.c.inc | 288 ++
 target/riscv/translate.c  |  10 +
 5 files changed, 396 insertions(+)

diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c
index 20bb89ad14f..2ed9b03193c 100644
--- a/target/riscv/fpu_helper.c
+++ b/target/riscv/fpu_helper.c
@@ -460,3 +460,70 @@ uint64_t helper_fsqrt_h(CPURISCVState *env, uint64_t rs1)
 float16 frs1 = check_nanbox_h(rs1);
 return nanbox_h(float16_sqrt(frs1, &env->fp_status));
 }
+
+target_ulong helper_fcvt_w_h(CPURISCVState *env, uint64_t rs1)
+{
+float16 frs1 = check_nanbox_h(rs1);
+return float16_to_int32(frs1, &env->fp_status);
+}
+
+target_ulong helper_fcvt_wu_h(CPURISCVState *env, uint64_t rs1)
+{
+float16 frs1 = check_nanbox_h(rs1);
+return (int32_t)float16_to_uint32(frs1, &env->fp_status);
+}
+
+target_ulong helper_fcvt_l_h(CPURISCVState *env, uint64_t rs1)
+{
+float16 frs1 = check_nanbox_h(rs1);
+return float16_to_int64(frs1, &env->fp_status);
+}
+
+target_ulong helper_fcvt_lu_h(CPURISCVState *env, uint64_t rs1)
+{
+float16 frs1 = check_nanbox_h(rs1);
+return float16_to_uint64(frs1, &env->fp_status);
+}
+
+uint64_t helper_fcvt_h_w(CPURISCVState *env, target_ulong rs1)
+{
+return nanbox_h(int32_to_float16((int32_t)rs1, &env->fp_status));
+}
+
+uint64_t helper_fcvt_h_wu(CPURISCVState *env, target_ulong rs1)
+{
+return nanbox_h(uint32_to_float16((uint32_t)rs1, &env->fp_status));
+}
+
+uint64_t helper_fcvt_h_l(CPURISCVState *env, target_ulong rs1)
+{
+return nanbox_h(int64_to_float16(rs1, &env->fp_status));
+}
+
+uint64_t helper_fcvt_h_lu(CPURISCVState *env, target_ulong rs1)
+{
+return nanbox_h(uint64_to_float16(rs1, &env->fp_status));
+}
+
+uint64_t helper_fcvt_h_s(CPURISCVState *env, uint64_t rs1)
+{
+float32 frs1 = check_nanbox_s(rs1);
+return nanbox_h(float32_to_float16(frs1, true, &env->fp_status));
+}
+
+uint64_t helper_fcvt_s_h(CPURISCVState *env, uint64_t rs1)
+{
+float16 frs1 = check_nanbox_h(rs1);
+return nanbox_s(float16_to_float32(frs1, true, &env->fp_status));
+}
+
+uint64_t helper_fcvt_h_d(CPURISCVState *env, uint64_t rs1)
+{
+return nanbox_h(float64_to_float16(rs1, true, &env->fp_status));
+}
+
+uint64_t helper_fcvt_d_h(CPURISCVState *env, uint64_t rs1)
+{
+float16 frs1 = check_nanbox_h(rs1);
+return float16_to_float64(frs1, true, &env->fp_status);
+}
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index c6c0323fafc..b50672d1684 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -74,6 +74,18 @@ DEF_HELPER_FLAGS_3(fdiv_h, TCG_CALL_NO_RWG, i64, env, i64, 
i64)
 DEF_HELPER_FLAGS_3(fmin_h, TCG_CALL_NO_RWG, i64, env, i64, i64)
 DEF_HELPER_FLAGS_3(fmax_h, TCG_CALL_NO_RWG, i64, env, i64, i64)
 DEF_HELPER_FLAGS_2(fsqrt_h, TCG_CALL_NO_RWG, i64, env, i64)
+DEF_HELPER_FLAGS_2(fcvt_s_h, TCG_CALL_NO_RWG, i64, env, i64)
+DEF_HELPER_FLAGS_2(fcvt_h_s, TCG_CALL_NO_RWG, i64, env, i64)
+DEF_HELPER_FLAGS_2(fcvt_d_h, TCG_CALL_NO_RWG, i64, env, i64)
+DEF_HELPER_FLAGS_2(fcvt_h_d, TCG_CALL_NO_RWG, i64, env, i64)
+DEF_HELPER_FLAGS_2(fcvt_w_h, TCG_CALL_NO_RWG, tl, env, i64)
+DEF_HELPER_FLAGS_2(fcvt_wu_h, TCG_CALL_NO_RWG, tl, env, i64)
+DEF_HELPER_FLAGS_2(fcvt_l_h, TCG_CALL_NO_RWG, tl, env, i64)
+DEF_HELPER_FLAGS_2(fcvt_lu_h, TCG_CALL_NO_RWG, tl, env, i64)
+DEF_HELPER_FLAGS_2(fcvt_h_w, TCG_CALL_NO_RWG, i64, env, tl)
+DEF_HELPER_FLAGS_2(fcvt_h_wu, TCG_CALL_NO_RWG, i64, env, tl)
+DEF_HELPER_FLAGS_2(fcvt_h_l, TCG_CALL_NO_RWG, i64, env, tl)
+DEF_HELPER_FLAGS_2(fcvt_h_lu, TCG_CALL_NO_RWG, i64, env, tl)
 
 /* Special functions */
 DEF_HELPER_2(csrr, tl, env, int)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 66c231a3010..ba40f3e7f89 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -739,5 +739,24 @@ fsub_h 110  . . ... . 1010011 @r_rm
 fmul_h 0001010  . . ... . 1010011 @r_rm
 fdiv_h 0001110  . . ... . 1010011 @r_rm
 fsqrt_h0101110  0 . ... . 1010011 @r2_rm
+fsgnj_h0010010  . . 000 . 1010011 @r
+fsgnjn_h   0010010  . . 001 . 1010011 @r
+fsgnjx_h   0010010  . . 010 . 1010011 @r
 fmin_h 0010110  . . 000 . 1010011 @r
 fmax_h 0010110  . . 001 . 1010011 @r
+fcvt_h_s   0100010  0 . ... . 1010011 @r2_rm
+fcvt_s_h   010  00010 . ... . 1010011 @r2_rm
+fcvt_h_d   0100010  1 . ... . 1010011 @r2_rm
+fcvt_d_h   011  00010 . ... . 1010011 @r2_rm
+fcvt_w_h   1100010  0 . ... . 1010011 @r2_rm
+fcvt_wu_h  1100010  1 . ... . 1010

[PATCH v4 5/8] target/riscv: zfh: half-precision floating-point classify

2021-10-19 Thread frank . chang
From: Kito Cheng 

Signed-off-by: Kito Cheng 
Signed-off-by: Chih-Min Chao 
Signed-off-by: Frank Chang 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/fpu_helper.c |  6 ++
 target/riscv/helper.h |  1 +
 target/riscv/insn32.decode|  1 +
 target/riscv/insn_trans/trans_rvzfh.c.inc | 12 
 4 files changed, 20 insertions(+)

diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c
index ec2009ee65b..388e23ca670 100644
--- a/target/riscv/fpu_helper.c
+++ b/target/riscv/fpu_helper.c
@@ -482,6 +482,12 @@ target_ulong helper_feq_h(CPURISCVState *env, uint64_t 
rs1, uint64_t rs2)
 return float16_eq_quiet(frs1, frs2, &env->fp_status);
 }
 
+target_ulong helper_fclass_h(uint64_t rs1)
+{
+float16 frs1 = check_nanbox_h(rs1);
+return fclass_h(frs1);
+}
+
 target_ulong helper_fcvt_w_h(CPURISCVState *env, uint64_t rs1)
 {
 float16 frs1 = check_nanbox_h(rs1);
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 9c89521d4ad..d25cf725c57 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -89,6 +89,7 @@ DEF_HELPER_FLAGS_2(fcvt_h_w, TCG_CALL_NO_RWG, i64, env, tl)
 DEF_HELPER_FLAGS_2(fcvt_h_wu, TCG_CALL_NO_RWG, i64, env, tl)
 DEF_HELPER_FLAGS_2(fcvt_h_l, TCG_CALL_NO_RWG, i64, env, tl)
 DEF_HELPER_FLAGS_2(fcvt_h_lu, TCG_CALL_NO_RWG, i64, env, tl)
+DEF_HELPER_FLAGS_1(fclass_h, TCG_CALL_NO_RWG_SE, tl, i64)
 
 /* Special functions */
 DEF_HELPER_2(csrr, tl, env, int)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 3906c9fb201..6c4cde216bc 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -754,6 +754,7 @@ fmv_x_h1110010  0 . 000 . 1010011 @r2
 feq_h  1010010  . . 010 . 1010011 @r
 flt_h  1010010  . . 001 . 1010011 @r
 fle_h  1010010  . . 000 . 1010011 @r
+fclass_h   1110010  0 . 001 . 1010011 @r2
 fcvt_h_w   1101010  0 . ... . 1010011 @r2_rm
 fcvt_h_wu  1101010  1 . ... . 1010011 @r2_rm
 fmv_h_x010  0 . 000 . 1010011 @r2
diff --git a/target/riscv/insn_trans/trans_rvzfh.c.inc 
b/target/riscv/insn_trans/trans_rvzfh.c.inc
index 8d0959a6671..0549e25fb45 100644
--- a/target/riscv/insn_trans/trans_rvzfh.c.inc
+++ b/target/riscv/insn_trans/trans_rvzfh.c.inc
@@ -372,6 +372,18 @@ static bool trans_fle_h(DisasContext *ctx, arg_fle_h *a)
 return true;
 }
 
+static bool trans_fclass_h(DisasContext *ctx, arg_fclass_h *a)
+{
+REQUIRE_FPU;
+REQUIRE_ZFH(ctx);
+
+TCGv dest = dest_gpr(ctx, a->rd);
+
+gen_helper_fclass_h(dest, cpu_fpr[a->rs1]);
+gen_set_gpr(ctx, a->rd, dest);
+return true;
+}
+
 static bool trans_fcvt_w_h(DisasContext *ctx, arg_fcvt_w_h *a)
 {
 REQUIRE_FPU;
-- 
2.25.1




[PATCH v4 2/8] target/riscv: zfh: half-precision computational

2021-10-19 Thread frank . chang
From: Kito Cheng 

Signed-off-by: Kito Cheng 
Signed-off-by: Chih-Min Chao 
Signed-off-by: Frank Chang 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/fpu_helper.c |  86 +++
 target/riscv/helper.h |  13 +++
 target/riscv/insn32.decode|  11 ++
 target/riscv/insn_trans/trans_rvzfh.c.inc | 129 ++
 target/riscv/internals.h  |  16 +++
 5 files changed, 255 insertions(+)

diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c
index d62f4709002..20bb89ad14f 100644
--- a/target/riscv/fpu_helper.c
+++ b/target/riscv/fpu_helper.c
@@ -81,6 +81,15 @@ void helper_set_rounding_mode(CPURISCVState *env, uint32_t 
rm)
 set_float_rounding_mode(softrm, &env->fp_status);
 }
 
+static uint64_t do_fmadd_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2,
+   uint64_t rs3, int flags)
+{
+float16 frs1 = check_nanbox_h(rs1);
+float16 frs2 = check_nanbox_h(rs2);
+float16 frs3 = check_nanbox_h(rs3);
+return nanbox_h(float16_muladd(frs1, frs2, frs3, flags, &env->fp_status));
+}
+
 static uint64_t do_fmadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2,
uint64_t rs3, int flags)
 {
@@ -102,6 +111,12 @@ uint64_t helper_fmadd_d(CPURISCVState *env, uint64_t frs1, 
uint64_t frs2,
 return float64_muladd(frs1, frs2, frs3, 0, &env->fp_status);
 }
 
+uint64_t helper_fmadd_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
+uint64_t frs3)
+{
+return do_fmadd_h(env, frs1, frs2, frs3, 0);
+}
+
 uint64_t helper_fmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
 uint64_t frs3)
 {
@@ -115,6 +130,12 @@ uint64_t helper_fmsub_d(CPURISCVState *env, uint64_t frs1, 
uint64_t frs2,
   &env->fp_status);
 }
 
+uint64_t helper_fmsub_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
+uint64_t frs3)
+{
+return do_fmadd_h(env, frs1, frs2, frs3, float_muladd_negate_c);
+}
+
 uint64_t helper_fnmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
  uint64_t frs3)
 {
@@ -128,6 +149,12 @@ uint64_t helper_fnmsub_d(CPURISCVState *env, uint64_t 
frs1, uint64_t frs2,
   &env->fp_status);
 }
 
+uint64_t helper_fnmsub_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
+ uint64_t frs3)
+{
+return do_fmadd_h(env, frs1, frs2, frs3, float_muladd_negate_product);
+}
+
 uint64_t helper_fnmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
  uint64_t frs3)
 {
@@ -142,6 +169,13 @@ uint64_t helper_fnmadd_d(CPURISCVState *env, uint64_t 
frs1, uint64_t frs2,
   float_muladd_negate_product, &env->fp_status);
 }
 
+uint64_t helper_fnmadd_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
+ uint64_t frs3)
+{
+return do_fmadd_h(env, frs1, frs2, frs3,
+  float_muladd_negate_c | float_muladd_negate_product);
+}
+
 uint64_t helper_fadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
 {
 float32 frs1 = check_nanbox_s(rs1);
@@ -374,3 +408,55 @@ target_ulong helper_fclass_d(uint64_t frs1)
 {
 return fclass_d(frs1);
 }
+
+uint64_t helper_fadd_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
+{
+float16 frs1 = check_nanbox_h(rs1);
+float16 frs2 = check_nanbox_h(rs2);
+return nanbox_h(float16_add(frs1, frs2, &env->fp_status));
+}
+
+uint64_t helper_fsub_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
+{
+float16 frs1 = check_nanbox_h(rs1);
+float16 frs2 = check_nanbox_h(rs2);
+return nanbox_h(float16_sub(frs1, frs2, &env->fp_status));
+}
+
+uint64_t helper_fmul_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
+{
+float16 frs1 = check_nanbox_h(rs1);
+float16 frs2 = check_nanbox_h(rs2);
+return nanbox_h(float16_mul(frs1, frs2, &env->fp_status));
+}
+
+uint64_t helper_fdiv_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
+{
+float16 frs1 = check_nanbox_h(rs1);
+float16 frs2 = check_nanbox_h(rs2);
+return nanbox_h(float16_div(frs1, frs2, &env->fp_status));
+}
+
+uint64_t helper_fmin_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
+{
+float16 frs1 = check_nanbox_h(rs1);
+float16 frs2 = check_nanbox_h(rs2);
+return nanbox_h(env->priv_ver < PRIV_VERSION_1_11_0 ?
+float16_minnum(frs1, frs2, &env->fp_status) :
+float16_minimum_number(frs1, frs2, &env->fp_status));
+}
+
+uint64_t helper_fmax_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
+{
+float16 frs1 = check_nanbox_h(rs1);
+float16 frs2 = check_nanbox_h(rs2);
+return nanbox_h(env->priv_ver < PRIV_VERSION_1_11_0 ?
+float16_maxnum(frs1, frs2, &env->fp_status) :
+float16_maximum_number(frs1, frs2, &env->fp_status));
+}
+
+uint64_t helper_fsqrt_h(CPURISCVState *env, uint64_t rs

[PATCH v4 7/8] target/riscv: zfh: implement zfhmin extension

2021-10-19 Thread frank . chang
From: Frank Chang 

Zfhmin extension is a subset of Zfh extension, consisting only of data
transfer and conversion instructions.

If enabled, only the following instructions from Zfh extension are
included:
  * flh, fsh, fmv.x.h, fmv.h.x, fcvt.s.h, fcvt.h.s
  * If D extension is present: fcvt.d.h, fcvt.h.d

Signed-off-by: Frank Chang 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.h|  1 +
 target/riscv/insn_trans/trans_rvzfh.c.inc | 22 ++
 target/riscv/translate.c  |  2 ++
 3 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 88684e72be1..d70f63ddfe6 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -298,6 +298,7 @@ struct RISCVCPU {
 bool ext_ifencei;
 bool ext_icsr;
 bool ext_zfh;
+bool ext_zfhmin;
 
 char *priv_spec;
 char *user_spec;
diff --git a/target/riscv/insn_trans/trans_rvzfh.c.inc 
b/target/riscv/insn_trans/trans_rvzfh.c.inc
index 0549e25fb45..5a7cac89585 100644
--- a/target/riscv/insn_trans/trans_rvzfh.c.inc
+++ b/target/riscv/insn_trans/trans_rvzfh.c.inc
@@ -22,13 +22,19 @@
 } \
 } while (0)
 
+#define REQUIRE_ZFH_OR_ZFHMIN(ctx) do {   \
+if (!(ctx->ext_zfh || ctx->ext_zfhmin)) { \
+return false; \
+} \
+} while (0)
+
 static bool trans_flh(DisasContext *ctx, arg_flh *a)
 {
 TCGv_i64 dest;
 TCGv t0;
 
 REQUIRE_FPU;
-REQUIRE_ZFH(ctx);
+REQUIRE_ZFH_OR_ZFHMIN(ctx);
 
 t0 = get_gpr(ctx, a->rs1, EXT_NONE);
 if (a->imm) {
@@ -50,7 +56,7 @@ static bool trans_fsh(DisasContext *ctx, arg_fsh *a)
 TCGv t0;
 
 REQUIRE_FPU;
-REQUIRE_ZFH(ctx);
+REQUIRE_ZFH_OR_ZFHMIN(ctx);
 
 t0 = get_gpr(ctx, a->rs1, EXT_NONE);
 if (a->imm) {
@@ -283,7 +289,7 @@ static bool trans_fmax_h(DisasContext *ctx, arg_fmax_h *a)
 static bool trans_fcvt_s_h(DisasContext *ctx, arg_fcvt_s_h *a)
 {
 REQUIRE_FPU;
-REQUIRE_ZFH(ctx);
+REQUIRE_ZFH_OR_ZFHMIN(ctx);
 
 gen_set_rm(ctx, a->rm);
 gen_helper_fcvt_s_h(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1]);
@@ -296,7 +302,7 @@ static bool trans_fcvt_s_h(DisasContext *ctx, arg_fcvt_s_h 
*a)
 static bool trans_fcvt_d_h(DisasContext *ctx, arg_fcvt_d_h *a)
 {
 REQUIRE_FPU;
-REQUIRE_ZFH(ctx);
+REQUIRE_ZFH_OR_ZFHMIN(ctx);
 REQUIRE_EXT(ctx, RVD);
 
 gen_set_rm(ctx, a->rm);
@@ -311,7 +317,7 @@ static bool trans_fcvt_d_h(DisasContext *ctx, arg_fcvt_d_h 
*a)
 static bool trans_fcvt_h_s(DisasContext *ctx, arg_fcvt_h_s *a)
 {
 REQUIRE_FPU;
-REQUIRE_ZFH(ctx);
+REQUIRE_ZFH_OR_ZFHMIN(ctx);
 
 gen_set_rm(ctx, a->rm);
 gen_helper_fcvt_h_s(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1]);
@@ -324,7 +330,7 @@ static bool trans_fcvt_h_s(DisasContext *ctx, arg_fcvt_h_s 
*a)
 static bool trans_fcvt_h_d(DisasContext *ctx, arg_fcvt_h_d *a)
 {
 REQUIRE_FPU;
-REQUIRE_ZFH(ctx);
+REQUIRE_ZFH_OR_ZFHMIN(ctx);
 REQUIRE_EXT(ctx, RVD);
 
 gen_set_rm(ctx, a->rm);
@@ -441,7 +447,7 @@ static bool trans_fcvt_h_wu(DisasContext *ctx, 
arg_fcvt_h_wu *a)
 static bool trans_fmv_x_h(DisasContext *ctx, arg_fmv_x_h *a)
 {
 REQUIRE_FPU;
-REQUIRE_ZFH(ctx);
+REQUIRE_ZFH_OR_ZFHMIN(ctx);
 
 TCGv dest = dest_gpr(ctx, a->rd);
 
@@ -461,7 +467,7 @@ static bool trans_fmv_x_h(DisasContext *ctx, arg_fmv_x_h *a)
 static bool trans_fmv_h_x(DisasContext *ctx, arg_fmv_h_x *a)
 {
 REQUIRE_FPU;
-REQUIRE_ZFH(ctx);
+REQUIRE_ZFH_OR_ZFHMIN(ctx);
 
 TCGv t0 = get_gpr(ctx, a->rs1, EXT_ZERO);
 
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 442ef42f441..f23bc919c08 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -70,6 +70,7 @@ typedef struct DisasContext {
 bool virt_enabled;
 bool ext_ifencei;
 bool ext_zfh;
+bool ext_zfhmin;
 bool hlsx;
 /* vector extension */
 bool vill;
@@ -559,6 +560,7 @@ static void riscv_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 ctx->frm = -1;  /* unknown rounding mode */
 ctx->ext_ifencei = cpu->cfg.ext_ifencei;
 ctx->ext_zfh = cpu->cfg.ext_zfh;
+ctx->ext_zfhmin = cpu->cfg.ext_zfhmin;
 ctx->vlen = cpu->cfg.vlen;
 ctx->mstatus_hs_fs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_FS);
 ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX);
-- 
2.25.1




[PATCH v4 4/8] target/riscv: zfh: half-precision floating-point compare

2021-10-19 Thread frank . chang
From: Kito Cheng 

Signed-off-by: Kito Cheng 
Signed-off-by: Chih-Min Chao 
Signed-off-by: Frank Chang 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/fpu_helper.c | 21 +
 target/riscv/helper.h |  3 ++
 target/riscv/insn32.decode|  3 ++
 target/riscv/insn_trans/trans_rvzfh.c.inc | 37 +++
 4 files changed, 64 insertions(+)

diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c
index 2ed9b03193c..ec2009ee65b 100644
--- a/target/riscv/fpu_helper.c
+++ b/target/riscv/fpu_helper.c
@@ -461,6 +461,27 @@ uint64_t helper_fsqrt_h(CPURISCVState *env, uint64_t rs1)
 return nanbox_h(float16_sqrt(frs1, &env->fp_status));
 }
 
+target_ulong helper_fle_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
+{
+float16 frs1 = check_nanbox_h(rs1);
+float16 frs2 = check_nanbox_h(rs2);
+return float16_le(frs1, frs2, &env->fp_status);
+}
+
+target_ulong helper_flt_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
+{
+float16 frs1 = check_nanbox_h(rs1);
+float16 frs2 = check_nanbox_h(rs2);
+return float16_lt(frs1, frs2, &env->fp_status);
+}
+
+target_ulong helper_feq_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
+{
+float16 frs1 = check_nanbox_h(rs1);
+float16 frs2 = check_nanbox_h(rs2);
+return float16_eq_quiet(frs1, frs2, &env->fp_status);
+}
+
 target_ulong helper_fcvt_w_h(CPURISCVState *env, uint64_t rs1)
 {
 float16 frs1 = check_nanbox_h(rs1);
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index b50672d1684..9c89521d4ad 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -74,6 +74,9 @@ DEF_HELPER_FLAGS_3(fdiv_h, TCG_CALL_NO_RWG, i64, env, i64, 
i64)
 DEF_HELPER_FLAGS_3(fmin_h, TCG_CALL_NO_RWG, i64, env, i64, i64)
 DEF_HELPER_FLAGS_3(fmax_h, TCG_CALL_NO_RWG, i64, env, i64, i64)
 DEF_HELPER_FLAGS_2(fsqrt_h, TCG_CALL_NO_RWG, i64, env, i64)
+DEF_HELPER_FLAGS_3(fle_h, TCG_CALL_NO_RWG, tl, env, i64, i64)
+DEF_HELPER_FLAGS_3(flt_h, TCG_CALL_NO_RWG, tl, env, i64, i64)
+DEF_HELPER_FLAGS_3(feq_h, TCG_CALL_NO_RWG, tl, env, i64, i64)
 DEF_HELPER_FLAGS_2(fcvt_s_h, TCG_CALL_NO_RWG, i64, env, i64)
 DEF_HELPER_FLAGS_2(fcvt_h_s, TCG_CALL_NO_RWG, i64, env, i64)
 DEF_HELPER_FLAGS_2(fcvt_d_h, TCG_CALL_NO_RWG, i64, env, i64)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index ba40f3e7f89..3906c9fb201 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -751,6 +751,9 @@ fcvt_d_h   011  00010 . ... . 1010011 @r2_rm
 fcvt_w_h   1100010  0 . ... . 1010011 @r2_rm
 fcvt_wu_h  1100010  1 . ... . 1010011 @r2_rm
 fmv_x_h1110010  0 . 000 . 1010011 @r2
+feq_h  1010010  . . 010 . 1010011 @r
+flt_h  1010010  . . 001 . 1010011 @r
+fle_h  1010010  . . 000 . 1010011 @r
 fcvt_h_w   1101010  0 . ... . 1010011 @r2_rm
 fcvt_h_wu  1101010  1 . ... . 1010011 @r2_rm
 fmv_h_x010  0 . 000 . 1010011 @r2
diff --git a/target/riscv/insn_trans/trans_rvzfh.c.inc 
b/target/riscv/insn_trans/trans_rvzfh.c.inc
index d1250257666..8d0959a6671 100644
--- a/target/riscv/insn_trans/trans_rvzfh.c.inc
+++ b/target/riscv/insn_trans/trans_rvzfh.c.inc
@@ -335,6 +335,43 @@ static bool trans_fcvt_h_d(DisasContext *ctx, arg_fcvt_h_d 
*a)
 return true;
 }
 
+static bool trans_feq_h(DisasContext *ctx, arg_feq_h *a)
+{
+REQUIRE_FPU;
+REQUIRE_ZFH(ctx);
+
+TCGv dest = dest_gpr(ctx, a->rd);
+
+gen_helper_feq_h(dest, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
+gen_set_gpr(ctx, a->rd, dest);
+return true;
+}
+
+static bool trans_flt_h(DisasContext *ctx, arg_flt_h *a)
+{
+REQUIRE_FPU;
+REQUIRE_ZFH(ctx);
+
+TCGv dest = dest_gpr(ctx, a->rd);
+
+gen_helper_flt_h(dest, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
+gen_set_gpr(ctx, a->rd, dest);
+
+return true;
+}
+
+static bool trans_fle_h(DisasContext *ctx, arg_fle_h *a)
+{
+REQUIRE_FPU;
+REQUIRE_ZFH(ctx);
+
+TCGv dest = dest_gpr(ctx, a->rd);
+
+gen_helper_fle_h(dest, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
+gen_set_gpr(ctx, a->rd, dest);
+return true;
+}
+
 static bool trans_fcvt_w_h(DisasContext *ctx, arg_fcvt_w_h *a)
 {
 REQUIRE_FPU;
-- 
2.25.1




[PATCH v4 1/8] target/riscv: zfh: half-precision load and store

2021-10-19 Thread frank . chang
From: Kito Cheng 

Signed-off-by: Kito Cheng 
Signed-off-by: Chih-Min Chao 
Signed-off-by: Frank Chang 
Reviewed-by: Richard Henderson 
---
 target/riscv/cpu.h|  1 +
 target/riscv/insn32.decode|  4 ++
 target/riscv/insn_trans/trans_rvzfh.c.inc | 65 +++
 target/riscv/translate.c  |  8 +++
 4 files changed, 78 insertions(+)
 create mode 100644 target/riscv/insn_trans/trans_rvzfh.c.inc

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 9e55b2f5b17..88684e72be1 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -297,6 +297,7 @@ struct RISCVCPU {
 bool ext_counters;
 bool ext_ifencei;
 bool ext_icsr;
+bool ext_zfh;
 
 char *priv_spec;
 char *user_spec;
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 2f251dac1bb..b36a3d8dbf8 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -726,3 +726,7 @@ binv   0110100 .. 001 . 0110011 @r
 binvi  01101. ... 001 . 0010011 @sh
 bset   0010100 .. 001 . 0110011 @r
 bseti  00101. ... 001 . 0010011 @sh
+
+# *** RV32 Zfh Extension ***
+flh   . 001 . 111 @i
+fsh...  . . 001 . 0100111 @s
diff --git a/target/riscv/insn_trans/trans_rvzfh.c.inc 
b/target/riscv/insn_trans/trans_rvzfh.c.inc
new file mode 100644
index 000..dad1d703d72
--- /dev/null
+++ b/target/riscv/insn_trans/trans_rvzfh.c.inc
@@ -0,0 +1,65 @@
+/*
+ * RISC-V translation routines for the RV64Zfh Standard Extension.
+ *
+ * Copyright (c) 2020 Chih-Min Chao, chihmin.c...@sifive.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+
+#define REQUIRE_ZFH(ctx) do { \
+if (!ctx->ext_zfh) {  \
+return false; \
+} \
+} while (0)
+
+static bool trans_flh(DisasContext *ctx, arg_flh *a)
+{
+TCGv_i64 dest;
+TCGv t0;
+
+REQUIRE_FPU;
+REQUIRE_ZFH(ctx);
+
+t0 = get_gpr(ctx, a->rs1, EXT_NONE);
+if (a->imm) {
+TCGv temp = temp_new(ctx);
+tcg_gen_addi_tl(temp, t0, a->imm);
+t0 = temp;
+}
+
+dest = cpu_fpr[a->rd];
+tcg_gen_qemu_ld_i64(dest, t0, ctx->mem_idx, MO_TEUW);
+gen_nanbox_h(dest, dest);
+
+mark_fs_dirty(ctx);
+return true;
+}
+
+static bool trans_fsh(DisasContext *ctx, arg_fsh *a)
+{
+TCGv t0;
+
+REQUIRE_FPU;
+REQUIRE_ZFH(ctx);
+
+t0 = get_gpr(ctx, a->rs1, EXT_NONE);
+if (a->imm) {
+TCGv temp = tcg_temp_new();
+tcg_gen_addi_tl(temp, t0, a->imm);
+t0 = temp;
+}
+
+tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], t0, ctx->mem_idx, MO_TEUW);
+
+return true;
+}
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index d2442f0cf5d..75048149f5a 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -69,6 +69,7 @@ typedef struct DisasContext {
 bool w;
 bool virt_enabled;
 bool ext_ifencei;
+bool ext_zfh;
 bool hlsx;
 /* vector extension */
 bool vill;
@@ -118,6 +119,11 @@ static void gen_nanbox_s(TCGv_i64 out, TCGv_i64 in)
 tcg_gen_ori_i64(out, in, MAKE_64BIT_MASK(32, 32));
 }
 
+static void gen_nanbox_h(TCGv_i64 out, TCGv_i64 in)
+{
+tcg_gen_ori_i64(out, in, MAKE_64BIT_MASK(16, 48));
+}
+
 /*
  * A narrow n-bit operation, where n < FLEN, checks that input operands
  * are correctly Nan-boxed, i.e., all upper FLEN - n bits are 1.
@@ -489,6 +495,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, 
target_ulong pc)
 #include "insn_trans/trans_rvh.c.inc"
 #include "insn_trans/trans_rvv.c.inc"
 #include "insn_trans/trans_rvb.c.inc"
+#include "insn_trans/trans_rvzfh.c.inc"
 #include "insn_trans/trans_privileged.c.inc"
 
 /* Include the auto-generated decoder for 16 bit insn */
@@ -541,6 +548,7 @@ static void riscv_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 ctx->misa = env->misa;
 ctx->frm = -1;  /* unknown rounding mode */
 ctx->ext_ifencei = cpu->cfg.ext_ifencei;
+ctx->ext_zfh = cpu->cfg.ext_zfh;
 ctx->vlen = cpu->cfg.vlen;
 ctx->mstatus_hs_fs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_FS);
 ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX);
-- 
2.25.1




Re: [PATCH v4 2/2] target/riscv: change the api for RVF/RVD fmin/fmax

2021-10-19 Thread Frank Chang
On Sat, Oct 16, 2021 at 4:54 PM  wrote:

> From: Chih-Min Chao 
>
> The sNaN propagation behavior has been changed since
> cd20cee7 in https://github.com/riscv/riscv-isa-manual.
>
> Signed-off-by: Chih-Min Chao 
> Signed-off-by: Frank Chang 
> ---
>  target/riscv/fpu_helper.c | 16 
>  1 file changed, 12 insertions(+), 4 deletions(-)
>
> diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c
> index 8700516a14c..d62f4709002 100644
> --- a/target/riscv/fpu_helper.c
> +++ b/target/riscv/fpu_helper.c
> @@ -174,14 +174,18 @@ uint64_t helper_fmin_s(CPURISCVState *env, uint64_t
> rs1, uint64_t rs2)
>  {
>  float32 frs1 = check_nanbox_s(rs1);
>  float32 frs2 = check_nanbox_s(rs2);
> -return nanbox_s(float32_minnum(frs1, frs2, &env->fp_status));
> +return nanbox_s(env->priv_ver < PRIV_VERSION_1_11_0 ?
> +float32_minnum(frs1, frs2, &env->fp_status) :
> +float32_minimum_number(frs1, frs2, &env->fp_status));
>  }
>
>  uint64_t helper_fmax_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
>  {
>  float32 frs1 = check_nanbox_s(rs1);
>  float32 frs2 = check_nanbox_s(rs2);
> -return nanbox_s(float32_maxnum(frs1, frs2, &env->fp_status));
> +return nanbox_s(env->priv_ver < PRIV_VERSION_1_11_0 ?
> +float32_maxnum(frs1, frs2, &env->fp_status) :
> +float32_maximum_number(frs1, frs2, &env->fp_status));
>  }
>
>  uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t rs1)
> @@ -283,12 +287,16 @@ uint64_t helper_fdiv_d(CPURISCVState *env, uint64_t
> frs1, uint64_t frs2)
>
>  uint64_t helper_fmin_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
>  {
> -return float64_minnum(frs1, frs2, &env->fp_status);
> +return env->priv_ver < PRIV_VERSION_1_11_0 ?
> +float64_minnum(frs1, frs2, &env->fp_status) :
> +float64_minimum_number(frs1, frs2, &env->fp_status);
>  }
>
>  uint64_t helper_fmax_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
>  {
> -return float64_maxnum(frs1, frs2, &env->fp_status);
> +return env->priv_ver < PRIV_VERSION_1_11_0 ?
> +float64_maxnum(frs1, frs2, &env->fp_status) :
> +float64_maximum_number(frs1, frs2, &env->fp_status);
>  }
>
>  uint64_t helper_fcvt_s_d(CPURISCVState *env, uint64_t rs1)
> --
> 2.25.1
>
>
If we have decided to tie RVF with Privilege spec version for now as
discussed in:
https://patchew.org/QEMU/20211015065500.3850513-1-frank.ch...@sifive.com/20211015065500.3850513-3-frank.ch...@sifive.com/
then I think this patch doesn't require any further changes, right?

Regards,
Frank Chang


RE: [PATCH V3] net/colo: check vnet_hdr_support flag when using virtio-net

2021-10-19 Thread Zhang, Chen



> -Original Message-
> From: Jason Wang 
> Sent: Tuesday, October 19, 2021 3:39 PM
> To: Zhang, Chen ; Eric Blake ;
> Markus Armbruster 
> Cc: qemu-dev ; Li Zhijian
> ; Lukas Straub ; Tao Xu
> 
> Subject: Re: [PATCH V3] net/colo: check vnet_hdr_support flag when using
> virtio-net
> 
> 
> 在 2021/9/18 上午10:04, Zhang Chen 写道:
> > When COLO use only one vnet_hdr_support parameter between COLO
> network
> > filter(filter-mirror, filter-redirector or filter-rewriter and
> > colo-compare, packet will not be parsed correctly. Acquire network
> > driver related to COLO, if it is nirtio-net,
> 
> 
> Typo.

Oh~ will fix in next version.

> 
> 
> >   check vnet_hdr_support flag of COLO network filter and colo-compare.
> >
> > Signed-off-by: Tao Xu 
> > Signed-off-by: Zhang Chen 
> > ---
> >
> > Changelog:
> > v3:
> >  Fix some typos.
> >  Rebased for Qemu 6.2.
> >
> > v2:
> >  Detect virtio-net driver and apply vnet_hdr_support
> >  automatically. (Jason)
> > ---
> >   net/colo-compare.c| 57
> +++
> >   net/colo.c| 20 +++
> >   net/colo.h|  4 +++
> >   net/filter-mirror.c   | 21 
> >   net/filter-rewriter.c | 10 
> >   qapi/qom.json |  6 +
> >   qemu-options.hx   |  6 +++--
> >   7 files changed, 122 insertions(+), 2 deletions(-)
> >
> > diff --git a/net/colo-compare.c b/net/colo-compare.c index
> > b100e7b51f..870bd05a41 100644
> > --- a/net/colo-compare.c
> > +++ b/net/colo-compare.c
> > @@ -110,6 +110,7 @@ struct CompareState {
> >   char *sec_indev;
> >   char *outdev;
> >   char *notify_dev;
> > +char *netdev;
> >   CharBackend chr_pri_in;
> >   CharBackend chr_sec_in;
> >   CharBackend chr_out;
> > @@ -838,6 +839,28 @@ static int compare_chr_can_read(void *opaque)
> >   return COMPARE_READ_LEN_MAX;
> >   }
> >
> > +static int colo_set_default_netdev(void *opaque, QemuOpts *opts,
> > +Error **errp) {
> > +const char *colo_obj_type, *netdev_from_filter;
> > +char **netdev = (char **)opaque;
> > +
> > +colo_obj_type = qemu_opt_get(opts, "qom-type");
> > +
> > +if (colo_obj_type &&
> > +(strcmp(colo_obj_type, "filter-mirror") == 0 ||
> > + strcmp(colo_obj_type, "filter-redirector") == 0 ||
> > + strcmp(colo_obj_type, "filter-rewriter") == 0)) {
> > +netdev_from_filter = qemu_opt_get(opts, "netdev");
> > +if (*netdev == NULL) {
> > +*netdev = g_strdup(netdev_from_filter);
> > +} else if (strcmp(*netdev, netdev_from_filter) != 0) {
> > +warn_report("%s is using a different netdev from other COLO "
> > +"component", colo_obj_type);
> > +}
> > +}
> > +return 0;
> > +}
> > +
> >   /*
> >* Called from the main thread on the primary for packets
> >* arriving over the socket from the primary.
> > @@ -1050,6 +1073,21 @@ static void compare_set_vnet_hdr(Object *obj,
> >   s->vnet_hdr = value;
> >   }
> >
> > +static char *compare_get_netdev(Object *obj, Error **errp) {
> > +CompareState *s = COLO_COMPARE(obj);
> > +
> > +return g_strdup(s->netdev);
> > +}
> > +
> > +static void compare_set_netdev(Object *obj, const char *value, Error
> > +**errp) {
> > +CompareState *s = COLO_COMPARE(obj);
> > +
> > +g_free(s->netdev);
> > +s->netdev = g_strdup(value);
> > +}
> > +
> >   static char *compare_get_notify_dev(Object *obj, Error **errp)
> >   {
> >   CompareState *s = COLO_COMPARE(obj); @@ -1274,6 +1312,12 @@
> > static void colo_compare_complete(UserCreatable *uc, Error **errp)
> >   max_queue_size = MAX_QUEUE_SIZE;
> >   }
> >
> > +if (!s->netdev) {
> > +/* Set default netdev as the first colo netfilter found */
> > +qemu_opts_foreach(qemu_find_opts("object"),
> > +  colo_set_default_netdev, &s->netdev, NULL);
> > +}
> > +
> >   if (find_and_check_chardev(&chr, s->pri_indev, errp) ||
> >   !qemu_chr_fe_init(&s->chr_pri_in, chr, errp)) {
> >   return;
> > @@ -1289,6 +1333,16 @@ static void
> colo_compare_complete(UserCreatable *uc, Error **errp)
> >   return;
> >   }
> >
> > +if (!s->vnet_hdr &&
> > +qemu_opts_foreach(qemu_find_opts("device"),
> > +  vnet_driver_check, s->netdev, NULL)) {
> > +/*
> > + * colo compare needs 'vnet_hdr_support' when it works on 
> > virtio-net,
> > + * add 'vnet_hdr_support' automatically
> > + */
> > +s->vnet_hdr = true;
> > +}
> > +
> >   net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize, s->vnet_hdr);
> >   net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize,
> > s->vnet_hdr);
> >
> > @@ -1400,6 +1454,9 @@ static void colo_compare_init(Object *obj)
> >   s->vnet_hdr = false;
> >   object_property_add_bool(obj, "vnet_hdr_support",
> compare_get_vnet_hdr,
> > 

Re: [PATCH V4 03/10] vhost-vdpa: prepare for the multiqueue support

2021-10-19 Thread Jason Wang
On Mon, Oct 18, 2021 at 11:44 PM Stefano Garzarella  wrote:
>
> On Mon, Oct 11, 2021 at 12:28:22PM +0800, Jason Wang wrote:
> >Unlike vhost-kernel, vhost-vdpa adapts a single device multiqueue
> >model. So we need to simply use virtqueue index as the vhost virtqueue
> >index. This is a must for multiqueue to work for vhost-vdpa.
> >
> >Signed-off-by: Jason Wang 
> >Message-Id: <20210907090322.1756-4-jasow...@redhat.com>
> >Reviewed-by: Michael S. Tsirkin 
> >Signed-off-by: Michael S. Tsirkin 
> >---
> > hw/virtio/vhost-vdpa.c | 4 ++--
> > 1 file changed, 2 insertions(+), 2 deletions(-)
> >
> >diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
> >index edac4017da..8587d30918 100644
> >--- a/hw/virtio/vhost-vdpa.c
> >+++ b/hw/virtio/vhost-vdpa.c
> >@@ -504,8 +504,8 @@ static int vhost_vdpa_get_vq_index(struct vhost_dev 
> >*dev, int idx)
> > {
> > assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
>
> Should we also change this assert?

I think this assert applies to multi-queue as well.

Thanks

>
> Thanks,
> Stefano
>
> >
> >-trace_vhost_vdpa_get_vq_index(dev, idx, idx - dev->vq_index);
> >-return idx - dev->vq_index;
> >+trace_vhost_vdpa_get_vq_index(dev, idx, idx);
> >+return idx;
> > }
> >
> > static int vhost_vdpa_set_vring_ready(struct vhost_dev *dev)
> >--
> >2.25.1
> >
> >
>




Re: [PATCH v9 00/10] vhost-vdpa: add support for configure interrupt

2021-10-19 Thread Cindy Lu
On Tue, Oct 19, 2021 at 2:56 PM Michael S. Tsirkin  wrote:
>
> On Thu, Sep 30, 2021 at 10:33:38AM +0800, Cindy Lu wrote:
> > these patches add the support for configure interrupt
> >
> > These codes are all tested in vp-vdpa (support configure interrupt)
> > vdpa_sim (not support configure interrupt), virtio tap device
> >
> > test in virtio-pci bus and virtio-mmio bus
>
>
> I was inclined to let it slide but it hangs make check
> so needs more work.
> Meanwhile please go over how the patchset is structured,
> and over description of each patch.
> I sent some comments but same applied to everything.
>
> Also, pls document the index == -1 hack in more detail.
> how does it work and why it's helpful.
>
> Thanks!
>
sure I will check this and add more details
> > Change in v2:
> > Add support for virtio-mmio bus
> > active the notifier while the backend support configure interrupt
> > misc fixes from v1
> >
> > Change in v3
> > fix the coding style problems
> >
> > Change in v4
> > misc fixes from v3
> > merge the set_config_notifier to set_guest_notifier
> > when vdpa start, check the feature by VIRTIO_NET_F_STATUS
> >
> > Change in v5
> > misc fixes from v4
> > split the code to introduce configure interrupt type and the callback 
> > function
> > will init the configure interrupt in all virtio-pci and virtio-mmio bus, 
> > but will
> > only active while using vhost-vdpa driver
> >
> > Change in v6
> > misc fixes from v5
> > decouple virtqueue from interrupt setting and misc process
> > fix the bug in virtio_net_handle_rx
> > use -1 as the queue number to identify if the interrupt is configure 
> > interrupt
> >
> > Change in v7
> > misc fixes from v6
> > decouple virtqueue from interrupt setting and misc process
> > decouple virtqueue from vector use/release process
> > decouple virtqueue from set notifier fd handler process
> > move config_notifier and masked_config_notifier to VirtIODevice
> > fix the bug in virtio_net_handle_rx, add more information
> > add VIRTIO_CONFIG_IRQ_IDX as the queue number to identify if the interrupt 
> > is configure interrupt
> >
> > Change in v8
> > misc fixes from v7
> > decouple virtqueue from interrupt setting and misc process
> > decouple virtqueue from vector use/release process
> > decouple virtqueue from set notifier fd handler process
> > move the vhost configure interrupt to vhost_net
> >
> > Change in v9
> > misc fixes from v8
> > address the comments for v8
> >
> > Cindy Lu (10):
> >   virtio: introduce macro IRTIO_CONFIG_IRQ_IDX
> >   virtio-pci: decouple notifier from interrupt process
> >   virtio-pci: decouple the single vector from the interrupt process
> >   vhost: add new call back function for config interrupt
> >   vhost-vdpa: add support for config interrupt call back
> >   virtio: add support for configure interrupt
> >   virtio-net: add support for configure interrupt
> >   vhost: add support for configure interrupt
> >   virtio-mmio: add support for configure interrupt
> >   virtio-pci: add support for configure interrupt
> >
> >  hw/display/vhost-user-gpu.c   |   6 +
> >  hw/net/vhost_net.c|  10 ++
> >  hw/net/virtio-net.c   |  16 +-
> >  hw/virtio/trace-events|   2 +
> >  hw/virtio/vhost-user-fs.c |   9 +-
> >  hw/virtio/vhost-vdpa.c|   7 +
> >  hw/virtio/vhost-vsock-common.c|   6 +
> >  hw/virtio/vhost.c |  76 +
> >  hw/virtio/virtio-crypto.c |   6 +
> >  hw/virtio/virtio-mmio.c   |  27 
> >  hw/virtio/virtio-pci.c| 260 --
> >  hw/virtio/virtio-pci.h|   4 +-
> >  hw/virtio/virtio.c|  29 
> >  include/hw/virtio/vhost-backend.h |   3 +
> >  include/hw/virtio/vhost.h |   4 +
> >  include/hw/virtio/virtio.h|   6 +
> >  include/net/vhost_net.h   |   3 +
> >  17 files changed, 386 insertions(+), 88 deletions(-)
> >
> > --
> > 2.21.3
>




Re: [PATCH v9 04/10] vhost: add new call back function for config interrupt

2021-10-19 Thread Cindy Lu
On Tue, Oct 19, 2021 at 2:52 PM Michael S. Tsirkin  wrote:
>
> On Thu, Sep 30, 2021 at 10:33:42AM +0800, Cindy Lu wrote:
> > To support the config interrupt, we need to
> > add a new call back function for config interrupt.
> >
> > Signed-off-by: Cindy Lu 
>
> Pls make commit log more informative.
> Doing what? Called back when?
>
sure, I will add more information in the commit log
>
> > ---
> >  include/hw/virtio/vhost-backend.h | 3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/include/hw/virtio/vhost-backend.h 
> > b/include/hw/virtio/vhost-backend.h
> > index 8475c5a29d..e732d2e702 100644
> > --- a/include/hw/virtio/vhost-backend.h
> > +++ b/include/hw/virtio/vhost-backend.h
> > @@ -126,6 +126,8 @@ typedef int (*vhost_get_device_id_op)(struct vhost_dev 
> > *dev, uint32_t *dev_id);
> >
> >  typedef bool (*vhost_force_iommu_op)(struct vhost_dev *dev);
> >
> > +typedef int (*vhost_set_config_call_op)(struct vhost_dev *dev,
> > +   int fd);
> >  typedef struct VhostOps {
> >  VhostBackendType backend_type;
> >  vhost_backend_init vhost_backend_init;
> > @@ -171,6 +173,7 @@ typedef struct VhostOps {
> >  vhost_vq_get_addr_op  vhost_vq_get_addr;
> >  vhost_get_device_id_op vhost_get_device_id;
> >  vhost_force_iommu_op vhost_force_iommu;
> > +vhost_set_config_call_op vhost_set_config_call;
> >  } VhostOps;
> >
> >  extern const VhostOps user_ops;
> > --
> > 2.21.3
>




Re: [RFC PATCH 0/3] Improve scalability of the SMP related Docs

2021-10-19 Thread wangyanan (Y)

Ping...

Is this a right direction to go or should I continue on with this ?

On 2021/10/7 18:43, Yanan Wang wrote:

Hi,

The motivation of this series is to improve the scalability of SMP
related Docs, so that we can easily/clearly extend them without making
confusion when we plan to introduce more target specific CPU topology
members (e.g. CPU cluster in Arm and CPU drawer/book in s390).

With more and more target specific CPU topology members introduced,
it may not be a good method any longer to put all the mixed parameters
into one single hierarchy and then describe the exact meaning of each
member in the Docs, which makes confusion for the reader. On the contrary,
it may be clearer to describe the currently supported sub-hierarchies
separately and better to list some examples in the Docs. For example,
for now we can describe "sockets/cores/threads" and "sockets/dies/cores/
threads" separately from the mixture of "sockets | dies | cores | threads",
and more sub-hierarchies can be described when new parameters are added.

Based on above consideration, correspondingly -smp docs in qemu-options,
comment of struct CpuTopology and SMP related comments in qapi/machine
are somehow rewritten.

Besides the maintainers, I also keep some people on Cc list who may be
interested in having a look at this. Comments welcome!

Thanks,
Yanan
.

Yanan Wang (3):
   qemu-options: Improve scalability of the -smp documentation
   include/hw/boards: Improve scalability of the CpuTopology comment
   qapi/machine.json: Improve scalability of the SMP related comments

  include/hw/boards.h | 26 +++--
  qapi/machine.json   | 47 ++-
  qemu-options.hx | 90 -
  3 files changed, 133 insertions(+), 30 deletions(-)

--
2.19.1

.





Re: [RFC PATCH v4 20/20] vdpa: Add custom IOTLB translations to SVQ

2021-10-19 Thread Jason Wang
On Wed, Oct 20, 2021 at 10:02 AM Jason Wang  wrote:
>
> On Tue, Oct 19, 2021 at 6:29 PM Eugenio Perez Martin
>  wrote:
> >
> > On Tue, Oct 19, 2021 at 11:25 AM Jason Wang  wrote:
> > >
> > >
> > > 在 2021/10/1 下午3:06, Eugenio Pérez 写道:
> > > > Use translations added in VhostIOVATree in SVQ.
> > > >
> > > > Now every element needs to store the previous address also, so VirtQueue
> > > > can consume the elements properly. This adds a little overhead per VQ
> > > > element, having to allocate more memory to stash them. As a possible
> > > > optimization, this allocation could be avoided if the descriptor is not
> > > > a chain but a single one, but this is left undone.
> > > >
> > > > TODO: iova range should be queried before, and add logic to fail when
> > > > GPA is outside of its range and memory listener or svq add it.
> > > >
> > > > Signed-off-by: Eugenio Pérez 
> > > > ---
> > > >   hw/virtio/vhost-shadow-virtqueue.h |   4 +-
> > > >   hw/virtio/vhost-shadow-virtqueue.c | 130 -
> > > >   hw/virtio/vhost-vdpa.c |  40 -
> > > >   hw/virtio/trace-events |   1 +
> > > >   4 files changed, 152 insertions(+), 23 deletions(-)
> > > >
> > > > diff --git a/hw/virtio/vhost-shadow-virtqueue.h 
> > > > b/hw/virtio/vhost-shadow-virtqueue.h
> > > > index b7baa424a7..a0e6b5267a 100644
> > > > --- a/hw/virtio/vhost-shadow-virtqueue.h
> > > > +++ b/hw/virtio/vhost-shadow-virtqueue.h
> > > > @@ -11,6 +11,7 @@
> > > >   #define VHOST_SHADOW_VIRTQUEUE_H
> > > >
> > > >   #include "hw/virtio/vhost.h"
> > > > +#include "hw/virtio/vhost-iova-tree.h"
> > > >
> > > >   typedef struct VhostShadowVirtqueue VhostShadowVirtqueue;
> > > >
> > > > @@ -28,7 +29,8 @@ bool vhost_svq_start(struct vhost_dev *dev, unsigned 
> > > > idx,
> > > >   void vhost_svq_stop(struct vhost_dev *dev, unsigned idx,
> > > >   VhostShadowVirtqueue *svq);
> > > >
> > > > -VhostShadowVirtqueue *vhost_svq_new(struct vhost_dev *dev, int idx);
> > > > +VhostShadowVirtqueue *vhost_svq_new(struct vhost_dev *dev, int idx,
> > > > +VhostIOVATree *iova_map);
> > > >
> > > >   void vhost_svq_free(VhostShadowVirtqueue *vq);
> > > >
> > > > diff --git a/hw/virtio/vhost-shadow-virtqueue.c 
> > > > b/hw/virtio/vhost-shadow-virtqueue.c
> > > > index 2fd0bab75d..9db538547e 100644
> > > > --- a/hw/virtio/vhost-shadow-virtqueue.c
> > > > +++ b/hw/virtio/vhost-shadow-virtqueue.c
> > > > @@ -11,12 +11,19 @@
> > > >   #include "hw/virtio/vhost-shadow-virtqueue.h"
> > > >   #include "hw/virtio/vhost.h"
> > > >   #include "hw/virtio/virtio-access.h"
> > > > +#include "hw/virtio/vhost-iova-tree.h"
> > > >
> > > >   #include "standard-headers/linux/vhost_types.h"
> > > >
> > > >   #include "qemu/error-report.h"
> > > >   #include "qemu/main-loop.h"
> > > >
> > > > +typedef struct SVQElement {
> > > > +VirtQueueElement elem;
> > > > +void **in_sg_stash;
> > > > +void **out_sg_stash;
> > > > +} SVQElement;
> > > > +
> > > >   /* Shadow virtqueue to relay notifications */
> > > >   typedef struct VhostShadowVirtqueue {
> > > >   /* Shadow vring */
> > > > @@ -46,8 +53,11 @@ typedef struct VhostShadowVirtqueue {
> > > >   /* Virtio device */
> > > >   VirtIODevice *vdev;
> > > >
> > > > +/* IOVA mapping if used */
> > > > +VhostIOVATree *iova_map;
> > > > +
> > > >   /* Map for returning guest's descriptors */
> > > > -VirtQueueElement **ring_id_maps;
> > > > +SVQElement **ring_id_maps;
> > > >
> > > >   /* Next head to expose to device */
> > > >   uint16_t avail_idx_shadow;
> > > > @@ -79,13 +89,6 @@ bool vhost_svq_valid_device_features(uint64_t 
> > > > *dev_features)
> > > >   continue;
> > > >
> > > >   case VIRTIO_F_ACCESS_PLATFORM:
> > > > -/* SVQ needs this feature disabled. Can't continue */
> > > > -if (*dev_features & BIT_ULL(b)) {
> > > > -clear_bit(b, dev_features);
> > > > -r = false;
> > > > -}
> > > > -break;
> > > > -
> > > >   case VIRTIO_F_VERSION_1:
> > > >   /* SVQ needs this feature, so can't continue */
> > > >   if (!(*dev_features & BIT_ULL(b))) {
> > > > @@ -126,6 +129,64 @@ static void 
> > > > vhost_svq_set_notification(VhostShadowVirtqueue *svq, bool enable)
> > > >   }
> > > >   }
> > > >
> > > > +static void vhost_svq_stash_addr(void ***stash, const struct iovec 
> > > > *iov,
> > > > + size_t num)
> > > > +{
> > > > +size_t i;
> > > > +
> > > > +if (num == 0) {
> > > > +return;
> > > > +}
> > > > +
> > > > +*stash = g_new(void *, num);
> > > > +for (i = 0; i < num; ++i) {
> > > > +(*stash)[i] = iov[i].iov_base;
> > > > +}
> > > > +}
> > > > +
> > > > +static void vhost_svq_unstash_addr(void **stash, struct iovec *iov, 
> > > > size_t num)
> > > > +{
> > > > +size_t i;
> > > > +
>

Re: [RFC PATCH v4 20/20] vdpa: Add custom IOTLB translations to SVQ

2021-10-19 Thread Jason Wang
On Tue, Oct 19, 2021 at 6:29 PM Eugenio Perez Martin
 wrote:
>
> On Tue, Oct 19, 2021 at 11:25 AM Jason Wang  wrote:
> >
> >
> > 在 2021/10/1 下午3:06, Eugenio Pérez 写道:
> > > Use translations added in VhostIOVATree in SVQ.
> > >
> > > Now every element needs to store the previous address also, so VirtQueue
> > > can consume the elements properly. This adds a little overhead per VQ
> > > element, having to allocate more memory to stash them. As a possible
> > > optimization, this allocation could be avoided if the descriptor is not
> > > a chain but a single one, but this is left undone.
> > >
> > > TODO: iova range should be queried before, and add logic to fail when
> > > GPA is outside of its range and memory listener or svq add it.
> > >
> > > Signed-off-by: Eugenio Pérez 
> > > ---
> > >   hw/virtio/vhost-shadow-virtqueue.h |   4 +-
> > >   hw/virtio/vhost-shadow-virtqueue.c | 130 -
> > >   hw/virtio/vhost-vdpa.c |  40 -
> > >   hw/virtio/trace-events |   1 +
> > >   4 files changed, 152 insertions(+), 23 deletions(-)
> > >
> > > diff --git a/hw/virtio/vhost-shadow-virtqueue.h 
> > > b/hw/virtio/vhost-shadow-virtqueue.h
> > > index b7baa424a7..a0e6b5267a 100644
> > > --- a/hw/virtio/vhost-shadow-virtqueue.h
> > > +++ b/hw/virtio/vhost-shadow-virtqueue.h
> > > @@ -11,6 +11,7 @@
> > >   #define VHOST_SHADOW_VIRTQUEUE_H
> > >
> > >   #include "hw/virtio/vhost.h"
> > > +#include "hw/virtio/vhost-iova-tree.h"
> > >
> > >   typedef struct VhostShadowVirtqueue VhostShadowVirtqueue;
> > >
> > > @@ -28,7 +29,8 @@ bool vhost_svq_start(struct vhost_dev *dev, unsigned 
> > > idx,
> > >   void vhost_svq_stop(struct vhost_dev *dev, unsigned idx,
> > >   VhostShadowVirtqueue *svq);
> > >
> > > -VhostShadowVirtqueue *vhost_svq_new(struct vhost_dev *dev, int idx);
> > > +VhostShadowVirtqueue *vhost_svq_new(struct vhost_dev *dev, int idx,
> > > +VhostIOVATree *iova_map);
> > >
> > >   void vhost_svq_free(VhostShadowVirtqueue *vq);
> > >
> > > diff --git a/hw/virtio/vhost-shadow-virtqueue.c 
> > > b/hw/virtio/vhost-shadow-virtqueue.c
> > > index 2fd0bab75d..9db538547e 100644
> > > --- a/hw/virtio/vhost-shadow-virtqueue.c
> > > +++ b/hw/virtio/vhost-shadow-virtqueue.c
> > > @@ -11,12 +11,19 @@
> > >   #include "hw/virtio/vhost-shadow-virtqueue.h"
> > >   #include "hw/virtio/vhost.h"
> > >   #include "hw/virtio/virtio-access.h"
> > > +#include "hw/virtio/vhost-iova-tree.h"
> > >
> > >   #include "standard-headers/linux/vhost_types.h"
> > >
> > >   #include "qemu/error-report.h"
> > >   #include "qemu/main-loop.h"
> > >
> > > +typedef struct SVQElement {
> > > +VirtQueueElement elem;
> > > +void **in_sg_stash;
> > > +void **out_sg_stash;
> > > +} SVQElement;
> > > +
> > >   /* Shadow virtqueue to relay notifications */
> > >   typedef struct VhostShadowVirtqueue {
> > >   /* Shadow vring */
> > > @@ -46,8 +53,11 @@ typedef struct VhostShadowVirtqueue {
> > >   /* Virtio device */
> > >   VirtIODevice *vdev;
> > >
> > > +/* IOVA mapping if used */
> > > +VhostIOVATree *iova_map;
> > > +
> > >   /* Map for returning guest's descriptors */
> > > -VirtQueueElement **ring_id_maps;
> > > +SVQElement **ring_id_maps;
> > >
> > >   /* Next head to expose to device */
> > >   uint16_t avail_idx_shadow;
> > > @@ -79,13 +89,6 @@ bool vhost_svq_valid_device_features(uint64_t 
> > > *dev_features)
> > >   continue;
> > >
> > >   case VIRTIO_F_ACCESS_PLATFORM:
> > > -/* SVQ needs this feature disabled. Can't continue */
> > > -if (*dev_features & BIT_ULL(b)) {
> > > -clear_bit(b, dev_features);
> > > -r = false;
> > > -}
> > > -break;
> > > -
> > >   case VIRTIO_F_VERSION_1:
> > >   /* SVQ needs this feature, so can't continue */
> > >   if (!(*dev_features & BIT_ULL(b))) {
> > > @@ -126,6 +129,64 @@ static void 
> > > vhost_svq_set_notification(VhostShadowVirtqueue *svq, bool enable)
> > >   }
> > >   }
> > >
> > > +static void vhost_svq_stash_addr(void ***stash, const struct iovec *iov,
> > > + size_t num)
> > > +{
> > > +size_t i;
> > > +
> > > +if (num == 0) {
> > > +return;
> > > +}
> > > +
> > > +*stash = g_new(void *, num);
> > > +for (i = 0; i < num; ++i) {
> > > +(*stash)[i] = iov[i].iov_base;
> > > +}
> > > +}
> > > +
> > > +static void vhost_svq_unstash_addr(void **stash, struct iovec *iov, 
> > > size_t num)
> > > +{
> > > +size_t i;
> > > +
> > > +if (num == 0) {
> > > +return;
> > > +}
> > > +
> > > +for (i = 0; i < num; ++i) {
> > > +iov[i].iov_base = stash[i];
> > > +}
> > > +g_free(stash);
> > > +}
> > > +
> > > +static void vhost_svq_translate_addr(const VhostShadowVirtqueue *svq,
> > > +   

Re: [RFC PATCH v4 11/20] vhost: Route host->guest notification through shadow virtqueue

2021-10-19 Thread Jason Wang
On Tue, Oct 19, 2021 at 4:40 PM Eugenio Perez Martin
 wrote:
>
> On Fri, Oct 15, 2021 at 6:42 AM Jason Wang  wrote:
> >
> >
> > 在 2021/10/15 上午12:39, Eugenio Perez Martin 写道:
> > > On Wed, Oct 13, 2021 at 5:47 AM Jason Wang  wrote:
> > >>
> > >> 在 2021/10/1 下午3:05, Eugenio Pérez 写道:
> > >>> This will make qemu aware of the device used buffers, allowing it to
> > >>> write the guest memory with its contents if needed.
> > >>>
> > >>> Since the use of vhost_virtqueue_start can unmasks and discard call
> > >>> events, vhost_virtqueue_start should be modified in one of these ways:
> > >>> * Split in two: One of them uses all logic to start a queue with no
> > >>> side effects for the guest, and another one tha actually assumes 
> > >>> that
> > >>> the guest has just started the device. Vdpa should use just the
> > >>> former.
> > >>> * Actually store and check if the guest notifier is masked, and do it
> > >>> conditionally.
> > >>> * Left as it is, and duplicate all the logic in vhost-vdpa.
> > >>>
> > >>> Signed-off-by: Eugenio Pérez 
> > >>> ---
> > >>>hw/virtio/vhost-shadow-virtqueue.c | 19 +++
> > >>>hw/virtio/vhost-vdpa.c | 38 
> > >>> +-
> > >>>2 files changed, 56 insertions(+), 1 deletion(-)
> > >>>
> > >>> diff --git a/hw/virtio/vhost-shadow-virtqueue.c 
> > >>> b/hw/virtio/vhost-shadow-virtqueue.c
> > >>> index 21dc99ab5d..3fe129cf63 100644
> > >>> --- a/hw/virtio/vhost-shadow-virtqueue.c
> > >>> +++ b/hw/virtio/vhost-shadow-virtqueue.c
> > >>> @@ -53,6 +53,22 @@ static void vhost_handle_guest_kick(EventNotifier *n)
> > >>>event_notifier_set(&svq->kick_notifier);
> > >>>}
> > >>>
> > >>> +/* Forward vhost notifications */
> > >>> +static void vhost_svq_handle_call_no_test(EventNotifier *n)
> > >>> +{
> > >>> +VhostShadowVirtqueue *svq = container_of(n, VhostShadowVirtqueue,
> > >>> + call_notifier);
> > >>> +
> > >>> +event_notifier_set(&svq->guest_call_notifier);
> > >>> +}
> > >>> +
> > >>> +static void vhost_svq_handle_call(EventNotifier *n)
> > >>> +{
> > >>> +if (likely(event_notifier_test_and_clear(n))) {
> > >>> +vhost_svq_handle_call_no_test(n);
> > >>> +}
> > >>> +}
> > >>> +
> > >>>/*
> > >>> * Obtain the SVQ call notifier, where vhost device notifies SVQ 
> > >>> that there
> > >>> * exists pending used buffers.
> > >>> @@ -180,6 +196,8 @@ VhostShadowVirtqueue *vhost_svq_new(struct 
> > >>> vhost_dev *dev, int idx)
> > >>>}
> > >>>
> > >>>svq->vq = virtio_get_queue(dev->vdev, vq_idx);
> > >>> +event_notifier_set_handler(&svq->call_notifier,
> > >>> +   vhost_svq_handle_call);
> > >>>return g_steal_pointer(&svq);
> > >>>
> > >>>err_init_call_notifier:
> > >>> @@ -195,6 +213,7 @@ err_init_kick_notifier:
> > >>>void vhost_svq_free(VhostShadowVirtqueue *vq)
> > >>>{
> > >>>event_notifier_cleanup(&vq->kick_notifier);
> > >>> +event_notifier_set_handler(&vq->call_notifier, NULL);
> > >>>event_notifier_cleanup(&vq->call_notifier);
> > >>>g_free(vq);
> > >>>}
> > >>> diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
> > >>> index bc34de2439..6c5f4c98b8 100644
> > >>> --- a/hw/virtio/vhost-vdpa.c
> > >>> +++ b/hw/virtio/vhost-vdpa.c
> > >>> @@ -712,13 +712,40 @@ static bool vhost_vdpa_svq_start_vq(struct 
> > >>> vhost_dev *dev, unsigned idx)
> > >>>{
> > >>>struct vhost_vdpa *v = dev->opaque;
> > >>>VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, 
> > >>> idx);
> > >>> -return vhost_svq_start(dev, idx, svq);
> > >>> +EventNotifier *vhost_call_notifier = 
> > >>> vhost_svq_get_svq_call_notifier(svq);
> > >>> +struct vhost_vring_file vhost_call_file = {
> > >>> +.index = idx + dev->vq_index,
> > >>> +.fd = event_notifier_get_fd(vhost_call_notifier),
> > >>> +};
> > >>> +int r;
> > >>> +bool b;
> > >>> +
> > >>> +/* Set shadow vq -> guest notifier */
> > >>> +assert(v->call_fd[idx]);
> > >>
> > >> We need aovid the asser() here. On which case we can hit this?
> > >>
> > > I would say that there is no way we can actually hit it, so let's remove 
> > > it.
> > >
> > >>> +vhost_svq_set_guest_call_notifier(svq, v->call_fd[idx]);
> > >>> +
> > >>> +b = vhost_svq_start(dev, idx, svq);
> > >>> +if (unlikely(!b)) {
> > >>> +return false;
> > >>> +}
> > >>> +
> > >>> +/* Set device -> SVQ notifier */
> > >>> +r = vhost_vdpa_set_vring_dev_call(dev, &vhost_call_file);
> > >>> +if (unlikely(r)) {
> > >>> +error_report("vhost_vdpa_set_vring_call for shadow vq failed");
> > >>> +return false;
> > >>> +}
> > >>
> > >> Similar to kick, do we need to set_vring_call() before vhost_svq_start()?
> > >>
> > > It should not matter at this moment because the device should not be
> > > started at this point and

Re: [PATCH 1/6] hw/riscv: microchip_pfsoc: Use MachineState::ram and MachineClass::default_ram_id

2021-10-19 Thread Bin Meng
Hi Igor,

On Tue, Oct 19, 2021 at 3:39 PM Igor Mammedov  wrote:
>
> On Mon, 18 Oct 2021 23:38:24 +0800
> Bin Meng  wrote:
>
> > Using memory_region_init_ram(), which can't possibly handle vhost-user,
> > and can't work as expected with '-numa node,memdev' options.
> >
> > Use MachineState::ram instead of manually initializing RAM memory
> > region, as well as by providing MachineClass::default_ram_id to
> > opt in to memdev scheme.
> >
> > Signed-off-by: Bin Meng 
> > ---
> >
> >  hw/riscv/microchip_pfsoc.c | 9 +++--
> >  1 file changed, 3 insertions(+), 6 deletions(-)
> >
> > diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
> > index e475b6d511..f10f55b488 100644
> > --- a/hw/riscv/microchip_pfsoc.c
> > +++ b/hw/riscv/microchip_pfsoc.c
> > @@ -459,7 +459,6 @@ static void 
> > microchip_icicle_kit_machine_init(MachineState *machine)
> >  const MemMapEntry *memmap = microchip_pfsoc_memmap;
> >  MicrochipIcicleKitState *s = MICROCHIP_ICICLE_KIT_MACHINE(machine);
> >  MemoryRegion *system_memory = get_system_memory();
> > -MemoryRegion *mem_low = g_new(MemoryRegion, 1);
> >  MemoryRegion *mem_low_alias = g_new(MemoryRegion, 1);
> >  MemoryRegion *mem_high = g_new(MemoryRegion, 1);
> >  MemoryRegion *mem_high_alias = g_new(MemoryRegion, 1);
> > @@ -486,16 +485,13 @@ static void 
> > microchip_icicle_kit_machine_init(MachineState *machine)
> >  qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
> >
> >  /* Register RAM */
> > -memory_region_init_ram(mem_low, NULL, "microchip.icicle.kit.ram_low",
> > -   memmap[MICROCHIP_PFSOC_DRAM_LO].size,
> > -   &error_fatal);
> >  memory_region_init_alias(mem_low_alias, NULL,
> >   "microchip.icicle.kit.ram_low.alias",
> > - mem_low, 0,
> > + machine->ram, 0,
> >   memmap[MICROCHIP_PFSOC_DRAM_LO_ALIAS].size);
> >  memory_region_add_subregion(system_memory,
> >  memmap[MICROCHIP_PFSOC_DRAM_LO].base,
> > -mem_low);
> > +machine->ram);
> >  memory_region_add_subregion(system_memory,
> >  memmap[MICROCHIP_PFSOC_DRAM_LO_ALIAS].base,
> >  mem_low_alias);
>
> looking at code it seems RAM is split between low and high regions,
> so converting only low region is wrong.
>
> I'd suggest something similar to 2dc9ce13d210 : taihu_405ep_init().
> i.e. ms->ram should hold whole RAM that is split between low and high
> using aliases.

Thank you for your pointers. I have just sent v2.

One note when looking at the taihu_405ep_init() implementation, the
following looks incorrect to me:

memory_region_init_alias(&ram_memories[1], NULL,
 "taihu_405ep.ram-1", machine->ram, ram_bases[1],
 ram_sizes[1]);

I think the 'offset' should be ram_sizes[0] instead of ram_bases[1],
although their values are the same which means they are two contiguous
regions, so it happens to work. But I might be nitpicking ...

>
> > @@ -606,6 +602,7 @@ static void 
> > microchip_icicle_kit_machine_class_init(ObjectClass *oc, void *data)
> > MICROCHIP_PFSOC_COMPUTE_CPU_COUNT;
> >  mc->min_cpus = MICROCHIP_PFSOC_MANAGEMENT_CPU_COUNT + 1;
> >  mc->default_cpus = mc->min_cpus;
> > +mc->default_ram_id = "microchip.icicle.kit.ram_low";
>
> given it is not versioned machine, so we don't have to worry about
> cross version migration here,
> so I'd use "microchip.icicle.kit.ram" for the name here
> and currently used "microchip.icicle.kit.ram_low" for corresponding alias

Regards,
Bin



Re: [PATCH v8 0/8] hw/arm/virt: Introduce cpu topology support

2021-10-19 Thread wangyanan (Y)

Ping... for review of the newly added ACPI patches.

On 2021/10/14 21:21, Yanan Wang wrote:

Hi,

This is the latest v8 with update in patch #6 and #8. Now only one
generic reference file for PPTT is added in tests/data/acpi/virt.
Machiel and Igor, please help to have a look, thanks!

And sorry for the name typo, definitely should be Michael of course.

Thanks,
Yanan

Description of this series:
Once the view of an accurate virtual cpu topology is provided to guest,
with a well-designed vCPU pinning to the pCPU we may get a huge benefit,
e.g., the scheduling performance improvement. See Dario Faggioli's
research and the related performance tests in [1] for reference.

This patch series introduces cpu topology support for Arm platform.
Both cpu-map in DT and ACPI PPTT table are introduced to store the
topology information. And we only describe the topology information
to 6.2 and newer virt machines, considering compatibility.

[1] 
https://kvmforum2020.sched.com/event/eE1y/virtual-topology-for-virtual-machines
-friend-or-foe-dario-faggioli-suse

Series tested locally on Arm64 machines kunpeng920.
After booting a Linux guest with "-smp 
16,sockets=4,cores=4,threads=1,maxcpus=16",
through lscpu we will see the information about CPU topology like:
Architecture:aarch64
Byte Order:  Little Endian
CPU(s):  16
On-line CPU(s) list: 0-15
Thread(s) per core:  1
Core(s) per socket:  4
Socket(s):   4
NUMA node(s):1
Vendor ID:   0x48
Model:   0
Stepping:0x1
BogoMIPS:200.00
NUMA node0 CPU(s):   0-15

and with "-smp 16" we will see:
Architecture:aarch64
Byte Order:  Little Endian
CPU(s):  16
On-line CPU(s) list: 0-15
Thread(s) per core:  1
Core(s) per socket:  16
Socket(s):   1
NUMA node(s):1
Vendor ID:   0x48
Model:   0
Stepping:0x1
BogoMIPS:200.00
NUMA node0 CPU(s):   0-15

Changelog:
v7->v8:
- rebased on top of master (commit e5b2333f24)
- only add one generic expected file for PPTT instead of four, which works
   fine enough for now (patch #6 and #8 updated)
- v7: 
https://lore.kernel.org/qemu-devel/20211007030746.10420-1-wangyana...@huawei.com/

v6->v7:
- rebased on top of master (commit ca61fa4b80)
- use newly introduced acpi_table_begin/acpi_table_end APIs to build PPTT
   (patch #5 updated)
- add reference files for PPTT to fix broken bios-table-test for Aarch64
   virt machine (patch #6-#8 added)
- v6: 
https://lore.kernel.org/qemu-devel/20210824122016.144364-1-wangyana...@huawei.com/

Andrew Jones (2):
   hw/arm/virt: Add cpu-map to device tree
   hw/acpi/aml-build: Add PPTT table

Yanan Wang (6):
   hw/arm/virt: Only describe cpu topology since virt-6.2
   device_tree: Add qemu_fdt_add_path
   hw/acpi/aml-build: Add Processor hierarchy node structure
   tests/data/acpi/virt: Add an empty expected file for PPTT
   hw/arm/virt-acpi-build: Generate PPTT table
   tests/data/acpi/virt: Update the empty expected file for PPTT

  hw/acpi/aml-build.c  |  86 +++
  hw/arm/virt-acpi-build.c |   8 +++-
  hw/arm/virt.c|  71 +
  include/hw/acpi/aml-build.h  |   7 +++
  include/hw/arm/virt.h|   4 +-
  include/sysemu/device_tree.h |   1 +
  softmmu/device_tree.c|  44 +-
  tests/data/acpi/virt/PPTT| Bin 0 -> 76 bytes
  8 files changed, 207 insertions(+), 14 deletions(-)
  create mode 100644 tests/data/acpi/virt/PPTT

--
2.19.1

.





Re: [PATCH v8 6/8] tests/data/acpi/virt: Add an empty expected file for PPTT

2021-10-19 Thread wangyanan (Y)

Ping...

On 2021/10/14 21:22, Yanan Wang wrote:

Add a generic empty binary file for the new introduced PPTT table
under tests/data/acpi/virt, and list it as files to be changed in
tests/qtest/bios-tables-test-allowed-diff.h

Signed-off-by: Yanan Wang 
---
  tests/data/acpi/virt/PPTT   | 0
  tests/qtest/bios-tables-test-allowed-diff.h | 1 +
  2 files changed, 1 insertion(+)
  create mode 100644 tests/data/acpi/virt/PPTT

diff --git a/tests/data/acpi/virt/PPTT b/tests/data/acpi/virt/PPTT
new file mode 100644
index 00..e69de29bb2
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..cb143a55a6 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,2 @@
  /* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/virt/PPTT",





[PATCH v2 5/6] hw/riscv: sifive_u: Use MachineState::ram and MachineClass::default_ram_id

2021-10-19 Thread Bin Meng
Using memory_region_init_ram(), which can't possibly handle vhost-user,
and can't work as expected with '-numa node,memdev' options.

Use MachineState::ram instead of manually initializing RAM memory
region, as well as by providing MachineClass::default_ram_id to
opt in to memdev scheme.

Signed-off-by: Bin Meng 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Igor Mammedov 
---

(no changes since v1)

 hw/riscv/sifive_u.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index fc5790b8ce..0217006c27 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -528,7 +528,6 @@ static void sifive_u_machine_init(MachineState *machine)
 const MemMapEntry *memmap = sifive_u_memmap;
 SiFiveUState *s = RISCV_U_MACHINE(machine);
 MemoryRegion *system_memory = get_system_memory();
-MemoryRegion *main_mem = g_new(MemoryRegion, 1);
 MemoryRegion *flash0 = g_new(MemoryRegion, 1);
 target_ulong start_addr = memmap[SIFIVE_U_DEV_DRAM].base;
 target_ulong firmware_end_addr, kernel_start_addr;
@@ -549,10 +548,8 @@ static void sifive_u_machine_init(MachineState *machine)
 qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
 
 /* register RAM */
-memory_region_init_ram(main_mem, NULL, "riscv.sifive.u.ram",
-   machine->ram_size, &error_fatal);
 memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DEV_DRAM].base,
-main_mem);
+machine->ram);
 
 /* register QSPI0 Flash */
 memory_region_init_ram(flash0, NULL, "riscv.sifive.u.flash0",
@@ -748,6 +745,7 @@ static void sifive_u_machine_class_init(ObjectClass *oc, 
void *data)
 mc->min_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + 1;
 mc->default_cpu_type = SIFIVE_U_CPU;
 mc->default_cpus = mc->min_cpus;
+mc->default_ram_id = "riscv.sifive.u.ram";
 
 object_class_property_add_bool(oc, "start-in-flash",
sifive_u_machine_get_start_in_flash,
-- 
2.25.1




[PATCH v2 3/6] hw/riscv: shakti_c: Use MachineState::ram and MachineClass::default_ram_id

2021-10-19 Thread Bin Meng
Using memory_region_init_ram(), which can't possibly handle vhost-user,
and can't work as expected with '-numa node,memdev' options.

Use MachineState::ram instead of manually initializing RAM memory
region, as well as by providing MachineClass::default_ram_id to
opt in to memdev scheme.

Signed-off-by: Bin Meng 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Igor Mammedov 
---

(no changes since v1)

 hw/riscv/shakti_c.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
index d7d1f91fa5..90e2cf609f 100644
--- a/hw/riscv/shakti_c.c
+++ b/hw/riscv/shakti_c.c
@@ -45,7 +45,6 @@ static void shakti_c_machine_state_init(MachineState *mstate)
 {
 ShaktiCMachineState *sms = RISCV_SHAKTI_MACHINE(mstate);
 MemoryRegion *system_memory = get_system_memory();
-MemoryRegion *main_mem = g_new(MemoryRegion, 1);
 
 /* Allow only Shakti C CPU for this platform */
 if (strcmp(mstate->cpu_type, TYPE_RISCV_CPU_SHAKTI_C) != 0) {
@@ -59,11 +58,9 @@ static void shakti_c_machine_state_init(MachineState *mstate)
 qdev_realize(DEVICE(&sms->soc), NULL, &error_abort);
 
 /* register RAM */
-memory_region_init_ram(main_mem, NULL, "riscv.shakti.c.ram",
-   mstate->ram_size, &error_fatal);
 memory_region_add_subregion(system_memory,
 shakti_c_memmap[SHAKTI_C_RAM].base,
-main_mem);
+mstate->ram);
 
 /* ROM reset vector */
 riscv_setup_rom_reset_vec(mstate, &sms->soc.cpus,
@@ -88,6 +85,7 @@ static void shakti_c_machine_class_init(ObjectClass *klass, 
void *data)
 mc->desc = "RISC-V Board compatible with Shakti SDK";
 mc->init = shakti_c_machine_state_init;
 mc->default_cpu_type = TYPE_RISCV_CPU_SHAKTI_C;
+mc->default_ram_id = "riscv.shakti.c.ram";
 }
 
 static const TypeInfo shakti_c_machine_type_info = {
-- 
2.25.1




Re: [PATCH v8 8/8] tests/data/acpi/virt: Update the empty expected file for PPTT

2021-10-19 Thread wangyanan (Y)

Ping...

On 2021/10/14 21:22, Yanan Wang wrote:

Run ./tests/data/acpi/rebuild-expected-aml.sh from build directory
to update PPTT binary. Also empty bios-tables-test-allowed-diff.h.

Disassembled output of the updated new file:

/*
  * Intel ACPI Component Architecture
  * AML/ASL+ Disassembler version 20180810 (64-bit version)
  * Copyright (c) 2000 - 2018 Intel Corporation
  *
  * Disassembly of tests/data/acpi/virt/PPTT, Fri Oct  8 10:12:32 2021
  *
  * ACPI Data Table [PPTT]
  *
  * Format: [HexOffset DecimalOffset ByteLength]  FieldName : FieldValue
  */

[000h    4]Signature : "PPTT"[Processor Properties 
Topology Table]
[004h 0004   4] Table Length : 004C
[008h 0008   1] Revision : 02
[009h 0009   1] Checksum : A8
[00Ah 0010   6]   Oem ID : "BOCHS "
[010h 0016   8] Oem Table ID : "BXPC"
[018h 0024   4] Oem Revision : 0001
[01Ch 0028   4]  Asl Compiler ID : "BXPC"
[020h 0032   4]Asl Compiler Revision : 0001

[024h 0036   1]Subtable Type : 00 [Processor Hierarchy Node]
[025h 0037   1]   Length : 14
[026h 0038   2] Reserved : 
[028h 0040   4]Flags (decoded below) : 0001
 Physical package : 1
  ACPI Processor ID valid : 0
[02Ch 0044   4]   Parent : 
[030h 0048   4]ACPI Processor ID : 
[034h 0052   4]  Private Resource Number : 

[038h 0056   1]Subtable Type : 00 [Processor Hierarchy Node]
[039h 0057   1]   Length : 14
[03Ah 0058   2] Reserved : 
[03Ch 0060   4]Flags (decoded below) : 000A
 Physical package : 0
  ACPI Processor ID valid : 1
[040h 0064   4]   Parent : 0024
[044h 0068   4]ACPI Processor ID : 
[048h 0072   4]  Private Resource Number : 

Raw Table Data: Length 76 (0x4C)

 : 50 50 54 54 4C 00 00 00 02 A8 42 4F 43 48 53 20  // PPTTL.BOCHS
 0010: 42 58 50 43 20 20 20 20 01 00 00 00 42 58 50 43  // BXPCBXPC
 0020: 01 00 00 00 00 14 00 00 01 00 00 00 00 00 00 00  // 
 0030: 00 00 00 00 00 00 00 00 00 14 00 00 0A 00 00 00  // 
 0040: 24 00 00 00 00 00 00 00 00 00 00 00  // $...

Signed-off-by: Yanan Wang 
---
  tests/data/acpi/virt/PPTT   | Bin 0 -> 76 bytes
  tests/qtest/bios-tables-test-allowed-diff.h |   1 -
  2 files changed, 1 deletion(-)

diff --git a/tests/data/acpi/virt/PPTT b/tests/data/acpi/virt/PPTT
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7a1258ecf123555b24462c98ccbb76b4ac1d0c2b
 100644
GIT binary patch
literal 76
zcmV-S0JHy4P*hY*2s6tOeNK+s}SWrVCARr(C&SWrU&06aWAL0
i0006aWAUa01^0tW#A

literal 0
KcmV+b0RR631

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index cb143a55a6..dfb8523c8b 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1,2 +1 @@
  /* List of comma-separated changed AML files to ignore */
-"tests/data/acpi/virt/PPTT",





[PATCH v2 6/6] hw/riscv: spike: Use MachineState::ram and MachineClass::default_ram_id

2021-10-19 Thread Bin Meng
Using memory_region_init_ram(), which can't possibly handle vhost-user,
and can't work as expected with '-numa node,memdev' options.

Use MachineState::ram instead of manually initializing RAM memory
region, as well as by providing MachineClass::default_ram_id to
opt in to memdev scheme.

Signed-off-by: Bin Meng 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Igor Mammedov 

---

(no changes since v1)

 hw/riscv/spike.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index 79ae355ae2..288d69cd9f 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -180,7 +180,6 @@ static void spike_board_init(MachineState *machine)
 const MemMapEntry *memmap = spike_memmap;
 SpikeState *s = SPIKE_MACHINE(machine);
 MemoryRegion *system_memory = get_system_memory();
-MemoryRegion *main_mem = g_new(MemoryRegion, 1);
 MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
 target_ulong firmware_end_addr, kernel_start_addr;
 uint32_t fdt_load_addr;
@@ -239,10 +238,8 @@ static void spike_board_init(MachineState *machine)
 }
 
 /* register system main memory (actual RAM) */
-memory_region_init_ram(main_mem, NULL, "riscv.spike.ram",
-   machine->ram_size, &error_fatal);
 memory_region_add_subregion(system_memory, memmap[SPIKE_DRAM].base,
-main_mem);
+machine->ram);
 
 /* create device tree */
 create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline,
@@ -326,6 +323,7 @@ static void spike_machine_class_init(ObjectClass *oc, void 
*data)
 mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props;
 mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id;
 mc->numa_mem_supported = true;
+mc->default_ram_id = "riscv.spike.ram";
 }
 
 static const TypeInfo spike_machine_typeinfo = {
-- 
2.25.1




[PATCH v2 2/6] hw/riscv: opentitan: Use MachineState::ram and MachineClass::default_ram_id

2021-10-19 Thread Bin Meng
Using memory_region_init_ram(), which can't possibly handle vhost-user,
and can't work as expected with '-numa node,memdev' options.

Use MachineState::ram instead of manually initializing RAM memory
region, as well as by providing MachineClass::default_ram_id to
opt in to memdev scheme.

While at it add check for user supplied RAM size and error out if it
mismatches board expected value.

Signed-off-by: Bin Meng 

---

Changes in v2:
- add RAM size check
- assign mc->default_ram_size

 hw/riscv/opentitan.c | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
index 9803ae6d70..5d568ea58a 100644
--- a/hw/riscv/opentitan.c
+++ b/hw/riscv/opentitan.c
@@ -19,6 +19,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/cutils.h"
 #include "hw/riscv/opentitan.h"
 #include "qapi/error.h"
 #include "hw/boards.h"
@@ -64,20 +65,25 @@ static const MemMapEntry ibex_memmap[] = {
 
 static void opentitan_board_init(MachineState *machine)
 {
+MachineClass *mc = MACHINE_GET_CLASS(machine);
 const MemMapEntry *memmap = ibex_memmap;
 OpenTitanState *s = g_new0(OpenTitanState, 1);
 MemoryRegion *sys_mem = get_system_memory();
-MemoryRegion *main_mem = g_new(MemoryRegion, 1);
+
+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);
+exit(EXIT_FAILURE);
+}
 
 /* Initialize SoC */
 object_initialize_child(OBJECT(machine), "soc", &s->soc,
 TYPE_RISCV_IBEX_SOC);
 qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
 
-memory_region_init_ram(main_mem, NULL, "riscv.lowrisc.ibex.ram",
-memmap[IBEX_DEV_RAM].size, &error_fatal);
 memory_region_add_subregion(sys_mem,
-memmap[IBEX_DEV_RAM].base, main_mem);
+memmap[IBEX_DEV_RAM].base, machine->ram);
 
 if (machine->firmware) {
 riscv_load_firmware(machine->firmware, memmap[IBEX_DEV_RAM].base, 
NULL);
@@ -95,6 +101,8 @@ static void opentitan_machine_init(MachineClass *mc)
 mc->init = opentitan_board_init;
 mc->max_cpus = 1;
 mc->default_cpu_type = TYPE_RISCV_CPU_IBEX;
+mc->default_ram_id = "riscv.lowrisc.ibex.ram";
+mc->default_ram_size = ibex_memmap[IBEX_DEV_RAM].size;
 }
 
 DEFINE_MACHINE("opentitan", opentitan_machine_init)
-- 
2.25.1




[PATCH v2 4/6] hw/riscv: sifive_e: Use MachineState::ram and MachineClass::default_ram_id

2021-10-19 Thread Bin Meng
Using memory_region_init_ram(), which can't possibly handle vhost-user,
and can't work as expected with '-numa node,memdev' options.

Use MachineState::ram instead of manually initializing RAM memory
region, as well as by providing MachineClass::default_ram_id to
opt in to memdev scheme.

While at it add check for user supplied RAM size and error out if it
mismatches board expected value.

Signed-off-by: Bin Meng 

---

Changes in v2:
- add RAM size check
- assign mc->default_ram_size

 hw/riscv/sifive_e.c | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index 6e95ea5896..9b206407a6 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -29,6 +29,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/cutils.h"
 #include "qemu/error-report.h"
 #include "qapi/error.h"
 #include "hw/boards.h"
@@ -71,22 +72,27 @@ static const MemMapEntry sifive_e_memmap[] = {
 
 static void sifive_e_machine_init(MachineState *machine)
 {
+MachineClass *mc = MACHINE_GET_CLASS(machine);
 const MemMapEntry *memmap = sifive_e_memmap;
 
 SiFiveEState *s = RISCV_E_MACHINE(machine);
 MemoryRegion *sys_mem = get_system_memory();
-MemoryRegion *main_mem = g_new(MemoryRegion, 1);
 int i;
 
+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);
+exit(EXIT_FAILURE);
+}
+
 /* Initialize SoC */
 object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_E_SOC);
 qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
 
 /* Data Tightly Integrated Memory */
-memory_region_init_ram(main_mem, NULL, "riscv.sifive.e.ram",
-memmap[SIFIVE_E_DEV_DTIM].size, &error_fatal);
 memory_region_add_subregion(sys_mem,
-memmap[SIFIVE_E_DEV_DTIM].base, main_mem);
+memmap[SIFIVE_E_DEV_DTIM].base, machine->ram);
 
 /* Mask ROM reset vector */
 uint32_t reset_vec[4];
@@ -142,6 +148,8 @@ static void sifive_e_machine_class_init(ObjectClass *oc, 
void *data)
 mc->init = sifive_e_machine_init;
 mc->max_cpus = 1;
 mc->default_cpu_type = SIFIVE_E_CPU;
+mc->default_ram_id = "riscv.sifive.e.ram";
+mc->default_ram_size = sifive_e_memmap[SIFIVE_E_DEV_DTIM].size;
 
 object_class_property_add_bool(oc, "revb", sifive_e_machine_get_revb,
sifive_e_machine_set_revb);
-- 
2.25.1




[PATCH v2 1/6] hw/riscv: microchip_pfsoc: Use MachineState::ram and MachineClass::default_ram_id

2021-10-19 Thread Bin Meng
Using memory_region_init_ram(), which can't possibly handle vhost-user,
and can't work as expected with '-numa node,memdev' options.

Use MachineState::ram instead of manually initializing RAM memory
region, as well as by providing MachineClass::default_ram_id to
opt in to memdev scheme.

Signed-off-by: Bin Meng 

---

Changes in v2:
- split RAM into low and high regions using aliases to machine->ram
- rename mc->default_ram_id to "microchip.icicle.kit.ram"

 hw/riscv/microchip_pfsoc.c | 36 
 1 file changed, 20 insertions(+), 16 deletions(-)

diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
index e475b6d511..3fc8545562 100644
--- a/hw/riscv/microchip_pfsoc.c
+++ b/hw/riscv/microchip_pfsoc.c
@@ -463,7 +463,7 @@ static void microchip_icicle_kit_machine_init(MachineState 
*machine)
 MemoryRegion *mem_low_alias = g_new(MemoryRegion, 1);
 MemoryRegion *mem_high = g_new(MemoryRegion, 1);
 MemoryRegion *mem_high_alias = g_new(MemoryRegion, 1);
-uint64_t mem_high_size;
+uint64_t mem_low_size, mem_high_size;
 hwaddr firmware_load_addr;
 const char *firmware_name;
 bool kernel_as_payload = false;
@@ -485,31 +485,34 @@ static void 
microchip_icicle_kit_machine_init(MachineState *machine)
 TYPE_MICROCHIP_PFSOC);
 qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
 
+/* Split RAM into low and high regions using aliases to machine->ram */
+mem_low_size = memmap[MICROCHIP_PFSOC_DRAM_LO].size;
+mem_high_size = machine->ram_size - mem_low_size;
+memory_region_init_alias(mem_low, NULL,
+ "microchip.icicle.kit.ram_low", machine->ram,
+ 0, mem_low_size);
+memory_region_init_alias(mem_high, NULL,
+ "microchip.icicle.kit.ram_high", machine->ram,
+ mem_low_size, mem_high_size);
+
 /* Register RAM */
-memory_region_init_ram(mem_low, NULL, "microchip.icicle.kit.ram_low",
-   memmap[MICROCHIP_PFSOC_DRAM_LO].size,
-   &error_fatal);
-memory_region_init_alias(mem_low_alias, NULL,
- "microchip.icicle.kit.ram_low.alias",
- mem_low, 0,
- memmap[MICROCHIP_PFSOC_DRAM_LO_ALIAS].size);
 memory_region_add_subregion(system_memory,
 memmap[MICROCHIP_PFSOC_DRAM_LO].base,
 mem_low);
+memory_region_add_subregion(system_memory,
+memmap[MICROCHIP_PFSOC_DRAM_HI].base,
+mem_high);
+
+/* Create aliases for the low and high RAM regions */
+memory_region_init_alias(mem_low_alias, NULL,
+ "microchip.icicle.kit.ram_low.alias",
+ mem_low, 0, mem_low_size);
 memory_region_add_subregion(system_memory,
 memmap[MICROCHIP_PFSOC_DRAM_LO_ALIAS].base,
 mem_low_alias);
-
-mem_high_size = machine->ram_size - 1 * GiB;
-
-memory_region_init_ram(mem_high, NULL, "microchip.icicle.kit.ram_high",
-   mem_high_size, &error_fatal);
 memory_region_init_alias(mem_high_alias, NULL,
  "microchip.icicle.kit.ram_high.alias",
  mem_high, 0, mem_high_size);
-memory_region_add_subregion(system_memory,
-memmap[MICROCHIP_PFSOC_DRAM_HI].base,
-mem_high);
 memory_region_add_subregion(system_memory,
 memmap[MICROCHIP_PFSOC_DRAM_HI_ALIAS].base,
 mem_high_alias);
@@ -606,6 +609,7 @@ static void 
microchip_icicle_kit_machine_class_init(ObjectClass *oc, void *data)
MICROCHIP_PFSOC_COMPUTE_CPU_COUNT;
 mc->min_cpus = MICROCHIP_PFSOC_MANAGEMENT_CPU_COUNT + 1;
 mc->default_cpus = mc->min_cpus;
+mc->default_ram_id = "microchip.icicle.kit.ram";
 
 /*
  * Map 513 MiB high memory, the mimimum required high memory size, because
-- 
2.25.1




[PATCH v2 0/6] hw/riscv: Use MachineState::ram and MachineClass::default_ram_id in all machines

2021-10-19 Thread Bin Meng
As of today, all RISC-V machines (except virt) are still using 
memory_region_init_ram()
to initilize the sysytem RAM, which can't possibly handle vhost-user, and can't
work as expected with '-numa node,memdev' options.

Change to use MachineState::ram instead of manually initializing RAM memory
region, as well as by providing MachineClass::default_ram_id to opt in to
memdev scheme.

Changes in v2:
- split RAM into low and high regions using aliases to machine->ram
- rename mc->default_ram_id to "microchip.icicle.kit.ram"
- opentitan: add RAM size check
- opentitan: assign mc->default_ram_size
- sifive_e: add RAM size check
- sifive_e: assign mc->default_ram_size

Bin Meng (6):
  hw/riscv: microchip_pfsoc: Use MachineState::ram and
MachineClass::default_ram_id
  hw/riscv: opentitan: Use MachineState::ram and
MachineClass::default_ram_id
  hw/riscv: shakti_c: Use MachineState::ram and
MachineClass::default_ram_id
  hw/riscv: sifive_e: Use MachineState::ram and
MachineClass::default_ram_id
  hw/riscv: sifive_u: Use MachineState::ram and
MachineClass::default_ram_id
  hw/riscv: spike: Use MachineState::ram and
MachineClass::default_ram_id

 hw/riscv/microchip_pfsoc.c | 36 
 hw/riscv/opentitan.c   | 16 
 hw/riscv/shakti_c.c|  6 ++
 hw/riscv/sifive_e.c| 16 
 hw/riscv/sifive_u.c|  6 ++
 hw/riscv/spike.c   |  6 ++
 6 files changed, 50 insertions(+), 36 deletions(-)

-- 
2.25.1




Re: [PATCH 07/31] target/loongarch: Add loongarch csr/iocsr instruction support

2021-10-19 Thread Richard Henderson

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:

+target_ulong helper_csr_rdq(CPULoongArchState *env, uint64_t csr)
+{
+int64_t v;
+
+#define CASE_CSR_RDQ(csr)\
+case LOONGARCH_CSR_ ## csr:  \
+{\
+v = env->CSR_ ## csr;\
+break;   \
+};   \


There's absolutely no reason to call a helper function for a simple load.


+case LOONGARCH_CSR_PGD:
+
+if (env->CSR_TLBRERA & 0x1) {
+v = env->CSR_TLBRBADV;
+} else {
+v = env->CSR_BADV;
+}
+
+if ((v >> 63) & 0x1) {
+v = env->CSR_PGDH;
+} else {
+v = env->CSR_PGDL;
+}
+break;


This is the only one that requires a helper on read.


+if (csr == LOONGARCH_CSR_ASID) {
+if (old_v != val) {
+tlb_flush(env_cpu(env));
+}
+}


And this is the only one that requires a helper on write.


+case LOONGARCH_CSR_ESTAT:
+qatomic_and(&env->CSR_ESTAT, ~mask);


Why do you believe this requires an atomic update?
What is going to race with the update to a cpu private value?


+static bool trans_csrrd(DisasContext *ctx, unsigned rd, unsigned csr)
+{
+TCGv dest = gpr_dst(ctx, rd, EXT_NONE);
+gen_helper_csr_rdq(dest, cpu_env, tcg_constant_i64(csr));
+return true;
+}
+
+static bool trans_csrwr(DisasContext *ctx, unsigned rd, unsigned csr)
+{
+TCGv dest = gpr_dst(ctx, rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, rd, EXT_NONE);
+
+switch (csr) {
+case LOONGARCH_CSR_CRMD:
+tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
+gen_helper_csr_wrq(dest, cpu_env, src1, 
tcg_constant_i64(LOONGARCH_CSR_CRMD));
+tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next + 4);
+ctx->base.is_jmp = DISAS_EXIT;
+break;
+case LOONGARCH_CSR_EUEN:
+gen_helper_csr_wrq(dest, cpu_env, src1, 
tcg_constant_i64(LOONGARCH_CSR_EUEN));
+/* Stop translation */
+tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next + 4);
+ctx->base.is_jmp = DISAS_EXIT;
+break;
+default:
+gen_helper_csr_wrq(dest, cpu_env, src1, tcg_constant_i64(csr));
+break;
+}
+return true;
+}
+
+static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rd, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rj, EXT_NONE);
+
+if (a->rj == 0) {
+return trans_csrrd(ctx, a->rd, a->csr);
+} else if (a->rj == 1) {
+return trans_csrwr(ctx, a->rd, a->csr);
+}


These should have been decoded separately; see below.

You're missing the check for priv 0 here and in all other functions.


+
+if (a->rd == 0) {
+gen_helper_csr_xchgq_r0(cpu_env, src2, tcg_constant_i64(a->csr));
+} else {
+gen_helper_csr_xchgq(dest, cpu_env, src1, src2, 
tcg_constant_i64(a->csr));
+}


Why do you believe r0 to require a special case?


+static bool trans_iocsrrd_b(DisasContext *ctx, arg_iocsrrd_b *a)
+{
+TCGv tmp = tcg_temp_new();
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+gen_helper_iocsr_read(tmp, cpu_env, src1);
+tcg_gen_qemu_ld_tl(dest, tmp, ctx->mem_idx, MO_SB);


This is wrong.  From the manual:

  All IOCSR registers use independent addressing space

therefore you cannot simply read from a modified address, you must use a completely 
different address space.


There are a couple of different solutions that are possible.

(1) Use helper functions calling address_space_ld/st*.

(2) Use a separate mmu_idx, which uses its own address space.
This requires bouncing through MemTxAttrs, since
cpu_asidx_from_attrs only take attrs and not mmu_idx.

The second one is may be overkill, unless there will be any cachable memory in iospace.  I 
would expect most of it to be device memory.



+csrxchg   0100 .. . . @fmt_rdrjcsr


{
  csrrd  0100 .. 0 . @fmt_rdcsr
  csrwr  0100 .. 1 . @fmt_rdcsr
  csrxchg    0100 .. . . @fmt_rdrjcsr
}


r~



Re: [PATCH] hw/qdev-core: Add compatibility for (non)-transitional devs

2021-10-19 Thread Jason Wang
On Wed, Oct 20, 2021 at 12:56 AM Eduardo Habkost  wrote:
>
> On Tue, Oct 19, 2021 at 12:13:17PM -0400, Michael S. Tsirkin wrote:
> > On Tue, Oct 19, 2021 at 11:29:13AM -0400, Eduardo Habkost wrote:
> > > On Tue, Oct 19, 2021 at 06:59:09AM -0400, Michael S. Tsirkin wrote:
> > > > On Tue, Oct 19, 2021 at 11:46:17AM +0100, Stefan Hajnoczi wrote:
> > > > > On Tue, Oct 12, 2021 at 10:36:01AM +0200, Jean-Louis Dupond wrote:
> > > > > > Forgot to CC maintainers.
> > > > >
> > > > > Also CCing Jason Wang and Michael Tsirkin for VIRTIO.
> > > > >
> > > > > Stefan
> > > >
> > > > OMG
> > > > where all compat properties broken all the time?
> > >
> > > Compat properties that existed when commit f6e501a28ef9 ("virtio:
> > > Provide version-specific variants of virtio PCI devices") was
> > > merged are not broken, because virtio-*-transitional and
> > > virtio-*-non-transitional were brand new QOM types (so there's no
> > > compatibility to be kept with old QEMU versions).
> > >
> > > Compat properties referencing "virtio-*-pci" instead of
> > > "virtio-*-pci-base" added after commit f6e501a28ef9 are probably
> > > broken, yes.
> > >
> > > --
> > > Eduardo
> >
> > Oh. So just this one:
> > { "virtio-net-pci", "vectors", "3"},
> >
> > right?
>
> I think so.  That's the only post-4.0 virtio-*-pci compat property I see in
> hw/core/machine.c.
>
> pc.c doesn't have any post-4.0 virtio-*-pci compat props.  I didn't see any
> virtio compat props on spapr.c and s390-virtio-ccw.c.
>
> >
> > about the patch: how do people feel about virtio specific
> > stuff in qdev core? Ok by everyone?
>
> Not OK, if we have a mechanism to avoid that, already (the
> "virtio-net-pci-base" type name).  I wonder what we can do to
> make this kind of mistake less likely, though.
>
> Jean-Louis, Jason, does the following fix work?

Yes.

Acked-by: Jason Wang 

Thanks

>
> Signed-off-by: Eduardo Habkost 
> ---
> diff --git a/hw/core/machine.c b/hw/core/machine.c
> index b8d95eec32d..bd9c6156c1a 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c
> @@ -56,7 +56,7 @@ GlobalProperty hw_compat_5_2[] = {
>  { "ICH9-LPC", "smm-compat", "on"},
>  { "PIIX4_PM", "smm-compat", "on"},
>  { "virtio-blk-device", "report-discard-granularity", "off" },
> -{ "virtio-net-pci", "vectors", "3"},
> +{ "virtio-net-pci-base", "vectors", "3"},
>  };
>  const size_t hw_compat_5_2_len = G_N_ELEMENTS(hw_compat_5_2);
>
> --
> Eduardo
>




Re: [PATCH v5 14/16] target/riscv: Align gprs and fprs in cpu_dump

2021-10-19 Thread Richard Henderson

On 10/19/21 3:10 PM, Alistair Francis wrote:

On Wed, Oct 20, 2021 at 2:18 AM Richard Henderson
 wrote:


Allocate 8 columns per register name.

Reviewed-by: LIU Zhiwei 
Signed-off-by: Richard Henderson 


Reviewed-by: Alistair Francis 

This probably isn't required though as there is already a similar
patch in my tree:
https://github.com/alistair23/qemu/tree/riscv-to-apply.next


Ah yes.  Just drop my version, I think.  I can rebase on your branch too, since I see a 
conflict with that patch.



r~



Re: [PATCH 00/64] Patch Round-up for stable 6.0.1, freeze on 2021-10-26

2021-10-19 Thread Ani Sinha
On Tue, Oct 19, 2021 at 23:53 Michael Roth  wrote:

> Quoting Ani Sinha (2021-10-19 09:43:52)
> >
> >
> > On Tue, 19 Oct 2021, Michael Roth wrote:
> >
> > > Hi everyone,
> > >
> > > The following new patches are queued for QEMU stable v6.0.1:
> > >
> > >   https://gitlab.com/qemu-project/qemu/-/commits/stable-6.0-staging/
> > >
> > > Patch freeze is 2021-10-26, and the release is planned for 2021-10-28:
> > >
> > >   https://wiki.qemu.org/Planning/6.0
> > >
> > > Please respond here or CC qemu-sta...@nongnu.org on any additional
> patches
> > > you think should (or shouldn't) be included in the release.
> >
> > I believe we should also include this patch:
> >
> https://lore.kernel.org/qemu-devel/20210916132838.3469580-2-...@anisinha.ca/T/
> >
> > It is also CC'd to qemu-stable@ but the patch itself was not tagged so
> (my
> > apologies for that).
>
> It looks like this patch is a fix for:
>
>   commit caf108bc587908f7608729f39639dccdfa53010b
>   Author: Julia Suvorova 
>   Date:   Tue Jul 13 02:42:00 2021 +0200
>
>   hw/i386/acpi-build: Add ACPI PCI hot-plug methods to Q35
>
> which is in 6.1.0, but not 6.0.0, so it didn't seem like it was needed
> for 6.0.1. Let me know if that's incorrect.
>
> Will definitely pull it in for 6.1.1 though.


Yes you are correct. This should be pulled in for 6.1.1 and not 6.0.1. In
fact for 6.0.1 there will likely be a conflict and the patch won’t apply.
Apologies for the noise.

>
>


Re: [PATCH v8 10/10] ACPI ERST: step 6 of bios-tables-test.c

2021-10-19 Thread Eric DeVolder

Ani, below. Eric

On 10/19/21 09:58, Ani Sinha wrote:



On Fri, 15 Oct 2021, Eric DeVolder wrote:


Following the guidelines in tests/qtest/bios-tables-test.c, this
is step 6.

Below is the disassembly of an ERST table, tests/data/acpi/pc/ERST.
This is a PCI device and as such its base address can change; it
is possible for the address fields to differ between this and other
ERST tables.

[000h    4]Signature : "ERST"[Error Record 
Serialization Table]
[004h 0004   4] Table Length : 0390
[008h 0008   1] Revision : 01
[009h 0009   1] Checksum : D6
[00Ah 0010   6]   Oem ID : "BOCHS "
[010h 0016   8] Oem Table ID : "BXPC"
[018h 0024   4] Oem Revision : 0001
[01Ch 0028   4]  Asl Compiler ID : "BXPC"
[020h 0032   4]Asl Compiler Revision : 0001

[024h 0036   4]  Serialization Header Length : 0030
[028h 0040   4] Reserved : 
[02Ch 0044   4]  Instruction Entry Count : 001B

[030h 0048   1]   Action : 00 [Begin Write Operation]
[031h 0049   1]  Instruction : 03 [Write Register Value]
[032h 0050   1]Flags (decoded below) : 00
   Preserve Register Bits : 0
[033h 0051   1] Reserved : 00

[034h 0052  12]  Register Region : [Generic Address Structure]
[034h 0052   1] Space ID : 00 [SystemMemory]
[035h 0053   1]Bit Width : 20
[036h 0054   1]   Bit Offset : 00
[037h 0055   1] Encoded Access Width : 03 [DWord Access:32]
[038h 0056   8]  Address : FEBF3000

[040h 0064   8]Value : 
[048h 0072   8] Mask : 00FF

[050h 0080   1]   Action : 01 [Begin Read Operation]
[051h 0081   1]  Instruction : 03 [Write Register Value]
[052h 0082   1]Flags (decoded below) : 00
   Preserve Register Bits : 0
[053h 0083   1] Reserved : 00

[054h 0084  12]  Register Region : [Generic Address Structure]
[054h 0084   1] Space ID : 00 [SystemMemory]
[055h 0085   1]Bit Width : 20
[056h 0086   1]   Bit Offset : 00
[057h 0087   1] Encoded Access Width : 03 [DWord Access:32]
[058h 0088   8]  Address : FEBF3000

[060h 0096   8]Value : 0001
[068h 0104   8] Mask : 00FF

[070h 0112   1]   Action : 02 [Begin Clear Operation]
[071h 0113   1]  Instruction : 03 [Write Register Value]
[072h 0114   1]Flags (decoded below) : 00
   Preserve Register Bits : 0
[073h 0115   1] Reserved : 00

[074h 0116  12]  Register Region : [Generic Address Structure]
[074h 0116   1] Space ID : 00 [SystemMemory]
[075h 0117   1]Bit Width : 20
[076h 0118   1]   Bit Offset : 00
[077h 0119   1] Encoded Access Width : 03 [DWord Access:32]
[078h 0120   8]  Address : FEBF3000

[080h 0128   8]Value : 0002
[088h 0136   8] Mask : 00FF

[090h 0144   1]   Action : 03 [End Operation]
[091h 0145   1]  Instruction : 03 [Write Register Value]
[092h 0146   1]Flags (decoded below) : 00
   Preserve Register Bits : 0
[093h 0147   1] Reserved : 00

[094h 0148  12]  Register Region : [Generic Address Structure]
[094h 0148   1] Space ID : 00 [SystemMemory]
[095h 0149   1]Bit Width : 20
[096h 0150   1]   Bit Offset : 00
[097h 0151   1] Encoded Access Width : 03 [DWord Access:32]
[098h 0152   8]  Address : FEBF3000

[0A0h 0160   8]Value : 0003
[0A8h 0168   8] Mask : 00FF

[0B0h 0176   1]   Action : 04 [Set Record Offset]
[0B1h 0177   1]  Instruction : 02 [Write Register]
[0B2h 0178   1]Flags (decoded below) : 00
   Preserve Register Bits : 0
[0B3h 0179   1] Reserved : 00

[0B4h 0180  12]  Register Region : [Generic Address Structure]
[0B4h 0180   1] Space ID : 00 [SystemMemory]
[0B5h 0181   1]Bit Width : 20
[0B6h 0182   1]   Bit Offset : 00
[0B7h 0183   1] Encoded Access Width : 03 [DWord Access:32]
[0B8h 0184   8]  Address : FEBF3008

[0C0h 0192   8]Value : 000

Re: [PATCH v14 3/8] [RISCV_PM] Support CSRs required for RISC-V PM extension except for the h-mode

2021-10-19 Thread Alistair Francis
On Mon, Oct 18, 2021 at 3:34 AM Alexey Baturo  wrote:
>
> Signed-off-by: Alexey Baturo 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu.c |   2 +
>  target/riscv/cpu.h |  11 ++
>  target/riscv/csr.c | 285 +
>  3 files changed, 298 insertions(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 1d69d1887e..75e8b8ca83 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -365,6 +365,8 @@ static void riscv_cpu_reset(DeviceState *dev)
>  env->mcause = 0;
>  env->pc = env->resetvec;
>  env->two_stage_lookup = false;
> +/* mmte is supposed to have pm.current hardwired to 1 */
> +env->mmte |= (PM_EXT_INITIAL | MMTE_M_PM_CURRENT);
>  #endif
>  cs->exception_index = RISCV_EXCP_NONE;
>  env->load_res = -1;
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 3f28dc5f3a..acb4ce9d23 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -236,6 +236,17 @@ struct CPURISCVState {
>
>  /* True if in debugger mode.  */
>  bool debugger;
> +
> +/*
> + * CSRs for PointerMasking extension
> + */
> +target_ulong mmte;
> +target_ulong mpmmask;
> +target_ulong mpmbase;
> +target_ulong spmmask;
> +target_ulong spmbase;
> +target_ulong upmmask;
> +target_ulong upmbase;
>  #endif
>
>  float_status fp_status;
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 23fbbd3216..d563289d37 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -192,6 +192,16 @@ static RISCVException hmode32(CPURISCVState *env, int 
> csrno)
>
>  }
>
> +/* Checks if PointerMasking registers could be accessed */
> +static RISCVException pointer_masking(CPURISCVState *env, int csrno)
> +{
> +/* Check if j-ext is present */
> +if (riscv_has_ext(env, RVJ)) {
> +return RISCV_EXCP_NONE;
> +}
> +return RISCV_EXCP_ILLEGAL_INST;
> +}
> +
>  static RISCVException pmp(CPURISCVState *env, int csrno)
>  {
>  if (riscv_feature(env, RISCV_FEATURE_PMP)) {
> @@ -1401,6 +1411,268 @@ static RISCVException write_pmpaddr(CPURISCVState 
> *env, int csrno,
>  return RISCV_EXCP_NONE;
>  }
>
> +/*
> + * Functions to access Pointer Masking feature registers
> + * We have to check if current priv lvl could modify
> + * csr in given mode
> + */
> +static bool check_pm_current_disabled(CPURISCVState *env, int csrno)
> +{
> +int csr_priv = get_field(csrno, 0x300);
> +int pm_current;
> +
> +/*
> + * If priv lvls differ that means we're accessing csr from higher priv 
> lvl,
> + * so allow the access
> + */
> +if (env->priv != csr_priv) {
> +return false;
> +}
> +switch (env->priv) {
> +case PRV_M:
> +pm_current = get_field(env->mmte, M_PM_CURRENT);
> +break;
> +case PRV_S:
> +pm_current = get_field(env->mmte, S_PM_CURRENT);
> +break;
> +case PRV_U:
> +pm_current = get_field(env->mmte, U_PM_CURRENT);
> +break;
> +default:
> +g_assert_not_reached();
> +}
> +/* It's same priv lvl, so we allow to modify csr only if pm.current==1 */
> +return !pm_current;
> +}
> +
> +static RISCVException read_mmte(CPURISCVState *env, int csrno,
> +target_ulong *val)
> +{
> +*val = env->mmte & MMTE_MASK;
> +return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_mmte(CPURISCVState *env, int csrno,
> + target_ulong val)
> +{
> +uint64_t mstatus;
> +target_ulong wpri_val = val & MMTE_MASK;
> +
> +if (val != wpri_val) {
> +qemu_log_mask(LOG_GUEST_ERROR,
> +  "MMTE: WPRI violation written 0x%lx vs expected 
> 0x%lx\n",
> +  val, wpri_val);
> +}
> +/* for machine mode pm.current is hardwired to 1 */
> +wpri_val |= MMTE_M_PM_CURRENT;
> +
> +/* hardwiring pm.instruction bit to 0, since it's not supported yet */
> +wpri_val &= ~(MMTE_M_PM_INSN | MMTE_S_PM_INSN | MMTE_U_PM_INSN);
> +env->mmte = wpri_val | PM_EXT_DIRTY;
> +
> +/* Set XS and SD bits, since PM CSRs are dirty */
> +mstatus = env->mstatus | MSTATUS_XS;
> +write_mstatus(env, csrno, mstatus);
> +return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException read_smte(CPURISCVState *env, int csrno,
> +target_ulong *val)
> +{
> +*val = env->mmte & SMTE_MASK;
> +return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_smte(CPURISCVState *env, int csrno,
> + target_ulong val)
> +{
> +target_ulong wpri_val = val & SMTE_MASK;
> +
> +if (val != wpri_val) {
> +qemu_log_mask(LOG_GUEST_ERROR,
> +  "SMTE: WPRI violation written 0x%lx vs expected 
> 0x%lx\n",
> +  val, wpri_val);
> +}
> +
> +/* if pm.current==0 we can't modify current PM CSRs */
> +if (check_pm_current_disabled(env, csr

Re: [PATCH v5 16/16] target/riscv: Compute mstatus.sd on demand

2021-10-19 Thread Alistair Francis
On Wed, Oct 20, 2021 at 2:52 AM Richard Henderson
 wrote:
>
> The position of this read-only field is dependent on the
> current cpu width.  Rather than having to compute that
> difference in many places, compute it only on read.
>
> Signed-off-by: Richard Henderson 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu_helper.c |  3 +--
>  target/riscv/csr.c| 37 ++---
>  target/riscv/translate.c  |  5 ++---
>  3 files changed, 25 insertions(+), 20 deletions(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 429afd1f48..0d1132f39d 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -185,10 +185,9 @@ bool riscv_cpu_fp_enabled(CPURISCVState *env)
>
>  void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
>  {
> -uint64_t sd = riscv_cpu_mxl(env) == MXL_RV32 ? MSTATUS32_SD : 
> MSTATUS64_SD;
>  uint64_t mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS |
>  MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE |
> -MSTATUS64_UXL | sd;
> +MSTATUS64_UXL;
>  bool current_virt = riscv_cpu_virt_enabled(env);
>
>  g_assert(riscv_has_ext(env, RVH));
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index c4a479ddd2..69e4d65fcd 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -477,10 +477,28 @@ static RISCVException read_mhartid(CPURISCVState *env, 
> int csrno,
>  }
>
>  /* Machine Trap Setup */
> +
> +/* We do not store SD explicitly, only compute it on demand. */
> +static uint64_t add_status_sd(RISCVMXL xl, uint64_t status)
> +{
> +if ((status & MSTATUS_FS) == MSTATUS_FS ||
> +(status & MSTATUS_XS) == MSTATUS_XS) {
> +switch (xl) {
> +case MXL_RV32:
> +return status | MSTATUS32_SD;
> +case MXL_RV64:
> +return status | MSTATUS64_SD;
> +default:
> +g_assert_not_reached();
> +}
> +}
> +return status;
> +}
> +
>  static RISCVException read_mstatus(CPURISCVState *env, int csrno,
> target_ulong *val)
>  {
> -*val = env->mstatus;
> +*val = add_status_sd(riscv_cpu_mxl(env), env->mstatus);
>  return RISCV_EXCP_NONE;
>  }
>
> @@ -498,7 +516,6 @@ static RISCVException write_mstatus(CPURISCVState *env, 
> int csrno,
>  {
>  uint64_t mstatus = env->mstatus;
>  uint64_t mask = 0;
> -int dirty;
>
>  /* flush tlb on mstatus fields that affect VM */
>  if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV |
> @@ -520,12 +537,7 @@ static RISCVException write_mstatus(CPURISCVState *env, 
> int csrno,
>
>  mstatus = (mstatus & ~mask) | (val & mask);
>
> -dirty = ((mstatus & MSTATUS_FS) == MSTATUS_FS) |
> -((mstatus & MSTATUS_XS) == MSTATUS_XS);
> -if (riscv_cpu_mxl(env) == MXL_RV32) {
> -mstatus = set_field(mstatus, MSTATUS32_SD, dirty);
> -} else {
> -mstatus = set_field(mstatus, MSTATUS64_SD, dirty);
> +if (riscv_cpu_mxl(env) == MXL_RV64) {
>  /* SXL and UXL fields are for now read only */
>  mstatus = set_field(mstatus, MSTATUS64_SXL, MXL_RV64);
>  mstatus = set_field(mstatus, MSTATUS64_UXL, MXL_RV64);
> @@ -798,13 +810,8 @@ static RISCVException read_sstatus(CPURISCVState *env, 
> int csrno,
>  {
>  target_ulong mask = (sstatus_v1_10_mask);
>
> -if (riscv_cpu_mxl(env) == MXL_RV32) {
> -mask |= SSTATUS32_SD;
> -} else {
> -mask |= SSTATUS64_SD;
> -}
> -
> -*val = env->mstatus & mask;
> +/* TODO: Use SXL not MXL. */
> +*val = add_status_sd(riscv_cpu_mxl(env), env->mstatus & mask);
>  return RISCV_EXCP_NONE;
>  }
>
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index de013fbf9b..35245aafa7 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -280,7 +280,6 @@ static void gen_jal(DisasContext *ctx, int rd, 
> target_ulong imm)
>  static void mark_fs_dirty(DisasContext *ctx)
>  {
>  TCGv tmp;
> -target_ulong sd = get_xl(ctx) == MXL_RV32 ? MSTATUS32_SD : MSTATUS64_SD;
>
>  if (ctx->mstatus_fs != MSTATUS_FS) {
>  /* Remember the state change for the rest of the TB. */
> @@ -288,7 +287,7 @@ static void mark_fs_dirty(DisasContext *ctx)
>
>  tmp = tcg_temp_new();
>  tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
> -tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
> +tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
>  tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
>  tcg_temp_free(tmp);
>  }
> @@ -299,7 +298,7 @@ static void mark_fs_dirty(DisasContext *ctx)
>
>  tmp = tcg_temp_new();
>  tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> -tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
> +tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
>  tcg_gen_st_tl(tmp

Re: [PATCH v5 15/16] target/riscv: Use riscv_csrrw_debug for cpu_dump

2021-10-19 Thread Alistair Francis
On Wed, Oct 20, 2021 at 2:50 AM Richard Henderson
 wrote:
>
> Use the official debug read interface to the csrs,
> rather than referencing the env slots directly.
> Put the list of csrs to dump into a table.
>
> Signed-off-by: Richard Henderson 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu.c | 90 +++---
>  1 file changed, 46 insertions(+), 44 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index f352c2b74c..3454b19c17 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -241,52 +241,54 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, 
> int flags)
>  }
>  #endif
>  qemu_fprintf(f, " %-8s " TARGET_FMT_lx "\n", "pc", env->pc);
> +
>  #ifndef CONFIG_USER_ONLY
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", 
> (target_ulong)env->mstatus);
> -if (riscv_cpu_mxl(env) == MXL_RV32) {
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatush ",
> - (target_ulong)(env->mstatus >> 32));
> +{
> +static const int dump_csrs[] = {
> +CSR_MHARTID,
> +CSR_MSTATUS,
> +CSR_MSTATUSH,
> +CSR_HSTATUS,
> +CSR_VSSTATUS,
> +CSR_MIP,
> +CSR_MIE,
> +CSR_MIDELEG,
> +CSR_HIDELEG,
> +CSR_MEDELEG,
> +CSR_HEDELEG,
> +CSR_MTVEC,
> +CSR_STVEC,
> +CSR_VSTVEC,
> +CSR_MEPC,
> +CSR_SEPC,
> +CSR_VSEPC,
> +CSR_MCAUSE,
> +CSR_SCAUSE,
> +CSR_VSCAUSE,
> +CSR_MTVAL,
> +CSR_STVAL,
> +CSR_HTVAL,
> +CSR_MTVAL2,
> +CSR_MSCRATCH,
> +CSR_SSCRATCH,
> +CSR_SATP,
> +};
> +
> +for (int i = 0; i < ARRAY_SIZE(dump_csrs); ++i) {
> +int csrno = dump_csrs[i];
> +target_ulong val = 0;
> +RISCVException res = riscv_csrrw_debug(env, csrno, &val, 0, 0);
> +
> +/*
> + * Rely on the smode, hmode, etc, predicates within csr.c
> + * to do the filtering of the registers that are present.
> + */
> +if (res == RISCV_EXCP_NONE) {
> +qemu_fprintf(f, " %-8s " TARGET_FMT_lx "\n",
> + csr_ops[csrno].name, val);
> +}
> +}
>  }
> -if (riscv_has_ext(env, RVH)) {
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus);
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ",
> - (target_ulong)env->vsstatus);
> -}
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip ", env->mip);
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie ", env->mie);
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mideleg ", env->mideleg);
> -if (riscv_has_ext(env, RVH)) {
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hideleg ", env->hideleg);
> -}
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "medeleg ", env->medeleg);
> -if (riscv_has_ext(env, RVH)) {
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hedeleg ", env->hedeleg);
> -}
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtvec   ", env->mtvec);
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stvec   ", env->stvec);
> -if (riscv_has_ext(env, RVH)) {
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vstvec  ", env->vstvec);
> -}
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mepc", env->mepc);
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "sepc", env->sepc);
> -if (riscv_has_ext(env, RVH)) {
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsepc   ", env->vsepc);
> -}
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mcause  ", env->mcause);
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "scause  ", env->scause);
> -if (riscv_has_ext(env, RVH)) {
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vscause ", env->vscause);
> -}
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval   ", env->mtval);
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stval   ", env->stval);
> -if (riscv_has_ext(env, RVH)) {
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "htval ", env->htval);
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval2 ", env->mtval2);
> -}
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mscratch", env->mscratch);
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "sscratch", env->sscratch);
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "satp", env->satp);
>  #endif
>
>  for (i = 0; i < 32; i++) {
> --
> 2.25.1
>
>



Re: [PATCH v5 14/16] target/riscv: Align gprs and fprs in cpu_dump

2021-10-19 Thread Alistair Francis
On Wed, Oct 20, 2021 at 2:18 AM Richard Henderson
 wrote:
>
> Allocate 8 columns per register name.
>
> Reviewed-by: LIU Zhiwei 
> Signed-off-by: Richard Henderson 

Reviewed-by: Alistair Francis 

This probably isn't required though as there is already a similar
patch in my tree:
https://github.com/alistair23/qemu/tree/riscv-to-apply.next

Alistair

> ---
>  target/riscv/cpu.c | 7 ---
>  1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 4e1920d5f0..f352c2b74c 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -240,7 +240,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, 
> int flags)
>  qemu_fprintf(f, " %s %d\n", "V  =  ", 
> riscv_cpu_virt_enabled(env));
>  }
>  #endif
> -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc  ", env->pc);
> +qemu_fprintf(f, " %-8s " TARGET_FMT_lx "\n", "pc", env->pc);
>  #ifndef CONFIG_USER_ONLY
>  qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
>  qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", 
> (target_ulong)env->mstatus);
> @@ -290,15 +290,16 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, 
> int flags)
>  #endif
>
>  for (i = 0; i < 32; i++) {
> -qemu_fprintf(f, " %s " TARGET_FMT_lx,
> +qemu_fprintf(f, " %-8s " TARGET_FMT_lx,
>   riscv_int_regnames[i], env->gpr[i]);
>  if ((i & 3) == 3) {
>  qemu_fprintf(f, "\n");
>  }
>  }
> +
>  if (flags & CPU_DUMP_FPU) {
>  for (i = 0; i < 32; i++) {
> -qemu_fprintf(f, " %s %016" PRIx64,
> +qemu_fprintf(f, " %-8s %016" PRIx64,
>   riscv_fpr_regnames[i], env->fpr[i]);
>  if ((i & 3) == 3) {
>  qemu_fprintf(f, "\n");
> --
> 2.25.1
>
>



Re: Deprecate the ppc405 boards in QEMU?

2021-10-19 Thread Cédric Le Goater

On 10/19/21 18:12, Christophe Leroy wrote:



Le 19/10/2021 à 16:56, BALATON Zoltan a écrit :

On Tue, 19 Oct 2021, Christophe Leroy wrote:

Le 19/10/2021 à 15:44, Christophe Leroy a écrit :

There is something:

=> bootm 0
Wrong Image Format for bootm command
ERROR: can't get kernel image!

=> md 0
:  b497aae1 616e9207 003227a4    '..Van...2'.
0010:   ee36255f 05070201    .6%_
0020: 4c696e75 782d352e 31352e30 2d726335    Linux-5.15.0-rc5
0030: 2d303232 32342d67 61336330 30376164    -02224-ga3c007ad
0040: 1f8b0800  0203ec5c 0f7013e7    ...\.p..

=> mw.l 0 0x27051956

=> bootm 0
## Booting kernel from Legacy Image at  ...
    Image Name:   Linux-5.15.0-rc5-02224-ga3c007ad
    Image Type:   PowerPC Linux Kernel Image (gzip compressed)
    Data Size:    3286948 Bytes = 3.1 MiB
    Load Address: 
    Entry Point:  
    Verifying Checksum ... Bad Data CRC
ERROR: can't get kernel image!


So we have something but it seems it gets overwritten by stuff.

Anyway loading a uImage at 0 is just bad because it is a gzipped image that 
should get gunzipped at address 0.

Or should we just copy the raw kernel at 0 and jump to the entry point ? But 
then we also need a device tree somewhere.



If I change KERNEL_LOAD_ADDR to 0x100, I can bootm at that address, and it 
seems it properly decompress the kernel:

=> bootm 0x100
## Booting kernel from Legacy Image at 0100 ...
  Image Name:   Linux-5.15.0-rc5-02224-ga3c007ad
  Image Type:   PowerPC Linux Kernel Image (gzip compressed)
  Data Size:    3296789 Bytes = 3.1 MiB
  Load Address: 
  Entry Point:  
  Verifying Checksum ... OK
  Uncompressing Kernel Image ... OK


And it initialises the MMU properly.

Then it gets stuck because there is no devicetree.

(gdb) bt
#0  0xc00094cc in udelay ()
#1  0xc0025d34 in panic ()
#2  0xc06415a0 in early_init_devtree ()
#3  0xc0641da8 in machine_init ()
#4  0xc0002200 in start_here ()


Maybe you need to embed a dtb in your kernel if that's possible somehow? Or QEMU 
has a -dtb option that sets machine->dtb but you need board code to do 
something with it. See how it's done in other boards like virtex_ml507 and 
sam460ex. But maybe you'd be better off not using -kernel option as it seems to 
not really working for these 405 boards but load and start the kernel from u-boot. 
Not sure what device does u-boot support but QEMU can emulate usb-storage, 
network, different disks so something might work with u-boot if this board has any 
peripherals. If it doesn't emulate any peripherals what do you expect to do with 
the kernel once it boots?



I should be able to build a multi-FIT image that embeds the kernel and the 
device tree.

I don't know about the peripherals, what I need it a kernel that is able to 
boot and run some user exe. I'm working on low level functionnalities like 
VMAP_STACK, STRICT_KERNEL_RWX, Userspace protection, etc ... I want to be able 
to check that after some modifications the kernel can still boot on every CPU 
sub-family, and I need to run LKDTM tests.

For this a kernel + initrd is enough.


hotfoot.dts is the only DT with a CPU model "PowerPC,405EP".

With cuImage.hotfoot,

U-Boot 2015.10-00236-g677f970bc6-dirty (Oct 06 2021 - 08:59:53 +0200)

CPU:   AMCC PowerPC 405EP Rev. B at 770 MHz (PLB=256 OPB=128 EBC=128)
   I2C boot EEPROM disabled
   Internal PCI arbiter enabled
   16 KiB I-Cache 16 KiB D-Cache
Board: Taihu - AMCC PPC405EP Evaluation Board
I2C:   ready
DRAM:  128 MiB
Flash: ## Unknown FLASH on Bank 0 - Size = 0x = 0 MB
## Unknown FLASH on Bank 1 - Size = 0x = 0 MB
0 Bytes
*** Warning - bad CRC, using default environment

PCI:   Bus Dev VenId DevId Class Int
PCI:
Net:   No ethernet found.

Type run flash_nfs to mount root filesystem over NFS

Hit any key to stop autoboot:  0
=> bootm 0100
## Booting kernel from Legacy Image at 0100 ...
   Image Name:   Linux-5.15.0-rc6-dirty
   Image Type:   PowerPC Linux Kernel Image (gzip compressed)
   Data Size:3326878 Bytes = 3.2 MiB
   Load Address: 0070
   Entry Point:  00701aa8
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK
Memory <- <0x0 0x800> (128MB)
CPU clock-frequency <- 0x0 (0MHz)
CPU timebase-frequency <- 0x0 (0MHz)
/plb: clock-frequency <- 0 (0MHz)
/plb/opb: clock-frequency <- 0 (0MHz)
/plb/ebc: clock-frequency <- 0 (0MHz)
/plb/opb/serial@ef600300: clock-frequency <- 0 (0MHz)
/plb/opb/serial@ef600400: clock-frequency <- 0 (0MHz)
ethernet0: local-mac-address <- 00:00:00:00:00:00
ethernet1: local-mac-address <- 00:00:2d:e5:44:80
Fixing devtree for 4M Flash

zImage starting: loaded at 0x0070 (sp: 0x07eaabb0)
Decompression error: 'Not a gzip file'
No valid compressed data found, assume uncompressed data
Allocating 0x6c128c bytes for kernel...
0x69e1ec bytes of uncompressed data copied

Linux/PowerPC load:
Finalizing device tree... flat tree at 0xdc5960
Lin

Re: [PATCH 06/31] target/loongarch: Add mmu support for Loongarch CPU.

2021-10-19 Thread Richard Henderson

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:

@@ -272,6 +288,7 @@ static const struct SysemuCPUOps loongarch_sysemu_ops = {
  #ifdef CONFIG_TCG
  #include "hw/core/tcg-cpu-ops.h"
  
+#ifdef CONFIG_USER_ONLY

  static bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
 MMUAccessType access_type, int mmu_idx,
 bool probe, uintptr_t retaddr)
@@ -280,9 +297,14 @@ static bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr 
address, int size,
  CPULoongArchState *env = &cpu->env;
  
  env->badaddr = address;

-cs->exception_index = EXCP_ADE;
+if (access_type == MMU_DATA_STORE) {
+cs->exception_index = EXCP_ADES;
+} else {
+cs->exception_index = EXCP_ADEL;
+}
  do_raise_exception(env, cs->exception_index, retaddr);
  }
+#endif


It's too early to add this ifdef.  With what's upstream at the moment, you've broken 
loongarch-linux-user build by removing loongarch_cpu_tlb_fill.


There are patches out for review that would require tlb_fill be a system-only hook, but 
they have not landed yet.



+#define LOONGARCH_HFLAG_KU 0x3 /* kernel/user mode mask   */
+#define LOONGARCH_HFLAG_UM 0x3 /* user mode flag */
+#define LOONGARCH_HFLAG_KM 0x0 /* kernel mode flag   */


I think you might as well represent all 3 priv levels: it's not a "kernel/user" 
mask.


+#define EXCP_TLB_NOMATCH   0x1
+#define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */


These should be with the other EXCP values in the enum.
At the moment you're overlapping EXCP_ADES and EXCP_SYSCALL.


@@ -130,7 +139,11 @@ void loongarch_cpu_list(void);
  
  static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch)

  {
+#ifdef CONFIG_USER_ONLY
  return MMU_USER_IDX;
+#else
+return env->CSR_CRMD & LOONGARCH_HFLAG_KU;


Better would be

return FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV);

since that's the field you're extracting from CRMD.


+typedef struct ls3a5k_tlb_t ls3a5k_tlb_t;


Types should be in CamelCase, without _t suffix.


+struct ls3a5k_tlb_t {
+target_ulong VPN;
+uint64_t PageMask;
+uint32_t PageSize;
+uint16_t ASID;
+unsigned int V0:1; /* CSR_TLBLO[0] */
+unsigned int V1:1;
+
+unsigned int D0:1; /* CSR_TLBLO[1] */
+unsigned int D1:1;
+
+unsigned int PLV0:2;   /* CSR_TLBLO[3:2] */
+unsigned int PLV1:2;
+
+unsigned int MAT0:3;   /* CSR_TLBLO[5:4] */
+unsigned int MAT1:3;
+
+unsigned int G:1;  /* CSR_TLBLO[6] */
+
+uint64_t PPN0; /* CSR_TLBLO[47:12] */
+uint64_t PPN1;
+
+unsigned int NR0:1;/* CSR_TLBLO[61] */
+unsigned int NR1:1;
+
+unsigned int NX0:1;/* CSR_TLBLO[62] */
+unsigned int NX1:1;
+
+unsigned int NE:1; /* CSR_TLBIDX[31] */
+
+unsigned int RPLV0:1;
+unsigned int RPLV1:1;  /* CSR_TLBLO[63] */
+};


It would be much better if you didn't use bitfields at all.  This was a bad idea when mips 
did it; let us not compound the error.


Just use the format defined by the architecture for the CSRs: a couple of uint64_t.  Use 
FIELD definitions to give the parts intelligible names.



+typedef struct ls3a5k_tlb_t ls3a5k_tlb_t;
+
+struct CPULoongArchTLBContext {
+uint32_t nb_tlb;
+int (*map_address)(struct CPULoongArchState *env, hwaddr *physical,
+   int *prot, target_ulong address,
+   MMUAccessType access_type);
+struct {
+uint64_t stlb_mask;
+uint32_t stlb_size; /* at most : 8 * 256 = 2048 */
+uint32_t mtlb_size; /* at most : 64 */
+ls3a5k_tlb_t tlb[LOONGARCH_TLB_MAX];
+} ls3a5k;
+};


There's probably no point in using an indirect function call until you've got more than 
one mmu implementation.  You're copying too much from mips.



+/* TLB state */
+static int get_tlb(QEMUFile *f, void *pv, size_t size,
+   const VMStateField *field)
+{
+ls3a5k_tlb_t *v = pv;
+uint32_t flags;
+
+qemu_get_betls(f, &v->VPN);
+qemu_get_be64s(f, &v->PageMask);
+qemu_get_be32s(f, &v->PageSize);
+qemu_get_be16s(f, &v->ASID);
+qemu_get_be32s(f, &flags);
+v->RPLV1 = (flags >> 21) & 1;
+v->RPLV0 = (flags >> 20) & 1;
+v->PLV1 = (flags >> 18) & 3;
+v->PLV0 = (flags >> 16) & 3;
+v->NE = (flags >> 15) & 1;
+v->NR1 = (flags >> 14) & 1;
+v->NR0 = (flags >> 13) & 1;
+v->NX1 = (flags >> 12) & 1;
+v->NX0 = (flags >> 11) & 1;
+v->D1 = (flags >> 10) & 1;
+v->D0 = (flags >> 9) & 1;
+v->V1 = (flags >> 8) & 1;
+v->V0 = (flags >> 7) & 1;
+v->MAT1 = (flags >> 4) & 7;
+v->MAT0 = (flags >> 1) & 7;
+v->G = (flags >> 0) & 1;
+qemu_get_be64s(f, &v->PPN0);
+qemu_get_be64s(f, &v->PPN1);


Some of the ugly things that go away if you don't use bitfields.


+const VMStateDescription vmstate_tlb = {
+.name = "cpu/tlb",
+.version_id = 2,
+.minimum_version

Re: Deprecate the ppc405 boards in QEMU?

2021-10-19 Thread Cédric Le Goater

On 10/19/21 18:12, Christophe Leroy wrote:



Le 19/10/2021 à 16:56, BALATON Zoltan a écrit :

On Tue, 19 Oct 2021, Christophe Leroy wrote:

Le 19/10/2021 à 15:44, Christophe Leroy a écrit :

There is something:

=> bootm 0
Wrong Image Format for bootm command
ERROR: can't get kernel image!

=> md 0
:  b497aae1 616e9207 003227a4    '..Van...2'.
0010:   ee36255f 05070201    .6%_
0020: 4c696e75 782d352e 31352e30 2d726335    Linux-5.15.0-rc5
0030: 2d303232 32342d67 61336330 30376164    -02224-ga3c007ad
0040: 1f8b0800  0203ec5c 0f7013e7    ...\.p..

=> mw.l 0 0x27051956

=> bootm 0
## Booting kernel from Legacy Image at  ...
    Image Name:   Linux-5.15.0-rc5-02224-ga3c007ad
    Image Type:   PowerPC Linux Kernel Image (gzip compressed)
    Data Size:    3286948 Bytes = 3.1 MiB
    Load Address: 
    Entry Point:  
    Verifying Checksum ... Bad Data CRC
ERROR: can't get kernel image!


So we have something but it seems it gets overwritten by stuff.

Anyway loading a uImage at 0 is just bad because it is a gzipped image that 
should get gunzipped at address 0.

Or should we just copy the raw kernel at 0 and jump to the entry point ? But 
then we also need a device tree somewhere.



If I change KERNEL_LOAD_ADDR to 0x100, I can bootm at that address, and it 
seems it properly decompress the kernel:

=> bootm 0x100
## Booting kernel from Legacy Image at 0100 ...
  Image Name:   Linux-5.15.0-rc5-02224-ga3c007ad
  Image Type:   PowerPC Linux Kernel Image (gzip compressed)
  Data Size:    3296789 Bytes = 3.1 MiB
  Load Address: 
  Entry Point:  
  Verifying Checksum ... OK
  Uncompressing Kernel Image ... OK


And it initialises the MMU properly.

Then it gets stuck because there is no devicetree.

(gdb) bt
#0  0xc00094cc in udelay ()
#1  0xc0025d34 in panic ()
#2  0xc06415a0 in early_init_devtree ()
#3  0xc0641da8 in machine_init ()
#4  0xc0002200 in start_here ()


Maybe you need to embed a dtb in your kernel if that's possible somehow? Or QEMU 
has a -dtb option that sets machine->dtb but you need board code to do 
something with it. See how it's done in other boards like virtex_ml507 and 
sam460ex. But maybe you'd be better off not using -kernel option as it seems to 
not really working for these 405 boards but load and start the kernel from u-boot. 
Not sure what device does u-boot support but QEMU can emulate usb-storage, 
network, different disks so something might work with u-boot if this board has any 
peripherals. If it doesn't emulate any peripherals what do you expect to do with 
the kernel once it boots?



I should be able to build a multi-FIT image that embeds the kernel and the 
device tree.

I don't know about the peripherals, what I need it a kernel that is able to 
boot and run some user exe. I'm working on low level functionnalities like 
VMAP_STACK, STRICT_KERNEL_RWX, Userspace protection, etc ... I want to be able 
to check that after some modifications the kernel can still boot on every CPU 
sub-family, and I need to run LKDTM tests.

For this a kernel + initrd is enough.

Thanks
Christophe


If we don't need a loader, we are better off simplifying the 405 boards with
a simple init sequence such as :

if (machine->kernel_filename) {
hwaddr kernel_base = 0;
int kernel_size = 0;
hwaddr initrd_base = 0;
int initrd_size = 0;

kernel_size = load_elf(machine->kernel_filename, NULL, NULL, NULL,
   &boot_entry, &kernel_base, NULL, NULL,
   0 /* LE */, PPC_ELF_MACHINE, 0, 0);
if (kernel_size < 0) {
error_report("Could not load kernel '%s' : %s",
 machine->kernel_filename, 
load_elf_strerror(kernel_size));
exit(1);
}

if (machine->initrd_filename) {
initrd_base = QEMU_ALIGN_UP(kernel_base + kernel_size, 0x1);
initrd_size = load_image_targphys(machine->initrd_filename,
  initrd_base, 16 * MiB /* Some 
value */);
if (initrd_size < 0) {
error_report("Could not load initial ram disk '%s'",
 machine->initrd_filename);
exit(1);
}
}

if (machine->dtb) {
dt_base = mw_dtb_load(machine, kernel_base, kernel_size, 
initrd_base,
  initrd_size);
}
}

We need to set the nip to 'boot_entry' and gpr[3] to 'dt_base'.

unless some pre-initialization of hw is required before running Linux ?

Thanks,

C.





[PATCH 1/2] qmp: Support fd-based KVM stats query

2021-10-19 Thread Mark Kanda
Introduce a QMP command 'query-kvmstats' to query KVM for vm and vcpu
fd-based statistics. The kernel support is provided by commit:

cb082bfab59a ("KVM: stats: Add fd-based API to read binary stats data")

The interface supports an optional 'filter' argument to specify a
particular stat to query.

Examples:
{ "execute": "query-kvmstats" }

{ "return": [
{ "name": "vm",
  "stats": [
{ "name": "max_mmu_page_hash_collisions",
  "unit": "none",
  "base": 10,
  "val": [ 0 ],
  "exponent": 0,
  "type": "peak" },
{ "name": "nx_lpage_splits",
  "unit": "none",
  "base": 10,
  "val": [ 120 ],
  "exponent": 0,
  "type": "instant" },
...
} ] },
{ "name": "vcpu_0",
  "stats": [
{ "name": "req_event",
  "unit": "none",
  "base": 10,
  "val": [ 500 ],
  "exponent": 0,
  "type": "cumulative" },
...

{ "execute": "query-kvmstats", "arguments" : { "filter" : "req_event" } }

{ "return": [
{ "name": "vm",
  "stats": [] },
{ "name": "vcpu_0",
  "stats": [
{ "name": "req_event",
  "unit": "none",
  "base": 10,
  "val": [ 500 ],
  "exponent": 0,
  "type": "cumulative" }
] },
{ "name": "vcpu_1",
  "stats": [
{ "name": "req_event",
  "unit": "none",
  "base": 10,
  "val": [ 61 ],
  "exponent": 0,
  "type": "cumulative" }
] } ] }

Signed-off-by: Mark Kanda 
---
 accel/kvm/kvm-all.c | 246 
 qapi/misc.json  |  73 +
 2 files changed, 319 insertions(+)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index db8d83b137..597d0c7a09 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -47,6 +47,7 @@
 #include "kvm-cpus.h"
 
 #include "hw/boards.h"
+#include "qapi/qapi-commands-misc.h"
 
 /* This check must be after config-host.h is included */
 #ifdef CONFIG_EVENTFD
@@ -3406,6 +3407,251 @@ int kvm_on_sigbus(int code, void *addr)
 #endif
 }
 
+typedef struct KvmStatsArgs {
+KvmStats *kvm_stat; /* QAPI auto-generated struct */
+char *filter;
+Error **errp;
+} KvmStatsArgs;
+
+static KvmStatDataList *add_kvmstat_entry(struct kvm_stats_desc *pdesc,
+  uint64_t *stats_data,
+  KvmStatDataList *data_list,
+  Error **errp)
+{
+KvmStatDataList *data_entry;
+uint64List *val_list = NULL;
+Error *local_err = NULL;
+int i;
+
+data_entry = g_malloc0(sizeof(*data_entry));
+data_entry->value = g_malloc0(sizeof(*data_entry->value));
+data_entry->value->name = g_strdup(pdesc->name);
+
+/* Convert flags to type, unit and base (QAPI auto-generated enums) */
+switch (pdesc->flags & KVM_STATS_TYPE_MASK) {
+case KVM_STATS_TYPE_CUMULATIVE:
+data_entry->value->type = KVM_STAT_TYPE_CUMULATIVE;
+break;
+case KVM_STATS_TYPE_INSTANT:
+data_entry->value->type = KVM_STAT_TYPE_INSTANT;
+break;
+case KVM_STATS_TYPE_PEAK:
+data_entry->value->type = KVM_STAT_TYPE_PEAK;
+break;
+default:
+error_setg(&local_err, "KVM stats: invalid type %u",
+   (pdesc->flags & KVM_STATS_TYPE_MASK)
+   >> KVM_STATS_TYPE_SHIFT);
+goto exit;
+}
+
+switch (pdesc->flags & KVM_STATS_UNIT_MASK) {
+case KVM_STATS_UNIT_NONE:
+data_entry->value->unit = KVM_STAT_UNIT_NONE;
+break;
+case KVM_STATS_UNIT_BYTES:
+data_entry->value->unit = KVM_STAT_UNIT_BYTES;
+break;
+case KVM_STATS_UNIT_CYCLES:
+data_entry->value->unit = KVM_STAT_UNIT_CYCLES;
+break;
+case KVM_STATS_UNIT_SECONDS:
+data_entry->value->unit = KVM_STAT_UNIT_SECONDS;
+break;
+default:
+error_setg(&local_err, "KVM stats: invalid unit %u",
+   (pdesc->flags & KVM_STATS_UNIT_MASK)
+   >> KVM_STATS_UNIT_SHIFT);
+goto exit;
+}
+
+switch (pdesc->flags & KVM_STATS_BASE_MASK) {
+case KVM_STATS_BASE_POW10:
+data_entry->value->base = 10;
+break;
+case  KVM_STATS_BASE_POW2:
+data_entry->value->base = 2;
+break;
+default:
+error_setg(&local_err, "KVM stats: invalid base %u",
+   (pdesc->flags & KVM_STATS_BASE_MASK)
+   >> KVM_STATS_BASE_SHIFT);
+goto exit;
+}
+
+data_entry->value->exponent = pdesc->exponent;
+
+/* Alloc and populate data list */
+for (i = 0; i < pdesc->size; i++) {
+uint64List *val_entry = g_malloc0(sizeof(*val_entry));
+val_entry->value = stats_data[i];
+val_entry->next = val_list;
+val_list = val_entry;
+}
+data_entry->value->val = val_list;
+data_entry->next = data_list;
+data_list = data_entry;
+
+   

[PATCH 2/2] hmp: Support fd-based KVM stats query

2021-10-19 Thread Mark Kanda
Leverage the QMP support for fd-based KVM stats.

The interface supports an optional 'filter' argument to specify a
particular stat to query. Base and exponent are displayed in human
readable format.

Examples:

(qemu) info kvmstats

vm:
  max_mmu_page_hash_collisions (peak): 0
  nx_lpage_splits (instant): 114
  lpages (instant): 193
  mmu_unsync (instant): 0
  mmu_cache_miss (cumulative): 293
  mmu_recycled (cumulative): 0
  mmu_flooded (cumulative): 0
  mmu_pde_zapped (cumulative): 0
  mmu_pte_write (cumulative): 0
  mmu_shadow_zapped (cumulative): 178
  remote_tlb_flush (cumulative): 63

vcpu_0:
  req_event (cumulative): 538
  nmi_injections (cumulative): 0
...

(qemu) info kvmstats halt_poll_fail_ns

vm:

vcpu_0:
  halt_poll_fail_ns (cumulative): 20*10^-9 seconds

vcpu_1:
  halt_poll_fail_ns (cumulative): 30*10^-9 seconds

Signed-off-by: Mark Kanda 
---
 hmp-commands-info.hx  | 13 +++
 include/monitor/hmp.h |  1 +
 monitor/hmp-cmds.c| 52 +++
 3 files changed, 66 insertions(+)

diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index 4c966e8a6b..ef5bca01d9 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -335,6 +335,19 @@ SRST
 Show KVM information.
 ERST
 
+{
+.name   = "kvmstats",
+.args_type  = "filter:s?",
+.params = "filter",
+.help   = "show KVM statistics; optional filter for stat name",
+.cmd= hmp_info_kvmstats,
+},
+
+SRST
+  ``info kvmstats``
+Show KVM statistics.
+ERST
+
 {
 .name   = "numa",
 .args_type  = "",
diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h
index 6bc27639e0..20be8f8586 100644
--- a/include/monitor/hmp.h
+++ b/include/monitor/hmp.h
@@ -21,6 +21,7 @@ void hmp_handle_error(Monitor *mon, Error *err);
 void hmp_info_name(Monitor *mon, const QDict *qdict);
 void hmp_info_version(Monitor *mon, const QDict *qdict);
 void hmp_info_kvm(Monitor *mon, const QDict *qdict);
+void hmp_info_kvmstats(Monitor *mon, const QDict *qdict);
 void hmp_info_status(Monitor *mon, const QDict *qdict);
 void hmp_info_uuid(Monitor *mon, const QDict *qdict);
 void hmp_info_chardev(Monitor *mon, const QDict *qdict);
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index bcaa41350e..24a545a66b 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -134,6 +134,58 @@ void hmp_info_kvm(Monitor *mon, const QDict *qdict)
 qapi_free_KvmInfo(info);
 }
 
+void hmp_info_kvmstats(Monitor *mon, const QDict *qdict)
+{
+KvmStatsList *stats_list, *stats_list_entry;
+KvmStats *stats_entry;
+KvmStatDataList *data_entry;
+KvmStatData *kvm_stat;
+uint64List *val;
+const char *filter;
+Error *err = NULL;
+
+filter = qdict_get_try_str(qdict, "filter");
+if (filter) {
+stats_list = qmp_query_kvmstats(TRUE, filter, &err);
+} else {
+stats_list = qmp_query_kvmstats(FALSE, NULL, &err);
+}
+
+if (err) {
+monitor_printf(mon, "%s\n", error_get_pretty(err));
+error_free(err);
+return;
+}
+
+for (stats_list_entry = stats_list; stats_list_entry;
+ stats_list_entry = stats_list_entry->next) {
+stats_entry = stats_list_entry->value;
+monitor_printf(mon, "\n%s:\n", stats_entry->name);
+
+for (data_entry = stats_entry->stats; data_entry;
+ data_entry = data_entry->next) {
+kvm_stat = data_entry->value;
+monitor_printf(mon, "  %s (%s):", kvm_stat->name,
+   KvmStatType_str(kvm_stat->type));
+
+for (val = kvm_stat->val; val; val = val->next) {
+if (kvm_stat->exponent) {
+/* Print the base and exponent as "*^" */
+monitor_printf(mon, " %lu*%d^%d", val->value,
+   kvm_stat->base, kvm_stat->exponent);
+} else {
+monitor_printf(mon, " %lu", val->value);
+}
+}
+
+/* Don't print "none" unit type */
+monitor_printf(mon, " %s\n", kvm_stat->unit == KVM_STAT_UNIT_NONE ?
+   "" : KvmStatUnit_str(kvm_stat->unit));
+}
+}
+qapi_free_KvmStatsList(stats_list);
+}
+
 void hmp_info_status(Monitor *mon, const QDict *qdict)
 {
 StatusInfo *info;
-- 
2.26.2




[PATCH 0/2] Support fd-based KVM stats

2021-10-19 Thread Mark Kanda
This patchset adds QEMU support for querying fd-based KVM stats. The kernel
support is provided by:

cb082bfab59a ("KVM: stats: Add fd-based API to read binary stats data")

Patch 1 adds QMP support; patch 2 adds HMP support.

Mark Kanda (2):
  qmp: Support fd-based KVM stats query
  hmp: Support fd-based KVM stats query

 accel/kvm/kvm-all.c   | 246 ++
 hmp-commands-info.hx  |  13 +++
 include/monitor/hmp.h |   1 +
 monitor/hmp-cmds.c|  52 +
 qapi/misc.json|  73 +
 5 files changed, 385 insertions(+)

-- 
2.26.2




Re: [PATCH 05/31] target/loongarch: Implement qmp_query_cpu_definitions()

2021-10-19 Thread Richard Henderson

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:

This patch introduce qmp_query_cpu_definitions interface.

Signed-off-by: Xiaojuan Yang
Signed-off-by: Song Gao
---
  qapi/machine-target.json |  6 --
  target/loongarch/cpu.c   | 28 
  2 files changed, 32 insertions(+), 2 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH v4 10/12] virtiofsd: Add inodes_by_handle hash table

2021-10-19 Thread Vivek Goyal
On Thu, Sep 16, 2021 at 10:40:43AM +0200, Hanna Reitz wrote:
> Currently, lo_inode.fhandle is always NULL and so always keep an O_PATH
> FD in lo_inode.fd.  Therefore, when the respective inode is unlinked,
> its inode ID will remain in use until we drop our lo_inode (and
> lo_inode_put() thus closes the FD).  Therefore, lo_find() can safely use
> the inode ID as an lo_inode key, because any inode with an inode ID we
> find in lo_data.inodes (on the same filesystem) must be the exact same
> file.
> 
> This will change when we start setting lo_inode.fhandle so we do not
> have to keep an O_PATH FD open.  Then, unlinking such an inode will
> immediately remove it, so its ID can then be reused by newly created
> files, even while the lo_inode object is still there[1].
> 
> So creating a new file can then reuse the old file's inode ID, and
> looking up the new file would lead to us finding the old file's
> lo_inode, which is not ideal.
> 
> Luckily, just as file handles cause this problem, they also solve it:  A
> file handle contains a generation ID, which changes when an inode ID is
> reused, so the new file can be distinguished from the old one.  So all
> we need to do is to add a second map besides lo_data.inodes that maps
> file handles to lo_inodes, namely lo_data.inodes_by_handle.  For
> clarity, lo_data.inodes is renamed to lo_data.inodes_by_ids.
> 
> Unfortunately, we cannot rely on being able to generate file handles
> every time.  Therefore, we still enter every lo_inode object into
> inodes_by_ids, but having an entry in inodes_by_handle is optional.  A
> potential inodes_by_handle entry then has precedence, the inodes_by_ids
> entry is just a fallback.
> 
> Note that we do not generate lo_fhandle objects yet, and so we also do
> not enter anything into the inodes_by_handle map yet.  Also, all lookups
> skip that map.  We might manually create file handles with some code
> that is immediately removed by the next patch again, but that would
> break the assumption in lo_find() that every lo_inode with a non-NULL
> .fhandle must have an entry in inodes_by_handle and vice versa.  So we
> leave actually using the inodes_by_handle map for the next patch.
> 
> [1] If some application in the guest still has the file open, there is
> going to be a corresponding FD mapping in lo_data.fd_map.  In such a
> case, the inode will only go away once every application in the guest
> has closed it.  The problem described only applies to cases where the
> guest does not have the file open, and it is just in the dentry cache,
> basically.
> 
> Signed-off-by: Hanna Reitz 
> ---
>  tools/virtiofsd/passthrough_ll.c | 81 +---
>  1 file changed, 65 insertions(+), 16 deletions(-)
> 
> diff --git a/tools/virtiofsd/passthrough_ll.c 
> b/tools/virtiofsd/passthrough_ll.c
> index bd8fc922ea..b7d6aa7f9d 100644
> --- a/tools/virtiofsd/passthrough_ll.c
> +++ b/tools/virtiofsd/passthrough_ll.c
> @@ -186,7 +186,8 @@ struct lo_data {
>  int announce_submounts;
>  bool use_statx;
>  struct lo_inode root;
> -GHashTable *inodes; /* protected by lo->mutex */
> +GHashTable *inodes_by_ids; /* protected by lo->mutex */
> +GHashTable *inodes_by_handle; /* protected by lo->mutex */
>  struct lo_map ino_map; /* protected by lo->mutex */
>  struct lo_map dirp_map; /* protected by lo->mutex */
>  struct lo_map fd_map; /* protected by lo->mutex */
> @@ -275,8 +276,9 @@ static struct {
>  /* That we loaded cap-ng in the current thread from the saved */
>  static __thread bool cap_loaded = 0;
>  
> -static struct lo_inode *lo_find(struct lo_data *lo, struct stat *st,
> -uint64_t mnt_id);
> +static struct lo_inode *lo_find(struct lo_data *lo,
> +const struct lo_fhandle *fhandle,
> +struct stat *st, uint64_t mnt_id);
>  static int xattr_map_client(const struct lo_data *lo, const char 
> *client_name,
>  char **out_name);
>  
> @@ -1143,18 +1145,40 @@ out_err:
>  fuse_reply_err(req, saverr);
>  }
>  
> -static struct lo_inode *lo_find(struct lo_data *lo, struct stat *st,
> -uint64_t mnt_id)

> +static struct lo_inode *lo_find(struct lo_data *lo,
> +const struct lo_fhandle *fhandle,
> +struct stat *st, uint64_t mnt_id)
>  {
> -struct lo_inode *p;
> -struct lo_key key = {
> +struct lo_inode *p = NULL;
> +struct lo_key ids_key = {
>  .ino = st->st_ino,
>  .dev = st->st_dev,
>  .mnt_id = mnt_id,
>  };
>  
>  pthread_mutex_lock(&lo->mutex);
> -p = g_hash_table_lookup(lo->inodes, &key);
> +if (fhandle) {
> +p = g_hash_table_lookup(lo->inodes_by_handle, fhandle);
> +}
> +if (!p) {
> +p = g_hash_table_lookup(lo->inodes_by_ids, &ids_key);
> +/*
> + * When we had to fall back to looking

Re: [PATCH 04/31] target/loongarch: Add basic vmstate description of CPU.

2021-10-19 Thread Richard Henderson

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:

+#ifndef CONFIG_USER_ONLY
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps loongarch_sysemu_ops = {
+.legacy_vmsd = &vmstate_loongarch_cpu,
+};
+#endif

The documentation for legacy_vmsd is quite clear:

Do not use in new targets, use #DeviceClass::vmsd instead.


+/* LoongArch CPU state */
+
+const VMStateDescription vmstate_loongarch_cpu = {
+.name = "cpu",
+.version_id = 20,
+.minimum_version_id = 20,


Version id should start at 0.


r~



Re: [PATCH 03/31] target/loongarch: Set default csr values.

2021-10-19 Thread Richard Henderson

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:

+#ifndef CONFIG_USER_ONLY
+static void set_loongarch_csr(CPULoongArchState *env)
+{
+uint64_t t;
+
+t = FIELD_DP64(0, CSR_PRCFG1, SAVE_NUM, 8);
+t = FIELD_DP64(t, CSR_PRCFG1, TIMER_BITS, 0x2f);
+t = FIELD_DP64(t, CSR_PRCFG1, VSMAX, 0x7);
+env->CSR_PRCFG1 = t;
+
+env->CSR_PRCFG2 = 0x3000;
+
+t = FIELD_DP64(0, CSR_PRCFG3, TLB_TYPE, 2);
+t = FIELD_DP64(t, CSR_PRCFG3, MTLB_ENTRY, 0x3f);
+t = FIELD_DP64(t, CSR_PRCFG3, STLB_WAYS, 0x7);
+t = FIELD_DP64(t, CSR_PRCFG3, STLB_SETS, 0x8);
+env->CSR_PRCFG3 = t;
+
+t = FIELD_DP64(0, CSR_CRMD, PLV, 0);
+t = FIELD_DP64(t, CSR_CRMD, IE, 0);
+t = FIELD_DP64(t, CSR_CRMD, DA, 1);
+t = FIELD_DP64(t, CSR_CRMD, PG, 0);
+t = FIELD_DP64(t, CSR_CRMD, DATF, 1);
+t = FIELD_DP64(t, CSR_CRMD, DATM, 1);
+env->CSR_CRMD = t;
+
+env->CSR_ECFG = FIELD_DP64(0, CSR_ECFG, VS, 7);
+env->CSR_STLBPS  = 0xe;
+env->CSR_RVACFG = 0x0;
+env->CSR_ASID = 0xa;
+env->CSR_ERA = env->pc;
+}
+#endif
+
  /* LoongArch CPU definitions */
  static void loongarch_3a5000_initfn(Object *obj)
  {
@@ -113,6 +147,9 @@ static void loongarch_3a5000_initfn(Object *obj)
  CPULoongArchState *env = &cpu->env;
  
  set_loongarch_cpucfg(env);

+#ifndef CONFIG_USER_ONLY
+set_loongarch_csr(env);
+#endif
  }
  
  static void loongarch_cpu_list_entry(gpointer data, gpointer user_data)

@@ -140,6 +177,9 @@ static void loongarch_cpu_reset(DeviceState *dev)
  lacc->parent_reset(dev);
  
  set_loongarch_cpucfg(env);

+#ifndef CONFIG_USER_ONLY
+set_loongarch_csr(env);
+#endif


As I said vs patch 2, I think you'll want to set all of these unconditionally.


r~



Re: [PATCH 02/31] target/loongarch: Add CSR registers definition

2021-10-19 Thread Richard Henderson

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:

+/*
+ * All Possible CSR registers used by tcg
+ *
+ * default value  in target/loongarch/cpu.c
+ *
+ * This macro will be used only in:
+ *  > target/loongarch/cpu.h:CPULoongArchState
+ *
+ * during translate:
+ *  > helper_csr_rdq()
+ *  > helper_csr_wrq()
+ *  > helper_csr_xchgq()
+ *  > helper_csr_xchgq_r0()
+ */
+#define CPU_LOONGARCH_CSR\
+uint64_t CSR_CRMD;   \
+uint64_t CSR_PRMD;   \


I don't see the point in this macro.  Just put the structure members directly into 
CPULoongArchState.


In addition, I think you'll want to include these members unconditionally.  We have found 
for ARM that it is easiest to minimize the differences between system and user emulation. 
 Having to ifdef each use of the csrs does not help.



r~



Re: [PATCH v4 11/12] virtiofsd: Optionally fill lo_inode.fhandle

2021-10-19 Thread Vivek Goyal
On Thu, Sep 16, 2021 at 10:40:44AM +0200, Hanna Reitz wrote:
> When the inode_file_handles option is set, try to generate a file handle
> for new inodes instead of opening an O_PATH FD.
> 
> Being able to open these again will require CAP_DAC_READ_SEARCH, so
> setting this option will result in us taking that capability.
> 
> Generating a file handle returns the mount ID it is valid for.  Opening
> it will require an FD instead.  We have mount_fds to map an ID to an FD.
> get_file_handle() scans /proc/self/mountinfo to map mount IDs to their
> mount points, which we open to get the mount FD we need.  To verify that
> the resulting FD indeed represents the handle's mount ID, we use
> statx().  Therefore, using file handles requires statx() support.
> 
> Signed-off-by: Hanna Reitz 
> ---
>  tools/virtiofsd/helper.c  |   3 +
>  tools/virtiofsd/passthrough_ll.c  | 297 --
>  tools/virtiofsd/passthrough_seccomp.c |   1 +
>  3 files changed, 289 insertions(+), 12 deletions(-)
> 
> diff --git a/tools/virtiofsd/helper.c b/tools/virtiofsd/helper.c
> index a8295d975a..311f05c7ee 100644
> --- a/tools/virtiofsd/helper.c
> +++ b/tools/virtiofsd/helper.c
> @@ -187,6 +187,9 @@ void fuse_cmdline_help(void)
> "   default: no_allow_direct_io\n"
> "-o announce_submounts  Announce sub-mount points to the 
> guest\n"
> "-o posix_acl/no_posix_acl  Enable/Disable posix_acl. 
> (default: disabled)\n"
> +   "-o inode_file_handles  Use file handles to reference 
> inodes\n"
> +   "   instead of O_PATH file 
> descriptors\n"
> +   "   (adds +dac_read_search to 
> modcaps)\n"
> );
>  }
>  
> diff --git a/tools/virtiofsd/passthrough_ll.c 
> b/tools/virtiofsd/passthrough_ll.c
> index b7d6aa7f9d..e86fad8b2f 100644
> --- a/tools/virtiofsd/passthrough_ll.c
> +++ b/tools/virtiofsd/passthrough_ll.c
> @@ -206,6 +206,8 @@ struct lo_data {
>  /* Maps (integer) mount IDs to lo_mount_fd objects */
>  GHashTable *mount_fds;
>  pthread_rwlock_t mount_fds_lock;
> +
> +int inode_file_handles;
>  };
>  
>  /**
> @@ -262,6 +264,10 @@ static const struct fuse_opt lo_opts[] = {
>  { "no_killpriv_v2", offsetof(struct lo_data, user_killpriv_v2), 0 },
>  { "posix_acl", offsetof(struct lo_data, user_posix_acl), 1 },
>  { "no_posix_acl", offsetof(struct lo_data, user_posix_acl), 0 },
> +{ "inode_file_handles", offsetof(struct lo_data, inode_file_handles), 1 
> },
> +{ "no_inode_file_handles",
> +  offsetof(struct lo_data, inode_file_handles),
> +  0 },
>  FUSE_OPT_END
>  };
>  static bool use_syslog = false;
> @@ -359,8 +365,15 @@ static void free_lo_mount_fd(gpointer data)
>   *
>   * Pass @drop_mount_fd_ref == true if and only if this handle has a
>   * strong reference to an lo_mount_fd object in the mount_fds hash
> - * table.  That is always the case for file handles stored in lo_inode
> - * objects.
> + * table, i.e. if this file handle has been returned by a
> + * get_file_handle() call where *can_open_handle was returned to be
> + * true.  (That is always the case for file handles stored in lo_inode
> + * objects, because those file handles must be open-able.)
> + *
> + * Conversely, pass @drop_mount_fd_ref == false if and only if this
> + * file handle has been returned by a get_file_handle() call where
> + * either NULL was passed for @can_open_handle, or where
> + * *can_open_handle was returned to be false.
>   */
>  static void release_file_handle(struct lo_data *lo, struct lo_fhandle *fh,
>  bool drop_mount_fd_ref)
> @@ -399,6 +412,196 @@ static void release_file_handle(struct lo_data *lo, 
> struct lo_fhandle *fh,
>  g_free(fh);
>  }
>  
> +/**
> + * Generate a file handle for the given dirfd/name combination.
> + *
> + * If mount_fds does not yet contain an entry for the handle's mount
> + * ID, (re)open dirfd/name in O_RDONLY mode and add it to mount_fds
> + * as the FD for that mount ID.  (That is the file that we have
> + * generated a handle for, so it should be representative for the
> + * mount ID.  However, to be sure (and to rule out races), we use
> + * statx() to verify that our assumption is correct.)
> + *
> + * Opening a mount FD can fail in various ways, and independently of
> + * whether generating a file handle was possible.  Many callers only
> + * care about getting a file handle for a lookup, though, and so do
> + * not necessarily need it to be usable.  (You need a valid mount FD
> + * for the handle to be usable.)
> + * *can_open_handle will be set to true if the file handle can be
> + * opened (i.e., we have a mount FD for it), and to false otherwise.
> + * By passing NULL for @can_open_handle, the caller indicates that
> + * they do not care about the handle being open-able, and so
> + * generating a mount FD will be skipped a

Re: [PATCH 01/31] target/loongarch: Upate the README for the softmmu.

2021-10-19 Thread Richard Henderson

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:

---
  target/loongarch/README  | 134 +++
  target/loongarch/ramdisk | Bin 0 -> 3077952 bytes
  target/loongarch/vmlinux | Bin 0 -> 24565536 bytes
  3 files changed, 134 insertions(+)
  create mode 100644 target/loongarch/ramdisk
  create mode 100755 target/loongarch/vmlinux


Wang Xuerui has already mentioned this, but let's make sure not to include such large test 
binaries in future.


The proper place for this is in a stable url, which could then either be referenced in the 
documentation.  But even better than that would be an acceptance test entry -- see 
tests/acceptance/boot_linux_console.py.



+  2.Modify the kernel code for the tcg. Modifications are listed later. I will 
try to
+commit to the kernel host.


This sounds like a bug in the qemu emulation of the device or boot environment.


r~



Re: [PULL 00/29] pc,pci,virtio: features, fixes

2021-10-19 Thread Richard Henderson

On 10/19/21 4:19 AM, Michael S. Tsirkin wrote:

The following changes since commit 9c050b661d3a43dfe2fd44106e559b39706d1296:

   Merge remote-tracking branch 'remotes/philmd/tags/mips-20211018' into 
staging (2021-10-18 09:16:51 -0700)

are available in the Git repository at:

   git://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git tags/for_upstream

for you to fetch changes up to bf2dd99b7d536cdba157fd6687810ce7b8340ccc:

   failover: fix a regression introduced by JSON'ification of -device 
(2021-10-19 07:15:34 -0400)


pc,pci,virtio: features, fixes

vhost user rng
Fixes, cleanups all over the place.

Signed-off-by: Michael S. Tsirkin 


Ani Sinha (3):
   tests/acpi/bios-tables-test: add and allow changes to a new q35 DSDT 
table blob
   tests/acpi/pcihp: add unit tests for hotplug on multifunction bridges 
for q35
   tests/acpi/bios-tables-test: update DSDT blob for multifunction bridge 
test

David Hildenbrand (1):
   libvhost-user: fix VHOST_USER_REM_MEM_REG skipping mmap_addr

Eric Auger (2):
   virtio-iommu: Remove the non transitional name
   virtio-iommu: Drop base_name and change generic_name

Eugenio Pérez (3):
   vdpa: Skip protected ram IOMMU mappings
   vdpa: Add vhost_vdpa_section_end
   vdpa: Check for iova range at mappings changes

Igor Mammedov (15):
   tests: acpi: dump table with failed checksum
   tests: qtest: add qtest_has_accel() to check if tested binary supports 
accelerator
   tests: acpi: whitelist expected tables for acpi/q35/xapic testcase
   tests: acpi: q35: test for x2APIC entries in SRAT
   tests: acpi: update expected tables blobs
   tests: acpi: whitelist new expected table tests/data/acpi/q35/DMAR.dmar
   tests: acpi: add testcase for intel_iommu (DMAR table)
   tests: acpi: add expected blob for DMAR table
   tests: acpi: whitelist expected blobs for new acpi/q35/ivrs testcase
   tests: acpi: add testcase for amd-iommu (IVRS table)
   tests: acpi: update expected blobs
   tests: acpi: arm/virt: drop redundant test_acpi_one() in 
test_acpi_virt_tcg()
   tests: arm-cpu-features: use qtest_has_kvm() API
   tests: migration-test: use qtest_has_accel() API
   tests: bios-tables-test: use qtest_has_accel() API to register TCG only 
tests

Laurent Vivier (1):
   failover: fix a regression introduced by JSON'ification of -device

Mathieu Poirier (3):
   vhost-user-rng: Add vhost-user-rng implementation
   vhost-user-rng-pci: Add vhost-user-rng-pci implementation
   docs: Add documentation for vhost based RNG implementation

Xueming Li (1):
   vhost-user: fix duplicated notifier MR init

  include/hw/virtio/vhost-user-rng.h|  33 
  include/hw/virtio/vhost-vdpa.h|   2 +
  include/hw/virtio/virtio-iommu.h  |   2 +-
  tests/qtest/libqos/libqtest.h |   8 +
  hw/net/virtio-net.c   |  24 ++-
  hw/virtio/vhost-user-rng-pci.c|  79 
  hw/virtio/vhost-user-rng.c| 289 ++
  hw/virtio/vhost-user.c|   5 +-
  hw/virtio/vhost-vdpa.c|  81 ++---
  hw/virtio/virtio-iommu-pci.c  |   4 +-
  subprojects/libvhost-user/libvhost-user.c |   1 +
  tests/qtest/acpi-utils.c  |  14 ++
  tests/qtest/arm-cpu-features.c|  29 +--
  tests/qtest/bios-tables-test.c|  90 --
  tests/qtest/libqtest.c|  27 +++
  tests/qtest/migration-test.c  |  15 +-
  docs/system/device-emulation.rst  |   1 +
  docs/system/devices/vhost-user-rng.rst|  39 
  hw/virtio/Kconfig |   5 +
  hw/virtio/meson.build |   2 +
  hw/virtio/trace-events|   1 +
  meson.build   |   6 +
  tests/data/acpi/q35/APIC.xapic| Bin 0 -> 2686 bytes
  tests/data/acpi/q35/DMAR.dmar | Bin 0 -> 120 bytes
  tests/data/acpi/q35/DSDT.ivrs | Bin 0 -> 8306 bytes
  tests/data/acpi/q35/DSDT.multi-bridge | Bin 0 -> 8583 bytes
  tests/data/acpi/q35/DSDT.xapic| Bin 0 -> 35652 bytes
  tests/data/acpi/q35/FACP.xapic| Bin 0 -> 244 bytes
  tests/data/acpi/q35/IVRS.ivrs | Bin 0 -> 104 bytes
  tests/data/acpi/q35/SRAT.xapic| Bin 0 -> 5080 bytes
  30 files changed, 672 insertions(+), 85 deletions(-)
  create mode 100644 include/hw/virtio/vhost-user-rng.h
  create mode 100644 hw/virtio/vhost-user-rng-pci.c
  create mode 100644 hw/virtio/vhost-user-rng.c
  create mode 100644 docs/system/devices/vhost-user-rng.rst
  create mode 100644 tests/data/acpi/q35/APIC.xapic
  create mode 100644 tests/data/acpi/q35/DMAR.dmar
  create mode 100644 tests/data/acpi/q35/DSDT.ivrs
  create mode 100644 tests/

Re: [PATCH 00/64] Patch Round-up for stable 6.0.1, freeze on 2021-10-26

2021-10-19 Thread Michael Roth
Quoting Ani Sinha (2021-10-19 09:43:52)
> 
> 
> On Tue, 19 Oct 2021, Michael Roth wrote:
> 
> > Hi everyone,
> >
> > The following new patches are queued for QEMU stable v6.0.1:
> >
> >   https://gitlab.com/qemu-project/qemu/-/commits/stable-6.0-staging/
> >
> > Patch freeze is 2021-10-26, and the release is planned for 2021-10-28:
> >
> >   https://wiki.qemu.org/Planning/6.0
> >
> > Please respond here or CC qemu-sta...@nongnu.org on any additional patches
> > you think should (or shouldn't) be included in the release.
> 
> I believe we should also include this patch:
> https://lore.kernel.org/qemu-devel/20210916132838.3469580-2-...@anisinha.ca/T/
> 
> It is also CC'd to qemu-stable@ but the patch itself was not tagged so (my
> apologies for that).

It looks like this patch is a fix for:

  commit caf108bc587908f7608729f39639dccdfa53010b
  Author: Julia Suvorova 
  Date:   Tue Jul 13 02:42:00 2021 +0200
  
  hw/i386/acpi-build: Add ACPI PCI hot-plug methods to Q35

which is in 6.1.0, but not 6.0.0, so it didn't seem like it was needed
for 6.0.1. Let me know if that's incorrect.

Will definitely pull it in for 6.1.1 though.



Re: [PATCH v3 03/21] Int128.h: addition of a few 128-bit operations

2021-10-19 Thread Richard Henderson

On 10/19/21 2:47 AM, Frédéric Pétrot wrote:

+static inline void divrem128(uint64_t ul, uint64_t uh,
+ uint64_t vl, uint64_t vh,
+ uint64_t *ql, uint64_t *qh,
+ uint64_t *rl, uint64_t *rh)


I think we should move all of the division implementation out of the header; this is 
really much too large to inline.


I think util/int128.c would be a reasonable place.

That said, why are you splitting the Int128 apart to pass as pieces here?  Seems like 
passing the Int128 and doing the split inside would make more sense.



+/* never happens, but makes gcc shy */
+n = 0;


Then g_assert_not_reached(), or change the previous if to an assert.

Hmm, it's not "never happens" so much as "divide by zero".
Please update the comment accordingly.


+if (r != NULL) {
+r[0] = k;
+}


r is a local array; useless check for null.


+s = clz32(v[n - 1]); /* 0 <= s <= 32 */
+if (s != 0) {
+for (i = n - 1; i > 0; i--) {
+vn[i] = ((v[i] << s) | (v[i - 1] >> (32 - s)));
+}
+vn[0] = v[0] << s;
+
+un[m] = u[m - 1] >> (32 - s);
+for (i = m - 1; i > 0; i--) {
+un[i] = (u[i] << s) | (u[i - 1] >> (32 - s));
+}
+un[0] = u[0] << s;


Why are you shifting the 128-bit value in 4 parts, rather than letting int128_lshift do 
the job?



r~



Re: [PATCH v3 02/21] memory: add a few defines for octo (128-bit) values

2021-10-19 Thread Richard Henderson

On 10/19/21 2:47 AM, Frédéric Pétrot wrote:

Introducing unsigned quad, signed quad, and octo accesses types
to handle load and store by 128-bit processors.

Signed-off-by: Frédéric Pétrot 
---
  include/exec/memop.h | 8 +++-
  1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/include/exec/memop.h b/include/exec/memop.h
index c554bb0ee8..476ea6cdae 100644
--- a/include/exec/memop.h
+++ b/include/exec/memop.h
@@ -85,10 +85,13 @@ typedef enum MemOp {
  MO_UB= MO_8,
  MO_UW= MO_16,
  MO_UL= MO_32,
+MO_UQ= MO_64,
  MO_SB= MO_SIGN | MO_8,
  MO_SW= MO_SIGN | MO_16,
  MO_SL= MO_SIGN | MO_32,
-MO_UQ = MO_64,
+MO_SQ= MO_SIGN | MO_64,
+MO_Q = MO_64,
+MO_O = MO_128,


There's no point in removing MO_Q in one patch and adding it back in the next.  And I 
guess we might as well name MO_O to MO_UO now.



@@ -105,9 +108,12 @@ typedef enum MemOp {
  #ifdef NEED_CPU_H
  MO_TEUW  = MO_TE | MO_UW,
  MO_TEUL  = MO_TE | MO_UL,
+MO_TEUQ  = MO_TE | MO_UQ,
  MO_TESW  = MO_TE | MO_SW,
  MO_TESL  = MO_TE | MO_SL,
  MO_TEQ   = MO_TE | MO_UQ,
+MO_TESQ  = MO_TE | MO_SQ,


These should have been renamed at the same time as MO_Q.  Though it seems you are missing 
a rename of these throughout target/?  Surely this patch does not build as-is.



r~



Re: [PATCH] gdbstub: Switch to the thread receiving a signal

2021-10-19 Thread Pavel Labath
Thanks for taking a look. I've sent out a new version of the patch. 
Besides the Makefile change, I have also replaced the direct 
gdbserver_state manipulation with a call to gdb_set_stop_cpu.


Further responses inline.

On 19/10/2021 19:02, Alex Bennée wrote:


Pavel Labath  writes:


Respond with Txxthread:; instead of a plain Sxx to indicate which
thread received the signal. Otherwise, the debugger will associate it
with the main one. Also automatically select this thread, as that is
what gdb expects.

Signed-off-by: Pavel Labath 
---
  gdbstub.c |  9 ++-
  tests/tcg/multiarch/Makefile.target   |  7 +++
  .../gdbstub/test-thread-breakpoint.py | 60 +++
  3 files changed, 74 insertions(+), 2 deletions(-)
  create mode 100644 tests/tcg/multiarch/gdbstub/test-thread-breakpoint.py

diff --git a/gdbstub.c b/gdbstub.c
index 36b85aa..7bd4479 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -3138,8 +3138,13 @@ gdb_handlesig(CPUState *cpu, int sig)
  tb_flush(cpu);
  
  if (sig != 0) {

-snprintf(buf, sizeof(buf), "S%02x", target_signal_to_gdb(sig));
-put_packet(buf);
+gdbserver_state.c_cpu = cpu;
+gdbserver_state.g_cpu = cpu;
+g_string_printf(gdbserver_state.str_buf,
+"T%02xthread:", target_signal_to_gdb(sig));
+gdb_append_thread_id(cpu, gdbserver_state.str_buf);
+g_string_append_c(gdbserver_state.str_buf, ';');
+put_strbuf();
  }
  /* put_packet() might have detected that the peer terminated the
 connection.  */
diff --git a/tests/tcg/multiarch/Makefile.target 
b/tests/tcg/multiarch/Makefile.target
index 85a6fb7..c7b7e8b 100644
--- a/tests/tcg/multiarch/Makefile.target
+++ b/tests/tcg/multiarch/Makefile.target
@@ -73,6 +73,13 @@ run-gdbstub-qxfer-auxv-read: sha1
--bin $< --test 
$(MULTIARCH_SRC)/gdbstub/test-qxfer-auxv-read.py, \
"basic gdbstub qXfer:auxv:read support")
  
+run-gdbstub-thread-breakpoint: testthread

+   $(call run-test, $@, $(GDB_SCRIPT) \
+   --gdb $(HAVE_GDB_BIN) \
+   --qemu $(QEMU) --qargs "$(QEMU_OPTS)" \
+   --bin $< --test 
$(MULTIARCH_SRC)/gdbstub/test-thread-breakpoint.py, \
+   "hitting a breakpoint on non-main thread")
+


You also need to add the test to EXTRA_RUNS here (or just bellow in fact).

Done.




  else
  run-gdbstub-%:
$(call skip-test, "gdbstub test $*", "need working gdb")
diff --git a/tests/tcg/multiarch/gdbstub/test-thread-breakpoint.py 
b/tests/tcg/multiarch/gdbstub/test-thread-breakpoint.py
new file mode 100644
index 000..798d508
--- /dev/null
+++ b/tests/tcg/multiarch/gdbstub/test-thread-breakpoint.py
@@ -0,0 +1,60 @@
+from __future__ import print_function
+#
+# Test auxiliary vector is loaded via gdbstub
+#
+# This is launched via tests/guest-debug/run-test.py
+#
+
+import gdb
+import sys
+
+failcount = 0
+
+def report(cond, msg):
+"Report success/fail of test"
+if cond:
+print ("PASS: %s" % (msg))
+else:
+print ("FAIL: %s" % (msg))
+global failcount
+failcount += 1
+
+def run_test():
+"Run through the tests one by one"
+
+sym, ok = gdb.lookup_symbol("thread1_func")
+gdb.execute("b thread1_func")
+gdb.execute("c")
+
+frame = gdb.selected_frame()
+report(str(frame.function()) == "thread1_func", "break @
  %s"%frame)


Does this actually check the correct thread is reported?
It does it indirectly -- there is only one thread which can have 
thread1_func on the stack. If we do not report the correct thread, 
selected_frame() will point into the bowels of pthread_join, as that's 
where the main thread will be stuck at.
I don't know of a direct way to check for the reported thread. 
gdb.selected_thread().name would be more direct, but I am not sure we 
would be able to correctly set the thread name on all supported platforms.





+
+#
+# This runs as the script it sourced (via -x, via run-test.py)
+#
+try:
+inferior = gdb.selected_inferior()
+arch = inferior.architecture()
+print("ATTACHED: %s" % arch.name())
+except (gdb.error, AttributeError):
+print("SKIPPING (not connected)", file=sys.stderr)
+exit(0)
+
+if gdb.parse_and_eval('$pc') == 0:
+print("SKIP: PC not set")
+exit(0)
+
+try:
+# These are not very useful in scripts
+gdb.execute("set pagination off")
+gdb.execute("set confirm off")
+
+# Run the actual tests
+run_test()
+except (gdb.error):
+print ("GDB Exception: %s" % (sys.exc_info()[0]))
+failcount += 1
+pass
+
+print("All tests complete: %d failures" % failcount)
+exit(failcount)








Re: [PATCH] gdbstub: Switch to the thread receiving a signal

2021-10-19 Thread Alex Bennée


Pavel Labath  writes:

> On 15/10/2021 17:59, Alex Bennée wrote:
>> Pavel Labath  writes:
>> 
>>> Ping.
>>>
>>> (This is my first qemu patch, so please let me know if I am doing
>>> something wrong.)
>> Apologies it slipped though the cracks. I shall have a look on
>> Monday.
>> 
>
> I don't want to impose, but did this get buried over the weekend by
> any chance?

I had a quick look over and made some comments. I haven't been able to
replicate the test manually so far but I might have broken tooling so I
need to dig into that.

>
> regards,
> pl


-- 
Alex Bennée



[PATCH v2] gdbstub: Switch to the thread receiving a signal

2021-10-19 Thread Pavel Labath
Respond with Txxthread:; instead of a plain Sxx to indicate which
thread received the signal. Otherwise, the debugger will associate it
with the main one. Also automatically select this thread, as that is
what gdb expects.

Signed-off-by: Pavel Labath 
---
 gdbstub.c |  8 ++-
 tests/tcg/multiarch/Makefile.target   | 10 +++-
 .../gdbstub/test-thread-breakpoint.py | 60 +++
 3 files changed, 75 insertions(+), 3 deletions(-)
 create mode 100644 tests/tcg/multiarch/gdbstub/test-thread-breakpoint.py

diff --git a/gdbstub.c b/gdbstub.c
index 36b85aa..23baaef 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -3138,8 +3138,12 @@ gdb_handlesig(CPUState *cpu, int sig)
 tb_flush(cpu);
 
 if (sig != 0) {
-snprintf(buf, sizeof(buf), "S%02x", target_signal_to_gdb(sig));
-put_packet(buf);
+gdb_set_stop_cpu(cpu);
+g_string_printf(gdbserver_state.str_buf,
+"T%02xthread:", target_signal_to_gdb(sig));
+gdb_append_thread_id(cpu, gdbserver_state.str_buf);
+g_string_append_c(gdbserver_state.str_buf, ';');
+put_strbuf();
 }
 /* put_packet() might have detected that the peer terminated the
connection.  */
diff --git a/tests/tcg/multiarch/Makefile.target 
b/tests/tcg/multiarch/Makefile.target
index 6ccb592..c84683f 100644
--- a/tests/tcg/multiarch/Makefile.target
+++ b/tests/tcg/multiarch/Makefile.target
@@ -70,11 +70,19 @@ run-gdbstub-qxfer-auxv-read: sha1
--bin $< --test 
$(MULTIARCH_SRC)/gdbstub/test-qxfer-auxv-read.py, \
"basic gdbstub qXfer:auxv:read support")
 
+run-gdbstub-thread-breakpoint: testthread
+   $(call run-test, $@, $(GDB_SCRIPT) \
+   --gdb $(HAVE_GDB_BIN) \
+   --qemu $(QEMU) --qargs "$(QEMU_OPTS)" \
+   --bin $< --test 
$(MULTIARCH_SRC)/gdbstub/test-thread-breakpoint.py, \
+   "hitting a breakpoint on non-main thread")
+
 else
 run-gdbstub-%:
$(call skip-test, "gdbstub test $*", "need working gdb")
 endif
-EXTRA_RUNS += run-gdbstub-sha1 run-gdbstub-qxfer-auxv-read
+EXTRA_RUNS += run-gdbstub-sha1 run-gdbstub-qxfer-auxv-read \
+ run-gdbstub-thread-breakpoint
 
 # ARM Compatible Semi Hosting Tests
 #
diff --git a/tests/tcg/multiarch/gdbstub/test-thread-breakpoint.py 
b/tests/tcg/multiarch/gdbstub/test-thread-breakpoint.py
new file mode 100644
index 000..798d508
--- /dev/null
+++ b/tests/tcg/multiarch/gdbstub/test-thread-breakpoint.py
@@ -0,0 +1,60 @@
+from __future__ import print_function
+#
+# Test auxiliary vector is loaded via gdbstub
+#
+# This is launched via tests/guest-debug/run-test.py
+#
+
+import gdb
+import sys
+
+failcount = 0
+
+def report(cond, msg):
+"Report success/fail of test"
+if cond:
+print ("PASS: %s" % (msg))
+else:
+print ("FAIL: %s" % (msg))
+global failcount
+failcount += 1
+
+def run_test():
+"Run through the tests one by one"
+
+sym, ok = gdb.lookup_symbol("thread1_func")
+gdb.execute("b thread1_func")
+gdb.execute("c")
+
+frame = gdb.selected_frame()
+report(str(frame.function()) == "thread1_func", "break @ %s"%frame)
+
+#
+# This runs as the script it sourced (via -x, via run-test.py)
+#
+try:
+inferior = gdb.selected_inferior()
+arch = inferior.architecture()
+print("ATTACHED: %s" % arch.name())
+except (gdb.error, AttributeError):
+print("SKIPPING (not connected)", file=sys.stderr)
+exit(0)
+
+if gdb.parse_and_eval('$pc') == 0:
+print("SKIP: PC not set")
+exit(0)
+
+try:
+# These are not very useful in scripts
+gdb.execute("set pagination off")
+gdb.execute("set confirm off")
+
+# Run the actual tests
+run_test()
+except (gdb.error):
+print ("GDB Exception: %s" % (sys.exc_info()[0]))
+failcount += 1
+pass
+
+print("All tests complete: %d failures" % failcount)
+exit(failcount)
-- 
2.32.0




  1   2   3   4   5   >