[RFC PATCH v3 4/4] plugins/cache: Added FIFO and LRU eviction policies.

2021-06-07 Thread Mahmoud Mandour
Implemented FIFO and LRU eviction policies.
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 | 205 +---
 1 file changed, 192 insertions(+), 13 deletions(-)

diff --git a/contrib/plugins/cache.c b/contrib/plugins/cache.c
index d8e8c750b6..be817da5b6 100644
--- a/contrib/plugins/cache.c
+++ b/contrib/plugins/cache.c
@@ -34,6 +34,14 @@ static uint64_t dmisses;
 static uint64_t imem_accesses;
 static uint64_t imisses;
 
+enum EvictionPolicy {
+LRU,
+FIFO,
+RAND,
+};
+
+enum EvictionPolicy policy;
+
 /*
  * A CacheSet is a set of cache blocks. A memory block that maps to a set can 
be
  * put in any of the blocks inside the set. The number of block per set is
@@ -53,6 +61,8 @@ static uint64_t imisses;
  * The set number is used to identify the set in which the block may exist.
  * The tag is compared against all the tags of a set to search for a match. If 
a
  * match is found, then the access is a hit.
+ *
+ * The CacheSet also contains bookkeaping information about eviction details.
  */
 
 struct CacheBlock {
@@ -62,6 +72,9 @@ struct CacheBlock {
 
 struct CacheSet {
 struct CacheBlock *blocks;
+uint64_t *lru_priorities;
+uint64_t lru_gen_counter;
+GQueue *fifo_queue;
 };
 
 struct Cache {
@@ -82,6 +95,12 @@ struct InsnData {
 uint64_t imisses;
 };
 
+void (*update_hit)(struct Cache *cache, int set, int blk);
+void (*update_miss)(struct Cache *cache, int set, int blk);
+
+void (*metadata_init)(struct Cache *cache);
+void (*metadata_destroy)(struct Cache *cache);
+
 struct Cache *dcache, *icache;
 
 static int pow_of_two(int num)
@@ -104,6 +123,103 @@ static inline uint64_t extract_set(struct Cache *cache, 
uint64_t addr)
 return (addr & cache->set_mask) >> cache->blksize_shift;
 }
 
+/*
+ * LRU evection policy: For each set, a generation counter is maintained
+ * alongside a priority array.
+ *
+ * On each set access, the generation counter is incremented.
+ *
+ * On a cache hit: The hit-block is assigned the current generation counter,
+ * indicating that it is the most recently used block.
+ *
+ * On a cache miss: The block with the least priority is searched and replaced
+ * with the newly-cached block, of which the priority is set to the current
+ * generation number.
+ */
+
+static void lru_priorities_init(struct Cache *cache)
+{
+int i, assoc;
+
+assoc = cache->assoc;
+for (i = 0; i < cache->num_sets; i++) {
+cache->sets[i].lru_priorities = g_new0(uint64_t, assoc);
+}
+}
+
+static void lru_update_blk(struct Cache *cache, int set_idx, int blk_idx)
+{
+struct CacheSet *set = >sets[set_idx];
+set->lru_priorities[blk_idx] = cache->sets[set_idx].lru_gen_counter;
+set->lru_gen_counter++;
+}
+
+static int lru_get_lru_block(struct Cache *cache, int set_idx)
+{
+int i, min_idx, min_priority;
+
+min_priority = cache->sets[set_idx].lru_priorities[0];
+min_idx = 0;
+
+for (i = 1; i < cache->assoc; i++) {
+if (cache->sets[set_idx].lru_priorities[i] < min_priority) {
+min_priority = cache->sets[set_idx].lru_priorities[i];
+min_idx = i;
+}
+}
+return min_idx;
+}
+
+static void lru_priorities_destroy(struct Cache *cache)
+{
+int i;
+
+for (i = 0; i < cache->num_sets; i++) {
+g_free(cache->sets[i].lru_priorities);
+}
+}
+
+/*
+ * FIFO eviction policy: a FIFO queue is maintained for each CacheSet that
+ * stores accesses to the cache.
+ *
+ * On a compulsory miss: The block index is enqueued to the fifo_queue to
+ * indicate that it's the latest cached block.
+ *
+ * On a conflict miss: The first-in block is removed from the cache and the new
+ * block is put in its place and enqueued to the FIFO queue.
+ */
+
+static void fifo_init(struct Cache *cache)
+{
+int i;
+
+for (i = 0; i < cache->num_sets; i++) {
+cache->sets[i].fifo_queue = g_queue_new();
+}
+}
+
+static int fifo_get_first_block(struct Cache *cache, int set)
+{
+GQueue *q = cache->sets[set].fifo_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].fifo_queue;
+g_queue_push_head(q, GINT_TO_POINTER(blk_idx));
+}
+
+static void fifo_destroy(struct Cache *cache)
+{
+int i;
+
+for (i = 0; i < cache->assoc; i++) {
+g_queue_free(cache->sets[i].fifo_queue);
+}
+}
+
 static bool bad_cache_params(int blksize, int assoc, int cachesize)
 {
 return (cachesize % blksize) != 0 || (cachesize % (blksize * assoc) != 0);
@@ -128,11 +244,17 @@ static struct Cache *cache_init(int blksize, int assoc, 
int cachesize)
 
 for (i = 0; i < cache->num_sets; i++) {
 cache->sets[i].blocks = g_new0(struct CacheBlock, assoc);
+cache->sets[i].lru_gen_counter = 0;
 }
 
 

[RFC PATCH v3 3/4] plugins/cache: Enabled cache parameterization

2021-06-07 Thread Mahmoud Mandour
Made both icache and dcache configurable through plugin arguments.

Signed-off-by: Mahmoud Mandour 
---
 contrib/plugins/cache.c | 44 +++--
 1 file changed, 42 insertions(+), 2 deletions(-)

diff --git a/contrib/plugins/cache.c b/contrib/plugins/cache.c
index 715e5443b0..d8e8c750b6 100644
--- a/contrib/plugins/cache.c
+++ b/contrib/plugins/cache.c
@@ -104,8 +104,17 @@ static inline uint64_t extract_set(struct Cache *cache, 
uint64_t addr)
 return (addr & cache->set_mask) >> cache->blksize_shift;
 }
 
+static bool bad_cache_params(int blksize, int assoc, int cachesize)
+{
+return (cachesize % blksize) != 0 || (cachesize % (blksize * assoc) != 0);
+}
+
 static struct Cache *cache_init(int blksize, int assoc, int cachesize)
 {
+if (bad_cache_params(blksize, assoc, cachesize)) {
+return NULL;
+}
+
 struct Cache *cache;
 int i;
 uint64_t blk_mask;
@@ -403,8 +412,30 @@ 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=")) {
-limit = g_ascii_strtoull(opt + 6, NULL, 10);
+if (g_str_has_prefix(opt, "I=")) {
+gchar **toks = g_strsplit(opt + 2, " ", -1);
+if (g_strv_length(toks) != 3) {
+g_strfreev(toks);
+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);
+g_strfreev(toks);
+} else if (g_str_has_prefix(opt, "D=")) {
+gchar **toks = g_strsplit(opt + 2, " ", -1);
+if (g_strv_length(toks) != 3) {
+g_strfreev(toks);
+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);
+g_strfreev(toks);
+} else if (g_str_has_prefix(opt, "limit=")) {
+limit = g_ascii_strtoll(opt + 6, NULL, 10);
 } else {
 fprintf(stderr, "option parsing failed: %s\n", opt);
 return -1;
@@ -412,7 +443,16 @@ int qemu_plugin_install(qemu_plugin_id_t id, const 
qemu_info_t *info,
 }
 
 dcache = cache_init(dblksize, dassoc, dcachesize);
+if (!dcache) {
+fprintf(stderr, "dcache cannot be constructed from given 
parameters\n");
+return -1;
+}
+
 icache = cache_init(iblksize, iassoc, icachesize);
+if (!icache) {
+fprintf(stderr, "icache cannot be constructed from given 
parameters\n");
+return -1;
+}
 
 qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans);
 qemu_plugin_register_atexit_cb(id, plugin_exit, NULL);
-- 
2.25.1




[RFC PATCH v3 1/4] plugins/api: expose symbol lookup to plugins

2021-06-07 Thread Mahmoud Mandour
From: Alex Bennée 

This is a quality of life helper for plugins so they don't need to
re-implement symbol lookup when dumping an address. The strings are
constant so don't need to be duplicated. One minor tweak is to return
NULL instead of a zero length string to show lookup failed.

Signed-off-by: Alex Bennée 
Message-Id: <20210601145824.3849-1-alex.ben...@linaro.org>
Signed-off-by: Mahmoud Mandour 
---
 include/qemu/qemu-plugin.h | 9 +
 plugins/api.c  | 6 ++
 2 files changed, 15 insertions(+)

diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h
index 97cdfd7761..dc3496f36c 100644
--- a/include/qemu/qemu-plugin.h
+++ b/include/qemu/qemu-plugin.h
@@ -525,6 +525,15 @@ qemu_plugin_register_vcpu_syscall_ret_cb(qemu_plugin_id_t 
id,
 
 char *qemu_plugin_insn_disas(const struct qemu_plugin_insn *insn);
 
+/**
+ * qemu_plugin_insn_symbol() - best effort symbol lookup
+ * @insn: instruction reference
+ *
+ * Return a static string referring to the symbol. This is dependent
+ * on the binary QEMU is running having provided a symbol table.
+ */
+const char *qemu_plugin_insn_symbol(const struct qemu_plugin_insn *insn);
+
 /**
  * qemu_plugin_vcpu_for_each() - iterate over the existing vCPU
  * @id: plugin ID
diff --git a/plugins/api.c b/plugins/api.c
index 817c9b6b69..332e2c60e2 100644
--- a/plugins/api.c
+++ b/plugins/api.c
@@ -233,6 +233,12 @@ char *qemu_plugin_insn_disas(const struct qemu_plugin_insn 
*insn)
 return plugin_disas(cpu, insn->vaddr, insn->data->len);
 }
 
+const char *qemu_plugin_insn_symbol(const struct qemu_plugin_insn *insn)
+{
+const char *sym = lookup_symbol(insn->vaddr);
+return sym[0] != 0 ? sym : NULL;
+}
+
 /*
  * The memory queries allow the plugin to query information about a
  * memory access.
-- 
2.25.1




[RFC PATCH v3 2/4] plugins: Added a new cache modelling plugin.

2021-06-07 Thread Mahmoud Mandour
Added a cache modelling plugin that uses a static configuration used in
many of the commercial microprocessors and uses random eviction policy.

The purpose of the plugin is to identify the most cache-thrashing
instructions for both instruction cache and data cache.

Signed-off-by: Mahmoud Mandour 
---
 contrib/plugins/Makefile |   1 +
 contrib/plugins/cache.c  | 423 +++
 2 files changed, 424 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..715e5443b0
--- /dev/null
+++ b/contrib/plugins/cache.c
@@ -0,0 +1,423 @@
+/*
+ * 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 enum qemu_plugin_mem_rw rw = QEMU_PLUGIN_MEM_RW;
+
+static GRand *rng;
+static GHashTable *miss_ht;
+
+static GMutex mtx;
+
+static int limit;
+static bool sys;
+
+static uint64_t dmem_accesses;
+static uint64_t dmisses;
+
+static uint64_t imem_accesses;
+static uint64_t imisses;
+
+/*
+ * A CacheSet is a set of cache blocks. A memory block that maps to a set can 
be
+ * put in any of the blocks inside the set. The number of block per set is
+ * called the associativity (assoc).
+ *
+ * Each block contains the the stored tag and a valid bit. Since this is not
+ * a functional simulator, the data itself is not stored. We only identify
+ * whether a block is in the cache or not by searching for its tag.
+ *
+ * In order to search for memory data in the cache, the set identifier and tag
+ * are extracted from the address and the set is probed to see whether a tag
+ * match occur.
+ *
+ * An address is logically divided into three portions: The block offset,
+ * the set number, and the tag.
+ *
+ * The set number is used to identify the set in which the block may exist.
+ * The tag is compared against all the tags of a set to search for a match. If 
a
+ * match is found, then the access is a hit.
+ */
+
+struct CacheBlock {
+uint64_t tag;
+bool valid;
+};
+
+struct CacheSet {
+struct CacheBlock *blocks;
+};
+
+struct Cache {
+struct CacheSet *sets;
+int num_sets;
+int cachesize;
+int assoc;
+int blksize_shift;
+uint64_t set_mask;
+uint64_t tag_mask;
+};
+
+struct InsnData {
+char *disas_str;
+const char *symbol;
+uint64_t addr;
+uint64_t dmisses;
+uint64_t imisses;
+};
+
+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;
+}
+
+static inline uint64_t extract_set(struct Cache *cache, uint64_t addr)
+{
+return (addr & cache->set_mask) >> cache->blksize_shift;
+}
+
+static struct Cache *cache_init(int blksize, int assoc, int cachesize)
+{
+struct Cache *cache;
+int i;
+uint64_t blk_mask;
+
+cache = g_new(struct Cache, 1);
+cache->assoc = assoc;
+cache->cachesize = cachesize;
+cache->num_sets = cachesize / (blksize * assoc);
+cache->sets = g_new(struct CacheSet, cache->num_sets);
+cache->blksize_shift = pow_of_two(blksize);
+
+for (i = 0; i < cache->num_sets; i++) {
+cache->sets[i].blocks = g_new0(struct CacheBlock, assoc);
+}
+
+blk_mask = blksize - 1;
+cache->set_mask = ((cache->num_sets - 1) << cache->blksize_shift);
+cache->tag_mask = ~(cache->set_mask | 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) {
+return i;
+}
+}
+
+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;
+}
+
+/**
+ * access_cache(): Simulate a cache access
+ * @cache: The cache under simulation
+ * @addr: The address of 

[RFC PATCH v3 0/4] Cache TCG plugin & symbol-resolution API

2021-06-07 Thread Mahmoud Mandour
This RFC series introduces a new cache TCG plugin that models separate
L1 data cache and L1 instruction cache and uses one shared cache for
all the cores.

It also includes a commit by Alex that adds an API call that resolves
the symbol of an insn.

The original RFC patch posted by Alex Bennée included incorporating
symbol resolution into the cache plugin that caused conflicts, so I
dropped the plugin additions from that and introduced them afterwards.

v2 -> v3:
Precomputed the value of block size shift once and stored in the
cache.

Removed tag shifting since it's okay to leave the tag in the
high-order bits and mask out set index and block offset.

Used one hashtable to store InsnData structs and made the structs
have separate counters for data misses and instruction misses.

Used a boolean to indicate whether an access resulted in a hit or a
miss.

Inserted an InsnData struct into the hashtable on translation-time
and made sure we do so once so that we don't rewrite the struct if
an instruction is translated multiple times.

Made the output format for most-missing instructions more
machine-readable.

Removed trace-generation.

Freed tokenized strings after argument parsing.

Returned null from cache_init() if argument cache config is bad.

Used one enum to indicate the chosen eviction policy.

Added function pointers for cache update and metadata initialization
and destroying. Those pointers are assigned to policy-specific
functions.

Remade LRU. Assigned a generation number that is incremented on each
set access to the currently-accessed block's priority. On miss, 
evicted the block with the least generation number.

Allowed to give multiple "evict" arguments and sticked to the last
one.

Alex Bennée (1):
  plugins/api: expose symbol lookup to plugins

Mahmoud Mandour (3):
  plugins: Added a new cache modelling plugin.
  plugins/cache: Enabled cache parameterization
  plugins/cache: Added FIFO and LRU eviction policies.

 contrib/plugins/Makefile   |   1 +
 contrib/plugins/cache.c| 642 +
 include/qemu/qemu-plugin.h |   9 +
 plugins/api.c  |   6 +
 4 files changed, 658 insertions(+)
 create mode 100644 contrib/plugins/cache.c

-- 
2.25.1




Re: [PATCH 10/55] target/arm: Add framework for MVE decode

2021-06-07 Thread Richard Henderson

On 6/7/21 9:57 AM, Peter Maydell wrote:

Add the framework for decoding MVE insns, with the necessary new
files and the meson.build rules, but no actual content yet.

Signed-off-by: Peter Maydell
---
  target/arm/translate-a32.h |  1 +
  target/arm/mve.decode  | 20 
  target/arm/translate-mve.c | 29 +
  target/arm/translate.c |  1 +
  target/arm/meson.build |  2 ++
  5 files changed, 53 insertions(+)
  create mode 100644 target/arm/mve.decode
  create mode 100644 target/arm/translate-mve.c


Reviewed-by: Richard Henderson 

r~



Re: [PATCH 09/55] target/arm: Implement MVE LETP insn

2021-06-07 Thread Richard Henderson

On 6/7/21 9:57 AM, Peter Maydell wrote:

Implement the MVE LETP insn.  This is like the existing LE loop-end
insn, but it must perform an FPU-enabled check, and on loop-exit it
resets LTPSIZE to 4.

To accommodate the requirement to do something on loop-exit, we drop
the use of condlabel and instead manage both the TB exits manually,
in the same way we already do in trans_WLS().

The other MVE-specific change to the LE insn is that we must raise an
INVSTATE UsageFault insn if LTPSIZE is not 4.

Signed-off-by: Peter Maydell
---
This amounts to a complete rewrite of trans_LE()...
---
  target/arm/t32.decode  |   2 +-
  target/arm/translate.c | 104 +
  2 files changed, 97 insertions(+), 9 deletions(-)


Reviewed-by: Richard Henderson 

r~



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

2021-06-07 Thread Cindy Lu
On Thu, Jun 3, 2021 at 2:28 PM Jason Wang  wrote:
>
>
> 在 2021/6/2 上午11:47, Cindy Lu 写道:
> > Add configure notifier support in vhost and virtio driver
> > When backend support VIRTIO_NET_F_STATUS,
>
>
> So config interrupt is the basic facility of the virtio device. We need
> to make the code not specific to this feature.
>
> But we can leave the specific device (like virtio-net, or vhost-net) to
> decide whether or not it can be used.
>
> For net, it is also used by guest announcement.
>
sure, I will rewrite this part
>
> > 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"
>
>
> Inclusion of device specific header in the general vhost code looks like
> a layer violation.
>
>
> >   #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);
>
>
> I think we can remove this.
>
>
> > +VirtIODevice *vdev = hdev->vdev;
> > +if ((hdev->started == false) ||
>
>
> We don't check this in vhost_virtqueue_pending(), any reason to do this?
>
>
> > +(hdev->vhost_ops->vhost_set_config_call == NULL)) {
>
>
> I think we need first check what happens if we try to down the link for
> vhost-vdpa network backend in the monitor. (Or should we block that from
> the monitor?)
>
> Then we can decided whether or not we need this.
>
>
I will remove this part
> > +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;
> > 

[PATCH v6 4/4] Jobs based on custom runners: add job definitions for QEMU's machines

2021-06-07 Thread Cleber Rosa
The QEMU project has two machines (aarch64 and s390x) that can be used
for jobs that do build and run tests.  This introduces those jobs,
which are a mapping of custom scripts used for the same purpose.

Signed-off-by: Cleber Rosa 
---
 .gitlab-ci.d/custom-runners.yml | 208 
 1 file changed, 208 insertions(+)

diff --git a/.gitlab-ci.d/custom-runners.yml b/.gitlab-ci.d/custom-runners.yml
index a07b27384c..061d3cdfed 100644
--- a/.gitlab-ci.d/custom-runners.yml
+++ b/.gitlab-ci.d/custom-runners.yml
@@ -12,3 +12,211 @@
 # guarantees a fresh repository on each job run.
 variables:
   GIT_STRATEGY: clone
+
+# All ubuntu-18.04 jobs should run successfully in an environment
+# setup by the scripts/ci/setup/build-environment.yml task
+# "Install basic packages to build QEMU on Ubuntu 18.04/20.04"
+ubuntu-18.04-s390x-all-linux-static:
+ allow_failure: true
+ needs: []
+ stage: build
+ tags:
+ - ubuntu_18.04
+ - s390x
+ rules:
+ - if: '$CI_COMMIT_BRANCH =~ /^staging/'
+ script:
+ # --disable-libssh is needed because of 
https://bugs.launchpad.net/qemu/+bug/1838763
+ # --disable-glusterfs is needed because there's no static version of those 
libs in distro supplied packages
+ - mkdir build
+ - cd build
+ - ../configure --enable-debug --static --disable-system --disable-glusterfs 
--disable-libssh
+ - make --output-sync -j`nproc`
+ - make --output-sync -j`nproc` check V=1
+ - make --output-sync -j`nproc` check-tcg V=1
+
+ubuntu-18.04-s390x-all:
+ allow_failure: true
+ needs: []
+ stage: build
+ tags:
+ - ubuntu_18.04
+ - s390x
+ rules:
+ - if: '$CI_COMMIT_BRANCH =~ /^staging/'
+ script:
+ - mkdir build
+ - cd build
+ - ../configure --disable-libssh
+ - make --output-sync -j`nproc`
+ - make --output-sync -j`nproc` check V=1
+
+ubuntu-18.04-s390x-alldbg:
+ allow_failure: true
+ needs: []
+ stage: build
+ tags:
+ - ubuntu_18.04
+ - s390x
+ rules:
+ - if: '$CI_COMMIT_BRANCH =~ /^staging/'
+ script:
+ - mkdir build
+ - cd build
+ - ../configure --enable-debug --disable-libssh
+ - make clean
+ - make --output-sync -j`nproc`
+ - make --output-sync -j`nproc` check V=1
+
+ubuntu-18.04-s390x-clang:
+ allow_failure: true
+ needs: []
+ stage: build
+ tags:
+ - ubuntu_18.04
+ - s390x
+ rules:
+ - if: '$CI_COMMIT_BRANCH =~ /^staging/'
+   when: manual
+ script:
+ - mkdir build
+ - cd build
+ - ../configure --disable-libssh --cc=clang --cxx=clang++ --enable-sanitizers
+ - make --output-sync -j`nproc`
+ - make --output-sync -j`nproc` check V=1
+
+ubuntu-18.04-s390x-tci:
+ allow_failure: true
+ needs: []
+ stage: build
+ tags:
+ - ubuntu_18.04
+ - s390x
+ rules:
+ - if: '$CI_COMMIT_BRANCH =~ /^staging/'
+ script:
+ - mkdir build
+ - cd build
+ - ../configure --disable-libssh --enable-tcg-interpreter
+ - make --output-sync -j`nproc`
+
+ubuntu-18.04-s390x-notcg:
+ allow_failure: true
+ needs: []
+ stage: build
+ tags:
+ - ubuntu_18.04
+ - s390x
+ rules:
+ - if: '$CI_COMMIT_BRANCH =~ /^staging/'
+   when: manual
+ script:
+ - mkdir build
+ - cd build
+ - ../configure --disable-libssh --disable-tcg
+ - make --output-sync -j`nproc`
+ - make --output-sync -j`nproc` check V=1
+
+# All ubuntu-20.04 jobs should run successfully in an environment
+# setup by the scripts/ci/setup/qemu/build-environment.yml task
+# "Install basic packages to build QEMU on Ubuntu 18.04/20.04"
+ubuntu-20.04-aarch64-all-linux-static:
+ allow_failure: true
+ needs: []
+ stage: build
+ tags:
+ - ubuntu_20.04
+ - aarch64
+ rules:
+ - if: '$CI_COMMIT_BRANCH =~ /^staging/'
+ script:
+ # --disable-libssh is needed because of 
https://bugs.launchpad.net/qemu/+bug/1838763
+ # --disable-glusterfs is needed because there's no static version of those 
libs in distro supplied packages
+ - mkdir build
+ - cd build
+ - ../configure --enable-debug --static --disable-system --disable-glusterfs 
--disable-libssh
+ - make --output-sync -j`nproc`
+ - make --output-sync -j`nproc` check V=1
+ - make --output-sync -j`nproc` check-tcg V=1
+
+ubuntu-20.04-aarch64-all:
+ allow_failure: true
+ needs: []
+ stage: build
+ tags:
+ - ubuntu_20.04
+ - aarch64
+ rules:
+ - if: '$CI_COMMIT_BRANCH =~ /^staging/'
+ script:
+ - mkdir build
+ - cd build
+ - ../configure --disable-libssh
+ - make --output-sync -j`nproc`
+ - make --output-sync -j`nproc` check V=1
+
+ubuntu-20.04-aarch64-alldbg:
+ allow_failure: true
+ needs: []
+ stage: build
+ tags:
+ - ubuntu_20.04
+ - aarch64
+ rules:
+ - if: '$CI_COMMIT_BRANCH =~ /^staging/'
+ script:
+ - mkdir build
+ - cd build
+ - ../configure --enable-debug --disable-libssh
+ - make clean
+ - make --output-sync -j`nproc`
+ - make --output-sync -j`nproc` check V=1
+
+ubuntu-20.04-aarch64-clang:
+ allow_failure: true
+ needs: []
+ stage: build
+ tags:
+ - ubuntu_20.04
+ - aarch64
+ rules:
+ - if: '$CI_COMMIT_BRANCH =~ /^staging/'
+   when: manual
+ script:
+ - mkdir build
+ - cd build
+ - ../configure --disable-libssh --cc=clang-10 --cxx=clang++-10 
--enable-sanitizers
+ - make --output-sync -j`nproc`
+ - make --output-sync 

[PATCH v6 3/4] Jobs based on custom runners: docs and gitlab-runner setup playbook

2021-06-07 Thread Cleber Rosa
To have the jobs dispatched to custom runners, gitlab-runner must
be installed, active as a service and properly configured.  The
variables file and playbook introduced here should help with those
steps.

The playbook introduced here covers the Linux distributions and
has been primarily tested on OS/machines that the QEMU project
has available to act as runners, namely:

 * Ubuntu 20.04 on aarch64
 * Ubuntu 18.04 on s390x

But, it should work on all other Linux distributions.  Earlier
versions were tested on FreeBSD too, so chances of success are
high.

Signed-off-by: Cleber Rosa 
---
 docs/devel/ci.rst  | 57 
 scripts/ci/setup/.gitignore|  1 +
 scripts/ci/setup/gitlab-runner.yml | 61 ++
 scripts/ci/setup/vars.yml.template | 12 ++
 4 files changed, 131 insertions(+)
 create mode 100644 scripts/ci/setup/.gitignore
 create mode 100644 scripts/ci/setup/gitlab-runner.yml
 create mode 100644 scripts/ci/setup/vars.yml.template

diff --git a/docs/devel/ci.rst b/docs/devel/ci.rst
index 35c6b5e269..bbd89e54d7 100644
--- a/docs/devel/ci.rst
+++ b/docs/devel/ci.rst
@@ -56,3 +56,60 @@ To run the playbook, execute::
 
   cd scripts/ci/setup
   ansible-playbook -i inventory build-environment.yml
+
+gitlab-runner setup and registration
+
+
+The gitlab-runner agent needs to be installed on each machine that
+will run jobs.  The association between a machine and a GitLab project
+happens with a registration token.  To find the registration token for
+your repository/project, navigate on GitLab's web UI to:
+
+ * Settings (the gears like icon), then
+ * CI/CD, then
+ * Runners, and click on the "Expand" button, then
+ * Under "Set up a specific Runner manually", look for the value under
+   "Use the following registration token during setup"
+
+Copy the ``scripts/ci/setup/vars.yml.template`` file to
+``scripts/ci/setup/vars.yml``.  Then, set the
+``gitlab_runner_registration_token`` variable to the value obtained
+earlier.
+
+.. note:: gitlab-runner is not available from the standard location
+  for all OS and architectures combinations.  For some systems,
+  a custom build may be necessary.  Some builds are avaiable
+  at https://cleber.fedorapeople.org/gitlab-runner/ and this
+  URI may be used as a value on ``vars.yml``
+
+To run the playbook, execute::
+
+  cd scripts/ci/setup
+  ansible-playbook -i inventory gitlab-runner.yml
+
+Following the registration, it's necessary to configure the runner tags,
+and optionally other configurations on the GitLab UI.  Navigate to:
+
+ * Settings (the gears like icon), then
+ * CI/CD, then
+ * Runners, and click on the "Expand" button, then
+ * "Runners activated for this project", then
+ * Click on the "Edit" icon (next to the "Lock" Icon)
+
+Under tags, add values matching the jobs a runner should run.  For a
+Ubuntu 20.04 aarch64 system, the tags should be set as::
+
+  ubuntu_20.04,aarch64
+
+Because the job definition at ``.gitlab-ci.d/custom-runners.yml``
+would contain::
+
+  ubuntu-20.04-aarch64-all:
+   tags:
+   - ubuntu_20.04
+   - aarch64
+
+It's also recommended to:
+
+ * increase the "Maximum job timeout" to something like ``2h``
+ * give it a better Description
diff --git a/scripts/ci/setup/.gitignore b/scripts/ci/setup/.gitignore
new file mode 100644
index 00..f112d05dd0
--- /dev/null
+++ b/scripts/ci/setup/.gitignore
@@ -0,0 +1 @@
+vars.yml
\ No newline at end of file
diff --git a/scripts/ci/setup/gitlab-runner.yml 
b/scripts/ci/setup/gitlab-runner.yml
new file mode 100644
index 00..98dab92bb5
--- /dev/null
+++ b/scripts/ci/setup/gitlab-runner.yml
@@ -0,0 +1,61 @@
+---
+- name: Installation of gitlab-runner
+  hosts: all
+  vars_files:
+- vars.yml
+  tasks:
+- debug:
+msg: 'Checking for a valid GitLab registration token'
+  failed_when: "gitlab_runner_registration_token == 
'PLEASE_PROVIDE_A_VALID_TOKEN'"
+
+- name: Create a group for the gitlab-runner service
+  group:
+name: gitlab-runner
+
+- name: Create a user for the gitlab-runner service
+  user:
+user: gitlab-runner
+group: gitlab-runner
+comment: GitLab Runner
+home: /home/gitlab-runner
+shell: /bin/bash
+
+- name: Remove the .bash_logout file when on Ubuntu systems
+  file:
+path: /home/gitlab-runner/.bash_logout
+state: absent
+  when: "ansible_facts['distribution'] == 'Ubuntu'"
+
+- name: Set the Operating System for gitlab-runner
+  set_fact:
+gitlab_runner_os: "{{ ansible_facts[\"system\"]|lower }}"
+- debug:
+msg: gitlab-runner OS is {{ gitlab_runner_os }}
+
+- name: Set the architecture for gitlab-runner
+  set_fact:
+gitlab_runner_arch: "{{ 
ansible_to_gitlab_arch[ansible_facts[\"architecture\"]] }}"
+- debug:
+msg: gitlab-runner arch is {{ gitlab_runner_arch }}
+
+

[PATCH v6 1/4] Jobs based on custom runners: documentation and configuration placeholder

2021-06-07 Thread Cleber Rosa
As described in the included documentation, the "custom runner" jobs
extend the GitLab CI jobs already in place.  One of their primary
goals of catching and preventing regressions on a wider number of host
systems than the ones provided by GitLab's shared runners.

This sets the stage in which other community members can add their own
machine configuration documentation/scripts, and accompanying job
definitions.  As a general rule, those newly added contributed jobs
should run as "non-gating", until their reliability is verified (AKA
"allow_failure: true").

Signed-off-by: Cleber Rosa 
---
 .gitlab-ci.d/custom-runners.yml | 14 ++
 .gitlab-ci.d/qemu-project.yml   |  1 +
 docs/devel/ci.rst   | 28 
 docs/devel/index.rst|  1 +
 4 files changed, 44 insertions(+)
 create mode 100644 .gitlab-ci.d/custom-runners.yml
 create mode 100644 docs/devel/ci.rst

diff --git a/.gitlab-ci.d/custom-runners.yml b/.gitlab-ci.d/custom-runners.yml
new file mode 100644
index 00..a07b27384c
--- /dev/null
+++ b/.gitlab-ci.d/custom-runners.yml
@@ -0,0 +1,14 @@
+# The CI jobs defined here require GitLab runners installed and
+# registered on machines that match their operating system names,
+# versions and architectures.  This is in contrast to the other CI
+# jobs that are intended to run on GitLab's "shared" runners.
+
+# Different than the default approach on "shared" runners, based on
+# containers, the custom runners have no such *requirement*, as those
+# jobs should be capable of running on operating systems with no
+# compatible container implementation, or no support from
+# gitlab-runner.  To avoid problems that gitlab-runner can cause while
+# reusing the GIT repository, let's enable the clone strategy, which
+# guarantees a fresh repository on each job run.
+variables:
+  GIT_STRATEGY: clone
diff --git a/.gitlab-ci.d/qemu-project.yml b/.gitlab-ci.d/qemu-project.yml
index 64cb2ba1da..dde8270301 100644
--- a/.gitlab-ci.d/qemu-project.yml
+++ b/.gitlab-ci.d/qemu-project.yml
@@ -9,3 +9,4 @@ include:
   - local: '/.gitlab-ci.d/crossbuilds.yml'
   - local: '/.gitlab-ci.d/buildtest.yml'
   - local: '/.gitlab-ci.d/static_checks.yml'
+  - local: '/.gitlab-ci.d/custom-runners.yml'
diff --git a/docs/devel/ci.rst b/docs/devel/ci.rst
new file mode 100644
index 00..585b7bf4b8
--- /dev/null
+++ b/docs/devel/ci.rst
@@ -0,0 +1,28 @@
+==
+CI
+==
+
+QEMU has configurations enabled for a number of different CI services.
+The most up to date information about them and their status can be
+found at::
+
+   https://wiki.qemu.org/Testing/CI
+
+Jobs on Custom Runners
+==
+
+Besides the jobs run under the various CI systems listed before, there
+are a number additional jobs that will run before an actual merge.
+These use the same GitLab CI's service/framework already used for all
+other GitLab based CI jobs, but rely on additional systems, not the
+ones provided by GitLab as "shared runners".
+
+The architecture of GitLab's CI service allows different machines to
+be set up with GitLab's "agent", called gitlab-runner, which will take
+care of running jobs created by events such as a push to a branch.
+Here, the combination of a machine, properly configured with GitLab's
+gitlab-runner, is called a "custom runner".
+
+The GitLab CI jobs definition for the custom runners are located under::
+
+  .gitlab-ci.d/custom-runners.yml
diff --git a/docs/devel/index.rst b/docs/devel/index.rst
index 791925dcda..c9a02e786e 100644
--- a/docs/devel/index.rst
+++ b/docs/devel/index.rst
@@ -27,6 +27,7 @@ Contents:
migration
atomics
stable-process
+   ci
qtest
decodetree
secure-coding-practices
-- 
2.25.4




[PATCH v6 2/4] Jobs based on custom runners: build environment docs and playbook

2021-06-07 Thread Cleber Rosa
To run basic jobs on custom runners, the environment needs to be
properly set up.  The most common requirement is having the right
packages installed.

The playbook introduced here covers the QEMU's project s390x and
aarch64 machines.  At the time this is being proposed, those machines
have already had this playbook applied to them.

Signed-off-by: Cleber Rosa 
---
 docs/devel/ci.rst  | 30 
 scripts/ci/setup/build-environment.yml | 98 ++
 scripts/ci/setup/inventory.template|  1 +
 3 files changed, 129 insertions(+)
 create mode 100644 scripts/ci/setup/build-environment.yml
 create mode 100644 scripts/ci/setup/inventory.template

diff --git a/docs/devel/ci.rst b/docs/devel/ci.rst
index 585b7bf4b8..35c6b5e269 100644
--- a/docs/devel/ci.rst
+++ b/docs/devel/ci.rst
@@ -26,3 +26,33 @@ gitlab-runner, is called a "custom runner".
 The GitLab CI jobs definition for the custom runners are located under::
 
   .gitlab-ci.d/custom-runners.yml
+
+Machine Setup Howto
+---
+
+For all Linux based systems, the setup can be mostly automated by the
+execution of two Ansible playbooks.  Create an ``inventory`` file
+under ``scripts/ci/setup``, such as this::
+
+  fully.qualified.domain
+  other.machine.hostname
+
+You may need to set some variables in the inventory file itself.  One
+very common need is to tell Ansible to use a Python 3 interpreter on
+those hosts.  This would look like::
+
+  fully.qualified.domain ansible_python_interpreter=/usr/bin/python3
+  other.machine.hostname ansible_python_interpreter=/usr/bin/python3
+
+Build environment
+~
+
+The ``scripts/ci/setup/build-environment.yml`` Ansible playbook will
+set up machines with the environment needed to perform builds and run
+QEMU tests.  It covers a number of different Linux distributions and
+FreeBSD.
+
+To run the playbook, execute::
+
+  cd scripts/ci/setup
+  ansible-playbook -i inventory build-environment.yml
diff --git a/scripts/ci/setup/build-environment.yml 
b/scripts/ci/setup/build-environment.yml
new file mode 100644
index 00..664f2f0519
--- /dev/null
+++ b/scripts/ci/setup/build-environment.yml
@@ -0,0 +1,98 @@
+---
+- name: Installation of basic packages to build QEMU
+  hosts: all
+  tasks:
+- name: Update apt cache
+  apt:
+update_cache: yes
+  when:
+- ansible_facts['distribution'] == 'Ubuntu'
+
+- name: Install basic packages to build QEMU on Ubuntu 18.04/20.04
+  package:
+name:
+# Originally from tests/docker/dockerfiles/ubuntu1804.docker
+  - ccache
+  - gcc
+  - gettext
+  - git
+  - glusterfs-common
+  - libaio-dev
+  - libattr1-dev
+  - libbrlapi-dev
+  - libbz2-dev
+  - libcacard-dev
+  - libcap-ng-dev
+  - libcurl4-gnutls-dev
+  - libdrm-dev
+  - libepoxy-dev
+  - libfdt-dev
+  - libgbm-dev
+  - libgtk-3-dev
+  - libibverbs-dev
+  - libiscsi-dev
+  - libjemalloc-dev
+  - libjpeg-turbo8-dev
+  - liblzo2-dev
+  - libncurses5-dev
+  - libncursesw5-dev
+  - libnfs-dev
+  - libnss3-dev
+  - libnuma-dev
+  - libpixman-1-dev
+  - librados-dev
+  - librbd-dev
+  - librdmacm-dev
+  - libsasl2-dev
+  - libsdl2-dev
+  - libseccomp-dev
+  - libsnappy-dev
+  - libspice-protocol-dev
+  - libssh-dev
+  - libusb-1.0-0-dev
+  - libusbredirhost-dev
+  - libvdeplug-dev
+  - libvte-2.91-dev
+  - libzstd-dev
+  - make
+  - python3-yaml
+  - python3-sphinx
+  - python3-sphinx-rtd-theme
+  - ninja-build
+  - sparse
+  - xfslibs-dev
+state: present
+  when:
+- ansible_facts['distribution'] == 'Ubuntu'
+
+- name: Install packages to build QEMU on Ubuntu 18.04/20.04 on non-s390x
+  package:
+name:
+  - libspice-server-dev
+  - libxen-dev
+state: present
+  when:
+- ansible_facts['distribution'] == 'Ubuntu'
+- ansible_facts['architecture'] != 's390x'
+
+- name: Install basic packages to build QEMU on Ubuntu 18.04
+  package:
+name:
+# Originally from tests/docker/dockerfiles/ubuntu1804.docker
+  - clang
+  when:
+- ansible_facts['distribution'] == 'Ubuntu'
+- ansible_facts['distribution_version'] == '18.04'
+
+- name: Install basic packages to build QEMU on Ubuntu 20.04
+  package:
+name:
+# Originally from tests/docker/dockerfiles/ubuntu2004.docker
+  - clang-10
+  - genisoimage
+  - liblttng-ust-dev
+  - libslirp-dev
+  - netcat-openbsd
+  when:
+- ansible_facts['distribution'] == 'Ubuntu'
+- 

[PATCH v6 0/4] GitLab Custom Runners and Jobs (was: QEMU Gating CI)

2021-06-07 Thread Cleber Rosa
TL;DR: this should allow the QEMU maintainer to push to the staging
branch, and have custom jobs running on the project's aarch64 and
s390x machines.  Jobs in this version are allowed to fail, to allow
for the inclusion of the novel machines/jobs without CI disruption.
Simple usage looks like:

   git push remote staging
   ./scripts/ci/gitlab-pipeline-status --verbose --wait

Long version:

The idea about a public facing Gating CI for QEMU was summarized in an
RFC[1].  Since then, it was decided that a simpler version should be
attempted first.

At this point, there are two specific runners (an aarch64 and an s390x)
registered with GitLab, at https://gitlab.com/qemu-project, currently
setup to the "qemu" repository.  To make it extra clear, the following
points deserve notice:

 - This work dealt with two different QEMU project machines:
I) s390x running Ubuntu 18.04
   II) aarch64 running Ubuntu 20.04

 - All CI jobs introduced here are allowed to fail.  It should have
   no impact on the overall PASS/FAIL result of the pipeline.

 - Both machines have already been completely configured used the code
   on this series.  No further action (besides pushing this code to
   the staging branch) is needed to have CI jobs executed on them.

 - The actual CI jobs to be executed are defined in this series,
   and map as best as possible the tests run by Peter Maydell on
   the staging branch.  Peter, given the time delta since the
   beginning of this work, it may be needed to further tweak
   them.

 - The actual results of CI jobs run from these definitions are
   probably more fluid than the results from the CI jobs run on the
   shared runners.  Both changes to the code being tested, and the
   conditions/resources of the machine should be taken into account.

 - A pipeline, and some of the jobs, can be seen on the links bellow.
   Besides successful jobs, it also contains jobs not started (set to
   manual, with the specific reasons noted later on the changes
   section):

   * https://gitlab.com/cleber.gnu/qemu/-/pipelines/316471691
- ubuntu-18.04-s390x-all: 
https://gitlab.com/cleber.gnu/qemu/-/jobs/1325698118
- ubuntu-20.04-aarch64-all: 
https://gitlab.com/cleber.gnu/qemu/-/jobs/1325698124

Changes from v5:

 - Moved include of ".gitlab-ci.d/custom-runners.yml" from
   ".gitlab-ci.yml" to ".gitlab-ci.d/qemu-project.yml"

 - Changed git clone strategy from "submodule recursive" to "clone",
   to guarantee a fresh and clean repo on every job, and let
   QEMU handle eventual needed recursive submodule operations

 - Require user to create an Ansible inventory file, based on the
   now provided "inventory.template" one.  Previously, the
   "iventory" file itself was provided and users were asked to edit
   it.

 - Registered runners will now be given a default set of tags, with
   their OS and architectures.  This, besides automating another step,
   works around a "gitlab-runner register" command line issue with
   "--run-untagged=false" not being respected if no tags are given.

 - Added conditional for installing either "clang" or "clang-10" to
   match the package name on different versions of Ubuntu.

 - Changed Ubuntu 20.04 jobs to use clang-10 instead of clang.

 - Defaults to not running untagged jobs when registering a gitlab
   runner.

 - Added python3-sphinx-rtd-theme package installation to
   build-environment.yml, to match 73e6aec6522.

 - Added genisoimage package installation to build-environment.yml
   when on Ubuntu 20.04 (not on 18.04) to match 7e86e5d5ccc.

 - Added liblttng-ust-dev package installation to
   build-environment.yml when on Ubuntu 20.04 (not on 18.04) to match
   8e9419b7902.

 - Added libslirp-dev package installation to build-environment.yml
   when on Ubuntu 20.04 (not on 18.04) to match 8e9419b7902.

 - Added netcat-openbsd package installation to build-environment.yml
   when on Ubuntu 20.04 (not on 18.04) to match c4cb1c9f2e1.

 - Bumped gitlab-runner version to 13.12.0

 - Use only gitlab-runner binaries from the official distribution (they
   are now also available for s390x, previously missing).

 - Selection of the OS and architecture for the gitlab-runner binary
   is now done automatically.  If necessary, architecture chosen can be
   influenced by editing the "ansible_to_gitlab_arch" values on vars.yml
   (after you've created one from the vars.yml.template).

 - Marked job "ubuntu-18.04-s390x-clang" as manual, given that
   the latest executions are getting stuck with the last
   output being "Sanitizers are enabled ==> Not running the
   qemu-iotests."

 - Marked job "ubuntu-18.04-s390x-notcg" as manual, given that the
   latest executions are getting stuck with the last tests being
   "tests/qtest/pxe-test" and "tests/qtest/boot-serial-test" which
   contains commands lines with "-accel kvm -accel tcg" and "-accel
   qtest".  Obviously tcg is disabled and KVM is not available on the
   QEMU s390x machine, and the fallback to qtest gets the tests 

Re: [PATCH 08/55] target/arm: Implement MVE DLSTP

2021-06-07 Thread Richard Henderson

On 6/7/21 9:57 AM, Peter Maydell wrote:

+{
+  # This is DLSTP
+  DLS 0  0 size:2 rn:4 1110   0001
+  LCTP    0  000  1110   0001
+}


Same comment with LCTP being the more specific encoding.
Either way,
Reviewed-by: Richard Henderson 


r~



Re: [PATCH] netdev: add more commands to preconfig mode

2021-06-07 Thread Jason Wang



在 2021/6/7 下午10:22, Daniel P. Berrangé 写道:

On Tue, May 11, 2021 at 11:39:55AM -0400, Paolo Bonzini wrote:

Creating and destroying network backend does not require a fully
constructed machine.  Allow the related monitor commands to run before
machine initialization has concluded.

Signed-off-by: Paolo Bonzini 
---
  hmp-commands.hx | 2 ++
  qapi/net.json   | 6 --
  2 files changed, 6 insertions(+), 2 deletions(-)

Reviewed-by: Daniel P. Berrangé 


Regards,
Daniel



Queued.

Thanks




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

2021-06-07 Thread Jason Wang



在 2021/6/6 上午1:19, Gautam Dawar 写道:

No user for this helper, let's remove it.

[GD>>]  These patches seem unrelated to me. Do you think they should be part of 
one patch series?



It doesn't harm.

I've queued this patch.

Thanks




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: [PATCH 1/2] vhost-vdpa: don't initialize backend_features

2021-06-07 Thread Jason Wang



在 2021/6/4 下午5:10, Gautam Dawar 写道:

Hi Jason,

-Original Message-
From: Jason Wang 
Sent: Wednesday, June 2, 2021 2:18 PM
To: Gautam Dawar ; m...@redhat.com; qemu-devel@nongnu.org
Cc: l...@redhat.com; qemu-sta...@nongnu.org
Subject: Re: [PATCH 1/2] vhost-vdpa: don't initialize backend_features

Hi Gautam:

在 2021/6/2 下午3:38, Gautam Dawar 写道:

Hi Jason,

Pls see my comments inline marked by GD>>

Regards,
Gautam

-Original Message-
From: Jason Wang 
Sent: Wednesday, June 2, 2021 9:01 AM
To: m...@redhat.com; qemu-devel@nongnu.org
Cc: Gautam Dawar ; l...@redhat.com; Jason Wang
; qemu-sta...@nongnu.org
Subject: [PATCH 1/2] vhost-vdpa: don't initialize backend_features

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;
[GD>>] Should this be initialized with 0 here? I am not sure if  memory 
allocated for struct vhost_dev is initialized with 0.


See vhost_net_init:

      struct vhost_net *net = g_new0(struct vhost_net, 1);

vhost_dev is embedded in the vhost_net structure. So I think it should be zero.

[GD>>]  That's correct. The embedded vhost_dev structure is indeed getting 
cleared to 0 in vhost_net_init().
Thanks



Ok, I've queued this patch.

Thanks






   v->listener = vhost_vdpa_memory_listener;
   v->msg_type = VHOST_IOTLB_MSG_V2;
   
--

2.25.1


[GD>>]
Signed-off-by: Gautam Dawar 
Acked-by: Gautam Dawar 






Re: [PATCH 07/55] target/arm: Implement MVE WLSTP insn

2021-06-07 Thread Richard Henderson

On 6/7/21 9:57 AM, Peter Maydell wrote:

+WLS   0  100 rn:4 1100 . .. 1 imm=%lob_imm 
size=4
+{
+  # This is WLSTP
+  WLS 0  0 size:2 rn:4 1100 . .. 1 imm=%lob_imm
+  LE  0  0 f:1 0  1100 . .. 1 imm=%lob_imm
+}


I guess it doesn't matter, but I'd swap these two, as LE is the more specific 
encoding.



@@ -8148,10 +8152,40 @@ static bool trans_WLS(DisasContext *s, arg_WLS *a)
   */
  return false;
  }
+if (a->size != 4) {
+/* WLSTP */
+if (!dc_isar_feature(aa32_mve, s)) {
+return false;
+}
+/*
+ * We need to check that the FPU is enabled here, but mustn't
+ * call vfp_access_check() to do that because we don't want to
+ * do the lazy state preservation in the "loop count is zero" case.
+ * Do the check-and-raise-exception by hand.
+ */
+if (s->fp_excp_el) {
+gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
+   syn_uncategorized(), s->fp_excp_el);
+}


Surely return true here...


+if (a->size != 4) {
+/*
+ * WLSTP: set FPSCR.LTPSIZE. This requires that we do the
+ * lazy state preservation, new FP context creation, etc,
+ * that vfp_access_check() does. We know that the actual
+ * access check will succeed (ie it won't generate code that
+ * throws an exception) because we did that check by hand earlier.
+ */
+bool ok = vfp_access_check(s);
+assert(ok);


... otherwise this assert will trigger.


r~
r~



[PULL 29/32] target/riscv: rvb: address calculation

2021-06-07 Thread Alistair Francis
From: Kito Cheng 

Signed-off-by: Kito Cheng 
Signed-off-by: Frank Chang 
Reviewed-by: Richard Henderson 
Message-id: 20210505160620.15723-15-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 target/riscv/insn32.decode  |  6 +
 target/riscv/translate.c| 32 +
 target/riscv/insn_trans/trans_rvb.c.inc | 24 +++
 3 files changed, 62 insertions(+)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index e6dab8dbbc..287920ee9b 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -686,6 +686,9 @@ ror011 .. 101 . 0110011 @r
 rol011 .. 001 . 0110011 @r
 grev   0110100 .. 101 . 0110011 @r
 gorc   0010100 .. 101 . 0110011 @r
+sh1add 001 .. 010 . 0110011 @r
+sh2add 001 .. 100 . 0110011 @r
+sh3add 001 .. 110 . 0110011 @r
 
 bseti  00101. ... 001 . 0010011 @sh
 bclri  01001. ... 001 . 0010011 @sh
@@ -714,6 +717,9 @@ rorw   011 .. 101 . 0111011 @r
 rolw   011 .. 001 . 0111011 @r
 grevw  0110100 .. 101 . 0111011 @r
 gorcw  0010100 .. 101 . 0111011 @r
+sh1add_uw  001 .. 010 . 0111011 @r
+sh2add_uw  001 .. 100 . 0111011 @r
+sh3add_uw  001 .. 110 . 0111011 @r
 
 bsetiw 0010100 .. 001 . 0011011 @sh5
 bclriw 0100100 .. 001 . 0011011 @sh5
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 35d4d36eef..ae9b5f7a2e 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -649,6 +649,21 @@ static bool gen_grevi(DisasContext *ctx, arg_grevi *a)
 return true;
 }
 
+#define GEN_SHADD(SHAMT)   \
+static void gen_sh##SHAMT##add(TCGv ret, TCGv arg1, TCGv arg2) \
+{  \
+TCGv t = tcg_temp_new();   \
+   \
+tcg_gen_shli_tl(t, arg1, SHAMT);   \
+tcg_gen_add_tl(ret, t, arg2);  \
+   \
+tcg_temp_free(t);  \
+}
+
+GEN_SHADD(1)
+GEN_SHADD(2)
+GEN_SHADD(3)
+
 static void gen_ctzw(TCGv ret, TCGv arg1)
 {
 tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32));
@@ -733,6 +748,23 @@ static void gen_gorcw(TCGv ret, TCGv arg1, TCGv arg2)
 gen_helper_gorcw(ret, arg1, arg2);
 }
 
+#define GEN_SHADD_UW(SHAMT)   \
+static void gen_sh##SHAMT##add_uw(TCGv ret, TCGv arg1, TCGv arg2) \
+{ \
+TCGv t = tcg_temp_new();  \
+  \
+tcg_gen_ext32u_tl(t, arg1);   \
+  \
+tcg_gen_shli_tl(t, t, SHAMT); \
+tcg_gen_add_tl(ret, t, arg2); \
+  \
+tcg_temp_free(t); \
+}
+
+GEN_SHADD_UW(1)
+GEN_SHADD_UW(2)
+GEN_SHADD_UW(3)
+
 static bool gen_arith(DisasContext *ctx, arg_r *a,
   void(*func)(TCGv, TCGv, TCGv))
 {
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc 
b/target/riscv/insn_trans/trans_rvb.c.inc
index ec9f9d2ef2..b27114a068 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -226,6 +226,17 @@ static bool trans_gorci(DisasContext *ctx, arg_gorci *a)
 return gen_shifti(ctx, a, gen_helper_gorc);
 }
 
+#define GEN_TRANS_SHADD(SHAMT) \
+static bool trans_sh##SHAMT##add(DisasContext *ctx, arg_sh##SHAMT##add *a) \
+{  \
+REQUIRE_EXT(ctx, RVB); \
+return gen_arith(ctx, a, gen_sh##SHAMT##add);  \
+}
+
+GEN_TRANS_SHADD(1)
+GEN_TRANS_SHADD(2)
+GEN_TRANS_SHADD(3)
+
 static bool trans_clzw(DisasContext *ctx, arg_clzw *a)
 {
 REQUIRE_64BIT(ctx);
@@ -386,3 +397,16 @@ static bool trans_gorciw(DisasContext *ctx, arg_gorciw *a)
 REQUIRE_EXT(ctx, RVB);
 return gen_shiftiw(ctx, a, gen_gorcw);
 }
+
+#define GEN_TRANS_SHADD_UW(SHAMT) \
+static bool trans_sh##SHAMT##add_uw(DisasContext *ctx,\
+arg_sh##SHAMT##add_uw *a) \
+{ \
+REQUIRE_64BIT(ctx);  

[PULL 31/32] target/riscv: rvb: support and turn on B-extension from command line

2021-06-07 Thread Alistair Francis
From: Kito Cheng 

B-extension is default off, use cpu rv32 or rv64 with x-b=true to
enable B-extension.

Signed-off-by: Kito Cheng 
Signed-off-by: Frank Chang 
Reviewed-by: Alistair Francis 
Reviewed-by: Richard Henderson 
Message-id: 20210505160620.15723-17-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h | 1 +
 target/riscv/cpu.c | 4 
 2 files changed, 5 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index c0c99c3d8d..de9262c930 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -286,6 +286,7 @@ struct RISCVCPU {
 bool ext_f;
 bool ext_d;
 bool ext_c;
+bool ext_b;
 bool ext_s;
 bool ext_u;
 bool ext_h;
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index ee2523f66b..5702c53c62 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -489,6 +489,9 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 if (cpu->cfg.ext_h) {
 target_misa |= RVH;
 }
+if (cpu->cfg.ext_b) {
+target_misa |= RVB;
+}
 if (cpu->cfg.ext_v) {
 target_misa |= RVV;
 if (!is_power_of_2(cpu->cfg.vlen)) {
@@ -559,6 +562,7 @@ static Property riscv_cpu_properties[] = {
 DEFINE_PROP_BOOL("s", RISCVCPU, cfg.ext_s, true),
 DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true),
 /* This is experimental so mark with 'x-' */
+DEFINE_PROP_BOOL("x-b", RISCVCPU, cfg.ext_b, false),
 DEFINE_PROP_BOOL("x-h", RISCVCPU, cfg.ext_h, false),
 DEFINE_PROP_BOOL("x-v", RISCVCPU, cfg.ext_v, false),
 DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true),
-- 
2.31.1




[PULL 27/32] target/riscv: rvb: generalized reverse

2021-06-07 Thread Alistair Francis
From: Frank Chang 

Signed-off-by: Frank Chang 
Reviewed-by: Richard Henderson 
Message-id: 20210505160620.15723-13-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 target/riscv/helper.h   |  4 ++
 target/riscv/insn32.decode  |  4 ++
 target/riscv/bitmanip_helper.c  | 64 +
 target/riscv/translate.c| 28 +++
 target/riscv/insn_trans/trans_rvb.c.inc | 31 
 target/riscv/meson.build|  1 +
 6 files changed, 132 insertions(+)
 create mode 100644 target/riscv/bitmanip_helper.c

diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index c7267593c3..f81b8faf3b 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -58,6 +58,10 @@ DEF_HELPER_FLAGS_2(fcvt_d_l, TCG_CALL_NO_RWG, i64, env, tl)
 DEF_HELPER_FLAGS_2(fcvt_d_lu, TCG_CALL_NO_RWG, i64, env, tl)
 DEF_HELPER_FLAGS_1(fclass_d, TCG_CALL_NO_RWG_SE, tl, i64)
 
+/* Bitmanip */
+DEF_HELPER_FLAGS_2(grev, TCG_CALL_NO_RWG_SE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(grevw, TCG_CALL_NO_RWG_SE, tl, tl, tl)
+
 /* Special functions */
 DEF_HELPER_3(csrrw, tl, env, tl, tl)
 DEF_HELPER_4(csrrs, tl, env, tl, tl, tl)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 71a9a182c0..6b5e276a9f 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -684,6 +684,7 @@ slo001 .. 001 . 0110011 @r
 sro001 .. 101 . 0110011 @r
 ror011 .. 101 . 0110011 @r
 rol011 .. 001 . 0110011 @r
+grev   0110100 .. 101 . 0110011 @r
 
 bseti  00101. ... 001 . 0010011 @sh
 bclri  01001. ... 001 . 0010011 @sh
@@ -692,6 +693,7 @@ bexti  01001. ... 101 . 0010011 @sh
 sloi   00100. ... 001 . 0010011 @sh
 sroi   00100. ... 101 . 0010011 @sh
 rori   01100. ... 101 . 0010011 @sh
+grevi  01101. ... 101 . 0010011 @sh
 
 # *** RV64B Standard Extension (in addition to RV32B) ***
 clzw   011 0 . 001 . 0011011 @r2
@@ -708,6 +710,7 @@ slow   001 .. 001 . 0111011 @r
 srow   001 .. 101 . 0111011 @r
 rorw   011 .. 101 . 0111011 @r
 rolw   011 .. 001 . 0111011 @r
+grevw  0110100 .. 101 . 0111011 @r
 
 bsetiw 0010100 .. 001 . 0011011 @sh5
 bclriw 0100100 .. 001 . 0011011 @sh5
@@ -715,3 +718,4 @@ binviw 0110100 .. 001 . 0011011 @sh5
 sloiw  001 .. 001 . 0011011 @sh5
 sroiw  001 .. 101 . 0011011 @sh5
 roriw  011 .. 101 . 0011011 @sh5
+greviw 0110100 .. 101 . 0011011 @sh5
diff --git a/target/riscv/bitmanip_helper.c b/target/riscv/bitmanip_helper.c
new file mode 100644
index 00..c625adaded
--- /dev/null
+++ b/target/riscv/bitmanip_helper.c
@@ -0,0 +1,64 @@
+/*
+ * RISC-V Bitmanip Extension Helpers for QEMU.
+ *
+ * Copyright (c) 2020 Kito Cheng, kito.ch...@sifive.com
+ * Copyright (c) 2020 Frank Chang, frank.ch...@sifive.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/host-utils.h"
+#include "exec/exec-all.h"
+#include "exec/helper-proto.h"
+#include "tcg/tcg.h"
+
+static const uint64_t adjacent_masks[] = {
+dup_const(MO_8, 0x55),
+dup_const(MO_8, 0x33),
+dup_const(MO_8, 0x0f),
+dup_const(MO_16, 0xff),
+dup_const(MO_32, 0x),
+UINT32_MAX
+};
+
+static inline target_ulong do_swap(target_ulong x, uint64_t mask, int shift)
+{
+return ((x & mask) << shift) | ((x & ~mask) >> shift);
+}
+
+static target_ulong do_grev(target_ulong rs1,
+target_ulong rs2,
+int bits)
+{
+target_ulong x = rs1;
+int i, shift;
+
+for (i = 0, shift = 1; shift < bits; i++, shift <<= 1) {
+if (rs2 & shift) {
+x = do_swap(x, adjacent_masks[i], shift);
+}
+}
+
+return x;
+}
+
+target_ulong HELPER(grev)(target_ulong rs1, target_ulong rs2)
+{
+return do_grev(rs1, rs2, TARGET_LONG_BITS);
+}
+
+target_ulong HELPER(grevw)(target_ulong rs1, target_ulong rs2)
+{
+return do_grev(rs1, rs2, 32);
+}
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 

[PULL 30/32] target/riscv: rvb: add/shift with prefix zero-extend

2021-06-07 Thread Alistair Francis
From: Kito Cheng 

Signed-off-by: Kito Cheng 
Signed-off-by: Frank Chang 
Reviewed-by: Richard Henderson 
Message-id: 20210505160620.15723-16-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 target/riscv/insn32.decode  |  3 +++
 target/riscv/translate.c|  6 ++
 target/riscv/insn_trans/trans_rvb.c.inc | 26 +
 3 files changed, 35 insertions(+)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 287920ee9b..f09f8d5faf 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -720,6 +720,7 @@ gorcw  0010100 .. 101 . 0111011 @r
 sh1add_uw  001 .. 010 . 0111011 @r
 sh2add_uw  001 .. 100 . 0111011 @r
 sh3add_uw  001 .. 110 . 0111011 @r
+add_uw 100 .. 000 . 0111011 @r
 
 bsetiw 0010100 .. 001 . 0011011 @sh5
 bclriw 0100100 .. 001 . 0011011 @sh5
@@ -729,3 +730,5 @@ sroiw  001 .. 101 . 0011011 @sh5
 roriw  011 .. 101 . 0011011 @sh5
 greviw 0110100 .. 101 . 0011011 @sh5
 gorciw 0010100 .. 101 . 0011011 @sh5
+
+slli_uw1. ... 001 . 0011011 @sh
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index ae9b5f7a2e..c6e8739614 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -765,6 +765,12 @@ GEN_SHADD_UW(1)
 GEN_SHADD_UW(2)
 GEN_SHADD_UW(3)
 
+static void gen_add_uw(TCGv ret, TCGv arg1, TCGv arg2)
+{
+tcg_gen_ext32u_tl(arg1, arg1);
+tcg_gen_add_tl(ret, arg1, arg2);
+}
+
 static bool gen_arith(DisasContext *ctx, arg_r *a,
   void(*func)(TCGv, TCGv, TCGv))
 {
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc 
b/target/riscv/insn_trans/trans_rvb.c.inc
index b27114a068..9e81f6e3de 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -410,3 +410,29 @@ static bool trans_sh##SHAMT##add_uw(DisasContext *ctx, 
   \
 GEN_TRANS_SHADD_UW(1)
 GEN_TRANS_SHADD_UW(2)
 GEN_TRANS_SHADD_UW(3)
+
+static bool trans_add_uw(DisasContext *ctx, arg_add_uw *a)
+{
+REQUIRE_64BIT(ctx);
+REQUIRE_EXT(ctx, RVB);
+return gen_arith(ctx, a, gen_add_uw);
+}
+
+static bool trans_slli_uw(DisasContext *ctx, arg_slli_uw *a)
+{
+REQUIRE_64BIT(ctx);
+REQUIRE_EXT(ctx, RVB);
+
+TCGv source1 = tcg_temp_new();
+gen_get_gpr(source1, a->rs1);
+
+if (a->shamt < 32) {
+tcg_gen_deposit_z_tl(source1, source1, a->shamt, 32);
+} else {
+tcg_gen_shli_tl(source1, source1, a->shamt);
+}
+
+gen_set_gpr(a->rd, source1);
+tcg_temp_free(source1);
+return true;
+}
-- 
2.31.1




[PULL 25/32] target/riscv: rvb: shift ones

2021-06-07 Thread Alistair Francis
From: Kito Cheng 

Signed-off-by: Kito Cheng 
Signed-off-by: Frank Chang 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Message-id: 20210505160620.15723-11-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 target/riscv/insn32.decode  |  8 
 target/riscv/translate.c| 14 +++
 target/riscv/insn_trans/trans_rvb.c.inc | 52 +
 3 files changed, 74 insertions(+)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 433b601b93..6bc9bbae9e 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -680,11 +680,15 @@ bset   0010100 .. 001 . 0110011 @r
 bclr   0100100 .. 001 . 0110011 @r
 binv   0110100 .. 001 . 0110011 @r
 bext   0100100 .. 101 . 0110011 @r
+slo001 .. 001 . 0110011 @r
+sro001 .. 101 . 0110011 @r
 
 bseti  00101. ... 001 . 0010011 @sh
 bclri  01001. ... 001 . 0010011 @sh
 binvi  01101. ... 001 . 0010011 @sh
 bexti  01001. ... 101 . 0010011 @sh
+sloi   00100. ... 001 . 0010011 @sh
+sroi   00100. ... 101 . 0010011 @sh
 
 # *** RV64B Standard Extension (in addition to RV32B) ***
 clzw   011 0 . 001 . 0011011 @r2
@@ -697,7 +701,11 @@ bsetw  0010100 .. 001 . 0111011 @r
 bclrw  0100100 .. 001 . 0111011 @r
 binvw  0110100 .. 001 . 0111011 @r
 bextw  0100100 .. 101 . 0111011 @r
+slow   001 .. 001 . 0111011 @r
+srow   001 .. 101 . 0111011 @r
 
 bsetiw 0010100 .. 001 . 0011011 @sh5
 bclriw 0100100 .. 001 . 0011011 @sh5
 binviw 0110100 .. 001 . 0011011 @sh5
+sloiw  001 .. 001 . 0011011 @sh5
+sroiw  001 .. 101 . 0011011 @sh5
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index e12240d125..088cf9f767 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -613,6 +613,20 @@ static void gen_bext(TCGv ret, TCGv arg1, TCGv shamt)
 tcg_gen_andi_tl(ret, ret, 1);
 }
 
+static void gen_slo(TCGv ret, TCGv arg1, TCGv arg2)
+{
+tcg_gen_not_tl(ret, arg1);
+tcg_gen_shl_tl(ret, ret, arg2);
+tcg_gen_not_tl(ret, ret);
+}
+
+static void gen_sro(TCGv ret, TCGv arg1, TCGv arg2)
+{
+tcg_gen_not_tl(ret, arg1);
+tcg_gen_shr_tl(ret, ret, arg2);
+tcg_gen_not_tl(ret, ret);
+}
+
 static void gen_ctzw(TCGv ret, TCGv arg1)
 {
 tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32));
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc 
b/target/riscv/insn_trans/trans_rvb.c.inc
index 69e5af44a1..28640322c4 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -155,6 +155,30 @@ static bool trans_bexti(DisasContext *ctx, arg_bexti *a)
 return gen_shifti(ctx, a, gen_bext);
 }
 
+static bool trans_slo(DisasContext *ctx, arg_slo *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_shift(ctx, a, gen_slo);
+}
+
+static bool trans_sloi(DisasContext *ctx, arg_sloi *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_shifti(ctx, a, gen_slo);
+}
+
+static bool trans_sro(DisasContext *ctx, arg_sro *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_shift(ctx, a, gen_sro);
+}
+
+static bool trans_sroi(DisasContext *ctx, arg_sroi *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_shifti(ctx, a, gen_sro);
+}
+
 static bool trans_clzw(DisasContext *ctx, arg_clzw *a)
 {
 REQUIRE_64BIT(ctx);
@@ -238,3 +262,31 @@ static bool trans_bextw(DisasContext *ctx, arg_bextw *a)
 REQUIRE_EXT(ctx, RVB);
 return gen_shiftw(ctx, a, gen_bext);
 }
+
+static bool trans_slow(DisasContext *ctx, arg_slow *a)
+{
+REQUIRE_64BIT(ctx);
+REQUIRE_EXT(ctx, RVB);
+return gen_shiftw(ctx, a, gen_slo);
+}
+
+static bool trans_sloiw(DisasContext *ctx, arg_sloiw *a)
+{
+REQUIRE_64BIT(ctx);
+REQUIRE_EXT(ctx, RVB);
+return gen_shiftiw(ctx, a, gen_slo);
+}
+
+static bool trans_srow(DisasContext *ctx, arg_srow *a)
+{
+REQUIRE_64BIT(ctx);
+REQUIRE_EXT(ctx, RVB);
+return gen_shiftw(ctx, a, gen_sro);
+}
+
+static bool trans_sroiw(DisasContext *ctx, arg_sroiw *a)
+{
+REQUIRE_64BIT(ctx);
+REQUIRE_EXT(ctx, RVB);
+return gen_shiftiw(ctx, a, gen_sro);
+}
-- 
2.31.1




[PULL 22/32] target/riscv: rvb: sign-extend instructions

2021-06-07 Thread Alistair Francis
From: Kito Cheng 

Signed-off-by: Kito Cheng 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Signed-off-by: Frank Chang 
Message-id: 20210505160620.15723-8-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 target/riscv/insn32.decode  |  3 +++
 target/riscv/insn_trans/trans_rvb.c.inc | 12 
 2 files changed, 15 insertions(+)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 81dfdfbafd..9361984634 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -663,6 +663,9 @@ vamomaxud_v 11100 . . . . 111 . 010 
@r_wdvm
 clz011000 00 . 001 . 0010011 @r2
 ctz011000 01 . 001 . 0010011 @r2
 cpop   011000 10 . 001 . 0010011 @r2
+sext_b 011000 000100 . 001 . 0010011 @r2
+sext_h 011000 000101 . 001 . 0010011 @r2
+
 andn   010 .. 111 . 0110011 @r
 orn010 .. 110 . 0110011 @r
 xnor   010 .. 100 . 0110011 @r
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc 
b/target/riscv/insn_trans/trans_rvb.c.inc
index 5a4fc02f70..3d594e8cb4 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -95,6 +95,18 @@ static bool trans_maxu(DisasContext *ctx, arg_maxu *a)
 return gen_arith(ctx, a, tcg_gen_umax_tl);
 }
 
+static bool trans_sext_b(DisasContext *ctx, arg_sext_b *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_unary(ctx, a, tcg_gen_ext8s_tl);
+}
+
+static bool trans_sext_h(DisasContext *ctx, arg_sext_h *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_unary(ctx, a, tcg_gen_ext16s_tl);
+}
+
 static bool trans_clzw(DisasContext *ctx, arg_clzw *a)
 {
 REQUIRE_64BIT(ctx);
-- 
2.31.1




[PULL 24/32] target/riscv: rvb: single-bit instructions

2021-06-07 Thread Alistair Francis
From: Frank Chang 

Signed-off-by: Kito Cheng 
Signed-off-by: Frank Chang 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Message-id: 20210505160620.15723-10-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 target/riscv/insn32.decode  | 17 +
 target/riscv/translate.c| 61 
 target/riscv/insn_trans/trans_rvb.c.inc | 97 +
 3 files changed, 175 insertions(+)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 9361984634..433b601b93 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -676,6 +676,15 @@ min101 .. 100 . 0110011 @r
 minu   101 .. 101 . 0110011 @r
 max101 .. 110 . 0110011 @r
 maxu   101 .. 111 . 0110011 @r
+bset   0010100 .. 001 . 0110011 @r
+bclr   0100100 .. 001 . 0110011 @r
+binv   0110100 .. 001 . 0110011 @r
+bext   0100100 .. 101 . 0110011 @r
+
+bseti  00101. ... 001 . 0010011 @sh
+bclri  01001. ... 001 . 0010011 @sh
+binvi  01101. ... 001 . 0010011 @sh
+bexti  01001. ... 101 . 0010011 @sh
 
 # *** RV64B Standard Extension (in addition to RV32B) ***
 clzw   011 0 . 001 . 0011011 @r2
@@ -684,3 +693,11 @@ cpopw  011 00010 . 001 . 0011011 @r2
 
 packw  100 .. 100 . 0111011 @r
 packuw 0100100 .. 100 . 0111011 @r
+bsetw  0010100 .. 001 . 0111011 @r
+bclrw  0100100 .. 001 . 0111011 @r
+binvw  0110100 .. 001 . 0111011 @r
+bextw  0100100 .. 101 . 0111011 @r
+
+bsetiw 0010100 .. 001 . 0011011 @sh5
+bclriw 0100100 .. 001 . 0011011 @sh5
+binviw 0110100 .. 001 . 0011011 @sh5
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 292cf09932..e12240d125 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -571,6 +571,48 @@ static void gen_packh(TCGv ret, TCGv arg1, TCGv arg2)
 tcg_temp_free(t);
 }
 
+static void gen_sbop_mask(TCGv ret, TCGv shamt)
+{
+tcg_gen_movi_tl(ret, 1);
+tcg_gen_shl_tl(ret, ret, shamt);
+}
+
+static void gen_bset(TCGv ret, TCGv arg1, TCGv shamt)
+{
+TCGv t = tcg_temp_new();
+
+gen_sbop_mask(t, shamt);
+tcg_gen_or_tl(ret, arg1, t);
+
+tcg_temp_free(t);
+}
+
+static void gen_bclr(TCGv ret, TCGv arg1, TCGv shamt)
+{
+TCGv t = tcg_temp_new();
+
+gen_sbop_mask(t, shamt);
+tcg_gen_andc_tl(ret, arg1, t);
+
+tcg_temp_free(t);
+}
+
+static void gen_binv(TCGv ret, TCGv arg1, TCGv shamt)
+{
+TCGv t = tcg_temp_new();
+
+gen_sbop_mask(t, shamt);
+tcg_gen_xor_tl(ret, arg1, t);
+
+tcg_temp_free(t);
+}
+
+static void gen_bext(TCGv ret, TCGv arg1, TCGv shamt)
+{
+tcg_gen_shr_tl(ret, arg1, shamt);
+tcg_gen_andi_tl(ret, ret, 1);
+}
+
 static void gen_ctzw(TCGv ret, TCGv arg1)
 {
 tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32));
@@ -673,6 +715,25 @@ static bool gen_shifti(DisasContext *ctx, arg_shift *a,
 return true;
 }
 
+static bool gen_shiftw(DisasContext *ctx, arg_r *a,
+   void(*func)(TCGv, TCGv, TCGv))
+{
+TCGv source1 = tcg_temp_new();
+TCGv source2 = tcg_temp_new();
+
+gen_get_gpr(source1, a->rs1);
+gen_get_gpr(source2, a->rs2);
+
+tcg_gen_andi_tl(source2, source2, 31);
+(*func)(source1, source1, source2);
+tcg_gen_ext32s_tl(source1, source1);
+
+gen_set_gpr(a->rd, source1);
+tcg_temp_free(source1);
+tcg_temp_free(source2);
+return true;
+}
+
 static bool gen_shiftiw(DisasContext *ctx, arg_shift *a,
 void(*func)(TCGv, TCGv, TCGv))
 {
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc 
b/target/riscv/insn_trans/trans_rvb.c.inc
index 3d594e8cb4..69e5af44a1 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -107,6 +107,54 @@ static bool trans_sext_h(DisasContext *ctx, arg_sext_h *a)
 return gen_unary(ctx, a, tcg_gen_ext16s_tl);
 }
 
+static bool trans_bset(DisasContext *ctx, arg_bset *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_shift(ctx, a, gen_bset);
+}
+
+static bool trans_bseti(DisasContext *ctx, arg_bseti *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_shifti(ctx, a, gen_bset);
+}
+
+static bool trans_bclr(DisasContext *ctx, arg_bclr *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_shift(ctx, a, gen_bclr);
+}
+
+static bool trans_bclri(DisasContext *ctx, arg_bclri *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_shifti(ctx, a, gen_bclr);
+}
+
+static bool trans_binv(DisasContext *ctx, arg_binv *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_shift(ctx, a, gen_binv);
+}
+
+static bool trans_binvi(DisasContext *ctx, arg_binvi *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return 

[PULL 32/32] target/riscv: rvb: add b-ext version cpu option

2021-06-07 Thread Alistair Francis
From: Frank Chang 

Default b-ext version is v0.93.

Signed-off-by: Frank Chang 
Reviewed-by: Alistair Francis 
Message-id: 20210505160620.15723-18-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h |  3 +++
 target/riscv/cpu.c | 23 +++
 2 files changed, 26 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index de9262c930..bf1c899c00 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -83,6 +83,7 @@ enum {
 #define PRIV_VERSION_1_10_0 0x00011000
 #define PRIV_VERSION_1_11_0 0x00011100
 
+#define BEXT_VERSION_0_93_0 0x9300
 #define VEXT_VERSION_0_07_1 0x0701
 
 enum {
@@ -132,6 +133,7 @@ struct CPURISCVState {
 target_ulong guest_phys_fault_addr;
 
 target_ulong priv_ver;
+target_ulong bext_ver;
 target_ulong vext_ver;
 target_ulong misa;
 target_ulong misa_mask;
@@ -297,6 +299,7 @@ struct RISCVCPU {
 
 char *priv_spec;
 char *user_spec;
+char *bext_spec;
 char *vext_spec;
 uint16_t vlen;
 uint16_t elen;
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 5702c53c62..991a6bb760 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -127,6 +127,11 @@ static void set_priv_version(CPURISCVState *env, int 
priv_ver)
 env->priv_ver = priv_ver;
 }
 
+static void set_bext_version(CPURISCVState *env, int bext_ver)
+{
+env->bext_ver = bext_ver;
+}
+
 static void set_vext_version(CPURISCVState *env, int vext_ver)
 {
 env->vext_ver = vext_ver;
@@ -388,6 +393,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 CPURISCVState *env = >env;
 RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
 int priv_version = PRIV_VERSION_1_11_0;
+int bext_version = BEXT_VERSION_0_93_0;
 int vext_version = VEXT_VERSION_0_07_1;
 target_ulong target_misa = env->misa;
 Error *local_err = NULL;
@@ -412,6 +418,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 }
 
 set_priv_version(env, priv_version);
+set_bext_version(env, bext_version);
 set_vext_version(env, vext_version);
 
 if (cpu->cfg.mmu) {
@@ -491,6 +498,21 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 }
 if (cpu->cfg.ext_b) {
 target_misa |= RVB;
+
+if (cpu->cfg.bext_spec) {
+if (!g_strcmp0(cpu->cfg.bext_spec, "v0.93")) {
+bext_version = BEXT_VERSION_0_93_0;
+} else {
+error_setg(errp,
+   "Unsupported bitmanip spec version '%s'",
+   cpu->cfg.bext_spec);
+return;
+}
+} else {
+qemu_log("bitmanip version is not specified, "
+ "use the default value v0.93\n");
+}
+set_bext_version(env, bext_version);
 }
 if (cpu->cfg.ext_v) {
 target_misa |= RVV;
@@ -569,6 +591,7 @@ static Property riscv_cpu_properties[] = {
 DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
 DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
 DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec),
+DEFINE_PROP_STRING("bext_spec", RISCVCPU, cfg.bext_spec),
 DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec),
 DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
 DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
-- 
2.31.1




[PULL 20/32] target/riscv: rvb: pack two words into one register

2021-06-07 Thread Alistair Francis
From: Kito Cheng 

Signed-off-by: Kito Cheng 
Signed-off-by: Frank Chang 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Message-id: 20210505160620.15723-6-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 target/riscv/insn32.decode  |  6 
 target/riscv/translate.c| 40 +
 target/riscv/insn_trans/trans_rvb.c.inc | 32 
 3 files changed, 78 insertions(+)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index a4d95ea621..9b2fd4b6fe 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -666,8 +666,14 @@ cpop   011000 10 . 001 . 0010011 @r2
 andn   010 .. 111 . 0110011 @r
 orn010 .. 110 . 0110011 @r
 xnor   010 .. 100 . 0110011 @r
+pack   100 .. 100 . 0110011 @r
+packu  0100100 .. 100 . 0110011 @r
+packh  100 .. 111 . 0110011 @r
 
 # *** RV64B Standard Extension (in addition to RV32B) ***
 clzw   011 0 . 001 . 0011011 @r2
 ctzw   011 1 . 001 . 0011011 @r2
 cpopw  011 00010 . 001 . 0011011 @r2
+
+packw  100 .. 100 . 0111011 @r
+packuw 0100100 .. 100 . 0111011 @r
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index c1a30c2172..5f1a3c694f 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -548,6 +548,29 @@ static bool gen_arith_div_uw(DisasContext *ctx, arg_r *a,
 return true;
 }
 
+static void gen_pack(TCGv ret, TCGv arg1, TCGv arg2)
+{
+tcg_gen_deposit_tl(ret, arg1, arg2,
+   TARGET_LONG_BITS / 2,
+   TARGET_LONG_BITS / 2);
+}
+
+static void gen_packu(TCGv ret, TCGv arg1, TCGv arg2)
+{
+TCGv t = tcg_temp_new();
+tcg_gen_shri_tl(t, arg1, TARGET_LONG_BITS / 2);
+tcg_gen_deposit_tl(ret, arg2, t, 0, TARGET_LONG_BITS / 2);
+tcg_temp_free(t);
+}
+
+static void gen_packh(TCGv ret, TCGv arg1, TCGv arg2)
+{
+TCGv t = tcg_temp_new();
+tcg_gen_ext8u_tl(t, arg2);
+tcg_gen_deposit_tl(ret, arg1, t, 8, TARGET_LONG_BITS - 8);
+tcg_temp_free(t);
+}
+
 static void gen_ctzw(TCGv ret, TCGv arg1)
 {
 tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32));
@@ -567,6 +590,23 @@ static void gen_cpopw(TCGv ret, TCGv arg1)
 tcg_gen_ctpop_tl(ret, arg1);
 }
 
+static void gen_packw(TCGv ret, TCGv arg1, TCGv arg2)
+{
+TCGv t = tcg_temp_new();
+tcg_gen_ext16s_tl(t, arg2);
+tcg_gen_deposit_tl(ret, arg1, t, 16, 48);
+tcg_temp_free(t);
+}
+
+static void gen_packuw(TCGv ret, TCGv arg1, TCGv arg2)
+{
+TCGv t = tcg_temp_new();
+tcg_gen_shri_tl(t, arg1, 16);
+tcg_gen_deposit_tl(ret, arg2, t, 0, 16);
+tcg_gen_ext32s_tl(ret, ret);
+tcg_temp_free(t);
+}
+
 static bool gen_arith(DisasContext *ctx, arg_r *a,
   void(*func)(TCGv, TCGv, TCGv))
 {
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc 
b/target/riscv/insn_trans/trans_rvb.c.inc
index b8676785c6..770205f96f 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -53,6 +53,24 @@ static bool trans_xnor(DisasContext *ctx, arg_xnor *a)
 return gen_arith(ctx, a, tcg_gen_eqv_tl);
 }
 
+static bool trans_pack(DisasContext *ctx, arg_pack *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_arith(ctx, a, gen_pack);
+}
+
+static bool trans_packu(DisasContext *ctx, arg_packu *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_arith(ctx, a, gen_packu);
+}
+
+static bool trans_packh(DisasContext *ctx, arg_packh *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_arith(ctx, a, gen_packh);
+}
+
 static bool trans_clzw(DisasContext *ctx, arg_clzw *a)
 {
 REQUIRE_64BIT(ctx);
@@ -73,3 +91,17 @@ static bool trans_cpopw(DisasContext *ctx, arg_cpopw *a)
 REQUIRE_EXT(ctx, RVB);
 return gen_unary(ctx, a, gen_cpopw);
 }
+
+static bool trans_packw(DisasContext *ctx, arg_packw *a)
+{
+REQUIRE_64BIT(ctx);
+REQUIRE_EXT(ctx, RVB);
+return gen_arith(ctx, a, gen_packw);
+}
+
+static bool trans_packuw(DisasContext *ctx, arg_packuw *a)
+{
+REQUIRE_64BIT(ctx);
+REQUIRE_EXT(ctx, RVB);
+return gen_arith(ctx, a, gen_packuw);
+}
-- 
2.31.1




[PULL 21/32] target/riscv: rvb: min/max instructions

2021-06-07 Thread Alistair Francis
From: Kito Cheng 

Signed-off-by: Kito Cheng 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Signed-off-by: Frank Chang 
Message-id: 20210505160620.15723-7-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 target/riscv/insn32.decode  |  4 
 target/riscv/insn_trans/trans_rvb.c.inc | 24 
 2 files changed, 28 insertions(+)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 9b2fd4b6fe..81dfdfbafd 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -669,6 +669,10 @@ xnor   010 .. 100 . 0110011 @r
 pack   100 .. 100 . 0110011 @r
 packu  0100100 .. 100 . 0110011 @r
 packh  100 .. 111 . 0110011 @r
+min101 .. 100 . 0110011 @r
+minu   101 .. 101 . 0110011 @r
+max101 .. 110 . 0110011 @r
+maxu   101 .. 111 . 0110011 @r
 
 # *** RV64B Standard Extension (in addition to RV32B) ***
 clzw   011 0 . 001 . 0011011 @r2
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc 
b/target/riscv/insn_trans/trans_rvb.c.inc
index 770205f96f..5a4fc02f70 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -71,6 +71,30 @@ static bool trans_packh(DisasContext *ctx, arg_packh *a)
 return gen_arith(ctx, a, gen_packh);
 }
 
+static bool trans_min(DisasContext *ctx, arg_min *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_arith(ctx, a, tcg_gen_smin_tl);
+}
+
+static bool trans_max(DisasContext *ctx, arg_max *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_arith(ctx, a, tcg_gen_smax_tl);
+}
+
+static bool trans_minu(DisasContext *ctx, arg_minu *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_arith(ctx, a, tcg_gen_umin_tl);
+}
+
+static bool trans_maxu(DisasContext *ctx, arg_maxu *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_arith(ctx, a, tcg_gen_umax_tl);
+}
+
 static bool trans_clzw(DisasContext *ctx, arg_clzw *a)
 {
 REQUIRE_64BIT(ctx);
-- 
2.31.1




[PULL 28/32] target/riscv: rvb: generalized or-combine

2021-06-07 Thread Alistair Francis
From: Frank Chang 

Signed-off-by: Frank Chang 
Reviewed-by: Richard Henderson 
Message-id: 20210505160620.15723-14-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 target/riscv/helper.h   |  2 ++
 target/riscv/insn32.decode  |  4 
 target/riscv/bitmanip_helper.c  | 26 +
 target/riscv/translate.c|  6 ++
 target/riscv/insn_trans/trans_rvb.c.inc | 26 +
 5 files changed, 64 insertions(+)

diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index f81b8faf3b..415e37bc37 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -61,6 +61,8 @@ DEF_HELPER_FLAGS_1(fclass_d, TCG_CALL_NO_RWG_SE, tl, i64)
 /* Bitmanip */
 DEF_HELPER_FLAGS_2(grev, TCG_CALL_NO_RWG_SE, tl, tl, tl)
 DEF_HELPER_FLAGS_2(grevw, TCG_CALL_NO_RWG_SE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(gorc, TCG_CALL_NO_RWG_SE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(gorcw, TCG_CALL_NO_RWG_SE, tl, tl, tl)
 
 /* Special functions */
 DEF_HELPER_3(csrrw, tl, env, tl, tl)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 6b5e276a9f..e6dab8dbbc 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -685,6 +685,7 @@ sro001 .. 101 . 0110011 @r
 ror011 .. 101 . 0110011 @r
 rol011 .. 001 . 0110011 @r
 grev   0110100 .. 101 . 0110011 @r
+gorc   0010100 .. 101 . 0110011 @r
 
 bseti  00101. ... 001 . 0010011 @sh
 bclri  01001. ... 001 . 0010011 @sh
@@ -694,6 +695,7 @@ sloi   00100. ... 001 . 0010011 @sh
 sroi   00100. ... 101 . 0010011 @sh
 rori   01100. ... 101 . 0010011 @sh
 grevi  01101. ... 101 . 0010011 @sh
+gorci  00101. ... 101 . 0010011 @sh
 
 # *** RV64B Standard Extension (in addition to RV32B) ***
 clzw   011 0 . 001 . 0011011 @r2
@@ -711,6 +713,7 @@ srow   001 .. 101 . 0111011 @r
 rorw   011 .. 101 . 0111011 @r
 rolw   011 .. 001 . 0111011 @r
 grevw  0110100 .. 101 . 0111011 @r
+gorcw  0010100 .. 101 . 0111011 @r
 
 bsetiw 0010100 .. 001 . 0011011 @sh5
 bclriw 0100100 .. 001 . 0011011 @sh5
@@ -719,3 +722,4 @@ sloiw  001 .. 001 . 0011011 @sh5
 sroiw  001 .. 101 . 0011011 @sh5
 roriw  011 .. 101 . 0011011 @sh5
 greviw 0110100 .. 101 . 0011011 @sh5
+gorciw 0010100 .. 101 . 0011011 @sh5
diff --git a/target/riscv/bitmanip_helper.c b/target/riscv/bitmanip_helper.c
index c625adaded..5b2f795d03 100644
--- a/target/riscv/bitmanip_helper.c
+++ b/target/riscv/bitmanip_helper.c
@@ -62,3 +62,29 @@ target_ulong HELPER(grevw)(target_ulong rs1, target_ulong 
rs2)
 {
 return do_grev(rs1, rs2, 32);
 }
+
+static target_ulong do_gorc(target_ulong rs1,
+target_ulong rs2,
+int bits)
+{
+target_ulong x = rs1;
+int i, shift;
+
+for (i = 0, shift = 1; shift < bits; i++, shift <<= 1) {
+if (rs2 & shift) {
+x |= do_swap(x, adjacent_masks[i], shift);
+}
+}
+
+return x;
+}
+
+target_ulong HELPER(gorc)(target_ulong rs1, target_ulong rs2)
+{
+return do_gorc(rs1, rs2, TARGET_LONG_BITS);
+}
+
+target_ulong HELPER(gorcw)(target_ulong rs1, target_ulong rs2)
+{
+return do_gorc(rs1, rs2, 32);
+}
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 8deb05add4..35d4d36eef 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -727,6 +727,12 @@ static void gen_grevw(TCGv ret, TCGv arg1, TCGv arg2)
 gen_helper_grev(ret, arg1, arg2);
 }
 
+static void gen_gorcw(TCGv ret, TCGv arg1, TCGv arg2)
+{
+tcg_gen_ext32u_tl(arg1, arg1);
+gen_helper_gorcw(ret, arg1, arg2);
+}
+
 static bool gen_arith(DisasContext *ctx, arg_r *a,
   void(*func)(TCGv, TCGv, TCGv))
 {
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc 
b/target/riscv/insn_trans/trans_rvb.c.inc
index 281e0ffae9..ec9f9d2ef2 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -214,6 +214,18 @@ static bool trans_grevi(DisasContext *ctx, arg_grevi *a)
 return gen_grevi(ctx, a);
 }
 
+static bool trans_gorc(DisasContext *ctx, arg_gorc *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_shift(ctx, a, gen_helper_gorc);
+}
+
+static bool trans_gorci(DisasContext *ctx, arg_gorci *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_shifti(ctx, a, gen_helper_gorc);
+}
+
 static bool trans_clzw(DisasContext *ctx, arg_clzw *a)
 {
 REQUIRE_64BIT(ctx);
@@ -360,3 +372,17 @@ static bool trans_greviw(DisasContext *ctx, arg_greviw *a)
 REQUIRE_EXT(ctx, RVB);
 return gen_shiftiw(ctx, a, gen_grevw);
 }
+
+static bool 

[PULL 18/32] target/riscv: rvb: count bits set

2021-06-07 Thread Alistair Francis
From: Frank Chang 

Signed-off-by: Kito Cheng 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Signed-off-by: Frank Chang 
Message-id: 20210505160620.15723-4-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 target/riscv/insn32.decode  |  2 ++
 target/riscv/translate.c|  6 ++
 target/riscv/insn_trans/trans_rvb.c.inc | 13 +
 3 files changed, 21 insertions(+)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 9a2ffab150..6f7671872d 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -662,7 +662,9 @@ vamomaxud_v 11100 . . . . 111 . 010 
@r_wdvm
 # *** RV32B Standard Extension ***
 clz011000 00 . 001 . 0010011 @r2
 ctz011000 01 . 001 . 0010011 @r2
+cpop   011000 10 . 001 . 0010011 @r2
 
 # *** RV64B Standard Extension (in addition to RV32B) ***
 clzw   011 0 . 001 . 0011011 @r2
 ctzw   011 1 . 001 . 0011011 @r2
+cpopw  011 00010 . 001 . 0011011 @r2
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 60fac0fe27..c1a30c2172 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -561,6 +561,12 @@ static void gen_clzw(TCGv ret, TCGv arg1)
 tcg_gen_subi_tl(ret, ret, 32);
 }
 
+static void gen_cpopw(TCGv ret, TCGv arg1)
+{
+tcg_gen_ext32u_tl(arg1, arg1);
+tcg_gen_ctpop_tl(ret, arg1);
+}
+
 static bool gen_arith(DisasContext *ctx, arg_r *a,
   void(*func)(TCGv, TCGv, TCGv))
 {
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc 
b/target/riscv/insn_trans/trans_rvb.c.inc
index 157b4e3c41..4a5d271b43 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -29,6 +29,12 @@ static bool trans_ctz(DisasContext *ctx, arg_ctz *a)
 return gen_unary(ctx, a, gen_ctz);
 }
 
+static bool trans_cpop(DisasContext *ctx, arg_cpop *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_unary(ctx, a, tcg_gen_ctpop_tl);
+}
+
 static bool trans_clzw(DisasContext *ctx, arg_clzw *a)
 {
 REQUIRE_64BIT(ctx);
@@ -42,3 +48,10 @@ static bool trans_ctzw(DisasContext *ctx, arg_ctzw *a)
 REQUIRE_EXT(ctx, RVB);
 return gen_unary(ctx, a, gen_ctzw);
 }
+
+static bool trans_cpopw(DisasContext *ctx, arg_cpopw *a)
+{
+REQUIRE_64BIT(ctx);
+REQUIRE_EXT(ctx, RVB);
+return gen_unary(ctx, a, gen_cpopw);
+}
-- 
2.31.1




[PULL 19/32] target/riscv: rvb: logic-with-negate

2021-06-07 Thread Alistair Francis
From: Kito Cheng 

Signed-off-by: Kito Cheng 
Signed-off-by: Frank Chang 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Message-id: 20210505160620.15723-5-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 target/riscv/insn32.decode  |  3 +++
 target/riscv/insn_trans/trans_rvb.c.inc | 18 ++
 2 files changed, 21 insertions(+)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 6f7671872d..a4d95ea621 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -663,6 +663,9 @@ vamomaxud_v 11100 . . . . 111 . 010 
@r_wdvm
 clz011000 00 . 001 . 0010011 @r2
 ctz011000 01 . 001 . 0010011 @r2
 cpop   011000 10 . 001 . 0010011 @r2
+andn   010 .. 111 . 0110011 @r
+orn010 .. 110 . 0110011 @r
+xnor   010 .. 100 . 0110011 @r
 
 # *** RV64B Standard Extension (in addition to RV32B) ***
 clzw   011 0 . 001 . 0011011 @r2
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc 
b/target/riscv/insn_trans/trans_rvb.c.inc
index 4a5d271b43..b8676785c6 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -35,6 +35,24 @@ static bool trans_cpop(DisasContext *ctx, arg_cpop *a)
 return gen_unary(ctx, a, tcg_gen_ctpop_tl);
 }
 
+static bool trans_andn(DisasContext *ctx, arg_andn *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_arith(ctx, a, tcg_gen_andc_tl);
+}
+
+static bool trans_orn(DisasContext *ctx, arg_orn *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_arith(ctx, a, tcg_gen_orc_tl);
+}
+
+static bool trans_xnor(DisasContext *ctx, arg_xnor *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_arith(ctx, a, tcg_gen_eqv_tl);
+}
+
 static bool trans_clzw(DisasContext *ctx, arg_clzw *a)
 {
 REQUIRE_64BIT(ctx);
-- 
2.31.1




[PULL 26/32] target/riscv: rvb: rotate (left/right)

2021-06-07 Thread Alistair Francis
From: Kito Cheng 

Signed-off-by: Kito Cheng 
Signed-off-by: Frank Chang 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Message-id: 20210505160620.15723-12-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 target/riscv/insn32.decode  |  6 
 target/riscv/translate.c| 36 +++
 target/riscv/insn_trans/trans_rvb.c.inc | 39 +
 3 files changed, 81 insertions(+)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 6bc9bbae9e..71a9a182c0 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -682,6 +682,8 @@ binv   0110100 .. 001 . 0110011 @r
 bext   0100100 .. 101 . 0110011 @r
 slo001 .. 001 . 0110011 @r
 sro001 .. 101 . 0110011 @r
+ror011 .. 101 . 0110011 @r
+rol011 .. 001 . 0110011 @r
 
 bseti  00101. ... 001 . 0010011 @sh
 bclri  01001. ... 001 . 0010011 @sh
@@ -689,6 +691,7 @@ binvi  01101. ... 001 . 0010011 @sh
 bexti  01001. ... 101 . 0010011 @sh
 sloi   00100. ... 001 . 0010011 @sh
 sroi   00100. ... 101 . 0010011 @sh
+rori   01100. ... 101 . 0010011 @sh
 
 # *** RV64B Standard Extension (in addition to RV32B) ***
 clzw   011 0 . 001 . 0011011 @r2
@@ -703,9 +706,12 @@ binvw  0110100 .. 001 . 0111011 @r
 bextw  0100100 .. 101 . 0111011 @r
 slow   001 .. 001 . 0111011 @r
 srow   001 .. 101 . 0111011 @r
+rorw   011 .. 101 . 0111011 @r
+rolw   011 .. 001 . 0111011 @r
 
 bsetiw 0010100 .. 001 . 0011011 @sh5
 bclriw 0100100 .. 001 . 0011011 @sh5
 binviw 0110100 .. 001 . 0011011 @sh5
 sloiw  001 .. 001 . 0011011 @sh5
 sroiw  001 .. 101 . 0011011 @sh5
+roriw  011 .. 101 . 0011011 @sh5
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 088cf9f767..c09b93f1b8 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -663,6 +663,42 @@ static void gen_packuw(TCGv ret, TCGv arg1, TCGv arg2)
 tcg_temp_free(t);
 }
 
+static void gen_rorw(TCGv ret, TCGv arg1, TCGv arg2)
+{
+TCGv_i32 t1 = tcg_temp_new_i32();
+TCGv_i32 t2 = tcg_temp_new_i32();
+
+/* truncate to 32-bits */
+tcg_gen_trunc_tl_i32(t1, arg1);
+tcg_gen_trunc_tl_i32(t2, arg2);
+
+tcg_gen_rotr_i32(t1, t1, t2);
+
+/* sign-extend 64-bits */
+tcg_gen_ext_i32_tl(ret, t1);
+
+tcg_temp_free_i32(t1);
+tcg_temp_free_i32(t2);
+}
+
+static void gen_rolw(TCGv ret, TCGv arg1, TCGv arg2)
+{
+TCGv_i32 t1 = tcg_temp_new_i32();
+TCGv_i32 t2 = tcg_temp_new_i32();
+
+/* truncate to 32-bits */
+tcg_gen_trunc_tl_i32(t1, arg1);
+tcg_gen_trunc_tl_i32(t2, arg2);
+
+tcg_gen_rotl_i32(t1, t1, t2);
+
+/* sign-extend 64-bits */
+tcg_gen_ext_i32_tl(ret, t1);
+
+tcg_temp_free_i32(t1);
+tcg_temp_free_i32(t2);
+}
+
 static bool gen_arith(DisasContext *ctx, arg_r *a,
   void(*func)(TCGv, TCGv, TCGv))
 {
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc 
b/target/riscv/insn_trans/trans_rvb.c.inc
index 28640322c4..429738db15 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -179,6 +179,24 @@ static bool trans_sroi(DisasContext *ctx, arg_sroi *a)
 return gen_shifti(ctx, a, gen_sro);
 }
 
+static bool trans_ror(DisasContext *ctx, arg_ror *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_shift(ctx, a, tcg_gen_rotr_tl);
+}
+
+static bool trans_rori(DisasContext *ctx, arg_rori *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_shifti(ctx, a, tcg_gen_rotr_tl);
+}
+
+static bool trans_rol(DisasContext *ctx, arg_rol *a)
+{
+REQUIRE_EXT(ctx, RVB);
+return gen_shift(ctx, a, tcg_gen_rotl_tl);
+}
+
 static bool trans_clzw(DisasContext *ctx, arg_clzw *a)
 {
 REQUIRE_64BIT(ctx);
@@ -290,3 +308,24 @@ static bool trans_sroiw(DisasContext *ctx, arg_sroiw *a)
 REQUIRE_EXT(ctx, RVB);
 return gen_shiftiw(ctx, a, gen_sro);
 }
+
+static bool trans_rorw(DisasContext *ctx, arg_rorw *a)
+{
+REQUIRE_64BIT(ctx);
+REQUIRE_EXT(ctx, RVB);
+return gen_shiftw(ctx, a, gen_rorw);
+}
+
+static bool trans_roriw(DisasContext *ctx, arg_roriw *a)
+{
+REQUIRE_64BIT(ctx);
+REQUIRE_EXT(ctx, RVB);
+return gen_shiftiw(ctx, a, gen_rorw);
+}
+
+static bool trans_rolw(DisasContext *ctx, arg_rolw *a)
+{
+REQUIRE_64BIT(ctx);
+REQUIRE_EXT(ctx, RVB);
+return gen_shiftw(ctx, a, gen_rolw);
+}
-- 
2.31.1




[PULL 16/32] target/riscv: reformat @sh format encoding for B-extension

2021-06-07 Thread Alistair Francis
From: Kito Cheng 

Signed-off-by: Kito Cheng 
Signed-off-by: Frank Chang 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Message-id: 20210505160620.15723-2-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 target/riscv/insn32.decode | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 8901ba1e1b..f75642bb0d 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -23,7 +23,7 @@
 %rd7:5
 %sh5   20:5
 
-%sh1020:10
+%sh720:7
 %csr20:12
 %rm 12:3
 %nf 29:3 !function=ex_plus_1
@@ -59,7 +59,7 @@
 @u     . ...   imm=%imm_u  
%rd
 @j     . ...   imm=%imm_j  
%rd
 
-@sh  ..  .. .  ... . ...   shamt=%sh10  %rs1 
%rd
+@sh  ..  .. .  ... . ...   shamt=%sh7 %rs1 
%rd
 @csr    .  ... . ...   %csr %rs1 
%rd
 
 @atom_ld . aq:1 rl:1 .  . ...  rs2=0 %rs1 
%rd
@@ -125,9 +125,9 @@ sltiu . 011 . 0010011 @i
 xori  . 100 . 0010011 @i
 ori   . 110 . 0010011 @i
 andi  . 111 . 0010011 @i
-slli 00 ... 001 . 0010011 @sh
-srli 00 ... 101 . 0010011 @sh
-srai 01 ... 101 . 0010011 @sh
+slli 0. ... 001 . 0010011 @sh
+srli 0. ... 101 . 0010011 @sh
+srai 01000. ... 101 . 0010011 @sh
 add  000 .. 000 . 0110011 @r
 sub  010 .. 000 . 0110011 @r
 sll  000 .. 001 . 0110011 @r
-- 
2.31.1




[PULL 15/32] target/riscv: Pass the same value to oprsz and maxsz.

2021-06-07 Thread Alistair Francis
From: LIU Zhiwei 

Since commit e2e7168a214b0ed98dc357bba96816486a289762, if oprsz
is still zero(as we don't use this field), simd_desc will trigger an
assert.

Besides, tcg_gen_gvec_*_ptr calls simd_desc in it's implementation.
Here we pass the value to maxsz and oprsz to bypass the assert.

Signed-off-by: LIU Zhiwei 
Reviewed-by: Richard Henderson 
Message-id: 20210521054816.1784297-1-zhiwei_...@c-sky.com
Signed-off-by: Alistair Francis 
---
 target/riscv/insn_trans/trans_rvv.c.inc | 89 ++---
 1 file changed, 50 insertions(+), 39 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvv.c.inc 
b/target/riscv/insn_trans/trans_rvv.c.inc
index 47914a3b69..83d9a285ba 100644
--- a/target/riscv/insn_trans/trans_rvv.c.inc
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
@@ -183,7 +183,7 @@ static bool ldst_us_trans(uint32_t vd, uint32_t rs1, 
uint32_t data,
  * The first part is vlen in bytes, encoded in maxsz of simd_desc.
  * The second part is lmul, encoded in data of simd_desc.
  */
-desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data));
+desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
 
 gen_get_gpr(base, rs1);
 tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
@@ -334,7 +334,7 @@ static bool ldst_stride_trans(uint32_t vd, uint32_t rs1, 
uint32_t rs2,
 mask = tcg_temp_new_ptr();
 base = tcg_temp_new();
 stride = tcg_temp_new();
-desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data));
+desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
 
 gen_get_gpr(base, rs1);
 gen_get_gpr(stride, rs2);
@@ -462,7 +462,7 @@ static bool ldst_index_trans(uint32_t vd, uint32_t rs1, 
uint32_t vs2,
 mask = tcg_temp_new_ptr();
 index = tcg_temp_new_ptr();
 base = tcg_temp_new();
-desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data));
+desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
 
 gen_get_gpr(base, rs1);
 tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
@@ -594,7 +594,7 @@ static bool ldff_trans(uint32_t vd, uint32_t rs1, uint32_t 
data,
 dest = tcg_temp_new_ptr();
 mask = tcg_temp_new_ptr();
 base = tcg_temp_new();
-desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data));
+desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
 
 gen_get_gpr(base, rs1);
 tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
@@ -671,7 +671,7 @@ static bool amo_trans(uint32_t vd, uint32_t rs1, uint32_t 
vs2,
 mask = tcg_temp_new_ptr();
 index = tcg_temp_new_ptr();
 base = tcg_temp_new();
-desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data));
+desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
 
 gen_get_gpr(base, rs1);
 tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
@@ -831,7 +831,7 @@ do_opivv_gvec(DisasContext *s, arg_rmrr *a, GVecGen3Fn 
*gvec_fn,
 data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
 tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2),
-   cpu_env, 0, s->vlen / 8, data, fn);
+   cpu_env, s->vlen / 8, s->vlen / 8, data, fn);
 }
 gen_set_label(over);
 return true;
@@ -874,7 +874,7 @@ static bool opivx_trans(uint32_t vd, uint32_t rs1, uint32_t 
vs2, uint32_t vm,
 data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
 data = FIELD_DP32(data, VDATA, VM, vm);
 data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
-desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data));
+desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
 
 tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
 tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2));
@@ -1021,7 +1021,7 @@ static bool opivi_trans(uint32_t vd, uint32_t imm, 
uint32_t vs2, uint32_t vm,
 data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
 data = FIELD_DP32(data, VDATA, VM, vm);
 data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
-desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data));
+desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
 
 tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
 tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2));
@@ -1119,7 +1119,7 @@ static bool do_opivv_widen(DisasContext *s, arg_rmrr *a,
 tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
vreg_ofs(s, a->rs1),
vreg_ofs(s, a->rs2),
-   cpu_env, 0, s->vlen / 8,
+   cpu_env, s->vlen / 8, s->vlen / 8,
data, fn);
 gen_set_label(over);
 return true;
@@ -1207,7 +1207,7 @@ static bool do_opiwv_widen(DisasContext *s, arg_rmrr *a,
 tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
vreg_ofs(s, a->rs1),
vreg_ofs(s, a->rs2),
-   cpu_env, 0, s->vlen / 8, 

[PULL 17/32] target/riscv: rvb: count leading/trailing zeros

2021-06-07 Thread Alistair Francis
From: Kito Cheng 

Signed-off-by: Kito Cheng 
Signed-off-by: Frank Chang 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Message-id: 20210505160620.15723-3-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h  |  1 +
 target/riscv/insn32.decode  | 11 ++-
 target/riscv/translate.c| 38 +
 target/riscv/insn_trans/trans_rvb.c.inc | 44 +
 4 files changed, 93 insertions(+), 1 deletion(-)
 create mode 100644 target/riscv/insn_trans/trans_rvb.c.inc

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 0b22b0a523..c0c99c3d8d 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -67,6 +67,7 @@
 #define RVS RV('S')
 #define RVU RV('U')
 #define RVH RV('H')
+#define RVB RV('B')
 
 /* S extension denotes that Supervisor mode exists, however it is possible
to have a core that support S mode but does not have an MMU and there
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index f75642bb0d..9a2ffab150 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -41,6 +41,7 @@
 imm rs1 rd
 imm rd
 rd rs1 rs2
+   rd rs1
 imm rs1 rs2
 imm rd
  shamt rs1 rd
@@ -68,7 +69,7 @@
 @r4_rm   . ..  . . ... . ... %rs3 %rs2 %rs1 %rm %rd
 @r_rm...   . . ... . ... %rs2 %rs1 %rm %rd
 @r2_rm   ...   . . ... . ... %rs1 %rm %rd
-@r2  ...   . . ... . ... %rs1 %rd
+@r2  ...   . . ... . ...  %rs1 %rd
 @r2_nfvm ... ... vm:1 . . ... . ...  %nf %rs1 %rd
 @r2_vm   .. vm:1 . . ... . ...  %rs2 %rd
 @r1_vm   .. vm:1 . . ... . ... %rd
@@ -657,3 +658,11 @@ vamomind_v  1 . . . . 111 . 010 
@r_wdvm
 vamomaxd_v  10100 . . . . 111 . 010 @r_wdvm
 vamominud_v 11000 . . . . 111 . 010 @r_wdvm
 vamomaxud_v 11100 . . . . 111 . 010 @r_wdvm
+
+# *** RV32B Standard Extension ***
+clz011000 00 . 001 . 0010011 @r2
+ctz011000 01 . 001 . 0010011 @r2
+
+# *** RV64B Standard Extension (in addition to RV32B) ***
+clzw   011 0 . 001 . 0011011 @r2
+ctzw   011 1 . 001 . 0011011 @r2
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index e945352bca..60fac0fe27 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -548,6 +548,19 @@ static bool gen_arith_div_uw(DisasContext *ctx, arg_r *a,
 return true;
 }
 
+static void gen_ctzw(TCGv ret, TCGv arg1)
+{
+tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32));
+tcg_gen_ctzi_tl(ret, ret, 64);
+}
+
+static void gen_clzw(TCGv ret, TCGv arg1)
+{
+tcg_gen_ext32u_tl(ret, arg1);
+tcg_gen_clzi_tl(ret, ret, 64);
+tcg_gen_subi_tl(ret, ret, 32);
+}
+
 static bool gen_arith(DisasContext *ctx, arg_r *a,
   void(*func)(TCGv, TCGv, TCGv))
 {
@@ -593,6 +606,30 @@ static uint32_t opcode_at(DisasContextBase *dcbase, 
target_ulong pc)
 return cpu_ldl_code(env, pc);
 }
 
+static void gen_ctz(TCGv ret, TCGv arg1)
+{
+tcg_gen_ctzi_tl(ret, arg1, TARGET_LONG_BITS);
+}
+
+static void gen_clz(TCGv ret, TCGv arg1)
+{
+tcg_gen_clzi_tl(ret, arg1, TARGET_LONG_BITS);
+}
+
+static bool gen_unary(DisasContext *ctx, arg_r2 *a,
+  void(*func)(TCGv, TCGv))
+{
+TCGv source = tcg_temp_new();
+
+gen_get_gpr(source, a->rs1);
+
+(*func)(source, source);
+
+gen_set_gpr(a->rd, source);
+tcg_temp_free(source);
+return true;
+}
+
 /* Include insn module translation function */
 #include "insn_trans/trans_rvi.c.inc"
 #include "insn_trans/trans_rvm.c.inc"
@@ -601,6 +638,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, 
target_ulong pc)
 #include "insn_trans/trans_rvd.c.inc"
 #include "insn_trans/trans_rvh.c.inc"
 #include "insn_trans/trans_rvv.c.inc"
+#include "insn_trans/trans_rvb.c.inc"
 #include "insn_trans/trans_privileged.c.inc"
 
 /* Include the auto-generated decoder for 16 bit insn */
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc 
b/target/riscv/insn_trans/trans_rvb.c.inc
new file mode 100644
index 00..157b4e3c41
--- /dev/null
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -0,0 +1,44 @@
+/*
+ * RISC-V translation routines for the RVB Standard Extension.
+ *
+ * Copyright (c) 2020 Kito Cheng, kito.ch...@sifive.com
+ * Copyright (c) 2020 Frank Chang, frank.ch...@sifive.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR 

[PULL 12/32] target/riscv: Remove unnecessary riscv_*_names[] declaration

2021-06-07 Thread Alistair Francis
From: Bin Meng 

riscv_excp_names[] and riscv_intr_names[] are only referenced by
target/riscv/cpu.c locally.

Signed-off-by: Bin Meng 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Alistair Francis 
Message-id: 20210514052435.2203156-1-bmeng...@gmail.com
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h | 2 --
 target/riscv/cpu.c | 4 ++--
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 0619b491a4..0b22b0a523 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -320,8 +320,6 @@ static inline bool riscv_feature(CPURISCVState *env, int 
feature)
 
 extern const char * const riscv_int_regnames[];
 extern const char * const riscv_fpr_regnames[];
-extern const char * const riscv_excp_names[];
-extern const char * const riscv_intr_names[];
 
 const char *riscv_cpu_get_trap_name(target_ulong cause, bool async);
 void riscv_cpu_do_interrupt(CPUState *cpu);
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1f1cef1d6a..aa48bca830 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -51,7 +51,7 @@ const char * const riscv_fpr_regnames[] = {
   "f30/ft10", "f31/ft11"
 };
 
-const char * const riscv_excp_names[] = {
+static const char * const riscv_excp_names[] = {
 "misaligned_fetch",
 "fault_fetch",
 "illegal_instruction",
@@ -78,7 +78,7 @@ const char * const riscv_excp_names[] = {
 "guest_store_page_fault",
 };
 
-const char * const riscv_intr_names[] = {
+static const char * const riscv_intr_names[] = {
 "u_software",
 "s_software",
 "vs_software",
-- 
2.31.1




[PULL 13/32] target/riscv: Dump CSR mscratch/sscratch/satp

2021-06-07 Thread Alistair Francis
From: Changbin Du 

This dumps the CSR mscratch/sscratch/satp and meanwhile aligns
the output of CSR mtval/stval.

Signed-off-by: Changbin Du 
Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
Message-id: 20210519155738.20486-1-changbin...@gmail.com
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index aa48bca830..ee2523f66b 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -286,12 +286,15 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, 
int flags)
 if (riscv_has_ext(env, RVH)) {
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vscause ", env->vscause);
 }
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval ", env->mtval);
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stval ", env->stval);
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval   ", env->mtval);
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stval   ", env->stval);
 if (riscv_has_ext(env, RVH)) {
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "htval ", env->htval);
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval2 ", env->mtval2);
 }
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mscratch", env->mscratch);
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "sscratch", env->sscratch);
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "satp", env->satp);
 #endif
 
 for (i = 0; i < 32; i++) {
-- 
2.31.1




[PULL 11/32] target/riscv: Do not include 'pmp.h' in user emulation

2021-06-07 Thread Alistair Francis
From: Philippe Mathieu-Daudé 

Physical Memory Protection is a system feature.
Avoid polluting the user-mode emulation by its definitions.

Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
Message-id: 20210516205333.696094-1-f4...@amsat.org
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 7e879fb9ca..0619b491a4 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -97,7 +97,9 @@ enum {
 
 typedef struct CPURISCVState CPURISCVState;
 
+#if !defined(CONFIG_USER_ONLY)
 #include "pmp.h"
+#endif
 
 #define RV_VLEN_MAX 256
 
-- 
2.31.1




[PULL 23/32] target/riscv: add gen_shifti() and gen_shiftiw() helper functions

2021-06-07 Thread Alistair Francis
From: Frank Chang 

Add gen_shifti() and gen_shiftiw() helper functions to reuse the same
interfaces for immediate shift instructions.

Signed-off-by: Frank Chang 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Message-id: 20210505160620.15723-9-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 target/riscv/translate.c| 39 ++
 target/riscv/insn_trans/trans_rvi.c.inc | 54 ++---
 2 files changed, 43 insertions(+), 50 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 5f1a3c694f..292cf09932 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -652,6 +652,45 @@ static uint32_t opcode_at(DisasContextBase *dcbase, 
target_ulong pc)
 return cpu_ldl_code(env, pc);
 }
 
+static bool gen_shifti(DisasContext *ctx, arg_shift *a,
+   void(*func)(TCGv, TCGv, TCGv))
+{
+if (a->shamt >= TARGET_LONG_BITS) {
+return false;
+}
+
+TCGv source1 = tcg_temp_new();
+TCGv source2 = tcg_temp_new();
+
+gen_get_gpr(source1, a->rs1);
+
+tcg_gen_movi_tl(source2, a->shamt);
+(*func)(source1, source1, source2);
+
+gen_set_gpr(a->rd, source1);
+tcg_temp_free(source1);
+tcg_temp_free(source2);
+return true;
+}
+
+static bool gen_shiftiw(DisasContext *ctx, arg_shift *a,
+void(*func)(TCGv, TCGv, TCGv))
+{
+TCGv source1 = tcg_temp_new();
+TCGv source2 = tcg_temp_new();
+
+gen_get_gpr(source1, a->rs1);
+tcg_gen_movi_tl(source2, a->shamt);
+
+(*func)(source1, source1, source2);
+tcg_gen_ext32s_tl(source1, source1);
+
+gen_set_gpr(a->rd, source1);
+tcg_temp_free(source1);
+tcg_temp_free(source2);
+return true;
+}
+
 static void gen_ctz(TCGv ret, TCGv arg1)
 {
 tcg_gen_ctzi_tl(ret, arg1, TARGET_LONG_BITS);
diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index bd93f634cf..6e736c9d0d 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -268,54 +268,17 @@ static bool trans_andi(DisasContext *ctx, arg_andi *a)
 }
 static bool trans_slli(DisasContext *ctx, arg_slli *a)
 {
-if (a->shamt >= TARGET_LONG_BITS) {
-return false;
-}
-
-if (a->rd != 0) {
-TCGv t = tcg_temp_new();
-gen_get_gpr(t, a->rs1);
-
-tcg_gen_shli_tl(t, t, a->shamt);
-
-gen_set_gpr(a->rd, t);
-tcg_temp_free(t);
-} /* NOP otherwise */
-return true;
+return gen_shifti(ctx, a, tcg_gen_shl_tl);
 }
 
 static bool trans_srli(DisasContext *ctx, arg_srli *a)
 {
-if (a->shamt >= TARGET_LONG_BITS) {
-return false;
-}
-
-if (a->rd != 0) {
-TCGv t = tcg_temp_new();
-gen_get_gpr(t, a->rs1);
-
-tcg_gen_shri_tl(t, t, a->shamt);
-gen_set_gpr(a->rd, t);
-tcg_temp_free(t);
-} /* NOP otherwise */
-return true;
+return gen_shifti(ctx, a, tcg_gen_shr_tl);
 }
 
 static bool trans_srai(DisasContext *ctx, arg_srai *a)
 {
-if (a->shamt >= TARGET_LONG_BITS) {
-return false;
-}
-
-if (a->rd != 0) {
-TCGv t = tcg_temp_new();
-gen_get_gpr(t, a->rs1);
-
-tcg_gen_sari_tl(t, t, a->shamt);
-gen_set_gpr(a->rd, t);
-tcg_temp_free(t);
-} /* NOP otherwise */
-return true;
+return gen_shifti(ctx, a, tcg_gen_sar_tl);
 }
 
 static bool trans_add(DisasContext *ctx, arg_add *a)
@@ -377,16 +340,7 @@ static bool trans_addiw(DisasContext *ctx, arg_addiw *a)
 static bool trans_slliw(DisasContext *ctx, arg_slliw *a)
 {
 REQUIRE_64BIT(ctx);
-TCGv source1;
-source1 = tcg_temp_new();
-gen_get_gpr(source1, a->rs1);
-
-tcg_gen_shli_tl(source1, source1, a->shamt);
-tcg_gen_ext32s_tl(source1, source1);
-gen_set_gpr(a->rd, source1);
-
-tcg_temp_free(source1);
-return true;
+return gen_shiftiw(ctx, a, tcg_gen_shl_tl);
 }
 
 static bool trans_srliw(DisasContext *ctx, arg_srliw *a)
-- 
2.31.1




[PULL 10/32] docs/system: Move the RISC-V -bios information to removed

2021-06-07 Thread Alistair Francis
QEMU 5.1 changed the behaviour of the default boot for the RISC-V virt
and sifive_u machines. This patch moves that change from the
deprecated.rst file to the removed-features.rst file and the
target-riscv.rst.

Signed-off-by: Alistair Francis 
Reviewed-by: Bin Meng 
Message-id: 
4f1c261e7f69045ab8bb8926d85fe1d35e48ea5b.1620081256.git.alistair.fran...@wdc.com
---
 docs/system/deprecated.rst   | 19 ---
 docs/system/removed-features.rst |  5 +
 docs/system/target-riscv.rst | 13 -
 3 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
index abbf8243a3..e2e0090878 100644
--- a/docs/system/deprecated.rst
+++ b/docs/system/deprecated.rst
@@ -52,25 +52,6 @@ pcspk-audiodev=``.
 ``tty`` and ``parport`` are aliases that will be removed. Instead, the
 actual backend names ``serial`` and ``parallel`` should be used.
 
-RISC-V ``-bios`` (since 5.1)
-
-
-QEMU 4.1 introduced support for the -bios option in QEMU for RISC-V for the
-RISC-V virt machine and sifive_u machine. QEMU 4.1 had no changes to the
-default behaviour to avoid breakages.
-
-QEMU 5.1 changes the default behaviour from ``-bios none`` to ``-bios 
default``.
-
-QEMU 5.1 has three options:
- 1. ``-bios default`` - This is the current default behavior if no -bios option
-  is included. This option will load the default OpenSBI firmware 
automatically.
-  The firmware is included with the QEMU release and no user interaction is
-  required. All a user needs to do is specify the kernel they want to boot
-  with the -kernel option
- 2. ``-bios none`` - QEMU will not automatically load any firmware. It is up
-  to the user to load all the images they need.
- 3. ``-bios `` - Tells QEMU to load the specified file as the firmwrae.
-
 Short-form boolean options (since 6.0)
 ''
 
diff --git a/docs/system/removed-features.rst b/docs/system/removed-features.rst
index 1d22195b1d..2b21bd39ab 100644
--- a/docs/system/removed-features.rst
+++ b/docs/system/removed-features.rst
@@ -126,6 +126,11 @@ devices.  Drives the board doesn't pick up can no longer 
be used with
 This option was undocumented and not used in the field.
 Use `-device usb-ccid`` instead.
 
+RISC-V firmware not booted by default (removed in 5.1)
+''
+
+QEMU 5.1 changes the default behaviour from ``-bios none`` to ``-bios default``
+for the RISC-V ``virt`` machine and ``sifive_u`` machine.
 
 QEMU Machine Protocol (QMP) commands
 
diff --git a/docs/system/target-riscv.rst b/docs/system/target-riscv.rst
index 4b3c78382c..a5cc06b726 100644
--- a/docs/system/target-riscv.rst
+++ b/docs/system/target-riscv.rst
@@ -70,5 +70,16 @@ undocumented; you can get a complete list by running
riscv/shakti-c
riscv/sifive_u
 
-RISC-V CPU features
+RISC-V CPU firmware
 ---
+
+When using the ``sifive_u`` or ``virt`` machine there are three different
+firmware boot options:
+1. ``-bios default`` - This is the default behaviour if no -bios option
+is included. This option will load the default OpenSBI firmware automatically.
+The firmware is included with the QEMU release and no user interaction is
+required. All a user needs to do is specify the kernel they want to boot
+with the -kernel option
+2. ``-bios none`` - QEMU will not automatically load any firmware. It is up
+to the user to load all the images they need.
+3. ``-bios `` - Tells QEMU to load the specified file as the firmware.
-- 
2.31.1




[PULL 14/32] target/riscv/pmp: Add assert for ePMP operations

2021-06-07 Thread Alistair Francis
Although we construct epmp_operation in such a way that it can only be
between 0 and 15 Coverity complains that we don't handle the other
possible cases. To fix Coverity and make it easier for humans to read
add a default case to the switch statement that calls
g_assert_not_reached().

Fixes: CID 1453108
Signed-off-by: Alistair Francis 
Reviewed-by: Bin Meng 
Reviewed-by: LIU Zhiwei 
Message-id: 
ec5f225928eec448278c82fcb1f6805ee61dde82.1621550996.git.alistair.fran...@wdc.com
---
 target/riscv/pmp.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
index 78203291de..82ed020b10 100644
--- a/target/riscv/pmp.c
+++ b/target/riscv/pmp.c
@@ -402,6 +402,8 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong 
addr,
 case 15:
 *allowed_privs = PMP_READ;
 break;
+default:
+g_assert_not_reached();
 }
 } else {
 switch (epmp_operation) {
@@ -433,6 +435,8 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong 
addr,
 case 7:
 *allowed_privs = PMP_READ | PMP_WRITE | PMP_EXEC;
 break;
+default:
+g_assert_not_reached();
 }
 }
 }
-- 
2.31.1




[PULL 06/32] docs/system/riscv: sifive_u: Document '-dtb' usage

2021-06-07 Thread Alistair Francis
From: Bin Meng 

Update the 'sifive_u' machine documentation to mention the '-dtb'
option that can be used to pass a custom DTB to QEMU.

Signed-off-by: Bin Meng 
Reviewed-by: Alistair Francis 
Message-id: 20210430071302.1489082-6-bmeng...@gmail.com
Signed-off-by: Alistair Francis 
---
 docs/system/riscv/sifive_u.rst | 47 +-
 1 file changed, 41 insertions(+), 6 deletions(-)

diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst
index dcdfbda931..32d0a1b85d 100644
--- a/docs/system/riscv/sifive_u.rst
+++ b/docs/system/riscv/sifive_u.rst
@@ -36,12 +36,21 @@ Hardware configuration information
 --
 
 The ``sifive_u`` machine automatically generates a device tree blob ("dtb")
-which it passes to the guest. This provides information about the addresses,
-interrupt lines and other configuration of the various devices in the system.
-Guest software should discover the devices that are present in the generated
-DTB instead of using a DTB for the real hardware, as some of the devices are
-not modeled by QEMU and trying to access these devices may cause unexpected
-behavior.
+which it passes to the guest, if there is no ``-dtb`` option. This provides
+information about the addresses, interrupt lines and other configuration of
+the various devices in the system. Guest software should discover the devices
+that are present in the generated DTB instead of using a DTB for the real
+hardware, as some of the devices are not modeled by QEMU and trying to access
+these devices may cause unexpected behavior.
+
+If users want to provide their own DTB, they can use the ``-dtb`` option.
+These DTBs should have the following requirements:
+
+* The /cpus node should contain at least one subnode for E51 and the number
+  of subnodes should match QEMU's ``-smp`` option
+* The /memory reg size should match QEMU’s selected ram_size via ``-m``
+* Should contain a node for the CLINT device with a compatible string
+  "riscv,clint0" if using with OpenSBI BIOS images
 
 Boot options
 
@@ -122,6 +131,32 @@ To boot the newly built Linux kernel in QEMU with the 
``sifive_u`` machine:
   -initrd /path/to/rootfs.ext4 \
   -append "root=/dev/ram"
 
+Alternatively, we can use a custom DTB to boot the machine by inserting a CLINT
+node in fu540-c000.dtsi in the Linux kernel,
+
+.. code-block:: none
+
+clint: clint@200 {
+compatible = "riscv,clint0";
+interrupts-extended = <_intc 3 _intc 7
+   _intc 3 _intc 7
+   _intc 3 _intc 7
+   _intc 3 _intc 7
+   _intc 3 _intc 7>;
+reg = <0x00 0x200 0x00 0x1>;
+};
+
+with the following command line options:
+
+.. code-block:: bash
+
+  $ qemu-system-riscv64 -M sifive_u -smp 5 -m 8G \
+  -display none -serial stdio \
+  -kernel arch/riscv/boot/Image \
+  -dtb arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dtb \
+  -initrd /path/to/rootfs.ext4 \
+  -append "root=/dev/ram"
+
 To build a Linux mainline kernel that can be booted by the ``sifive_u`` machine
 in 32-bit mode, use the rv32_defconfig configuration. A patch is required to
 fix the 32-bit boot issue for Linux kernel v5.10.
-- 
2.31.1




[PULL 07/32] hw/riscv: Use macros for BIOS image names

2021-06-07 Thread Alistair Francis
From: Bin Meng 

The OpenSBI BIOS image names are used by many RISC-V machines.
Let's define macros for them.

Signed-off-by: Bin Meng 
Reviewed-by: Alistair Francis 
Message-id: 20210430071302.1489082-7-bmeng...@gmail.com
Signed-off-by: Alistair Francis 
---
 include/hw/riscv/boot.h | 5 +
 hw/riscv/sifive_u.c | 6 ++
 hw/riscv/spike.c| 6 ++
 hw/riscv/virt.c | 6 ++
 4 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
index 11a21dd584..0e89400b09 100644
--- a/include/hw/riscv/boot.h
+++ b/include/hw/riscv/boot.h
@@ -24,6 +24,11 @@
 #include "hw/loader.h"
 #include "hw/riscv/riscv_hart.h"
 
+#define RISCV32_BIOS_BIN"opensbi-riscv32-generic-fw_dynamic.bin"
+#define RISCV32_BIOS_ELF"opensbi-riscv32-generic-fw_dynamic.elf"
+#define RISCV64_BIOS_BIN"opensbi-riscv64-generic-fw_dynamic.bin"
+#define RISCV64_BIOS_ELF"opensbi-riscv64-generic-fw_dynamic.elf"
+
 bool riscv_is_32bit(RISCVHartArrayState *harts);
 
 target_ulong riscv_calc_kernel_start_addr(RISCVHartArrayState *harts,
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index a32a95d58f..273c86418c 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -560,12 +560,10 @@ static void sifive_u_machine_init(MachineState *machine)
 
 if (riscv_is_32bit(>soc.u_cpus)) {
 firmware_end_addr = riscv_find_and_load_firmware(machine,
-"opensbi-riscv32-generic-fw_dynamic.bin",
-start_addr, NULL);
+RISCV32_BIOS_BIN, start_addr, NULL);
 } else {
 firmware_end_addr = riscv_find_and_load_firmware(machine,
-"opensbi-riscv64-generic-fw_dynamic.bin",
-start_addr, NULL);
+RISCV64_BIOS_BIN, start_addr, NULL);
 }
 
 if (machine->kernel_filename) {
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index 4b08816dfa..fead77f0c4 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -258,13 +258,11 @@ static void spike_board_init(MachineState *machine)
  */
 if (riscv_is_32bit(>soc[0])) {
 firmware_end_addr = riscv_find_and_load_firmware(machine,
-"opensbi-riscv32-generic-fw_dynamic.elf",
-memmap[SPIKE_DRAM].base,
+RISCV32_BIOS_ELF, memmap[SPIKE_DRAM].base,
 htif_symbol_callback);
 } else {
 firmware_end_addr = riscv_find_and_load_firmware(machine,
-"opensbi-riscv64-generic-fw_dynamic.elf",
-memmap[SPIKE_DRAM].base,
+RISCV64_BIOS_ELF, memmap[SPIKE_DRAM].base,
 htif_symbol_callback);
 }
 
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 560216d217..4a3cd2599a 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -681,12 +681,10 @@ static void virt_machine_init(MachineState *machine)
 
 if (riscv_is_32bit(>soc[0])) {
 firmware_end_addr = riscv_find_and_load_firmware(machine,
-"opensbi-riscv32-generic-fw_dynamic.bin",
-start_addr, NULL);
+RISCV32_BIOS_BIN, start_addr, NULL);
 } else {
 firmware_end_addr = riscv_find_and_load_firmware(machine,
-"opensbi-riscv64-generic-fw_dynamic.bin",
-start_addr, NULL);
+RISCV64_BIOS_BIN, start_addr, NULL);
 }
 
 if (machine->kernel_filename) {
-- 
2.31.1




[PULL 08/32] hw/riscv: microchip_pfsoc: Support direct kernel boot

2021-06-07 Thread Alistair Francis
From: Bin Meng 

At present the Microchip Icicle Kit machine only supports using
'-bios' to load the HSS, and does not support '-kernel' for direct
kernel booting just like other RISC-V machines do. One has to use
U-Boot which is chain-loaded by HSS, to load a kernel for testing.
This is not so convenient.

Adding '-kernel' support together with the existing '-bios', we
follow the following table to select which payload we execute:

  -bios |-kernel | payload
  --++
  N |  N | HSS
  Y | don't care | HSS
  N |  Y | kernel

This ensures backwards compatibility with how we used to expose
'-bios' to users. When '-kernel' is used for direct boot, '-dtb'
must be present to provide a valid device tree for the board,
as we don't generate device tree.

When direct kernel boot is used, the OpenSBI fw_dynamic BIOS image
is used to boot a payload like U-Boot or OS kernel directly.

Documentation is updated to describe the direct kernel boot. Note
as of today there is still no PolarFire SoC support in the upstream
Linux kernel hence the document does not include instructions for
that. It will be updated in the future.

Signed-off-by: Bin Meng 
Reviewed-by: Alistair Francis 
Message-id: 20210430071302.1489082-8-bmeng...@gmail.com
Signed-off-by: Alistair Francis 
---
 docs/system/riscv/microchip-icicle-kit.rst | 30 ++--
 hw/riscv/microchip_pfsoc.c | 81 +-
 2 files changed, 103 insertions(+), 8 deletions(-)

diff --git a/docs/system/riscv/microchip-icicle-kit.rst 
b/docs/system/riscv/microchip-icicle-kit.rst
index e803131763..54ced661e3 100644
--- a/docs/system/riscv/microchip-icicle-kit.rst
+++ b/docs/system/riscv/microchip-icicle-kit.rst
@@ -31,17 +31,37 @@ Boot options
 
 The ``microchip-icicle-kit`` machine can start using the standard -bios
 functionality for loading its BIOS image, aka Hart Software Services (HSS_).
-HSS loads the second stage bootloader U-Boot from an SD card. It does not
-support direct kernel loading via the -kernel option. One has to load kernel
-from U-Boot.
+HSS loads the second stage bootloader U-Boot from an SD card. Then a kernel
+can be loaded from U-Boot. It also supports direct kernel booting via the
+-kernel option along with the device tree blob via -dtb. When direct kernel
+boot is used, the OpenSBI fw_dynamic BIOS image is used to boot a payload
+like U-Boot or OS kernel directly.
+
+The user provided DTB should have the following requirements:
+
+* The /cpus node should contain at least one subnode for E51 and the number
+  of subnodes should match QEMU's ``-smp`` option
+* The /memory reg size should match QEMU’s selected ram_size via ``-m``
+* Should contain a node for the CLINT device with a compatible string
+  "riscv,clint0"
+
+QEMU follows below truth table to select which payload to execute:
+
+=  == ===
+-bios -kernel payload
+=  == ===
+N   N HSS
+Y  don't care HSS
+N   Y  kernel
+=  == ===
 
 The memory is set to 1537 MiB by default which is the minimum required high
 memory size by HSS. A sanity check on ram size is performed in the machine
 init routine to prompt user to increase the RAM size to > 1537 MiB when less
 than 1537 MiB ram is detected.
 
-Boot the machine
-
+Running HSS
+---
 
 HSS 2020.12 release is tested at the time of writing. To build an HSS image
 that can be booted by the ``microchip-icicle-kit`` machine, type the following
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
index 6cbd17ebf2..eb8e79e0a1 100644
--- a/hw/riscv/microchip_pfsoc.c
+++ b/hw/riscv/microchip_pfsoc.c
@@ -51,6 +51,7 @@
 #include "hw/riscv/microchip_pfsoc.h"
 #include "hw/intc/sifive_clint.h"
 #include "hw/intc/sifive_plic.h"
+#include "sysemu/device_tree.h"
 #include "sysemu/sysemu.h"
 
 /*
@@ -460,6 +461,12 @@ static void microchip_icicle_kit_machine_init(MachineState 
*machine)
 MemoryRegion *mem_high = g_new(MemoryRegion, 1);
 MemoryRegion *mem_high_alias = g_new(MemoryRegion, 1);
 uint64_t mem_high_size;
+hwaddr firmware_load_addr;
+const char *firmware_name;
+bool kernel_as_payload = false;
+target_ulong firmware_end_addr, kernel_start_addr;
+uint64_t kernel_entry;
+uint32_t fdt_load_addr;
 DriveInfo *dinfo = drive_get_next(IF_SD);
 
 /* Sanity check on RAM size */
@@ -504,9 +511,6 @@ static void microchip_icicle_kit_machine_init(MachineState 
*machine)
 memmap[MICROCHIP_PFSOC_DRAM_HI_ALIAS].base,
 mem_high_alias);
 
-/* Load the firmware */
-riscv_find_and_load_firmware(machine, BIOS_FILENAME, RESET_VECTOR, NULL);
-
 /* Attach an SD card */
 if (dinfo) {
 CadenceSDHCIState *sdhci = &(s->soc.sdhci);
@@ -516,6 +520,77 @@ static void microchip_icicle_kit_machine_init(MachineState 
*machine)
 

[PULL 09/32] target/riscv: fix wfi exception behavior

2021-06-07 Thread Alistair Francis
From: Jose Martins 

The wfi exception trigger behavior should take into account user mode,
hstatus.vtw, and the fact the an wfi might raise different types of
exceptions depending on various factors:

If supervisor mode is not present:

- an illegal instruction exception should be generated if user mode
executes and wfi instruction and mstatus.tw = 1.

If supervisor mode is present:

- when a wfi instruction is executed, an illegal exception should be triggered
if either the current mode is user or the mode is supervisor and mstatus.tw is
set.

Plus, if the hypervisor extensions are enabled:

- a virtual instruction exception should be raised when a wfi is executed from
virtual-user or virtual-supervisor and hstatus.vtw is set.

Signed-off-by: Jose Martins 
Reviewed-by: Alistair Francis 
Message-id: 20210420213656.85148-1-josemartin...@gmail.com
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu_bits.h  |  1 +
 target/riscv/op_helper.c | 11 ---
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 52640e6856..7330ff5a19 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -390,6 +390,7 @@
 #define HSTATUS_HU   0x0200
 #define HSTATUS_VGEIN0x0003F000
 #define HSTATUS_VTVM 0x0010
+#define HSTATUS_VTW  0x0020
 #define HSTATUS_VTSR 0x0040
 #define HSTATUS_VSXL 0x3
 
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 170b494227..3c48e739ac 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -177,10 +177,15 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong 
cpu_pc_deb)
 void helper_wfi(CPURISCVState *env)
 {
 CPUState *cs = env_cpu(env);
+bool rvs = riscv_has_ext(env, RVS);
+bool prv_u = env->priv == PRV_U;
+bool prv_s = env->priv == PRV_S;
 
-if ((env->priv == PRV_S &&
-get_field(env->mstatus, MSTATUS_TW)) ||
-riscv_cpu_virt_enabled(env)) {
+if (((prv_s || (!rvs && prv_u)) && get_field(env->mstatus, MSTATUS_TW)) ||
+(rvs && prv_u && !riscv_cpu_virt_enabled(env))) {
+riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+} else if (riscv_cpu_virt_enabled(env) && (prv_u ||
+(prv_s && get_field(env->hstatus, HSTATUS_VTW {
 riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC());
 } else {
 cs->halted = 1;
-- 
2.31.1




[PULL 02/32] hw/riscv: virt: Switch to use qemu_fdt_setprop_string_array() helper

2021-06-07 Thread Alistair Francis
From: Bin Meng 

Since commit 78da6a1bca22 ("device_tree: add qemu_fdt_setprop_string_array 
helper"),
we can use the new helper to set the compatible strings for the
SiFive test device node.

Signed-off-by: Bin Meng 
Reviewed-by: Alistair Francis 
Message-id: 20210430071302.1489082-2-bmeng...@gmail.com
Signed-off-by: Alistair Francis 
---
 hw/riscv/virt.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 95a11adaa2..1e017d1c52 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -394,8 +394,11 @@ static void create_fdt(RISCVVirtState *s, const 
MemMapEntry *memmap,
 (long)memmap[VIRT_TEST].base);
 qemu_fdt_add_subnode(fdt, name);
 {
-const char compat[] = "sifive,test1\0sifive,test0\0syscon";
-qemu_fdt_setprop(fdt, name, "compatible", compat, sizeof(compat));
+static const char * const compat[3] = {
+"sifive,test1", "sifive,test0", "syscon"
+};
+qemu_fdt_setprop_string_array(fdt, name, "compatible", (char 
**),
+  ARRAY_SIZE(compat));
 }
 qemu_fdt_setprop_cells(fdt, name, "reg",
 0x0, memmap[VIRT_TEST].base,
-- 
2.31.1




[PULL 04/32] hw/riscv: Support the official PLIC DT bindings

2021-06-07 Thread Alistair Francis
From: Bin Meng 

The official DT bindings of PLIC uses "sifive,plic-1.0.0" as the
compatible string in the upstream Linux kernel. "riscv,plic0" is
now legacy and has to be kept for backward compatibility of legacy
systems.

Signed-off-by: Bin Meng 
Reviewed-by: Alistair Francis 
Message-id: 20210430071302.1489082-4-bmeng...@gmail.com
Signed-off-by: Alistair Francis 
---
 hw/riscv/sifive_u.c | 6 +-
 hw/riscv/virt.c | 6 +-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index d3828dc880..a32a95d58f 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -101,6 +101,9 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry 
*memmap,
 static const char * const clint_compat[2] = {
 "sifive,clint0", "riscv,clint0"
 };
+static const char * const plic_compat[2] = {
+"sifive,plic-1.0.0", "riscv,plic0"
+};
 
 if (ms->dtb) {
 fdt = s->fdt = load_device_tree(ms->dtb, >fdt_size);
@@ -270,7 +273,8 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry 
*memmap,
 (long)memmap[SIFIVE_U_DEV_PLIC].base);
 qemu_fdt_add_subnode(fdt, nodename);
 qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 1);
-qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv,plic0");
+qemu_fdt_setprop_string_array(fdt, nodename, "compatible",
+(char **)_compat, ARRAY_SIZE(plic_compat));
 qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0);
 qemu_fdt_setprop(fdt, nodename, "interrupts-extended",
 cells, (ms->smp.cpus * 4 - 2) * sizeof(uint32_t));
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 5159e7e020..560216d217 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -197,6 +197,9 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry 
*memmap,
 static const char * const clint_compat[2] = {
 "sifive,clint0", "riscv,clint0"
 };
+static const char * const plic_compat[2] = {
+"sifive,plic-1.0.0", "riscv,plic0"
+};
 
 if (mc->dtb) {
 fdt = mc->fdt = load_device_tree(mc->dtb, >fdt_size);
@@ -319,7 +322,8 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry 
*memmap,
 "#address-cells", FDT_PLIC_ADDR_CELLS);
 qemu_fdt_setprop_cell(fdt, plic_name,
 "#interrupt-cells", FDT_PLIC_INT_CELLS);
-qemu_fdt_setprop_string(fdt, plic_name, "compatible", "riscv,plic0");
+qemu_fdt_setprop_string_array(fdt, plic_name, "compatible",
+(char **)_compat, ARRAY_SIZE(plic_compat));
 qemu_fdt_setprop(fdt, plic_name, "interrupt-controller", NULL, 0);
 qemu_fdt_setprop(fdt, plic_name, "interrupts-extended",
 plic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4);
-- 
2.31.1




[PULL 05/32] docs/system/riscv: Correct the indentation level of supported devices

2021-06-07 Thread Alistair Francis
From: Bin Meng 

The supported device bullet list has an additional space before each
entry, which makes a wrong indentation level. Correct it.

Signed-off-by: Bin Meng 
Reviewed-by: Alistair Francis 
Message-id: 20210430071302.1489082-5-bmeng...@gmail.com
Signed-off-by: Alistair Francis 
---
 docs/system/riscv/microchip-icicle-kit.rst | 20 +++
 docs/system/riscv/sifive_u.rst | 30 +++---
 2 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/docs/system/riscv/microchip-icicle-kit.rst 
b/docs/system/riscv/microchip-icicle-kit.rst
index 4fe97bce3f..e803131763 100644
--- a/docs/system/riscv/microchip-icicle-kit.rst
+++ b/docs/system/riscv/microchip-icicle-kit.rst
@@ -15,16 +15,16 @@ Supported devices
 
 The ``microchip-icicle-kit`` machine supports the following devices:
 
- * 1 E51 core
- * 4 U54 cores
- * Core Level Interruptor (CLINT)
- * Platform-Level Interrupt Controller (PLIC)
- * L2 Loosely Integrated Memory (L2-LIM)
- * DDR memory controller
- * 5 MMUARTs
- * 1 DMA controller
- * 2 GEM Ethernet controllers
- * 1 SDHC storage controller
+* 1 E51 core
+* 4 U54 cores
+* Core Level Interruptor (CLINT)
+* Platform-Level Interrupt Controller (PLIC)
+* L2 Loosely Integrated Memory (L2-LIM)
+* DDR memory controller
+* 5 MMUARTs
+* 1 DMA controller
+* 2 GEM Ethernet controllers
+* 1 SDHC storage controller
 
 Boot options
 
diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst
index 98e7562848..dcdfbda931 100644
--- a/docs/system/riscv/sifive_u.rst
+++ b/docs/system/riscv/sifive_u.rst
@@ -9,21 +9,21 @@ Supported devices
 
 The ``sifive_u`` machine supports the following devices:
 
- * 1 E51 / E31 core
- * Up to 4 U54 / U34 cores
- * Core Level Interruptor (CLINT)
- * Platform-Level Interrupt Controller (PLIC)
- * Power, Reset, Clock, Interrupt (PRCI)
- * L2 Loosely Integrated Memory (L2-LIM)
- * DDR memory controller
- * 2 UARTs
- * 1 GEM Ethernet controller
- * 1 GPIO controller
- * 1 One-Time Programmable (OTP) memory with stored serial number
- * 1 DMA controller
- * 2 QSPI controllers
- * 1 ISSI 25WP256 flash
- * 1 SD card in SPI mode
+* 1 E51 / E31 core
+* Up to 4 U54 / U34 cores
+* Core Level Interruptor (CLINT)
+* Platform-Level Interrupt Controller (PLIC)
+* Power, Reset, Clock, Interrupt (PRCI)
+* L2 Loosely Integrated Memory (L2-LIM)
+* DDR memory controller
+* 2 UARTs
+* 1 GEM Ethernet controller
+* 1 GPIO controller
+* 1 One-Time Programmable (OTP) memory with stored serial number
+* 1 DMA controller
+* 2 QSPI controllers
+* 1 ISSI 25WP256 flash
+* 1 SD card in SPI mode
 
 Please note the real world HiFive Unleashed board has a fixed configuration of
 1 E51 core and 4 U54 core combination and the RISC-V core boots in 64-bit mode.
-- 
2.31.1




[PULL 03/32] hw/riscv: Support the official CLINT DT bindings

2021-06-07 Thread Alistair Francis
From: Bin Meng 

Linux kernel commit a2770b57d083 ("dt-bindings: timer: Add CLINT bindings")
adds the official DT bindings for CLINT, which uses "sifive,clint0"
as the compatible string. "riscv,clint0" is now legacy and has to
be kept for backward compatibility of legacy systems.

Signed-off-by: Bin Meng 
Reviewed-by: Alistair Francis 
Message-id: 20210430071302.1489082-3-bmeng...@gmail.com
Signed-off-by: Alistair Francis 
---
 hw/riscv/sifive_u.c | 6 +-
 hw/riscv/spike.c| 6 +-
 hw/riscv/virt.c | 6 +-
 3 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 89cccd7fd5..d3828dc880 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -98,6 +98,9 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry 
*memmap,
 uint32_t plic_phandle, prci_phandle, gpio_phandle, phandle = 1;
 uint32_t hfclk_phandle, rtcclk_phandle, phy_phandle;
 static const char * const ethclk_names[2] = { "pclk", "hclk" };
+static const char * const clint_compat[2] = {
+"sifive,clint0", "riscv,clint0"
+};
 
 if (ms->dtb) {
 fdt = s->fdt = load_device_tree(ms->dtb, >fdt_size);
@@ -209,7 +212,8 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry 
*memmap,
 nodename = g_strdup_printf("/soc/clint@%lx",
 (long)memmap[SIFIVE_U_DEV_CLINT].base);
 qemu_fdt_add_subnode(fdt, nodename);
-qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv,clint0");
+qemu_fdt_setprop_string_array(fdt, nodename, "compatible",
+(char **)_compat, ARRAY_SIZE(clint_compat));
 qemu_fdt_setprop_cells(fdt, nodename, "reg",
 0x0, memmap[SIFIVE_U_DEV_CLINT].base,
 0x0, memmap[SIFIVE_U_DEV_CLINT].size);
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index fe0806a476..4b08816dfa 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -59,6 +59,9 @@ static void create_fdt(SpikeState *s, const MemMapEntry 
*memmap,
 uint32_t cpu_phandle, intc_phandle, phandle = 1;
 char *name, *mem_name, *clint_name, *clust_name;
 char *core_name, *cpu_name, *intc_name;
+static const char * const clint_compat[2] = {
+"sifive,clint0", "riscv,clint0"
+};
 
 fdt = s->fdt = create_device_tree(>fdt_size);
 if (!fdt) {
@@ -152,7 +155,8 @@ static void create_fdt(SpikeState *s, const MemMapEntry 
*memmap,
 (memmap[SPIKE_CLINT].size * socket);
 clint_name = g_strdup_printf("/soc/clint@%lx", clint_addr);
 qemu_fdt_add_subnode(fdt, clint_name);
-qemu_fdt_setprop_string(fdt, clint_name, "compatible", "riscv,clint0");
+qemu_fdt_setprop_string_array(fdt, clint_name, "compatible",
+(char **)_compat, ARRAY_SIZE(clint_compat));
 qemu_fdt_setprop_cells(fdt, clint_name, "reg",
 0x0, clint_addr, 0x0, memmap[SPIKE_CLINT].size);
 qemu_fdt_setprop(fdt, clint_name, "interrupts-extended",
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 1e017d1c52..5159e7e020 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -194,6 +194,9 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry 
*memmap,
 char *name, *clint_name, *plic_name, *clust_name;
 hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2;
 hwaddr flashbase = virt_memmap[VIRT_FLASH].base;
+static const char * const clint_compat[2] = {
+"sifive,clint0", "riscv,clint0"
+};
 
 if (mc->dtb) {
 fdt = mc->fdt = load_device_tree(mc->dtb, >fdt_size);
@@ -299,7 +302,8 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry 
*memmap,
 (memmap[VIRT_CLINT].size * socket);
 clint_name = g_strdup_printf("/soc/clint@%lx", clint_addr);
 qemu_fdt_add_subnode(fdt, clint_name);
-qemu_fdt_setprop_string(fdt, clint_name, "compatible", "riscv,clint0");
+qemu_fdt_setprop_string_array(fdt, clint_name, "compatible",
+(char **)_compat, ARRAY_SIZE(clint_compat));
 qemu_fdt_setprop_cells(fdt, clint_name, "reg",
 0x0, clint_addr, 0x0, memmap[VIRT_CLINT].size);
 qemu_fdt_setprop(fdt, clint_name, "interrupts-extended",
-- 
2.31.1




[PULL 00/32] riscv-to-apply queue

2021-06-07 Thread Alistair Francis
The following changes since commit a35947f15c0ee695eba3c55248ec8ac3e4e23cca:

  Merge remote-tracking branch 
'remotes/stsquad/tags/pull-testing-updates-070621-2' into staging (2021-06-07 
15:45:48 +0100)

are available in the Git repository at:

  g...@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20210608-1

for you to fetch changes up to d2c1a177b138be35cb96216baa870c3564b123e4:

  target/riscv: rvb: add b-ext version cpu option (2021-06-08 09:59:46 +1000)


Second RISC-V PR for QEMU 6.1

 - Update the PLIC and CLINT DT bindings
 - Improve documentation for RISC-V machines
 - Support direct kernel boot for microchip_pfsoc
 - Fix WFI exception behaviour
 - Improve CSR printing
 - Initial support for the experimental Bit Manip extension


Alistair Francis (2):
  docs/system: Move the RISC-V -bios information to removed
  target/riscv/pmp: Add assert for ePMP operations

Bin Meng (9):
  hw/riscv: sifive_u: Switch to use qemu_fdt_setprop_string_array() helper
  hw/riscv: virt: Switch to use qemu_fdt_setprop_string_array() helper
  hw/riscv: Support the official CLINT DT bindings
  hw/riscv: Support the official PLIC DT bindings
  docs/system/riscv: Correct the indentation level of supported devices
  docs/system/riscv: sifive_u: Document '-dtb' usage
  hw/riscv: Use macros for BIOS image names
  hw/riscv: microchip_pfsoc: Support direct kernel boot
  target/riscv: Remove unnecessary riscv_*_names[] declaration

Changbin Du (1):
  target/riscv: Dump CSR mscratch/sscratch/satp

Frank Chang (6):
  target/riscv: rvb: count bits set
  target/riscv: add gen_shifti() and gen_shiftiw() helper functions
  target/riscv: rvb: single-bit instructions
  target/riscv: rvb: generalized reverse
  target/riscv: rvb: generalized or-combine
  target/riscv: rvb: add b-ext version cpu option

Jose Martins (1):
  target/riscv: fix wfi exception behavior

Kito Cheng (11):
  target/riscv: reformat @sh format encoding for B-extension
  target/riscv: rvb: count leading/trailing zeros
  target/riscv: rvb: logic-with-negate
  target/riscv: rvb: pack two words into one register
  target/riscv: rvb: min/max instructions
  target/riscv: rvb: sign-extend instructions
  target/riscv: rvb: shift ones
  target/riscv: rvb: rotate (left/right)
  target/riscv: rvb: address calculation
  target/riscv: rvb: add/shift with prefix zero-extend
  target/riscv: rvb: support and turn on B-extension from command line

LIU Zhiwei (1):
  target/riscv: Pass the same value to oprsz and maxsz.

Philippe Mathieu-Daudé (1):
  target/riscv: Do not include 'pmp.h' in user emulation

 docs/system/deprecated.rst |  19 --
 docs/system/removed-features.rst   |   5 +
 docs/system/riscv/microchip-icicle-kit.rst |  50 +++-
 docs/system/riscv/sifive_u.rst |  77 +++--
 docs/system/target-riscv.rst   |  13 +-
 include/hw/riscv/boot.h|   5 +
 target/riscv/cpu.h |   9 +-
 target/riscv/cpu_bits.h|   1 +
 target/riscv/helper.h  |   6 +
 target/riscv/insn32.decode |  87 +-
 hw/riscv/microchip_pfsoc.c |  81 +-
 hw/riscv/sifive_u.c|  24 +-
 hw/riscv/spike.c   |  12 +-
 hw/riscv/virt.c|  25 +-
 target/riscv/bitmanip_helper.c |  90 ++
 target/riscv/cpu.c |  38 ++-
 target/riscv/op_helper.c   |  11 +-
 target/riscv/pmp.c |   4 +
 target/riscv/translate.c   | 306 
 target/riscv/insn_trans/trans_rvb.c.inc| 438 +
 target/riscv/insn_trans/trans_rvi.c.inc|  54 +---
 target/riscv/insn_trans/trans_rvv.c.inc|  89 +++---
 target/riscv/meson.build   |   1 +
 23 files changed, 1260 insertions(+), 185 deletions(-)
 create mode 100644 target/riscv/bitmanip_helper.c
 create mode 100644 target/riscv/insn_trans/trans_rvb.c.inc



[PULL 01/32] hw/riscv: sifive_u: Switch to use qemu_fdt_setprop_string_array() helper

2021-06-07 Thread Alistair Francis
From: Bin Meng 

Since commit 78da6a1bca22 ("device_tree: add qemu_fdt_setprop_string_array 
helper"),
we can use the new helper to set the clock name for the ethernet
controller node.

Signed-off-by: Bin Meng 
Reviewed-by: Alistair Francis 
Message-id: 20210430071302.1489082-1-bmeng...@gmail.com
Signed-off-by: Alistair Francis 
---
 hw/riscv/sifive_u.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 698637e8e1..89cccd7fd5 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -95,9 +95,9 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry 
*memmap,
 int cpu;
 uint32_t *cells;
 char *nodename;
-char ethclk_names[] = "pclk\0hclk";
 uint32_t plic_phandle, prci_phandle, gpio_phandle, phandle = 1;
 uint32_t hfclk_phandle, rtcclk_phandle, phy_phandle;
+static const char * const ethclk_names[2] = { "pclk", "hclk" };
 
 if (ms->dtb) {
 fdt = s->fdt = load_device_tree(ms->dtb, >fdt_size);
@@ -412,8 +412,8 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry 
*memmap,
 qemu_fdt_setprop_cell(fdt, nodename, "interrupts", SIFIVE_U_GEM_IRQ);
 qemu_fdt_setprop_cells(fdt, nodename, "clocks",
 prci_phandle, PRCI_CLK_GEMGXLPLL, prci_phandle, PRCI_CLK_GEMGXLPLL);
-qemu_fdt_setprop(fdt, nodename, "clock-names", ethclk_names,
-sizeof(ethclk_names));
+qemu_fdt_setprop_string_array(fdt, nodename, "clock-names",
+(char **)_names, ARRAY_SIZE(ethclk_names));
 qemu_fdt_setprop(fdt, nodename, "local-mac-address",
 s->soc.gem.conf.macaddr.a, ETH_ALEN);
 qemu_fdt_setprop_cell(fdt, nodename, "#address-cells", 1);
-- 
2.31.1




Re: [PATCH 06/55] target/arm: Implement MVE LCTP

2021-06-07 Thread Richard Henderson

On 6/7/21 9:57 AM, Peter Maydell wrote:

Implement the MVE LCTP instruction.

We put its decode and implementation with the other
low-overhead-branch insns because although it is only present if MVE
is implemented it is logically in the same group as the other LOB
insns.

Signed-off-by: Peter Maydell
---
  target/arm/t32.decode  |  2 ++
  target/arm/translate.c | 24 
  2 files changed, 26 insertions(+)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH 05/55] target/arm: Let vfp_access_check() handle late NOCP checks

2021-06-07 Thread Richard Henderson

On 6/7/21 9:57 AM, Peter Maydell wrote:

In commit a3494d4671797c we reworked the M-profile handling of its
checks for when the NOCP exception should be raised because the FPU
is disabled, so that (in line with the architecture) the NOCP check
is done early over a large range of the encoding space, and takes
precedence over UNDEF exceptions.  As part of this, we removed the
code from full_vfp_access_check() which raised an exception there for
M-profile with the FPU disabled, because it was no longer reachable.

For MVE, some instructions which are outside the "coprocessor space"
region of the encoding space must nonetheless do "is the FPU enabled"
checks and possibly raise a NOCP exception.  (In particular this
covers the MVE-specific low-overhead branch insns LCTP, DLSTP and
WLSTP.) To support these insns, reinstate the code in
full_vfp_access_check(), so that their trans functions can call
vfp_access_check() and get the correct behaviour.

Signed-off-by: Peter Maydell
---
  target/arm/translate-vfp.c | 20 +++-
  1 file changed, 15 insertions(+), 5 deletions(-)


Reviewed-by: Richard Henderson 

r~



[PATCH v1 1/5] ui/gtk: Create a common release_dmabuf helper

2021-06-07 Thread Vivek Kasireddy
Since the texture release mechanism is same for both gtk-egl
and gtk-glarea, move the helper from gtk-egl to common gtk
code so that it can be shared by both gtk backends.

Cc: Gerd Hoffmann 
Signed-off-by: Vivek Kasireddy 
---
 include/ui/gtk.h |  2 --
 ui/gtk-egl.c |  8 
 ui/gtk.c | 11 ++-
 3 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/include/ui/gtk.h b/include/ui/gtk.h
index 9516670ebc..e6cbf0507c 100644
--- a/include/ui/gtk.h
+++ b/include/ui/gtk.h
@@ -178,8 +178,6 @@ void gd_egl_cursor_dmabuf(DisplayChangeListener *dcl,
   uint32_t hot_x, uint32_t hot_y);
 void gd_egl_cursor_position(DisplayChangeListener *dcl,
 uint32_t pos_x, uint32_t pos_y);
-void gd_egl_release_dmabuf(DisplayChangeListener *dcl,
-   QemuDmaBuf *dmabuf);
 void gd_egl_scanout_flush(DisplayChangeListener *dcl,
   uint32_t x, uint32_t y, uint32_t w, uint32_t h);
 void gtk_egl_init(DisplayGLMode mode);
diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
index 2a2e6d3a17..b671181272 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -249,14 +249,6 @@ void gd_egl_cursor_position(DisplayChangeListener *dcl,
 vc->gfx.cursor_y = pos_y * vc->gfx.scale_y;
 }
 
-void gd_egl_release_dmabuf(DisplayChangeListener *dcl,
-   QemuDmaBuf *dmabuf)
-{
-#ifdef CONFIG_GBM
-egl_dmabuf_release_texture(dmabuf);
-#endif
-}
-
 void gd_egl_scanout_flush(DisplayChangeListener *dcl,
   uint32_t x, uint32_t y, uint32_t w, uint32_t h)
 {
diff --git a/ui/gtk.c b/ui/gtk.c
index 98046f577b..6132bab52f 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -575,6 +575,14 @@ static bool gd_has_dmabuf(DisplayChangeListener *dcl)
 return vc->gfx.has_dmabuf;
 }
 
+static void gd_gl_release_dmabuf(DisplayChangeListener *dcl,
+ QemuDmaBuf *dmabuf)
+{
+#ifdef CONFIG_GBM
+egl_dmabuf_release_texture(dmabuf);
+#endif
+}
+
 /** DisplayState Callbacks (opengl version) **/
 
 static const DisplayChangeListenerOps dcl_gl_area_ops = {
@@ -593,6 +601,7 @@ static const DisplayChangeListenerOps dcl_gl_area_ops = {
 .dpy_gl_scanout_disable  = gd_gl_area_scanout_disable,
 .dpy_gl_update   = gd_gl_area_scanout_flush,
 .dpy_gl_scanout_dmabuf   = gd_gl_area_scanout_dmabuf,
+.dpy_gl_release_dmabuf   = gd_gl_release_dmabuf,
 .dpy_has_dmabuf  = gd_has_dmabuf,
 };
 
@@ -615,8 +624,8 @@ static const DisplayChangeListenerOps dcl_egl_ops = {
 .dpy_gl_scanout_dmabuf   = gd_egl_scanout_dmabuf,
 .dpy_gl_cursor_dmabuf= gd_egl_cursor_dmabuf,
 .dpy_gl_cursor_position  = gd_egl_cursor_position,
-.dpy_gl_release_dmabuf   = gd_egl_release_dmabuf,
 .dpy_gl_update   = gd_egl_scanout_flush,
+.dpy_gl_release_dmabuf   = gd_gl_release_dmabuf,
 .dpy_has_dmabuf  = gd_has_dmabuf,
 };
 
-- 
2.30.2




[PATCH v1 3/5] ui/egl: Add egl helpers to help with synchronization

2021-06-07 Thread Vivek Kasireddy
These egl helpers would be used for creating and waiting on
a sync object.

Cc: Gerd Hoffmann 
Signed-off-by: Vivek Kasireddy 
---
 include/ui/console.h |  2 ++
 include/ui/egl-helpers.h |  3 +++
 ui/egl-helpers.c | 44 
 ui/gtk.c | 15 ++
 4 files changed, 64 insertions(+)

diff --git a/include/ui/console.h b/include/ui/console.h
index c3dca61c31..a89f739f10 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -168,6 +168,8 @@ typedef struct QemuDmaBuf {
 uint64_t  modifier;
 uint32_t  texture;
 bool  y0_top;
+void  *sync;
+int   fence_fd;
 } QemuDmaBuf;
 
 typedef struct DisplayState DisplayState;
diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h
index f1bf8f97fc..5a7575dc13 100644
--- a/include/ui/egl-helpers.h
+++ b/include/ui/egl-helpers.h
@@ -45,6 +45,9 @@ int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, 
EGLint *fourcc,
 
 void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf);
 void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf);
+void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf);
+void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf);
+void egl_dmabuf_wait_sync(QemuDmaBuf *dmabuf);
 
 #endif
 
diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
index 6d0cb2b5cb..47220b66e0 100644
--- a/ui/egl-helpers.c
+++ b/ui/egl-helpers.c
@@ -76,6 +76,50 @@ void egl_fb_setup_for_tex(egl_fb *fb, int width, int height,
   GL_TEXTURE_2D, fb->texture, 0);
 }
 
+void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf)
+{
+EGLSyncKHR sync;
+
+if (epoxy_has_egl_extension(qemu_egl_display,
+"EGL_KHR_fence_sync") &&
+epoxy_has_egl_extension(qemu_egl_display,
+"EGL_ANDROID_native_fence_sync")) {
+sync = eglCreateSyncKHR(qemu_egl_display,
+   EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
+if (sync != EGL_NO_SYNC_KHR) {
+dmabuf->sync = sync;
+}
+}
+}
+
+void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf)
+{
+if (dmabuf->sync) {
+dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display,
+  dmabuf->sync);
+eglDestroySyncKHR(qemu_egl_display, dmabuf->sync);
+dmabuf->sync = NULL;
+}
+}
+
+void egl_dmabuf_wait_sync(QemuDmaBuf *dmabuf)
+{
+EGLSyncKHR sync;
+EGLint attrib_list[] = {
+EGL_SYNC_NATIVE_FENCE_FD_ANDROID, dmabuf->fence_fd,
+EGL_NONE,
+};
+
+sync = eglCreateSyncKHR(qemu_egl_display,
+EGL_SYNC_NATIVE_FENCE_ANDROID, attrib_list);
+if (sync != EGL_NO_SYNC_KHR) {
+eglClientWaitSyncKHR(qemu_egl_display, sync,
+ 0, EGL_FOREVER_KHR);
+eglDestroySyncKHR(qemu_egl_display, sync);
+dmabuf->fence_fd = -1;
+}
+}
+
 void egl_fb_setup_new_tex(egl_fb *fb, int width, int height)
 {
 GLuint texture;
diff --git a/ui/gtk.c b/ui/gtk.c
index 6132bab52f..cd884ca26c 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -583,6 +583,19 @@ static void gd_gl_release_dmabuf(DisplayChangeListener 
*dcl,
 #endif
 }
 
+static void gd_gl_wait_dmabuf(DisplayChangeListener *dcl,
+  QemuDmaBuf *dmabuf)
+{
+#ifdef CONFIG_GBM
+egl_dmabuf_create_fence(dmabuf);
+if (dmabuf->fence_fd <= 0) {
+return;
+}
+
+egl_dmabuf_wait_sync(dmabuf);
+#endif
+}
+
 /** DisplayState Callbacks (opengl version) **/
 
 static const DisplayChangeListenerOps dcl_gl_area_ops = {
@@ -602,6 +615,7 @@ static const DisplayChangeListenerOps dcl_gl_area_ops = {
 .dpy_gl_update   = gd_gl_area_scanout_flush,
 .dpy_gl_scanout_dmabuf   = gd_gl_area_scanout_dmabuf,
 .dpy_gl_release_dmabuf   = gd_gl_release_dmabuf,
+.dpy_gl_wait_dmabuf  = gd_gl_wait_dmabuf,
 .dpy_has_dmabuf  = gd_has_dmabuf,
 };
 
@@ -626,6 +640,7 @@ static const DisplayChangeListenerOps dcl_egl_ops = {
 .dpy_gl_cursor_position  = gd_egl_cursor_position,
 .dpy_gl_update   = gd_egl_scanout_flush,
 .dpy_gl_release_dmabuf   = gd_gl_release_dmabuf,
+.dpy_gl_wait_dmabuf  = gd_gl_wait_dmabuf,
 .dpy_has_dmabuf  = gd_has_dmabuf,
 };
 
-- 
2.30.2




[PATCH v1 2/5] ui: Add a helper to wait on a dmabuf sync object

2021-06-07 Thread Vivek Kasireddy
This will be called by virtio-gpu in the subsequent patches.

Cc: Gerd Hoffmann 
Signed-off-by: Vivek Kasireddy 
---
 include/ui/console.h |  5 +
 ui/console.c | 10 ++
 2 files changed, 15 insertions(+)

diff --git a/include/ui/console.h b/include/ui/console.h
index b30b63976a..c3dca61c31 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -240,6 +240,9 @@ typedef struct DisplayChangeListenerOps {
 /* optional */
 void (*dpy_gl_release_dmabuf)(DisplayChangeListener *dcl,
   QemuDmaBuf *dmabuf);
+/* optional */
+void (*dpy_gl_wait_dmabuf)(DisplayChangeListener *dcl,
+   QemuDmaBuf *dmabuf);
 /* required if GL */
 void (*dpy_gl_update)(DisplayChangeListener *dcl,
   uint32_t x, uint32_t y, uint32_t w, uint32_t h);
@@ -312,6 +315,8 @@ void dpy_gl_cursor_position(QemuConsole *con,
 uint32_t pos_x, uint32_t pos_y);
 void dpy_gl_release_dmabuf(QemuConsole *con,
QemuDmaBuf *dmabuf);
+void dpy_gl_wait_dmabuf(QemuConsole *con,
+QemuDmaBuf *dmabuf);
 void dpy_gl_update(QemuConsole *con,
uint32_t x, uint32_t y, uint32_t w, uint32_t h);
 
diff --git a/ui/console.c b/ui/console.c
index 2de5f4105b..b0abfd2246 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1917,6 +1917,16 @@ void dpy_gl_release_dmabuf(QemuConsole *con,
 }
 }
 
+void dpy_gl_wait_dmabuf(QemuConsole *con,
+QemuDmaBuf *dmabuf)
+{
+assert(con->gl);
+
+if (con->gl->ops->dpy_gl_wait_dmabuf) {
+con->gl->ops->dpy_gl_wait_dmabuf(con->gl, dmabuf);
+}
+}
+
 void dpy_gl_update(QemuConsole *con,
uint32_t x, uint32_t y, uint32_t w, uint32_t h)
 {
-- 
2.30.2




[PATCH v1 4/5] ui: Create sync objects only for blobs

2021-06-07 Thread Vivek Kasireddy
For now, create sync objects only for dmabufs that are blobs.

Cc: Gerd Hoffmann 
Signed-off-by: Vivek Kasireddy 
---
 hw/display/virtio-gpu-udmabuf.c |  2 ++
 include/ui/console.h|  1 +
 include/ui/egl-helpers.h|  1 +
 ui/gtk-egl.c| 10 ++
 ui/gtk-gl-area.c|  8 
 5 files changed, 22 insertions(+)

diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c
index 3c01a415e7..33e329e8aa 100644
--- a/hw/display/virtio-gpu-udmabuf.c
+++ b/hw/display/virtio-gpu-udmabuf.c
@@ -185,6 +185,8 @@ static VGPUDMABuf
 dmabuf->buf.stride = fb->stride;
 dmabuf->buf.fourcc = qemu_pixman_to_drm_format(fb->format);
 dmabuf->buf.fd = res->dmabuf_fd;
+dmabuf->buf.blob = true;
+dmabuf->buf.sync = NULL;
 
 dmabuf->scanout_id = scanout_id;
 QTAILQ_INSERT_HEAD(>dmabuf.bufs, dmabuf, next);
diff --git a/include/ui/console.h b/include/ui/console.h
index a89f739f10..310d34c67a 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -170,6 +170,7 @@ typedef struct QemuDmaBuf {
 bool  y0_top;
 void  *sync;
 int   fence_fd;
+bool  blob;
 } QemuDmaBuf;
 
 typedef struct DisplayState DisplayState;
diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h
index 5a7575dc13..1bc0e31b03 100644
--- a/include/ui/egl-helpers.h
+++ b/include/ui/egl-helpers.h
@@ -19,6 +19,7 @@ typedef struct egl_fb {
 GLuint texture;
 GLuint framebuffer;
 bool delete_texture;
+QemuDmaBuf *dmabuf;
 } egl_fb;
 
 void egl_fb_destroy(egl_fb *fb);
diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
index b671181272..b748f51b0b 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -209,6 +209,8 @@ void gd_egl_scanout_dmabuf(DisplayChangeListener *dcl,
QemuDmaBuf *dmabuf)
 {
 #ifdef CONFIG_GBM
+VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
+
 egl_dmabuf_import_texture(dmabuf);
 if (!dmabuf->texture) {
 return;
@@ -217,6 +219,10 @@ void gd_egl_scanout_dmabuf(DisplayChangeListener *dcl,
 gd_egl_scanout_texture(dcl, dmabuf->texture,
false, dmabuf->width, dmabuf->height,
0, 0, dmabuf->width, dmabuf->height);
+
+if (dmabuf->blob) {
+vc->gfx.guest_fb.dmabuf = dmabuf;
+}
 #endif
 }
 
@@ -281,6 +287,10 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl,
 egl_fb_blit(>gfx.win_fb, >gfx.guest_fb, !vc->gfx.y0_top);
 }
 
+if (vc->gfx.guest_fb.dmabuf) {
+egl_dmabuf_create_sync(vc->gfx.guest_fb.dmabuf);
+}
+
 eglSwapBuffers(qemu_egl_display, vc->gfx.esurface);
 }
 
diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
index dd5783fec7..94f3b87c42 100644
--- a/ui/gtk-gl-area.c
+++ b/ui/gtk-gl-area.c
@@ -71,6 +71,10 @@ void gd_gl_area_draw(VirtualConsole *vc)
 surface_gl_render_texture(vc->gfx.gls, vc->gfx.ds);
 }
 
+if (vc->gfx.guest_fb.dmabuf) {
+egl_dmabuf_create_sync(vc->gfx.guest_fb.dmabuf);
+}
+
 glFlush();
 graphic_hw_gl_flushed(vc->gfx.dcl.con);
 }
@@ -231,6 +235,10 @@ void gd_gl_area_scanout_dmabuf(DisplayChangeListener *dcl,
 gd_gl_area_scanout_texture(dcl, dmabuf->texture,
false, dmabuf->width, dmabuf->height,
0, 0, dmabuf->width, dmabuf->height);
+
+if (dmabuf->blob) {
+vc->gfx.guest_fb.dmabuf = dmabuf;
+}
 #endif
 }
 
-- 
2.30.2




[PATCH v1 5/5] virtio-gpu: Make resource_flush wait on the sync object for blobs

2021-06-07 Thread Vivek Kasireddy
To make sure that the Guest would not use the backing storage
associated with a blob resource before or at the same time when
the Host does a blit with it, resource_flush needs to wait on
the sync object associated with the blob. Doing this would prevent
tearing/flickering or other issues when using blob resources.

Cc: Gerd Hoffmann 
Signed-off-by: Vivek Kasireddy 
Signed-off-by: Dongwon Kim 
---
 hw/display/virtio-gpu-udmabuf.c | 28 
 hw/display/virtio-gpu.c |  1 +
 include/hw/virtio/virtio-gpu.h  |  2 ++
 3 files changed, 31 insertions(+)

diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c
index 33e329e8aa..8c1b6f8763 100644
--- a/hw/display/virtio-gpu-udmabuf.c
+++ b/hw/display/virtio-gpu-udmabuf.c
@@ -167,6 +167,34 @@ static void virtio_gpu_free_dmabuf(VirtIOGPU *g, 
VGPUDMABuf *dmabuf)
 g_free(dmabuf);
 }
 
+static VGPUDMABuf
+*virtio_gpu_find_dmabuf(VirtIOGPU *g,
+struct virtio_gpu_simple_resource *res)
+{
+VGPUDMABuf *dmabuf, *tmp;
+
+QTAILQ_FOREACH_SAFE(dmabuf, >dmabuf.bufs, next, tmp) {
+if (dmabuf->buf.fd == res->dmabuf_fd) {
+return dmabuf;
+}
+}
+
+return NULL;
+}
+
+void virtio_gpu_resource_wait_sync(VirtIOGPU *g,
+   struct virtio_gpu_simple_resource *res)
+{
+struct virtio_gpu_scanout *scanout;
+VGPUDMABuf *dmabuf;
+
+dmabuf = virtio_gpu_find_dmabuf(g, res);
+if (dmabuf && dmabuf->buf.sync) {
+scanout = >parent_obj.scanout[dmabuf->scanout_id];
+dpy_gl_wait_dmabuf(scanout->con, >buf);
+}
+}
+
 static VGPUDMABuf
 *virtio_gpu_create_dmabuf(VirtIOGPU *g,
   uint32_t scanout_id,
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 4d549377cb..dd037137e9 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -523,6 +523,7 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
 console_has_gl(scanout->con)) {
 dpy_gl_update(scanout->con, 0, 0, scanout->width,
   scanout->height);
+virtio_gpu_resource_wait_sync(g, res);
 return;
 }
 }
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index bcf54d970f..9b9b499d06 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -274,6 +274,8 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g,
  uint32_t scanout_id,
  struct virtio_gpu_simple_resource *res,
  struct virtio_gpu_framebuffer *fb);
+void virtio_gpu_resource_wait_sync(VirtIOGPU *g,
+   struct virtio_gpu_simple_resource *res);
 
 /* virtio-gpu-3d.c */
 void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
-- 
2.30.2




[PATCH v1 0/5] virtio-gpu: Add implicit (and default) sync mechanism for blobs

2021-06-07 Thread Vivek Kasireddy
When the Guest and Host are using Blob resources, there is a chance
that they may use the underlying storage associated with a Blob at
the same time leading to glitches such as flickering or tearing.
To prevent these from happening, the Host needs to ensure that it
waits until its Blit is completed by the Host GPU before returning
control back to the Guest from resource_flush().

This should be the default behavior regardless of the type of Guest
that is using Blob resources but would be particularly useful for 
Guests that are using frontbuffer rendering such as Linux with X
or Windows 10, etc.

Cc: Gerd Hoffmann 
Cc: Dongwon Kim 
Cc: Tina Zhang 

Vivek Kasireddy (5):
  ui/gtk: Create a common release_dmabuf helper
  ui: Add a helper to wait on a dmabuf sync object
  ui/egl: Add egl helpers to help with synchronization
  ui: Create sync objects only for blobs
  virtio-gpu: Make resource_flush wait on the sync object for blobs

 hw/display/virtio-gpu-udmabuf.c | 30 ++
 hw/display/virtio-gpu.c |  1 +
 include/hw/virtio/virtio-gpu.h  |  2 ++
 include/ui/console.h|  8 ++
 include/ui/egl-helpers.h|  4 +++
 include/ui/gtk.h|  2 --
 ui/console.c| 10 
 ui/egl-helpers.c| 44 +
 ui/gtk-egl.c| 18 --
 ui/gtk-gl-area.c|  8 ++
 ui/gtk.c| 26 ++-
 11 files changed, 142 insertions(+), 11 deletions(-)

-- 
2.30.2




Re: [PATCH 04/55] target/arm: Add handling for PSR.ECI/ICI

2021-06-07 Thread Richard Henderson

On 6/7/21 9:57 AM, Peter Maydell wrote:

+void clear_eci_state(DisasContext *s)
+{
+/*
+ * Clear any ECI/ICI state: used when a load multiple/store
+ * multiple insn executes.
+ */
+if (s->eci) {
+TCGv_i32 tmp = tcg_temp_new_i32();
+tcg_gen_movi_i32(tmp, 0);


tcg_const_i32 or preferably tcg_constant_i32.



+/*
+ * the CONDEXEC TB flags are CPSR bits [15:10][26:25]. On A-profile this
+ * is always the IT bits. On M-profile, some of the reserved encodings
+ * of IT are used instead to indicate either ICI or ECI, which
+ * indicate partial progress of a restartable insn that was interrupted
+ * partway through by an exception:
+ *  * if CONDEXEC[3:0] != 0b : CONDEXEC is IT bits
+ *  * if CONDEXEC[3:0] == 0b : CONDEXEC is ICI or ECI bits
+ * In all cases CONDEXEC == 0 means "not in IT block or restartable
+ * insn, behave normally".
+ */
+if (condexec & 0xf) {
+dc->condexec_mask = (condexec & 0xf) << 1;
+dc->condexec_cond = condexec >> 4;
+dc->eci = 0;
+} else {
+dc->condexec_mask = 0;
+dc->condexec_cond = 0;
+if (arm_feature(env, ARM_FEATURE_M)) {
+dc->eci = condexec >> 4;
+}


This else leaves eci uninitialized.


  dc->insn = insn;
  
+if (dc->eci) {

+/*
+ * For M-profile continuable instructions, ECI/ICI handling
+ * falls into these cases:
+ *  - interrupt-continuable instructions
+ * These are the various load/store multiple insns (both
+ * integer and fp). The ICI bits indicate the register
+ * where the load/store can resume. We make the IMPDEF
+ * choice to always do "instruction restart", ie ignore
+ * the ICI value and always execute the ldm/stm from the
+ * start. So all we need to do is zero PSR.ICI if the
+ * insn executes.
+ *  - MVE instructions subject to beat-wise execution
+ * Here the ECI bits indicate which beats have already been
+ * executed, and we must honour this. Each insn of this
+ * type will handle it correctly. We will update PSR.ECI
+ * in the helper function for the insn (some ECI values
+ * mean that the following insn also has been partially
+ * executed).
+ *  - Special cases which don't advance ECI
+ * The insns LE, LETP and BKPT leave the ECI/ICI state
+ * bits untouched.
+ *  - all other insns (the common case)
+ * Non-zero ECI/ICI means an INVSTATE UsageFault.
+ * We place a rewind-marker here. Insns in the previous
+ * three categories will set a flag in the DisasContext.
+ * If the flag isn't set after we call disas_thumb_insn()
+ * or disas_thumb2_insn() then we know we have a "some other
+ * insn" case. We will rewind to the marker (ie throwing away
+ * all the generated code) and instead emit "take exception".
+ */
+dc->eci_handled = false;


This should be done in arm_tr_init_disas_context, I think, unconditionally, 
next to eci.



+dc->insn_eci_rewind = tcg_last_op();


I believe that this is identical to dc->insn_start.  Certainly there does not 
seem to be any possibility of any opcodes emitted in between.


If you think we should use a different field, then initialize it to null next 
to eci/eci_handled.



r~



Re: [PATCH qemu v20] spapr: Implement Open Firmware client interface

2021-06-07 Thread BALATON Zoltan

On Mon, 7 Jun 2021, David Gibson wrote:

On Fri, Jun 04, 2021 at 03:59:22PM +0200, BALATON Zoltan wrote:

On Fri, 4 Jun 2021, David Gibson wrote:

On Wed, Jun 02, 2021 at 02:29:29PM +0200, BALATON Zoltan wrote:

On Wed, 2 Jun 2021, David Gibson wrote:

On Thu, May 27, 2021 at 02:42:39PM +0200, BALATON Zoltan wrote:

On Thu, 27 May 2021, David Gibson wrote:

On Tue, May 25, 2021 at 12:08:45PM +0200, BALATON Zoltan wrote:

On Tue, 25 May 2021, David Gibson wrote:

On Mon, May 24, 2021 at 12:55:07PM +0200, BALATON Zoltan wrote:

On Mon, 24 May 2021, David Gibson wrote:

What's ePAPR then and how is it different from PAPR? I mean the acronym not
the hypercall method, the latter is explained in that doc but what ePAPR
stands for and why is that method called like that is not clear to me.


Ok, history lesson time.

For a long time PAPR has been the document that described the OS
environment for IBM POWER based server hardware.  Before it was called
PAPR (POWER Architecture Platform Requirements) it was called the
"RPA" (Requirements for the POWER Architecture, I think?).  You might
see the old name in a few places.

Requiring a full Open Firmware and a bunch of other fairly heavyweight
stuff, PAPR really wasn't suitable for embedded ppc chips and boards.
The situation with those used to be a complete mess with basically
every board variant having it's own different firmware with its own
different way of presenting some fragments of vital data to the OS.

ePAPR - Embedded Power Architecture Platform Requirements - was
created as a standard to try to unify how this stuff was handled on
embedded ppc chips.  I was one of the authors on early versions of
it.  It's mostly based around giving the OS a flattened device tree,
with some deliberately minimal requirements on firmware initialization
and entry state.  Here's a link to one of those early versions:

http://elinux.org/images/c/cf/Power_ePAPR_APPROVED_v1.1.pdf

I thought there were later versions, but I couldn't seem to find any.
It's possible the process of refining later versions just petered out
as the embedded ppc world mostly died and the flattened device tree
development mostly moved to ARM.

Since some of the embedded chips from Freescale had hypervisor
capabilities, a hypercall model was added to ePAPR - but that wasn't
something I was greatly involved in, so I don't know much about it.

ePAPR is the reason that the original PAPR is sometimes referred to as
"sPAPR" to disambiguate.


Ah, thanks that really puts it in context. I've heard about PReP and CHRP 
in connection with the boards I've tried to emulate but don't know much 
about PAPR and server POWER systems.



The ePAPR (1.) seems to be preferred by KVM and
MOL OSI supported for compatibility.


That document looks pretty out of date.  Most of it is only discussing
KVM PR, which is now barely maintained.  KVM HV only works with PAPR
hypercalls.


The links says it's latest kernel docs, so maybe an update need to be sent
to KVM?


I guess, but the chances of me finding time to do it are approximately
zero.


So if we need something else instead of
2. PAPR hypercalls there seems to be two options: ePAPR and MOL OSI which
should work with KVM but then I'm not sure how to handle those on TCG.


[...]

I've tested that the missing rtas is not the reason for getting no output
via serial though, as even when disabling rtas on pegasos2.rom it boots and
I still get serial output just some PCI devices are not detected (such as
USB, the video card and the not emulated ethernet port but these are not
fatal so it might even work as a first try without rtas, just to boot a
Linux kernel for testing it would be enough if I can fix the serial output).
I still don't know why it's not finding serial but I think it may be some
missing or wrong info in the device tree I generat. I'll try to focus on
this for now and leave the above rtas question for later.


Oh.. another thought on that.  You have an ISA serial port on Pegasos,
I believe.  I wonder if the PCI->ISA bridge needs some configuration /
initialization that the firmware is expected to do.  If so you'll need
to mimic that setup in qemu for the VOF case.


That's what I begin to think because I've added everything to the device
tree that I thought could be needed and I still don't get it working so it
may need some config from the firmware. But how do I access device registers
from board code? I've tried adding a machine reset method and write to
memory mapped device registers but all my attempts failed. I've tried
cpu_stl_le_data and even memory_region_dispatch_write but these did not get
to the device. What's the way to access guest mmio regs from QEMU?


That's odd, cpu_stl() and memory_region_dispatch_write() should work
from board code (after the relevant memory regions are configured, of
course).  As an ISA serial port, it's probably accessed through IO
space, not memory space though, so you'd need _space_io.  And
if there is some bridge configuration 

[PATCH] softfloat: Fix tp init in float32_exp2

2021-06-07 Thread Richard Henderson
Typo in the conversion to FloatParts64.

Fixes: 572c4d862ff2
Fixes: Coverity CID 1457457
Signed-off-by: Richard Henderson 
---
 fpu/softfloat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 1cb162882b..4d0160fe9c 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -4818,7 +4818,7 @@ float32 float32_exp2(float32 a, float_status *status)
 
 float_raise(float_flag_inexact, status);
 
-float64_unpack_canonical(, float64_ln2, status);
+float64_unpack_canonical(, float64_ln2, status);
 xp = *parts_mul(, , status);
 xnp = xp;
 
-- 
2.25.1




Re: [PULL 25/29] softfloat: Convert float32_exp2 to FloatParts

2021-06-07 Thread Richard Henderson

On 6/7/21 2:07 PM, Peter Maydell wrote:

+FloatParts64 xp, xnp, tp, rp;


Coverity points out that we declare tp here without initializing it...

...

+float64_unpack_canonical(, float64_ln2, status);
+xp = *parts_mul(, , status);


...and then here we pass  to parts_mul() which looks at
its various fields. Missing initializer of some sort ?


Typo in the unpack; should have been tp.


r~



Re: [PATCH qemu v20] spapr: Implement Open Firmware client interface

2021-06-07 Thread BALATON Zoltan

On Mon, 7 Jun 2021, David Gibson wrote:

On Mon, Jun 07, 2021 at 12:21:21AM +0200, BALATON Zoltan wrote:

On Fri, 4 Jun 2021, David Gibson wrote:

On Wed, Jun 02, 2021 at 02:29:29PM +0200, BALATON Zoltan wrote:

On Wed, 2 Jun 2021, David Gibson wrote:

On Thu, May 27, 2021 at 02:42:39PM +0200, BALATON Zoltan wrote:

On Thu, 27 May 2021, David Gibson wrote:

On Tue, May 25, 2021 at 12:08:45PM +0200, BALATON Zoltan wrote:

On Tue, 25 May 2021, David Gibson wrote:

On Mon, May 24, 2021 at 12:55:07PM +0200, BALATON Zoltan wrote:

On Mon, 24 May 2021, David Gibson wrote:

On Sun, May 23, 2021 at 07:09:26PM +0200, BALATON Zoltan wrote:

On Sun, 23 May 2021, BALATON Zoltan wrote:
and would using sc 1 for hypercalls on pegasos2 cause other
problems later even if the assert could be removed?


At least in the short term, I think you probably can remove the
assert.  In your case the 'sc 1' calls aren't truly to a hypervisor,
but a special case escape to qemu for the firmware emulation.  I think
it's unlikely to cause problems later, because nothing on a 32-bit
system should be attempting an 'sc 1'.  The only thing I can think of
that would fail is some test case which explicitly verified that 'sc
1' triggered a 0x700 (SIGILL from userspace).


OK so the assert should check if the CPU has an HV bit. I think there was a
#detine for that somewhere that I can add to the assert then I can try that.
What I wasn't sure about is that sc 1 would conflict with the guest's usage
of normal sc calls or are these going through different paths and only sc 1
will trigger vhyp callback not affecting notmal sc calls?


The vhyp shouldn't affect normal system calls, 'sc 1' is specifically
for hypercalls, as opposed to normal 'sc' (a.k.a. 'sc 0'), and the
vhyp only intercepts the hypercall version (after all Linux on PAPR
certainly uses its own system calls, and hypercalls are active for the
lifetime of the guest there).


(Or if this causes
an otherwise unnecessary VM exit on KVM even when it works then maybe
looking for a different way in the future might be needed.


What you're doing here won't work with KVM as it stands.  There are
basically two paths into the vhyp hypercall path: 1) from TCG, if we
interpret an 'sc 1' instruction we enter vhyp, 2) from KVM, if we get
a KVM_EXIT_PAPR_HCALL KVM exit then we also go to the vhyp path.

The second path is specific to the PAPR (ppc64) implementation of KVM,
and will not work for a non-PAPR platform without substantial
modification of the KVM code.


OK so then at that point when we try KVM we'll need to look at alternative
ways, I think MOL OSI worked with KVM at least in MOL but will probably make
all syscalls exit KVM but since we'll probably need to use KVM PR it will
exit anyway. For now I keep this vhyp as it does not run with KVM for other
reasons yet so that's another area to clean up so as a proof of concept
first version of using VOF vhyp will do.


Eh, since you'll need to modify KVM anyway, it probably makes just as
much sense to modify it to catch the 'sc 1' as MoL's magic thingy.


I'm not sure how KVM works for this case so I also don't know why and what
would need to be modified. I think we'll only have KVM PR working as newer
POWER CPUs having HV (besides being rare among potential users) are probably
too different to run the OSes that expect at most a G4 on pegasos2 so likely
it won't work with KVM HV.


Oh, it definitely won't work with KVM HV.


If we have KVM PR doesn't sc already trap so we
could add MOL OSI without further modification to KVM itself only needing
change in QEMU?


Uh... I guess so?


I also hope that MOL OSI could be useful for porting some
paravirt drivers from MOL for running Mac OS X on Mac emulation but I don't
know about that for sure so I'm open to any other solution too.


Maybe.  I never know much about MOL to begin with, and anything I did
know was a decade or more ago so I've probably forgotten.


That may still be more than what I know about it since I never had any
knowledge about PPC KVM and don't have any PPC hardware to test with so I'm
mostly guessing. (I could test with KVM emulated in QEMU and I did set up an
environment for that but that's a bit slow and inconvenient so I'd leave KVM
support to those interested and have more knowledge and hardware for it.)


Sounds like a problem for someone else another time, then.


So now that it works on TCG with vhyp I tried what it would do on KVM PR
with the sc 1 but I could only test that on QEMU itself running in a Linux
guest. First I've hit missing this callback:

https://git.qemu.org/?p=qemu.git;a=blob;f=target/ppc/kvm.c;h=104a308abb5700b2fe075397271f314d7f607543;hb=HEAD#l856

that I can fix by providing a callback in pegasos2.c that does what the else
clause would do returning POWERPC_CPU(current_cpu)->env.spr[SPR_SDR1] (I
guess that's the correct thing to do if it works without vhyp).


For your case, yes that's right.  Again vhyp is designed for the case
where the (hash) MMU is 

Re: [PATCH] qemu-{img,nbd}: Don't report zeroed cluster as a hole

2021-06-07 Thread Eric Blake
On Mon, Jun 07, 2021 at 04:22:27PM -0500, Eric Blake wrote:

[replying to myself]

> > Here is simpler reproducer:
> > 
> > # Create a qcow2 image with a raw backing file:
> > $ qemu-img create base.raw $((4*64*1024))
> > $ qemu-img create -f qcow2 -b base.raw -F raw top.qcow2
> > 
> > # Write to first 3 clusters of base:
> > $ qemu-io -f raw -c "write -P 65 0 64k" base.raw
> > $ qemu-io -f raw -c "write -P 66 64k 64k" base.raw
> > $ qemu-io -f raw -c "write -P 67 128k 64k" base.raw
> > 
> > # Write to second cluster of top, hiding second cluster of base:
> > $ qemu-io -f qcow2 -c "write -P 69 64k 64k" top.qcow2
> > 
> > # Write zeroes to third cluster of top, hiding third cluster of base:
> > $ qemu-io -f qcow2 -c "write -z 128k 64k" top.qcow2

Aha. While reproducing this locally, I typoed this as 'write -z 12k
64k', which absolutely changes the map produced...

> 
> $ ./qemu-nbd -r -t -f qcow2 top.qcow2 -A
> $ nbdinfo --map=qemu:allocation-depth nbd://localhost
>  0  1310721  local
> 131072  1310722  backing depth 2
> 
> However, _that_ output looks odd - it claims that clusters 0 and 1 are
> local, and 2 and 3 come from a backing file.  Without reading code, I
> would have expected something closer to the qcow2 view, claiming that
> clusters 1 and 2 are local, while 0 and 3 come from a backing file (3
> could also be reported as unallocated, but only if you use a qcow2 as
> the backing file instead of raw, since we have no easy way to
> determine which holes map to file system allocations in raw files).

and totally explains my confusion here.

> 
> /me goes to debug...  I'll need to reply in a later email when I've
> spent more time on that.
> 

After recreating the file properly, by writing the zeroes at 128k
instead of 12k, I now see:

$ nbdinfo --map=qemu:allocation-depth nbd://localhost
 0   655362  backing depth 2
 65536  1310721  local
196608   655362  backing depth 2

which is EXACTLY what I expected.  And sufficient for you to recreate
your backing chain:

Cluster 0 is backing depth 2 + allocated, so it comes from the backing
file; nothing to write in your replacement top.qcow2.  Cluster 1 is
local + allocated, so it comes from top.qcow2 and consists of actual
data, definitely write that one.  Cluster 2 is local + hole,zero, so
it reads as zero, but comes from top.qcow2 without any allocation;
when building your replacement .qcow2 file, you MUST write this
cluster to match the local allocation and override anything being
inherited from the backing file, but it is up to you whether you write
it as allocated zeroes or as an unallocated but reads-as-zero cluster.
Cluster 3 is backing depth 2 + hole,zero, which means it was read from
the backing file, and you can safely omit it from your replacement
top.qcow2.

> In short, I agree that the current situation is awkward, but I'm not
> sure that this patch is right.  Rather, I'm wondering if we have a bug
> in qemu:allocation-depth, and where once that is fixed, you should be
> using that alongside base:allocation when deciding how to guess on how
> to reconstruct a qcow2 backing chain using only information learned
> over NBD.

And since the problem was in my command line transcription skills, and
not in qemu proper, I don't think we want this patch; rather, I feel
we are better served if you could fix your downstream tooling to start
using qemu:allocation-depth if you are trying to recreate which
portions of a qcow2 file MUST be written in order for that qcow2 file
backed by a different image to provide the same data as seen over NBD.

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




Re: [PATCH v3 0/4] target/i386/cpu: introduce new CPU models for x86-64 ABI levels

2021-06-07 Thread Eduardo Habkost
On Mon, Jun 07, 2021 at 02:58:39PM +0100, Daniel P. Berrangé wrote:
> This series is motivated by this blog that describes how RHEL-9
> will recommend use of the x86-64-v2 microarchitectural ABI level:
> 
>   
> https://developers.redhat.com/blog/2021/01/05/building-red-hat-enterprise-linux-9-for-the-x86-64-v2-microarchitecture-level/
> 
> The implication of compiling code with -march=x86-64-v2 is that
> this code will no longer be guaranteed to be runnable on a
> number of the CPU models exposed by the x86_64 target emulator,
> most notably qemu64 which is the default.
> 
> This series is not proposing to change the QEMU default CPU model
> for x86_64 target. I show how this is can trivially be done in
> patch 3, but not suggesting that we actually do that, as upstream
> is quite conservative in dropping support for old host hardware.
> 
> New CPU models
> ==
> 
> It is instead exploring the possibilities of defining new CPU
> models in QEMU to closely match the x86-64 uarch ABI levels in
> a relatively vendor agnostic manner. This could be used by
> downstream vendors who wish to target specific uarch ABI levels
> in custom machine types.
> 
> One of the nice things about "qemu64" is that its naming presents
> it as effectively being a vendor-neutral model (if we ignore that
> vendor=AMD is in fact reported in CPUID).
> 
> If we look at the feature set fo x86-64-v2 ABI, we see that the
> QEMU "Nehalem" model is the closest match. This is also happens
> to be runnable on AMD Opteron G4/G5 and EPYC hosts. None the less,
> the use of an Intel specific CPU model name on an AMD host feels
> uncomfortable.
> 
> Vendor neutral naming
> =
> 
> The idea behind this series is thus to introduce new CPU model
> names with vendor neutral naming, to more directly correlate
> with defined x86-64 uarch ABI levels. We don't want to just
> invent CPUs with a completely arbitrary set of CPU features as
> history has shown that brings its own problems. eg a guest
> uses features A and B, but only does CPUID checks for existence
> of feature B, assuming that B implies A.
> 
> The specification for x86-64 ABI levels uses x86-64-vNN naming
> but this clashes with QEMU's use of "vNN" for versioning. I
> felt it would be confusing to end up with CPU model names
> like  "x86-64-v1-v1". Thus I've used an "-abiNNN" suffix
> instead. Also note I have an "-abi1" suffix here for the
> baseline. Arguably we could just drop the suffix entirely for
> the baseline.
> 
> A further note is that we could have used "qemu64" as the
> naming prefix, eg qemu64-abi2, qemu64-abi3, etc. Alot of
> people hold negative opinions of the qemu64 model in general
> though, so I felt a clean break with the past might be
> desirable, even though the x86-64-abi1 CPU  model is effectively
> identical to qemu64.
> 
> Runnability of new models
> =
> 
> The goal of the x86-64-abiNNN CPU models is that they should be
> runnable on any physical host which supports the CPUIDs features
> for that uarch ABI level. It is hard to figure out what exact
> set of CPUID features we should report. The uarch ABI document
> only specifies the minimum expectation, but we can't define a
> CPU in QEMU using only the minimum set as that would omit
> countless important features.
> 

Do you have a list of features that were not in the ABI document
but were included in the CPU models you've added?  What exactly
make them important enough for us, but not important enough for
the ABI level specification writers?


In patch 2/3 you wrote:

| Historically we've found that defining CPU models with an arbitrary
| combination of CPU features can be problematic, as some guest OS
| will not check all features they use, and instead assume that if
| they see feature "XX", then "YY" will always exist. This is reasonable
| in bare metal, but subject to breakage in virtualization.

Do we know how likely that is?  Any examples where this has
happened?

What if we simply used the raw list of features from the
specification, add those as CPU models experimentally, and let
people report issues if they find them?  Too risky?  Not useful
in practice?

Maybe we could provide both a "x86-64-abiNN" and a
"x86-64-abiNN-minimal" CPU model.  We could even use the -minimal
CPU model definition to write a test case that ensure the
algorithm you describe below is always being followed.  The name
should make it clear that the CPU model is more conservative but
less likely to be useful.


> Thus to determine the feature set to use in x86-64-abiNNN CPU
> models, this series used a script (see patch 4) which did the
> following:
> 
>   * Find list of current CPU models that satisfy ABI NN
>   * From this list, calculate the lowest common denominator (LCD)
> of CPUID features
>   * From the LCD, find the existing CPU model that has the fewest
> extra features over the LCD.
>   * Use that closest match, minus the extra features
> to define 

Re: [PATCH] qemu-{img,nbd}: Don't report zeroed cluster as a hole

2021-06-07 Thread Eric Blake
On Mon, Jun 07, 2021 at 11:22:04PM +0300, Nir Soffer wrote:
> When zeroing a cluster in an image with backing file, qemu-img and
> qemu-nbd reported the area as a hole. This does not affect the guest
> since the area is read as zero, but breaks code trying to reconstruct
> the image chain based on qemu-img map or qemu-nbd block status response.

Trying to reconstruct the image chain based on qemu-nbd block status
should not be attempted on just base:allocation data, but should also
take into account qemu:allocation-depth.  From the perspective of the
core NBD protocol, there is no backing file, so trying to guess what
the backing file contains without using qemu extensions is unlikely to
be correct, as shown in your example.  The fact that you could abuse
it with qemu 5.2 but it broke in 6.0 is not necessarily the sign of a
regression in 6.0, but rather could be evidence that you have been
trying to use an undocumented implementation quirk rather than a
stable interface.

> 
> Here is simpler reproducer:
> 
> # Create a qcow2 image with a raw backing file:
> $ qemu-img create base.raw $((4*64*1024))
> $ qemu-img create -f qcow2 -b base.raw -F raw top.qcow2
> 
> # Write to first 3 clusters of base:
> $ qemu-io -f raw -c "write -P 65 0 64k" base.raw
> $ qemu-io -f raw -c "write -P 66 64k 64k" base.raw
> $ qemu-io -f raw -c "write -P 67 128k 64k" base.raw
> 
> # Write to second cluster of top, hiding second cluster of base:
> $ qemu-io -f qcow2 -c "write -P 69 64k 64k" top.qcow2
> 
> # Write zeroes to third cluster of top, hiding third cluster of base:
> $ qemu-io -f qcow2 -c "write -z 128k 64k" top.qcow2
> 
> This creates:
> 
> top:  -D0-
> base: ABC-
> 
> How current qemu-img and qemu-nbd report the state:
> 
> $ qemu-img map --output json top.qcow2
> [{ "start": 0, "length": 65536, "depth": 1, "zero": false, "data": true, 
> "offset": 0},
> { "start": 65536, "length": 65536, "depth": 0, "zero": false, "data": 
> true, "offset": 327680},
> { "start": 131072, "length": 65536, "depth": 0, "zero": true, "data": 
> false},
> { "start": 196608, "length": 65536, "depth": 1, "zero": true, "data": 
> false, "offset": 196608}]

Note how this one reports "depth":1 when the backing file is consulted...

> 
> $ qemu-nbd -r -t -f qcow2 top.qcow2 &
> $ qemu-img map --output json nbd://localhost
> [{ "start": 0, "length": 131072, "depth": 0, "zero": false, "data": true, 
> "offset": 0},
> { "start": 131072, "length": 131072, "depth": 0, "zero": true, "data": 
> false, "offset": 131072}]

...but since NBD has no notion of a backing file, there is nothing
that qemu can do to report depth information itself.  If you want to
reconstruct the backing chain, you should be able to further query
qemu:allocation-depth, and piece the two queries together to get what
you need:

$ ./qemu-nbd -r -t -f qcow2 top.qcow2 -A
$ nbdinfo --map=qemu:allocation-depth nbd://localhost
 0  1310721  local
131072  1310722  backing depth 2

However, _that_ output looks odd - it claims that clusters 0 and 1 are
local, and 2 and 3 come from a backing file.  Without reading code, I
would have expected something closer to the qcow2 view, claiming that
clusters 1 and 2 are local, while 0 and 3 come from a backing file (3
could also be reported as unallocated, but only if you use a qcow2 as
the backing file instead of raw, since we have no easy way to
determine which holes map to file system allocations in raw files).

/me goes to debug...  I'll need to reply in a later email when I've
spent more time on that.

[Oh, and that reminds me, I would love to patch nbdinfo to let --map
query all available contexts, not just base:allocation, without having
to explicitly name alternative --map=FOO... But it missed today's
stable release of libnbd 1.8]

[The same information can be obtained via qemu-img using
x-dirty-bitmap and --image-opts, but is so much more of a hack that
for now I will just refer to iotest 309 instead of spelling it out
here]

> 
> $ nbdinfo --map nbd://localhost
>  0  1310720  allocated
> 131072  1310723  hole,zero

This faithfully reflects what qemu-img saw, which is all the more the
NBD protocol lets us send without the use of extensions like
qemu:allocation-depth.

> 
> The third extents is reported as a hole in both cases. In qmeu-nbd the

qemu

> cluster is merged with forth cluster which is actually a hole.
> 
> This is incorrect since if it was a hole, the third cluster would be
> exposed to the guest. Programs using qemu-nbd output to reconstruct the
> image chain on other storage would be confused and copy only the first 2
> cluster. The results of this copy will be an image exposing the third
> cluster from the base image, corrupting the guest data.

This is where I disagree - if the NBD protocol exposed the notion of a
backing file, then reporting a local hole should indeed imply 

Re: [PATCH 03/55] target/arm: Handle VPR semantics in existing code

2021-06-07 Thread Richard Henderson

On 6/7/21 9:57 AM, Peter Maydell wrote:

@@ -410,16 +415,19 @@ void HELPER(v7m_preserve_fp_state)(CPUARMState *env)
  env->v7m.fpccr[is_secure] &= ~R_V7M_FPCCR_LSPACT_MASK;
  
  if (ts) {

-/* Clear s0 to s31 and the FPSCR */
+/* Clear s0 to s31 and the FPSCR and VPR */
  int i;
  
  for (i = 0; i < 32; i += 2) {

  *aa32_vfp_dreg(env, i / 2) = 0;
  }
  vfp_set_fpscr(env, 0);
+if (cpu_isar_feature(aa32_mve, cpu)) {
+env->v7m.vpr = 0;
+}


If the vpr does not exist without mve, is it cleaner to simply set vpr 
unconditionally?


Either way it looks good.
Reviewed-by: Richard Henderson 


r~



Re: [PULL 25/29] softfloat: Convert float32_exp2 to FloatParts

2021-06-07 Thread Peter Maydell
On Thu, 3 Jun 2021 at 22:58, Richard Henderson
 wrote:
>
> Keep the intermediate results in FloatParts instead of
> converting back and forth between float64.  Use muladd
> instead of separate mul+add.
>
> Reviewed-by: Alex Bennée 
> Signed-off-by: Richard Henderson 
> ---
>  fpu/softfloat.c | 53 +
>  1 file changed, 23 insertions(+), 30 deletions(-)
>
> diff --git a/fpu/softfloat.c b/fpu/softfloat.c
> index c32b1c7113..27306d6a93 100644
> --- a/fpu/softfloat.c
> +++ b/fpu/softfloat.c
> @@ -5210,47 +5210,40 @@ static const float64 float32_exp2_coefficients[15] =
>
>  float32 float32_exp2(float32 a, float_status *status)
>  {
> -bool aSign;
> -int aExp;
> -uint32_t aSig;
> -float64 r, x, xn;
> +FloatParts64 xp, xnp, tp, rp;

Coverity points out that we declare tp here without initializing it...

>  int i;
> -a = float32_squash_input_denormal(a, status);
>
> -aSig = extractFloat32Frac( a );
> -aExp = extractFloat32Exp( a );
> -aSign = extractFloat32Sign( a );
> -
> -if ( aExp == 0xFF) {
> -if (aSig) {
> -return propagateFloat32NaN(a, float32_zero, status);
> +float32_unpack_canonical(, a, status);
> +if (unlikely(xp.cls != float_class_normal)) {
> +switch (xp.cls) {
> +case float_class_snan:
> +case float_class_qnan:
> +parts_return_nan(, status);
> +return float32_round_pack_canonical(, status);
> +case float_class_inf:
> +return xp.sign ? float32_zero : a;
> +case float_class_zero:
> +return float32_one;
> +default:
> +break;
>  }
> -return (aSign) ? float32_zero : a;
> -}
> -if (aExp == 0) {
> -if (aSig == 0) return float32_one;
> +g_assert_not_reached();
>  }
>
>  float_raise(float_flag_inexact, status);
>
> -/* *** */
> -/* using float64 for approximation */
> -/* *** */
> -x = float32_to_float64(a, status);
> -x = float64_mul(x, float64_ln2, status);
> +float64_unpack_canonical(, float64_ln2, status);
> +xp = *parts_mul(, , status);

...and then here we pass  to parts_mul() which looks at
its various fields. Missing initializer of some sort ?

(CID 1457457)

thanks
-- PMM



Re: [RFC PATCH] target/ppc: fix address translation bug for hash table mmus

2021-06-07 Thread Richard Henderson

On 6/7/21 12:29 PM, Bruno Piazera Larsen wrote:
I just tried sending mmu_idx all the way down, but I ran into a very weird bug 
of gcc. If we have to add one more parameter that GCC can't just optimize away 
we get at least a slow down of 5x for the first test of check-acceptance (could 
be more, but the test times out after 900 seconds, so I'm not sure).


That's odd.  We already have more arguments than the number of argument 
registers...  A 5x slowdown is distinctly odd.



One way 
that I managed to get around that is saving the current MSR, setting it to 5, 
and restoring after the xlate call. The code ended up something like:


int new_idx = (5msr = (env->msr & clr) | new_idx;
ret = ppc_radix64_partition_scoped_xlate(...);
/* restore old mmu_idx */
env->msr = (env->msr & clr) | old_idx;


No, this is silly.

We need to do one of two things:
  - make sure everything is inlined,
  - reduce the number of arguments.

We're currently passing in 9 arguments, which really is too many already.  We 
should be using something akin to mmu_ctx_t, but probably specific to radix64 
without the random stuff collected for random other mmu models.



r~



Re: [PATCH v3 0/7] acpi: Error Record Serialization Table, ERST, support for QEMU

2021-06-07 Thread Eric DeVolder
Igor,
Thanks for the information/feedback. I am working to implement all your 
suggestions; from my perspective, there were two big changes requested, and the 
use of hostmem-file was the first, and the conversion to PCI the second. V3 was 
the hostmem-file, and hopefully all changes then in v4.
Regards,
eric


From: Igor Mammedov 
Sent: Monday, June 7, 2021 7:49 AM
To: Eric DeVolder 
Cc: qemu-devel@nongnu.org ; m...@redhat.com 
; marcel.apfelb...@gmail.com ; 
pbonz...@redhat.com ; r...@twiddle.net ; 
ehabk...@redhat.com ; Konrad Wilk 
; Boris Ostrovsky 
Subject: Re: [PATCH v3 0/7] acpi: Error Record Serialization Table, ERST, 
support for QEMU

On Fri, 28 May 2021 14:14:12 -0400
Eric DeVolder  wrote:

> NOTE: Also, I wanted to push this v3 for review while alerting
> that I will be on holiday through June 8 (possibly a few days
> later).
this version addressed only the way the host storage is accessed
(and even that is only partially and needs more work to put into it)
The rest of the comments on v2 are still not addressed.

> NOTE: The patches are arranged such that each can be applied
> in order and not break the build (except the 0001 patch). Igor
> has hinted at changing this, but I'm unsure how else to
> re-arrange these patches accordingly.
as minimum, see suggestion for splitting #4 in 5/7

> NOTE: With the conversion to TYPE_MEMORY_BACKEND_FILE, live
> migration to a completely different host does not behave
> properly (it loses the ERST contents because the file is not
> present on the new host). This still needs to be worked out.
> Other than live migration, this patchset fully works.

see: vmstate_register_ram_global()

> This patchset introduces support for the ACPI Error Record
> Serialization Table, ERST.
>
> Linux uses the persistent storage filesystem, pstore, to record
> information (eg. dmesg tail) upon panics and shutdowns.  Pstore is
> independent of, and runs before, kdump.  In certain scenarios (ie.
> hosts/guests with root filesystems on NFS/iSCSI where networking
> software and/or hardware fails), pstore may contain the only
> information available for post-mortem debugging.
>
> Two common storage backends for the pstore filesystem are ACPI ERST
> and UEFI. Most BIOS implement ACPI ERST; however, ACPI ERST is not
> currently supported in QEMU, and UEFI is not utilized in all guests.
> By implementing ACPI ERST within QEMU, then the ACPI ERST becomes a
> viable pstore storage backend for virtual machines (as it is now for
> bare metal machines).
>
> Enabling support for ACPI ERST facilitates a consistent method to
> capture kernel panic information in a wide range of guests: from
> resource-constrained microvms to very large guests, and in
> particular, in direct-boot environments (which would lack UEFI
> run-time services).
>
> Note that Microsoft Windows also utilizes the ACPI ERST for certain
> crash information, if available.
>
> The ACPI ERST persistent storage is contained within a single backing
> file, with a default size of 64KiB. The size and filename of the
> backing file can be obtained from QEMU parameters.
>
> The ACPI specification[1], in Chapter "ACPI Platform Error Interfaces
> (APEI)", and specifically subsection "Error Serialization", outlines
> a method for storing error records into persistent storage.
>
> [1] "Advanced Configuration and Power Interface Specification",
> version 6.2, May 2017.
> https://www.uefi.org/sites/default/files/resources/ACPI_6_2.pdf
>
> [2] "Unified Extensible Firmware Interface Specification",
> version 2.8, March 2019.
> https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_final.pdf
>
> Suggested-by: Konrad Wilk 
> Signed-off-by: Eric DeVolder 
>
> ---
> v3: 28may2021
>  - Converted to using a TYPE_MEMORY_BACKEND_FILE object rather than
>internal array with explicit file operations, per Igor.
good start but it's not complete yet.

>  - Changed the way the qdev and base address are handled, allowing
>ERST to be disabled at run-time. Also aligns better with other
>existing code.
it aligns with ancient code template and the way it used to plumb
into board (it's fine for pre-existing devices but not for new ones
(unless there is no other way )).
v2 had suggestions how to proceed (you asked some questions back then,
but result is not reflected in this series, which still has the old
code as it was in v2).


> v2: 8feb2021
>  - Added qtest/smoke test per Paolo Bonzini
>  - Split patch into smaller chunks, per Igo Mammedov
>  - Did away with use of ACPI packed structures, per Igo Mammedov
>
> v1: 26oct2020
>  - initial post
>
> ---
>  hw/acpi/erst.c | 909 
> +
>  hw/acpi/meson.build|   1 +
>  hw/i386/acpi-build.c   |   4 +
>  include/hw/acpi/erst.h |  97 ++
>  4 files changed, 1011 insertions(+)
>  create mode 100644 hw/acpi/erst.c
>  create mode 100644 include/hw/acpi/erst.h
>
>
> Eric DeVolder (7):
>   ACPI 

Re: [PATCH 03/11] softfloat: Introduce float_flag_inorm_denormal

2021-06-07 Thread Richard Henderson

On 6/7/21 10:19 AM, Alex Bennée wrote:

If you've got a better ordering of operations for this, do tell.


What I really want is to know which instructions translate into the if
(s->flush_inputs_to_zero) and verifying that is only checked once. Maybe
I'm just suspicious of compilers ability to optimise things away...






  Dump of assembler code for function float32_mul:
 0x00895d60 <+0>: movzbl 0x1(%rdx),%eax
 0x00895d64 <+4>: test   $0x10,%al
 0x00895d66 <+6>: je 0x895e30 


s->float_exception_flags & float_flag_inexact


 0x00895d6c <+12>:cmpb   $0x0,(%rdx)
 0x00895d6f <+15>:jne0x895e30 


s->float_rounding_mode == float_round_nearest_even


 0x00895d75 <+21>:test   $0x7f80,%edi
 0x00895d7b <+27>:jne0x895da0 
 0x00895d7d <+29>:test   $0x7fff,%edi
 0x00895d83 <+35>:je 0x895da0 


float32_is_denormal


 0x00895d85 <+37>:cmpb   $0x0,0x5(%rdx)
 0x00895d89 <+41>:je 0x895e60 


s->flush_inputs_to_zero


 0x00895d8f <+47>:or $0x40,%eax
 0x00895d92 <+50>:and$0x8000,%edi
 0x00895d98 <+56>:mov%al,0x1(%rdx)


flush-to-zero and set iflush_denormal


 0x00895da0 <+64>:test   $0x7f80,%esi
 0x00895da6 <+70>:jne0x895dd0 
 0x00895da8 <+72>:test   $0x7fff,%esi
 0x00895dae <+78>:je 0x895dd0 


float32_is_denormal (second operand)


 0x00895db0 <+80>:cmpb   $0x0,0x5(%rdx)
 0x00895db4 <+84>:movzbl 0x1(%rdx),%eax
 0x00895db8 <+88>:je 0x895e50 
 0x00895dbe <+94>:or $0x40,%eax
 0x00895dc1 <+97>:and$0x8000,%esi


s->flush_inputs_to_zero,
flush-to-zero,
set iflush_denormal.

...


 0x00895e50 <+240>:   or $0x20,%eax
 0x00895e53 <+243>:   mov%al,0x1(%rdx)
 0x00895e56 <+246>:   jmpq   0x895dd0 


set inorm_denormal (second operand)


 0x00895e60 <+256>:   or $0x20,%eax
 0x00895e63 <+259>:   mov%al,0x1(%rdx)
 0x00895e66 <+262>:   jmpq   0x895da0 


set inorm_denormal (first operand)

There do seem to be 3 reads/writes to exception_flags for float_raise.


r~



[PATCH] qemu-{img,nbd}: Don't report zeroed cluster as a hole

2021-06-07 Thread Nir Soffer
When zeroing a cluster in an image with backing file, qemu-img and
qemu-nbd reported the area as a hole. This does not affect the guest
since the area is read as zero, but breaks code trying to reconstruct
the image chain based on qemu-img map or qemu-nbd block status response.

Here is simpler reproducer:

# Create a qcow2 image with a raw backing file:
$ qemu-img create base.raw $((4*64*1024))
$ qemu-img create -f qcow2 -b base.raw -F raw top.qcow2

# Write to first 3 clusters of base:
$ qemu-io -f raw -c "write -P 65 0 64k" base.raw
$ qemu-io -f raw -c "write -P 66 64k 64k" base.raw
$ qemu-io -f raw -c "write -P 67 128k 64k" base.raw

# Write to second cluster of top, hiding second cluster of base:
$ qemu-io -f qcow2 -c "write -P 69 64k 64k" top.qcow2

# Write zeroes to third cluster of top, hiding third cluster of base:
$ qemu-io -f qcow2 -c "write -z 128k 64k" top.qcow2

This creates:

top:  -D0-
base: ABC-

How current qemu-img and qemu-nbd report the state:

$ qemu-img map --output json top.qcow2
[{ "start": 0, "length": 65536, "depth": 1, "zero": false, "data": true, 
"offset": 0},
{ "start": 65536, "length": 65536, "depth": 0, "zero": false, "data": true, 
"offset": 327680},
{ "start": 131072, "length": 65536, "depth": 0, "zero": true, "data": 
false},
{ "start": 196608, "length": 65536, "depth": 1, "zero": true, "data": 
false, "offset": 196608}]

$ qemu-nbd -r -t -f qcow2 top.qcow2 &
$ qemu-img map --output json nbd://localhost
[{ "start": 0, "length": 131072, "depth": 0, "zero": false, "data": true, 
"offset": 0},
{ "start": 131072, "length": 131072, "depth": 0, "zero": true, "data": 
false, "offset": 131072}]

$ nbdinfo --map nbd://localhost
 0  1310720  allocated
131072  1310723  hole,zero

The third extents is reported as a hole in both cases. In qmeu-nbd the
cluster is merged with forth cluster which is actually a hole.

This is incorrect since if it was a hole, the third cluster would be
exposed to the guest. Programs using qemu-nbd output to reconstruct the
image chain on other storage would be confused and copy only the first 2
cluster. The results of this copy will be an image exposing the third
cluster from the base image, corrupting the guest data.

I found that it can be fixed using BDRV_BLOCK_OFFSET_VALID when
reporting the status of the extent. When we have a valid offset, we
report based on BDRV_BLOCK_DATA. Otherwise we report based on
BDRV_BLOCK_ALLOCATED.

With this fix we get:

$ build/qemu-img map --output json top.qcow2
[{ "start": 0, "length": 65536, "depth": 1, "zero": false, "data": true, 
"offset": 0},
{ "start": 65536, "length": 65536, "depth": 0, "zero": false, "data": true, 
"offset": 327680},
{ "start": 131072, "length": 65536, "depth": 0, "zero": true, "data": true},
{ "start": 196608, "length": 65536, "depth": 1, "zero": true, "data": 
false, "offset": 196608}]

$ build/qemu-nbd -r -t -f qcow2 top.qcow2 &
$ qemu-img map --output json nbd://localhost
[{ "start": 0, "length": 131072, "depth": 0, "zero": false, "data": true, 
"offset": 0},
{ "start": 131072, "length": 65536, "depth": 0, "zero": true, "data": true, 
"offset": 131072},
{ "start": 196608, "length": 65536, "depth": 0, "zero": true, "data": 
false, "offset": 196608}]

$ nbdinfo --map nbd://localhost
 0  1310720  allocated
131072   655362  zero
196608   655363  hole,zero

The issue was found by ovirt-imageio functional tests:
https://github.com/oVirt/ovirt-imageio/blob/master/daemon/test/client_test.py

I did not update any of the existing tests, and I'm sure many tests are
missing, and the documentation should change to describe the new
behavior. Posting as is for early review.

Signed-off-by: Nir Soffer 
Resolves: https://bugzilla.redhat.com/1968693
---
 nbd/server.c | 8 ++--
 qemu-img.c   | 4 +++-
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/nbd/server.c b/nbd/server.c
index b60ebc3ab6..adf37905d5 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -2127,8 +2127,12 @@ static int blockstatus_to_extents(BlockDriverState *bs, 
uint64_t offset,
 return ret;
 }
 
-flags = (ret & BDRV_BLOCK_DATA ? 0 : NBD_STATE_HOLE) |
-(ret & BDRV_BLOCK_ZERO ? NBD_STATE_ZERO : 0);
+flags = (ret & BDRV_BLOCK_ZERO ? NBD_STATE_ZERO : 0);
+
+if (ret & BDRV_BLOCK_OFFSET_VALID)
+flags |= (ret & BDRV_BLOCK_DATA ? 0 : NBD_STATE_HOLE);
+else
+flags |= (ret & BDRV_BLOCK_ALLOCATED ? 0 : NBD_STATE_HOLE);
 
 if (nbd_extent_array_add(ea, num, flags) < 0) {
 return 0;
diff --git a/qemu-img.c b/qemu-img.c
index a5993682aa..6808e12d87 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -3039,7 +3039,9 @@ static int get_block_status(BlockDriverState *bs, int64_t 
offset,
 *e = (MapEntry) {
 

[PATCH 40/42] scripts/qmp-shell: move to python/qemu/qmp/qmp_shell.py

2021-06-07 Thread John Snow
The script will be unavailable for a commit or two, which will help
preserve development history attached to the new file. A forwarder will
be added shortly afterwards.

With qmp_shell in the python qemu.qmp package, now it is fully type
checked, linted, etc. via the Python CI. It will be quite a bit harder
to accidentally break it again in the future.

Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell => python/qemu/qmp/qmp_shell.py | 3 ---
 1 file changed, 3 deletions(-)
 rename scripts/qmp/qmp-shell => python/qemu/qmp/qmp_shell.py (99%)
 mode change 100755 => 100644

diff --git a/scripts/qmp/qmp-shell b/python/qemu/qmp/qmp_shell.py
old mode 100755
new mode 100644
similarity index 99%
rename from scripts/qmp/qmp-shell
rename to python/qemu/qmp/qmp_shell.py
index 15aedb80c2..337acfce2d
--- a/scripts/qmp/qmp-shell
+++ b/python/qemu/qmp/qmp_shell.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python3
 #
 # Copyright (C) 2009, 2010 Red Hat Inc.
 #
@@ -96,8 +95,6 @@
 Sequence,
 )
 
-
-sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
 from qemu import qmp
 from qemu.qmp import QMPMessage
 
-- 
2.31.1




[PATCH 41/42] python: add qmp-shell entry point

2021-06-07 Thread John Snow
now 'qmp-shell' should be available from the command line when
installing the python package.

Signed-off-by: John Snow 
---
 python/setup.cfg | 1 +
 1 file changed, 1 insertion(+)

diff --git a/python/setup.cfg b/python/setup.cfg
index 7f3c59d74e..85cecbb41b 100644
--- a/python/setup.cfg
+++ b/python/setup.cfg
@@ -51,6 +51,7 @@ console_scripts =
 qom-tree = qemu.qmp.qom:QOMTree.entry_point
 qom-fuse = qemu.qmp.qom_fuse:QOMFuse.entry_point [fuse]
 qemu-ga-client = qemu.qmp.qemu_ga_client:main
+qmp-shell = qemu.qmp.qmp_shell:main
 
 [flake8]
 extend-ignore = E722  # Prefer pylint's bare-except checks to flake8's
-- 
2.31.1




[PATCH 42/42] scripts/qmp-shell: add redirection shim

2021-06-07 Thread John Snow
qmp-shell has a new home, add a redirect for a little while as the dust
settles.

Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 11 +++
 1 file changed, 11 insertions(+)
 create mode 100755 scripts/qmp/qmp-shell

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
new file mode 100755
index 00..4a20f97db7
--- /dev/null
+++ b/scripts/qmp/qmp-shell
@@ -0,0 +1,11 @@
+#!/usr/bin/env python3
+
+import os
+import sys
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
+from qemu.qmp import qmp_shell
+
+
+if __name__ == '__main__':
+qmp_shell.main()
-- 
2.31.1




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

2021-06-07 Thread Mathieu Poirier
On Fri, 4 Jun 2021 at 07:36, Srivatsa Vaddagiri  wrote:
>
> * Mathieu Poirier via Stratos-dev  
> [2021-06-01 20:03:14]:
>
> > 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.
>
> Is there a Rust language based equivalent that is planned as well (just like
> what was done for virtio-i2c)?
>

Yes, that part is in the works.

> - vatsa
>
> --
> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation



Re: [PATCH v3 3/4] scripts: helper to generate x86_64 CPU ABI compat info

2021-06-07 Thread Eduardo Habkost
On Mon, Jun 07, 2021 at 02:11:44PM -0300, Eduardo Habkost wrote:
> On Mon, Jun 07, 2021 at 02:58:42PM +0100, Daniel P. Berrangé wrote:
> [...]
> > +# Assumes externally launched process such as
> > +#
> > +#   qemu-system-x86_64 -qmp unix:/tmp/qmp,server,nowait -display none 
> > -accel kvm
> > +#
> > +# Note different results will be obtained with TCG, as
> > +# TCG masks out certain features otherwise present in
> > +# the CPU model definitions, as does KVM.
> > +
> > +
> > +sock = sys.argv[1]
> > +cmd = sys.argv[2]
> > +shell = qmp.QEMUMonitorProtocol(sock)
> > +shell.connect()
> > +
> > +models = shell.cmd("query-cpu-definitions")
> 
> I would make the script launch QEMU itself, using the QEMUMachine
> class.
> 
> But life is too short for polishing a quick utility script, so:
> 
> Acked-by: Eduardo Habkost 
> 
> I plan to queue this once I review the rest of the series.

I'm queueing patch 1/4 and this one.

I'm not sure about the lowest common denominator approach for
generating the CPU models in patch 2/4, but I need to read your
the cover letter more carefully, to be able to comment.

-- 
Eduardo




[PATCH 39/42] scripts/qmp-shell: add docstrings

2021-06-07 Thread John Snow
Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 39 ++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index 1a8a4ba18a..15aedb80c2 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -106,15 +106,20 @@ LOG = logging.getLogger(__name__)
 
 
 class QMPCompleter:
+"""
+QMPCompleter provides a readline library tab-complete behavior.
+"""
 # NB: Python 3.9+ will probably allow us to subclass list[str] directly,
 # but pylint as of today does not know that List[str] is simply 'list'.
 def __init__(self) -> None:
 self._matches: List[str] = []
 
 def append(self, value: str) -> None:
+"""Append a new valid completion to the list of possibilities."""
 return self._matches.append(value)
 
 def complete(self, text: str, state: int) -> Optional[str]:
+"""readline.set_completer() callback implementation."""
 for cmd in self._matches:
 if cmd.startswith(text):
 if state == 0:
@@ -124,7 +129,9 @@ class QMPCompleter:
 
 
 class QMPShellError(qmp.QMPError):
-pass
+"""
+QMP Shell Base error class.
+"""
 
 
 class FuzzyJSON(ast.NodeTransformer):
@@ -137,6 +144,9 @@ class FuzzyJSON(ast.NodeTransformer):
 @classmethod
 def visit_Name(cls,  # pylint: disable=invalid-name
node: ast.Name) -> ast.AST:
+"""
+Transform Name nodes with certain values into Constant (keyword) nodes.
+"""
 if node.id == 'true':
 return ast.Constant(value=True)
 if node.id == 'false':
@@ -147,6 +157,13 @@ class FuzzyJSON(ast.NodeTransformer):
 
 
 class QMPShell(qmp.QEMUMonitorProtocol):
+"""
+QMPShell provides a basic readline-based QMP shell.
+
+:param address: Address of the QMP server.
+:param pretty: Pretty-print QMP messages.
+:param verbose: Echo outgoing QMP messages to console.
+"""
 def __init__(self, address: qmp.SocketAddrT,
  pretty: bool = False, verbose: bool = False):
 super().__init__(address)
@@ -333,6 +350,9 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 
 def show_banner(self,
 msg: str = 'Welcome to the QMP low-level shell!') -> None:
+"""
+Print to stdio a greeting, and the QEMU version if available.
+"""
 print(msg)
 if not self._greeting:
 print('Connected')
@@ -342,6 +362,9 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 
 @property
 def prompt(self) -> str:
+"""
+Return the current shell prompt, including a trailing space.
+"""
 if self._transmode:
 return 'TRANS> '
 return '(QEMU) '
@@ -367,6 +390,9 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 return self._execute_cmd(cmdline)
 
 def repl(self) -> Iterator[None]:
+"""
+Return an iterator that implements the REPL.
+"""
 self.show_banner()
 while self.read_exec_command():
 yield
@@ -374,6 +400,13 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 
 
 class HMPShell(QMPShell):
+"""
+HMPShell provides a basic readline-based HMP shell, tunnelled via QMP.
+
+:param address: Address of the QMP server.
+:param pretty: Pretty-print QMP messages.
+:param verbose: Echo outgoing QMP messages to console.
+"""
 def __init__(self, address: qmp.SocketAddrT,
  pretty: bool = False, verbose: bool = False):
 super().__init__(address, pretty, verbose)
@@ -451,11 +484,15 @@ class HMPShell(QMPShell):
 
 
 def die(msg: str) -> NoReturn:
+"""Write an error to stderr, then exit with a return code of 1."""
 sys.stderr.write('ERROR: %s\n' % msg)
 sys.exit(1)
 
 
 def main() -> None:
+"""
+qmp-shell entry point: parse command line arguments and start the REPL.
+"""
 parser = argparse.ArgumentParser()
 parser.add_argument('-H', '--hmp', action='store_true',
 help='Use HMP interface')
-- 
2.31.1




[PATCH 22/42] scripts/qmp-shell: move the REPL functionality into QMPShell

2021-06-07 Thread John Snow
Instead of doing this in main, move it into the class itself. (This
makes it easier to put into the qemu.qmp package later by removing as
much as we can from the main() function.)

Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index 31269859c4..aa148517a8 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -318,6 +318,12 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 
 return self._execute_cmd(cmdline)
 
+def repl(self):
+self.show_banner()
+while self.read_exec_command():
+yield
+self.close()
+
 
 class HMPShell(QMPShell):
 def __init__(self, address, pretty=False, verbose=False):
@@ -435,10 +441,8 @@ def main():
 except OSError as err:
 die(f"Couldn't connect to {args.qmp_server}: {err!s}")
 
-qemu.show_banner()
-while qemu.read_exec_command():
+for _ in qemu.repl():
 pass
-qemu.close()
 
 
 if __name__ == '__main__':
-- 
2.31.1




[PATCH 38/42] scripts/qmp-shell: make QMPShellError inherit QMPError

2021-06-07 Thread John Snow
In preparation for moving qmp-shell into the qemu.qmp package, make
QMPShellError inherit from QMPError so that all custom errors in this
package all derive from QMPError.

Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index 40ff9e0a82..1a8a4ba18a 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -123,7 +123,7 @@ class QMPCompleter:
 return None
 
 
-class QMPShellError(Exception):
+class QMPShellError(qmp.QMPError):
 pass
 
 
-- 
2.31.1




[PATCH 36/42] scripts/qmp-shell: convert usage comment to docstring

2021-06-07 Thread John Snow
The nice usage comment should be a docstring instead of a comment, so
that it's visible from other python tooling.

Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 128 --
 1 file changed, 72 insertions(+), 56 deletions(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index 8d5845ab48..82fe16cff8 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -1,7 +1,5 @@
 #!/usr/bin/env python3
 #
-# Low-level QEMU shell on top of QMP.
-#
 # Copyright (C) 2009, 2010 Red Hat Inc.
 #
 # Authors:
@@ -10,60 +8,78 @@
 # This work is licensed under the terms of the GNU GPL, version 2.  See
 # the COPYING file in the top-level directory.
 #
-# Usage:
-#
-# Start QEMU with:
-#
-# # qemu [...] -qmp unix:./qmp-sock,server
-#
-# Run the shell:
-#
-# $ qmp-shell ./qmp-sock
-#
-# Commands have the following format:
-#
-#< command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ]
-#
-# For example:
-#
-# (QEMU) device_add driver=e1000 id=net1
-# {u'return': {}}
-# (QEMU)
-#
-# key=value pairs also support Python or JSON object literal subset notations,
-# without spaces. Dictionaries/objects {} are supported as are arrays [].
-#
-#example-command arg-name1={'key':'value','obj'={'prop':"value"}}
-#
-# Both JSON and Python formatting should work, including both styles of
-# string literal quotes. Both paradigms of literal values should work,
-# including null/true/false for JSON and None/True/False for Python.
-#
-#
-# Transactions have the following multi-line format:
-#
-#transaction(
-#action-name1 [ arg-name1=arg1 ] ... [arg-nameN=argN ]
-#...
-#action-nameN [ arg-name1=arg1 ] ... [arg-nameN=argN ]
-#)
-#
-# One line transactions are also supported:
-#
-#transaction( action-name1 ... )
-#
-# For example:
-#
-# (QEMU) transaction(
-# TRANS> block-dirty-bitmap-add node=drive0 name=bitmap1
-# TRANS> block-dirty-bitmap-clear node=drive0 name=bitmap0
-# TRANS> )
-# {"return": {}}
-# (QEMU)
-#
-# Use the -v and -p options to activate the verbose and pretty-print options,
-# which will echo back the properly formatted JSON-compliant QMP that is being
-# sent to QEMU, which is useful for debugging and documentation generation.
+
+"""
+Low-level QEMU shell on top of QMP.
+
+usage: qmp-shell [-h] [-H] [-N] [-v] [-p] qmp_server
+
+positional arguments:
+  qmp_server< UNIX socket path | TCP address:port >
+
+optional arguments:
+  -h, --helpshow this help message and exit
+  -H, --hmp Use HMP interface
+  -N, --skip-negotiation
+Skip negotiate (for qemu-ga)
+  -v, --verbose Verbose (echo commands sent and received)
+  -p, --pretty  Pretty-print JSON
+
+
+Start QEMU with:
+
+# qemu [...] -qmp unix:./qmp-sock,server
+
+Run the shell:
+
+$ qmp-shell ./qmp-sock
+
+Commands have the following format:
+
+   < command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ]
+
+For example:
+
+(QEMU) device_add driver=e1000 id=net1
+{'return': {}}
+(QEMU)
+
+key=value pairs also support Python or JSON object literal subset notations,
+without spaces. Dictionaries/objects {} are supported as are arrays [].
+
+   example-command arg-name1={'key':'value','obj'={'prop':"value"}}
+
+Both JSON and Python formatting should work, including both styles of
+string literal quotes. Both paradigms of literal values should work,
+including null/true/false for JSON and None/True/False for Python.
+
+
+Transactions have the following multi-line format:
+
+   transaction(
+   action-name1 [ arg-name1=arg1 ] ... [arg-nameN=argN ]
+   ...
+   action-nameN [ arg-name1=arg1 ] ... [arg-nameN=argN ]
+   )
+
+One line transactions are also supported:
+
+   transaction( action-name1 ... )
+
+For example:
+
+(QEMU) transaction(
+TRANS> block-dirty-bitmap-add node=drive0 name=bitmap1
+TRANS> block-dirty-bitmap-clear node=drive0 name=bitmap0
+TRANS> )
+{"return": {}}
+(QEMU)
+
+Use the -v and -p options to activate the verbose and pretty-print options,
+which will echo back the properly formatted JSON-compliant QMP that is being
+sent to QEMU, which is useful for debugging and documentation generation.
+"""
+
 import argparse
 import ast
 import json
-- 
2.31.1




[PATCH 30/42] python/qmp: return generic type from context manager

2021-06-07 Thread John Snow
__enter__ can be invoked from a subclass, so it needs a more flexible
type.

Signed-off-by: John Snow 
---
 python/qemu/qmp/__init__.py | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/python/qemu/qmp/__init__.py b/python/qemu/qmp/__init__.py
index ba0d2281d6..376954cb6d 100644
--- a/python/qemu/qmp/__init__.py
+++ b/python/qemu/qmp/__init__.py
@@ -30,6 +30,7 @@
 TextIO,
 Tuple,
 Type,
+TypeVar,
 Union,
 cast,
 )
@@ -220,7 +221,9 @@ def __get_events(self, wait: Union[bool, float] = False) -> 
None:
 if ret is None:
 raise QMPConnectError("Error while reading from socket")
 
-def __enter__(self) -> 'QEMUMonitorProtocol':
+T = TypeVar('T')
+
+def __enter__(self: T) -> T:
 # Implement context manager enter function.
 return self
 
-- 
2.31.1




[PATCH 35/42] scripts/qmp-shell: Remove too-broad-exception

2021-06-07 Thread John Snow
We are only anticipating QMPShellErrors here, for syntax we weren't able
to understand. Other errors, if any, should be allowed to percolate
upwards.

Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index 78e4eae007..8d5845ab48 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -291,10 +291,13 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 def _execute_cmd(self, cmdline: str) -> bool:
 try:
 qmpcmd = self.__build_cmd(cmdline)
-except Exception as err:
-print('Error while parsing command line: %s' % err)
-print('command format:  ', end=' ')
-print('[arg-name1=arg1] ... [arg-nameN=argN]')
+except QMPShellError as err:
+print(
+f"Error while parsing command line: {err!s}\n"
+"command format:  "
+"[arg-name1=arg1] ... [arg-nameN=argN",
+file=sys.stderr
+)
 return True
 # For transaction mode, we may have just cached the action:
 if qmpcmd is None:
-- 
2.31.1




[PATCH 13/42] scripts/qmp-shell: rename one and two-letter variables

2021-06-07 Thread John Snow
A bit of churn and housekeeping for pylint, flake8 et al.

Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 24 
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index 8d84467b53..afb4b0c544 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -176,8 +176,8 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 pass
 # Try once again as FuzzyJSON:
 try:
-st = ast.parse(val, mode='eval')
-return ast.literal_eval(FuzzyJSON().visit(st))
+tree = ast.parse(val, mode='eval')
+return ast.literal_eval(FuzzyJSON().visit(tree))
 except SyntaxError:
 pass
 except ValueError:
@@ -195,14 +195,14 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 value = self.__parse_value(val)
 optpath = key.split('.')
 curpath = []
-for p in optpath[:-1]:
-curpath.append(p)
-d = parent.get(p, {})
-if type(d) is not dict:
+for path in optpath[:-1]:
+curpath.append(path)
+obj = parent.get(path, {})
+if type(obj) is not dict:
 msg = 'Cannot use "{:s}" as both leaf and non-leaf key'
 raise QMPShellError(msg.format('.'.join(curpath)))
-parent[p] = d
-parent = d
+parent[path] = obj
+parent = obj
 if optpath[-1] in parent:
 if type(parent[optpath[-1]]) is dict:
 msg = 'Cannot use "{:s}" as both leaf and non-leaf key'
@@ -267,8 +267,8 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 def _execute_cmd(self, cmdline):
 try:
 qmpcmd = self.__build_cmd(cmdline)
-except Exception as e:
-print('Error while parsing command line: %s' % e)
+except Exception as err:
+print('Error while parsing command line: %s' % err)
 print('command format:  ', end=' ')
 print('[arg-name1=arg1] ... [arg-nameN=argN]')
 return True
@@ -313,8 +313,8 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 print()
 return False
 if cmdline == '':
-for ev in self.get_events():
-print(ev)
+for event in self.get_events():
+print(event)
 self.clear_events()
 return True
 else:
-- 
2.31.1




[PATCH 29/42] scripts/qmp-shell: unprivatize 'pretty' property

2021-06-07 Thread John Snow
Similar to verbose, there's no reason this needs to be hidden.

Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index b465c7f9e2..f14fe211cc 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -135,11 +135,11 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 super().__init__(address)
 self._greeting: Optional[QMPMessage] = None
 self._completer = QMPCompleter()
-self._pretty = pretty
 self._transmode = False
 self._actions: List[QMPMessage] = []
 self._histfile = os.path.join(os.path.expanduser('~'),
   '.qmp-shell_history')
+self.pretty = pretty
 self.verbose = verbose
 
 def _fill_completion(self) -> None:
@@ -274,10 +274,9 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 return qmpcmd
 
 def _print(self, qmp_message: object) -> None:
-indent = None
-if self._pretty:
-indent = 4
-jsobj = json.dumps(qmp_message, indent=indent, sort_keys=self._pretty)
+jsobj = json.dumps(qmp_message,
+   indent=4 if self.pretty else None,
+   sort_keys=self.pretty)
 print(str(jsobj))
 
 def _execute_cmd(self, cmdline: str) -> bool:
-- 
2.31.1




[PATCH 32/42] scripts/qmp-shell: use logging to show warnings

2021-06-07 Thread John Snow
A perfect candidate is non-fatal shell history messages.

Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index ec028d662e..0199a13a34 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -67,6 +67,7 @@
 import argparse
 import ast
 import json
+import logging
 import os
 import re
 import readline
@@ -85,6 +86,9 @@ from qemu import qmp
 from qemu.qmp import QMPMessage
 
 
+LOG = logging.getLogger(__name__)
+
+
 class QMPCompleter:
 # NB: Python 3.9+ will probably allow us to subclass list[str] directly,
 # but pylint as of today does not know that List[str] is simply 'list'.
@@ -167,13 +171,15 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 except FileNotFoundError:
 pass
 except IOError as err:
-print(f"Failed to read history '{self._histfile}': {err!s}")
+msg = f"Failed to read history '{self._histfile}': {err!s}"
+LOG.warning(msg)
 
 def _save_history(self) -> None:
 try:
 readline.write_history_file(self._histfile)
 except IOError as err:
-print(f"Failed to save history file '{self._histfile}': {err!s}")
+msg = f"Failed to save history file '{self._histfile}': {err!s}"
+LOG.warning(msg)
 
 @classmethod
 def __parse_value(cls, val: str) -> object:
-- 
2.31.1




[PATCH 16/42] scripts/qmp-shell: use isinstance() instead of type()

2021-06-07 Thread John Snow
A bit more idiomatic, and quiets some linter warnings.

Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index bf7a49dfc1..970f43dd00 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -195,13 +195,13 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 for path in optpath[:-1]:
 curpath.append(path)
 obj = parent.get(path, {})
-if type(obj) is not dict:
+if not isinstance(obj, dict):
 msg = 'Cannot use "{:s}" as both leaf and non-leaf key'
 raise QMPShellError(msg.format('.'.join(curpath)))
 parent[path] = obj
 parent = obj
 if optpath[-1] in parent:
-if type(parent[optpath[-1]]) is dict:
+if isinstance(parent[optpath[-1]], dict):
 msg = 'Cannot use "{:s}" as both leaf and non-leaf key'
 raise QMPShellError(msg.format('.'.join(curpath)))
 raise QMPShellError(f'Cannot set "{key}" multiple times')
-- 
2.31.1




[PATCH 33/42] scripts/qmp-shell: remove TODO

2021-06-07 Thread John Snow
We still want to revamp qmp-shell again, but there's much more to the
idea than the comment now intuits. Remove it.

Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 2 --
 1 file changed, 2 deletions(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index 0199a13a34..3c32b576a3 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -130,8 +130,6 @@ class FuzzyJSON(ast.NodeTransformer):
 return node
 
 
-# TODO: QMPShell's interface is a bit ugly (eg. _fill_completion() and
-#   _execute_cmd()). Let's design a better one.
 class QMPShell(qmp.QEMUMonitorProtocol):
 def __init__(self, address: qmp.SocketAddrT,
  pretty: bool = False, verbose: bool = False):
-- 
2.31.1




[PATCH 37/42] scripts/qmp-shell: remove double-underscores

2021-06-07 Thread John Snow
They're not needed; single underscore is enough to express intent that
these methods are "internal". double underscore is used as a weak name
mangling, but that isn't beneficial for us here.

Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 52 +--
 1 file changed, 26 insertions(+), 26 deletions(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index 82fe16cff8..40ff9e0a82 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -171,7 +171,7 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 for cmd in cmds['return']:
 self._completer.append(cmd['name'])
 
-def __completer_setup(self) -> None:
+def _completer_setup(self) -> None:
 self._completer = QMPCompleter()
 self._fill_completion()
 readline.set_history_length(1024)
@@ -196,7 +196,7 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 LOG.warning(msg)
 
 @classmethod
-def __parse_value(cls, val: str) -> object:
+def _parse_value(cls, val: str) -> object:
 try:
 return int(val)
 except ValueError:
@@ -221,9 +221,9 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 pass
 return val
 
-def __cli_expr(self,
-   tokens: Sequence[str],
-   parent: qmp.QMPObject) -> None:
+def _cli_expr(self,
+  tokens: Sequence[str],
+  parent: qmp.QMPObject) -> None:
 for arg in tokens:
 (key, sep, val) = arg.partition('=')
 if sep != '=':
@@ -231,7 +231,7 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 f"Expected a key=value pair, got '{arg!s}'"
 )
 
-value = self.__parse_value(val)
+value = self._parse_value(val)
 optpath = key.split('.')
 curpath = []
 for path in optpath[:-1]:
@@ -249,7 +249,7 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 raise QMPShellError(f'Cannot set "{key}" multiple times')
 parent[optpath[-1]] = value
 
-def __build_cmd(self, cmdline: str) -> Optional[QMPMessage]:
+def _build_cmd(self, cmdline: str) -> Optional[QMPMessage]:
 """
 Build a QMP input object from a user provided command-line in the
 following format:
@@ -289,13 +289,13 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 if cmdargs[-1] == ')':
 cmdargs.pop(-1)
 finalize = True
-self.__cli_expr(cmdargs[1:], action['data'])
+self._cli_expr(cmdargs[1:], action['data'])
 self._actions.append(action)
-return self.__build_cmd(')') if finalize else None
+return self._build_cmd(')') if finalize else None
 
 # Standard command: parse and return it to be executed.
 qmpcmd = {'execute': cmdargs[0], 'arguments': {}}
-self.__cli_expr(cmdargs[1:], qmpcmd['arguments'])
+self._cli_expr(cmdargs[1:], qmpcmd['arguments'])
 return qmpcmd
 
 def _print(self, qmp_message: object) -> None:
@@ -306,7 +306,7 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 
 def _execute_cmd(self, cmdline: str) -> bool:
 try:
-qmpcmd = self.__build_cmd(cmdline)
+qmpcmd = self._build_cmd(cmdline)
 except QMPShellError as err:
 print(
 f"Error while parsing command line: {err!s}\n"
@@ -329,7 +329,7 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 
 def connect(self, negotiate: bool = True) -> None:
 self._greeting = super().connect(negotiate)
-self.__completer_setup()
+self._completer_setup()
 
 def show_banner(self,
 msg: str = 'Welcome to the QMP low-level shell!') -> None:
@@ -377,10 +377,10 @@ class HMPShell(QMPShell):
 def __init__(self, address: qmp.SocketAddrT,
  pretty: bool = False, verbose: bool = False):
 super().__init__(address, pretty, verbose)
-self.__cpu_index = 0
+self._cpu_index = 0
 
-def __cmd_completion(self) -> None:
-for cmd in self.__cmd_passthrough('help')['return'].split('\r\n'):
+def _cmd_completion(self) -> None:
+for cmd in self._cmd_passthrough('help')['return'].split('\r\n'):
 if cmd and cmd[0] != '[' and cmd[0] != '\t':
 name = cmd.split()[0]  # drop help text
 if name == 'info':
@@ -396,22 +396,22 @@ class HMPShell(QMPShell):
 self._completer.append(name)
 self._completer.append('help ' + name)  # help completion
 
-def __info_completion(self) -> None:
-for cmd in self.__cmd_passthrough('info')['return'].split('\r\n'):
+def _info_completion(self) -> None:
+for cmd in self._cmd_passthrough('info')['return'].split('\r\n'):
 if cmd:
 self._completer.append('info ' + cmd.split()[1])
 
-def __other_completion(self) -> None:
+  

[PATCH 23/42] scripts/qmp-shell: Fix "FuzzyJSON" parser

2021-06-07 Thread John Snow
I'm not sure when this regressed (Or maybe if it was ever working right
to begin with?), but the Python AST requires you to change "Names" to
"Constants" in order to truly convert `false` to `False`.

Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index aa148517a8..847d34890f 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -95,18 +95,19 @@ class QMPShellError(Exception):
 class FuzzyJSON(ast.NodeTransformer):
 """
 This extension of ast.NodeTransformer filters literal "true/false/null"
-values in an AST and replaces them by proper "True/False/None" values that
-Python can properly evaluate.
+values in a Python AST and replaces them by proper "True/False/None" values
+that Python can properly evaluate.
 """
 
 @classmethod
-def visit_Name(cls, node):  # pylint: disable=invalid-name
+def visit_Name(cls,  # pylint: disable=invalid-name
+   node: ast.Name) -> ast.AST:
 if node.id == 'true':
-node.id = 'True'
+return ast.Constant(value=True)
 if node.id == 'false':
-node.id = 'False'
+return ast.Constant(value=False)
 if node.id == 'null':
-node.id = 'None'
+return ast.Constant(value=None)
 return node
 
 
@@ -174,10 +175,9 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 # Try once again as FuzzyJSON:
 try:
 tree = ast.parse(val, mode='eval')
-return ast.literal_eval(FuzzyJSON().visit(tree))
-except SyntaxError:
-pass
-except ValueError:
+transformed = FuzzyJSON().visit(tree)
+return ast.literal_eval(transformed)
+except (SyntaxError, ValueError):
 pass
 return val
 
-- 
2.31.1




[PATCH 17/42] scripts/qmp-shell: use argparse

2021-06-07 Thread John Snow
Use argparse instead of an open-coded CLI parser, for consistency with
everything else.

Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 82 +--
 1 file changed, 32 insertions(+), 50 deletions(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index 970f43dd00..5317dcd516 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -64,7 +64,7 @@
 # Use the -v and -p options to activate the verbose and pretty-print options,
 # which will echo back the properly formatted JSON-compliant QMP that is being
 # sent to QEMU, which is useful for debugging and documentation generation.
-
+import argparse
 import ast
 import atexit
 import json
@@ -401,65 +401,47 @@ def die(msg):
 sys.exit(1)
 
 
-def fail_cmdline(option=None):
-if option:
-sys.stderr.write('ERROR: bad command-line option \'%s\'\n' % option)
-sys.stderr.write(
-'qmp-shell [ -v ] [ -p ] [ -H ] [ -N ] '
-'< UNIX socket path> | < TCP address:port >\n'
-)
-sys.stderr.write('-v Verbose (echo command sent and received)\n')
-sys.stderr.write('-p Pretty-print JSON\n')
-sys.stderr.write('-H Use HMP interface\n')
-sys.stderr.write('-N Skip negotiate (for qemu-ga)\n')
-sys.exit(1)
-
-
 def main():
-addr = ''
-qemu = None
-hmp = False
-pretty = False
-verbose = False
-negotiate = True
+parser = argparse.ArgumentParser()
+parser.add_argument('-H', '--hmp', action='store_true',
+help='Use HMP interface')
+parser.add_argument('-N', '--skip-negotiation', action='store_true',
+help='Skip negotiate (for qemu-ga)')
+parser.add_argument('-v', '--verbose', action='store_true',
+help='Verbose (echo commands sent and received)')
+parser.add_argument('-p', '--pretty', action='store_true',
+help='Pretty-print JSON')
 
+default_server = os.environ.get('QMP_SOCKET')
+parser.add_argument('qmp_server', action='store',
+default=default_server,
+help='< UNIX socket path | TCP address:port >')
+
+args = parser.parse_args()
+if args.qmp_server is None:
+parser.error("QMP socket or TCP address must be specified")
+
+qemu: QMPShell
 try:
-for arg in sys.argv[1:]:
-if arg == "-H":
-if qemu is not None:
-fail_cmdline(arg)
-hmp = True
-elif arg == "-p":
-pretty = True
-elif arg == "-N":
-negotiate = False
-elif arg == "-v":
-verbose = True
-else:
-if qemu is not None:
-fail_cmdline(arg)
-if hmp:
-qemu = HMPShell(arg)
-else:
-qemu = QMPShell(arg, pretty)
-addr = arg
-
-if qemu is None:
-fail_cmdline()
+if args.hmp:
+qemu = HMPShell(args.qmp_server)
+else:
+qemu = QMPShell(args.qmp_server, args.pretty)
 except qmp.QMPBadPortError:
-die('bad port number in command-line')
+parser.error(f"Bad port number: {args.qmp_server}")
+return  # pycharm doesn't know error() is noreturn
 
 try:
-qemu.connect(negotiate)
+qemu.connect(negotiate=not args.skip_negotiation)
 except qmp.QMPConnectError:
-die('Didn\'t get QMP greeting message')
+die("Didn't get QMP greeting message")
 except qmp.QMPCapabilitiesError:
-die('Could not negotiate capabilities')
-except OSError:
-die('Could not connect to %s' % addr)
+die("Couldn't negotiate capabilities")
+except OSError as err:
+die(f"Couldn't connect to {args.qmp_server}: {err!s}")
 
 qemu.show_banner()
-qemu.set_verbosity(verbose)
+qemu.set_verbosity(args.verbose)
 while qemu.read_exec_command(qemu.get_prompt()):
 pass
 qemu.close()
-- 
2.31.1




[PATCH 09/42] scripts/qmp-shell: declare verbose in __init__

2021-06-07 Thread John Snow
Linters get angry when we don't define state at init time.

Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 1 +
 1 file changed, 1 insertion(+)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index 3066e37ae5..4027454324 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -120,6 +120,7 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 self._actions = list()
 self._histfile = os.path.join(os.path.expanduser('~'),
   '.qmp-shell_history')
+self._verbose = False
 
 def _fill_completion(self):
 cmds = self.cmd('query-commands')
-- 
2.31.1




[PATCH 18/42] scripts/qmp-shell: Add pretty attribute to HMP shell

2021-06-07 Thread John Snow
It's less useful, but it makes the initialization methods LSP
consistent, which quiets a mypy complaint.

Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 11 ---
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index 5317dcd516..de5fa189f0 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -322,8 +322,8 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 
 
 class HMPShell(QMPShell):
-def __init__(self, address):
-super().__init__(address)
+def __init__(self, address, pretty=False):
+super().__init__(address, pretty)
 self.__cpu_index = 0
 
 def __cmd_completion(self):
@@ -421,12 +421,9 @@ def main():
 if args.qmp_server is None:
 parser.error("QMP socket or TCP address must be specified")
 
-qemu: QMPShell
+shell_class = HMPShell if args.hmp else QMPShell
 try:
-if args.hmp:
-qemu = HMPShell(args.qmp_server)
-else:
-qemu = QMPShell(args.qmp_server, args.pretty)
+qemu = shell_class(args.qmp_server, args.pretty)
 except qmp.QMPBadPortError:
 parser.error(f"Bad port number: {args.qmp_server}")
 return  # pycharm doesn't know error() is noreturn
-- 
2.31.1




[PATCH 08/42] scripts/qmp-shell: Use python3-style super()

2021-06-07 Thread John Snow
Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index f354549bf2..3066e37ae5 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -112,7 +112,7 @@ class FuzzyJSON(ast.NodeTransformer):
 #   _execute_cmd()). Let's design a better one.
 class QMPShell(qmp.QEMUMonitorProtocol):
 def __init__(self, address, pretty=False):
-super(QMPShell, self).__init__(self.parse_address(address))
+super().__init__(self.parse_address(address))
 self._greeting = None
 self._completer = None
 self._pretty = pretty
@@ -281,7 +281,7 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 return True
 
 def connect(self, negotiate: bool = True):
-self._greeting = super(QMPShell, self).connect(negotiate)
+self._greeting = super().connect(negotiate)
 self.__completer_setup()
 
 def show_banner(self, msg='Welcome to the QMP low-level shell!'):
@@ -322,7 +322,7 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 
 class HMPShell(QMPShell):
 def __init__(self, address):
-QMPShell.__init__(self, address)
+super().__init__(address)
 self.__cpu_index = 0
 
 def __cmd_completion(self):
-- 
2.31.1




[PATCH 31/42] scripts/qmp-shell: Use context manager instead of atexit

2021-06-07 Thread John Snow
We can invoke the shell history writing when we leave the QMPShell scope
instead of relying on atexit. Doing so may be preferable to avoid global
state being registered from within a class instead of from the
application logic directly.

Use QMP's context manager to hook this history saving at close time,
which gets invoked when we leave the context block.

Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 33 ++---
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index f14fe211cc..ec028d662e 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -66,7 +66,6 @@
 # sent to QEMU, which is useful for debugging and documentation generation.
 import argparse
 import ast
-import atexit
 import json
 import os
 import re
@@ -142,6 +141,11 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 self.pretty = pretty
 self.verbose = verbose
 
+def close(self) -> None:
+# Hook into context manager of parent to save shell history.
+self._save_history()
+super().close()
+
 def _fill_completion(self) -> None:
 cmds = self.cmd('query-commands')
 if 'error' in cmds:
@@ -164,9 +168,8 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 pass
 except IOError as err:
 print(f"Failed to read history '{self._histfile}': {err!s}")
-atexit.register(self.__save_history)
 
-def __save_history(self) -> None:
+def _save_history(self) -> None:
 try:
 readline.write_history_file(self._histfile)
 except IOError as err:
@@ -448,25 +451,25 @@ def main() -> None:
 parser.error("QMP socket or TCP address must be specified")
 
 shell_class = HMPShell if args.hmp else QMPShell
+
 try:
 address = shell_class.parse_address(args.qmp_server)
 except qmp.QMPBadPortError:
 parser.error(f"Bad port number: {args.qmp_server}")
 return  # pycharm doesn't know error() is noreturn
 
-qemu = shell_class(address, args.pretty, args.verbose)
+with shell_class(address, args.pretty, args.verbose) as qemu:
+try:
+qemu.connect(negotiate=not args.skip_negotiation)
+except qmp.QMPConnectError:
+die("Didn't get QMP greeting message")
+except qmp.QMPCapabilitiesError:
+die("Couldn't negotiate capabilities")
+except OSError as err:
+die(f"Couldn't connect to {args.qmp_server}: {err!s}")
 
-try:
-qemu.connect(negotiate=not args.skip_negotiation)
-except qmp.QMPConnectError:
-die("Didn't get QMP greeting message")
-except qmp.QMPCapabilitiesError:
-die("Couldn't negotiate capabilities")
-except OSError as err:
-die(f"Couldn't connect to {args.qmp_server}: {err!s}")
-
-for _ in qemu.repl():
-pass
+for _ in qemu.repl():
+pass
 
 
 if __name__ == '__main__':
-- 
2.31.1




[PATCH 26/42] python/qmp: add QMPObject type alias

2021-06-07 Thread John Snow
This is meant to represent any generic object seen in a QMPMessage, not
just the root object itself.

Signed-off-by: John Snow 
---
 python/qemu/qmp/__init__.py | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/python/qemu/qmp/__init__.py b/python/qemu/qmp/__init__.py
index a6e1a7b857..ba0d2281d6 100644
--- a/python/qemu/qmp/__init__.py
+++ b/python/qemu/qmp/__init__.py
@@ -41,6 +41,9 @@
 #: QMPReturnValue is the 'return' value of a command.
 QMPReturnValue = object
 
+#: QMPObject is any object in a QMP message.
+QMPObject = Dict[str, object]
+
 # QMPMessage can be outgoing commands or incoming events/returns.
 # QMPReturnValue is usually a dict/json object, but due to QAPI's
 # 'returns-whitelist', it can actually be anything.
-- 
2.31.1




[PATCH 15/42] scripts/qmp-shell: remove if-raise-else patterns

2021-06-07 Thread John Snow
Shushes pylint. I don't always mind these patterns personally, but I'm
not as sure that I want to remove the warning from pylint's repertoire
entirely. Oh well.

Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index 80cd432607..bf7a49dfc1 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -204,8 +204,7 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 if type(parent[optpath[-1]]) is dict:
 msg = 'Cannot use "{:s}" as both leaf and non-leaf key'
 raise QMPShellError(msg.format('.'.join(curpath)))
-else:
-raise QMPShellError(f'Cannot set "{key}" multiple times')
+raise QMPShellError(f'Cannot set "{key}" multiple times')
 parent[optpath[-1]] = value
 
 def __build_cmd(self, cmdline):
@@ -309,13 +308,14 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 except EOFError:
 print()
 return False
+
 if cmdline == '':
 for event in self.get_events():
 print(event)
 self.clear_events()
 return True
-else:
-return self._execute_cmd(cmdline)
+
+return self._execute_cmd(cmdline)
 
 def set_verbosity(self, verbose):
 self._verbose = verbose
-- 
2.31.1




[PATCH 19/42] scripts/qmp-shell: Make verbose a public attribute

2021-06-07 Thread John Snow
No real reason to hide this behind an underscore; make it part of the
initializer and make it a regular RW attribute.
Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 16 ++--
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index de5fa189f0..cfcefb95f9 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -113,7 +113,7 @@ class FuzzyJSON(ast.NodeTransformer):
 # TODO: QMPShell's interface is a bit ugly (eg. _fill_completion() and
 #   _execute_cmd()). Let's design a better one.
 class QMPShell(qmp.QEMUMonitorProtocol):
-def __init__(self, address, pretty=False):
+def __init__(self, address, pretty=False, verbose=False):
 super().__init__(self.parse_address(address))
 self._greeting = None
 self._completer = None
@@ -122,7 +122,7 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 self._actions = list()
 self._histfile = os.path.join(os.path.expanduser('~'),
   '.qmp-shell_history')
-self._verbose = False
+self.verbose = verbose
 
 def _fill_completion(self):
 cmds = self.cmd('query-commands')
@@ -271,7 +271,7 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 # For transaction mode, we may have just cached the action:
 if qmpcmd is None:
 return True
-if self._verbose:
+if self.verbose:
 self._print(qmpcmd)
 resp = self.cmd_obj(qmpcmd)
 if resp is None:
@@ -317,13 +317,10 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 
 return self._execute_cmd(cmdline)
 
-def set_verbosity(self, verbose):
-self._verbose = verbose
-
 
 class HMPShell(QMPShell):
-def __init__(self, address, pretty=False):
-super().__init__(address, pretty)
+def __init__(self, address, pretty=False, verbose=False):
+super().__init__(address, pretty, verbose)
 self.__cpu_index = 0
 
 def __cmd_completion(self):
@@ -423,7 +420,7 @@ def main():
 
 shell_class = HMPShell if args.hmp else QMPShell
 try:
-qemu = shell_class(args.qmp_server, args.pretty)
+qemu = shell_class(args.qmp_server, args.pretty, args.verbose)
 except qmp.QMPBadPortError:
 parser.error(f"Bad port number: {args.qmp_server}")
 return  # pycharm doesn't know error() is noreturn
@@ -438,7 +435,6 @@ def main():
 die(f"Couldn't connect to {args.qmp_server}: {err!s}")
 
 qemu.show_banner()
-qemu.set_verbosity(args.verbose)
 while qemu.read_exec_command(qemu.get_prompt()):
 pass
 qemu.close()
-- 
2.31.1




[PATCH 14/42] scripts/qmp-shell: fix shell history exception handling

2021-06-07 Thread John Snow
We want to remove exceptions that are too broad here; we only want to
catch IOErrors that get raised as a direct result of the open call.

Signed-off-by: John Snow 
---
 scripts/qmp/qmp-shell | 15 ++-
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index afb4b0c544..80cd432607 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -67,7 +67,6 @@
 
 import ast
 import atexit
-import errno
 import json
 import os
 import re
@@ -143,19 +142,17 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 readline.set_completer_delims('')
 try:
 readline.read_history_file(self._histfile)
-except Exception as e:
-if isinstance(e, IOError) and e.errno == errno.ENOENT:
-# File not found. No problem.
-pass
-else:
-print("Failed to read history '%s'; %s" % (self._histfile, e))
+except FileNotFoundError:
+pass
+except IOError as err:
+print(f"Failed to read history '{self._histfile}': {err!s}")
 atexit.register(self.__save_history)
 
 def __save_history(self):
 try:
 readline.write_history_file(self._histfile)
-except Exception as e:
-print("Failed to save history file '%s'; %s" % (self._histfile, e))
+except IOError as err:
+print(f"Failed to save history file '{self._histfile}': {err!s}")
 
 @classmethod
 def __parse_value(cls, val):
-- 
2.31.1




  1   2   3   4   >