Re: [PATCH 2/2] nbd/server: Use drained block ops to quiesce the server

2021-06-01 Thread Sergio Lopez
On Tue, Jun 01, 2021 at 04:29:07PM -0500, Eric Blake wrote:
> On Tue, Jun 01, 2021 at 07:57:28AM +0200, Sergio Lopez wrote:
> > Before switching between AioContexts we need to make sure that we're
> > fully quiesced ("nb_requests == 0" for every client) when entering the
> > drained section.
> > 
> > To do this, we set "quiescing = true" for every client on
> > ".drained_begin" to prevent new coroutines to be created, and check if
> 
> s/to be created/from being created/
> 
> > "nb_requests == 0" on ".drained_poll". Finally, once we're exiting the
> > drained section, on ".drained_end" we set "quiescing = false" and
> > call "nbd_client_receive_next_request()" to resume the processing of
> > new requests.
> > 
> > With these changes, "blk_aio_attach()" and "blk_aio_detach()" can be
> > reverted to be as simple as they were before f148ae7d36.
> 
> Is that reversion planned to be patch 3 of your series in v2?

Actually, we need part of the changes introduced in f148ae7d36, so
it's probably simpler to manually revert "blk_aio_attach()" and
"blk_aio_detach()" here than doing an actual reversion and then
reintroducing the changes.

Thanks,
Sergio.


signature.asc
Description: PGP signature


Re: [RFC PATCH v2 3/3] plugins: cache: Added FIFO and LRU eviction policies.

2021-06-01 Thread Mahmoud Mandour
On Tue, Jun 1, 2021 at 3:27 PM Alex Bennée  wrote:

>
> Mahmoud Mandour  writes:
>
> > Now one of the three eviction policies can be chosen as an argument. On
> > not specifying an argument, LRU is used by default.
> >
> > Signed-off-by: Mahmoud Mandour 
> > ---
> >  contrib/plugins/cache.c | 159 
> >  1 file changed, 146 insertions(+), 13 deletions(-)
> >
> > diff --git a/contrib/plugins/cache.c b/contrib/plugins/cache.c
> > index fa0bf1dd40..1e323494bf 100644
> > --- a/contrib/plugins/cache.c
> > +++ b/contrib/plugins/cache.c
> > @@ -18,6 +18,8 @@
> >
> >  QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
> >
> > +static bool fifo, lru, rnd;
> > +
>
> Ironically this would be a good use for a single variable with an enum,
> or alternatively a function pointer which can be set on initialisation.
>
> I think that I will implement the function pointers thing because as you
mention bellow it will somewhat reduce the clutter of checking the current
eviction policy each time and decide on which function to call.

>  static GRand *rng;
> >  static GHashTable *dmiss_ht;
> >  static GHashTable *imiss_ht;
> > @@ -55,6 +57,8 @@ struct CacheBlock {
> >
> >  struct CacheSet {
> >  struct CacheBlock *blocks;
> > +uint16_t *priorities;
> > +GQueue *evict_queue;
> >  };
> >
> >  struct Cache {
> > @@ -93,6 +97,84 @@ static inline uint64_t extract_set(struct Cache
> *cache, uint64_t addr)
> >  return (addr & cache->set_mask) >> (pow_of_two(cache->blksize));
> >  }
>
> I think it would be useful to summarise the LRU behaviour here in a
> comment and explain how the priorities are meant to change as the cache
> is used.


> >
> > +static void lru_priorities_init(struct Cache *cache)
> > +{
> > +int i, j;
> > +
> > +for (i = 0; i < cache->num_sets; i++) {
> > +cache->sets[i].priorities = g_new(uint16_t, cache->assoc);
> > +for (j = 0; j < cache->assoc; j++) {
> > +cache->sets[i].priorities[j] = cache->assoc - j - 1;
> > +}
> > +}
> > +}
> > +
> > +static void lru_update_on_miss(struct Cache *cache,
> > +  int set_idx,
> > +  int blk_idx)
> > +{
> > +int i;
> > +
> > +for (i = 0; i < cache->assoc; i++) {
> > +cache->sets[set_idx].priorities[i]++;
> > +}
> > +
> > +cache->sets[set_idx].priorities[blk_idx] = 0;
>
> So we increment priority for all non-hit blocks and reset it for the
> entry just used? This isn't totally clear to follow however see bellow:


> > +}
> > +
> > +static void lru_update_on_hit(struct Cache *cache,
> > + int set_idx,
> > + int blk_idx)
> > +{
> > +uint16_t blk_priority;
> > +int i;
> > +
> > +blk_priority = cache->sets[set_idx].priorities[blk_idx];
> > +for (i = 0; i < cache->assoc; i++) {
> > +if (cache->sets[set_idx].priorities[i] < blk_priority) {
> > +cache->sets[set_idx].priorities[i]++;
> > +}
> > +}
> > +cache->sets[set_idx].priorities[blk_idx] = 0;
>
> This seems pretty expensive depending on the number of blocks. Another
> approach would be to have a generation number that is incremented on
> each access and stored in the appropriate set. Then...
>
> > +}
> > +
> > +static int lru_get_lru_block(struct Cache *cache, int set_idx)
> > +{
> > +int i;
> > +
> > +for (i = 0; i < cache->assoc; i++) {
> > +if (cache->sets[set_idx].priorities[i] == cache->assoc - 1) {
> > +return i;
> > +}
> > +}
>
> when you get to search for a "stale" block you just look for the lowest
> generation number. The eviction logic should be being called less than
> the update logic right?


Sorry for the confusion about LRU, so my idea is that if we have ASSOC
blocks in each set, the invariant is that I always have the least recently
used
block with a priority of ASSOC - 1. the second least recently used block
with
a priority of ASSOC - 2, etc. By incrementing every priority on miss, I
demote
other blocks and set the newly-cached block to priority 0, so we maintain
the
recency of usage sequence.

To be clear, your solution is on hit: increase the hit-block priority, and
on miss,
remove the element with the least priority (probably the new block here
will get
the highest priority which can be stored in the set itself so we don't
search for it)

If I understood something incorrectly please correct me.

The problem with that is we won't have the usage sequence anymore.
Consider a set with ASSOC = 4, and that set initially has no valid blocks
and the program generates the following accesses to the set:

MISS and replace block 3 (will increment block 3's priority to 1)
MISS and replace block 2 (will increment block 2's priority to 1)
MISS and replace block 1 (will increment block 1's priority to 1)
MISS and replace block 0 (will increment block 

Re: [RFC PATCH v2 2/3] plugins: cache: Enabled parameterization and added trace printing

2021-06-01 Thread Mahmoud Mandour
On Tue, Jun 1, 2021 at 1:29 PM Alex Bennée  wrote:

>
> (Stefan CC'ed for tracing discussion)
>
> Mahmoud Mandour  writes:
>
> > Made both icache and dcache configurable through plugin arguments
> > and added memory trace printing in a separate file.
>
> Please keep the commits discreet and single topic. The memory trace is
> an extra feature so should be in it's own commit.
>
> >
> > Signed-off-by: Mahmoud Mandour 
> > ---
> >  contrib/plugins/cache.c | 68 +++--
> >  1 file changed, 66 insertions(+), 2 deletions(-)
> >
> > diff --git a/contrib/plugins/cache.c b/contrib/plugins/cache.c
> > index 8c9d1dd538..fa0bf1dd40 100644
> > --- a/contrib/plugins/cache.c
> > +++ b/contrib/plugins/cache.c
> > @@ -22,7 +22,7 @@ static GRand *rng;
> >  static GHashTable *dmiss_ht;
> >  static GHashTable *imiss_ht;
> >
> > -static GMutex dmtx, imtx;
> > +static GMutex dmtx, imtx, fmtx;
> >
> >  static int limit;
> >  static bool sys;
> > @@ -33,6 +33,8 @@ static uint64_t dmisses;
> >  static uint64_t imem_accesses;
> >  static uint64_t imisses;
> >
> > +FILE *tracefile;
> > +
> >  static enum qemu_plugin_mem_rw rw = QEMU_PLUGIN_MEM_RW;
> >
> >  enum AccessResult {
> > @@ -205,6 +207,16 @@ static void vcpu_mem_access(unsigned int cpu_index,
> qemu_plugin_meminfo_t info,
> >  insn_addr = ((struct InsnData *) userdata)->addr;
> >  effective_addr = hwaddr ? qemu_plugin_hwaddr_phys_addr(hwaddr) :
> vaddr;
> >
> > +if (tracefile) {
> > +g_mutex_lock();
> > +g_autoptr(GString) rep = g_string_new("");
> > +bool is_store = qemu_plugin_mem_is_store(info);
> > +g_string_append_printf(rep, "%c: 0x%" PRIx64,
> > +is_store ? 'S' : 'L', effective_addr);
> > +fprintf(tracefile, "%s\n", rep->str);
> > +g_mutex_unlock();
> > +}
>
> I can see this would be useful for debugging but I'm wary of adding
> ad-hoc tracing formats when QEMU already has support for a wide range of
> tracing formats. We discussed this a bit in:
>
>   Subject: trace_FOO_tcg bit-rotted?
>   Date: Tue, 06 Apr 2021 17:00:20 +0100
>   Message-ID: <87eefnwd0l@linaro.org>
>
> However I don't know how easy it would be to leverage the existing
> tracing infrastructure from inside a plugin. As I understand it QEMU
> currently builds a static list of trace points during the build so maybe
> we would need additional infrastructure for a plugin to register a trace
> point and for the final output to be use-able. For example the binary
> trace output I think still needs to reference the source trace-events
> file?
>
> So that's not a NACK but maybe we could spend a little time working out
> if we can come up with a cleaner solution?

Alright then, I will have it removed for now and maybe add it if there's a
better
solution for it.

>


> Stefan, any thoughts?
>
> >  if (access_cache(dcache, effective_addr) == MISS) {
> >  struct InsnData *insn = get_or_create(dmiss_ht, userdata,
> insn_addr);
> >  insn->misses++;
> > @@ -221,11 +233,20 @@ static void vcpu_insn_exec(unsigned int
> vcpu_index, void *userdata)
> >  g_mutex_lock();
> >  addr = ((struct InsnData *) userdata)->addr;
> >
> > +if (tracefile) {
> > +g_mutex_lock();
> > +g_autoptr(GString) rep = g_string_new("");
> > +g_string_append_printf(rep, "I: 0x%" PRIx64, addr);
> > +fprintf(tracefile, "%s\n", rep->str);
> > +g_mutex_unlock();
> > +}
> > +
> >  if (access_cache(icache, addr) == MISS) {
> >  struct InsnData *insn = get_or_create(imiss_ht, userdata, addr);
> >  insn->misses++;
> >  imisses++;
> >  }
> > +
> >  imem_accesses++;
> >  g_mutex_unlock();
> >  }
> > @@ -352,6 +373,15 @@ static void plugin_exit()
> >
> >  g_mutex_unlock();
> >  g_mutex_unlock();
> > +
> > +if (tracefile) {
> > +fclose(tracefile);
> > +}
> > +}
> > +
> > +static bool bad_cache_params(int blksize, int assoc, int cachesize)
> > +{
> > +return (cachesize % blksize) != 0 || (cachesize % (blksize * assoc)
> != 0);
> >  }
> >
> >  QEMU_PLUGIN_EXPORT
> > @@ -377,14 +407,48 @@ int qemu_plugin_install(qemu_plugin_id_t id, const
> qemu_info_t *info,
> >
> >  for (i = 0; i < argc; i++) {
> >  char *opt = argv[i];
> > -if (g_str_has_prefix(opt, "limit=")) {
> > +if (g_str_has_prefix(opt, "I=")) {
> > +gchar **toks = g_strsplit(opt + 2, " ", -1);
> > +if (g_strv_length(toks) != 3) {
> > +fprintf(stderr, "option parsing failed: %s\n", opt);
> > +return -1;
> > +}
> > +icachesize = g_ascii_strtoull(toks[0], NULL, 10);
> > +iassoc = g_ascii_strtoull(toks[1], NULL, 10);
> > +iblksize = g_ascii_strtoull(toks[2], NULL, 10);
> > +} else if (g_str_has_prefix(opt, "D=")) {
> > +gchar **toks = g_strsplit(opt + 2, " ", -1);
> > +if 

[PATCH] target/i386: Fix decode of cr8

2021-06-01 Thread Richard Henderson
A recent cleanup did not recognize that there are two ways
to encode cr8: one via the LOCK and the other via REX.

Fixes: 7eff2e7c
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/380
Signed-off-by: Richard Henderson 
---
 target/i386/tcg/translate.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 834186bcae..a7f5c0c8f2 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -8091,6 +8091,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 case 2:
 case 3:
 case 4:
+case 8:
 break;
 default:
 goto unknown_op;
-- 
2.25.1




Re: [RFC PATCH 1/3] plugins: Added a new cache modelling plugin

2021-06-01 Thread Mahmoud Mandour
On Tue, Jun 1, 2021 at 1:12 PM Alex Bennée  wrote:

>
> Mahmoud Mandour  writes:
>
> > Added a cache modelling plugin that uses a static configuration used in
> > many of the commercial microprocessors and uses random eviction policy.
> >
> > Signed-off-by: Mahmoud Mandour 
> > ---
> >  contrib/plugins/Makefile |   1 +
> >  contrib/plugins/cache.c  | 398 +++
> >  2 files changed, 399 insertions(+)
> >  create mode 100644 contrib/plugins/cache.c
> >
> > diff --git a/contrib/plugins/Makefile b/contrib/plugins/Makefile
> > index b9d7935e5e..2237b47f8b 100644
> > --- a/contrib/plugins/Makefile
> > +++ b/contrib/plugins/Makefile
> > @@ -18,6 +18,7 @@ NAMES += hotpages
> >  NAMES += howvec
> >  NAMES += lockstep
> >  NAMES += hwprofile
> > +NAMES += cache
> >
> >  SONAMES := $(addsuffix .so,$(addprefix lib,$(NAMES)))
> >
> > diff --git a/contrib/plugins/cache.c b/contrib/plugins/cache.c
> > new file mode 100644
> > index 00..f8c15ebed2
> > --- /dev/null
> > +++ b/contrib/plugins/cache.c
> > @@ -0,0 +1,398 @@
> > +/*
> > + * Copyright (C) 2021, Mahmoud Mandour 
> > + *
> > + * License: GNU GPL, version 2 or later.
> > + *   See the COPYING file in the top-level directory.
> > + */
> > +
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#include 
> > +
> > +QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
> > +
> > +static GRand *rng;
> > +static GHashTable *dmiss_ht;
> > +static GHashTable *imiss_ht;
> > +
> > +static GMutex dmtx, imtx;
> > +
> > +static int limit;
> > +static bool sys;
> > +
> > +static uint64_t dmem_accesses;
> > +static uint64_t dmisses;
> > +
> > +static uint64_t imem_accesses;
> > +static uint64_t imisses;
> > +
> > +static enum qemu_plugin_mem_rw rw = QEMU_PLUGIN_MEM_RW;
> > +
> > +enum AccessResult {
> > +HIT = 0,
> > +MISS = 1
> > +};
> > +
> > +struct InsnData {
> > +char *disas_str;
> > +uint64_t addr;
> > +uint64_t misses;
> > +};
>
> A little commentary to the relationship between CacheSet and CacheBlock
> would be useful here for those trying to follow the code. Maybe a little
> ascii art if your up to it?
>
> > +
> > +struct CacheBlock {
> > +uint64_t tag;
> > +bool valid;
> > +};
> > +
> > +struct CacheSet {
> > +struct CacheBlock *blocks;
> > +};
> > +
> > +struct Cache {
> > +struct CacheSet *sets;
> > +int num_sets;
> > +
> > +int cachesize;
> > +int blksize;
> > +int assoc;
> > +
> > +uint64_t blk_mask;
> > +uint64_t set_mask;
> > +uint64_t tag_mask;
> > +};
> > +
> > +struct Cache *dcache, *icache;
> > +
> > +static int pow_of_two(int num)
> > +{
> > +g_assert((num & (num - 1)) == 0);
> > +int ret = 0;
> > +while (num /= 2) {
> > +ret++;
> > +}
> > +return ret;
> > +}
>
> You could probably eliminate this by:
>
>   a) pre-calculating masks and shifts at start-up
>   b) expressing cache-size as a power of 2 (are caches ever not?)
>
> Currently it is by far the biggest hit on the CPU:
>
>   46.42%  qemu-aarch64  libcache.so  [.] pow_of_two
>   16.71%  qemu-aarch64  libcache.so  [.] lru_update_on_hit
>   14.12%  qemu-aarch64  libcache.so  [.] in_cache
>6.73%  qemu-aarch64  libcache.so  [.] extract_tag
>4.52%  qemu-aarch64  libcache.so  [.] extract_set
>4.48%  qemu-aarch64  libcache.so  [.] access_cache
>2.34%  qemu-aarch64  libcache.so  [.] vcpu_insn_exec
>1.63%  qemu-aarch64  libcache.so  [.] vcpu_mem_access
>0.72%  qemu-aarch64  libglib-2.0.so.0.5800.3  [.] g_mutex_lock
>
> > +static inline uint64_t extract_tag(struct Cache *cache, uint64_t addr)
> > +{
> > +return (addr & cache->tag_mask) >>
> > +(pow_of_two(cache->num_sets) + pow_of_two(cache->blksize));
> > +}
> > +
> > +static inline uint64_t extract_set(struct Cache *cache, uint64_t addr)
> > +{
> > +return (addr & cache->set_mask) >> (pow_of_two(cache->blksize));
> > +}
>
> It would make sense to enforce pow_of_two for num_sets and blksize on
> initialisation to avoid doing it for every tag. Maybe rename them to
> set_shift and blksize_shift to better indicate their usage.
>
> That's of course problematic, I guess I need to precompute it once
for each cache and not for each tag extraction. However, I  think that I
got this
wrong since I do not even need to shift down the tag. I can extract the tag
as
the high-order bits by only masking for every access and also store that in
the
cache, which works fine. pow_of_two would still propose a  problem since I
need to compute it for extract_set, so I can store that once in the cache,
yes.

Also, can you please tell me what do you use to access plugin profiling
data? To my
knowledge, gprof is not able to work out profiling data for loaded shared
libraries.
I tried sprof but I'm getting an error caused by a 

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

2021-06-01 Thread Cindy Lu
Add new call back function in vhost-vdpa, this call back function only
supported in vhost-vdpa backend

Signed-off-by: Cindy Lu 
---
 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 c62727f879..60a15f0186 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: %p"
+
 
 # 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 01d2101d09..9ba2a2bed4 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -545,6 +545,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)
@@ -611,4 +617,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 v7 08/10] virtio-pci: decouple virtqueue from kvm_virtio_pci_vector_use

2021-06-01 Thread Cindy Lu
inorder to support configure interrupt, we need to decouple
virtqueue from vector use and vector release function
this patch introduce vector_release_one and vector_use_one
to support one vector.

Signed-off-by: Cindy Lu 
---
 hw/virtio/virtio-pci.c | 122 -
 1 file changed, 61 insertions(+), 61 deletions(-)

diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 6a4ef413a4..f863c89de6 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -666,7 +666,6 @@ static uint32_t virtio_read_config(PCIDevice *pci_dev,
 }
 
 static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy,
-unsigned int queue_no,
 unsigned int vector)
 {
 VirtIOIRQFD *irqfd = >vector_irqfd[vector];
@@ -710,85 +709,86 @@ static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy 
*proxy,
 ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, n, irqfd->virq);
 assert(ret == 0);
 }
-
-static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs)
+static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no,
+  EventNotifier **n, unsigned int *vector)
 {
 PCIDevice *dev = >pci_dev;
 VirtIODevice *vdev = virtio_bus_get_device(>bus);
-VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
-unsigned int vector;
-int ret, queue_no;
 VirtQueue *vq;
-EventNotifier *n;
-for (queue_no = 0; queue_no < nvqs; queue_no++) {
+
+if (queue_no == VIRTIO_CONFIG_IRQ_IDX) {
+return -1;
+} else {
 if (!virtio_queue_get_num(vdev, queue_no)) {
-break;
-}
-vector = virtio_queue_vector(vdev, queue_no);
-if (vector >= msix_nr_vectors_allocated(dev)) {
-continue;
-}
-ret = kvm_virtio_pci_vq_vector_use(proxy, queue_no, vector);
-if (ret < 0) {
-goto undo;
-}
-/* If guest supports masking, set up irqfd now.
- * Otherwise, delay until unmasked in the frontend.
- */
-if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) {
-vq = virtio_get_queue(vdev, queue_no);
-n = virtio_queue_get_guest_notifier(vq);
-ret = kvm_virtio_pci_irqfd_use(proxy, n, vector);
-if (ret < 0) {
-kvm_virtio_pci_vq_vector_release(proxy, vector);
-goto undo;
-}
+return -1;
 }
+*vector = virtio_queue_vector(vdev, queue_no);
+vq = virtio_get_queue(vdev, queue_no);
+*n = virtio_queue_get_guest_notifier(vq);
+}
+if (*vector >= msix_nr_vectors_allocated(dev)) {
+return -1;
 }
 return 0;
+}
 
+static int kvm_virtio_pci_vector_use_one(VirtIOPCIProxy *proxy, int queue_no)
+{
+unsigned int vector;
+int ret;
+EventNotifier *n;
+ret = virtio_pci_get_notifier(proxy, queue_no, , );
+if (ret < 0) {
+return ret;
+}
+ret = kvm_virtio_pci_vq_vector_use(proxy, vector);
+if (ret < 0) {
+goto undo;
+}
+ret = kvm_virtio_pci_irqfd_use(proxy, n, vector);
+if (ret < 0) {
+goto undo;
+}
+return 0;
 undo:
-while (--queue_no >= 0) {
-vector = virtio_queue_vector(vdev, queue_no);
-if (vector >= msix_nr_vectors_allocated(dev)) {
-continue;
-}
-if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) {
-vq = virtio_get_queue(vdev, queue_no);
-n = virtio_queue_get_guest_notifier(vq);
-kvm_virtio_pci_irqfd_release(proxy, n, vector);
-}
-kvm_virtio_pci_vq_vector_release(proxy, vector);
+kvm_virtio_pci_irqfd_release(proxy, n, vector);
+return ret;
+}
+static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs)
+{
+int queue_no;
+int ret = 0;
+for (queue_no = 0; queue_no < nvqs; queue_no++) {
+ret = kvm_virtio_pci_vector_use_one(proxy, queue_no);
 }
 return ret;
 }
 
-static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs)
+
+static void kvm_virtio_pci_vector_release_one(VirtIOPCIProxy *proxy,
+int queue_no)
 {
-PCIDevice *dev = >pci_dev;
 VirtIODevice *vdev = virtio_bus_get_device(>bus);
 unsigned int vector;
-int queue_no;
-VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
-VirtQueue *vq;
 EventNotifier *n;
+int ret;
+VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
+ret = virtio_pci_get_notifier(proxy, queue_no, , );
+if (ret < 0) {
+return;
+}
+
+if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) {
+kvm_virtio_pci_irqfd_release(proxy, n, vector);
+}
+kvm_virtio_pci_vq_vector_release(proxy, vector);
+}
+static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs)
+{
+int queue_no;
+
 for (queue_no = 0; 

[PATCH v7 09/10] virtio-pci: add support for configure interrupt

2021-06-01 Thread Cindy Lu
Add support for configure interrupt, use kvm_irqfd_assign and set the
gsi to kernel. When the configure notifier was eventfd_signal by host
kernel, this will finally inject an msix interrupt to guest

Signed-off-by: Cindy Lu 
---
 hw/virtio/virtio-pci.c | 63 --
 1 file changed, 60 insertions(+), 3 deletions(-)

diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index f863c89de6..1e03f11a85 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -717,7 +717,8 @@ static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, 
int queue_no,
 VirtQueue *vq;
 
 if (queue_no == VIRTIO_CONFIG_IRQ_IDX) {
-return -1;
+*n = virtio_get_config_notifier(vdev);
+*vector = vdev->config_vector;
 } else {
 if (!virtio_queue_get_num(vdev, queue_no)) {
 return -1;
@@ -764,6 +765,10 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy 
*proxy, int nvqs)
 return ret;
 }
 
+static int kvm_virtio_pci_vector_config_use(VirtIOPCIProxy *proxy)
+{
+return kvm_virtio_pci_vector_use_one(proxy, VIRTIO_CONFIG_IRQ_IDX);
+}
 
 static void kvm_virtio_pci_vector_release_one(VirtIOPCIProxy *proxy,
 int queue_no)
@@ -792,6 +797,28 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy 
*proxy, int nvqs)
 }
 }
 
+static void kvm_virtio_pci_vector_config_release(VirtIOPCIProxy *proxy)
+{
+kvm_virtio_pci_vector_release_one(proxy, VIRTIO_CONFIG_IRQ_IDX);
+}
+static int virtio_pci_set_config_notifier(DeviceState *d, bool assign)
+{
+VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
+VirtIODevice *vdev = virtio_bus_get_device(>bus);
+EventNotifier *notifier = virtio_get_config_notifier(vdev);
+int r = 0;
+if (assign) {
+r = event_notifier_init(notifier, 0);
+virtio_set_notifier_fd_handler(vdev, VIRTIO_CONFIG_IRQ_IDX, true, 
true);
+kvm_virtio_pci_vector_config_use(proxy);
+} else {
+virtio_set_notifier_fd_handler(vdev, VIRTIO_CONFIG_IRQ_IDX,
+ false, true);
+kvm_virtio_pci_vector_config_release(proxy);
+event_notifier_cleanup(notifier);
+}
+return r;
+}
 static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
unsigned int queue_no,
unsigned int vector,
@@ -873,9 +900,17 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, 
unsigned vector,
 }
 vq = virtio_vector_next_queue(vq);
 }
-
+n = virtio_get_config_notifier(vdev);
+ret = virtio_pci_vq_vector_unmask(proxy, VIRTIO_CONFIG_IRQ_IDX,
+vector, msg, n);
+if (ret < 0) {
+goto config_undo;
+}
 return 0;
 
+config_undo:
+n = virtio_get_config_notifier(vdev);
+virtio_pci_vq_vector_mask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector, n);
 undo:
 vq = virtio_vector_first_queue(vdev, vector);
 while (vq && unmasked >= 0) {
@@ -909,6 +944,8 @@ static void virtio_pci_vector_mask(PCIDevice *dev, unsigned 
vector)
 }
 vq = virtio_vector_next_queue(vq);
 }
+n = virtio_get_config_notifier(vdev);
+virtio_pci_vq_vector_mask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector, n);
 }
 
 static void virtio_pci_vector_poll(PCIDevice *dev,
@@ -942,6 +979,20 @@ static void virtio_pci_vector_poll(PCIDevice *dev,
 msix_set_pending(dev, vector);
 }
 }
+   /*check for config interrupt*/
+   vector = vdev->config_vector;
+   notifier = virtio_get_config_notifier(vdev);
+   if (vector < vector_start || vector >= vector_end ||
+!msix_is_masked(dev, vector)) {
+return;
+   }
+   if (k->guest_notifier_pending) {
+if (k->guest_notifier_pending(vdev, VIRTIO_CONFIG_IRQ_IDX)) {
+msix_set_pending(dev, vector);
+}
+   } else if (event_notifier_test_and_clear(notifier)) {
+msix_set_pending(dev, vector);
+   }
 }
 
 static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign,
@@ -1002,6 +1053,7 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, 
int nvqs, bool assign)
 msix_unset_vector_notifiers(>pci_dev);
 if (proxy->vector_irqfd) {
 kvm_virtio_pci_vector_release(proxy, nvqs);
+kvm_virtio_pci_vector_config_release(proxy);
 g_free(proxy->vector_irqfd);
 proxy->vector_irqfd = NULL;
 }
@@ -1029,6 +1081,10 @@ static int virtio_pci_set_guest_notifiers(DeviceState 
*d, int nvqs, bool assign)
 goto assign_error;
 }
 }
+r = virtio_pci_set_config_notifier(d, assign);
+if (r < 0) {
+goto config_error;
+}
 r = msix_set_vector_notifiers(>pci_dev,
   virtio_pci_vector_unmask,
   virtio_pci_vector_mask,
@@ -1045,7 +1101,8 @@ notifiers_error:
 assert(assign);
 

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

2021-06-01 Thread Cindy Lu
To support configure interrupt, we need to
add a new call back function for config interrupt.

Signed-off-by: Cindy Lu 
---
 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 8a6f8e2a7a..adaf6982d2 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -125,6 +125,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;
@@ -170,6 +172,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




[PATCH v7 07/10] virtio-mmio: add support for configure interrupt

2021-06-01 Thread Cindy Lu
Add configure interrupt support for virtio-mmio bus. This
interrupt will working while backend is vhost-vdpa

Signed-off-by: Cindy Lu 
---
 hw/virtio/virtio-mmio.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
index 13772d52bb..423267d51c 100644
--- a/hw/virtio/virtio-mmio.c
+++ b/hw/virtio/virtio-mmio.c
@@ -670,7 +670,26 @@ static int virtio_mmio_set_guest_notifier(DeviceState *d, 
int n, bool assign,
 
 return 0;
 }
+static int virtio_mmio_set_config_notifier(DeviceState *d, bool assign)
+{
+VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
+VirtIODevice *vdev = virtio_bus_get_device(>bus);
+VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
 
+EventNotifier *notifier = virtio_get_config_notifier(vdev);
+int r = 0;
+if (assign) {
+r = event_notifier_init(notifier, 0);
+virtio_set_notifier_fd_handler(vdev, -1, true, false);
+} else {
+virtio_set_notifier_fd_handler(vdev, -1, false, false);
+event_notifier_cleanup(notifier);
+}
+if (vdc->guest_notifier_mask && vdev->use_guest_notifier_mask) {
+vdc->guest_notifier_mask(vdev, -1, !assign);
+}
+return r;
+}
 static int virtio_mmio_set_guest_notifiers(DeviceState *d, int nvqs,
bool assign)
 {
@@ -692,8 +711,15 @@ static int virtio_mmio_set_guest_notifiers(DeviceState *d, 
int nvqs,
 goto assign_error;
 }
 }
+r = virtio_mmio_set_config_notifier(d, assign);
+if (r < 0) {
+goto config_assign_error;
+}
 
 return 0;
+config_assign_error:
+assert(assign);
+r = virtio_mmio_set_config_notifier(d, false);
 
 assign_error:
 /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
-- 
2.21.3




[PATCH v7 03/10] virtio: decouple virtqueue from set notifier fd handler

2021-06-01 Thread Cindy Lu
To support config interrupt.we need to decouple virtqueue number
from virtio_queue_set_guest_notifier_fd_handler,

Signed-off-by: Cindy Lu 
---
 hw/s390x/virtio-ccw.c  |  6 +++---
 hw/virtio/virtio-mmio.c|  4 ++--
 hw/virtio/virtio-pci.c |  4 ++--
 hw/virtio/virtio.c | 17 +++--
 include/hw/virtio/virtio.h |  2 +-
 5 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 8195f3546e..58bb5232fd 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -1028,11 +1028,11 @@ static int 
virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
 if (r < 0) {
 return r;
 }
-virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
+virtio_set_notifier_fd_handler(vdev, n, true, with_irqfd);
 if (with_irqfd) {
 r = virtio_ccw_add_irqfd(dev, n);
 if (r) {
-virtio_queue_set_guest_notifier_fd_handler(vq, false,
+virtio_set_notifier_fd_handler(vdev, n, false,
with_irqfd);
 return r;
 }
@@ -1056,7 +1056,7 @@ static int virtio_ccw_set_guest_notifier(VirtioCcwDevice 
*dev, int n,
 if (with_irqfd) {
 virtio_ccw_remove_irqfd(dev, n);
 }
-virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
+virtio_set_notifier_fd_handler(vdev, n, false, with_irqfd);
 event_notifier_cleanup(notifier);
 }
 return 0;
diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
index 342c918ea7..13772d52bb 100644
--- a/hw/virtio/virtio-mmio.c
+++ b/hw/virtio/virtio-mmio.c
@@ -658,9 +658,9 @@ static int virtio_mmio_set_guest_notifier(DeviceState *d, 
int n, bool assign,
 if (r < 0) {
 return r;
 }
-virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
+virtio_set_notifier_fd_handler(vdev, n, true, with_irqfd);
 } else {
-virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
+virtio_set_notifier_fd_handler(vdev, n, false, with_irqfd);
 event_notifier_cleanup(notifier);
 }
 
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index c5c080ec94..6a4ef413a4 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -958,9 +958,9 @@ static int virtio_pci_set_guest_notifier(DeviceState *d, 
int n, bool assign,
 if (r < 0) {
 return r;
 }
-virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
+virtio_set_notifier_fd_handler(vdev, n, true, with_irqfd);
 } else {
-virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
+virtio_set_notifier_fd_handler(vdev, n, false, with_irqfd);
 event_notifier_cleanup(notifier);
 }
 
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 07f4e60b30..c5d786bb5e 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -3505,19 +3505,24 @@ static void 
virtio_queue_guest_notifier_read(EventNotifier *n)
 }
 }
 
-void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign,
-bool with_irqfd)
+
+void virtio_set_notifier_fd_handler(VirtIODevice *vdev, int queue_no,
+   bool assign, bool with_irqfd)
 {
+EventNotifier *e ;
+EventNotifierHandler *handler;
+VirtQueue *vq = virtio_get_queue(vdev, queue_no);
+e = >guest_notifier;
+handler = virtio_queue_guest_notifier_read;
 if (assign && !with_irqfd) {
-event_notifier_set_handler(>guest_notifier,
-   virtio_queue_guest_notifier_read);
+event_notifier_set_handler(e, handler);
 } else {
-event_notifier_set_handler(>guest_notifier, NULL);
+event_notifier_set_handler(e, NULL);
 }
 if (!assign) {
 /* Test and clear notifier before closing it,
  * in case poll callback didn't have time to run. */
-virtio_queue_guest_notifier_read(>guest_notifier);
+handler(e);
 }
 }
 
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 63cb9455ed..447899dea5 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -310,7 +310,7 @@ void virtio_queue_update_used_idx(VirtIODevice *vdev, int 
n);
 VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n);
 uint16_t virtio_get_queue_index(VirtQueue *vq);
 EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq);
-void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign,
+void virtio_set_notifier_fd_handler(VirtIODevice *vdev, int n, bool assign,
 bool with_irqfd);
 int virtio_device_start_ioeventfd(VirtIODevice *vdev);
 int virtio_device_grab_ioeventfd(VirtIODevice *vdev);
-- 
2.21.3




[PATCH v7 10/10] virtio-net: add peer_deleted check in virtio_net_handle_rx

2021-06-01 Thread Cindy Lu
During the test, We found this function will continue running
while the peer is deleted, this will cause the crash. so add
check for this. this only exist in  machines type microvm

reproduce step :
load the VM with
qemu-system-x86_64 -M microvm
...
-netdev tap,id=tap0,vhost=on,script=no,downscript=no \
-device virtio-net-device,netdev=tap0 \
..
enter the VM's console
shutdown the VM
(gdb) bt

0  0x5595b926 in qemu_net_queue_flush (queue=0x0) at ../net/queue.c:275
1  0x55a046ea in qemu_flush_or_purge_queued_packets (nc=0x56ccb920, 
purge=false)
at ../net/net.c:624
2  0x55a04736 in qemu_flush_queued_packets (nc=0x56ccb920) at 
../net/net.c:637
3  0x55ccc01a in virtio_net_handle_rx (vdev=0x57360ed0, 
vq=0x740d6010)
at ../hw/net/virtio-net.c:1401
4  0x55ce907a in virtio_queue_notify_vq (vq=0x740d6010) at 
../hw/virtio/virtio.c:2346
5  0x55cec07c in virtio_queue_host_notifier_read (n=0x740d608c)
at ../hw/virtio/virtio.c:3606
6  0x560376ac in aio_dispatch_handler (ctx=0x56a857e0, 
node=0x56f013d0)
at ../util/aio-posix.c:329
7  0x560377a4 in aio_dispatch_ready_handlers (ctx=0x56a857e0,
ready_list=0x7fffdfe0) at ../util/aio-posix.c:359
8  0x56038209 in aio_poll (ctx=0x56a857e0, blocking=false) at 
../util/aio-posix.c:662
9  0x55e51c6f in monitor_cleanup () at ../monitor/monitor.c:637
10 0x55d2d626 in qemu_cleanup () at ../softmmu/runstate.c:821
11 0x5585b19b in main (argc=21, argv=0x7fffe1c8, 
envp=0x7fffe278)

Signed-off-by: Cindy Lu 
---
 hw/net/virtio-net.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 02033be748..927a808654 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1397,7 +1397,9 @@ static void virtio_net_handle_rx(VirtIODevice *vdev, 
VirtQueue *vq)
 {
 VirtIONet *n = VIRTIO_NET(vdev);
 int queue_index = vq2q(virtio_get_queue_index(vq));
-
+if (n->nic->peer_deleted) {
+return;
+}
 qemu_flush_queued_packets(qemu_get_subqueue(n->nic, queue_index));
 }
 
-- 
2.21.3




[PATCH v7 06/10] vhost:add support for configure interrupt

2021-06-01 Thread Cindy Lu
Add configure notifier support in vhost and virtio driver
When backend support VIRTIO_NET_F_STATUS,setup the configure
interrupt function in vhost_dev_start and release the related
resource when vhost_dev_stop

Signed-off-by: Cindy Lu 
---
 hw/net/vhost_net.c |  9 +
 hw/net/virtio-net.c|  6 
 hw/virtio/vhost.c  | 68 --
 hw/virtio/virtio.c | 23 +++--
 include/hw/virtio/vhost.h  |  2 ++
 include/hw/virtio/virtio.h |  3 ++
 include/net/vhost_net.h|  3 ++
 7 files changed, 109 insertions(+), 5 deletions(-)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 24d555e764..5d0c35f18d 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -426,6 +426,15 @@ void vhost_net_virtqueue_mask(VHostNetState *net, 
VirtIODevice *dev,
 vhost_virtqueue_mask(>dev, dev, idx, mask);
 }
 
+bool vhost_net_config_pending(VHostNetState *net, int idx)
+{
+return vhost_config_pending(>dev, idx);
+}
+void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev,
+  bool mask)
+{
+vhost_config_mask(>dev, dev, mask);
+}
 VHostNetState *get_vhost_net(NetClientState *nc)
 {
 VHostNetState *vhost_net = 0;
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index f50235b5d6..02033be748 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -3055,6 +3055,9 @@ static bool 
virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx)
 if (idx != VIRTIO_CONFIG_IRQ_IDX) {
 return vhost_net_virtqueue_pending(get_vhost_net(nc->peer), idx);
 }
+if (idx == VIRTIO_CONFIG_IRQ_IDX) {
+return vhost_net_config_pending(get_vhost_net(nc->peer), idx);
+   }
 return false;
 }
 
@@ -3067,6 +3070,9 @@ static void virtio_net_guest_notifier_mask(VirtIODevice 
*vdev, int idx,
 if (idx != VIRTIO_CONFIG_IRQ_IDX) {
 vhost_net_virtqueue_mask(get_vhost_net(nc->peer), vdev, idx, mask);
 }
+if (idx == VIRTIO_CONFIG_IRQ_IDX) {
+vhost_net_config_mask(get_vhost_net(nc->peer), vdev, mask);
+ }
 }
 
 static void virtio_net_set_config_size(VirtIONet *n, uint64_t host_features)
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index e2163a0d63..3b05f09d98 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -21,6 +21,7 @@
 #include "qemu/error-report.h"
 #include "qemu/memfd.h"
 #include "standard-headers/linux/vhost_types.h"
+#include "standard-headers/linux/virtio_net.h"
 #include "exec/address-spaces.h"
 #include "hw/virtio/virtio-bus.h"
 #include "hw/virtio/virtio-access.h"
@@ -1505,6 +1506,16 @@ bool vhost_virtqueue_pending(struct vhost_dev *hdev, int 
n)
 return event_notifier_test_and_clear(>masked_notifier);
 }
 
+bool vhost_config_pending(struct vhost_dev *hdev, int n)
+{
+assert(hdev->vhost_ops);
+VirtIODevice *vdev = hdev->vdev;
+if ((hdev->started == false) ||
+(hdev->vhost_ops->vhost_set_config_call == NULL)) {
+return false;
+}
+return event_notifier_test_and_clear(>masked_config_notifier);
+}
 /* Mask/unmask events from this vq. */
 void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
  bool mask)
@@ -1529,6 +1540,30 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, 
VirtIODevice *vdev, int n,
 VHOST_OPS_DEBUG("vhost_set_vring_call failed");
 }
 }
+void vhost_config_mask(struct vhost_dev *hdev, VirtIODevice *vdev,
+ bool mask)
+{
+   int fd;
+   int r;
+   EventNotifier *masked_config_notifier = >masked_config_notifier;
+   EventNotifier *config_notifier = >config_notifier;
+   assert(hdev->vhost_ops);
+
+   if ((hdev->started == false) ||
+(hdev->vhost_ops->vhost_set_config_call == NULL)) {
+return ;
+}
+if (mask) {
+assert(vdev->use_guest_notifier_mask);
+fd = event_notifier_get_fd(masked_config_notifier);
+} else {
+fd = event_notifier_get_fd(config_notifier);
+}
+   r = hdev->vhost_ops->vhost_set_config_call(hdev, );
+   if (r < 0) {
+error_report("vhost_set_config_call failed");
+}
+}
 
 uint64_t vhost_get_features(struct vhost_dev *hdev, const int *feature_bits,
 uint64_t features)
@@ -1708,6 +1743,7 @@ int vhost_dev_get_inflight(struct vhost_dev *dev, 
uint16_t queue_size,
 int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
 {
 int i, r;
+int fd = 0;
 
 /* should only be called after backend is connected */
 assert(hdev->vhost_ops);
@@ -1739,7 +1775,14 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice 
*vdev)
 goto fail_vq;
 }
 }
-
+r = event_notifier_init(>masked_config_notifier, 0);
+if (r < 0) {
+return r;
+}
+event_notifier_test_and_clear(>masked_config_notifier);
+if (!vdev->use_guest_notifier_mask) {
+vhost_config_mask(hdev, vdev, true);
+}
 if (hdev->log_enabled) {
 uint64_t log_base;
 
@@ 

[PATCH v7 02/10] virtio-pci:decouple virtqueue from interrupt setting process

2021-06-01 Thread Cindy Lu
Decouple virtqueue from interrupt setting process to support config interrupt
Now the code for interrupt/vector are coupling
with the vq number, this patch will decouple the vritqueue
numbers from these functions.

Signed-off-by: Cindy Lu 
---
 hw/virtio/virtio-pci.c | 51 --
 1 file changed, 29 insertions(+), 22 deletions(-)

diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index b321604d9b..c5c080ec94 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -693,23 +693,17 @@ static void 
kvm_virtio_pci_vq_vector_release(VirtIOPCIProxy *proxy,
 }
 
 static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy,
- unsigned int queue_no,
+ EventNotifier *n,
  unsigned int vector)
 {
 VirtIOIRQFD *irqfd = >vector_irqfd[vector];
-VirtIODevice *vdev = virtio_bus_get_device(>bus);
-VirtQueue *vq = virtio_get_queue(vdev, queue_no);
-EventNotifier *n = virtio_queue_get_guest_notifier(vq);
 return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, irqfd->virq);
 }
 
 static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy *proxy,
-  unsigned int queue_no,
+  EventNotifier *n ,
   unsigned int vector)
 {
-VirtIODevice *vdev = virtio_bus_get_device(>bus);
-VirtQueue *vq = virtio_get_queue(vdev, queue_no);
-EventNotifier *n = virtio_queue_get_guest_notifier(vq);
 VirtIOIRQFD *irqfd = >vector_irqfd[vector];
 int ret;
 
@@ -724,7 +718,8 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, 
int nvqs)
 VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
 unsigned int vector;
 int ret, queue_no;
-
+VirtQueue *vq;
+EventNotifier *n;
 for (queue_no = 0; queue_no < nvqs; queue_no++) {
 if (!virtio_queue_get_num(vdev, queue_no)) {
 break;
@@ -741,7 +736,9 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, 
int nvqs)
  * Otherwise, delay until unmasked in the frontend.
  */
 if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) {
-ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector);
+vq = virtio_get_queue(vdev, queue_no);
+n = virtio_queue_get_guest_notifier(vq);
+ret = kvm_virtio_pci_irqfd_use(proxy, n, vector);
 if (ret < 0) {
 kvm_virtio_pci_vq_vector_release(proxy, vector);
 goto undo;
@@ -757,7 +754,9 @@ undo:
 continue;
 }
 if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) {
-kvm_virtio_pci_irqfd_release(proxy, queue_no, vector);
+vq = virtio_get_queue(vdev, queue_no);
+n = virtio_queue_get_guest_notifier(vq);
+kvm_virtio_pci_irqfd_release(proxy, n, vector);
 }
 kvm_virtio_pci_vq_vector_release(proxy, vector);
 }
@@ -771,7 +770,8 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy 
*proxy, int nvqs)
 unsigned int vector;
 int queue_no;
 VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
-
+VirtQueue *vq;
+EventNotifier *n;
 for (queue_no = 0; queue_no < nvqs; queue_no++) {
 if (!virtio_queue_get_num(vdev, queue_no)) {
 break;
@@ -784,7 +784,9 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy 
*proxy, int nvqs)
  * Otherwise, it was cleaned when masked in the frontend.
  */
 if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) {
-kvm_virtio_pci_irqfd_release(proxy, queue_no, vector);
+vq = virtio_get_queue(vdev, queue_no);
+n = virtio_queue_get_guest_notifier(vq);
+kvm_virtio_pci_irqfd_release(proxy, n, vector);
 }
 kvm_virtio_pci_vq_vector_release(proxy, vector);
 }
@@ -793,12 +795,11 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy 
*proxy, int nvqs)
 static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
unsigned int queue_no,
unsigned int vector,
-   MSIMessage msg)
+   MSIMessage msg,
+   EventNotifier *n)
 {
 VirtIODevice *vdev = virtio_bus_get_device(>bus);
 VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
-VirtQueue *vq = virtio_get_queue(vdev, queue_no);
-EventNotifier *n = virtio_queue_get_guest_notifier(vq);
 VirtIOIRQFD *irqfd;
 int ret = 0;
 
@@ -825,14 +826,15 @@ static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy 
*proxy,
 event_notifier_set(n);
 }
 } else {
-ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector);
+ret = kvm_virtio_pci_irqfd_use(proxy, n, vector);
 }

[PATCH v7 01/10] virtio: introduce macro IRTIO_CONFIG_IRQ_IDX 聽

2021-06-01 Thread Cindy Lu
In order to support configure interrupt for vhost-vdpa
introduce VIRTIO_CONFIG_IRQ_IDX -1as a queue index,
then we can reuse the function guest_notifier_mask and
guest_notifier_pending.
we add the check of queue index, if the driver
not support configure interrupt, the function will just return

Signed-off-by: Cindy Lu 
---
 hw/display/vhost-user-gpu.c|  6 ++
 hw/net/virtio-net.c| 10 +++---
 hw/virtio/vhost-user-fs.c  |  9 +++--
 hw/virtio/vhost-vsock-common.c |  6 ++
 hw/virtio/virtio-crypto.c  |  6 ++
 include/hw/virtio/virtio.h |  2 ++
 6 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
index 6cdaa1c73b..c232d55986 100644
--- a/hw/display/vhost-user-gpu.c
+++ b/hw/display/vhost-user-gpu.c
@@ -483,6 +483,9 @@ vhost_user_gpu_guest_notifier_pending(VirtIODevice *vdev, 
int idx)
 {
 VhostUserGPU *g = VHOST_USER_GPU(vdev);
 
+if (idx == VIRTIO_CONFIG_IRQ_IDX) {
+return false;
+}
 return vhost_virtqueue_pending(>vhost->dev, idx);
 }
 
@@ -491,6 +494,9 @@ vhost_user_gpu_guest_notifier_mask(VirtIODevice *vdev, int 
idx, bool mask)
 {
 VhostUserGPU *g = VHOST_USER_GPU(vdev);
 
+if (idx == VIRTIO_CONFIG_IRQ_IDX) {
+return;
+}
 vhost_virtqueue_mask(>vhost->dev, vdev, idx, mask);
 }
 
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 66b9ff4511..f50235b5d6 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -3052,7 +3052,10 @@ static bool 
virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx)
 VirtIONet *n = VIRTIO_NET(vdev);
 NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx));
 assert(n->vhost_started);
-return vhost_net_virtqueue_pending(get_vhost_net(nc->peer), idx);
+if (idx != VIRTIO_CONFIG_IRQ_IDX) {
+return vhost_net_virtqueue_pending(get_vhost_net(nc->peer), idx);
+}
+return false;
 }
 
 static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
@@ -3061,8 +3064,9 @@ static void virtio_net_guest_notifier_mask(VirtIODevice 
*vdev, int idx,
 VirtIONet *n = VIRTIO_NET(vdev);
 NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx));
 assert(n->vhost_started);
-vhost_net_virtqueue_mask(get_vhost_net(nc->peer),
- vdev, idx, mask);
+if (idx != VIRTIO_CONFIG_IRQ_IDX) {
+vhost_net_virtqueue_mask(get_vhost_net(nc->peer), vdev, idx, mask);
+}
 }
 
 static void virtio_net_set_config_size(VirtIONet *n, uint64_t host_features)
diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c
index 6f7f91533d..7e8ca25f71 100644
--- a/hw/virtio/vhost-user-fs.c
+++ b/hw/virtio/vhost-user-fs.c
@@ -156,11 +156,13 @@ static void vuf_handle_output(VirtIODevice *vdev, 
VirtQueue *vq)
  */
 }
 
-static void vuf_guest_notifier_mask(VirtIODevice *vdev, int idx,
-bool mask)
+static void vuf_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask)
 {
 VHostUserFS *fs = VHOST_USER_FS(vdev);
 
+if (idx == VIRTIO_CONFIG_IRQ_IDX) {
+return;
+}
 vhost_virtqueue_mask(>vhost_dev, vdev, idx, mask);
 }
 
@@ -168,6 +170,9 @@ static bool vuf_guest_notifier_pending(VirtIODevice *vdev, 
int idx)
 {
 VHostUserFS *fs = VHOST_USER_FS(vdev);
 
+if (idx == VIRTIO_CONFIG_IRQ_IDX) {
+return false;
+}
 return vhost_virtqueue_pending(>vhost_dev, idx);
 }
 
diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c
index 4ad6e234ad..2112b44802 100644
--- a/hw/virtio/vhost-vsock-common.c
+++ b/hw/virtio/vhost-vsock-common.c
@@ -101,6 +101,9 @@ static void 
vhost_vsock_common_guest_notifier_mask(VirtIODevice *vdev, int idx,
 {
 VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
 
+if (idx == VIRTIO_CONFIG_IRQ_IDX) {
+return;
+}
 vhost_virtqueue_mask(>vhost_dev, vdev, idx, mask);
 }
 
@@ -109,6 +112,9 @@ static bool 
vhost_vsock_common_guest_notifier_pending(VirtIODevice *vdev,
 {
 VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
 
+if (idx == VIRTIO_CONFIG_IRQ_IDX) {
+return false;
+}
 return vhost_virtqueue_pending(>vhost_dev, idx);
 }
 
diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
index 54f9bbb789..1d5192f8b4 100644
--- a/hw/virtio/virtio-crypto.c
+++ b/hw/virtio/virtio-crypto.c
@@ -948,6 +948,9 @@ static void virtio_crypto_guest_notifier_mask(VirtIODevice 
*vdev, int idx,
 
 assert(vcrypto->vhost_started);
 
+if (idx == VIRTIO_CONFIG_IRQ_IDX) {
+return;
+}
 cryptodev_vhost_virtqueue_mask(vdev, queue, idx, mask);
 }
 
@@ -958,6 +961,9 @@ static bool 
virtio_crypto_guest_notifier_pending(VirtIODevice *vdev, int idx)
 
 assert(vcrypto->vhost_started);
 
+if (idx == VIRTIO_CONFIG_IRQ_IDX) {
+return false;
+}
 return cryptodev_vhost_virtqueue_pending(vdev, queue, idx);
 }
 
diff --git a/include/hw/virtio/virtio.h 

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

2021-06-01 Thread Cindy Lu
these patches are add the support for configure interrupt 

These code are all tested in vp-vdpa (support configure interrupt)
vdpa_sim (not support configure interrupt)

test in virtio-pci bus and virtio-mmio bus

Change in v2:
Add support for virtio-mmio bus
active the notifier while the backend support configure interrupt
misc fixes form v1

Change in v3
fix the coding style problems

Change in v4
misc fixes form 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 form v4
split the code for introduce configure interrupt type and 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 form 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 form v6
decouple virtqueue from interrupt setting and misc process
decouple virtqueue from verctor 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

Cindy Lu (10):
  virtio: introduce macro IRTIO_CONFIG_IRQ_IDX  
  virtio-pci:decouple virtqueue from interrupt setting process
  virtio: decouple virtqueue from set notifier fd handler
  vhost: add new call back function for config interrupt
  vhost-vdpa: add support for config interrupt call back
  vhost:add support for configure interrupt
  virtio-mmio: add support for configure interrupt
  virtio-pci: decouple virtqueue from kvm_virtio_pci_vector_use
  virtio-pci: add support for configure interrupt
  virtio-net: add peer_deleted check in virtio_net_handle_rx

 hw/display/vhost-user-gpu.c   |   6 +
 hw/net/vhost_net.c|   9 ++
 hw/net/virtio-net.c   |  20 ++-
 hw/s390x/virtio-ccw.c |   6 +-
 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 |  68 +-
 hw/virtio/virtio-crypto.c |   6 +
 hw/virtio/virtio-mmio.c   |  30 -
 hw/virtio/virtio-pci.c| 210 +++---
 hw/virtio/virtio.c|  34 -
 include/hw/virtio/vhost-backend.h |   3 +
 include/hw/virtio/vhost.h |   2 +
 include/hw/virtio/virtio.h|   7 +-
 include/net/vhost_net.h   |   3 +
 17 files changed, 335 insertions(+), 93 deletions(-)

-- 
2.21.3




Re: [PATCH v2 2/2] ui/vdagent: fix clipboard info memory leak in error path

2021-06-01 Thread Thomas Huth

On 01/06/2021 17.57, Stefan Hajnoczi wrote:

If the size of a VD_AGENT_CLIPBOARD_GRAB message is invalid we leak info
when returning early.

Thanks to Coverity for spotting this:

*** CID 1453266:  Resource leaks  (RESOURCE_LEAK)
/qemu/ui/vdagent.c: 465 in vdagent_chr_recv_clipboard()
459 info = qemu_clipboard_info_new(>cbpeer, s);
460 if (size > sizeof(uint32_t) * 10) {
461 /*
462  * spice has 6 types as of 2021. Limiting to 10 entries
463  * so we we have some wiggle room.
464  */

 CID 1453266:  Resource leaks  (RESOURCE_LEAK)
 Variable "info" going out of scope leaks the storage it points to.

465 return;
466 }
467 while (size >= sizeof(uint32_t)) {
468 trace_vdagent_cb_grab_type(GET_NAME(type_name, *(uint32_t 
*)data));
469 switch (*(uint32_t *)data) {
470 case VD_AGENT_CLIPBOARD_UTF8_TEXT:

Fixes: f0349f4d8947ad32d0fa4678cbf5dbb356fcbda1 ("ui/vdagent: add clipboard 
support")
Reviewed-by: Gerd Hoffmann 
Signed-off-by: Stefan Hajnoczi 
---
  ui/vdagent.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ui/vdagent.c b/ui/vdagent.c
index a253a8fe63..8fc54d330e 100644
--- a/ui/vdagent.c
+++ b/ui/vdagent.c
@@ -456,7 +456,6 @@ static void vdagent_chr_recv_clipboard(VDAgentChardev *vd, 
VDAgentMessage *msg)
  switch (msg->type) {
  case VD_AGENT_CLIPBOARD_GRAB:
  trace_vdagent_cb_grab_selection(GET_NAME(sel_name, s));
-info = qemu_clipboard_info_new(>cbpeer, s);
  if (size > sizeof(uint32_t) * 10) {
  /*
   * spice has 6 types as of 2021. Limiting to 10 entries
@@ -464,6 +463,7 @@ static void vdagent_chr_recv_clipboard(VDAgentChardev *vd, 
VDAgentMessage *msg)
   */
  return;
  }
+info = qemu_clipboard_info_new(>cbpeer, s);
  while (size >= sizeof(uint32_t)) {
  trace_vdagent_cb_grab_type(GET_NAME(type_name, *(uint32_t 
*)data));
  switch (*(uint32_t *)data) {



Reviewed-by: Thomas Huth 




Re: [PATCH v2 1/2] vhost-user-blk-test: fix Coverity open(2) false positives

2021-06-01 Thread Thomas Huth

On 01/06/2021 17.57, Stefan Hajnoczi wrote:

Coverity checks that the file descriptor return value of open(2) is
checked and used. Normally this is helpful in identifying real bugs but
vhost-user-blk-test opens /dev/null as stdin and stdout after fork.

In this case we don't need to look at the return value because these
open(2) calls cannot fail in any reasonable environment. We already know
their return values ahead of time since we closed stdin and stdout
previously. open(2) is guaranteed to pick the lowest available fd
number.

Silence Coverity by introducing code that checks what we already know to
be true.

** CID 1453270:  Resource leaks  (RESOURCE_LEAK)
/qemu/tests/qtest/vhost-user-blk-test.c: 920 in start_vhost_user_blk()


*** CID 1453270:  Resource leaks  (RESOURCE_LEAK)
/qemu/tests/qtest/vhost-user-blk-test.c: 920 in start_vhost_user_blk()
914  * Close standard file descriptors so tap-driver.pl pipe 
detects when
915  * our parent terminates.
916  */
917 close(0);
918 close(1);
919 open("/dev/null", O_RDONLY);

 CID 1453270:  Resource leaks  (RESOURCE_LEAK)
 Ignoring handle opened by "open("/dev/null", 1)" leaks it.

920 open("/dev/null", O_WRONLY);
921
922 execlp("/bin/sh", "sh", "-c", storage_daemon_command->str, 
NULL);
923 exit(1);
924 }
925 g_string_free(storage_daemon_command, true);

** CID 1453269:  Error handling issues  (NEGATIVE_RETURNS)
/qemu/tests/qtest/vhost-user-blk-test.c: 829 in create_listen_socket()


*** CID 1453269:  Error handling issues  (NEGATIVE_RETURNS)
/qemu/tests/qtest/vhost-user-blk-test.c: 829 in create_listen_socket()
823 char *path;
824
825 /* No race because our pid makes the path unique */
826 path = g_strdup_printf("/tmp/qtest-%d-sock.XX", getpid());
827 tmp_fd = mkstemp(path);
828 g_assert_cmpint(tmp_fd, >=, 0);

 CID 1453269:  Error handling issues  (NEGATIVE_RETURNS)
 "tmp_fd" is passed to a parameter that cannot be negative.

829 close(tmp_fd);
830 unlink(path);
831
832 *fd = qtest_socket_server(path);
833 g_test_queue_destroy(destroy_file, path);
834 return path;

** CID 1453268:(CHECKED_RETURN)
/qemu/tests/qtest/vhost-user-blk-test.c: 920 in start_vhost_user_blk()
/qemu/tests/qtest/vhost-user-blk-test.c: 919 in start_vhost_user_blk()


*** CID 1453268:(CHECKED_RETURN)
/qemu/tests/qtest/vhost-user-blk-test.c: 920 in start_vhost_user_blk()
914  * Close standard file descriptors so tap-driver.pl pipe 
detects when
915  * our parent terminates.
916  */
917 close(0);
918 close(1);
919 open("/dev/null", O_RDONLY);

 CID 1453268:(CHECKED_RETURN)
 Calling "open("/dev/null", 1)" without checking return value. This library 
function may fail and return an error code. [Note: The source code implementation of the function 
has been overridden by a builtin model.]

920 open("/dev/null", O_WRONLY);
921
922 execlp("/bin/sh", "sh", "-c", storage_daemon_command->str, 
NULL);
923 exit(1);
924 }
925 g_string_free(storage_daemon_command, true);
/qemu/tests/qtest/vhost-user-blk-test.c: 919 in start_vhost_user_blk()
913 /*
914  * Close standard file descriptors so tap-driver.pl pipe 
detects when
915  * our parent terminates.
916  */
917 close(0);
918 close(1);

 CID 1453268:(CHECKED_RETURN)
 Calling "open("/dev/null", 0)" without checking return value. This library 
function may fail and return an error code. [Note: The source code implementation of the function 
has been overridden by a builtin model.]

919 open("/dev/null", O_RDONLY);
920 open("/dev/null", O_WRONLY);
921
922 execlp("/bin/sh", "sh", "-c", storage_daemon_command->str, 
NULL);
923 exit(1);
924 }

Signed-off-by: Stefan Hajnoczi 
---
  tests/qtest/vhost-user-blk-test.c | 8 ++--
  1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/tests/qtest/vhost-user-blk-test.c 
b/tests/qtest/vhost-user-blk-test.c
index 8796c74ca4..c5c4667759 100644
--- a/tests/qtest/vhost-user-blk-test.c
+++ b/tests/qtest/vhost-user-blk-test.c
@@ -910,14 +910,18 @@ static void start_vhost_user_blk(GString *cmd_line, int 
vus_instances,
 storage_daemon_command->str);
  pid_t pid = fork();
  if (pid == 0) {
+int fd;
+
  /*
   * Close standard file descriptors so 

[PATCH 1/2] vhost-vdpa: don't initialize backend_features

2021-06-01 Thread Jason Wang
We used to initialize backend_features during vhost_vdpa_init()
regardless whether or not it was supported by vhost. This will lead
the unsupported features like VIRTIO_F_IN_ORDER to be included and set
to the vhost-vdpa during vhost_dev_start. Because the
VIRTIO_F_IN_ORDER is not supported by vhost-vdpa so it won't be
advertised to guest which will break the datapath.

Fix this by not initializing the backend_features, so the
acked_features could be built only from guest features via
vhost_net_ack_features().

Fixes: 108a64818e69b ("vhost-vdpa: introduce vhost-vdpa backend")
Cc: qemu-sta...@nongnu.org
Cc: Gautam Dawar 
Signed-off-by: Jason Wang 
---
 hw/virtio/vhost-vdpa.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 01d2101d09..5fe43a4eb5 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -275,15 +275,12 @@ static void vhost_vdpa_add_status(struct vhost_dev *dev, 
uint8_t status)
 static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque)
 {
 struct vhost_vdpa *v;
-uint64_t features;
 assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA);
 trace_vhost_vdpa_init(dev, opaque);
 
 v = opaque;
 v->dev = dev;
 dev->opaque =  opaque ;
-vhost_vdpa_call(dev, VHOST_GET_FEATURES, );
-dev->backend_features = features;
 v->listener = vhost_vdpa_memory_listener;
 v->msg_type = VHOST_IOTLB_MSG_V2;
 
-- 
2.25.1




[PATCH 2/2] vhost-vdpa: remove the unused vhost_vdpa_get_acked_features()

2021-06-01 Thread Jason Wang
No user for this helper, let's remove it.

Signed-off-by: Jason Wang 
---
 include/net/vhost-vdpa.h | 1 -
 net/vhost-vdpa.c | 9 -
 2 files changed, 10 deletions(-)

diff --git a/include/net/vhost-vdpa.h b/include/net/vhost-vdpa.h
index 45e34b7cfc..b81f9a6f2a 100644
--- a/include/net/vhost-vdpa.h
+++ b/include/net/vhost-vdpa.h
@@ -15,7 +15,6 @@
 #define TYPE_VHOST_VDPA "vhost-vdpa"
 
 struct vhost_net *vhost_vdpa_get_vhost_net(NetClientState *nc);
-uint64_t vhost_vdpa_get_acked_features(NetClientState *nc);
 
 extern const int vdpa_feature_bits[];
 
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index fe659ec9e2..8dc86332a6 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -66,15 +66,6 @@ VHostNetState *vhost_vdpa_get_vhost_net(NetClientState *nc)
 return s->vhost_net;
 }
 
-uint64_t vhost_vdpa_get_acked_features(NetClientState *nc)
-{
-VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
-assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
-s->acked_features = vhost_net_get_acked_features(s->vhost_net);
-
-return s->acked_features;
-}
-
 static int vhost_vdpa_net_check_device_id(struct vhost_net *net)
 {
 uint32_t device_id;
-- 
2.25.1




Re: [RFC PATCH v2 3/3] plugins: cache: Added FIFO and LRU eviction policies.

2021-06-01 Thread Mahmoud Mandour
On Sun, May 30, 2021 at 8:37 AM Mahmoud Mandour 
wrote:

> Now one of the three eviction policies can be chosen as an argument. On
> not specifying an argument, LRU is used by default.
>
> Signed-off-by: Mahmoud Mandour 
> ---
>  contrib/plugins/cache.c | 159 
>  1 file changed, 146 insertions(+), 13 deletions(-)
>
> diff --git a/contrib/plugins/cache.c b/contrib/plugins/cache.c
> index fa0bf1dd40..1e323494bf 100644
> --- a/contrib/plugins/cache.c
> +++ b/contrib/plugins/cache.c
> @@ -18,6 +18,8 @@
>
>  QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
>
> +static bool fifo, lru, rnd;
> +
>  static GRand *rng;
>  static GHashTable *dmiss_ht;
>  static GHashTable *imiss_ht;
> @@ -55,6 +57,8 @@ struct CacheBlock {
>
>  struct CacheSet {
>  struct CacheBlock *blocks;
> +uint16_t *priorities;
> +GQueue *evict_queue;
>  };
>
>  struct Cache {
> @@ -93,6 +97,84 @@ static inline uint64_t extract_set(struct Cache *cache,
> uint64_t addr)
>  return (addr & cache->set_mask) >> (pow_of_two(cache->blksize));
>  }
>
> +static void lru_priorities_init(struct Cache *cache)
> +{
> +int i, j;
> +
> +for (i = 0; i < cache->num_sets; i++) {
> +cache->sets[i].priorities = g_new(uint16_t, cache->assoc);
> +for (j = 0; j < cache->assoc; j++) {
> +cache->sets[i].priorities[j] = cache->assoc - j - 1;
> +}
> +}
> +}
> +
> +static void lru_update_on_miss(struct Cache *cache,
> +  int set_idx,
> +  int blk_idx)
> +{
> +int i;
> +
> +for (i = 0; i < cache->assoc; i++) {
> +cache->sets[set_idx].priorities[i]++;
> +}
> +
> +cache->sets[set_idx].priorities[blk_idx] = 0;
> +}
> +
> +static void lru_update_on_hit(struct Cache *cache,
> + int set_idx,
> + int blk_idx)
> +{
> +uint16_t blk_priority;
> +int i;
> +
> +blk_priority = cache->sets[set_idx].priorities[blk_idx];
> +for (i = 0; i < cache->assoc; i++) {
> +if (cache->sets[set_idx].priorities[i] < blk_priority) {
> +cache->sets[set_idx].priorities[i]++;
> +}
> +}
> +cache->sets[set_idx].priorities[blk_idx] = 0;
> +}
> +
> +static int lru_get_lru_block(struct Cache *cache, int set_idx)
> +{
> +int i;
> +
> +for (i = 0; i < cache->assoc; i++) {
> +if (cache->sets[set_idx].priorities[i] == cache->assoc - 1) {
> +return i;
> +}
> +}
> +
> +g_assert_not_reached();
> +}
> +
> +static void fifo_init(struct Cache *cache)
> +{
> +int i;
> +
> +for (i = 0; i < cache->num_sets; i++) {
> +cache->sets[i].evict_queue = g_queue_new();
> +}
> +}
> +
> +static int fifo_get_first_in_block(struct Cache *cache, int set)
> +{
> +GQueue *q = cache->sets[set].evict_queue;
> +return GPOINTER_TO_INT(g_queue_pop_tail(q));
> +}
> +
> +static void fifo_update_on_miss(struct Cache *cache,
> +int set,
> +int blk_idx)
> +{
> +GQueue *q = cache->sets[set].evict_queue;
> +g_queue_push_head(q, GINT_TO_POINTER(blk_idx));
> +}
> +
> +
>  static struct Cache *cache_init(int blksize, int assoc, int cachesize)
>  {
>  struct Cache *cache;
> @@ -113,6 +195,12 @@ static struct Cache *cache_init(int blksize, int
> assoc, int cachesize)
>  cache->set_mask = ((cache->num_sets - 1) <<
> (pow_of_two(cache->blksize)));
>  cache->tag_mask = ~(cache->set_mask | cache->blk_mask);
>
> +if (lru) {
> +lru_priorities_init(cache);
> +} else if (fifo) {
> +fifo_init(cache);
> +}
> +
>  return cache;
>  }
>
> @@ -131,12 +219,20 @@ static int get_invalid_block(struct Cache *cache,
> uint64_t set)
>  return -1;
>  }
>
> -static int get_replaced_block(struct Cache *cache)
> +static int get_replaced_block(struct Cache *cache, int set)
>  {
> -return g_rand_int_range(rng, 0, cache->assoc);
> +if (rnd) {
> +return g_rand_int_range(rng, 0, cache->assoc);
> +} else if (lru) {
> +return lru_get_lru_block(cache, set);
> +} else if (fifo) {
> +return fifo_get_first_in_block(cache, set);
> +}
> +
> +g_assert_not_reached();
>  }
>
> -static bool in_cache(struct Cache *cache, uint64_t addr)
> +static int in_cache(struct Cache *cache, uint64_t addr)
>  {
>  int i;
>  uint64_t tag, set;
> @@ -147,29 +243,39 @@ static bool in_cache(struct Cache *cache, uint64_t
> addr)
>  for (i = 0; i < cache->assoc; i++) {
>  if (cache->sets[set].blocks[i].tag == tag &&
>  cache->sets[set].blocks[i].valid) {
> -return true;
> +return i;
>  }
>  }
>
> -return false;
> +return -1;
>  }
>
>  static enum AccessResult access_cache(struct Cache *cache, uint64_t addr)
>  {
>  uint64_t tag, set;
> -int 

Re: [RFC PATCH v2 2/3] plugins: cache: Enabled parameterization and added trace printing

2021-06-01 Thread Mahmoud Mandour
CC'ing Emilio

On Sun, May 30, 2021 at 8:37 AM Mahmoud Mandour 
wrote:

> Made both icache and dcache configurable through plugin arguments
> and added memory trace printing in a separate file.
>
> Signed-off-by: Mahmoud Mandour 
> ---
>  contrib/plugins/cache.c | 68 +++--
>  1 file changed, 66 insertions(+), 2 deletions(-)
>
> diff --git a/contrib/plugins/cache.c b/contrib/plugins/cache.c
> index 8c9d1dd538..fa0bf1dd40 100644
> --- a/contrib/plugins/cache.c
> +++ b/contrib/plugins/cache.c
> @@ -22,7 +22,7 @@ static GRand *rng;
>  static GHashTable *dmiss_ht;
>  static GHashTable *imiss_ht;
>
> -static GMutex dmtx, imtx;
> +static GMutex dmtx, imtx, fmtx;
>
>  static int limit;
>  static bool sys;
> @@ -33,6 +33,8 @@ static uint64_t dmisses;
>  static uint64_t imem_accesses;
>  static uint64_t imisses;
>
> +FILE *tracefile;
> +
>  static enum qemu_plugin_mem_rw rw = QEMU_PLUGIN_MEM_RW;
>
>  enum AccessResult {
> @@ -205,6 +207,16 @@ static void vcpu_mem_access(unsigned int cpu_index,
> qemu_plugin_meminfo_t info,
>  insn_addr = ((struct InsnData *) userdata)->addr;
>  effective_addr = hwaddr ? qemu_plugin_hwaddr_phys_addr(hwaddr) :
> vaddr;
>
> +if (tracefile) {
> +g_mutex_lock();
> +g_autoptr(GString) rep = g_string_new("");
> +bool is_store = qemu_plugin_mem_is_store(info);
> +g_string_append_printf(rep, "%c: 0x%" PRIx64,
> +is_store ? 'S' : 'L', effective_addr);
> +fprintf(tracefile, "%s\n", rep->str);
> +g_mutex_unlock();
> +}
> +
>  if (access_cache(dcache, effective_addr) == MISS) {
>  struct InsnData *insn = get_or_create(dmiss_ht, userdata,
> insn_addr);
>  insn->misses++;
> @@ -221,11 +233,20 @@ static void vcpu_insn_exec(unsigned int vcpu_index,
> void *userdata)
>  g_mutex_lock();
>  addr = ((struct InsnData *) userdata)->addr;
>
> +if (tracefile) {
> +g_mutex_lock();
> +g_autoptr(GString) rep = g_string_new("");
> +g_string_append_printf(rep, "I: 0x%" PRIx64, addr);
> +fprintf(tracefile, "%s\n", rep->str);
> +g_mutex_unlock();
> +}
> +
>  if (access_cache(icache, addr) == MISS) {
>  struct InsnData *insn = get_or_create(imiss_ht, userdata, addr);
>  insn->misses++;
>  imisses++;
>  }
> +
>  imem_accesses++;
>  g_mutex_unlock();
>  }
> @@ -352,6 +373,15 @@ static void plugin_exit()
>
>  g_mutex_unlock();
>  g_mutex_unlock();
> +
> +if (tracefile) {
> +fclose(tracefile);
> +}
> +}
> +
> +static bool bad_cache_params(int blksize, int assoc, int cachesize)
> +{
> +return (cachesize % blksize) != 0 || (cachesize % (blksize * assoc)
> != 0);
>  }
>
>  QEMU_PLUGIN_EXPORT
> @@ -377,14 +407,48 @@ int qemu_plugin_install(qemu_plugin_id_t id, const
> qemu_info_t *info,
>
>  for (i = 0; i < argc; i++) {
>  char *opt = argv[i];
> -if (g_str_has_prefix(opt, "limit=")) {
> +if (g_str_has_prefix(opt, "I=")) {
> +gchar **toks = g_strsplit(opt + 2, " ", -1);
> +if (g_strv_length(toks) != 3) {
> +fprintf(stderr, "option parsing failed: %s\n", opt);
> +return -1;
> +}
> +icachesize = g_ascii_strtoull(toks[0], NULL, 10);
> +iassoc = g_ascii_strtoull(toks[1], NULL, 10);
> +iblksize = g_ascii_strtoull(toks[2], NULL, 10);
> +} else if (g_str_has_prefix(opt, "D=")) {
> +gchar **toks = g_strsplit(opt + 2, " ", -1);
> +if (g_strv_length(toks) != 3) {
> +fprintf(stderr, "option parsing failed: %s\n", opt);
> +return -1;
> +}
> +dcachesize = g_ascii_strtoull(toks[0], NULL, 10);
> +dassoc = g_ascii_strtoull(toks[1], NULL, 10);
> +dblksize = g_ascii_strtoull(toks[2], NULL, 10);
> +} else if (g_str_has_prefix(opt, "limit=")) {
>  limit = g_ascii_strtoull(opt + 6, NULL, 10);
> +} else if (g_str_has_prefix(opt, "tracefile=")) {
> +char *file_name = opt + 10;
> +tracefile = fopen(file_name, "w");
> +if (!tracefile) {
> +fprintf(stderr, "could not open: %s for writing\n",
> file_name);
> +}
>  } else {
>  fprintf(stderr, "option parsing failed: %s\n", opt);
>  return -1;
>  }
>  }
>
> +if (bad_cache_params(iblksize, iassoc, icachesize)) {
> +fprintf(stderr, "icache cannot be constructed from given
> parameters\n");
> +return -1;
> +}
> +
> +if (bad_cache_params(dblksize, dassoc, dcachesize)) {
> +fprintf(stderr, "dcache cannot be constructed from given
> parameters\n");
> +return -1;
> +}
> +
>  dcache = cache_init(dblksize, dassoc, dcachesize);
>  icache = cache_init(iblksize, iassoc, icachesize);
>
> --
> 2.25.1
>
>


Re: [RFC PATCH v2 1/3] plugins: Added a new cache modelling plugin

2021-06-01 Thread Mahmoud Mandour
On Sun, May 30, 2021 at 8:37 AM Mahmoud Mandour 
wrote:

> Added a cache modelling plugin that uses a static configuration used in
> many of the commercial microprocessors and uses random eviction policy.
>
> Signed-off-by: Mahmoud Mandour 
> ---
>  contrib/plugins/Makefile |   1 +
>  contrib/plugins/cache.c  | 398 +++
>  2 files changed, 399 insertions(+)
>  create mode 100644 contrib/plugins/cache.c
>
> diff --git a/contrib/plugins/Makefile b/contrib/plugins/Makefile
> index b9d7935e5e..2237b47f8b 100644
> --- a/contrib/plugins/Makefile
> +++ b/contrib/plugins/Makefile
> @@ -18,6 +18,7 @@ NAMES += hotpages
>  NAMES += howvec
>  NAMES += lockstep
>  NAMES += hwprofile
> +NAMES += cache
>
>  SONAMES := $(addsuffix .so,$(addprefix lib,$(NAMES)))
>
> diff --git a/contrib/plugins/cache.c b/contrib/plugins/cache.c
> new file mode 100644
> index 00..8c9d1dd538
> --- /dev/null
> +++ b/contrib/plugins/cache.c
> @@ -0,0 +1,398 @@
> +/*
> + * Copyright (C) 2021, Mahmoud Mandour 
> + *
> + * License: GNU GPL, version 2 or later.
> + *   See the COPYING file in the top-level directory.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +
> +QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
> +
> +static GRand *rng;
> +static GHashTable *dmiss_ht;
> +static GHashTable *imiss_ht;
> +
> +static GMutex dmtx, imtx;
> +
> +static int limit;
> +static bool sys;
> +
> +static uint64_t dmem_accesses;
> +static uint64_t dmisses;
> +
> +static uint64_t imem_accesses;
> +static uint64_t imisses;
> +
> +static enum qemu_plugin_mem_rw rw = QEMU_PLUGIN_MEM_RW;
> +
> +enum AccessResult {
> +HIT = 0,
> +MISS = 1
> +};
> +
> +struct InsnData {
> +char *disas_str;
> +uint64_t addr;
> +uint64_t misses;
> +};
> +
> +struct CacheBlock {
> +uint64_t tag;
> +bool valid;
> +};
> +
> +struct CacheSet {
> +struct CacheBlock *blocks;
> +};
> +
> +struct Cache {
> +struct CacheSet *sets;
> +int num_sets;
> +
> +int cachesize;
> +int blksize;
> +int assoc;
> +
> +uint64_t blk_mask;
> +uint64_t set_mask;
> +uint64_t tag_mask;
> +};
> +
> +struct Cache *dcache, *icache;
> +
> +static int pow_of_two(int num)
> +{
> +g_assert((num & (num - 1)) == 0);
> +int ret = 0;
> +while (num /= 2) {
> +ret++;
> +}
> +return ret;
> +}
> +
> +static inline uint64_t extract_tag(struct Cache *cache, uint64_t addr)
> +{
> +return (addr & cache->tag_mask) >>
> +(pow_of_two(cache->num_sets) + pow_of_two(cache->blksize));
> +}
> +
> +static inline uint64_t extract_set(struct Cache *cache, uint64_t addr)
> +{
> +return (addr & cache->set_mask) >> (pow_of_two(cache->blksize));
> +}
> +
> +static struct Cache *cache_init(int blksize, int assoc, int cachesize)
> +{
> +struct Cache *cache;
> +int i;
> +
> +cache = g_new(struct Cache, 1);
> +cache->blksize = blksize;
> +cache->assoc = assoc;
> +cache->cachesize = cachesize;
> +cache->num_sets = cachesize / (blksize * assoc);
> +cache->sets = g_new(struct CacheSet, cache->num_sets);
> +
> +for (i = 0; i < cache->num_sets; i++) {
> +cache->sets[i].blocks = g_new0(struct CacheBlock, assoc);
> +}
> +
> +cache->blk_mask = blksize - 1;
> +cache->set_mask = ((cache->num_sets - 1) <<
> (pow_of_two(cache->blksize)));
> +cache->tag_mask = ~(cache->set_mask | cache->blk_mask);
> +
> +return cache;
> +}
> +
> +static int get_invalid_block(struct Cache *cache, uint64_t set)
> +{
> +int i;
> +
> +for (i = 0; i < cache->assoc; i++) {
> +if (!cache->sets[set].blocks[i].valid) {
> +/* conflict miss */
> +return i;
> +}
> +}
> +
> +/* compulsary miss */
> +return -1;
> +}
> +
> +static int get_replaced_block(struct Cache *cache)
> +{
> +return g_rand_int_range(rng, 0, cache->assoc);
> +}
> +
> +static bool in_cache(struct Cache *cache, uint64_t addr)
> +{
> +int i;
> +uint64_t tag, set;
> +
> +tag = extract_tag(cache, addr);
> +set = extract_set(cache, addr);
> +
> +for (i = 0; i < cache->assoc; i++) {
> +if (cache->sets[set].blocks[i].tag == tag &&
> +cache->sets[set].blocks[i].valid) {
> +return true;
> +}
> +}
> +
> +return false;
> +}
> +
> +static enum AccessResult access_cache(struct Cache *cache, uint64_t addr)
> +{
> +uint64_t tag, set;
> +int replaced_blk;
> +
> +if (in_cache(cache, addr)) {
> +return HIT;
> +}
> +
> +tag = extract_tag(cache, addr);
> +set = extract_set(cache, addr);
> +
> +replaced_blk = get_invalid_block(cache, set);
> +
> +if (replaced_blk == -1) {
> +replaced_blk = get_replaced_block(cache);
> +}
> +
> +cache->sets[set].blocks[replaced_blk].tag = tag;
> +cache->sets[set].blocks[replaced_blk].valid = true;
> +
> 

[PATCH] migration/rdma: Fix cm event use after free

2021-06-01 Thread Li Zhijian
Signed-off-by: Li Zhijian 
---
 migration/rdma.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/migration/rdma.c b/migration/rdma.c
index 1cdb4561f32..d90b29a4b51 100644
--- a/migration/rdma.c
+++ b/migration/rdma.c
@@ -1539,16 +1539,20 @@ static int qemu_rdma_wait_comp_channel(RDMAContext 
*rdma)
 
 if (pfds[1].revents) {
 ret = rdma_get_cm_event(rdma->channel, _event);
-if (!ret) {
-rdma_ack_cm_event(cm_event);
+if (ret) {
+error_report("failed to get cm event while wait "
+ "completion channel");
+return -EPIPE;
 }
 
 error_report("receive cm event while wait comp channel,"
  "cm event is %d", cm_event->event);
 if (cm_event->event == RDMA_CM_EVENT_DISCONNECTED ||
 cm_event->event == RDMA_CM_EVENT_DEVICE_REMOVAL) {
+rdma_ack_cm_event(cm_event);
 return -EPIPE;
 }
+rdma_ack_cm_event(cm_event);
 }
 break;
 
@@ -3285,7 +3289,6 @@ static void rdma_cm_poll_handler(void *opaque)
 error_report("get_cm_event failed %d", errno);
 return;
 }
-rdma_ack_cm_event(cm_event);
 
 if (cm_event->event == RDMA_CM_EVENT_DISCONNECTED ||
 cm_event->event == RDMA_CM_EVENT_DEVICE_REMOVAL) {
@@ -3298,12 +3301,14 @@ static void rdma_cm_poll_handler(void *opaque)
 rdma->return_path->error_state = -EPIPE;
 }
 }
+rdma_ack_cm_event(cm_event);
 
 if (mis->migration_incoming_co) {
 qemu_coroutine_enter(mis->migration_incoming_co);
 }
 return;
 }
+rdma_ack_cm_event(cm_event);
 }
 
 static int qemu_rdma_accept(RDMAContext *rdma)
-- 
2.30.2






[PATCH] target/arm: Mark LDS{MIN,MAX} as signed operations

2021-06-01 Thread Richard Henderson
The operands to tcg_gen_atomic_fetch_s{min,max}_i64 must
be signed, so that the inputs are properly extended.
Zero extend the result afterward, as needed.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/364
Signed-off-by: Richard Henderson 
---
 target/arm/translate-a64.c | 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index ceac0ee2bd..d6906d9012 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -3355,8 +3355,9 @@ static void disas_ldst_atomic(DisasContext *s, uint32_t 
insn,
 int o3_opc = extract32(insn, 12, 4);
 bool r = extract32(insn, 22, 1);
 bool a = extract32(insn, 23, 1);
-TCGv_i64 tcg_rs, clean_addr;
+TCGv_i64 tcg_rs, tcg_rt, clean_addr;
 AtomicThreeOpFn *fn = NULL;
+MemOp mop = s->be_data | size | MO_ALIGN;
 
 if (is_vector || !dc_isar_feature(aa64_atomics, s)) {
 unallocated_encoding(s);
@@ -3377,9 +3378,11 @@ static void disas_ldst_atomic(DisasContext *s, uint32_t 
insn,
 break;
 case 004: /* LDSMAX */
 fn = tcg_gen_atomic_fetch_smax_i64;
+mop |= MO_SIGN;
 break;
 case 005: /* LDSMIN */
 fn = tcg_gen_atomic_fetch_smin_i64;
+mop |= MO_SIGN;
 break;
 case 006: /* LDUMAX */
 fn = tcg_gen_atomic_fetch_umax_i64;
@@ -3422,6 +3425,7 @@ static void disas_ldst_atomic(DisasContext *s, uint32_t 
insn,
 }
 
 tcg_rs = read_cpu_reg(s, rs, true);
+tcg_rt = cpu_reg(s, rt);
 
 if (o3_opc == 1) { /* LDCLR */
 tcg_gen_not_i64(tcg_rs, tcg_rs);
@@ -3430,8 +3434,11 @@ static void disas_ldst_atomic(DisasContext *s, uint32_t 
insn,
 /* The tcg atomic primitives are all full barriers.  Therefore we
  * can ignore the Acquire and Release bits of this instruction.
  */
-fn(cpu_reg(s, rt), clean_addr, tcg_rs, get_mem_index(s),
-   s->be_data | size | MO_ALIGN);
+fn(tcg_rt, clean_addr, tcg_rs, get_mem_index(s), mop);
+
+if ((mop & MO_SIGN) && size != MO_64) {
+tcg_gen_ext32u_i64(tcg_rt, tcg_rt);
+}
 }
 
 /*
-- 
2.25.1




Re: [PATCH v4] i386: Add ratelimit for bus locks acquired in guest

2021-06-01 Thread Chenyi Qiang




On 6/2/2021 4:10 AM, Eduardo Habkost wrote:

On Tue, Jun 01, 2021 at 02:18:37PM -0400, Eduardo Habkost wrote:

On Mon, May 31, 2021 at 01:14:54PM +0800, Chenyi Qiang wrote:



On 5/28/2021 5:19 AM, Eduardo Habkost wrote:

On Fri, May 21, 2021 at 12:38:20PM +0800, Chenyi Qiang wrote:
[...]

@@ -4222,6 +4247,15 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
   }
   }
+static void kvm_rate_limit_on_bus_lock(void)
+{
+uint64_t delay_ns = ratelimit_calculate_delay(_lock_ratelimit_ctrl, 1);
+
+if (delay_ns) {
+g_usleep(delay_ns / SCALE_US);
+}
+}
+
   MemTxAttrs kvm_arch_post_run(CPUState *cpu, struct kvm_run *run)
   {
   X86CPU *x86_cpu = X86_CPU(cpu);
@@ -4237,6 +4271,9 @@ MemTxAttrs kvm_arch_post_run(CPUState *cpu, struct 
kvm_run *run)
   } else {
   env->eflags &= ~IF_MASK;
   }
+if (run->flags & KVM_RUN_X86_BUS_LOCK) {


Does the KVM API guarantee that KVM_RUN_X86_BUS_LOCK will never
be set if KVM_BUS_LOCK_DETECTION_EXIT isn't enabled?  (Otherwise
we risk crashing in ratelimit_calculate_delay() above if rate
limiting is disabled).



Yes. KVM_RUN_X86_BUS_LOCK flag is set when bus lock VM exit happens. Bus
lock VM exit is disabled by default and can only be enabled through the
KVM_BUS_LOCK_DETECTION_EXIT capability.


I'm queueing on x86-next, thanks!


This breaks the build.  Is there a linux-headers update patch I've missed?



Thanks for the queue and sorry for forgetting to submit the 
linux-headers update patch.



../target/i386/kvm/kvm.c: In function 'kvm_arch_init':
../target/i386/kvm/kvm.c:2322:42: error: 'KVM_CAP_X86_BUS_LOCK_EXIT' undeclared 
(first use in this function); did you mean 'KVM_CAP_X86_DISABLE_EXITS'?
  ret = kvm_check_extension(s, KVM_CAP_X86_BUS_LOCK_EXIT);
   ^
   KVM_CAP_X86_DISABLE_EXITS





Re: [PATCH v1 2/6] KVM: introduce dirty_pages into CPUState

2021-06-01 Thread Peter Xu
On Wed, Jun 02, 2021 at 08:27:19AM +0800, Hyman Huang wrote:
> 在 2021/6/2 7:20, Peter Xu 写道:
> > On Tue, Jun 01, 2021 at 01:04:06AM +0800, huang...@chinatelecom.cn wrote:
> > > diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
> > > index 044f668a6e..973c193501 100644
> > > --- a/include/hw/core/cpu.h
> > > +++ b/include/hw/core/cpu.h
> > > @@ -375,6 +375,8 @@ struct CPUState {
> > >   struct kvm_run *kvm_run;
> > >   struct kvm_dirty_gfn *kvm_dirty_gfns;
> > >   uint32_t kvm_fetch_index;
> > > +uint64_t dirty_pages;
> > > +bool stat_dirty_pages;
> > 
> > Shall we make this bool a global one?  As I don't think we'll be able to 
> > only
> > enable it on a subset of cpus?
> Yes, it's a reasonable advice, i'll apply this on the next version

Or even drop the bool and do the accounting unconditionally?  No need to do +1
for each pfn, but do it once before returning from kvm_dirty_ring_reap_one().

-- 
Peter Xu




Re: [PATCH v1 0/6] support dirtyrate at the granualrity of vcpu

2021-06-01 Thread Hyman Huang




在 2021/6/2 5:54, Peter Xu 写道:

On Tue, Jun 01, 2021 at 01:02:45AM +0800, huang...@chinatelecom.cn wrote:

From: Hyman Huang(黄勇) 

Since the Dirty Ring on QEMU part has been merged recently, how to use
this feature is under consideration.

In the scene of migration, it is valuable to provide a more accurante
interface to track dirty memory than existing one, so that the upper
layer application can make a wise decision, or whatever. More importantly,
dirtyrate info at the granualrity of vcpu could provide a possibility to
make migration convergent by imposing restriction on vcpu. With Dirty
Ring, we can calculate dirtyrate efficiently and cheaply.

The old interface implemented by sampling pages, it consumes cpu
resource, and the larger guest memory size become, the more cpu resource
it consumes, namely, hard to scale. New interface has no such drawback.


Yong,

Thanks for working on this!

Some high-level comments:

- The layout of the patch looks a bit odd.  E.g., you introduced the new "vcpu"
   qmp parameter in patch 3, however it's not yet implemented, meanwhile I feel
   like you squashed mostly all the rest into patch 6.  It's okay to use a
   single big patch, but IMHO better to not declare that flag in QMP before it's
   working, so ideally that should be the last patch to do that.

   From that POV: patch 1/2/4 look ok to be separated; perhaps squash patch
   3/5/6 into one single patch to enable the new method as the last one?

Yeah previously the concern is make the patch clear and small, however 
with the comment of each commit, it seems ok. As you said, it's okay to 
use a single big patch, i'll adjust the patch set style base on your advice.

- You used "vcpu" across the patchset to show the per-vcpu new method.  Shall
   we rename it globally to "per_vcpu" or "vcpu_based"?  A raw "vcpu" looks more
   like a struct pointer not a boolean.

Indeed, actually the initial name of the option is "per_vcpu". : ). i'll 
fix this.

- Using memory_global_dirty_log_start|stop() may not be wise too IMHO, at least
   we need to make sure it's not during migration, otherwise we could call the
   stop() before migration ends then that'll be a problem..

Yeah, this may be a serious problem, thanks for your timely advice.


   Maybe we can start to make global_dirty_log a bitmask? Then we define:

 GLOBAL_DIRTY_MIGRATION
 GLOBAL_DIRTY_DIRTY_RATE

   All references to global_dirty_log should mostly be untouched because any bit
   set there should justify that global dirty logging is enabled (either for
   migration or for dirty rate measurement).

   Migration starting half-way of dirty rate measurement seems okay too even
   taking things like init-all-set into account, afaict.. as long as dirty rate
   code never touches the qemu dirty bitmap, but only do the accounting when
   collecting the pages...

   Feel free to think more about it on any other potential conflict with
   migration, but in general seems working to me.


I'll apply this on the next version.

- Would you consider picking up my HMP patch and let HMP work from the 1st day?

- Please Cc the author of dirty rate too (Chuan Zheng ),
   while I already started to do so in this email.


I'd be glad to do this above two.

Thanks,



Thanks Peter!

--
Best regard

Hyman Huang(黄勇)



Re: [PATCH v3 0/2] target/s390x: Fix SIGILL psw.addr reporting

2021-06-01 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20210602002210.3144559-1-...@linux.ibm.com/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20210602002210.3144559-1-...@linux.ibm.com
Subject: [PATCH v3 0/2] target/s390x: Fix SIGILL psw.addr reporting

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 - [tag update]  
patchew/1622589584-22571-1-git-send-email-tsimp...@quicinc.com -> 
patchew/1622589584-22571-1-git-send-email-tsimp...@quicinc.com
 * [new tag] patchew/20210602002210.3144559-1-...@linux.ibm.com -> 
patchew/20210602002210.3144559-1-...@linux.ibm.com
Switched to a new branch 'test'
495bc5c tests/tcg/s390x: Test SIGILL and SIGSEGV handling
2e28eb9 target/s390x: Fix SIGILL psw.addr reporting

=== OUTPUT BEGIN ===
1/2 Checking commit 2e28eb9526d2 (target/s390x: Fix SIGILL psw.addr reporting)
2/2 Checking commit 495bc5cfd59a (tests/tcg/s390x: Test SIGILL and SIGSEGV 
handling)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#26: 
new file mode 100644

ERROR: externs should be avoided in .c files
#44: FILE: tests/tcg/s390x/signal.c:14:
+void illegal_op(void);

ERROR: externs should be avoided in .c files
#45: FILE: tests/tcg/s390x/signal.c:15:
+void after_illegal_op(void);

ERROR: externs should be avoided in .c files
#51: FILE: tests/tcg/s390x/signal.c:21:
+void stg(void *dst, unsigned long src);

ERROR: externs should be avoided in .c files
#56: FILE: tests/tcg/s390x/signal.c:26:
+void mvc_8(void *dst, void *src);

total: 4 errors, 1 warnings, 167 lines checked

Patch 2/2 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20210602002210.3144559-1-...@linux.ibm.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-de...@redhat.com

Re: [PATCH v1 2/6] KVM: introduce dirty_pages into CPUState

2021-06-01 Thread Hyman Huang




在 2021/6/2 7:20, Peter Xu 写道:

On Tue, Jun 01, 2021 at 01:04:06AM +0800, huang...@chinatelecom.cn wrote:

diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 044f668a6e..973c193501 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -375,6 +375,8 @@ struct CPUState {
  struct kvm_run *kvm_run;
  struct kvm_dirty_gfn *kvm_dirty_gfns;
  uint32_t kvm_fetch_index;
+uint64_t dirty_pages;
+bool stat_dirty_pages;


Shall we make this bool a global one?  As I don't think we'll be able to only
enable it on a subset of cpus?

Yes, it's a reasonable advice, i'll apply this on the next version




--
Best regard

Hyman Huang(黄勇)



[PATCH v3 2/2] tests/tcg/s390x: Test SIGILL and SIGSEGV handling

2021-06-01 Thread Ilya Leoshkevich
Verify that s390x-specific uc_mcontext.psw.addr is reported correctly.

Signed-off-by: Ilya Leoshkevich 
---
 tests/tcg/s390x/Makefile.target |   1 +
 tests/tcg/s390x/signal.c| 163 
 2 files changed, 164 insertions(+)
 create mode 100644 tests/tcg/s390x/signal.c

diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target
index 241ef28f61..cdb7d85316 100644
--- a/tests/tcg/s390x/Makefile.target
+++ b/tests/tcg/s390x/Makefile.target
@@ -8,3 +8,4 @@ TESTS+=exrl-trtr
 TESTS+=pack
 TESTS+=mvo
 TESTS+=mvc
+TESTS+=signal
diff --git a/tests/tcg/s390x/signal.c b/tests/tcg/s390x/signal.c
new file mode 100644
index 00..c25d7dd019
--- /dev/null
+++ b/tests/tcg/s390x/signal.c
@@ -0,0 +1,163 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * Various instructions that generate SIGILL and SIGSEGV. They could have been
+ * defined in a separate .s file, but this would complicate the build, so the
+ * inline asm is used instead.
+ */
+
+void illegal_op(void);
+void after_illegal_op(void);
+asm(".globl\tillegal_op\n"
+"illegal_op:\t.byte\t0x00,0x00\n"
+"\t.globl\tafter_illegal_op\n"
+"after_illegal_op:\tbr\t%r14");
+
+void stg(void *dst, unsigned long src);
+asm(".globl\tstg\n"
+"stg:\tstg\t%r3,0(%r2)\n"
+"\tbr\t%r14");
+
+void mvc_8(void *dst, void *src);
+asm(".globl\tmvc_8\n"
+"mvc_8:\tmvc\t0(8,%r2),0(%r3)\n"
+"\tbr\t%r14");
+
+static void safe_puts(const char *s)
+{
+write(0, s, strlen(s));
+write(0, "\n", 1);
+}
+
+enum exception {
+exception_operation,
+exception_translation,
+exception_protection,
+};
+
+static struct {
+int sig;
+void *addr;
+unsigned long psw_addr;
+enum exception exception;
+} expected;
+
+static void handle_signal(int sig, siginfo_t *info, void *ucontext)
+{
+void *page;
+int err;
+
+if (sig != expected.sig) {
+safe_puts("[  FAILED  ] wrong signal");
+_exit(1);
+}
+
+if (info->si_addr != expected.addr) {
+safe_puts("[  FAILED  ] wrong si_addr");
+_exit(1);
+}
+
+if (((ucontext_t *)ucontext)->uc_mcontext.psw.addr != expected.psw_addr) {
+safe_puts("[  FAILED  ] wrong psw.addr");
+_exit(1);
+}
+
+switch (expected.exception) {
+case exception_translation:
+page = mmap(expected.addr, 4096, PROT_READ | PROT_WRITE,
+MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+if (page != expected.addr) {
+safe_puts("[  FAILED  ] mmap() failed");
+_exit(1);
+}
+break;
+case exception_protection:
+err = mprotect(expected.addr, 4096, PROT_READ | PROT_WRITE);
+if (err != 0) {
+safe_puts("[  FAILED  ] mprotect() failed");
+_exit(1);
+}
+break;
+}
+}
+
+static void check_sigsegv(void *func, enum exception exception,
+  unsigned long val)
+{
+int prot;
+unsigned long *page;
+unsigned long *addr;
+int err;
+
+prot = exception == exception_translation ? PROT_NONE : PROT_READ;
+page = mmap(NULL, 4096, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+assert(page != MAP_FAILED);
+if (exception == exception_translation) {
+/* Hopefully nothing will be mapped at this address. */
+err = munmap(page, 4096);
+assert(err == 0);
+}
+addr = page + (val & 0x1ff);
+
+expected.sig = SIGSEGV;
+expected.addr = page;
+expected.psw_addr = (unsigned long)func;
+expected.exception = exception;
+if (func == stg) {
+stg(addr, val);
+} else {
+assert(func == mvc_8);
+mvc_8(addr, );
+}
+assert(*addr == val);
+
+err = munmap(page, 4096);
+assert(err == 0);
+}
+
+int main(void)
+{
+struct sigaction act;
+int err;
+
+memset(, 0, sizeof(act));
+act.sa_sigaction = handle_signal;
+act.sa_flags = SA_SIGINFO;
+err = sigaction(SIGILL, , NULL);
+assert(err == 0);
+err = sigaction(SIGSEGV, , NULL);
+assert(err == 0);
+
+safe_puts("[ RUN  ] Operation exception");
+expected.sig = SIGILL;
+expected.addr = illegal_op;
+expected.psw_addr = (unsigned long)after_illegal_op;
+expected.exception = exception_operation;
+illegal_op();
+safe_puts("[   OK ]");
+
+safe_puts("[ RUN  ] Translation exception from stg");
+check_sigsegv(stg, exception_translation, 42);
+safe_puts("[   OK ]");
+
+safe_puts("[ RUN  ] Translation exception from mvc");
+check_sigsegv(mvc_8, exception_translation, 4242);
+safe_puts("[   OK ]");
+
+safe_puts("[ RUN  ] Protection exception from stg");
+check_sigsegv(stg, exception_protection, 424242);
+safe_puts("[   OK ]");
+
+safe_puts("[ RUN  ] Protection exception from mvc");
+check_sigsegv(mvc_8, exception_protection, 42424242);
+safe_puts("[   OK ]");
+
+

[PATCH v3 0/2] target/s390x: Fix SIGILL psw.addr reporting

2021-06-01 Thread Ilya Leoshkevich
qemu-s390x puts a wrong value into SIGILL's siginfo_t's psw.addr: it
should be a pointer to the instruction following the illegal
instruction, but at the moment it is a pointer to the illegal
instruction itself. This breaks OpenJDK, which relies on this value.

Patch 1 fixes the issue, patch 2 adds a test.

v1: https://lists.nongnu.org/archive/html/qemu-devel/2021-05/msg06592.html
v1 -> v2: Use a better buglink (Cornelia), simplify the inline asm
  magic in the test and add an explanation (David).

v2: https://lists.nongnu.org/archive/html/qemu-devel/2021-05/msg06649.html
v2 -> v3: Fix SIGSEGV handling (found when trying to run valgrind under
  qemu-user).

Ilya Leoshkevich (2):
  target/s390x: Fix SIGILL psw.addr reporting
  tests/tcg/s390x: Test SIGILL and SIGSEGV handling

 linux-user/s390x/cpu_loop.c |  23 -
 target/s390x/excp_helper.c  |  71 +++---
 target/s390x/internal.h |   1 +
 target/s390x/mem_helper.c   |   2 +-
 tests/tcg/s390x/Makefile.target |   1 +
 tests/tcg/s390x/signal.c| 163 
 6 files changed, 224 insertions(+), 37 deletions(-)
 create mode 100644 tests/tcg/s390x/signal.c

-- 
2.31.1




[PATCH v3 1/2] target/s390x: Fix SIGILL psw.addr reporting

2021-06-01 Thread Ilya Leoshkevich
When a s390x CPU attempts to execute an illegal instruction, an
operation exception is recognized. This is a suppressing exception,
which means that the PSW is advanced by the length of the illegal
instruction.

On the real hardware or in qemu-system-s390x the kernel then raises
SIGILL with si_addr pointing to the suppressed instruction and
psw.addr containing the updated PSW.

Unfortunately qemu-s390x sets both to the address of the suppressed
instruction at the moment. Fix by sharing the PSW advancement logic
with qemu-system-s390x and setting si_addr to the address of the
instruction that raised the exception.

Sharing the PSW advancement logic means, however, that now the helpers
and the CPU loop must follow the hardware and the kernel a little bit
more strictly. In particular:

* Unmapped memory accesses should result in a translation rather than
  in an addressing exception.
* Protection exception must rewind psw.addr.
* Translation exception must cause a SIGSEGV.

While at it, also fix the handling of addressing and privileged
operation exceptions.

Buglink: https://gitlab.com/qemu-project/qemu/-/issues/319
Signed-off-by: Ilya Leoshkevich 
---
 linux-user/s390x/cpu_loop.c | 23 ++--
 target/s390x/excp_helper.c  | 71 -
 target/s390x/internal.h |  1 +
 target/s390x/mem_helper.c   |  2 +-
 4 files changed, 60 insertions(+), 37 deletions(-)

diff --git a/linux-user/s390x/cpu_loop.c b/linux-user/s390x/cpu_loop.c
index f2d1215fb1..72ba9170ed 100644
--- a/linux-user/s390x/cpu_loop.c
+++ b/linux-user/s390x/cpu_loop.c
@@ -21,6 +21,7 @@
 #include "qemu-common.h"
 #include "qemu.h"
 #include "cpu_loop-common.h"
+#include "internal.h"
 
 /* s390x masks the fault address it reports in si_addr for SIGSEGV and SIGBUS 
*/
 #define S390X_FAIL_ADDR_MASK -4096LL
@@ -29,6 +30,7 @@ void cpu_loop(CPUS390XState *env)
 {
 CPUState *cs = env_cpu(env);
 int trapnr, n, sig;
+target_ulong excp_psw_addr;
 target_siginfo_t info;
 target_ulong addr;
 abi_long ret;
@@ -38,6 +40,7 @@ void cpu_loop(CPUS390XState *env)
 trapnr = cpu_exec(cs);
 cpu_exec_end(cs);
 process_queued_cpu_work(cs);
+excp_psw_addr = env->psw.addr;
 
 switch (trapnr) {
 case EXCP_INTERRUPT:
@@ -66,15 +69,29 @@ void cpu_loop(CPUS390XState *env)
 n = TARGET_TRAP_BRKPT;
 goto do_signal_pc;
 case EXCP_PGM:
+s390_cpu_program_interrupt_advance_psw(env);
 n = env->int_pgm_code;
 switch (n) {
 case PGM_OPERATION:
-case PGM_PRIVILEGED:
 sig = TARGET_SIGILL;
 n = TARGET_ILL_ILLOPC;
 goto do_signal_pc;
-case PGM_PROTECTION:
+case PGM_PRIVILEGED:
+sig = TARGET_SIGILL;
+n = TARGET_ILL_PRVOPC;
+goto do_signal_pc;
 case PGM_ADDRESSING:
+sig = TARGET_SIGILL;
+n = TARGET_ILL_ILLADR;
+goto do_signal_pc;
+case PGM_PROTECTION:
+/*
+ * Protection exception handler is special: it is the only one
+ * that rewinds psw.addr.
+ */
+env->psw.addr = excp_psw_addr;
+/* FALL THROUGH */
+case PGM_PAGE_TRANS:
 sig = TARGET_SIGSEGV;
 /* XXX: check env->error_code */
 n = TARGET_SEGV_MAPERR;
@@ -131,7 +148,7 @@ void cpu_loop(CPUS390XState *env)
 break;
 
 do_signal_pc:
-addr = env->psw.addr;
+addr = excp_psw_addr;
 do_signal:
 info.si_signo = sig;
 info.si_errno = 0;
diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c
index 20625c2c8f..4133e93978 100644
--- a/target/s390x/excp_helper.c
+++ b/target/s390x/excp_helper.c
@@ -82,6 +82,42 @@ void HELPER(data_exception)(CPUS390XState *env, uint32_t dxc)
 tcg_s390_data_exception(env, dxc, GETPC());
 }
 
+void s390_cpu_program_interrupt_advance_psw(CPUS390XState *env)
+{
+switch (env->int_pgm_code) {
+case PGM_PER:
+if (env->per_perc_atmid & PER_CODE_EVENT_NULLIFICATION) {
+break;
+}
+/* FALL THROUGH */
+case PGM_OPERATION:
+case PGM_PRIVILEGED:
+case PGM_EXECUTE:
+case PGM_PROTECTION:
+case PGM_ADDRESSING:
+case PGM_SPECIFICATION:
+case PGM_DATA:
+case PGM_FIXPT_OVERFLOW:
+case PGM_FIXPT_DIVIDE:
+case PGM_DEC_OVERFLOW:
+case PGM_DEC_DIVIDE:
+case PGM_HFP_EXP_OVERFLOW:
+case PGM_HFP_EXP_UNDERFLOW:
+case PGM_HFP_SIGNIFICANCE:
+case PGM_HFP_DIVIDE:
+case PGM_TRANS_SPEC:
+case PGM_SPECIAL_OP:
+case PGM_OPERAND:
+case PGM_HFP_SQRT:
+case PGM_PC_TRANS_SPEC:
+case PGM_ALET_SPEC:
+case PGM_MONITOR:
+/* advance the PSW if our exception is not nullifying */
+

Re: [PATCH v2 4/4] Hexagon (target/hexagon) remove unused TCG variables

2021-06-01 Thread Richard Henderson

On 6/1/21 4:19 PM, Taylor Simpson wrote:

Signed-off-by: Taylor Simpson
---
  target/hexagon/genptr.c|  6 --
  target/hexagon/translate.c | 11 ++-
  2 files changed, 2 insertions(+), 15 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: [PULL 00/44] Python patches

2021-06-01 Thread John Snow

On 6/1/21 6:36 AM, Peter Maydell wrote:

On Sun, 30 May 2021 at 20:22, John Snow  wrote:


On 5/30/21 3:09 PM, Peter Maydell wrote:

Fails to build on my machine that runs the BSD VMs, apparently
before it gets to the point of launching the VM:



When I have seen this error message in the past, it has been because of
using a new Python version and it gets confused reading stale cached
information generated from an older interpreter.


This seems like a bug in Python...



Yes. I don't know why it's like that either...


Can you do me a favor and delete any __pycache__ folders and/or any
*.pyc files that might be hiding in your tree and/or build folders and
try running it again?


I tried that, and it does seem to make more progress. It now
fails with:



One of the acceptance test patches causes this, I've squashed in a fixup 
and have re-sent the PR.


Thanks,
--js




Re: [PATCH v2 3/4] Hexagon (target/hexagon) cleanup gen_store_conditional[48] functions

2021-06-01 Thread Richard Henderson

On 6/1/21 4:19 PM, Taylor Simpson wrote:

Previously the store-conditional code was writing to hex_pred[prednum].
Then, the fGEN_TCG override was reading from there to the destination
variable so that the packet commit logic would handle it properly.

The correct implementation is to write to the destination variable
and don't have the extra read in the override.

Remove the unused arguments from gen_store_conditional[48]

Signed-off-by: Taylor Simpson
---
  target/hexagon/gen_tcg.h |  4 ++--
  target/hexagon/macros.h  |  2 +-
  target/hexagon/genptr.c  | 10 --
  3 files changed, 7 insertions(+), 9 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: GSoC Intro - TUI interface for QMP

2021-06-01 Thread John Snow

On 5/26/21 11:35 AM, Niteesh G. S. wrote:

Hello Stefan,

On Mon, May 24, 2021 at 7:02 PM Stefan Hajnoczi > wrote:


On Sat, May 22, 2021 at 12:32:00AM +0530, Niteesh G. S. wrote:
 > By end of this summer, I would like to get a basic TUI with some
desirable
 > features working. Some of the features I would like to get
working are
 > 1) Syntax checking
 > 2) Syntax highlighting
 > 3) Code completion
 > 4) Logging
 >
 > I would like to hear some of the features you would like to have
and also
 > your
 > advice's on implementation.

Welcome Niteesh!

It would be great to have an QMP API documentation viewer built into the
TUI. When you enter a command like 'migrate' it would automatically
display the associated QMP command documentation from qapi/*.json.

That's a great idea.
Do you want the documentation as a popup or in a separate tab?
By separate tab what I mean is a full window dedicated to documentation
with some kind of search functionality.

Thanks,
Niteesh.




If we're talking about an urwid interface ...

There are a few ways to do this.

1. Explicitly, if you type something like "/help [command-name]" in the 
command bar, you could create a panel that temporarily replaces the 
history panel that shows the arguments and usage of the requested 
command name.


You could use page-up/page-down to scroll the help up and down accordingly.

To exit the help window, you could issue some keypress (like Ctrl+X? If 
you prototype this, just make it configurable -- I am sure people will 
have opinions.)


While the help window is up, the command entry bar could stay active -- 
i.e., you can type your command while the help is visible on-screen.


(As an aside: If we expect that we will have more than just one or two 
slash commands, it may be nice to have urwid create a popup suggestion 
box when you type a '/', hinting to the user what local shell commands 
are available.)



2. You could just display the help output as a flow item directly in the 
history pane, but if QEMU is receiving lots of events, you run the risk 
of having the help message flood off the screen.


Still, it might be a very simple way to implement it -- and the user can 
always just scroll up.



3. If we get around to implementing any kind of fancy syntax for the 
command entry bar, it may be possible to have the shell read the 
partially-entered command and guess which command we want to see help 
for -- maybe by pressing Ctrl+H?



A challenge will be where to pull the help text from. The QEMU server is 
not capable (today) of sending help information over the QMP socket itself.


We will need to implement a QMP command inside of QEMU directly that is 
capable of delivering this information to the client so that it can 
render it.


Since not all versions of QEMU will have this feature, the qmp-shell 
will need to be able to gracefully deal with the lack of help text, 
displaying an error indicating that this version of QEMU does not have 
help information compiled into it.


--js




Re: [PATCH v2 2/4] Hexagon (target/hexagon) fix l2fetch instructions

2021-06-01 Thread Richard Henderson

On 6/1/21 4:19 PM, Taylor Simpson wrote:

Y4_l2fetch == l2fetch(Rs32, Rt32)
Y5_l2fetch == l2fetch(Rs32, Rtt32)

The semantics for these instructions are present, but the encodings
are missing.

Note that these are treated as nops in qemu, so we add overrides.

Test case added to tests/tcg/hexagon/misc.c

Signed-off-by: Taylor Simpson
---
  target/hexagon/gen_tcg.h  | 11 +++
  tests/tcg/hexagon/misc.c  |  9 +
  target/hexagon/imported/encode_pp.def |  3 +++
  3 files changed, 23 insertions(+)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH v2 1/4] Hexagon (target/hexagon) fix bug in fLSBNEW*

2021-06-01 Thread Richard Henderson

On 6/1/21 4:19 PM, Taylor Simpson wrote:

Change fLSBNEW/fLSBNEW0/fLSBNEW1 from copy to "x & 1"
Remove gen_logical_not function
Clean up fLSBNEWNOT to use andi-1 followed by xori-1

Test cases added to tests/tcg/hexagon/misc.c

Signed-off-by: Taylor Simpson
---
  target/hexagon/macros.h| 27 ++-
  target/hexagon/op_helper.c |  5 -
  tests/tcg/hexagon/misc.c   | 39 ++-
  3 files changed, 48 insertions(+), 23 deletions(-)


Reviewed-by: Richard Henderson 

r~



[PULL v2 04/44] Python: add utility function for retrieving port redirection

2021-06-01 Thread John Snow
From: Cleber Rosa 

Slightly different versions for the same utility code are currently
present on different locations.  This unifies them all, giving
preference to the version from virtiofs_submounts.py, because of the
last tweaks added to it.

While at it, this adds a "qemu.utils" module to host the utility
function and a test.

Signed-off-by: Cleber Rosa 
Reviewed-by: Wainer dos Santos Moschetta 
Reviewed-by: Eric Auger 
Reviewed-by: Willian Rampazzo 
Message-Id: <20210412044644.55083-4-cr...@redhat.com>
Signed-off-by: John Snow 
[Squashed in below fix. --js]
Signed-off-by: John Snow 
Signed-off-by: Cleber Rosa 
Message-Id: <20210601154546.130870-2-cr...@redhat.com>
Signed-off-by: John Snow 
---
 python/qemu/utils.py | 33 
 tests/acceptance/info_usernet.py | 29 +
 tests/acceptance/linux_ssh_mips_malta.py | 16 +---
 tests/acceptance/virtiofs_submounts.py   | 21 ---
 tests/vm/basevm.py   | 11 +++-
 5 files changed, 78 insertions(+), 32 deletions(-)
 create mode 100644 python/qemu/utils.py
 create mode 100644 tests/acceptance/info_usernet.py

diff --git a/python/qemu/utils.py b/python/qemu/utils.py
new file mode 100644
index 000..5ed789275ee
--- /dev/null
+++ b/python/qemu/utils.py
@@ -0,0 +1,33 @@
+"""
+QEMU utility library
+
+This offers miscellaneous utility functions, which may not be easily
+distinguishable or numerous to be in their own module.
+"""
+
+# Copyright (C) 2021 Red Hat Inc.
+#
+# Authors:
+#  Cleber Rosa 
+#
+# This work is licensed under the terms of the GNU GPL, version 2.  See
+# the COPYING file in the top-level directory.
+#
+
+import re
+from typing import Optional
+
+
+def get_info_usernet_hostfwd_port(info_usernet_output: str) -> Optional[int]:
+"""
+Returns the port given to the hostfwd parameter via info usernet
+
+:param info_usernet_output: output generated by hmp command "info usernet"
+:return: the port number allocated by the hostfwd option
+"""
+for line in info_usernet_output.split('\r\n'):
+regex = r'TCP.HOST_FORWARD.*127\.0\.0\.1\s+(\d+)\s+10\.'
+match = re.search(regex, line)
+if match is not None:
+return int(match[1])
+return None
diff --git a/tests/acceptance/info_usernet.py b/tests/acceptance/info_usernet.py
new file mode 100644
index 000..9c1fd903a0b
--- /dev/null
+++ b/tests/acceptance/info_usernet.py
@@ -0,0 +1,29 @@
+# Test for the hmp command "info usernet"
+#
+# Copyright (c) 2021 Red Hat, Inc.
+#
+# Author:
+#  Cleber Rosa 
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# later.  See the COPYING file in the top-level directory.
+
+from avocado_qemu import Test
+
+from qemu.utils import get_info_usernet_hostfwd_port
+
+
+class InfoUsernet(Test):
+
+def test_hostfwd(self):
+self.vm.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22')
+self.vm.launch()
+res = self.vm.command('human-monitor-command',
+  command_line='info usernet')
+port = get_info_usernet_hostfwd_port(res)
+self.assertIsNotNone(port,
+ ('"info usernet" output content does not seem to '
+  'contain the redirected port'))
+self.assertGreater(port, 0,
+   ('Found a redirected port that is not greater than'
+' zero'))
diff --git a/tests/acceptance/linux_ssh_mips_malta.py 
b/tests/acceptance/linux_ssh_mips_malta.py
index 6dbd02d49d5..052008f02d4 100644
--- a/tests/acceptance/linux_ssh_mips_malta.py
+++ b/tests/acceptance/linux_ssh_mips_malta.py
@@ -18,6 +18,8 @@
 from avocado.utils import archive
 from avocado.utils import ssh
 
+from qemu.utils import get_info_usernet_hostfwd_port
+
 
 class LinuxSSH(Test):
 
@@ -70,18 +72,14 @@ def get_kernel_info(self, endianess, wordsize):
 def setUp(self):
 super(LinuxSSH, self).setUp()
 
-def get_portfwd(self):
+def ssh_connect(self, username, password):
+self.ssh_logger = logging.getLogger('ssh')
 res = self.vm.command('human-monitor-command',
   command_line='info usernet')
-line = res.split('\r\n')[2]
-port = re.split(r'.*TCP.HOST_FORWARD.*127\.0\.0\.1 (\d+)\s+10\..*',
-line)[1]
+port = get_info_usernet_hostfwd_port(res)
+if not port:
+self.cancel("Failed to retrieve SSH port")
 self.log.debug("sshd listening on port:" + port)
-return port
-
-def ssh_connect(self, username, password):
-self.ssh_logger = logging.getLogger('ssh')
-port = self.get_portfwd()
 self.ssh_session = ssh.Session(self.VM_IP, port=int(port),
user=username, password=password)
 for i in range(10):
diff --git a/tests/acceptance/virtiofs_submounts.py 

[PULL v2 00/44] Python patches

2021-06-01 Thread John Snow
The following changes since commit 52848929b70dcf92a68aedcfd90207be81ba3274:

  Merge remote-tracking branch 'remotes/kraxel/tags/usb-20210528-pull-request' 
into staging (2021-05-30 20:10:30 +0100)

are available in the Git repository at:

  https://gitlab.com/jsnow/qemu.git tags/python-pull-request

for you to fetch changes up to 6b9c277797879ce41ed20deb6737f4156cc279b3:

  gitlab: add python linters to CI (2021-06-01 16:21:21 -0400)


Pull request

V2:
 - Squashed in fixup for
   'Python: add utility function for retrieving port redirection'
 - Rebased on today's upstream

CI here:
https://gitlab.com/jsnow/qemu/-/pipelines/313202814



Cleber Rosa (12):
  Python: expose QEMUMachine's temporary directory
  tests/acceptance/virtiofs_submounts.py: add missing accel tag
  tests/acceptance/virtiofs_submounts.py: evaluate string not length
  Python: add utility function for retrieving port redirection
  Acceptance Tests: move useful ssh methods to base class
  Acceptance Tests: add port redirection for ssh by default
  Acceptance Tests: make username/password configurable
  Acceptance Tests: set up SSH connection by default after boot for
LinuxTest
  tests/acceptance/virtiofs_submounts.py: remove launch_vm()
  Acceptance Tests: add basic documentation on LinuxTest base class
  Acceptance Tests: introduce CPU hotplug test
  tests/acceptance/virtiofs_submounts.py: fix setup of SSH pubkey

John Snow (31):
  python/console_socket: avoid one-letter variable
  python/machine: use subprocess.DEVNULL instead of
open(os.path.devnull)
  python/machine: use subprocess.run instead of subprocess.Popen
  python/console_socket: Add a pylint ignore
  python/machine: Disable pylint warning for open() in _pre_launch
  python/machine: disable warning for Popen in _launch()
  python/machine: Trim line length to below 80 chars
  iotests/297: add --namespace-packages to mypy arguments
  python: create qemu packages
  python: add qemu package installer
  python: add VERSION file
  python: add directory structure README.rst files
  python: add MANIFEST.in
  python: Add pipenv support
  python: add pylint import exceptions
  python: move pylintrc into setup.cfg
  python: add pylint to pipenv
  python: move flake8 config to setup.cfg
  python: add excluded dirs to flake8 config
  python: Add flake8 to pipenv
  python: move mypy.ini into setup.cfg
  python: add mypy to pipenv
  python: move .isort.cfg into setup.cfg
  python/qemu: add isort to pipenv
  python/qemu: add qemu package itself to pipenv
  python: add devel package requirements to setuptools
  python: add avocado-framework and tests
  python: add Makefile for some common tasks
  python: add .gitignore
  python: add tox support
  gitlab: add python linters to CI

Willian Rampazzo (1):
  acceptance tests: bump Avocado version to 88.1

 docs/devel/testing.rst  |  26 +++
 python/PACKAGE.rst  |  43 
 python/README.rst   |  58 +
 python/qemu/README.rst  |   8 +
 python/qemu/machine/README.rst  |   9 +
 python/qemu/qmp/README.rst  |   9 +
 python/qemu/utils/README.rst|   7 +
 .gitlab-ci.d/containers.yml |   5 +
 .gitlab-ci.d/static_checks.yml  |  21 ++
 python/.gitignore   |  16 ++
 python/MANIFEST.in  |   3 +
 python/Makefile |  48 
 python/Pipfile  |  13 ++
 python/Pipfile.lock | 231 
 python/VERSION  |   1 +
 python/avocado.cfg  |  10 +
 python/mypy.ini |   4 -
 python/qemu/.flake8 |   2 -
 python/qemu/.isort.cfg  |   7 -
 python/qemu/__init__.py |  11 -
 python/qemu/machine/__init__.py |  36 +++
 python/qemu/{ => machine}/console_socket.py |  11 +-
 python/qemu/{ => machine}/machine.py|  68 --
 python/qemu/{ => machine}/qtest.py  |   9 +-
 python/qemu/pylintrc|  58 -
 python/qemu/{qmp.py => qmp/__init__.py} |  12 +-
 python/qemu/utils/__init__.py   |  45 
 python/qemu/{ => utils}/accel.py|   0
 python/setup.cfg| 102 +
 python/setup.py |  23 ++
 python/tests/flake8.sh  |   2 +
 python/tests/isort.sh   |   2 +
 python/tests/mypy.sh|   2 +
 python/tests/pylint.sh  |   2 +
 tests/acceptance/avocado_qemu/__init__.py   |  69 +-
 tests/acceptance/boot_linux.py  |  18 +-
 tests/acceptance/hotplug_cpu.py |  37 
 

Re: [PATCH v1 2/6] KVM: introduce dirty_pages into CPUState

2021-06-01 Thread Peter Xu
On Tue, Jun 01, 2021 at 01:04:06AM +0800, huang...@chinatelecom.cn wrote:
> diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
> index 044f668a6e..973c193501 100644
> --- a/include/hw/core/cpu.h
> +++ b/include/hw/core/cpu.h
> @@ -375,6 +375,8 @@ struct CPUState {
>  struct kvm_run *kvm_run;
>  struct kvm_dirty_gfn *kvm_dirty_gfns;
>  uint32_t kvm_fetch_index;
> +uint64_t dirty_pages;
> +bool stat_dirty_pages;

Shall we make this bool a global one?  As I don't think we'll be able to only
enable it on a subset of cpus?

-- 
Peter Xu




[PATCH v2 4/4] Hexagon (target/hexagon) remove unused TCG variables

2021-06-01 Thread Taylor Simpson
Signed-off-by: Taylor Simpson 
---
 target/hexagon/genptr.c|  6 --
 target/hexagon/translate.c | 11 ++-
 2 files changed, 2 insertions(+), 15 deletions(-)

diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index bd18cb1..5dbabe0 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -121,10 +121,7 @@ static void gen_log_reg_write_pair(int rnum, TCGv_i64 val)
 
 static inline void gen_log_pred_write(DisasContext *ctx, int pnum, TCGv val)
 {
-TCGv zero = tcg_const_tl(0);
 TCGv base_val = tcg_temp_new();
-TCGv and_val = tcg_temp_new();
-TCGv pred_written = tcg_temp_new();
 
 tcg_gen_andi_tl(base_val, val, 0xff);
 
@@ -143,10 +140,7 @@ static inline void gen_log_pred_write(DisasContext *ctx, 
int pnum, TCGv val)
 }
 tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << pnum);
 
-tcg_temp_free(zero);
 tcg_temp_free(base_val);
-tcg_temp_free(and_val);
-tcg_temp_free(pred_written);
 }
 
 static inline void gen_read_p3_0(TCGv control_reg)
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 9a37644..b23d36a 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -273,7 +273,6 @@ static void gen_reg_writes(DisasContext *ctx)
 
 static void gen_pred_writes(DisasContext *ctx, Packet *pkt)
 {
-TCGv zero, control_reg, pval;
 int i;
 
 /* Early exit if the log is empty */
@@ -281,10 +280,6 @@ static void gen_pred_writes(DisasContext *ctx, Packet *pkt)
 return;
 }
 
-zero = tcg_const_tl(0);
-control_reg = tcg_temp_new();
-pval = tcg_temp_new();
-
 /*
  * Only endloop instructions will conditionally
  * write a predicate.  If there are no endloop
@@ -292,6 +287,7 @@ static void gen_pred_writes(DisasContext *ctx, Packet *pkt)
  * write of the predicates.
  */
 if (pkt->pkt_has_endloop) {
+TCGv zero = tcg_const_tl(0);
 TCGv pred_written = tcg_temp_new();
 for (i = 0; i < ctx->preg_log_idx; i++) {
 int pred_num = ctx->preg_log[i];
@@ -302,6 +298,7 @@ static void gen_pred_writes(DisasContext *ctx, Packet *pkt)
hex_new_pred_value[pred_num],
hex_pred[pred_num]);
 }
+tcg_temp_free(zero);
 tcg_temp_free(pred_written);
 } else {
 for (i = 0; i < ctx->preg_log_idx; i++) {
@@ -314,10 +311,6 @@ static void gen_pred_writes(DisasContext *ctx, Packet *pkt)
 }
 }
 }
-
-tcg_temp_free(zero);
-tcg_temp_free(control_reg);
-tcg_temp_free(pval);
 }
 
 static void gen_check_store_width(DisasContext *ctx, int slot_num)
-- 
2.7.4



[PATCH v2 3/4] Hexagon (target/hexagon) cleanup gen_store_conditional[48] functions

2021-06-01 Thread Taylor Simpson
Previously the store-conditional code was writing to hex_pred[prednum].
Then, the fGEN_TCG override was reading from there to the destination
variable so that the packet commit logic would handle it properly.

The correct implementation is to write to the destination variable
and don't have the extra read in the override.

Remove the unused arguments from gen_store_conditional[48]

Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_tcg.h |  4 ++--
 target/hexagon/macros.h  |  2 +-
 target/hexagon/genptr.c  | 10 --
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index a375d6a..ee94c90 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -424,9 +424,9 @@
 #define fGEN_TCG_L4_loadd_locked(SHORTCODE) \
 SHORTCODE
 #define fGEN_TCG_S2_storew_locked(SHORTCODE) \
-do { SHORTCODE; READ_PREG(PdV, PdN); } while (0)
+SHORTCODE
 #define fGEN_TCG_S4_stored_locked(SHORTCODE) \
-do { SHORTCODE; READ_PREG(PdV, PdN); } while (0)
+SHORTCODE
 
 #define fGEN_TCG_STORE(SHORTCODE) \
 do { \
diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 2b208f3..84fa687 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -591,7 +591,7 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int 
shift)
 
 #ifdef QEMU_GENERATE
 #define fSTORE_LOCKED(NUM, SIZE, EA, SRC, PRED) \
-gen_store_conditional##SIZE(env, ctx, PdN, PRED, EA, SRC);
+gen_store_conditional##SIZE(ctx, PRED, EA, SRC);
 #endif
 
 #ifdef QEMU_GENERATE
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 797a6c0..bd18cb1 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -334,8 +334,7 @@ static inline void gen_load_locked8u(TCGv_i64 dest, TCGv 
vaddr, int mem_index)
 tcg_gen_mov_i64(hex_llsc_val_i64, dest);
 }
 
-static inline void gen_store_conditional4(CPUHexagonState *env,
-  DisasContext *ctx, int prednum,
+static inline void gen_store_conditional4(DisasContext *ctx,
   TCGv pred, TCGv vaddr, TCGv src)
 {
 TCGLabel *fail = gen_new_label();
@@ -349,7 +348,7 @@ static inline void gen_store_conditional4(CPUHexagonState 
*env,
 tmp = tcg_temp_new();
 tcg_gen_atomic_cmpxchg_tl(tmp, hex_llsc_addr, hex_llsc_val, src,
   ctx->mem_idx, MO_32);
-tcg_gen_movcond_tl(TCG_COND_EQ, hex_pred[prednum], tmp, hex_llsc_val,
+tcg_gen_movcond_tl(TCG_COND_EQ, pred, tmp, hex_llsc_val,
one, zero);
 tcg_temp_free(one);
 tcg_temp_free(zero);
@@ -363,8 +362,7 @@ static inline void gen_store_conditional4(CPUHexagonState 
*env,
 tcg_gen_movi_tl(hex_llsc_addr, ~0);
 }
 
-static inline void gen_store_conditional8(CPUHexagonState *env,
-  DisasContext *ctx, int prednum,
+static inline void gen_store_conditional8(DisasContext *ctx,
   TCGv pred, TCGv vaddr, TCGv_i64 src)
 {
 TCGLabel *fail = gen_new_label();
@@ -380,7 +378,7 @@ static inline void gen_store_conditional8(CPUHexagonState 
*env,
ctx->mem_idx, MO_64);
 tcg_gen_movcond_i64(TCG_COND_EQ, tmp, tmp, hex_llsc_val_i64,
 one, zero);
-tcg_gen_extrl_i64_i32(hex_pred[prednum], tmp);
+tcg_gen_extrl_i64_i32(pred, tmp);
 tcg_temp_free_i64(one);
 tcg_temp_free_i64(zero);
 tcg_temp_free_i64(tmp);
-- 
2.7.4



[PATCH v2 0/4] Hexagon (target/hexagon) bug fixes and cleanup

2021-06-01 Thread Taylor Simpson
Fixes for bugs found by inspection and internal testing
Tests added to tests/tcg/hexagon/misc.c

*** Changes in v2 ***
Added patches 3 and 4

Taylor Simpson (4):
  Hexagon (target/hexagon) fix bug in fLSBNEW*
  Hexagon (target/hexagon) fix l2fetch instructions
  Hexagon (target/hexagon) cleanup gen_store_conditional[48] functions
  Hexagon (target/hexagon) remove unused TCG variables

 target/hexagon/gen_tcg.h  | 15 +--
 target/hexagon/macros.h   | 29 -
 target/hexagon/genptr.c   | 16 +++-
 target/hexagon/op_helper.c|  5 
 target/hexagon/translate.c| 11 ++--
 tests/tcg/hexagon/misc.c  | 48 ++-
 target/hexagon/imported/encode_pp.def |  3 +++
 7 files changed, 80 insertions(+), 47 deletions(-)

-- 
2.7.4



[PATCH v2 1/4] Hexagon (target/hexagon) fix bug in fLSBNEW*

2021-06-01 Thread Taylor Simpson
Change fLSBNEW/fLSBNEW0/fLSBNEW1 from copy to "x & 1"
Remove gen_logical_not function
Clean up fLSBNEWNOT to use andi-1 followed by xori-1

Test cases added to tests/tcg/hexagon/misc.c

Signed-off-by: Taylor Simpson 
---
 target/hexagon/macros.h| 27 ++-
 target/hexagon/op_helper.c |  5 -
 tests/tcg/hexagon/misc.c   | 39 ++-
 3 files changed, 48 insertions(+), 23 deletions(-)

diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index b726c3b..2b208f3 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -239,33 +239,26 @@ static inline void gen_pred_cancel(TCGv pred, int 
slot_num)
 #endif
 
 #ifdef QEMU_GENERATE
-#define fLSBNEW(PVAL)   tcg_gen_mov_tl(LSB, (PVAL))
-#define fLSBNEW0tcg_gen_mov_tl(LSB, hex_new_pred_value[0])
-#define fLSBNEW1tcg_gen_mov_tl(LSB, hex_new_pred_value[1])
+#define fLSBNEW(PVAL)   tcg_gen_andi_tl(LSB, (PVAL), 1)
+#define fLSBNEW0tcg_gen_andi_tl(LSB, hex_new_pred_value[0], 1)
+#define fLSBNEW1tcg_gen_andi_tl(LSB, hex_new_pred_value[1], 1)
 #else
-#define fLSBNEW(PVAL)   (PVAL)
-#define fLSBNEW0new_pred_value(env, 0)
-#define fLSBNEW1new_pred_value(env, 1)
+#define fLSBNEW(PVAL)   ((PVAL) & 1)
+#define fLSBNEW0(env->new_pred_value[0] & 1)
+#define fLSBNEW1(env->new_pred_value[1] & 1)
 #endif
 
 #ifdef QEMU_GENERATE
-static inline void gen_logical_not(TCGv dest, TCGv src)
-{
-TCGv one = tcg_const_tl(1);
-TCGv zero = tcg_const_tl(0);
-
-tcg_gen_movcond_tl(TCG_COND_NE, dest, src, zero, zero, one);
-
-tcg_temp_free(one);
-tcg_temp_free(zero);
-}
 #define fLSBOLDNOT(VAL) \
 do { \
 tcg_gen_andi_tl(LSB, (VAL), 1); \
 tcg_gen_xori_tl(LSB, LSB, 1); \
 } while (0)
 #define fLSBNEWNOT(PNUM) \
-gen_logical_not(LSB, (PNUM))
+do { \
+tcg_gen_andi_tl(LSB, (PNUM), 1); \
+tcg_gen_xori_tl(LSB, LSB, 1); \
+} while (0)
 #else
 #define fLSBNEWNOT(PNUM) (!fLSBNEW(PNUM))
 #define fLSBOLDNOT(VAL) (!fLSBOLD(VAL))
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 63dd685..4595559 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -128,11 +128,6 @@ void HELPER(debug_start_packet)(CPUHexagonState *env)
 }
 }
 
-static int32_t new_pred_value(CPUHexagonState *env, int pnum)
-{
-return env->new_pred_value[pnum];
-}
-
 /* Checks for bookkeeping errors between disassembly context and runtime */
 void HELPER(debug_check_store_width)(CPUHexagonState *env, int slot, int check)
 {
diff --git a/tests/tcg/hexagon/misc.c b/tests/tcg/hexagon/misc.c
index 17c3919..9e139f3 100644
--- a/tests/tcg/hexagon/misc.c
+++ b/tests/tcg/hexagon/misc.c
@@ -181,6 +181,19 @@ static inline void S4_storeirifnew_io(void *p, int pred)
: "p0", "memory");
 }
 
+static int L2_ploadrifnew_pi(void *p, int pred)
+{
+  int result;
+  asm volatile("%0 = #31\n\t"
+   "{\n\t"
+   "p0 = cmp.eq(%1, #1)\n\t"
+   "if (!p0.new) %0 = memw(%2++#4)\n\t"
+   "}\n\t"
+   : "=r"(result) : "r"(pred), "r"(p)
+   : "p0");
+  return result;
+}
+
 /*
  * Test that compound-compare-jump is executed in 2 parts
  * First we have to do all the compares in the packet and
@@ -298,8 +311,24 @@ static int auto_and(void)
 return retval;
 }
 
+void test_lsbnew(void)
+{
+int result;
+
+asm("r0 = #2\n\t"
+"r1 = #5\n\t"
+"{\n\t"
+"p0 = r0\n\t"
+"if (p0.new) r1 = #3\n\t"
+"}\n\t"
+"%0 = r1\n\t"
+: "=r"(result) :: "r0", "r1", "p0");
+check(result, 5);
+}
+
 int main()
 {
+int res;
 long long res64;
 int pred;
 
@@ -394,6 +423,12 @@ int main()
 S4_storeirifnew_io([8], 1);
 check(array[9], 9);
 
+memcpy(array, init, sizeof(array));
+res = L2_ploadrifnew_pi([6], 0);
+check(res, 6);
+res = L2_ploadrifnew_pi([7], 1);
+check(res, 31);
+
 int x = cmpnd_cmp_jump();
 check(x, 12);
 
@@ -406,7 +441,7 @@ int main()
 check((int)pair, 5);
 check((int)(pair >> 32), 7);
 
-int res = test_clrtnew(1, 7);
+res = test_clrtnew(1, 7);
 check(res, 0);
 res = test_clrtnew(2, 7);
 check(res, 7);
@@ -422,6 +457,8 @@ int main()
 res = auto_and();
 check(res, 0);
 
+test_lsbnew();
+
 puts(err ? "FAIL" : "PASS");
 return err;
 }
-- 
2.7.4



[PATCH v2 2/4] Hexagon (target/hexagon) fix l2fetch instructions

2021-06-01 Thread Taylor Simpson
Y4_l2fetch == l2fetch(Rs32, Rt32)
Y5_l2fetch == l2fetch(Rs32, Rtt32)

The semantics for these instructions are present, but the encodings
are missing.

Note that these are treated as nops in qemu, so we add overrides.

Test case added to tests/tcg/hexagon/misc.c

Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_tcg.h  | 11 +++
 tests/tcg/hexagon/misc.c  |  9 +
 target/hexagon/imported/encode_pp.def |  3 +++
 3 files changed, 23 insertions(+)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index 18fcdbc..a375d6a 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -734,4 +734,15 @@
 #define fGEN_TCG_F2_dfmpyhh(SHORTCODE) \
 gen_helper_dfmpyhh(RxxV, cpu_env, RxxV, RssV, RttV)
 
+/* Nothing to do for these in qemu, need to suppress compiler warnings */
+#define fGEN_TCG_Y4_l2fetch(SHORTCODE) \
+do { \
+RsV = RsV; \
+RtV = RtV; \
+} while (0)
+#define fGEN_TCG_Y5_l2fetch(SHORTCODE) \
+do { \
+RsV = RsV; \
+} while (0)
+
 #endif
diff --git a/tests/tcg/hexagon/misc.c b/tests/tcg/hexagon/misc.c
index 9e139f3..f0b1947 100644
--- a/tests/tcg/hexagon/misc.c
+++ b/tests/tcg/hexagon/misc.c
@@ -326,6 +326,13 @@ void test_lsbnew(void)
 check(result, 5);
 }
 
+void test_l2fetch(void)
+{
+/* These don't do anything in qemu, just make sure they don't assert */
+asm volatile ("l2fetch(r0, r1)\n\t"
+  "l2fetch(r0, r3:2)\n\t");
+}
+
 int main()
 {
 int res;
@@ -459,6 +466,8 @@ int main()
 
 test_lsbnew();
 
+test_l2fetch();
+
 puts(err ? "FAIL" : "PASS");
 return err;
 }
diff --git a/target/hexagon/imported/encode_pp.def 
b/target/hexagon/imported/encode_pp.def
index 35ae3d2..939c6fc 100644
--- a/target/hexagon/imported/encode_pp.def
+++ b/target/hexagon/imported/encode_pp.def
@@ -493,6 +493,9 @@ DEF_ENC32(Y2_dccleana, ICLASS_ST" 000 00 00s 
PP-- ")
 DEF_ENC32(Y2_dcinva,   ICLASS_ST" 000 00 01s PP-- ")
 DEF_ENC32(Y2_dccleaninva,  ICLASS_ST" 000 00 10s PP-- ")
 
+DEF_ENC32(Y4_l2fetch,  ICLASS_ST" 011 00 00s PP-t 000-")
+DEF_ENC32(Y5_l2fetch,  ICLASS_ST" 011 01 00s PP-t ")
+
 /***/
 /* */
 /* */
-- 
2.7.4



Re: [PATCH] hw/arm/boot: Use NUMA node ID in memory node name

2021-06-01 Thread Gavin Shan

Hi Drew,

On 6/1/21 5:50 PM, Andrew Jones wrote:

On Tue, Jun 01, 2021 at 03:30:04PM +0800, Gavin Shan wrote:

We possibly populate empty nodes where memory isn't included and might
be hot added at late time. The FDT memory nodes can't be created due
to conflicts on their names if multiple empty nodes are specified.
For example, the VM fails to start with the following error messages.

   /home/gavin/sandbox/qemu.main/build/qemu-system-aarch64  \
   -accel kvm -machine virt,gic-version=host\
   -cpu host -smp 4,sockets=2,cores=2,threads=1 -m 1024M,maxmem=64G \
   -object memory-backend-ram,id=mem0,size=512M \
   -object memory-backend-ram,id=mem1,size=512M \
   -numa node,nodeid=0,cpus=0-1,memdev=mem0 \
   -numa node,nodeid=1,cpus=2-3,memdev=mem1 \
   -numa node,nodeid=2  \
   -numa node,nodeid=3  \
 :
   -device virtio-balloon-pci,id=balloon0,free-page-reporting=yes

   qemu-system-aarch64: FDT: Failed to create subnode /memory@8000: \
FDT_ERR_EXISTS

This fixes the issue by using NUMA node ID or zero in the memory node
name to avoid the conflicting memory node names. With this applied, the
VM can boot successfully with above command lines.

Signed-off-by: Gavin Shan 
---
  hw/arm/boot.c | 7 ++-
  1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index d7b059225e..3169bdf595 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -432,7 +432,12 @@ static int fdt_add_memory_node(void *fdt, uint32_t acells, 
hwaddr mem_base,
  char *nodename;
  int ret;
  
-nodename = g_strdup_printf("/memory@%" PRIx64, mem_base);

+if (numa_node_id >= 0) {
+nodename = g_strdup_printf("/memory@%d", numa_node_id);
+} else {
+nodename = g_strdup("/memory@0");
+}
+
  qemu_fdt_add_subnode(fdt, nodename);
  qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory");
  ret = qemu_fdt_setprop_sized_cells(fdt, nodename, "reg", acells, mem_base,


[...]



Is it conventional to use the unit-address like this? If so, can you point
out where that's documented? If it's not conventional, then we shouldn't
do it. And then I'm not sure what we should do in this case. Here's a
couple links I found, but they don't really help...

https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#sect-node-names
https://devicetree-specification.readthedocs.io/en/latest/chapter3-devicenodes.html#memory-node



As stated in the document (section 2.2.1.1). It's conventional to take the first
address of 'reg' property as unit-address, but it's not mandatory as I 
understand:

(1) In section 2.2.1.1, the bus can specify additional format to unit-address.
(2) The device node name isn't used to identify the device node in Linux kernel.
They are actually identified by 'device_type' property.
(drivers/of/fdt.c::early_init_dt_scan_memory())

I think it's still nice to include the unit-address in meory node's name. For 
the
conflicting nodes, we add more suffix like below. I can update the code in v2 if
it's preferred way to go.

   memory@0
   memory@0-0   # For empty NUMA node
   memory@0-1   # For empty NUMA node
   memory@8000
   memory@8000-0# For empty NUMA node
   memory@8000-1# For empty NUMA node

---

https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#sect-node-names

The unit-address must match the first address specified in the reg property of 
the node.
If the node has no reg property, the @unit-address must be omitted and the 
node-name
alone differentiates the node from other nodes at the same level in the tree. 
The binding
for a particular bus may specify additional, more specific requirements for the 
format
of reg and the unit-address.

Thanks,
Gavin




Re: [PATCH v1 0/6] support dirtyrate at the granualrity of vcpu

2021-06-01 Thread Peter Xu
On Tue, Jun 01, 2021 at 01:02:45AM +0800, huang...@chinatelecom.cn wrote:
> From: Hyman Huang(黄勇) 
> 
> Since the Dirty Ring on QEMU part has been merged recently, how to use
> this feature is under consideration.
> 
> In the scene of migration, it is valuable to provide a more accurante
> interface to track dirty memory than existing one, so that the upper
> layer application can make a wise decision, or whatever. More importantly,
> dirtyrate info at the granualrity of vcpu could provide a possibility to
> make migration convergent by imposing restriction on vcpu. With Dirty
> Ring, we can calculate dirtyrate efficiently and cheaply.
> 
> The old interface implemented by sampling pages, it consumes cpu 
> resource, and the larger guest memory size become, the more cpu resource
> it consumes, namely, hard to scale. New interface has no such drawback.

Yong,

Thanks for working on this!

Some high-level comments:

- The layout of the patch looks a bit odd.  E.g., you introduced the new "vcpu"
  qmp parameter in patch 3, however it's not yet implemented, meanwhile I feel
  like you squashed mostly all the rest into patch 6.  It's okay to use a
  single big patch, but IMHO better to not declare that flag in QMP before it's
  working, so ideally that should be the last patch to do that.

  From that POV: patch 1/2/4 look ok to be separated; perhaps squash patch
  3/5/6 into one single patch to enable the new method as the last one?

- You used "vcpu" across the patchset to show the per-vcpu new method.  Shall
  we rename it globally to "per_vcpu" or "vcpu_based"?  A raw "vcpu" looks more
  like a struct pointer not a boolean.

- Using memory_global_dirty_log_start|stop() may not be wise too IMHO, at least
  we need to make sure it's not during migration, otherwise we could call the
  stop() before migration ends then that'll be a problem..

  Maybe we can start to make global_dirty_log a bitmask? Then we define:

GLOBAL_DIRTY_MIGRATION
GLOBAL_DIRTY_DIRTY_RATE

  All references to global_dirty_log should mostly be untouched because any bit
  set there should justify that global dirty logging is enabled (either for
  migration or for dirty rate measurement).

  Migration starting half-way of dirty rate measurement seems okay too even
  taking things like init-all-set into account, afaict.. as long as dirty rate
  code never touches the qemu dirty bitmap, but only do the accounting when
  collecting the pages...

  Feel free to think more about it on any other potential conflict with
  migration, but in general seems working to me.

- Would you consider picking up my HMP patch and let HMP work from the 1st day?

- Please Cc the author of dirty rate too (Chuan Zheng ),
  while I already started to do so in this email.

Thanks,

-- 
Peter Xu




[RFC PATCH 0/5] target/ppc: powerpc_excp improvements - part I

2021-06-01 Thread Fabiano Rosas
This is my attempt at reducing the size of powerpc_excp and cleaning
it up a bit. It has two parts:

part I (this series) tackles the big switch statement that runs the
interrupt emulation code. Each interrupt now gets its own callback
function that is kept within QOM. The per-processor code still
registers the interrupts in a similar manner to what is done today and
powerpc_excp replaces its switch statement for a function call.

part II (still WIP: https://github.com/farosas/qemu/commits/powerpc_excp)
tries to make powerpc_excp processor agnostic by removing the excp_model
checks and moving processor-specific interrupt properties to
per-processor QOM classes.

I think it would be nice if we could at the end have separate
interrupts and interrupt model implementations. That way we could
start moving things into well defined per-processor files, CONFIGs,
etc.

(So far tested on x86 emulating P9 and compile-only 32-bit and
linux-user. I still need to gather some command lines for the older
cpus.)

Based-on: eb22196316ee653178ae517de83b490ad3636b91 # ppc-for-6.1

Fabiano Rosas (5):
  target/ppc: powerpc_excp: Move lpes code to where it is used
  target/ppc: powerpc_excp: Remove dump_syscall_vectored
  target/ppc: powerpc_excp: Consolidade TLB miss code
  target/ppc: powerpc_excp: Standardize arguments to interrupt code
  target/ppc: powerpc_excp: Move interrupt raising code to QOM

 target/ppc/cpu.h |  29 +-
 target/ppc/cpu_init.c| 640 +++--
 target/ppc/excp_helper.c | 670 +--
 target/ppc/interrupts.c  | 638 +
 target/ppc/machine.c |   2 +-
 target/ppc/meson.build   |   1 +
 target/ppc/ppc_intr.h|  55 
 target/ppc/translate.c   |   3 +-
 8 files changed, 1117 insertions(+), 921 deletions(-)
 create mode 100644 target/ppc/interrupts.c
 create mode 100644 target/ppc/ppc_intr.h

--
2.29.2



[RFC PATCH 4/5] target/ppc: powerpc_excp: Standardize arguments to interrupt code

2021-06-01 Thread Fabiano Rosas
The next patches will split the big switch statement in powerpc_excp
into individual functions so it would be cleaner if all variables are
already grouped in a structure and their names consistent.

This patch makes it so that the old values for MSR and NIP (from env)
are saved at the beginning as regs.msr and regs.nip and all
modifications are done over this regs version. At the end of the
function regs.msr and regs.nip are saved in the SRRs and regs.new_msr
and regs.new_nip are written to env.

There are two points of interest here:

- The system call code has a particularity where it needs to use
env->nip because it might return early and the modification needs to
be seen by the virtual hypervisor hypercall code. I have added a
comment making this clear.

- The MSR filter at the beginning is being applied to the old MSR value
only, i.e. the one that goes into SRR1. The new_msr is taken from
env->msr without filtering the reserved bits. This might be a bug in
the existing code. I'm also adding a comment to point that out.

Signed-off-by: Fabiano Rosas 
---
 target/ppc/excp_helper.c | 231 +--
 1 file changed, 125 insertions(+), 106 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index fd147e2a37..12bf829c8f 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -186,7 +186,7 @@ static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState 
*env, int excp,
 static inline void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int 
excp,
   target_ulong msr,
   target_ulong *new_msr,
-  target_ulong *vector)
+  target_ulong *new_nip)
 {
 #if defined(TARGET_PPC64)
 CPUPPCState *env = >env;
@@ -263,9 +263,9 @@ static inline void ppc_excp_apply_ail(PowerPCCPU *cpu, int 
excp_model, int excp,
 
 if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
 if (ail == 2) {
-*vector |= 0x00018000ull;
+*new_nip |= 0x00018000ull;
 } else if (ail == 3) {
-*vector |= 0xc0004000ull;
+*new_nip |= 0xc0004000ull;
 }
 } else {
 /*
@@ -273,15 +273,15 @@ static inline void ppc_excp_apply_ail(PowerPCCPU *cpu, 
int excp_model, int excp,
  * only the MSR. AIL=3 replaces the 0x17000 base with 0xc...3000.
  */
 if (ail == 3) {
-*vector &= ~0x00017000ull; /* Un-apply the base offset */
-*vector |= 0xc0003000ull; /* Apply scv's AIL=3 offset */
+*new_nip &= ~0x00017000ull; /* Un-apply the base offset */
+*new_nip |= 0xc0003000ull; /* Apply scv's AIL=3 offset */
 }
 }
 #endif
 }
 
-static inline void powerpc_set_excp_state(PowerPCCPU *cpu,
-  target_ulong vector, target_ulong 
msr)
+static inline void powerpc_set_excp_state(PowerPCCPU *cpu, target_ulong 
new_nip,
+  target_ulong new_msr)
 {
 CPUState *cs = CPU(cpu);
 CPUPPCState *env = >env;
@@ -294,9 +294,9 @@ static inline void powerpc_set_excp_state(PowerPCCPU *cpu,
  * will prevent setting of the HV bit which some exceptions might need
  * to do.
  */
-env->msr = msr & env->msr_mask;
+env->msr = new_msr & env->msr_mask;
 hreg_compute_hflags(env);
-env->nip = vector;
+env->nip = new_nip;
 /* Reset exception state */
 cs->exception_index = POWERPC_EXCP_NONE;
 env->error_code = 0;
@@ -311,6 +311,17 @@ static inline void powerpc_set_excp_state(PowerPCCPU *cpu,
 check_tlb_flush(env, false);
 }
 
+struct ppc_intr_args {
+target_ulong nip;
+target_ulong msr;
+target_ulong new_nip;
+target_ulong new_msr;
+int sprn_srr0;
+int sprn_srr1;
+int sprn_asrr0;
+int sprn_asrr1;
+};
+
 /*
  * Note that this function should be greatly optimized when called
  * with a constant excp, from ppc_hw_interrupt
@@ -319,37 +330,40 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
 {
 CPUState *cs = CPU(cpu);
 CPUPPCState *env = >env;
-target_ulong msr, new_msr, vector;
-int srr0, srr1, asrr0, asrr1, lev = -1;
+struct ppc_intr_args regs;
+int lev = -1;
 
 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
   " => %08x (%02x)\n", env->nip, excp, env->error_code);
 
 /* new srr1 value excluding must-be-zero bits */
 if (excp_model == POWERPC_EXCP_BOOKE) {
-msr = env->msr;
+regs.msr = env->msr;
 } else {
-msr = env->msr & ~0x783fULL;
+regs.msr = env->msr & ~0x783fULL;
 }
+regs.nip = env->nip;
 
 /*
  * new interrupt handler msr preserves existing HV and ME unless
  * explicitly overriden
+ *
+ * XXX: should this use the filtered MSR 

[RFC PATCH 2/5] target/ppc: powerpc_excp: Remove dump_syscall_vectored

2021-06-01 Thread Fabiano Rosas
This function is identical to dump_syscall, so use the latter for
system call vectored as well.

Signed-off-by: Fabiano Rosas 
---
 target/ppc/excp_helper.c | 14 +-
 1 file changed, 1 insertion(+), 13 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 5ea8503b46..9e3aae1c96 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -70,18 +70,6 @@ static inline void dump_syscall(CPUPPCState *env)
   ppc_dump_gpr(env, 8), env->nip);
 }
 
-static inline void dump_syscall_vectored(CPUPPCState *env)
-{
-qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64
-  " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64
-  " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64
-  " nip=" TARGET_FMT_lx "\n",
-  ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
-  ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
-  ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7),
-  ppc_dump_gpr(env, 8), env->nip);
-}
-
 static inline void dump_hcall(CPUPPCState *env)
 {
 qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64
@@ -564,7 +552,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
 break;
 case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */
 lev = env->error_code;
-dump_syscall_vectored(env);
+dump_syscall(env);
 env->nip += 4;
 new_msr |= env->msr & ((target_ulong)1 << MSR_EE);
 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
-- 
2.29.2




[RFC PATCH 1/5] target/ppc: powerpc_excp: Move lpes code to where it is used

2021-06-01 Thread Fabiano Rosas
Signed-off-by: Fabiano Rosas 
---
 target/ppc/excp_helper.c | 47 +---
 1 file changed, 25 insertions(+), 22 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 04418054f5..5ea8503b46 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -333,7 +333,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
 CPUPPCState *env = >env;
 target_ulong msr, new_msr, vector;
 int srr0, srr1, asrr0, asrr1, lev = -1;
-bool lpes0;
 
 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
   " => %08x (%02x)\n", env->nip, excp, env->error_code);
@@ -365,27 +364,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
 excp = powerpc_reset_wakeup(cs, env, excp, );
 }
 
-/*
- * Exception targeting modifiers
- *
- * LPES0 is supported on POWER7/8/9
- * LPES1 is not supported (old iSeries mode)
- *
- * On anything else, we behave as if LPES0 is 1
- * (externals don't alter MSR:HV)
- */
-#if defined(TARGET_PPC64)
-if (excp_model == POWERPC_EXCP_POWER7 ||
-excp_model == POWERPC_EXCP_POWER8 ||
-excp_model == POWERPC_EXCP_POWER9 ||
-excp_model == POWERPC_EXCP_POWER10) {
-lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
-} else
-#endif /* defined(TARGET_PPC64) */
-{
-lpes0 = true;
-}
-
 /*
  * Hypervisor emulation assistance interrupt only exists on server
  * arch 2.05 server or later. We also don't want to generate it if
@@ -473,8 +451,32 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
 msr |= env->error_code;
 break;
 case POWERPC_EXCP_EXTERNAL:  /* External input   */
+{
+bool lpes0;
+
 cs = CPU(cpu);
 
+/*
+ * Exception targeting modifiers
+ *
+ * LPES0 is supported on POWER7/8/9
+ * LPES1 is not supported (old iSeries mode)
+ *
+ * On anything else, we behave as if LPES0 is 1
+ * (externals don't alter MSR:HV)
+ */
+#if defined(TARGET_PPC64)
+if (excp_model == POWERPC_EXCP_POWER7 ||
+excp_model == POWERPC_EXCP_POWER8 ||
+excp_model == POWERPC_EXCP_POWER9 ||
+excp_model == POWERPC_EXCP_POWER10) {
+lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
+} else
+#endif /* defined(TARGET_PPC64) */
+{
+lpes0 = true;
+}
+
 if (!lpes0) {
 new_msr |= (target_ulong)MSR_HVB;
 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
@@ -486,6 +488,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
 env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
 }
 break;
+}
 case POWERPC_EXCP_ALIGN: /* Alignment exception  */
 /* Get rS/rD and rA from faulting opcode */
 /*
-- 
2.29.2




[RFC PATCH 5/5] target/ppc: powerpc_excp: Move interrupt raising code to QOM

2021-06-01 Thread Fabiano Rosas
This patch introduces a new way to dispatch the emulated interrupts in
powerpc_excp. It leverages the QEMU object model to store the
implementations for each interrupt and link them to their identifier
from POWERPC_EXCP enum. The processor-specific code then uses this
identifier to register which interrupts it supports.

Interrupts now come out of the big switch in powerpc_excp into their
own functions:

  static void ppc_intr_system_reset()
  {
  /*
   * Interrupt code. Sets any specific registers and MSR bits.
   */
  }
  PPC_DEFINE_INTR(POWERPC_EXCP_RESET, system_reset, "System reset");

  ^This line registers the interrupt with QOM.

When we initialize the emulated processor, the correct set of
interrupts is instantiated (pretty much like we already do):

  static void init_excp_POWER9(CPUPPCState *env)
  {
  ppc_intr_add(env, 0x0100, POWERPC_EXCP_RESET);
  (...)
  }

When it comes the time to inject the interrupt:

  static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
  {
  (...)

  intr = >entry_points[excp];
  intr->setup_regs();<-- ppc_intr_system_reset function

  (...)
  env->spr[srr0] = nip;
  env->spr[srr1] = msr;

  env->nip = intr->addr;
  env->msr = new_msr;
  }

Some points to notice:

- The structure for the new PPCInterrupt class object is stored
  directly inside of CPUPPCState (env) so the translation code can
  still access it linearly at an offset.

- Some interrupts were being registered for P7/8/9/10 but were never
  implemented (i.e. not in the powerpc_excp switch statement). They
  are likely never triggered. We now get the benefit of QOM warning in
  such cases:

  qemu-system-ppc64: missing object type 'POWERPC_EXCP_SDOOR'
  qemu-system-ppc64: missing object type 'POWERPC_EXCP_HV_MAINT'

- The code currently allows for Program interrupts to be ignored and
  System call interrupts to be directed to the vhyp hypercall code. I
  have added an 'ignore' flag to deal with these two cases and return
  early from powerpc_excp.

Signed-off-by: Fabiano Rosas 
---
 target/ppc/cpu.h |  29 +-
 target/ppc/cpu_init.c| 640 +++
 target/ppc/excp_helper.c | 545 ++---
 target/ppc/interrupts.c  | 638 ++
 target/ppc/machine.c |   2 +-
 target/ppc/meson.build   |   1 +
 target/ppc/ppc_intr.h|  55 
 target/ppc/translate.c   |   3 +-
 8 files changed, 1066 insertions(+), 847 deletions(-)
 create mode 100644 target/ppc/interrupts.c
 create mode 100644 target/ppc/ppc_intr.h

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index b0934d9be4..012677965f 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -174,6 +174,33 @@ enum {
 POWERPC_EXCP_TRAP  = 0x40,
 };
 
+typedef struct PPCInterrupt PPCInterrupt;
+typedef struct ppc_intr_args ppc_intr_args;
+typedef void (*ppc_intr_fn_t)(PowerPCCPU *cpu, PPCInterrupt *intr,
+  int excp_model, ppc_intr_args *regs,
+  bool *ignore);
+
+struct ppc_intr_args {
+target_ulong nip;
+target_ulong msr;
+target_ulong new_nip;
+target_ulong new_msr;
+int sprn_srr0;
+int sprn_srr1;
+int sprn_asrr0;
+int sprn_asrr1;
+int lev;
+};
+
+struct PPCInterrupt {
+Object parent;
+
+int id;
+const char *name;
+target_ulong addr;
+ppc_intr_fn_t setup_regs;
+};
+
 #define PPC_INPUT(env) ((env)->bus_model)
 
 /*/
@@ -1115,7 +1142,7 @@ struct CPUPPCState {
 uint32_t irq_input_state;
 void **irq_inputs;
 
-target_ulong excp_vectors[POWERPC_EXCP_NB]; /* Exception vectors */
+PPCInterrupt entry_points[POWERPC_EXCP_NB];
 target_ulong excp_prefix;
 target_ulong ivor_mask;
 target_ulong ivpr_mask;
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index d0411e7302..d91183357d 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -46,6 +46,7 @@
 #include "helper_regs.h"
 #include "internal.h"
 #include "spr_tcg.h"
+#include "ppc_intr.h"
 
 /* #define PPC_DEBUG_SPR */
 /* #define USE_APPLE_GDB */
@@ -2132,16 +2133,16 @@ static void register_8xx_sprs(CPUPPCState *env)
 static void init_excp_4xx_real(CPUPPCState *env)
 {
 #if !defined(CONFIG_USER_ONLY)
-env->excp_vectors[POWERPC_EXCP_CRITICAL] = 0x0100;
-env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x0200;
-env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x0500;
-env->excp_vectors[POWERPC_EXCP_ALIGN]= 0x0600;
-env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x0700;
-env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x0C00;
-env->excp_vectors[POWERPC_EXCP_PIT]  = 0x1000;
-env->excp_vectors[POWERPC_EXCP_FIT]  = 0x1010;
-env->excp_vectors[POWERPC_EXCP_WDT]  = 0x1020;
-env->excp_vectors[POWERPC_EXCP_DEBUG]= 0x2000;
+

[RFC PATCH 3/5] target/ppc: powerpc_excp: Consolidade TLB miss code

2021-06-01 Thread Fabiano Rosas
The only difference in the code for Instruction fetch, Data load and
Data store TLB miss errors is that when called from an unsupported
processor (i.e. not one of 602, 603, 603e, G2, 7x5 or 74xx), they
abort with a message specific to the operation type (insn fetch, data
load/store).

If a processor does not support those interrupts we should not be
registering them in init_excp_ to begin with, so that error
message would never be used.

I'm leaving the message in for completeness, but making it generic and
consolidating the three interrupts into the same case statement body.

Signed-off-by: Fabiano Rosas 
---
 target/ppc/excp_helper.c | 37 ++---
 1 file changed, 2 insertions(+), 35 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 9e3aae1c96..fd147e2a37 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -689,52 +689,20 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
   "is not implemented yet !\n");
 break;
 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error  */
-switch (excp_model) {
-case POWERPC_EXCP_602:
-case POWERPC_EXCP_603:
-case POWERPC_EXCP_603E:
-case POWERPC_EXCP_G2:
-goto tlb_miss_tgpr;
-case POWERPC_EXCP_7x5:
-goto tlb_miss;
-case POWERPC_EXCP_74xx:
-goto tlb_miss_74xx;
-default:
-cpu_abort(cs, "Invalid instruction TLB miss exception\n");
-break;
-}
-break;
 case POWERPC_EXCP_DLTLB: /* Data load TLB miss   */
-switch (excp_model) {
-case POWERPC_EXCP_602:
-case POWERPC_EXCP_603:
-case POWERPC_EXCP_603E:
-case POWERPC_EXCP_G2:
-goto tlb_miss_tgpr;
-case POWERPC_EXCP_7x5:
-goto tlb_miss;
-case POWERPC_EXCP_74xx:
-goto tlb_miss_74xx;
-default:
-cpu_abort(cs, "Invalid data load TLB miss exception\n");
-break;
-}
-break;
 case POWERPC_EXCP_DSTLB: /* Data store TLB miss  */
 switch (excp_model) {
 case POWERPC_EXCP_602:
 case POWERPC_EXCP_603:
 case POWERPC_EXCP_603E:
 case POWERPC_EXCP_G2:
-tlb_miss_tgpr:
 /* Swap temporary saved registers with GPRs */
 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
 new_msr |= (target_ulong)1 << MSR_TGPR;
 hreg_swap_gpr_tgpr(env);
 }
-goto tlb_miss;
+/* fall through */
 case POWERPC_EXCP_7x5:
-tlb_miss:
 #if defined(DEBUG_SOFTWARE_TLB)
 if (qemu_log_enabled()) {
 const char *es;
@@ -769,7 +737,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
 break;
 case POWERPC_EXCP_74xx:
-tlb_miss_74xx:
 #if defined(DEBUG_SOFTWARE_TLB)
 if (qemu_log_enabled()) {
 const char *es;
@@ -799,7 +766,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
 msr |= env->error_code; /* key bit */
 break;
 default:
-cpu_abort(cs, "Invalid data store TLB miss exception\n");
+cpu_abort(cs, "Invalid TLB miss exception\n");
 break;
 }
 break;
-- 
2.29.2




Re: [PATCH v3 05/33] block/nbd: BDRVNBDState: drop unused connect_err and connect_status

2021-06-01 Thread Eric Blake
On Fri, Apr 16, 2021 at 11:08:43AM +0300, Vladimir Sementsov-Ogievskiy wrote:
> These fields are write-only. Drop them.
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> Reviewed-by: Roman Kagan 
> ---
>  block/nbd.c | 12 ++--
>  1 file changed, 2 insertions(+), 10 deletions(-)
>

Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v3 03/33] block/nbd: ensure ->connection_thread is always valid

2021-06-01 Thread Eric Blake
On Fri, Apr 16, 2021 at 11:08:41AM +0300, Vladimir Sementsov-Ogievskiy wrote:
> From: Roman Kagan 
> 
> Simplify lifetime management of BDRVNBDState->connect_thread by
> delaying the possible cleanup of it until the BDRVNBDState itself goes
> away.
> 
> This also reverts
>  0267101af6 "block/nbd: fix possible use after free of s->connect_thread"
> as now s->connect_thread can't be cleared until the very end.
> 
> Signed-off-by: Roman Kagan 
>  [vsementsov: rebase, revert 0267101af6 changes]
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---
>  block/nbd.c | 56 -
>  1 file changed, 21 insertions(+), 35 deletions(-)
> 

>  static void nbd_clear_bdrvstate(BlockDriverState *bs)
>  {
>  BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
> +NBDConnectThread *thr = s->connect_thread;
> +bool thr_running;
> +
> +qemu_mutex_lock(>mutex);
> +thr_running = thr->state == CONNECT_THREAD_RUNNING;
> +if (thr_running) {
> +thr->state = CONNECT_THREAD_RUNNING_DETACHED;
> +}
> +qemu_mutex_unlock(>mutex);
> +
> +/* the runaway thread will clean it up itself */

s/clean it up/clean up/

Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v3 02/33] block/nbd: fix how state is cleared on nbd_open() failure paths

2021-06-01 Thread Eric Blake
On Fri, Apr 16, 2021 at 11:08:40AM +0300, Vladimir Sementsov-Ogievskiy wrote:
> We have two "return error" paths in nbd_open() after
> nbd_process_options(). Actually we should call nbd_clear_bdrvstate()
> on these paths. Interesting that nbd_process_options() calls
> nbd_clear_bdrvstate() by itself.
> 
> Let's fix leaks and refactor things to be more obvious:
> 
> - intialize yank at top of nbd_open()
> - move yank cleanup to nbd_clear_bdrvstate()
> - refactor nbd_open() so that all failure paths except for
>   yank-register goes through nbd_clear_bdrvstate()
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---
>  block/nbd.c | 36 ++--
>  1 file changed, 18 insertions(+), 18 deletions(-)
>

Reviewed-by: Eric Blake 

--
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH 2/2] nbd/server: Use drained block ops to quiesce the server

2021-06-01 Thread Eric Blake
On Tue, Jun 01, 2021 at 06:31:29PM +0200, Sergio Lopez wrote:
> > Hm, how do you get more than one coroutine per client yielding in
> > nbd_read_eof() at the same time? I thought the model is that you always
> > have one coroutine reading the next request (which is
> > client->recv_coroutine) and all the others are just processing the
> > request they had read earlier. Multiple coroutines reading from the
> > same socket would sound like a bad idea.
> 
> You're right, there's only a single coroutine yielding on
> nbd_read_eof(). I've added the list while at a moment I was trying to
> keep track of every coroutine, and I kept it without thinking if it
> was really needed.
> 
> I'll drop it, entering just client->recv_coroutine is it isn't NULL.

Sounds like I'll wait for the v2 before applying.  But the overall
logic changes made sense to me.

> > The patch looks correct to me, though I'm not sure if yield_co_list is
> > an unnecessary complication (and if it isn't, whether that's safe).
> > 
> > I would be happy enough to apply it anyway if you can explain the
> > yield_co_list thing, but I'll give Eric some time to have a look, too.

Thanks for catching my attention on this!

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH 2/2] nbd/server: Use drained block ops to quiesce the server

2021-06-01 Thread Eric Blake
On Tue, Jun 01, 2021 at 07:57:28AM +0200, Sergio Lopez wrote:
> Before switching between AioContexts we need to make sure that we're
> fully quiesced ("nb_requests == 0" for every client) when entering the
> drained section.
> 
> To do this, we set "quiescing = true" for every client on
> ".drained_begin" to prevent new coroutines to be created, and check if

s/to be created/from being created/

> "nb_requests == 0" on ".drained_poll". Finally, once we're exiting the
> drained section, on ".drained_end" we set "quiescing = false" and
> call "nbd_client_receive_next_request()" to resume the processing of
> new requests.
> 
> With these changes, "blk_aio_attach()" and "blk_aio_detach()" can be
> reverted to be as simple as they were before f148ae7d36.

Is that reversion planned to be patch 3 of your series in v2?

> 
> RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1960137
> Suggested-by: Kevin Wolf 
> Signed-off-by: Sergio Lopez 
> ---
>  nbd/server.c | 99 +++-
>  1 file changed, 75 insertions(+), 24 deletions(-)
> 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v2 02/26] s390x/tcg: Fix instruction name for VECTOR FP LOAD (LENGTHENED|ROUNDED)

2021-06-01 Thread Richard Henderson

On 5/17/21 7:27 AM, David Hildenbrand wrote:

Let's use the correct name.

Signed-off-by: David Hildenbrand
---
  target/s390x/insn-data.def | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH v2 01/26] s390x/tcg: Fix FP CONVERT TO (LOGICAL) FIXED NaN handling

2021-06-01 Thread Richard Henderson

On 5/17/21 7:27 AM, David Hildenbrand wrote:

@@ -634,6 +664,9 @@ uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, 
uint64_t l, uint32_t m34)
 
 s390_restore_bfp_rounding_mode(env, old_mode);

 handle_exceptions(env, xxc_from_m34(m34), GETPC());
+if (float128_is_any_nan(make_float128(h, l))) {
+return 0;
+}


I wonder if handle_exceptions should return s390_exc.
Then you can test

  exc = handle_exceptions(...);
  if (unlikely(exc & S390_IEEE_MASK_INVALID)) {
ret = 0;
  }
  return ret;




+++ b/target/s390x/vec_fpu_helper.c
@@ -326,6 +326,9 @@ void HELPER(gvec_vcdlg64s)(void *v1, const void *v2, 
CPUS390XState *env,
  
  static uint64_t vcgd64(uint64_t a, float_status *s)

  {
+if (float64_is_any_nan(a)) {
+return INT64_MIN;
+}
  return float64_to_int64(a, s);
  }
  
@@ -349,6 +352,9 @@ void HELPER(gvec_vcgd64s)(void *v1, const void *v2, CPUS390XState *env,
  
  static uint64_t vclgd64(uint64_t a, float_status *s)

  {
+if (float64_is_any_nan(a)) {
+return 0;
+}
  return float64_to_uint64(a, s);
  }


You do still need to raise invalid, as far as I can see.


r~



Re: [PATCH 1/2] block-backend: add drained_poll

2021-06-01 Thread Eric Blake
On Tue, Jun 01, 2021 at 05:59:10PM +0200, Kevin Wolf wrote:
> > +++ b/block/block-backend.c
> > @@ -2393,8 +2393,13 @@ static void blk_root_drained_begin(BdrvChild *child)
> >  static bool blk_root_drained_poll(BdrvChild *child)
> >  {
> >  BlockBackend *blk = child->opaque;
> > +int ret = 0;
> 
> It's really a bool.
> 
> >  assert(blk->quiesce_counter);
> > -return !!blk->in_flight;
> > +
> > +if (blk->dev_ops && blk->dev_ops->drained_poll) {
> > +ret = blk->dev_ops->drained_poll(blk->dev_opaque);
> > +}
> > +return ret || !!blk->in_flight;
> >  }
> 
> Doesn't make a difference for correctness, of course, so whether you
> change it or not:
> 
> Reviewed-by: Kevin Wolf 

Likewise, with that cosmetic change,
Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v6 12/14] target/ppc: Implement vcfuged instruction

2021-06-01 Thread Richard Henderson

On 6/1/21 12:35 PM, matheus.fe...@eldorado.org.br wrote:

+++ b/target/ppc/translate/vector-impl.c.inc
@@ -0,0 +1,56 @@
+/*
+ * Power ISA decode for Vector Facility instructions
+ *
+ * Copyright (c) 2021 Instituto de Pesquisas Eldorado (eldorado.org.br)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#define REQUIRE_ALTIVEC(CTX) \
+do {\
+if (unlikely(!(CTX)->altivec_enabled)) {\
+gen_exception((CTX), POWERPC_EXCP_VPU); \
+return true;\
+}   \
+} while (0)


I think it would be better to name this REQUIRE_VECTOR, to match the 
Vector_Unavailable() pseudo-code in the current manual.


Also, I think you should place this in translate.c, because you will also need 
this for VSX.


Otherwise,
Reviewed-by: Richard Henderson 


r~



Re: [PATCH v6 11/14] target/ppc: Implement cfuged instruction

2021-06-01 Thread Richard Henderson

On 6/1/21 12:35 PM, matheus.fe...@eldorado.org.br wrote:

From: Matheus Ferst

Signed-off-by: Matheus Ferst
---
  target/ppc/helper.h|  1 +
  target/ppc/insn32.decode   |  4 ++
  target/ppc/int_helper.c| 62 ++
  target/ppc/translate/fixedpoint-impl.c.inc | 12 +
  4 files changed, 79 insertions(+)


Reviewed-by: Richard Henderson 

r~



Re: [Stratos-dev] [PATCH 3/5] vhost-user-rng: backend: Add RNG vhost-user daemon implementation

2021-06-01 Thread Joakim Bech
On Tue, Jun 01, 2021 at 08:03:20PM +, Mathieu Poirier via Stratos-dev wrote:
> This patch provides the vhost-user backend implementation to work
> in tandem with the vhost-user-rng implementation of the QEMU VMM.
> 
> It uses the vhost-user API so that other VMM can re-use the interface
> without having to write the driver again.
> 
> Signed-off-by: Mathieu Poirier 
> ---
>  tools/meson.build|   8 +
>  tools/vhost-user-rng/50-qemu-rng.json.in |   5 +
>  tools/vhost-user-rng/main.c  | 403 +++
>  tools/vhost-user-rng/meson.build |  10 +
>  4 files changed, 426 insertions(+)
>  create mode 100644 tools/vhost-user-rng/50-qemu-rng.json.in
>  create mode 100644 tools/vhost-user-rng/main.c
>  create mode 100644 tools/vhost-user-rng/meson.build
> 
> diff --git a/tools/meson.build b/tools/meson.build
> index 3e5a0abfa29f..66b0a11fbb45 100644
> --- a/tools/meson.build
> +++ b/tools/meson.build
> @@ -24,3 +24,11 @@ endif
>  if have_virtiofsd
>subdir('virtiofsd')
>  endif
> +
> +have_virtiorng = (have_system and
> +have_tools and
> +'CONFIG_LINUX' in config_host)
> +
> +if have_virtiorng
> +  subdir('vhost-user-rng')
> +endif
> diff --git a/tools/vhost-user-rng/50-qemu-rng.json.in 
> b/tools/vhost-user-rng/50-qemu-rng.json.in
> new file mode 100644
> index ..9186c3c6fe1d
> --- /dev/null
> +++ b/tools/vhost-user-rng/50-qemu-rng.json.in
> @@ -0,0 +1,5 @@
> +{
> +  "description": "QEMU vhost-user-rng",
> +  "type": "bridge",
> +  "binary": "@libexecdir@/vhost-user-rng"
> +}
> diff --git a/tools/vhost-user-rng/main.c b/tools/vhost-user-rng/main.c
> new file mode 100644
> index ..ba7380b12659
> --- /dev/null
> +++ b/tools/vhost-user-rng/main.c
> @@ -0,0 +1,403 @@
> +/*
> + * VIRTIO RNG Emulation via vhost-user
> + *
> + * Copyright (c) 2021 Mathieu Poirier 
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#define G_LOG_DOMAIN "vhost-user-rng"
> +#define G_LOG_USE_STRUCTURED 1
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "qemu/cutils.h"
> +#include "subprojects/libvhost-user/libvhost-user-glib.h"
> +#include "subprojects/libvhost-user/libvhost-user.h"
> +
> +#ifndef container_of
> +#define container_of(ptr, type, member) ({  \
> +const typeof(((type *) 0)->member) * __mptr = (ptr); \
> +(type *) ((char *) __mptr - offsetof(type, member)); })
> +#endif
> +
> +typedef struct {
> +VugDev dev;
> +struct itimerspec ts;
> +timer_t rate_limit_timer;
> +pthread_mutex_t rng_mutex;
> +pthread_cond_t rng_cond;
> +int64_t quota_remaining;
> +bool activate_timer;
> +GMainLoop *loop;
> +} VuRNG;
> +
> +static gboolean print_cap, verbose;
> +static gchar *source_path, *socket_path;
> +static gint source_fd, socket_fd = -1;
> +
> +/* Defaults tailored on virtio-rng.c */
> +static uint32_t period_ms = 1 << 16;
> +static uint64_t max_bytes = INT64_MAX;
> +
> +static void check_rate_limit(union sigval sv)
> +{
> +VuRNG *rng = sv.sival_ptr;
> +bool wakeup = false;
> +
> +pthread_mutex_lock(>rng_mutex);
> +/*
> + * The timer has expired and the guest has used all available
> + * antropy, which means function vu_rng_handle_request() is waiting
s/antropy/entropy/

I also found 'antropy' at two more locations in this patch (that made me
wonder).

> + * on us.  As such wake it up once we're done here.
> + */
> +if (rng->quota_remaining == 0) {
> +wakeup = true;
> +}
> +
> +/*
> + * Reset the antropy available to the guest and tell function
> + * vu_rng_handle_requests() to start the timer before using it.
> + */
> +rng->quota_remaining = max_bytes;
> +rng->activate_timer = true;
> +pthread_mutex_unlock(>rng_mutex);
> +
> +if (wakeup) {
> +pthread_cond_signal(>rng_cond);
> +}
> +}
> +
> +static void setup_timer(VuRNG *rng)
> +{
> +struct sigevent sev;
> +int ret;
> +
> +memset(>ts, 0, sizeof(struct itimerspec));
> +rng->ts.it_value.tv_sec = period_ms / 1000;
> +rng->ts.it_value.tv_nsec = (period_ms % 1000) * 100;
> +
> +/*
> + * Call function check_rate_limit() as if it was the start of
> + * a new thread when the timer expires.
> + */
> +sev.sigev_notify = SIGEV_THREAD;
> +sev.sigev_notify_function = check_rate_limit;
> +sev.sigev_value.sival_ptr = rng;
> +/* Needs to be NULL if defaults attributes are to be used. */
> +sev.sigev_notify_attributes = NULL;
> +ret = timer_create(CLOCK_MONOTONIC, , >rate_limit_timer);
> +if (ret < 0) {
> +fprintf(stderr, "timer_create() failed\n");
> +}
> +
> +}
> +
> +
> +/* Virtio helpers */
> +static uint64_t 

Re: [PATCH v6 14/14] target/ppc: Move cmp/cmpi/cmpl/cmpli to decodetree

2021-06-01 Thread Richard Henderson

On 6/1/21 12:35 PM, matheus.fe...@eldorado.org.br wrote:

--- a/target/ppc/translate/fixedpoint-impl.c.inc
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
@@ -1,4 +1,4 @@
-/*
+/*
   * Power ISA decode for Fixed-Point Facility instructions


Watch the whitespace errors.

Otherwise,
Reviewed-by: Richard Henderson 

r~



Re: [PATCH v3 1/1] yank: Unregister function when using TLS migration

2021-06-01 Thread Leonardo Brás
On Tue, 2021-06-01 at 10:50 -0400, Peter Xu wrote:
> On Tue, Jun 01, 2021 at 02:40:31AM -0300, Leonardo Bras wrote:
> > [...]
> >  inside migration_channel_connect() and
> > migration_channel_process_incoming() move yank_register_function()
> > so
> > it only runs once on a TLS migration.
> 
> Slightly inaccurate I guess, as it was run once too before this
> patch, but not
> paired for tls?

Yeah, I think I got confused over this:
I remembered having multiple instances of yank_register_function()
during TLS migration on qemu.org/master, but after re-testing it, I
think it was in fact something to do with V1 and V2.

So, yes, that's correct, in qemu.org/master there was a single
yank_register_function() and no pairing yank_unregister_function()
during TLS migration. 

> 
> IIUC when we call the 2nd time at below chunk we won't register
> again:
> 
>     if (object_dynamic_cast(OBJECT(ioc),
> TYPE_QIO_CHANNEL_SOCKET)) {
>     yank_register_function(MIGRATION_YANK_INSTANCE,
>    migration_yank_iochannel,
>    QIO_CHANNEL(ioc));
>     }
> 
> Because the 2nd call will be TYPE_QIO_CHANNEL_TLS, so
> object_dynamic_cast()
> will return with a failure, I think (note, TYPE_QIO_CHANNEL_TLS's
> parent is
> TYPE_QIO_CHANNEL, not TYPE_QIO_CHANNEL_SOCKET).
> 
> > 
> > Fixes: b5eea99ec2f ("migration: Add yank feature", 2021-01-13)
> > Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1964326
> > Signed-off-by: Leonardo Bras 
> 
> Reviewed-by: Peter Xu 
> 
> Thanks Leo!

Thank you Peter!






Re: [PATCH] target/ppc: fix single-step exception regression

2021-06-01 Thread Richard Henderson

On 6/1/21 11:02 AM, Luis Pires wrote:

+if (is_jmp == DISAS_EXIT || is_jmp == DISAS_CHAIN) {
+/* We have not updated nip yet, so do it now */
+gen_update_nip(ctx, nip);
+}


This is incorrect.  Both EXIT and CHAIN *have* updated nip, but to something 
that isn't the next instruction.  E.g. return from interrupt.



r~



Re: [PATCH v2 1/2] hw/nvme: add support for boot partiotions

2021-06-01 Thread Keith Busch
On Tue, Jun 01, 2021 at 09:07:56PM +0200, Klaus Jensen wrote:
> On Jun  1 11:07, Keith Busch wrote:
> > On Tue, Jun 01, 2021 at 07:41:34PM +0200, Klaus Jensen wrote:
> > > On Jun  1 10:19, Keith Busch wrote:
> > > > On Tue, Jun 01, 2021 at 08:07:48PM +0530, Gollu Appalanaidu wrote:
> > > > > NVMe Boot Partitions provides an area that may be read by the host
> > > > > without initializing queues or even enabling the controller. This
> > > > > allows various platform initialization code to be stored on the NVMe
> > > > > device instead of some separete medium.
> > > > >
> > > > > This patch adds the read support for such an area, as well as support
> > > > > for updating the boot partition contents from the host through the
> > > > > FW Download and Commit commands.
> > > >
> > > > Please provide some details on what platform initilization sequence
> > > > running on QEMU is going to make use of this feature.
> > > >
> > > 
> > > I totally get your reluctance to accept useless features like device
> > > self-test and ill-supported ones like write uncorrectable.
> > > 
> > > But I think this feature qualifies just fine for the device. It is useful
> > > for embedded development and while there might not be any qemu boards that
> > > wants to use this *right now*, it allows for experimentation. And this is 
> > > a
> > > feature that actually *is* implemented by real products for embedded
> > > systems.
> > 
> > That wasn't my request, though. I am well aware of the feature and also
> > have hardware that implements it. It just sounds like you haven't
> > actually tested this feature under the protocol's intended use cases
> > inside this environment. I think that type of testing and a high level
> > description of it in the changelog ought to be part of acceptance
> > criteria.
> > 
> 
> Alright, I see.
> 
> You'd like to see this tested by defining a new board that loads firmware
> over PCIe from the device?

Yes, something like that.

When the feature was initially published, I took a very brief look at
how qemu could use it and concluded this wasn't very practical here. I
would be happy to know if there's any example platform that can use it,
though. That, to me, demostrates sufficient value.



Re: [PATCH v4] i386: Add ratelimit for bus locks acquired in guest

2021-06-01 Thread Eduardo Habkost
On Tue, Jun 01, 2021 at 02:18:37PM -0400, Eduardo Habkost wrote:
> On Mon, May 31, 2021 at 01:14:54PM +0800, Chenyi Qiang wrote:
> > 
> > 
> > On 5/28/2021 5:19 AM, Eduardo Habkost wrote:
> > > On Fri, May 21, 2021 at 12:38:20PM +0800, Chenyi Qiang wrote:
> > > [...]
> > > > @@ -4222,6 +4247,15 @@ void kvm_arch_pre_run(CPUState *cpu, struct 
> > > > kvm_run *run)
> > > >   }
> > > >   }
> > > > +static void kvm_rate_limit_on_bus_lock(void)
> > > > +{
> > > > +uint64_t delay_ns = 
> > > > ratelimit_calculate_delay(_lock_ratelimit_ctrl, 1);
> > > > +
> > > > +if (delay_ns) {
> > > > +g_usleep(delay_ns / SCALE_US);
> > > > +}
> > > > +}
> > > > +
> > > >   MemTxAttrs kvm_arch_post_run(CPUState *cpu, struct kvm_run *run)
> > > >   {
> > > >   X86CPU *x86_cpu = X86_CPU(cpu);
> > > > @@ -4237,6 +4271,9 @@ MemTxAttrs kvm_arch_post_run(CPUState *cpu, 
> > > > struct kvm_run *run)
> > > >   } else {
> > > >   env->eflags &= ~IF_MASK;
> > > >   }
> > > > +if (run->flags & KVM_RUN_X86_BUS_LOCK) {
> > > 
> > > Does the KVM API guarantee that KVM_RUN_X86_BUS_LOCK will never
> > > be set if KVM_BUS_LOCK_DETECTION_EXIT isn't enabled?  (Otherwise
> > > we risk crashing in ratelimit_calculate_delay() above if rate
> > > limiting is disabled).
> > > 
> > 
> > Yes. KVM_RUN_X86_BUS_LOCK flag is set when bus lock VM exit happens. Bus
> > lock VM exit is disabled by default and can only be enabled through the
> > KVM_BUS_LOCK_DETECTION_EXIT capability.
> 
> I'm queueing on x86-next, thanks!

This breaks the build.  Is there a linux-headers update patch I've missed?

../target/i386/kvm/kvm.c: In function 'kvm_arch_init':
../target/i386/kvm/kvm.c:2322:42: error: 'KVM_CAP_X86_BUS_LOCK_EXIT' undeclared 
(first use in this function); did you mean 'KVM_CAP_X86_DISABLE_EXITS'?
 ret = kvm_check_extension(s, KVM_CAP_X86_BUS_LOCK_EXIT);
  ^
  KVM_CAP_X86_DISABLE_EXITS

-- 
Eduardo




[PATCH 3/5] vhost-user-rng: backend: Add RNG vhost-user daemon implementation

2021-06-01 Thread Mathieu Poirier
This patch provides the vhost-user backend implementation to work
in tandem with the vhost-user-rng implementation of the QEMU VMM.

It uses the vhost-user API so that other VMM can re-use the interface
without having to write the driver again.

Signed-off-by: Mathieu Poirier 
---
 tools/meson.build|   8 +
 tools/vhost-user-rng/50-qemu-rng.json.in |   5 +
 tools/vhost-user-rng/main.c  | 403 +++
 tools/vhost-user-rng/meson.build |  10 +
 4 files changed, 426 insertions(+)
 create mode 100644 tools/vhost-user-rng/50-qemu-rng.json.in
 create mode 100644 tools/vhost-user-rng/main.c
 create mode 100644 tools/vhost-user-rng/meson.build

diff --git a/tools/meson.build b/tools/meson.build
index 3e5a0abfa29f..66b0a11fbb45 100644
--- a/tools/meson.build
+++ b/tools/meson.build
@@ -24,3 +24,11 @@ endif
 if have_virtiofsd
   subdir('virtiofsd')
 endif
+
+have_virtiorng = (have_system and
+have_tools and
+'CONFIG_LINUX' in config_host)
+
+if have_virtiorng
+  subdir('vhost-user-rng')
+endif
diff --git a/tools/vhost-user-rng/50-qemu-rng.json.in 
b/tools/vhost-user-rng/50-qemu-rng.json.in
new file mode 100644
index ..9186c3c6fe1d
--- /dev/null
+++ b/tools/vhost-user-rng/50-qemu-rng.json.in
@@ -0,0 +1,5 @@
+{
+  "description": "QEMU vhost-user-rng",
+  "type": "bridge",
+  "binary": "@libexecdir@/vhost-user-rng"
+}
diff --git a/tools/vhost-user-rng/main.c b/tools/vhost-user-rng/main.c
new file mode 100644
index ..ba7380b12659
--- /dev/null
+++ b/tools/vhost-user-rng/main.c
@@ -0,0 +1,403 @@
+/*
+ * VIRTIO RNG Emulation via vhost-user
+ *
+ * Copyright (c) 2021 Mathieu Poirier 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#define G_LOG_DOMAIN "vhost-user-rng"
+#define G_LOG_USE_STRUCTURED 1
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "qemu/cutils.h"
+#include "subprojects/libvhost-user/libvhost-user-glib.h"
+#include "subprojects/libvhost-user/libvhost-user.h"
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({  \
+const typeof(((type *) 0)->member) * __mptr = (ptr); \
+(type *) ((char *) __mptr - offsetof(type, member)); })
+#endif
+
+typedef struct {
+VugDev dev;
+struct itimerspec ts;
+timer_t rate_limit_timer;
+pthread_mutex_t rng_mutex;
+pthread_cond_t rng_cond;
+int64_t quota_remaining;
+bool activate_timer;
+GMainLoop *loop;
+} VuRNG;
+
+static gboolean print_cap, verbose;
+static gchar *source_path, *socket_path;
+static gint source_fd, socket_fd = -1;
+
+/* Defaults tailored on virtio-rng.c */
+static uint32_t period_ms = 1 << 16;
+static uint64_t max_bytes = INT64_MAX;
+
+static void check_rate_limit(union sigval sv)
+{
+VuRNG *rng = sv.sival_ptr;
+bool wakeup = false;
+
+pthread_mutex_lock(>rng_mutex);
+/*
+ * The timer has expired and the guest has used all available
+ * antropy, which means function vu_rng_handle_request() is waiting
+ * on us.  As such wake it up once we're done here.
+ */
+if (rng->quota_remaining == 0) {
+wakeup = true;
+}
+
+/*
+ * Reset the antropy available to the guest and tell function
+ * vu_rng_handle_requests() to start the timer before using it.
+ */
+rng->quota_remaining = max_bytes;
+rng->activate_timer = true;
+pthread_mutex_unlock(>rng_mutex);
+
+if (wakeup) {
+pthread_cond_signal(>rng_cond);
+}
+}
+
+static void setup_timer(VuRNG *rng)
+{
+struct sigevent sev;
+int ret;
+
+memset(>ts, 0, sizeof(struct itimerspec));
+rng->ts.it_value.tv_sec = period_ms / 1000;
+rng->ts.it_value.tv_nsec = (period_ms % 1000) * 100;
+
+/*
+ * Call function check_rate_limit() as if it was the start of
+ * a new thread when the timer expires.
+ */
+sev.sigev_notify = SIGEV_THREAD;
+sev.sigev_notify_function = check_rate_limit;
+sev.sigev_value.sival_ptr = rng;
+/* Needs to be NULL if defaults attributes are to be used. */
+sev.sigev_notify_attributes = NULL;
+ret = timer_create(CLOCK_MONOTONIC, , >rate_limit_timer);
+if (ret < 0) {
+fprintf(stderr, "timer_create() failed\n");
+}
+
+}
+
+
+/* Virtio helpers */
+static uint64_t rng_get_features(VuDev *dev)
+{
+if (verbose) {
+g_info("%s: replying", __func__);
+}
+return 0;
+}
+
+static void rng_set_features(VuDev *dev, uint64_t features)
+{
+if (verbose && features) {
+g_autoptr(GString) s = g_string_new("Requested un-handled feature");
+g_string_append_printf(s, " 0x%" PRIx64 "", features);
+g_info("%s: %s", __func__, s->str);
+}
+}
+
+static void vu_rng_handle_requests(VuDev *dev, int qidx)
+{
+VuRNG *rng = container_of(dev, VuRNG, dev.parent);

[PATCH 4/5] docs: Add documentation for vhost based RNG implementation

2021-06-01 Thread Mathieu Poirier
Add description and example for the vhost-user based RNG implementation.
Tailored on Viresh Kumar's vhost-user-i2c documentation.

Signed-off-by: Mathieu Poirier 
---
 docs/tools/vhost-user-rng.rst | 74 +++
 1 file changed, 74 insertions(+)
 create mode 100644 docs/tools/vhost-user-rng.rst

diff --git a/docs/tools/vhost-user-rng.rst b/docs/tools/vhost-user-rng.rst
new file mode 100644
index ..7f69d7bb3c58
--- /dev/null
+++ b/docs/tools/vhost-user-rng.rst
@@ -0,0 +1,74 @@
+QEMU vhost-user-rng - RNG emulation backend
+===
+
+Synopsis
+
+
+**vhost-user-rng** [*OPTIONS*]
+
+Description
+---
+
+This program is a vhost-user backend that emulates a VirtIO random number
+generator (RNG).  It uses the host's random number generator pool,
+/dev/urandom by default but configurable at will, to satisfy requests from
+guests.
+
+This program is designed to work with QEMU's ``-device
+vhost-user-rng-pci`` but should work with any virtual machine monitor
+(VMM) that supports vhost-user. See the Examples section below.
+
+Options
+---
+
+.. program:: vhost-user-rng
+
+.. option:: -h, --help
+
+  Print help.
+
+.. option:: -v, --verbose
+
+   Increase verbosity of output
+
+.. option:: -s, --socket-path=PATH
+
+  Listen on vhost-user UNIX domain socket at PATH. Incompatible with --fd.
+
+.. option:: -f, --fd=FDNUM
+
+  Accept connections from vhost-user UNIX domain socket file descriptor FDNUM.
+  The file descriptor must already be listening for connections.
+  Incompatible with --socket-path.
+
+.. option:: -p, --period
+
+  Rate, in milliseconds, at which the RNG hardware can generate random data.
+  Used in conjunction with the --max-bytes option.
+
+.. option:: -m, --max-bytes
+
+  In conjuction with the --period parameter, provides the maximum number of 
byte
+  per milliseconds a RNG device can generate.
+
+Examples
+
+
+The daemon should be started first:
+
+::
+
+  host# vhost-user-rng --socket-path=rng.sock --period=1000 --max-bytes=4096
+
+The QEMU invocation needs to create a chardev socket the device can
+use to communicate as well as share the guests memory over a memfd.
+
+::
+
+  host# qemu-system
\
+  -chardev socket,path=$(PATH)/rng.sock,id=rng0
\
+  -device vhost-user-rng-pci,chardev=rng0  
\
+  -m 4096  
\
+  -object memory-backend-file,id=mem,size=4G,mem-path=/dev/shm,share=on
\
+  -numa node,memdev=mem
\
+  ...
-- 
2.25.1




[PATCH 5/5] MAINTAINERS: Add maintainer for vhost-user RNG implementation

2021-06-01 Thread Mathieu Poirier
This patch adds entry for the vhost-user-rng related files.

Signed-off-by: Mathieu Poirier 
---
 MAINTAINERS | 9 +
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 5f55404f2fae..6a0d61443571 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1937,6 +1937,15 @@ F: include/sysemu/rng*.h
 F: backends/rng*.c
 F: tests/qtest/virtio-rng-test.c
 
+vhost-user-rng
+M: Mathieu Poirier 
+S: Supported
+F: docs/tools/vhost-user-rng.rst
+F: hw/virtio/vhost-user-rng.c
+F: hw/virtio/vhost-user-rng-pci.c
+F: include/hw/virtio/vhost-user-rng.h
+F: tools/vhost-user-rng/*
+
 virtio-crypto
 M: Gonglei 
 S: Supported
-- 
2.25.1




[PATCH 2/5] vhost-user-rng-pci: Add vhost-user-rng-pci implementation

2021-06-01 Thread Mathieu Poirier
This patch provides a PCI bus interface to the vhost-user-rng backed.
The implentation is similar to what was done for vhost-user-i2c-pci and
vhost-user-fs-pci.

Signed-off-by: Mathieu Poirier 
---
 hw/virtio/meson.build  |  1 +
 hw/virtio/vhost-user-rng-pci.c | 79 ++
 2 files changed, 80 insertions(+)
 create mode 100644 hw/virtio/vhost-user-rng-pci.c

diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index e386791f2a05..1430b370e64d 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -26,6 +26,7 @@ virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: 
files('virtio-rng.c'))
 virtio_ss.add(when: 'CONFIG_VIRTIO_IOMMU', if_true: files('virtio-iommu.c'))
 virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c'))
 virtio_ss.add(when: 'CONFIG_VHOST_USER_RNG', if_true: 
files('vhost-user-rng.c'))
+virtio_ss.add(when: ['CONFIG_VHOST_USER_RNG', 'CONFIG_VIRTIO_PCI'], if_true: 
files('vhost-user-rng-pci.c'))
 
 virtio_pci_ss = ss.source_set()
 virtio_pci_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: 
files('vhost-vsock-pci.c'))
diff --git a/hw/virtio/vhost-user-rng-pci.c b/hw/virtio/vhost-user-rng-pci.c
new file mode 100644
index ..2de39fd4
--- /dev/null
+++ b/hw/virtio/vhost-user-rng-pci.c
@@ -0,0 +1,79 @@
+/*
+ * Vhost-user RNG virtio device PCI glue
+ *
+ * Copyright (c) 2021 Mathieu Poirier 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/qdev-properties.h"
+#include "hw/virtio/vhost-user-rng.h"
+#include "virtio-pci.h"
+
+struct VHostUserRNGPCI {
+VirtIOPCIProxy parent_obj;
+VHostUserRNG vdev;
+};
+
+typedef struct VHostUserRNGPCI VHostUserRNGPCI;
+
+#define TYPE_VHOST_USER_RNG_PCI "vhost-user-rng-pci-base"
+
+DECLARE_INSTANCE_CHECKER(VHostUserRNGPCI, VHOST_USER_RNG_PCI,
+ TYPE_VHOST_USER_RNG_PCI)
+
+static Property vhost_user_rng_pci_properties[] = {
+DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
+   DEV_NVECTORS_UNSPECIFIED),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void vhost_user_rng_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
+{
+VHostUserRNGPCI *dev = VHOST_USER_RNG_PCI(vpci_dev);
+DeviceState *vdev = DEVICE(>vdev);
+
+if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
+vpci_dev->nvectors = 1;
+}
+
+qdev_realize(vdev, BUS(_dev->bus), errp);
+}
+
+static void vhost_user_rng_pci_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
+PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
+k->realize = vhost_user_rng_pci_realize;
+set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
+device_class_set_props(dc, vhost_user_rng_pci_properties);
+pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+pcidev_k->device_id = 0; /* Set by virtio-pci based on virtio id */
+pcidev_k->revision = 0x00;
+pcidev_k->class_id = PCI_CLASS_COMMUNICATION_OTHER;
+}
+
+static void vhost_user_rng_pci_instance_init(Object *obj)
+{
+VHostUserRNGPCI *dev = VHOST_USER_RNG_PCI(obj);
+
+virtio_instance_init_common(obj, >vdev, sizeof(dev->vdev),
+TYPE_VHOST_USER_RNG);
+}
+
+static const VirtioPCIDeviceTypeInfo vhost_user_rng_pci_info = {
+.base_name = TYPE_VHOST_USER_RNG_PCI,
+.non_transitional_name = "vhost-user-rng-pci",
+.instance_size = sizeof(VHostUserRNGPCI),
+.instance_init = vhost_user_rng_pci_instance_init,
+.class_init = vhost_user_rng_pci_class_init,
+};
+
+static void vhost_user_rng_pci_register(void)
+{
+virtio_pci_types_register(_user_rng_pci_info);
+}
+
+type_init(vhost_user_rng_pci_register);
-- 
2.25.1




[PATCH 1/5] vhost-user-rng: Add vhost-user-rng implementation

2021-06-01 Thread Mathieu Poirier
Following in the footsteps of what whas done for vhost-user-i2c
and virtiofsd, introduce a random number generator (RNG) backend
that communicates with a vhost-user server to retrieve entropy.
That way another VMM could be using the same vhost-user daemon and
avoid having to write yet another RNG driver.

Signed-off-by: Mathieu Poirier 
---
 hw/virtio/Kconfig  |   5 +
 hw/virtio/meson.build  |   1 +
 hw/virtio/vhost-user-rng.c | 294 +
 include/hw/virtio/vhost-user-rng.h |  33 
 4 files changed, 333 insertions(+)
 create mode 100644 hw/virtio/vhost-user-rng.c
 create mode 100644 include/hw/virtio/vhost-user-rng.h

diff --git a/hw/virtio/Kconfig b/hw/virtio/Kconfig
index 0eda25c4e1bf..69066ab14e6d 100644
--- a/hw/virtio/Kconfig
+++ b/hw/virtio/Kconfig
@@ -58,3 +58,8 @@ config VIRTIO_MEM
 depends on LINUX
 depends on VIRTIO_MEM_SUPPORTED
 select MEM_DEVICE
+
+config VHOST_USER_RNG
+bool
+default y
+depends on VIRTIO && VHOST_USER
diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index fbff9bc9d4de..e386791f2a05 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -25,6 +25,7 @@ virtio_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: 
files('vhost-user-vsock.
 virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng.c'))
 virtio_ss.add(when: 'CONFIG_VIRTIO_IOMMU', if_true: files('virtio-iommu.c'))
 virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c'))
+virtio_ss.add(when: 'CONFIG_VHOST_USER_RNG', if_true: 
files('vhost-user-rng.c'))
 
 virtio_pci_ss = ss.source_set()
 virtio_pci_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: 
files('vhost-vsock-pci.c'))
diff --git a/hw/virtio/vhost-user-rng.c b/hw/virtio/vhost-user-rng.c
new file mode 100644
index ..78447e8d3791
--- /dev/null
+++ b/hw/virtio/vhost-user-rng.c
@@ -0,0 +1,294 @@
+/*
+ * Vhost-user RNG virtio device
+ *
+ * Copyright (c) 2021 Mathieu Poirier 
+ *
+ * Implementation seriously tailored on vhost-user-i2c.c
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/qdev-properties.h"
+#include "hw/virtio/virtio-bus.h"
+#include "hw/virtio/vhost-user-rng.h"
+#include "qemu/error-report.h"
+#include "standard-headers/linux/virtio_ids.h"
+
+static void vu_rng_start(VirtIODevice *vdev)
+{
+VHostUserRNG *rng = VHOST_USER_RNG(vdev);
+BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
+VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
+int ret;
+int i;
+
+if (!k->set_guest_notifiers) {
+error_report("binding does not support guest notifiers");
+return;
+}
+
+ret = vhost_dev_enable_notifiers(>vhost_dev, vdev);
+if (ret < 0) {
+error_report("Error enabling host notifiers: %d", -ret);
+return;
+}
+
+ret = k->set_guest_notifiers(qbus->parent, rng->vhost_dev.nvqs, true);
+if (ret < 0) {
+error_report("Error binding guest notifier: %d", -ret);
+goto err_host_notifiers;
+}
+
+rng->vhost_dev.acked_features = vdev->guest_features;
+ret = vhost_dev_start(>vhost_dev, vdev);
+if (ret < 0) {
+error_report("Error starting vhost-user-rng: %d", -ret);
+goto err_guest_notifiers;
+}
+
+/*
+ * guest_notifier_mask/pending not used yet, so just unmask
+ * everything here. virtio-pci will do the right thing by
+ * enabling/disabling irqfd.
+ */
+for (i = 0; i < rng->vhost_dev.nvqs; i++) {
+vhost_virtqueue_mask(>vhost_dev, vdev, i, false);
+}
+
+return;
+
+err_guest_notifiers:
+k->set_guest_notifiers(qbus->parent, rng->vhost_dev.nvqs, false);
+err_host_notifiers:
+vhost_dev_disable_notifiers(>vhost_dev, vdev);
+}
+
+static void vu_rng_stop(VirtIODevice *vdev)
+{
+VHostUserRNG *rng = VHOST_USER_RNG(vdev);
+BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
+VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
+int ret;
+
+if (!k->set_guest_notifiers) {
+return;
+}
+
+vhost_dev_stop(>vhost_dev, vdev);
+
+ret = k->set_guest_notifiers(qbus->parent, rng->vhost_dev.nvqs, false);
+if (ret < 0) {
+error_report("vhost guest notifier cleanup failed: %d", ret);
+return;
+}
+
+vhost_dev_disable_notifiers(>vhost_dev, vdev);
+}
+
+static void vu_rng_set_status(VirtIODevice *vdev, uint8_t status)
+{
+VHostUserRNG *rng = VHOST_USER_RNG(vdev);
+bool should_start = status & VIRTIO_CONFIG_S_DRIVER_OK;
+
+if (!vdev->vm_running) {
+should_start = false;
+}
+
+if (rng->vhost_dev.started == should_start) {
+return;
+}
+
+if (should_start) {
+vu_rng_start(vdev);
+} else {
+vu_rng_stop(vdev);
+}
+}
+
+static uint64_t vu_rng_get_features(VirtIODevice *vdev,
+uint64_t requested_features, Error **errp)
+{
+/* No feature bits used yet */
+

[PATCH 0/5] virtio: Add vhost-user based RNG service

2021-06-01 Thread Mathieu Poirier
Hi all,

This sets adds a vhost-user based random number generator (RNG),
similar to what has been done for i2c and virtiofsd.  In fact
the implementation for vhost-user-rng and vhost-user-rng-pci
follow what was done for vhost-user-i2c.

Applies cleanly to git://git.qemu.org/qemu.git master (52848929b70d).

Regards,
Mathieu

Mathieu Poirier (5):
  vhost-user-rng: Add vhost-user-rng implementation
  vhost-user-rng-pci: Add vhost-user-rng-pci implementation
  vhost-user-rng: backend: Add RNG vhost-user daemon implementation
  docs: Add documentation for vhost based RNG implementation
  MAINTAINERS: Add maintainer for vhost-user RNG implementation

 MAINTAINERS  |   9 +
 docs/tools/vhost-user-rng.rst|  74 +
 hw/virtio/Kconfig|   5 +
 hw/virtio/meson.build|   2 +
 hw/virtio/vhost-user-rng-pci.c   |  79 +
 hw/virtio/vhost-user-rng.c   | 294 +
 include/hw/virtio/vhost-user-rng.h   |  33 ++
 tools/meson.build|   8 +
 tools/vhost-user-rng/50-qemu-rng.json.in |   5 +
 tools/vhost-user-rng/main.c  | 403 +++
 tools/vhost-user-rng/meson.build |  10 +
 11 files changed, 922 insertions(+)
 create mode 100644 docs/tools/vhost-user-rng.rst
 create mode 100644 hw/virtio/vhost-user-rng-pci.c
 create mode 100644 hw/virtio/vhost-user-rng.c
 create mode 100644 include/hw/virtio/vhost-user-rng.h
 create mode 100644 tools/vhost-user-rng/50-qemu-rng.json.in
 create mode 100644 tools/vhost-user-rng/main.c
 create mode 100644 tools/vhost-user-rng/meson.build

-- 
2.25.1




[PATCH v6 14/14] target/ppc: Move cmp/cmpi/cmpl/cmpli to decodetree

2021-06-01 Thread matheus . ferst
From: Matheus Ferst 

Additionally, REQUIRE_64BIT when L=1 to match what is specified in The
Programming Environments Manual:

"For 32-bit implementations, the L field must be cleared, otherwise the
instruction form is invalid."

Some CPUs are known to deviate from this specification by ignoring the
L bit [1]. The stricter behavior, however, can help users that test
software with qemu, making it more likely to detect bugs that would
otherwise be silent.

If deemed necessary, a future patch can adapt this behavior based on
the specific CPU model.

[1] The 601 manual is the only one I've found that explicitly states
that the L bit is ignored, but we also observe this behavior in a 7447A
v1.2.

Signed-off-by: Matheus Ferst 
---
 target/ppc/insn32.decode   | 14 ++
 target/ppc/translate.c | 52 --
 target/ppc/translate/fixedpoint-impl.c.inc | 33 +-
 3 files changed, 46 insertions(+), 53 deletions(-)

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 93e5d44d9e..9fd8d6b817 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -20,6 +20,10 @@
   rt ra si:int64_t
 @D  .. rt:5 ra:5 si:s16 
 
+_bf   bf l:bool ra imm
+@D_bfs  .. bf:3 - l:1 ra:5 imm:s16  _bf
+@D_bfu  .. bf:3 - l:1 ra:5 imm:16   _bf
+
 %ds_si  2:s14  !function=times_4
 @DS .. rt:5 ra:5 .. ..   si=%ds_si
 
@@ -36,6 +40,9 @@
 _bi   rt bi
 @X_bi   .. rt:5 bi:5 - .. - _bi
 
+_bfl  bf l:bool ra rb
+@X_bfl  .. bf:3 - l:1 ra:5 rb:5 ..- _bfl
+
 ### Fixed-Point Load Instructions
 
 LBZ 100010 . .  @D
@@ -89,6 +96,13 @@ STDU10 . . ..01 @DS
 STDX01 . . . 0010010101 -   @X
 STDUX   01 . . . 0010110101 -   @X
 
+### Fixed-Point Compare Instructions
+
+CMP 01 ... - . . . 00 - @X_bfl
+CMPL01 ... - . . . 10 - @X_bfl
+CMPI001011 ... - . .    @D_bfs
+CMPLI   001010 ... - . .    @D_bfu
+
 ### Fixed-Point Arithmetic Instructions
 
 ADDI001110 . .  @D
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 35d8831d44..95e4d9b815 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -1489,54 +1489,6 @@ static inline void gen_set_Rc0(DisasContext *ctx, TCGv 
reg)
 }
 }
 
-/* cmp */
-static void gen_cmp(DisasContext *ctx)
-{
-if ((ctx->opcode & 0x0020) && (ctx->insns_flags & PPC_64B)) {
-gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
-   1, crfD(ctx->opcode));
-} else {
-gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
- 1, crfD(ctx->opcode));
-}
-}
-
-/* cmpi */
-static void gen_cmpi(DisasContext *ctx)
-{
-if ((ctx->opcode & 0x0020) && (ctx->insns_flags & PPC_64B)) {
-gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
-1, crfD(ctx->opcode));
-} else {
-gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
-  1, crfD(ctx->opcode));
-}
-}
-
-/* cmpl */
-static void gen_cmpl(DisasContext *ctx)
-{
-if ((ctx->opcode & 0x0020) && (ctx->insns_flags & PPC_64B)) {
-gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
-   0, crfD(ctx->opcode));
-} else {
-gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
- 0, crfD(ctx->opcode));
-}
-}
-
-/* cmpli */
-static void gen_cmpli(DisasContext *ctx)
-{
-if ((ctx->opcode & 0x0020) && (ctx->insns_flags & PPC_64B)) {
-gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
-0, crfD(ctx->opcode));
-} else {
-gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
-  0, crfD(ctx->opcode));
-}
-}
-
 /* cmprb - range comparison: isupper, isaplha, islower*/
 static void gen_cmprb(DisasContext *ctx)
 {
@@ -7639,10 +7591,6 @@ GEN_HANDLER_E(brw, 0x1F, 0x1B, 0x04, 0xF801, 
PPC_NONE, PPC2_ISA310),
 GEN_HANDLER_E(brh, 0x1F, 0x1B, 0x06, 0xF801, PPC_NONE, PPC2_ISA310),
 #endif
 GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0x, PPC_NONE),
-GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x0040, PPC_INTEGER),
-GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x0040, PPC_INTEGER),
-GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x0041, PPC_INTEGER),
-GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x0040, PPC_INTEGER),
 #if defined(TARGET_PPC64)
 GEN_HANDLER_E(cmpeqb, 0x1F, 0x00, 0x07, 0x0060, PPC_NONE, PPC2_ISA300),
 #endif
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc 

[PATCH v6 13/14] target/ppc: Move addpcis to decodetree

2021-06-01 Thread matheus . ferst
From: Matheus Ferst 

Reviewed-by: Richard Henderson 
Signed-off-by: Matheus Ferst 
---
 target/ppc/insn32.decode   | 6 ++
 target/ppc/translate.c | 9 -
 target/ppc/translate/fixedpoint-impl.c.inc | 7 +++
 3 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 77edf407ab..93e5d44d9e 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -23,6 +23,10 @@
 %ds_si  2:s14  !function=times_4
 @DS .. rt:5 ra:5 .. ..   si=%ds_si
 
+ rt d
+%dx_d   6:s10 16:5 0:1
+@DX .. rt:5  . .. . .d=%dx_d
+
  vrt vra vrb
 @VX .. vrt:5 vra:5 vrb:5 .. .   
 
@@ -90,6 +94,8 @@ STDUX   01 . . . 0010110101 -   @X
 ADDI001110 . .  @D
 ADDIS   00 . .  @D
 
+ADDPCIS 010011 . . .. 00010 .   @DX
+
 ## Fixed-Point Logical Instructions
 
 CFUGED  01 . . . 0011011100 -   @X
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index ed5515f8e2..35d8831d44 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -1779,14 +1779,6 @@ static void gen_addic_(DisasContext *ctx)
 gen_op_addic(ctx, 1);
 }
 
-/* addpcis */
-static void gen_addpcis(DisasContext *ctx)
-{
-target_long d = DX(ctx->opcode);
-
-tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], ctx->base.pc_next + (d << 16));
-}
-
 static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
  TCGv arg2, int sign, int compute_ov)
 {
@@ -7659,7 +7651,6 @@ GEN_HANDLER_E(cmprb, 0x1F, 0x00, 0x06, 0x0041, 
PPC_NONE, PPC2_ISA300),
 GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x0001, PPC_ISEL),
 GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x, PPC_INTEGER),
 GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x, PPC_INTEGER),
-GEN_HANDLER_E(addpcis, 0x13, 0x2, 0xFF, 0x, PPC_NONE, PPC2_ISA300),
 GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x0400, PPC_INTEGER),
 GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x0400, PPC_INTEGER),
 GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x, PPC_INTEGER),
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc 
b/target/ppc/translate/fixedpoint-impl.c.inc
index 50933a3b9d..2713366791 100644
--- a/target/ppc/translate/fixedpoint-impl.c.inc
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
@@ -194,6 +194,13 @@ static bool trans_ADDIS(DisasContext *ctx, arg_D *a)
 return trans_ADDI(ctx, a);
 }
 
+static bool trans_ADDPCIS(DisasContext *ctx, arg_DX *a)
+{
+REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+tcg_gen_movi_tl(cpu_gpr[a->rt], ctx->base.pc_next + (a->d << 16));
+return true;
+}
+
 static bool trans_INVALID(DisasContext *ctx, arg_INVALID *a)
 {
 gen_invalid(ctx);
-- 
2.25.1




[PATCH v6 11/14] target/ppc: Implement cfuged instruction

2021-06-01 Thread matheus . ferst
From: Matheus Ferst 

Signed-off-by: Matheus Ferst 
---
 target/ppc/helper.h|  1 +
 target/ppc/insn32.decode   |  4 ++
 target/ppc/int_helper.c| 62 ++
 target/ppc/translate/fixedpoint-impl.c.inc | 12 +
 4 files changed, 79 insertions(+)

diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index ea9f2a236c..c517b9f025 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -46,6 +46,7 @@ DEF_HELPER_4(divwe, tl, env, tl, tl, i32)
 DEF_HELPER_FLAGS_1(popcntb, TCG_CALL_NO_RWG_SE, tl, tl)
 DEF_HELPER_FLAGS_2(cmpb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
 DEF_HELPER_3(sraw, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(cfuged, TCG_CALL_NO_RWG_SE, i64, i64, i64)
 #if defined(TARGET_PPC64)
 DEF_HELPER_FLAGS_2(cmpeqb, TCG_CALL_NO_RWG_SE, i32, tl, tl)
 DEF_HELPER_FLAGS_1(popcntw, TCG_CALL_NO_RWG_SE, tl, tl)
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index bc69c70493..d4044d9069 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -87,6 +87,10 @@ STDUX   01 . . . 0010110101 -   @X
 ADDI001110 . .  @D
 ADDIS   00 . .  @D
 
+## Fixed-Point Logical Instructions
+
+CFUGED  01 . . . 0011011100 -   @X
+
 ### Move To/From System Register Instructions
 
 SETBC   01 . . - 011000 -   @X_bi
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index 41f8477d4b..efa833ef64 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -320,6 +320,68 @@ target_ulong helper_popcntb(target_ulong val)
 }
 #endif
 
+uint64_t helper_cfuged(uint64_t src, uint64_t mask)
+{
+/*
+ * Instead of processing the mask bit-by-bit from the most significant to
+ * the least significant bit, as described in PowerISA, we'll handle it in
+ * blocks of 'n' zeros/ones from LSB to MSB. To avoid the decision to use
+ * ctz or cto, we negate the mask at the end of the loop.
+ */
+target_ulong m, left = 0, right = 0;
+unsigned int n, i = 64;
+bool bit = false; /* tracks if we are processing zeros or ones */
+
+if (mask == 0 || mask == -1) {
+return src;
+}
+
+/* Processes the mask in blocks, from LSB to MSB */
+while (i) {
+/* Find how many bits we should take */
+n = ctz64(mask);
+if (n > i) {
+n = i;
+}
+
+/*
+ * Extracts 'n' trailing bits of src and put them on the leading 'n'
+ * bits of 'right' or 'left', pushing down the previously extracted
+ * values.
+ */
+m = (1ll << n) - 1;
+if (bit) {
+right = ror64(right | (src & m), n);
+} else {
+left = ror64(left | (src & m), n);
+}
+
+/*
+ * Discards the processed bits from 'src' and 'mask'. Note that we are
+ * removing 'n' trailing zeros from 'mask', but the logical shift will
+ * add 'n' leading zeros back, so the population count of 'mask' is 
kept
+ * the same.
+ */
+src >>= n;
+mask >>= n;
+i -= n;
+bit = !bit;
+mask = ~mask;
+}
+
+/*
+ * At the end, right was ror'ed ctpop(mask) times. To put it back in place,
+ * we'll shift it more 64-ctpop(mask) times.
+ */
+if (bit) {
+n = ctpop64(mask);
+} else {
+n = 64 - ctpop64(mask);
+}
+
+return left | (right >> n);
+}
+
 /*/
 /* PowerPC 601 specific instructions (POWER bridge) */
 target_ulong helper_div(CPUPPCState *env, target_ulong arg1, target_ulong arg2)
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc 
b/target/ppc/translate/fixedpoint-impl.c.inc
index 5f9845fa40..50933a3b9d 100644
--- a/target/ppc/translate/fixedpoint-impl.c.inc
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
@@ -227,3 +227,15 @@ TRANS(SETBC, do_set_bool_cond, false, false)
 TRANS(SETBCR, do_set_bool_cond, false, true)
 TRANS(SETNBC, do_set_bool_cond, true, false)
 TRANS(SETNBCR, do_set_bool_cond, true, true)
+
+static bool trans_CFUGED(DisasContext *ctx, arg_X *a)
+{
+REQUIRE_64BIT(ctx);
+REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+#if defined(TARGET_PPC64)
+gen_helper_cfuged(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
+#else
+qemu_build_not_reached();
+#endif
+return true;
+}
-- 
2.25.1




[PATCH v6 12/14] target/ppc: Implement vcfuged instruction

2021-06-01 Thread matheus . ferst
From: Matheus Ferst 

Signed-off-by: Matheus Ferst 
---
 target/ppc/insn32.decode   |  7 
 target/ppc/translate.c |  1 +
 target/ppc/translate/vector-impl.c.inc | 56 ++
 3 files changed, 64 insertions(+)
 create mode 100644 target/ppc/translate/vector-impl.c.inc

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index d4044d9069..77edf407ab 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -23,6 +23,9 @@
 %ds_si  2:s14  !function=times_4
 @DS .. rt:5 ra:5 .. ..   si=%ds_si
 
+ vrt vra vrb
+@VX .. vrt:5 vra:5 vrb:5 .. .   
+
   rt ra rb
 @X  .. rt:5 ra:5 rb:5 .. .  
 
@@ -97,3 +100,7 @@ SETBC   01 . . - 011000 -   @X_bi
 SETBCR  01 . . - 011010 -   @X_bi
 SETNBC  01 . . - 011100 -   @X_bi
 SETNBCR 01 . . - 00 -   @X_bi
+
+## Vector Bit Manipulation Instruction
+
+VCFUGED 000100 . . . 10101001101@VX
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 3c3cb1b664..ed5515f8e2 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -7538,6 +7538,7 @@ static int times_4(DisasContext *ctx, int x)
 #include "translate/vmx-impl.c.inc"
 
 #include "translate/vsx-impl.c.inc"
+#include "translate/vector-impl.c.inc"
 
 #include "translate/dfp-impl.c.inc"
 
diff --git a/target/ppc/translate/vector-impl.c.inc 
b/target/ppc/translate/vector-impl.c.inc
new file mode 100644
index 00..117ce9b137
--- /dev/null
+++ b/target/ppc/translate/vector-impl.c.inc
@@ -0,0 +1,56 @@
+/*
+ * Power ISA decode for Vector Facility instructions
+ *
+ * Copyright (c) 2021 Instituto de Pesquisas Eldorado (eldorado.org.br)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#define REQUIRE_ALTIVEC(CTX) \
+do {\
+if (unlikely(!(CTX)->altivec_enabled)) {\
+gen_exception((CTX), POWERPC_EXCP_VPU); \
+return true;\
+}   \
+} while (0)
+
+static bool trans_VCFUGED(DisasContext *ctx, arg_VX *a)
+{
+TCGv_i64 tgt, src, mask;
+
+REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+REQUIRE_ALTIVEC(ctx);
+
+tgt = tcg_temp_new_i64();
+src = tcg_temp_new_i64();
+mask = tcg_temp_new_i64();
+
+/* centrifuge lower double word */
+get_cpu_vsrl(src, a->vra + 32);
+get_cpu_vsrl(mask, a->vrb + 32);
+gen_helper_cfuged(tgt, src, mask);
+set_cpu_vsrl(a->vrt + 32, tgt);
+
+/* centrifuge higher double word */
+get_cpu_vsrh(src, a->vra + 32);
+get_cpu_vsrh(mask, a->vrb + 32);
+gen_helper_cfuged(tgt, src, mask);
+set_cpu_vsrh(a->vrt + 32, tgt);
+
+tcg_temp_free_i64(tgt);
+tcg_temp_free_i64(src);
+tcg_temp_free_i64(mask);
+
+return true;
+}
-- 
2.25.1




[PATCH v6 10/14] target/ppc: Implement setbc/setbcr/stnbc/setnbcr instructions

2021-06-01 Thread matheus . ferst
From: Matheus Ferst 

Implements the following PowerISA v3.1 instructions:
setbc: Set Boolean Condition
setbcr: Set Boolean Condition Reverse
setnbc: Set Negative Boolean Condition
setnbcr: Set Negative Boolean Condition Reverse

Signed-off-by: Matheus Ferst 
---
 target/ppc/insn32.decode   | 10 ++
 target/ppc/translate/fixedpoint-impl.c.inc | 23 ++
 2 files changed, 33 insertions(+)

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 00ec0f4328..bc69c70493 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -26,6 +26,9 @@
   rt ra rb
 @X  .. rt:5 ra:5 rb:5 .. .  
 
+_bi   rt bi
+@X_bi   .. rt:5 bi:5 - .. - _bi
+
 ### Fixed-Point Load Instructions
 
 LBZ 100010 . .  @D
@@ -83,3 +86,10 @@ STDUX   01 . . . 0010110101 -   @X
 
 ADDI001110 . .  @D
 ADDIS   00 . .  @D
+
+### Move To/From System Register Instructions
+
+SETBC   01 . . - 011000 -   @X_bi
+SETBCR  01 . . - 011010 -   @X_bi
+SETNBC  01 . . - 011100 -   @X_bi
+SETNBCR 01 . . - 00 -   @X_bi
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc 
b/target/ppc/translate/fixedpoint-impl.c.inc
index 2d2d874146..5f9845fa40 100644
--- a/target/ppc/translate/fixedpoint-impl.c.inc
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
@@ -204,3 +204,26 @@ static bool trans_PNOP(DisasContext *ctx, arg_PNOP *a)
 {
 return true;
 }
+
+static bool do_set_bool_cond(DisasContext *ctx, arg_X_bi *a, bool neg, bool 
rev)
+{
+REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+uint32_t mask = 0x08 >> (a->bi & 0x03);
+TCGCond cond = rev ? TCG_COND_EQ : TCG_COND_NE;
+TCGv temp = tcg_temp_new();
+
+tcg_gen_extu_i32_tl(temp, cpu_crf[a->bi >> 2]);
+tcg_gen_andi_tl(temp, temp, mask);
+tcg_gen_setcondi_tl(cond, cpu_gpr[a->rt], temp, 0);
+if (neg) {
+tcg_gen_neg_tl(cpu_gpr[a->rt], cpu_gpr[a->rt]);
+}
+tcg_temp_free(temp);
+
+return true;
+}
+
+TRANS(SETBC, do_set_bool_cond, false, false)
+TRANS(SETBCR, do_set_bool_cond, false, true)
+TRANS(SETNBC, do_set_bool_cond, true, false)
+TRANS(SETNBCR, do_set_bool_cond, true, true)
-- 
2.25.1




[PATCH v6 09/14] target/ppc: Implement prefixed integer store instructions

2021-06-01 Thread matheus . ferst
From: Richard Henderson 

Signed-off-by: Richard Henderson 
Signed-off-by: Matheus Ferst 
---
 target/ppc/insn64.decode   | 12 
 target/ppc/translate/fixedpoint-impl.c.inc |  4 
 2 files changed, 16 insertions(+)

diff --git a/target/ppc/insn64.decode b/target/ppc/insn64.decode
index 547bd1736f..72c5944a53 100644
--- a/target/ppc/insn64.decode
+++ b/target/ppc/insn64.decode
@@ -39,6 +39,18 @@ PLWA01 00 0--.-- .. \
 PLD 01 00 0--.-- .. \
 111001 . .  @PLS_D
 
+### Fixed-Point Store Instructions
+
+PSTW01 10 0--.-- .. \
+100100 . .  @PLS_D
+PSTB01 10 0--.-- .. \
+100110 . .  @PLS_D
+PSTH01 10 0--.-- .. \
+101100 . .  @PLS_D
+
+PSTD01 00 0--.-- .. \
+01 . .  @PLS_D
+
 ### Fixed-Point Arithmetic Instructions
 
 PADDI   01 10 0--.-- .. \
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc 
b/target/ppc/translate/fixedpoint-impl.c.inc
index adeee33289..2d2d874146 100644
--- a/target/ppc/translate/fixedpoint-impl.c.inc
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
@@ -142,24 +142,28 @@ TRANS(STB, do_ldst_D, false, true, MO_UB)
 TRANS(STBX, do_ldst_X, false, true, MO_UB)
 TRANS(STBU, do_ldst_D, true, true, MO_UB)
 TRANS(STBUX, do_ldst_X, true, true, MO_UB)
+TRANS(PSTB, do_ldst_PLS_D, false, true, MO_UB)
 
 /* Store Halfword */
 TRANS(STH, do_ldst_D, false, true, MO_UW)
 TRANS(STHX, do_ldst_X, false, true, MO_UW)
 TRANS(STHU, do_ldst_D, true, true, MO_UW)
 TRANS(STHUX, do_ldst_X, true, true, MO_UW)
+TRANS(PSTH, do_ldst_PLS_D, false, true, MO_UW)
 
 /* Store Word */
 TRANS(STW, do_ldst_D, false, true, MO_UL)
 TRANS(STWX, do_ldst_X, false, true, MO_UL)
 TRANS(STWU, do_ldst_D, true, true, MO_UL)
 TRANS(STWUX, do_ldst_X, true, true, MO_UL)
+TRANS(PSTW, do_ldst_PLS_D, false, true, MO_UL)
 
 /* Store Doubleword */
 TRANS64(STD, do_ldst_D, false, true, MO_Q)
 TRANS64(STDX, do_ldst_X, false, true, MO_Q)
 TRANS64(STDU, do_ldst_D, true, true, MO_Q)
 TRANS64(STDUX, do_ldst_X, true, true, MO_Q)
+TRANS64(PSTD, do_ldst_PLS_D, false, true, MO_Q)
 
 /*
  * Fixed-Point Arithmetic Instructions
-- 
2.25.1




[PATCH v6 04/14] target/ppc: Move ADDI, ADDIS to decodetree, implement PADDI

2021-06-01 Thread matheus . ferst
From: Richard Henderson 

Signed-off-by: Richard Henderson 
Signed-off-by: Matheus Ferst 
---
 target/ppc/insn32.decode   |  8 
 target/ppc/insn64.decode   | 12 ++
 target/ppc/translate.c | 29 --
 target/ppc/translate/fixedpoint-impl.c.inc | 44 ++
 4 files changed, 64 insertions(+), 29 deletions(-)

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index a3a8ae06bf..e7c062d8b4 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -16,3 +16,11 @@
 # You should have received a copy of the GNU Lesser General Public
 # License along with this library; if not, see .
 #
+
+  rt ra si:int64_t
+@D  .. rt:5 ra:5 si:s16 
+
+### Fixed-Point Arithmetic Instructions
+
+ADDI001110 . .  @D
+ADDIS   00 . .  @D
diff --git a/target/ppc/insn64.decode b/target/ppc/insn64.decode
index a38b1f84dc..1965088915 100644
--- a/target/ppc/insn64.decode
+++ b/target/ppc/insn64.decode
@@ -16,3 +16,15 @@
 # You should have received a copy of the GNU Lesser General Public
 # License along with this library; if not, see .
 #
+
+# Format MLS:D and 8LS:D
+_D  rt ra si:int64_t r:bool
+%pls_si 32:s18 0:16
+@PLS_D  .. .. ... r:1 .. .. \
+.. rt:5 ra:5    \
+_D si=%pls_si
+
+### Fixed-Point Arithmetic Instructions
+
+PADDI   01 10 0--.-- .. \
+001110 . .  @PLS_D
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index f3f464c654..3012c7447a 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -1760,19 +1760,6 @@ GEN_INT_ARITH_ADD(addex, 0x05, cpu_ov, 1, 1, 0);
 /* addze  addze.  addzeo  addzeo.*/
 GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, cpu_ca, 1, 1, 0)
 GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, cpu_ca, 1, 1, 1)
-/* addi */
-static void gen_addi(DisasContext *ctx)
-{
-target_long simm = SIMM(ctx->opcode);
-
-if (rA(ctx->opcode) == 0) {
-/* li case */
-tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
-} else {
-tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)],
-cpu_gpr[rA(ctx->opcode)], simm);
-}
-}
 /* addic  addic.*/
 static inline void gen_op_addic(DisasContext *ctx, bool compute_rc0)
 {
@@ -1792,20 +1779,6 @@ static void gen_addic_(DisasContext *ctx)
 gen_op_addic(ctx, 1);
 }
 
-/* addis */
-static void gen_addis(DisasContext *ctx)
-{
-target_long simm = SIMM(ctx->opcode);
-
-if (rA(ctx->opcode) == 0) {
-/* lis case */
-tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm << 16);
-} else {
-tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)],
-cpu_gpr[rA(ctx->opcode)], simm << 16);
-}
-}
-
 /* addpcis */
 static void gen_addpcis(DisasContext *ctx)
 {
@@ -7817,10 +7790,8 @@ GEN_HANDLER_E(cmpeqb, 0x1F, 0x00, 0x07, 0x0060, 
PPC_NONE, PPC2_ISA300),
 GEN_HANDLER_E(cmpb, 0x1F, 0x1C, 0x0F, 0x0001, PPC_NONE, PPC2_ISA205),
 GEN_HANDLER_E(cmprb, 0x1F, 0x00, 0x06, 0x0041, PPC_NONE, PPC2_ISA300),
 GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x0001, PPC_ISEL),
-GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x, PPC_INTEGER),
 GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x, PPC_INTEGER),
 GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x, PPC_INTEGER),
-GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x, PPC_INTEGER),
 GEN_HANDLER_E(addpcis, 0x13, 0x2, 0xFF, 0x, PPC_NONE, PPC2_ISA300),
 GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x0400, PPC_INTEGER),
 GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x0400, PPC_INTEGER),
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc 
b/target/ppc/translate/fixedpoint-impl.c.inc
index be75085cee..344a3ed54b 100644
--- a/target/ppc/translate/fixedpoint-impl.c.inc
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
@@ -16,3 +16,47 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see .
  */
+
+/*
+ * Incorporate CIA into the constant when R=1.
+ * Validate that when R=1, RA=0.
+ */
+static bool resolve_PLS_D(DisasContext *ctx, arg_D *d, arg_PLS_D *a)
+{
+d->rt = a->rt;
+d->ra = a->ra;
+d->si = a->si;
+if (a->r) {
+if (unlikely(a->ra != 0)) {
+gen_invalid(ctx);
+return false;
+}
+d->si += ctx->cia;
+}
+return true;
+}
+
+static bool trans_ADDI(DisasContext *ctx, arg_D *a)
+{
+if (a->ra) {
+tcg_gen_addi_tl(cpu_gpr[a->rt], cpu_gpr[a->ra], a->si);
+} else {
+tcg_gen_movi_tl(cpu_gpr[a->rt], a->si);
+}
+return true;
+}
+
+static bool trans_PADDI(DisasContext *ctx, arg_PLS_D *a)
+{
+arg_D d;
+if 

[PATCH v6 08/14] target/ppc: Move D/DS/X-form integer stores to decodetree

2021-06-01 Thread matheus . ferst
From: Richard Henderson 

These are all connected by macros in the legacy decoding.

Signed-off-by: Richard Henderson 
Signed-off-by: Matheus Ferst 
---
 target/ppc/insn32.decode   | 22 ++
 target/ppc/translate.c | 85 +-
 target/ppc/translate/fixedpoint-impl.c.inc | 24 ++
 3 files changed, 49 insertions(+), 82 deletions(-)

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 70f64c235b..00ec0f4328 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -57,6 +57,28 @@ LDU 111010 . . ..01 @DS
 LDX 01 . . . 010101 -   @X
 LDUX01 . . . 110101 -   @X
 
+### Fixed-Point Store Instructions
+
+STB 100110 . .  @D
+STBU100111 . .  @D
+STBX01 . . . 0011010111 -   @X
+STBUX   01 . . . 000111 -   @X
+
+STH 101100 . .  @D
+STHU101101 . .  @D
+STHX01 . . . 0110010111 -   @X
+STHUX   01 . . . 0110110111 -   @X
+
+STW 100100 . .  @D
+STWU100101 . .  @D
+STWX01 . . . 0010010111 -   @X
+STWUX   01 . . . 0010110111 -   @X
+
+STD 10 . . ..00 @DS
+STDU10 . . ..01 @DS
+STDX01 . . . 0010010101 -   @X
+STDUX   01 . . . 0010110101 -   @X
+
 ### Fixed-Point Arithmetic Instructions
 
 ADDI001110 . .  @D
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index d9238d1d10..3c3cb1b664 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -3299,7 +3299,9 @@ static void glue(gen_qemu_, stop)(DisasContext *ctx,  
  \
 tcg_gen_qemu_st_tl(val, addr, ctx->mem_idx, op);\
 }
 
+#if defined(TARGET_PPC64) || !defined(CONFIG_USER_ONLY)
 GEN_QEMU_STORE_TL(st8,  DEF_MEMOP(MO_UB))
+#endif
 GEN_QEMU_STORE_TL(st16, DEF_MEMOP(MO_UW))
 GEN_QEMU_STORE_TL(st32, DEF_MEMOP(MO_UL))
 
@@ -3432,52 +3434,6 @@ static void gen_lq(DisasContext *ctx)
 #endif
 
 /***  Integer store***/
-#define GEN_ST(name, stop, opc, type) \
-static void glue(gen_, name)(DisasContext *ctx)   \
-{ \
-TCGv EA;  \
-gen_set_access_type(ctx, ACCESS_INT); \
-EA = tcg_temp_new();  \
-gen_addr_imm_index(ctx, EA, 0);   \
-gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);   \
-tcg_temp_free(EA);\
-}
-
-#define GEN_STU(name, stop, opc, type)\
-static void glue(gen_, stop##u)(DisasContext *ctx)\
-{ \
-TCGv EA;  \
-if (unlikely(rA(ctx->opcode) == 0)) { \
-gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);   \
-return;   \
-} \
-gen_set_access_type(ctx, ACCESS_INT); \
-EA = tcg_temp_new();  \
-if (type == PPC_64B)  \
-gen_addr_imm_index(ctx, EA, 0x03);\
-else  \
-gen_addr_imm_index(ctx, EA, 0);   \
-gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);   \
-tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
-tcg_temp_free(EA);\
-}
-
-#define GEN_STUX(name, stop, opc2, opc3, type)\
-static void glue(gen_, name##ux)(DisasContext *ctx)   \
-{ \
-TCGv EA;  \
-if 

[PATCH v6 07/14] target/ppc: Implement prefixed integer load instructions

2021-06-01 Thread matheus . ferst
From: Richard Henderson 

Signed-off-by: Richard Henderson 
Signed-off-by: Matheus Ferst 
---
 target/ppc/insn64.decode   | 15 +++
 target/ppc/translate/fixedpoint-impl.c.inc | 16 
 2 files changed, 31 insertions(+)

diff --git a/target/ppc/insn64.decode b/target/ppc/insn64.decode
index 9aa5097a98..547bd1736f 100644
--- a/target/ppc/insn64.decode
+++ b/target/ppc/insn64.decode
@@ -24,6 +24,21 @@
 .. rt:5 ra:5    \
 _D si=%pls_si
 
+### Fixed-Point Load Instructions
+
+PLBZ01 10 0--.-- .. \
+100010 . .  @PLS_D
+PLHZ01 10 0--.-- .. \
+101000 . .  @PLS_D
+PLHA01 10 0--.-- .. \
+101010 . .  @PLS_D
+PLWZ01 10 0--.-- .. \
+10 . .  @PLS_D
+PLWA01 00 0--.-- .. \
+101001 . .  @PLS_D
+PLD 01 00 0--.-- .. \
+111001 . .  @PLS_D
+
 ### Fixed-Point Arithmetic Instructions
 
 PADDI   01 10 0--.-- .. \
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc 
b/target/ppc/translate/fixedpoint-impl.c.inc
index 6140dd41ca..7687f31d6f 100644
--- a/target/ppc/translate/fixedpoint-impl.c.inc
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
@@ -80,6 +80,16 @@ static bool do_ldst_D(DisasContext *ctx, arg_D *a, bool 
update, bool store,
 return do_ldst(ctx, a->rt, a->ra, tcg_constant_tl(a->si), update, store, 
mop);
 }
 
+static bool do_ldst_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool update,
+  bool store, MemOp mop)
+{
+arg_D d;
+if (!resolve_PLS_D(ctx, , a)) {
+return true;
+}
+return do_ldst_D(ctx, , update, store, mop);
+}
+
 static bool do_ldst_X(DisasContext *ctx, arg_X *a, bool update,
   bool store, MemOp mop)
 {
@@ -91,35 +101,41 @@ TRANS(LBZ, do_ldst_D, false, false, MO_UB)
 TRANS(LBZX, do_ldst_X, false, false, MO_UB)
 TRANS(LBZU, do_ldst_D, true, false, MO_UB)
 TRANS(LBZUX, do_ldst_X, true, false, MO_UB)
+TRANS(PLBZ, do_ldst_PLS_D, false, false, MO_UB)
 
 /* Load Halfword and Zero */
 TRANS(LHZ, do_ldst_D, false, false, MO_UW)
 TRANS(LHZX, do_ldst_X, false, false, MO_UW)
 TRANS(LHZU, do_ldst_D, true, false, MO_UW)
 TRANS(LHZUX, do_ldst_X, true, false, MO_UW)
+TRANS(PLHZ, do_ldst_PLS_D, false, false, MO_UW)
 
 /* Load Halfword Algebraic */
 TRANS(LHA, do_ldst_D, false, false, MO_SW)
 TRANS(LHAX, do_ldst_X, false, false, MO_SW)
 TRANS(LHAU, do_ldst_D, true, false, MO_SW)
 TRANS(LHAXU, do_ldst_X, true, false, MO_SW)
+TRANS(PLHA, do_ldst_PLS_D, false, false, MO_SW)
 
 /* Load Word and Zero */
 TRANS(LWZ, do_ldst_D, false, false, MO_UL)
 TRANS(LWZX, do_ldst_X, false, false, MO_UL)
 TRANS(LWZU, do_ldst_D, true, false, MO_UL)
 TRANS(LWZUX, do_ldst_X, true, false, MO_UL)
+TRANS(PLWZ, do_ldst_PLS_D, false, false, MO_UL)
 
 /* Load Word Algebraic */
 TRANS64(LWA, do_ldst_D, false, false, MO_SL)
 TRANS64(LWAX, do_ldst_X, false, false, MO_SL)
 TRANS64(LWAUX, do_ldst_X, true, false, MO_SL)
+TRANS64(PLWA, do_ldst_PLS_D, false, false, MO_SL)
 
 /* Load Doubleword */
 TRANS64(LD, do_ldst_D, false, false, MO_Q)
 TRANS64(LDX, do_ldst_X, false, false, MO_Q)
 TRANS64(LDU, do_ldst_D, true, false, MO_Q)
 TRANS64(LDUX, do_ldst_X, true, false, MO_Q)
+TRANS64(PLD, do_ldst_PLS_D, false, false, MO_Q)
 
 /*
  * Fixed-Point Arithmetic Instructions
-- 
2.25.1




[PATCH v6 05/14] target/ppc: Implement PNOP

2021-06-01 Thread matheus . ferst
From: Richard Henderson 

The illegal suffix behavior matches what was observed in a
POWER10 DD2.0 machine.

Signed-off-by: Richard Henderson 
Signed-off-by: Matheus Ferst 
---
 target/ppc/insn64.decode   | 67 ++
 target/ppc/translate/fixedpoint-impl.c.inc | 11 
 2 files changed, 78 insertions(+)

diff --git a/target/ppc/insn64.decode b/target/ppc/insn64.decode
index 1965088915..9aa5097a98 100644
--- a/target/ppc/insn64.decode
+++ b/target/ppc/insn64.decode
@@ -28,3 +28,70 @@
 
 PADDI   01 10 0--.-- .. \
 001110 . .  @PLS_D
+
+### Prefixed No-operation Instruction
+
+@PNOP   01 11 -- 00 \
+
+
+{
+  [
+## Invalid suffixes: Branch instruction
+# bc[l][a]
+INVALID \
+01--@PNOP
+# b[l][a]
+INVALID \
+010010--@PNOP
+# bclr[l]
+INVALID \
+010011---01-@PNOP
+# bcctr[l]
+INVALID \
+010011---11-@PNOP
+# bctar[l]
+INVALID \
+010011---100011-@PNOP
+
+## Invalid suffixes: rfebb
+INVALID \
+010011---0010010010-@PNOP
+
+## Invalid suffixes: context synchronizing other than isync
+# sc
+INVALID \
+0100011-@PNOP
+# scv
+INVALID \
+01000101@PNOP
+# rfscv
+INVALID \
+010011---0001010010-@PNOP
+# rfid
+INVALID \
+010011---010010-@PNOP
+# hrfid
+INVALID \
+010011---0100010010-@PNOP
+# urfid
+INVALID \
+010011---0100110010-@PNOP
+# stop
+INVALID \
+010011---0101110010-@PNOP
+# mtmsr w/ L=0
+INVALID \
+01-0-0010010010-@PNOP
+# mtmsrd w/ L=0
+INVALID \
+01-0-0010110010-@PNOP
+
+## Invalid suffixes: Service Processor Attention
+INVALID \
+001-@PNOP
+  ]
+
+  ## Valid suffixes
+  PNOP  \
+@PNOP
+}
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc 
b/target/ppc/translate/fixedpoint-impl.c.inc
index 344a3ed54b..ce034a14a7 100644
--- a/target/ppc/translate/fixedpoint-impl.c.inc
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
@@ -60,3 +60,14 @@ static bool trans_ADDIS(DisasContext *ctx, arg_D *a)
 a->si <<= 16;
 return trans_ADDI(ctx, a);
 }
+
+static bool trans_INVALID(DisasContext *ctx, arg_INVALID *a)
+{
+gen_invalid(ctx);
+return true;
+}
+
+static bool trans_PNOP(DisasContext *ctx, arg_PNOP *a)
+{
+return true;
+}
-- 
2.25.1




[PATCH v6 03/14] target/ppc: Add infrastructure for prefixed insns

2021-06-01 Thread matheus . ferst
From: Richard Henderson 

Signed-off-by: Luis Pires 
Signed-off-by: Richard Henderson 
Signed-off-by: Matheus Ferst 
---
 target/ppc/cpu.h   |  1 +
 target/ppc/insn32.decode   | 18 +++
 target/ppc/insn64.decode   | 18 +++
 target/ppc/meson.build |  9 ++
 target/ppc/translate.c | 37 ++
 target/ppc/translate/fixedpoint-impl.c.inc | 18 +++
 6 files changed, 95 insertions(+), 6 deletions(-)
 create mode 100644 target/ppc/insn32.decode
 create mode 100644 target/ppc/insn64.decode
 create mode 100644 target/ppc/translate/fixedpoint-impl.c.inc

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index b0934d9be4..ad34c479ec 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -144,6 +144,7 @@ enum {
 POWERPC_EXCP_ALIGN_PROT= 0x04,  /* Access cross protection boundary  */
 POWERPC_EXCP_ALIGN_BAT = 0x05,  /* Access cross a BAT/seg boundary   */
 POWERPC_EXCP_ALIGN_CACHE   = 0x06,  /* Impossible dcbz access*/
+POWERPC_EXCP_ALIGN_INSN= 0x07,  /* Pref. insn x-ing 64-byte boundary */
 /* Exception subtypes for POWERPC_EXCP_PROGRAM   */
 /* FP exceptions */
 POWERPC_EXCP_FP= 0x10,
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
new file mode 100644
index 00..a3a8ae06bf
--- /dev/null
+++ b/target/ppc/insn32.decode
@@ -0,0 +1,18 @@
+#
+# Power ISA decode for 32-bit insns (opcode space 0)
+#
+# Copyright (c) 2021 Instituto de Pesquisas Eldorado (eldorado.org.br)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see .
+#
diff --git a/target/ppc/insn64.decode b/target/ppc/insn64.decode
new file mode 100644
index 00..a38b1f84dc
--- /dev/null
+++ b/target/ppc/insn64.decode
@@ -0,0 +1,18 @@
+#
+# Power ISA decode for 64-bit prefixed insns (opcode space 0 and 1)
+#
+# Copyright (c) 2021 Instituto de Pesquisas Eldorado (eldorado.org.br)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see .
+#
diff --git a/target/ppc/meson.build b/target/ppc/meson.build
index a6a53a8d5c..a4f18ff414 100644
--- a/target/ppc/meson.build
+++ b/target/ppc/meson.build
@@ -20,6 +20,15 @@ ppc_ss.add(when: 'CONFIG_TCG', if_true: files(
 
 ppc_ss.add(libdecnumber)
 
+gen = [
+  decodetree.process('insn32.decode',
+ extra_args: '--static-decode=decode_insn32'),
+  decodetree.process('insn64.decode',
+ extra_args: ['--static-decode=decode_insn64',
+  '--insnwidth=64']),
+]
+ppc_ss.add(gen)
+
 ppc_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: 
files('kvm-stub.c'))
 ppc_ss.add(when: 'CONFIG_USER_ONLY', if_true: files('user_only_helper.c'))
 
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index d2c9fd9dd7..f3f464c654 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -7690,6 +7690,10 @@ static inline void set_avr64(int regno, TCGv_i64 src, 
bool high)
 # define REQUIRE_64BIT(CTX)  REQUIRE_INSNS_FLAGS(CTX, 64B)
 #endif
 
+#include "decode-insn32.c.inc"
+#include "decode-insn64.c.inc"
+#include "translate/fixedpoint-impl.c.inc"
+
 #include "translate/fp-impl.c.inc"
 
 #include "translate/vmx-impl.c.inc"
@@ -8850,11 +8854,18 @@ static bool ppc_tr_breakpoint_check(DisasContextBase 
*dcbase, CPUState *cs,
 return true;
 }
 
+static bool is_prefix_insn(DisasContext *ctx, uint32_t insn)
+{
+REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+return opc1(insn) == 1;
+}
+
 static void ppc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
 PowerPCCPU *cpu 

[PATCH v6 06/14] target/ppc: Move D/DS/X-form integer loads to decodetree

2021-06-01 Thread matheus . ferst
From: Richard Henderson 

These are all connected by macros in the legacy decoding.

Signed-off-by: Richard Henderson 
Signed-off-by: Matheus Ferst 
---
 target/ppc/insn32.decode   |  37 ++
 target/ppc/translate.c | 147 -
 target/ppc/translate/fixedpoint-impl.c.inc |  89 +
 3 files changed, 150 insertions(+), 123 deletions(-)

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index e7c062d8b4..70f64c235b 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -20,6 +20,43 @@
   rt ra si:int64_t
 @D  .. rt:5 ra:5 si:s16 
 
+%ds_si  2:s14  !function=times_4
+@DS .. rt:5 ra:5 .. ..   si=%ds_si
+
+  rt ra rb
+@X  .. rt:5 ra:5 rb:5 .. .  
+
+### Fixed-Point Load Instructions
+
+LBZ 100010 . .  @D
+LBZU100011 . .  @D
+LBZX01 . . . 0001010111 -   @X
+LBZUX   01 . . . 0001110111 -   @X
+
+LHZ 101000 . .  @D
+LHZU101001 . .  @D
+LHZX01 . . . 0100010111 -   @X
+LHZUX   01 . . . 0100110111 -   @X
+
+LHA 101010 . .  @D
+LHAU101011 . .  @D
+LHAX01 . . . 0101010111 -   @X
+LHAXU   01 . . . 0101110111 -   @X
+
+LWZ 10 . .  @D
+LWZU11 . .  @D
+LWZX01 . . . 010111 -   @X
+LWZUX   01 . . . 110111 -   @X
+
+LWA 111010 . . ..10 @DS
+LWAX01 . . . 0101010101 -   @X
+LWAUX   01 . . . 0101110101 -   @X
+
+LD  111010 . . ..00 @DS
+LDU 111010 . . ..01 @DS
+LDX 01 . . . 010101 -   @X
+LDUX01 . . . 110101 -   @X
+
 ### Fixed-Point Arithmetic Instructions
 
 ADDI001110 . .  @D
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 3012c7447a..d9238d1d10 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -3323,54 +3323,6 @@ GEN_QEMU_STORE_64(st64, DEF_MEMOP(MO_Q))
 GEN_QEMU_STORE_64(st64r, BSWAP_MEMOP(MO_Q))
 #endif
 
-#define GEN_LD(name, ldop, opc, type) \
-static void glue(gen_, name)(DisasContext *ctx)   \
-{ \
-TCGv EA;  \
-gen_set_access_type(ctx, ACCESS_INT); \
-EA = tcg_temp_new();  \
-gen_addr_imm_index(ctx, EA, 0);   \
-gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);   \
-tcg_temp_free(EA);\
-}
-
-#define GEN_LDU(name, ldop, opc, type)\
-static void glue(gen_, name##u)(DisasContext *ctx)\
-{ \
-TCGv EA;  \
-if (unlikely(rA(ctx->opcode) == 0 ||  \
- rA(ctx->opcode) == rD(ctx->opcode))) {   \
-gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);   \
-return;   \
-} \
-gen_set_access_type(ctx, ACCESS_INT); \
-EA = tcg_temp_new();  \
-if (type == PPC_64B)  \
-gen_addr_imm_index(ctx, EA, 0x03);\
-else  \
-gen_addr_imm_index(ctx, EA, 0);   \
-gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);   \
-tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
-tcg_temp_free(EA);\
-}
-
-#define GEN_LDUX(name, ldop, opc2, opc3, type)\
-static void glue(gen_, 

[PATCH v6 02/14] target/ppc: Move page crossing check to ppc_tr_translate_insn

2021-06-01 Thread matheus . ferst
From: Richard Henderson 

With prefixed instructions, the number of instructions
remaining until the page crossing is no longer constant.

Signed-off-by: Richard Henderson 
Signed-off-by: Matheus Ferst 
---
 target/ppc/translate.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 11fd3342a0..d2c9fd9dd7 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -8821,9 +8821,6 @@ static void ppc_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 
 if (ctx->singlestep_enabled & (CPU_SINGLE_STEP | GDBSTUB_SINGLE_STEP)) {
 ctx->base.max_insns = 1;
-} else {
-int bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
-ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
 }
 }
 
@@ -8874,6 +8871,12 @@ static void ppc_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cs)
 gen_invalid(ctx);
 }
 
+/* End the TB when crossing a page boundary. */
+if (ctx->base.is_jmp == DISAS_NEXT &&
+!(ctx->base.pc_next & ~TARGET_PAGE_MASK)) {
+ctx->base.is_jmp = DISAS_TOO_MANY;
+}
+
 translator_loop_temp_check(>base);
 }
 
-- 
2.25.1




[PATCH v6 01/14] target/ppc: Introduce macros to check isa extensions

2021-06-01 Thread matheus . ferst
From: Richard Henderson 

These will be used by the decodetree trans_* functions
to early-exit when the instruction set is not enabled.

Signed-off-by: Richard Henderson 
Signed-off-by: Matheus Ferst 
---
 target/ppc/translate.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index e16a2721e2..11fd3342a0 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -7664,6 +7664,32 @@ static inline void set_avr64(int regno, TCGv_i64 src, 
bool high)
 tcg_gen_st_i64(src, cpu_env, avr64_offset(regno, high));
 }
 
+/*
+ * Helpers for trans_* functions to check for specific insns flags.
+ * Use token pasting to ensure that we use the proper flag with the
+ * proper variable.
+ */
+#define REQUIRE_INSNS_FLAGS(CTX, NAME) \
+do {\
+if (((CTX)->insns_flags & PPC_##NAME) == 0) {   \
+return false;   \
+}   \
+} while (0)
+
+#define REQUIRE_INSNS_FLAGS2(CTX, NAME) \
+do {\
+if (((CTX)->insns_flags2 & PPC2_##NAME) == 0) { \
+return false;   \
+}   \
+} while (0)
+
+/* Then special-case the check for 64-bit so that we elide code for ppc32. */
+#if TARGET_LONG_BITS == 32
+# define REQUIRE_64BIT(CTX)  return false
+#else
+# define REQUIRE_64BIT(CTX)  REQUIRE_INSNS_FLAGS(CTX, 64B)
+#endif
+
 #include "translate/fp-impl.c.inc"
 
 #include "translate/vmx-impl.c.inc"
-- 
2.25.1




[PATCH v6 00/14] Base for adding PowerPC 64-bit instructions

2021-06-01 Thread matheus . ferst
From: Matheus Ferst 

This series provides the basic infrastructure for adding the new 32/64-bit
instructions in Power ISA 3.1 to target/ppc.

v6:
- Rebase on ppc-for-6.1;
- Fix rebase error in patch 02/14;
- Fix style errors;
- REQUIRE_64BIT when L=1 in cmp/cmpi/cmpl/cmpli.

v5:
- Rebase on ppc-for-6.1;
- Change copyright line from new files;
- Remove argument set from PNOP;
- Add comments to explain helper_cfuged implementation;
- New REQUIRE_ALTIVEC macro;
- REQUIRE_ALTIVEC and REQUIRE_INSNS_FLAGS2 in trans_CFUGED;
- cmp/cmpi/cmpl/cmpli moved to decodetree.

v4:
- Rebase on ppc-for-6.1;
- Fold do_ldst_D and do_ldst_X;
- Add tcg_const_tl, used to share do_ldst_D and do_ldst_X code;
- Unfold prefixed and non-prefixed loads/stores/addi to let non-prefixed insns 
use the non-prefixed formats;
- PNOP invalid suffixes;
- setbc/setbcr/stnbc/setnbcr implemented;
- cfuged/vcfuged implemented;
- addpcis moved to decodetree.

v3:
- More changes for decodetree.
- Cleanup exception/is_jmp logic to the point exception is removed.
- Fold in Luis' isa check for prefixed insn support.
- Share trans_* between prefixed and non-prefixed instructions.
- Use macros to minimize the trans_* boilerplate.
- Fix decode mistake for STHX/STHXU.

v2:
- Store current pc in ctx instead of insn_size
- Use separate decode files for 32- and 64-bit instructions
- Improvements to the exception/is_jmp logic
- Use translator_loop_temp_check()
- Moved logic to prevent translation from crossing page boundaries
- Additional instructions using decodetree: addis, pnop, loads/stores
- Added check for prefixed insn support in cpu flags


Matheus Ferst (5):
  target/ppc: Implement setbc/setbcr/stnbc/setnbcr instructions
  target/ppc: Implement cfuged instruction
  target/ppc: Implement vcfuged instruction
  target/ppc: Move addpcis to decodetree
  target/ppc: Move cmp/cmpi/cmpl/cmpli to decodetree

Richard Henderson (9):
  target/ppc: Introduce macros to check isa extensions
  target/ppc: Move page crossing check to ppc_tr_translate_insn
  target/ppc: Add infrastructure for prefixed insns
  target/ppc: Move ADDI, ADDIS to decodetree, implement PADDI
  target/ppc: Implement PNOP
  target/ppc: Move D/DS/X-form integer loads to decodetree
  target/ppc: Implement prefixed integer load instructions
  target/ppc: Move D/DS/X-form integer stores to decodetree
  target/ppc: Implement prefixed integer store instructions

 target/ppc/cpu.h   |   1 +
 target/ppc/helper.h|   1 +
 target/ppc/insn32.decode   | 126 +++
 target/ppc/insn64.decode   | 124 +++
 target/ppc/int_helper.c|  62 
 target/ppc/meson.build |   9 +
 target/ppc/translate.c | 391 +
 target/ppc/translate/fixedpoint-impl.c.inc | 279 +++
 target/ppc/translate/vector-impl.c.inc |  56 +++
 9 files changed, 747 insertions(+), 302 deletions(-)
 create mode 100644 target/ppc/insn32.decode
 create mode 100644 target/ppc/insn64.decode
 create mode 100644 target/ppc/translate/fixedpoint-impl.c.inc
 create mode 100644 target/ppc/translate/vector-impl.c.inc

-- 
2.25.1




Re: [PATCH v2 1/2] hw/nvme: add support for boot partiotions

2021-06-01 Thread Klaus Jensen

On Jun  1 11:07, Keith Busch wrote:

On Tue, Jun 01, 2021 at 07:41:34PM +0200, Klaus Jensen wrote:

On Jun  1 10:19, Keith Busch wrote:
> On Tue, Jun 01, 2021 at 08:07:48PM +0530, Gollu Appalanaidu wrote:
> > NVMe Boot Partitions provides an area that may be read by the host
> > without initializing queues or even enabling the controller. This
> > allows various platform initialization code to be stored on the NVMe
> > device instead of some separete medium.
> >
> > This patch adds the read support for such an area, as well as support
> > for updating the boot partition contents from the host through the
> > FW Download and Commit commands.
>
> Please provide some details on what platform initilization sequence
> running on QEMU is going to make use of this feature.
>

I totally get your reluctance to accept useless features like device
self-test and ill-supported ones like write uncorrectable.

But I think this feature qualifies just fine for the device. It is useful
for embedded development and while there might not be any qemu boards that
wants to use this *right now*, it allows for experimentation. And this is a
feature that actually *is* implemented by real products for embedded
systems.


That wasn't my request, though. I am well aware of the feature and also
have hardware that implements it. It just sounds like you haven't
actually tested this feature under the protocol's intended use cases
inside this environment. I think that type of testing and a high level
description of it in the changelog ought to be part of acceptance
criteria.



Alright, I see.

You'd like to see this tested by defining a new board that loads 
firmware over PCIe from the device?


signature.asc
Description: PGP signature


Re: [PATCH 2/2] i386: run accel_cpu_instance_init as instance_post_init

2021-06-01 Thread Eduardo Habkost
On Sat, May 29, 2021 at 11:13:13AM +0200, Claudio Fontana wrote:
> This partially fixes host and max cpu initialization,
> by running the accel cpu initialization only after all instance
> init functions are called for all X86 cpu subclasses.

Can you describe what exactly are the initialization ordering
dependencies that were broken?

> 
> Partial Fix.

What does "partial fix" mean?

> 
> Fixes: 48afe6e4eabf ("i386: split cpu accelerators from cpu.c, using 
> AccelCPUClass")
> Signed-off-by: Claudio Fontana 

The fix looks simple and may be obvious, my only concerns are:

1. Testing.  Luckily we are a bit early in the release cycle so
   we have some time for that.
2. Describing more clearly what exactly was wrong.  This can be
   fixed manually in the commit message when applying the patch.


An even better long term solution would be removing the
initialization ordering dependencies and make
accel_cpu_instance_init() safe to be called earlier.  Would that
be doable?


> ---
>  target/i386/cpu.c | 10 +++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 6bcb7dbc2c..ae148fbd2f 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -6422,6 +6422,11 @@ static void 
> x86_cpu_register_feature_bit_props(X86CPUClass *xcc,
>  x86_cpu_register_bit_prop(xcc, name, w, bitnr);
>  }
>  
> +static void x86_cpu_post_initfn(Object *obj)
> +{
> +accel_cpu_instance_init(CPU(obj));
> +}
> +
>  static void x86_cpu_initfn(Object *obj)
>  {
>  X86CPU *cpu = X86_CPU(obj);
> @@ -6473,9 +6478,6 @@ static void x86_cpu_initfn(Object *obj)
>  if (xcc->model) {
>  x86_cpu_load_model(cpu, xcc->model);
>  }
> -
> -/* if required, do accelerator-specific cpu initializations */
> -accel_cpu_instance_init(CPU(obj));
>  }
>  
>  static int64_t x86_cpu_get_arch_id(CPUState *cs)
> @@ -6810,6 +6812,8 @@ static const TypeInfo x86_cpu_type_info = {
>  .parent = TYPE_CPU,
>  .instance_size = sizeof(X86CPU),
>  .instance_init = x86_cpu_initfn,
> +.instance_post_init = x86_cpu_post_initfn,
> +
>  .abstract = true,
>  .class_size = sizeof(X86CPUClass),
>  .class_init = x86_cpu_common_class_init,
> -- 
> 2.26.2
> 

-- 
Eduardo




Re: [PATCH 1/2] i386: reorder call to cpu_exec_realizefn in x86_cpu_realizefn

2021-06-01 Thread Eduardo Habkost
+Vitaly

On Sat, May 29, 2021 at 11:13:12AM +0200, Claudio Fontana wrote:
> we need to expand features first, before we attempt to check them
> in the accel realizefn code called by cpu_exec_realizefn().
> 
> At the same time we need checks for code_urev and host_cpuid_required,
> and modifications to cpu->mwait to happen after the initial setting
> of them inside the accel realizefn code.

I miss an explanation why those 3 steps need to happen after
accel realizefn.

I'm worried by the fragility of the ordering.  If there are
specific things that must be done before/after
cpu_exec_realizefn(), this needs to be clear in the code.

> 
> Partial Fix.
> 
> Fixes: 48afe6e4eabf ("i386: split cpu accelerators from cpu.c, using 
> AccelCPUClass")

Shouldn't this be
  f5cc5a5c1686 ("i386: split cpu accelerators from cpu.c, using AccelCPUClass")
?

Also, it looks like part of the ordering change was made in
commit 30565f10e907 ("cpu: call AccelCPUClass::cpu_realizefn in
cpu_exec_realizefn").



> Signed-off-by: Claudio Fontana 
> ---
>  target/i386/cpu.c | 56 +++
>  1 file changed, 28 insertions(+), 28 deletions(-)
> 
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 9e211ac2ce..6bcb7dbc2c 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -6133,34 +6133,6 @@ static void x86_cpu_realizefn(DeviceState *dev, Error 
> **errp)
>  Error *local_err = NULL;
>  static bool ht_warned;
>  
> -/* Process Hyper-V enlightenments */
> -x86_cpu_hyperv_realize(cpu);

Vitaly, is this reordering going to affect the Hyper-V cleanup
work you are doing?  It seems harmless and it makes sense to keep
the "realize" functions close together, but I'd like to confirm.

> -
> -cpu_exec_realizefn(cs, _err);
> -if (local_err != NULL) {
> -error_propagate(errp, local_err);
> -return;
> -}
> -
> -if (xcc->host_cpuid_required && !accel_uses_host_cpuid()) {
> -g_autofree char *name = x86_cpu_class_get_model_name(xcc);
> -error_setg(_err, "CPU model '%s' requires KVM or HVF", name);
> -goto out;
> -}
> -
> -if (cpu->ucode_rev == 0) {
> -/* The default is the same as KVM's.  */
> -if (IS_AMD_CPU(env)) {
> -cpu->ucode_rev = 0x0165;
> -} else {
> -cpu->ucode_rev = 0x1ULL;
> -}
> -}
> -
> -/* mwait extended info: needed for Core compatibility */
> -/* We always wake on interrupt even if host does not have the capability 
> */
> -cpu->mwait.ecx |= CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
> -
>  if (cpu->apic_id == UNASSIGNED_APIC_ID) {
>  error_setg(errp, "apic-id property was not initialized properly");
>  return;
> @@ -6190,6 +6162,34 @@ static void x86_cpu_realizefn(DeviceState *dev, Error 
> **errp)
> & CPUID_EXT2_AMD_ALIASES);
>  }
>  
> +/* Process Hyper-V enlightenments */
> +x86_cpu_hyperv_realize(cpu);
> +
> +cpu_exec_realizefn(cs, _err);

I'm worried by the reordering of cpu_exec_realizefn().  That
function does a lot, and reordering it might have even more
unwanted side effects.

I wonder if it wouldn't be easier to revert commit 30565f10e907
("cpu: call AccelCPUClass::cpu_realizefn in cpu_exec_realizefn").


> +if (local_err != NULL) {
> +error_propagate(errp, local_err);
> +return;
> +}
> +
> +if (xcc->host_cpuid_required && !accel_uses_host_cpuid()) {
> +g_autofree char *name = x86_cpu_class_get_model_name(xcc);
> +error_setg(_err, "CPU model '%s' requires KVM or HVF", name);
> +goto out;
> +}
> +
> +if (cpu->ucode_rev == 0) {
> +/* The default is the same as KVM's.  */
> +if (IS_AMD_CPU(env)) {
> +cpu->ucode_rev = 0x0165;
> +} else {
> +cpu->ucode_rev = 0x1ULL;
> +}
> +}
> +
> +/* mwait extended info: needed for Core compatibility */
> +/* We always wake on interrupt even if host does not have the capability 
> */
> +cpu->mwait.ecx |= CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
> +

The dependency between those lines and cpu_exec_realizefn() is
completely unclear here.  What can we do to make this clearer and
less fragile?

Note that this is not a comment on this fix, specifically, but on
how the initialization ordering is easy to break here.


>  /* For 64bit systems think about the number of physical bits to present.
>   * ideally this should be the same as the host; anything other than 
> matching
>   * the host can cause incorrect guest behaviour.
> -- 
> 2.26.2
> 

-- 
Eduardo




[RFC PATCH] target/ppc: removed usage of ppc_store_sdr1 in kvm.c

2021-06-01 Thread Bruno Larsen (billionai)
The only use of this function in kvm.c is right after using the KVM
ioctl to get the registers themselves, so there is no need to do the
error checks done by ppc_store_sdr1.

The probable reason this was here before is because of the hack where
KVM PR stores the hash table size along with the SDR1 information, but
since ppc_store_sdr1 would also store that information, there should be
no need to do any extra processing here.

Signed-off-by: Bruno Larsen (billionai) 
---

This change means we won't have to compile ppc_store_sdr1 when we get
disable-tcg working, but I'm not working on that code motion just yet
since Lucas is dealing with the same file.

I'm sending this as an RFC because I'm pretty sure I'm missing
something, but from what I can see, this is all we'd need

 target/ppc/kvm.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 104a308abb..3f52a7189d 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -1159,7 +1159,11 @@ static int kvmppc_get_books_sregs(PowerPCCPU *cpu)
 }
 
 if (!cpu->vhyp) {
-ppc_store_sdr1(env, sregs.u.s.sdr1);
+/*
+ * We have just gotten the SDR1, there should be no
+ * reason to do error checking right?
+ */
+env->spr[SPR_SDR1] = sregs.u.s.sdr1;
 }
 
 /* Sync SLB */
-- 
2.17.1




Re: HSS Issue with GCC 10, Qemu Setup for microchip-icicle-kit

2021-06-01 Thread Rahul Pathak
I swapped the serial_hd() index between the MMUART0 and MMUART1 , so my
default qemu console is the MMUART1.
I can see the U-Boot and Kernel logs now.

I still need both serial consoles for HSS and UBoot/Kernel and will need
your help to make the original qemu command line work with
unix\#serial1.sock.
I am unable to figure out what's wrong with unix\#serial1.sock

On Tue, Jun 1, 2021 at 7:48 PM Rahul Pathak 
wrote:

> Hi Bin,
>
> Thanks for the response.
>
> I think the issue currently is that if I keep the "wait=on" and launch
> minicom on  "unix\#serial1.sock" then nothing happens.
> Qemu keeps waiting for the connection on serial1 and no logs for uboot and
> Kernel appears on the serial1.
>
> Thanks
> Rahul
>
> On Tue, Jun 1, 2021 at 7:39 PM Bin Meng  wrote:
>
>> Hi Rahul,
>>
>> On Tue, Jun 1, 2021 at 11:12 AM Rahul Pathak 
>> wrote:
>> >
>> > Hi BIn,Alistair,
>> >
>> > I was passing the hss.elf file and it was strange that gdb after
>> connecting was not letting the target to continue from gdb.
>>
>> This is the expected behavior if you pass an image to gdb before
>> connecting to the target, as gdb will assume the debug contexts are
>> the same, but it's not the case for PolarFire which has 1+4 hybrid
>> configuration.
>>
>> > what worked was to not pass anything and then connect the to target
>> then load the symbol file as hss.elf.
>> > I followed the steps from the "Attaching the GDB" doc and was able to
>> debug.
>> >
>>
>> Yes, that's the correct way to debug PolarFire.
>>
>> >
>> > For the qemu command line from the doc, I made the "wait=off" then qemu
>> was not waiting for another serial connection
>> > and launched the hss.
>>
>> You need to connect to the other serial connection otherwise QEMU does
>> not start the emulation when "wait=on"
>>
>> >
>> >
>> > The problem remains is that I still do not have the u-boot and linux
>> booting. The unix\#serial1.sock remains offline always.
>> > These are the HSS logs -
>> >
>> > [0.115001] HSS_E51_Banner(): PolarFire(R) SoC Hart Software Services
>> (HSS) - version 0.99.15
>> > (c) Copyright 2017-2020 Microchip Corporation.
>> >
>> > [0.116234] HSS_E51_Banner(): incorporating OpenSBI - version 0.6
>> > (c) Copyright 2019-2020 Western Digital Corporation.
>> >
>> > [0.117071] HSS_PrintBuildId(): Build ID:
>> 811342a39f80176f9e2086bf963a83224b3d3a2e
>> > [0.117817] HSS_PrintToolVersions(): Built with the following tools:
>> >  - riscv64-unknown-linux-gnu-gcc (GCC) 10.2.0
>>
>> Yeah, this log indicates that GCC 10.x works with HSS :)
>>
>> >  - GNU ld (GNU Binutils) 2.36.1
>> >
>> > [0.118760] HSS_MemTestDDRFast(): DDR size is 1 GiB
>> > [0.130270] HSS_MMCInit(): Attempting to select SDCARD ... Passed
>> > Press a key to enter CLI, ESC to skip
>> > Timeout in 5 seconds
>> >
>> > .
>> > [5.138747] HSS_TinyCLI_Parser(): CLI check timeout
>> > [5.139371] IPI_QueuesInit(): Initializing IPI Queues (9000 bytes @
>> 8000e40)...
>> > [5.140435] HSS_PMP_Init(): Initializing PMPs
>> > [5.141093] HSS_BootInit(): Initializing Boot Image..
>> > [5.141787] getBootImageFromMMC_(): Preparing to copy from MMC to DDR ...
>> > [5.142671] getBootImageFromMMC_(): Attempting to read image header
>> (1552 bytes) ...
>> > [5.144118] GPT_ValidateHeader(): Validated GPT Header ...
>> > [5.153768] GPT_ValidatePartitionEntries(): Validated GPT Partition
>> Entries ...
>> > [5.155210] copyBootImageToDDR_(): Copying 436008 bytes to 0xA000
>> > [5.407848] copyBootImageToDDR_(): Calculated CRC32 of image in DDR is
>> 795fbbea
>> > [5.412058] HSS_BootInit():  boot image passed CRC
>> > [5.412407] HSS_BootInit(): Boot image set name:
>> "PolarFire-SoC-HSS::U-Boot"
>> > [5.412951] HSS_BootInit(): Boot Image registered...
>> > [5.413376] HSS_Boot_RestartCore(): called for all harts
>> > [5.414295] RunStateMachine(): boot_service(u54_1)::Init ->
>> boot_service(u54_1)::SetupPMP
>> > [5.414812] RunStateMachine(): boot_service(u54_2)::Init ->
>> boot_service(u54_2)::SetupPMP
>> > [5.415207] RunStateMachine(): boot_service(u54_3)::Init ->
>> boot_service(u54_3)::SetupPMP
>> > [5.415631] RunStateMachine(): boot_service(u54_4)::Init ->
>> boot_service(u54_4)::SetupPMP
>> > [5.416107] RunStateMachine(): usbdmsc_service::init ->
>> usbdmsc_service::idle
>> > [5.417164] RunStateMachine(): boot_service(u54_1)::SetupPMP ->
>> boot_service(u54_1)::SetupPMPComplete
>> > [5.417887] RunStateMachine(): boot_service(u54_2)::SetupPMP ->
>> boot_service(u54_2)::SetupPMPComplete
>> > [5.418552] RunStateMachine(): boot_service(u54_3)::SetupPMP ->
>> boot_service(u54_3)::SetupPMPComplete
>> > [5.419890] RunStateMachine(): boot_service(u54_4)::SetupPMP ->
>> boot_service(u54_4)::SetupPMPComplete
>> > [23.955147] RunStateMachine(): boot_service(u54_1)::SetupPMPComplete ->
>> boot_service(u54_1)::ZeroInit
>> > [23.955754] RunStateMachine(): boot_service(u54_2)::SetupPMPComplete ->
>> boot_service(u54_2)::ZeroInit
>> > [23.956259] RunStateMachine(): boot_service(u54_3)::SetupPMPComplete ->
>> 

[PULL 24/24] sev: add missing firmware error conditions

2021-06-01 Thread Eduardo Habkost
From: Connor Kuehl 

The SEV userspace header[1] exports a couple of other error conditions that
aren't listed in QEMU's SEV implementation, so let's just round out the
list.

[1] linux-headers/linux/psp-sev.h

Signed-off-by: Connor Kuehl 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20210430134830.254741-3-cku...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 target/i386/sev.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target/i386/sev.c b/target/i386/sev.c
index 5467407ee1d..83df8c09f6a 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -110,6 +110,8 @@ static const char *const sev_fw_errlist[] = {
 [SEV_RET_HWSEV_RET_UNSAFE]   = "Hardware unsafe",
 [SEV_RET_UNSUPPORTED]= "Feature not supported",
 [SEV_RET_INVALID_PARAM]  = "Invalid parameter",
+[SEV_RET_RESOURCE_LIMIT] = "Required firmware resource depleted",
+[SEV_RET_SECURE_DATA_INVALID]= "Part-specific integrity check failure",
 };
 
 #define SEV_FW_MAX_ERROR  ARRAY_SIZE(sev_fw_errlist)
-- 
2.30.2




[PULL 21/24] i386: use global kvm_state in hyperv_enabled() check

2021-06-01 Thread Eduardo Habkost
From: Vitaly Kuznetsov 

There is no need to use vCPU-specific kvm state in hyperv_enabled() check
and we need to do that when feature expansion happens early, before vCPU
specific KVM state is created.

Signed-off-by: Vitaly Kuznetsov 
Reviewed-by: Eduardo Habkost 
Message-Id: <20210422161130.652779-15-vkuzn...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 target/i386/kvm/kvm.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 6bcb74b1d84..c676ee8b38a 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -716,8 +716,7 @@ unsigned long kvm_arch_vcpu_id(CPUState *cs)
 
 static bool hyperv_enabled(X86CPU *cpu)
 {
-CPUState *cs = CPU(cpu);
-return kvm_check_extension(cs->kvm_state, KVM_CAP_HYPERV) > 0 &&
+return kvm_check_extension(kvm_state, KVM_CAP_HYPERV) > 0 &&
 ((cpu->hyperv_spinlock_attempts != HYPERV_SPINLOCK_NEVER_NOTIFY) ||
  cpu->hyperv_features || cpu->hyperv_passthrough);
 }
-- 
2.30.2




[PULL 16/24] i386: split hyperv_handle_properties() into hyperv_expand_features()/hyperv_fill_cpuids()

2021-06-01 Thread Eduardo Habkost
From: Vitaly Kuznetsov 

The intention is to call hyperv_expand_features() early, before vCPUs
are created and use the acquired data later when we set guest visible
CPUID data.

Signed-off-by: Vitaly Kuznetsov 
Reviewed-by: Eduardo Habkost 
Message-Id: <20210422161130.652779-10-vkuzn...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 target/i386/kvm/kvm.c | 34 --
 1 file changed, 24 insertions(+), 10 deletions(-)

diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 2dd60fcaacf..10c836a2bf1 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -1187,16 +1187,15 @@ static uint32_t hv_build_cpuid_leaf(CPUState *cs, 
uint32_t func, int reg)
 }
 
 /*
- * Fill in Hyper-V CPUIDs. Returns the number of entries filled in cpuid_ent in
- * case of success, errno < 0 in case of failure and 0 when no Hyper-V
- * extentions are enabled.
+ * Expand Hyper-V CPU features. In partucular, check that all the requested
+ * features are supported by the host and the sanity of the configuration
+ * (that all the required dependencies are included). Also, this takes care
+ * of 'hv_passthrough' mode and fills the environment with all supported
+ * Hyper-V features.
  */
-static int hyperv_handle_properties(CPUState *cs,
-struct kvm_cpuid_entry2 *cpuid_ent)
+static int hyperv_expand_features(CPUState *cs)
 {
 X86CPU *cpu = X86_CPU(cs);
-struct kvm_cpuid_entry2 *c;
-uint32_t cpuid_i = 0;
 int r;
 
 if (!hyperv_enabled(cpu))
@@ -1295,6 +1294,19 @@ static int hyperv_handle_properties(CPUState *cs,
 return -ENOSYS;
 }
 
+return 0;
+}
+
+/*
+ * Fill in Hyper-V CPUIDs. Returns the number of entries filled in cpuid_ent.
+ */
+static int hyperv_fill_cpuids(CPUState *cs,
+  struct kvm_cpuid_entry2 *cpuid_ent)
+{
+X86CPU *cpu = X86_CPU(cs);
+struct kvm_cpuid_entry2 *c;
+uint32_t cpuid_i = 0;
+
 c = _ent[cpuid_i++];
 c->function = HV_CPUID_VENDOR_AND_MAX_FUNCTIONS;
 c->eax = hyperv_feat_enabled(cpu, HYPERV_FEAT_EVMCS) ?
@@ -1502,11 +1514,13 @@ int kvm_arch_init_vcpu(CPUState *cs)
 env->apic_bus_freq = KVM_APIC_BUS_FREQUENCY;
 
 /* Paravirtualization CPUIDs */
-r = hyperv_handle_properties(cs, cpuid_data.entries);
+r = hyperv_expand_features(cs);
 if (r < 0) {
 return r;
-} else if (r > 0) {
-cpuid_i = r;
+}
+
+if (hyperv_enabled(cpu)) {
+cpuid_i = hyperv_fill_cpuids(cs, cpuid_data.entries);
 kvm_base = KVM_CPUID_SIGNATURE_NEXT;
 has_msr_hv_hypercall = true;
 }
-- 
2.30.2




  1   2   3   4   >