Re: [PATCH v14 5/8] qmp: decode feature & status bits in virtio-status

2022-06-09 Thread Michael S. Tsirkin
On Thu, May 19, 2022 at 02:30:43AM -0400, Jonah Palmer wrote:
> 
> On 5/16/22 16:26, Michael S. Tsirkin wrote:
> 
> On Fri, Apr 01, 2022 at 09:23:22AM -0400, Jonah Palmer wrote:
> 
> From: Laurent Vivier 
> 
> Display feature names instead of bitmaps for host, guest, and
> backend for VirtIODevices.
> 
> Display status names instead of bitmaps for VirtIODevices.
> 
> Display feature names instead of bitmaps for backend, protocol,
> acked, and features (hdev->features) for vhost devices.
> 
> Decode features according to device ID. Decode statuses
> according to configuration status bitmap (config_status_map).
> Decode vhost user protocol features according to vhost user
> protocol bitmap (vhost_user_protocol_map).
> 
> Transport features are on the first line. Undecoded bits (if
> any) are stored in a separate field.
> 
> Signed-off-by: Jonah Palmer 
> 
> 
> So this has several problems that I missed previously.
> First, sign off from poster is missing.
> 
> My apologies, will add missing Laurent's SOB in correct order for
> patches 3-8.


Were you going to repost?

> 
> 
> 
> 
> ---
>  hw/block/virtio-blk.c  |  29 
>  hw/char/virtio-serial-bus.c|  11 ++
>  hw/display/virtio-gpu.c|  18 ++
>  hw/input/virtio-input.c|  10 ++
>  hw/net/virtio-net.c|  47 +
>  hw/scsi/virtio-scsi.c  |  17 ++
>  hw/virtio/vhost-user-fs.c  |  10 ++
>  hw/virtio/vhost-user-i2c.c |  14 ++
>  hw/virtio/vhost-vsock-common.c |  10 ++
>  hw/virtio/virtio-balloon.c |  14 ++
>  hw/virtio/virtio-crypto.c  |  10 ++
>  hw/virtio/virtio-iommu.c   |  14 ++
>  hw/virtio/virtio-mem.c |  11 ++
>  hw/virtio/virtio.c | 302 
> -
>  include/hw/virtio/vhost.h  |   3 +
>  include/hw/virtio/virtio.h |  19 +++
>  qapi/virtio.json   | 156 ++---
>  17 files changed, 667 insertions(+), 28 deletions(-)
> 
> diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
> index 27c71ad316..f104603040 100644
> --- a/hw/block/virtio-blk.c
> +++ b/hw/block/virtio-blk.c
> @@ -13,6 +13,7 @@
> 
>  #include "qemu/osdep.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-visit-virtio.h"
>  #include "qemu/iov.h"
>  #include "qemu/module.h"
>  #include "qemu/error-report.h"
> @@ -33,10 +34,38 @@
>  #include "migration/qemu-file-types.h"
>  #include "hw/virtio/virtio-access.h"
>  #include "qemu/coroutine.h"
> +#include "standard-headers/linux/vhost_types.h"
> 
>  /* Config size before the discard support (hide associated config 
> fields) */
>  #define VIRTIO_BLK_CFG_SIZE offsetof(struct virtio_blk_config, \
>   max_discard_sectors)
> +
> +qmp_virtio_feature_map_t blk_map[] = {
> +#define FEATURE_ENTRY(name) \
> +{ VIRTIO_BLK_F_##name, #name }
> +FEATURE_ENTRY(SIZE_MAX),
> +FEATURE_ENTRY(SEG_MAX),
> +FEATURE_ENTRY(GEOMETRY),
> +FEATURE_ENTRY(RO),
> +FEATURE_ENTRY(BLK_SIZE),
> +FEATURE_ENTRY(TOPOLOGY),
> +FEATURE_ENTRY(MQ),
> +FEATURE_ENTRY(DISCARD),
> +FEATURE_ENTRY(WRITE_ZEROES),
> +#ifndef VIRTIO_BLK_NO_LEGACY
> +FEATURE_ENTRY(BARRIER),
> +FEATURE_ENTRY(SCSI),
> +FEATURE_ENTRY(FLUSH),
> +FEATURE_ENTRY(CONFIG_WCE),
> +#endif /* !VIRTIO_BLK_NO_LEGACY */
> +#undef FEATURE_ENTRY
> +#define FEATURE_ENTRY(name) \
> +{ VHOST_F_##name, #name }
> +FEATURE_ENTRY(LOG_ALL),
> +#undef FEATURE_ENTRY
> +{ -1, "" }
> +};
> +
>  /*
>   * Starting from the discard feature, we can use this array to 
> properly
>   * set the config size depending on the features enabled.
> diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
> index 7d4601cb5d..fbb31a2b16 100644
> --- a/hw/char/virtio-serial-bus.c
> +++ b/hw/char/virtio-serial-bus.c
> @@ -20,6 +20,7 @@
> 
>  #include "qemu/osdep.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-visit-virtio.h"
>  #include "qemu/iov.h"
>  #include "qemu/main-loop.h"
>  #include "qemu/module.h"
> @@ -32,6 +33,16 @@
>  #include "hw/virtio/virtio-serial.h"
>  #include "hw/virtio/virtio-access.h"
> 
> +qmp_virtio_feature_map_t serial_map[] = {
> +#define FEATURE_ENTRY(name) \
> +{ 

[PATCH 8/9] target/riscv: debug: Return 0 if previous value written to tselect >= number of triggers

2022-06-09 Thread frank . chang
From: Frank Chang 

If the value written to tselect is greater than or equal to the number
of supported triggers, then the following reads of tselect would return
value 0.

Signed-off-by: Frank Chang 
---
 target/riscv/cpu.h   | 1 +
 target/riscv/debug.c | 6 ++
 2 files changed, 7 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index bac5f00722..c7ee3f80e6 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -289,6 +289,7 @@ struct CPUArchState {
 
 /* trigger module */
 target_ulong trigger_cur;
+target_ulong trigger_prev;
 target_ulong tdata1[RV_MAX_TRIGGERS];
 target_ulong tdata2[RV_MAX_TRIGGERS];
 target_ulong tdata3[RV_MAX_TRIGGERS];
diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index ce9ff15d75..83b72fa1b9 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -158,6 +158,10 @@ bool tdata_available(CPURISCVState *env, int tdata_index)
 
 target_ulong tselect_csr_read(CPURISCVState *env)
 {
+if (env->trigger_prev >= RV_MAX_TRIGGERS) {
+return 0;
+}
+
 return env->trigger_cur;
 }
 
@@ -166,6 +170,8 @@ void tselect_csr_write(CPURISCVState *env, target_ulong val)
 if (val < RV_MAX_TRIGGERS) {
 env->trigger_cur = val;
 }
+
+env->trigger_prev = val;
 }
 
 static target_ulong tdata1_validate(CPURISCVState *env, target_ulong val,
-- 
2.36.1




[PATCH 9/9] target/riscv: debug: Add initial support of type 6 trigger

2022-06-09 Thread frank . chang
From: Frank Chang 

Type 6 trigger is similar to a type 2 trigger, but provides additional
functionality and should be used instead of type 2 in newer
implementations.

Signed-off-by: Frank Chang 
---
 target/riscv/debug.c | 174 ++-
 target/riscv/debug.h |  18 +
 2 files changed, 188 insertions(+), 4 deletions(-)

diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index 83b72fa1b9..43ee10c1c3 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -39,7 +39,7 @@
  * - tdata3
  * - tinfo
  *
- * The following triggers are implemented:
+ * The following triggers are initialized by default:
  *
  * Index | Type |  tdata mapping | Description
  * --+--++
@@ -102,10 +102,12 @@ static trigger_action_t get_trigger_action(CPURISCVState 
*env,
 case TRIGGER_TYPE_AD_MATCH:
 action = (tdata1 & TYPE2_ACTION) >> 12;
 break;
+case TRIGGER_TYPE_AD_MATCH6:
+action = (tdata1 & TYPE6_ACTION) >> 12;
+break;
 case TRIGGER_TYPE_INST_CNT:
 case TRIGGER_TYPE_INT:
 case TRIGGER_TYPE_EXCP:
-case TRIGGER_TYPE_AD_MATCH6:
 case TRIGGER_TYPE_EXT_SRC:
 qemu_log_mask(LOG_UNIMP, "trigger type: %d is not supported\n",
   trigger_type);
@@ -380,6 +382,123 @@ static void type2_reg_write(CPURISCVState *env, 
target_ulong index,
 return;
 }
 
+/* type 6 trigger */
+
+static inline bool type6_breakpoint_enabled(target_ulong ctrl)
+{
+bool mode = !!(ctrl & (TYPE6_VU | TYPE6_VS | TYPE6_U | TYPE6_S | TYPE6_M));
+bool rwx = !!(ctrl & (TYPE6_LOAD | TYPE6_STORE | TYPE6_EXEC));
+
+return mode && rwx;
+}
+
+static target_ulong type6_mcontrol6_validate(CPURISCVState *env,
+ target_ulong ctrl)
+{
+target_ulong val;
+uint32_t size;
+
+/* validate the generic part first */
+val = tdata1_validate(env, ctrl, TRIGGER_TYPE_AD_MATCH6);
+
+/* validate unimplemented (always zero) bits */
+warn_always_zero_bit(ctrl, TYPE6_MATCH, "match");
+warn_always_zero_bit(ctrl, TYPE6_CHAIN, "chain");
+warn_always_zero_bit(ctrl, TYPE6_ACTION, "action");
+warn_always_zero_bit(ctrl, TYPE6_TIMING, "timing");
+warn_always_zero_bit(ctrl, TYPE6_SELECT, "select");
+warn_always_zero_bit(ctrl, TYPE6_HIT, "hit");
+
+/* validate size encoding */
+size = extract32(ctrl, 16, 4);
+if (access_size[size] == -1) {
+qemu_log_mask(LOG_UNIMP, "access size %d is not supported, using 
SIZE_ANY\n",
+  size);
+} else {
+val |= (ctrl & TYPE6_SIZE);
+}
+
+/* keep the mode and attribute bits */
+val |= (ctrl & (TYPE6_VU | TYPE6_VS | TYPE6_U | TYPE6_S | TYPE6_M |
+TYPE6_LOAD | TYPE6_STORE | TYPE6_EXEC));
+
+return val;
+}
+
+static void type6_breakpoint_insert(CPURISCVState *env, target_ulong index)
+{
+target_ulong ctrl = env->tdata1[index];
+target_ulong addr = env->tdata2[index];
+bool enabled = type6_breakpoint_enabled(ctrl);
+CPUState *cs = env_cpu(env);
+int flags = BP_CPU | BP_STOP_BEFORE_ACCESS;
+uint32_t size;
+
+if (!enabled) {
+return;
+}
+
+if (ctrl & TYPE6_EXEC) {
+cpu_breakpoint_insert(cs, addr, flags, >cpu_breakpoint[index]);
+}
+
+if (ctrl & TYPE6_LOAD) {
+flags |= BP_MEM_READ;
+}
+
+if (ctrl & TYPE6_STORE) {
+flags |= BP_MEM_WRITE;
+}
+
+if (flags & BP_MEM_ACCESS) {
+size = extract32(ctrl, 16, 4);
+if (size != 0) {
+cpu_watchpoint_insert(cs, addr, size, flags,
+  >cpu_watchpoint[index]);
+} else {
+cpu_watchpoint_insert(cs, addr, 8, flags,
+  >cpu_watchpoint[index]);
+}
+}
+}
+
+static void type6_breakpoint_remove(CPURISCVState *env, target_ulong index)
+{
+type2_breakpoint_remove(env, index);
+}
+
+static void type6_reg_write(CPURISCVState *env, target_ulong index,
+int tdata_index, target_ulong val)
+{
+target_ulong new_val;
+
+switch (tdata_index) {
+case TDATA1:
+new_val = type6_mcontrol6_validate(env, val);
+if (new_val != env->tdata1[index]) {
+env->tdata1[index] = new_val;
+type6_breakpoint_remove(env, index);
+type6_breakpoint_insert(env, index);
+}
+break;
+case TDATA2:
+if (val != env->tdata2[index]) {
+env->tdata2[index] = val;
+type6_breakpoint_remove(env, index);
+type6_breakpoint_insert(env, index);
+}
+break;
+case TDATA3:
+qemu_log_mask(LOG_UNIMP,
+  "tdata3 is not supported for type 6 trigger\n");
+break;
+default:
+g_assert_not_reached();
+}
+
+return;
+}
+
 target_ulong tdata_csr_read(CPURISCVState *env, int tdata_index)
 {
 switch 

[PATCH 7/9] target/riscv: debug: Check VU/VS modes for type 2 trigger

2022-06-09 Thread frank . chang
From: Frank Chang 

Type 2 trigger cannot be fired in VU/VS modes.

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

diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index ab23566113..ce9ff15d75 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -457,6 +457,11 @@ bool riscv_cpu_debug_check_breakpoint(CPUState *cs)
 
 switch (trigger_type) {
 case TRIGGER_TYPE_AD_MATCH:
+/* type 2 trigger cannot be fired in VU/VS mode */
+if (riscv_cpu_virt_enabled(env)) {
+return false;
+}
+
 ctrl = env->tdata1[i];
 pc = env->tdata2[i];
 
@@ -492,6 +497,11 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, 
CPUWatchpoint *wp)
 
 switch (trigger_type) {
 case TRIGGER_TYPE_AD_MATCH:
+/* type 2 trigger cannot be fired in VU/VS mode */
+if (riscv_cpu_virt_enabled(env)) {
+return false;
+}
+
 ctrl = env->tdata1[i];
 addr = env->tdata2[i];
 flags = 0;
-- 
2.36.1




[PATCH 6/9] target/riscv: debug: Create common trigger actions function

2022-06-09 Thread frank . chang
From: Frank Chang 

Trigger actions are shared among all triggers. Extract to a common
function.

Signed-off-by: Frank Chang 
---
 target/riscv/debug.c | 55 ++--
 target/riscv/debug.h | 13 +++
 2 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index 1668b8abda..ab23566113 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -91,6 +91,35 @@ static inline target_ulong get_trigger_type(CPURISCVState 
*env,
 return extract_trigger_type(env, env->tdata1[trigger_index]);
 }
 
+static trigger_action_t get_trigger_action(CPURISCVState *env,
+   target_ulong trigger_index)
+{
+target_ulong tdata1 = env->tdata1[trigger_index];
+int trigger_type = get_trigger_type(env, trigger_index);
+trigger_action_t action = DBG_ACTION_NONE;
+
+switch (trigger_type) {
+case TRIGGER_TYPE_AD_MATCH:
+action = (tdata1 & TYPE2_ACTION) >> 12;
+break;
+case TRIGGER_TYPE_INST_CNT:
+case TRIGGER_TYPE_INT:
+case TRIGGER_TYPE_EXCP:
+case TRIGGER_TYPE_AD_MATCH6:
+case TRIGGER_TYPE_EXT_SRC:
+qemu_log_mask(LOG_UNIMP, "trigger type: %d is not supported\n",
+  trigger_type);
+break;
+case TRIGGER_TYPE_NO_EXIST:
+case TRIGGER_TYPE_UNAVAIL:
+break;
+default:
+g_assert_not_reached();
+}
+
+return action;
+}
+
 static inline target_ulong build_tdata1(CPURISCVState *env,
 trigger_type_t type,
 bool dmode, target_ulong data)
@@ -181,6 +210,28 @@ static inline void warn_always_zero_bit(target_ulong val, 
target_ulong mask,
 }
 }
 
+static void do_trigger_action(CPURISCVState *env, target_ulong trigger_index)
+{
+trigger_action_t action = get_trigger_action(env, trigger_index);
+
+switch (action) {
+case DBG_ACTION_BP:
+riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0);
+break;
+case DBG_ACTION_DBG_MODE:
+case DBG_ACTION_TRACE0:
+case DBG_ACTION_TRACE1:
+case DBG_ACTION_TRACE2:
+case DBG_ACTION_TRACE3:
+case DBG_ACTION_EXT_DBG0:
+case DBG_ACTION_EXT_DBG1:
+qemu_log_mask(LOG_UNIMP, "action: %d is not supported\n", action);
+break;
+default:
+g_assert_not_reached();
+}
+}
+
 /* type 2 trigger */
 
 static uint32_t type2_breakpoint_size(CPURISCVState *env, target_ulong ctrl)
@@ -381,11 +432,11 @@ void riscv_cpu_debug_excp_handler(CPUState *cs)
 if (cs->watchpoint_hit) {
 if (cs->watchpoint_hit->flags & BP_CPU) {
 cs->watchpoint_hit = NULL;
-riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0);
+do_trigger_action(env, DBG_ACTION_BP);
 }
 } else {
 if (cpu_breakpoint_test(cs, env->pc, BP_CPU)) {
-riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0);
+do_trigger_action(env, DBG_ACTION_BP);
 }
 }
 }
diff --git a/target/riscv/debug.h b/target/riscv/debug.h
index 9f69c64591..0e4859cf74 100644
--- a/target/riscv/debug.h
+++ b/target/riscv/debug.h
@@ -44,6 +44,19 @@ typedef enum {
 TRIGGER_TYPE_NUM
 } trigger_type_t;
 
+/* actions */
+typedef enum {
+DBG_ACTION_NONE = -1,   /* sentinel value */
+DBG_ACTION_BP = 0,
+DBG_ACTION_DBG_MODE,
+DBG_ACTION_TRACE0,
+DBG_ACTION_TRACE1,
+DBG_ACTION_TRACE2,
+DBG_ACTION_TRACE3,
+DBG_ACTION_EXT_DBG0 = 8,
+DBG_ACTION_EXT_DBG1
+} trigger_action_t;
+
 /* tdata1 field masks */
 
 #define RV32_TYPE(t)((uint32_t)(t) << 28)
-- 
2.36.1




[PATCH 1/9] target/riscv: debug: Determine the trigger type from tdata1.type

2022-06-09 Thread frank . chang
From: Frank Chang 

Current RISC-V debug assumes that only type 2 trigger is supported.
To allow more types of triggers to be supported in the future
(e.g. type 6 trigger, which is similar to type 2 trigger with additional
 functionality), we should determine the trigger type from tdata1.type.

RV_MAX_TRIGGERS is also introduced in replacement of TRIGGER_TYPE2_NUM.

Signed-off-by: Frank Chang 
---
 target/riscv/cpu.h |   2 +-
 target/riscv/csr.c |   2 +-
 target/riscv/debug.c   | 183 -
 target/riscv/debug.h   |  15 ++--
 target/riscv/machine.c |   2 +-
 5 files changed, 137 insertions(+), 67 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 7d6397acdf..535123a989 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -289,7 +289,7 @@ struct CPUArchState {
 
 /* trigger module */
 target_ulong trigger_cur;
-type2_trigger_t type2_trig[TRIGGER_TYPE2_NUM];
+type2_trigger_t type2_trig[RV_MAX_TRIGGERS];
 
 /* machine specific rdtime callback */
 uint64_t (*rdtime_fn)(void *);
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 6dbe9b541f..005ae31a01 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -2776,7 +2776,7 @@ static RISCVException read_tdata(CPURISCVState *env, int 
csrno,
  target_ulong *val)
 {
 /* return 0 in tdata1 to end the trigger enumeration */
-if (env->trigger_cur >= TRIGGER_NUM && csrno == CSR_TDATA1) {
+if (env->trigger_cur >= RV_MAX_TRIGGERS && csrno == CSR_TDATA1) {
 *val = 0;
 return RISCV_EXCP_NONE;
 }
diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index fc6e13222f..abbcd38a17 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -52,8 +52,15 @@
 /* tdata availability of a trigger */
 typedef bool tdata_avail[TDATA_NUM];
 
-static tdata_avail tdata_mapping[TRIGGER_NUM] = {
-[TRIGGER_TYPE2_IDX_0 ... TRIGGER_TYPE2_IDX_1] = { true, true, false },
+static tdata_avail tdata_mapping[TRIGGER_TYPE_NUM] = {
+[TRIGGER_TYPE_NO_EXIST] = { false, false, false },
+[TRIGGER_TYPE_AD_MATCH] = { true, true, true },
+[TRIGGER_TYPE_INST_CNT] = { true, false, true },
+[TRIGGER_TYPE_INT] = { true, true, true },
+[TRIGGER_TYPE_EXCP] = { true, true, true },
+[TRIGGER_TYPE_AD_MATCH6] = { true, true, true },
+[TRIGGER_TYPE_EXT_SRC] = { true, false, false },
+[TRIGGER_TYPE_UNAVAIL] = { true, true, true }
 };
 
 /* only breakpoint size 1/2/4/8 supported */
@@ -67,6 +74,26 @@ static int access_size[SIZE_NUM] = {
 [6 ... 15] = -1,
 };
 
+static inline target_ulong extract_trigger_type(CPURISCVState *env,
+target_ulong tdata1)
+{
+switch (riscv_cpu_mxl(env)) {
+case MXL_RV32:
+return extract32(tdata1, 28, 4);
+case MXL_RV64:
+return extract64(tdata1, 60, 4);
+default:
+g_assert_not_reached();
+}
+}
+
+static inline target_ulong get_trigger_type(CPURISCVState *env,
+target_ulong trigger_index)
+{
+target_ulong tdata1 = env->type2_trig[trigger_index].mcontrol;
+return extract_trigger_type(env, tdata1);
+}
+
 static inline target_ulong trigger_type(CPURISCVState *env,
 trigger_type_t type)
 {
@@ -89,15 +116,17 @@ static inline target_ulong trigger_type(CPURISCVState *env,
 
 bool tdata_available(CPURISCVState *env, int tdata_index)
 {
+int trigger_type = get_trigger_type(env, env->trigger_cur);
+
 if (unlikely(tdata_index >= TDATA_NUM)) {
 return false;
 }
 
-if (unlikely(env->trigger_cur >= TRIGGER_NUM)) {
+if (unlikely(env->trigger_cur >= RV_MAX_TRIGGERS)) {
 return false;
 }
 
-return tdata_mapping[env->trigger_cur][tdata_index];
+return tdata_mapping[trigger_type][tdata_index];
 }
 
 target_ulong tselect_csr_read(CPURISCVState *env)
@@ -137,6 +166,7 @@ static target_ulong tdata1_validate(CPURISCVState *env, 
target_ulong val,
 qemu_log_mask(LOG_GUEST_ERROR,
   "ignoring type write to tdata1 register\n");
 }
+
 if (dmode != 0) {
 qemu_log_mask(LOG_UNIMP, "debug mode is not supported\n");
 }
@@ -261,9 +291,8 @@ static void type2_breakpoint_remove(CPURISCVState *env, 
target_ulong index)
 }
 
 static target_ulong type2_reg_read(CPURISCVState *env,
-   target_ulong trigger_index, int tdata_index)
+   target_ulong index, int tdata_index)
 {
-uint32_t index = trigger_index - TRIGGER_TYPE2_IDX_0;
 target_ulong tdata;
 
 switch (tdata_index) {
@@ -280,10 +309,9 @@ static target_ulong type2_reg_read(CPURISCVState *env,
 return tdata;
 }
 
-static void type2_reg_write(CPURISCVState *env, target_ulong trigger_index,
+static void type2_reg_write(CPURISCVState *env, target_ulong index,
 int tdata_index, 

[PATCH 5/9] target/riscv: debug: Introduce tinfo CSR

2022-06-09 Thread frank . chang
From: Frank Chang 

tinfo.info:
  One bit for each possible type enumerated in tdata1.
  If the bit is set, then that type is supported by the currently
  selected trigger.

Signed-off-by: Frank Chang 
---
 target/riscv/cpu_bits.h |  1 +
 target/riscv/csr.c  |  8 
 target/riscv/debug.c| 10 +++---
 target/riscv/debug.h|  2 ++
 4 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 4d04b20d06..666b4d69ca 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -331,6 +331,7 @@
 #define CSR_TDATA1  0x7a1
 #define CSR_TDATA2  0x7a2
 #define CSR_TDATA3  0x7a3
+#define CSR_TINFO   0x7a4
 
 /* Debug Mode Registers */
 #define CSR_DCSR0x7b0
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 005ae31a01..823b6bd520 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -2800,6 +2800,13 @@ static RISCVException write_tdata(CPURISCVState *env, 
int csrno,
 return RISCV_EXCP_NONE;
 }
 
+static RISCVException read_tinfo(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+*val = tinfo_csr_read(env);
+return RISCV_EXCP_NONE;
+}
+
 /*
  * Functions to access Pointer Masking feature registers
  * We have to check if current priv lvl could modify
@@ -3588,6 +3595,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_TDATA1]=  { "tdata1",  debug, read_tdata,   write_tdata   },
 [CSR_TDATA2]=  { "tdata2",  debug, read_tdata,   write_tdata   },
 [CSR_TDATA3]=  { "tdata3",  debug, read_tdata,   write_tdata   },
+[CSR_TINFO] =  { "tinfo",   debug, read_tinfo,   write_ignore  },
 
 /* User Pointer Masking */
 [CSR_UMTE]={ "umte",pointer_masking, read_umte,write_umte  
  },
diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index 296192ffc4..1668b8abda 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -37,9 +37,7 @@
  * - tdata1
  * - tdata2
  * - tdata3
- *
- * We don't support writable 'type' field in the tdata1 register, so there is
- * no need to implement the "tinfo" CSR.
+ * - tinfo
  *
  * The following triggers are implemented:
  *
@@ -369,6 +367,12 @@ void tdata_csr_write(CPURISCVState *env, int tdata_index, 
target_ulong val)
 }
 }
 
+target_ulong tinfo_csr_read(CPURISCVState *env)
+{
+/* assume all triggers support the same types of triggers */
+return BIT(TRIGGER_TYPE_AD_MATCH);
+}
+
 void riscv_cpu_debug_excp_handler(CPUState *cs)
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
diff --git a/target/riscv/debug.h b/target/riscv/debug.h
index 76146f373a..9f69c64591 100644
--- a/target/riscv/debug.h
+++ b/target/riscv/debug.h
@@ -95,6 +95,8 @@ void tselect_csr_write(CPURISCVState *env, target_ulong val);
 target_ulong tdata_csr_read(CPURISCVState *env, int tdata_index);
 void tdata_csr_write(CPURISCVState *env, int tdata_index, target_ulong val);
 
+target_ulong tinfo_csr_read(CPURISCVState *env);
+
 void riscv_cpu_debug_excp_handler(CPUState *cs);
 bool riscv_cpu_debug_check_breakpoint(CPUState *cs);
 bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp);
-- 
2.36.1




[PATCH 2/9] target/riscv: debug: Introduce build_tdata1() to build tdata1 register content

2022-06-09 Thread frank . chang
From: Frank Chang 

Introduce build_tdata1() to build tdata1 register content, which can be
shared among all types of triggers.

Signed-off-by: Frank Chang 
---
 target/riscv/debug.c | 15 ++-
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index abbcd38a17..089aae0696 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -94,18 +94,23 @@ static inline target_ulong get_trigger_type(CPURISCVState 
*env,
 return extract_trigger_type(env, tdata1);
 }
 
-static inline target_ulong trigger_type(CPURISCVState *env,
-trigger_type_t type)
+static inline target_ulong build_tdata1(CPURISCVState *env,
+trigger_type_t type,
+bool dmode, target_ulong data)
 {
 target_ulong tdata1;
 
 switch (riscv_cpu_mxl(env)) {
 case MXL_RV32:
-tdata1 = RV32_TYPE(type);
+tdata1 = RV32_TYPE(type) |
+ (dmode ? RV32_DMODE : 0) |
+ (data & RV32_DATA_MASK);
 break;
 case MXL_RV64:
 case MXL_RV128:
-tdata1 = RV64_TYPE(type);
+tdata1 = RV64_TYPE(type) |
+ (dmode ? RV64_DMODE : 0) |
+ (data & RV64_DATA_MASK);
 break;
 default:
 g_assert_not_reached();
@@ -490,7 +495,7 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, 
CPUWatchpoint *wp)
 
 void riscv_trigger_init(CPURISCVState *env)
 {
-target_ulong tdata1 = trigger_type(env, TRIGGER_TYPE_AD_MATCH);
+target_ulong tdata1 = build_tdata1(env, TRIGGER_TYPE_AD_MATCH, 0, 0);
 int i;
 
 /* init to type 2 triggers */
-- 
2.36.1




[PATCH 4/9] target/riscv: debug: Restrict the range of tselect value can be written

2022-06-09 Thread frank . chang
From: Frank Chang 

The value of tselect CSR can be written should be limited within the
range of supported triggers number.

Signed-off-by: Frank Chang 
---
 target/riscv/debug.c | 9 +++--
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index 6913682f75..296192ffc4 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -126,10 +126,6 @@ bool tdata_available(CPURISCVState *env, int tdata_index)
 return false;
 }
 
-if (unlikely(env->trigger_cur >= RV_MAX_TRIGGERS)) {
-return false;
-}
-
 return tdata_mapping[trigger_type][tdata_index];
 }
 
@@ -140,8 +136,9 @@ target_ulong tselect_csr_read(CPURISCVState *env)
 
 void tselect_csr_write(CPURISCVState *env, target_ulong val)
 {
-/* all target_ulong bits of tselect are implemented */
-env->trigger_cur = val;
+if (val < RV_MAX_TRIGGERS) {
+env->trigger_cur = val;
+}
 }
 
 static target_ulong tdata1_validate(CPURISCVState *env, target_ulong val,
-- 
2.36.1




[PATCH 0/9] Improve RISC-V Debug support

2022-06-09 Thread frank . chang
From: Frank Chang 

This patchset refactors RISC-V Debug support to allow more types of
triggers to be extended.

The initial support of type 6 trigger, which is similar to type 2
trigger with additional functionality, is also introduced in this
patchset.

Frank Chang (9):
  target/riscv: debug: Determine the trigger type from tdata1.type
  target/riscv: debug: Introduce build_tdata1() to build tdata1 register
content
  target/riscv: debug: Introduce tdata1, tdata2, and tdata3 CSRs
  target/riscv: debug: Restrict the range of tselect value can be
written
  target/riscv: debug: Introduce tinfo CSR
  target/riscv: debug: Create common trigger actions function
  target/riscv: debug: Check VU/VS modes for type 2 trigger
  target/riscv: debug: Return 0 if previous value written to tselect >=
number of triggers
  target/riscv: debug: Add initial support of type 6 trigger

 target/riscv/cpu.h  |   7 +-
 target/riscv/cpu_bits.h |   1 +
 target/riscv/csr.c  |  10 +-
 target/riscv/debug.c| 483 
 target/riscv/debug.h|  55 +++--
 target/riscv/machine.c  |  20 +-
 6 files changed, 445 insertions(+), 131 deletions(-)

--
2.36.1




[PATCH 3/9] target/riscv: debug: Introduce tdata1, tdata2, and tdata3 CSRs

2022-06-09 Thread frank . chang
From: Frank Chang 

Replace type2_trigger_t with the real tdata1, tdata2, and tdata3 CSRs,
which allows us to support more types of triggers in the future.

Signed-off-by: Frank Chang 
---
 target/riscv/cpu.h |   6 ++-
 target/riscv/debug.c   | 101 -
 target/riscv/debug.h   |   7 ---
 target/riscv/machine.c |  20 ++--
 4 files changed, 48 insertions(+), 86 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 535123a989..bac5f00722 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -289,7 +289,11 @@ struct CPUArchState {
 
 /* trigger module */
 target_ulong trigger_cur;
-type2_trigger_t type2_trig[RV_MAX_TRIGGERS];
+target_ulong tdata1[RV_MAX_TRIGGERS];
+target_ulong tdata2[RV_MAX_TRIGGERS];
+target_ulong tdata3[RV_MAX_TRIGGERS];
+struct CPUBreakpoint *cpu_breakpoint[RV_MAX_TRIGGERS];
+struct CPUWatchpoint *cpu_watchpoint[RV_MAX_TRIGGERS];
 
 /* machine specific rdtime callback */
 uint64_t (*rdtime_fn)(void *);
diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index 089aae0696..6913682f75 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -90,8 +90,7 @@ static inline target_ulong extract_trigger_type(CPURISCVState 
*env,
 static inline target_ulong get_trigger_type(CPURISCVState *env,
 target_ulong trigger_index)
 {
-target_ulong tdata1 = env->type2_trig[trigger_index].mcontrol;
-return extract_trigger_type(env, tdata1);
+return extract_trigger_type(env, env->tdata1[trigger_index]);
 }
 
 static inline target_ulong build_tdata1(CPURISCVState *env,
@@ -187,6 +186,8 @@ static inline void warn_always_zero_bit(target_ulong val, 
target_ulong mask,
 }
 }
 
+/* type 2 trigger */
+
 static uint32_t type2_breakpoint_size(CPURISCVState *env, target_ulong ctrl)
 {
 uint32_t size, sizelo, sizehi = 0;
@@ -246,8 +247,8 @@ static target_ulong type2_mcontrol_validate(CPURISCVState 
*env,
 
 static void type2_breakpoint_insert(CPURISCVState *env, target_ulong index)
 {
-target_ulong ctrl = env->type2_trig[index].mcontrol;
-target_ulong addr = env->type2_trig[index].maddress;
+target_ulong ctrl = env->tdata1[index];
+target_ulong addr = env->tdata2[index];
 bool enabled = type2_breakpoint_enabled(ctrl);
 CPUState *cs = env_cpu(env);
 int flags = BP_CPU | BP_STOP_BEFORE_ACCESS;
@@ -258,7 +259,7 @@ static void type2_breakpoint_insert(CPURISCVState *env, 
target_ulong index)
 }
 
 if (ctrl & TYPE2_EXEC) {
-cpu_breakpoint_insert(cs, addr, flags, >type2_trig[index].bp);
+cpu_breakpoint_insert(cs, addr, flags, >cpu_breakpoint[index]);
 }
 
 if (ctrl & TYPE2_LOAD) {
@@ -272,10 +273,10 @@ static void type2_breakpoint_insert(CPURISCVState *env, 
target_ulong index)
 size = type2_breakpoint_size(env, ctrl);
 if (size != 0) {
 cpu_watchpoint_insert(cs, addr, size, flags,
-  >type2_trig[index].wp);
+  >cpu_watchpoint[index]);
 } else {
 cpu_watchpoint_insert(cs, addr, 8, flags,
-  >type2_trig[index].wp);
+  >cpu_watchpoint[index]);
 }
 }
 }
@@ -284,34 +285,15 @@ static void type2_breakpoint_remove(CPURISCVState *env, 
target_ulong index)
 {
 CPUState *cs = env_cpu(env);
 
-if (env->type2_trig[index].bp) {
-cpu_breakpoint_remove_by_ref(cs, env->type2_trig[index].bp);
-env->type2_trig[index].bp = NULL;
+if (env->cpu_breakpoint[index]) {
+cpu_breakpoint_remove_by_ref(cs, env->cpu_breakpoint[index]);
+env->cpu_breakpoint[index] = NULL;
 }
 
-if (env->type2_trig[index].wp) {
-cpu_watchpoint_remove_by_ref(cs, env->type2_trig[index].wp);
-env->type2_trig[index].wp = NULL;
-}
-}
-
-static target_ulong type2_reg_read(CPURISCVState *env,
-   target_ulong index, int tdata_index)
-{
-target_ulong tdata;
-
-switch (tdata_index) {
-case TDATA1:
-tdata = env->type2_trig[index].mcontrol;
-break;
-case TDATA2:
-tdata = env->type2_trig[index].maddress;
-break;
-default:
-g_assert_not_reached();
+if (env->cpu_watchpoint[index]) {
+cpu_watchpoint_remove_by_ref(cs, env->cpu_watchpoint[index]);
+env->cpu_watchpoint[index] = NULL;
 }
-
-return tdata;
 }
 
 static void type2_reg_write(CPURISCVState *env, target_ulong index,
@@ -322,19 +304,23 @@ static void type2_reg_write(CPURISCVState *env, 
target_ulong index,
 switch (tdata_index) {
 case TDATA1:
 new_val = type2_mcontrol_validate(env, val);
-if (new_val != env->type2_trig[index].mcontrol) {
-env->type2_trig[index].mcontrol = new_val;
+if (new_val != env->tdata1[index]) {
+env->tdata1[index] = new_val;
 

[PULL 25/25] target/riscv: trans_rvv: Avoid assert for RV32 and e64

2022-06-09 Thread Alistair Francis
From: Alistair Francis 

When running a 32-bit guest, with a e64 vmv.v.x and vl_eq_vlmax set to
true the `tcg_debug_assert(vece <= MO_32)` will be triggered inside
tcg_gen_gvec_dup_i32().

This patch checks that condition and instead uses tcg_gen_gvec_dup_i64()
is required.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1028
Suggested-by: Robert Bu 
Signed-off-by: Alistair Francis 
Reviewed-by: Richard Henderson 
Message-Id: <20220608234701.369536-1-alistair.fran...@opensource.wdc.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/insn_trans/trans_rvv.c.inc | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvv.c.inc 
b/target/riscv/insn_trans/trans_rvv.c.inc
index 4f84d4878a..6c091824b6 100644
--- a/target/riscv/insn_trans/trans_rvv.c.inc
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
@@ -2128,8 +2128,16 @@ static bool trans_vmv_v_x(DisasContext *s, arg_vmv_v_x 
*a)
 s1 = get_gpr(s, a->rs1, EXT_SIGN);
 
 if (s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
-tcg_gen_gvec_dup_tl(s->sew, vreg_ofs(s, a->rd),
-MAXSZ(s), MAXSZ(s), s1);
+if (get_xl(s) == MXL_RV32 && s->sew == MO_64) {
+TCGv_i64 s1_i64 = tcg_temp_new_i64();
+tcg_gen_ext_tl_i64(s1_i64, s1);
+tcg_gen_gvec_dup_i64(s->sew, vreg_ofs(s, a->rd),
+ MAXSZ(s), MAXSZ(s), s1_i64);
+tcg_temp_free_i64(s1_i64);
+} else {
+tcg_gen_gvec_dup_tl(s->sew, vreg_ofs(s, a->rd),
+MAXSZ(s), MAXSZ(s), s1);
+}
 } else {
 TCGv_i32 desc;
 TCGv_i64 s1_i64 = tcg_temp_new_i64();
-- 
2.36.1




[PULL 21/25] target/riscv: rvv: Add tail agnostic for vector mask instructions

2022-06-09 Thread Alistair Francis
From: eopXD 

The tail elements in the destination mask register are updated under
a tail-agnostic policy.

Signed-off-by: eop Chen 
Reviewed-by: Frank Chang 
Reviewed-by: Weiwei Li 
Acked-by: Alistair Francis 
Message-Id: <165449614532.19704.7000832880482980398...@git.sr.ht>
Signed-off-by: Alistair Francis 
---
 target/riscv/vector_helper.c| 30 +
 target/riscv/insn_trans/trans_rvv.c.inc |  6 +
 2 files changed, 36 insertions(+)

diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index 174a548ac2..75b59cf917 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -4717,6 +4717,8 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1,  
\
   uint32_t desc)  \
 { \
 uint32_t vl = env->vl;\
+uint32_t total_elems = env_archcpu(env)->cfg.vlen;\
+uint32_t vta_all_1s = vext_vta_all_1s(desc);  \
 uint32_t i;   \
 int a, b; \
   \
@@ -4726,6 +4728,15 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, 
 \
 vext_set_elem_mask(vd, i, OP(b, a));  \
 } \
 env->vstart = 0;  \
+/* mask destination register are always tail- \
+ * agnostic   \
+ */   \
+/* set tail elements to 1s */ \
+if (vta_all_1s) { \
+for (; i < total_elems; i++) {\
+vext_set_elem_mask(vd, i, 1); \
+} \
+} \
 }
 
 #define DO_NAND(N, M)  (!(N & M))
@@ -4793,6 +4804,8 @@ static void vmsetm(void *vd, void *v0, void *vs2, 
CPURISCVState *env,
 {
 uint32_t vm = vext_vm(desc);
 uint32_t vl = env->vl;
+uint32_t total_elems = env_archcpu(env)->cfg.vlen;
+uint32_t vta_all_1s = vext_vta_all_1s(desc);
 int i;
 bool first_mask_bit = false;
 
@@ -4821,6 +4834,13 @@ static void vmsetm(void *vd, void *v0, void *vs2, 
CPURISCVState *env,
 }
 }
 env->vstart = 0;
+/* mask destination register are always tail-agnostic */
+/* set tail elements to 1s */
+if (vta_all_1s) {
+for (; i < total_elems; i++) {
+vext_set_elem_mask(vd, i, 1);
+}
+}
 }
 
 void HELPER(vmsbf_m)(void *vd, void *v0, void *vs2, CPURISCVState *env,
@@ -4848,6 +4868,9 @@ void HELPER(NAME)(void *vd, void *v0, void *vs2, 
CPURISCVState *env,  \
 { \
 uint32_t vm = vext_vm(desc);  \
 uint32_t vl = env->vl;\
+uint32_t esz = sizeof(ETYPE); \
+uint32_t total_elems = vext_get_total_elems(env, desc, esz);  \
+uint32_t vta = vext_vta(desc);\
 uint32_t sum = 0; \
 int i;\
   \
@@ -4861,6 +4884,8 @@ void HELPER(NAME)(void *vd, void *v0, void *vs2, 
CPURISCVState *env,  \
 } \
 } \
 env->vstart = 0;  \
+/* set tail elements to 1s */ \
+vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);  \
 }
 
 GEN_VEXT_VIOTA_M(viota_m_b, uint8_t,  H1)
@@ -4874,6 +4899,9 @@ void HELPER(NAME)(void *vd, void *v0, CPURISCVState *env, 
uint32_t desc)  \
 { \
 uint32_t vm = vext_vm(desc);  \
 uint32_t vl = env->vl;\
+uint32_t esz = sizeof(ETYPE); \
+uint32_t total_elems = vext_get_total_elems(env, desc, esz);  \
+uint32_t vta = vext_vta(desc);\
 int i;\
   \
 for (i = env->vstart; i < vl; i++) {  \
@@ -4883,6 +4911,8 @@ void HELPER(NAME)(void *vd, void 

[PULL 16/25] target/riscv: rvv: Add tail agnostic for vector integer comparison instructions

2022-06-09 Thread Alistair Francis
From: eopXD 

Compares write mask registers, and so always operate under a tail-
agnostic policy.

Signed-off-by: eop Chen 
Reviewed-by: Frank Chang 
Reviewed-by: Weiwei Li 
Acked-by: Alistair Francis 
Message-Id: <165449614532.19704.700083288048298039...@git.sr.ht>
Signed-off-by: Alistair Francis 
---
 target/riscv/vector_helper.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index 056c2a1c7e..a64506bf02 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -1371,6 +1371,8 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void 
*vs2,   \
 { \
 uint32_t vm = vext_vm(desc);  \
 uint32_t vl = env->vl;\
+uint32_t total_elems = env_archcpu(env)->cfg.vlen;\
+uint32_t vta_all_1s = vext_vta_all_1s(desc);  \
 uint32_t i;   \
   \
 for (i = env->vstart; i < vl; i++) {  \
@@ -1382,6 +1384,13 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void 
*vs2,   \
 vext_set_elem_mask(vd, i, DO_OP(s2, s1)); \
 } \
 env->vstart = 0;  \
+/* mask destination register are always tail-agnostic */  \
+/* set tail elements to 1s */ \
+if (vta_all_1s) { \
+for (; i < total_elems; i++) {\
+vext_set_elem_mask(vd, i, 1); \
+} \
+} \
 }
 
 GEN_VEXT_CMP_VV(vmseq_vv_b, uint8_t,  H1, DO_MSEQ)
@@ -1420,6 +1429,8 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, 
void *vs2,   \
 {   \
 uint32_t vm = vext_vm(desc);\
 uint32_t vl = env->vl;  \
+uint32_t total_elems = env_archcpu(env)->cfg.vlen;  \
+uint32_t vta_all_1s = vext_vta_all_1s(desc);\
 uint32_t i; \
 \
 for (i = env->vstart; i < vl; i++) {\
@@ -1431,6 +1442,13 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, 
void *vs2,   \
 DO_OP(s2, (ETYPE)(target_long)s1)); \
 }   \
 env->vstart = 0;\
+/* mask destination register are always tail-agnostic */\
+/* set tail elements to 1s */   \
+if (vta_all_1s) {   \
+for (; i < total_elems; i++) {  \
+vext_set_elem_mask(vd, i, 1);   \
+}   \
+}   \
 }
 
 GEN_VEXT_CMP_VX(vmseq_vx_b, uint8_t,  H1, DO_MSEQ)
-- 
2.36.1




[PULL 14/25] target/riscv: rvv: Add tail agnostic for vx, vvm, vxm instructions

2022-06-09 Thread Alistair Francis
From: eopXD 

`vmadc` and `vmsbc` produces a mask value, they always operate with
a tail agnostic policy.

Signed-off-by: eop Chen 
Reviewed-by: Frank Chang 
Reviewed-by: Weiwei Li 
Acked-by: Alistair Francis 
Message-Id: <165449614532.19704.700083288048298039...@git.sr.ht>
Signed-off-by: Alistair Francis 
---
 target/riscv/internals.h|   5 +-
 target/riscv/vector_helper.c| 314 +---
 target/riscv/insn_trans/trans_rvv.c.inc |  13 +-
 3 files changed, 190 insertions(+), 142 deletions(-)

diff --git a/target/riscv/internals.h b/target/riscv/internals.h
index 512c6c30cf..193ce57a6d 100644
--- a/target/riscv/internals.h
+++ b/target/riscv/internals.h
@@ -25,8 +25,9 @@
 FIELD(VDATA, VM, 0, 1)
 FIELD(VDATA, LMUL, 1, 3)
 FIELD(VDATA, VTA, 4, 1)
-FIELD(VDATA, NF, 5, 4)
-FIELD(VDATA, WD, 5, 1)
+FIELD(VDATA, VTA_ALL_1S, 5, 1)
+FIELD(VDATA, NF, 6, 4)
+FIELD(VDATA, WD, 6, 1)
 
 /* float point classify helpers */
 target_ulong fclass_h(uint64_t frs1);
diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index ee28e1b92d..7cdb5d12af 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -127,6 +127,11 @@ static inline uint32_t vext_vta(uint32_t desc)
 return FIELD_EX32(simd_data(desc), VDATA, VTA);
 }
 
+static inline uint32_t vext_vta_all_1s(uint32_t desc)
+{
+return FIELD_EX32(simd_data(desc), VDATA, VTA_ALL_1S);
+}
+
 /*
  * Get the maximum number of elements can be operated.
  *
@@ -867,10 +872,12 @@ RVVCALL(OPIVX2, vrsub_vx_d, OP_SSS_D, H8, H8, DO_RSUB)
 
 static void do_vext_vx(void *vd, void *v0, target_long s1, void *vs2,
CPURISCVState *env, uint32_t desc,
-   opivx2_fn fn)
+   opivx2_fn fn, uint32_t esz)
 {
 uint32_t vm = vext_vm(desc);
 uint32_t vl = env->vl;
+uint32_t total_elems = vext_get_total_elems(env, desc, esz);
+uint32_t vta = vext_vta(desc);
 uint32_t i;
 
 for (i = env->vstart; i < vl; i++) {
@@ -880,30 +887,32 @@ static void do_vext_vx(void *vd, void *v0, target_long 
s1, void *vs2,
 fn(vd, s1, vs2, i);
 }
 env->vstart = 0;
+/* set tail elements to 1s */
+vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);
 }
 
 /* generate the helpers for OPIVX */
-#define GEN_VEXT_VX(NAME) \
+#define GEN_VEXT_VX(NAME, ESZ)\
 void HELPER(NAME)(void *vd, void *v0, target_ulong s1,\
   void *vs2, CPURISCVState *env,  \
   uint32_t desc)  \
 { \
 do_vext_vx(vd, v0, s1, vs2, env, desc,\
-   do_##NAME);\
-}
-
-GEN_VEXT_VX(vadd_vx_b)
-GEN_VEXT_VX(vadd_vx_h)
-GEN_VEXT_VX(vadd_vx_w)
-GEN_VEXT_VX(vadd_vx_d)
-GEN_VEXT_VX(vsub_vx_b)
-GEN_VEXT_VX(vsub_vx_h)
-GEN_VEXT_VX(vsub_vx_w)
-GEN_VEXT_VX(vsub_vx_d)
-GEN_VEXT_VX(vrsub_vx_b)
-GEN_VEXT_VX(vrsub_vx_h)
-GEN_VEXT_VX(vrsub_vx_w)
-GEN_VEXT_VX(vrsub_vx_d)
+   do_##NAME, ESZ);   \
+}
+
+GEN_VEXT_VX(vadd_vx_b, 1)
+GEN_VEXT_VX(vadd_vx_h, 2)
+GEN_VEXT_VX(vadd_vx_w, 4)
+GEN_VEXT_VX(vadd_vx_d, 8)
+GEN_VEXT_VX(vsub_vx_b, 1)
+GEN_VEXT_VX(vsub_vx_h, 2)
+GEN_VEXT_VX(vsub_vx_w, 4)
+GEN_VEXT_VX(vsub_vx_d, 8)
+GEN_VEXT_VX(vrsub_vx_b, 1)
+GEN_VEXT_VX(vrsub_vx_h, 2)
+GEN_VEXT_VX(vrsub_vx_w, 4)
+GEN_VEXT_VX(vrsub_vx_d, 8)
 
 void HELPER(vec_rsubs8)(void *d, void *a, uint64_t b, uint32_t desc)
 {
@@ -1031,30 +1040,30 @@ RVVCALL(OPIVX2, vwadd_wx_w, WOP_WSSS_W, H8, H4, DO_ADD)
 RVVCALL(OPIVX2, vwsub_wx_b, WOP_WSSS_B, H2, H1, DO_SUB)
 RVVCALL(OPIVX2, vwsub_wx_h, WOP_WSSS_H, H4, H2, DO_SUB)
 RVVCALL(OPIVX2, vwsub_wx_w, WOP_WSSS_W, H8, H4, DO_SUB)
-GEN_VEXT_VX(vwaddu_vx_b)
-GEN_VEXT_VX(vwaddu_vx_h)
-GEN_VEXT_VX(vwaddu_vx_w)
-GEN_VEXT_VX(vwsubu_vx_b)
-GEN_VEXT_VX(vwsubu_vx_h)
-GEN_VEXT_VX(vwsubu_vx_w)
-GEN_VEXT_VX(vwadd_vx_b)
-GEN_VEXT_VX(vwadd_vx_h)
-GEN_VEXT_VX(vwadd_vx_w)
-GEN_VEXT_VX(vwsub_vx_b)
-GEN_VEXT_VX(vwsub_vx_h)
-GEN_VEXT_VX(vwsub_vx_w)
-GEN_VEXT_VX(vwaddu_wx_b)
-GEN_VEXT_VX(vwaddu_wx_h)
-GEN_VEXT_VX(vwaddu_wx_w)
-GEN_VEXT_VX(vwsubu_wx_b)
-GEN_VEXT_VX(vwsubu_wx_h)
-GEN_VEXT_VX(vwsubu_wx_w)
-GEN_VEXT_VX(vwadd_wx_b)
-GEN_VEXT_VX(vwadd_wx_h)
-GEN_VEXT_VX(vwadd_wx_w)
-GEN_VEXT_VX(vwsub_wx_b)
-GEN_VEXT_VX(vwsub_wx_h)
-GEN_VEXT_VX(vwsub_wx_w)
+GEN_VEXT_VX(vwaddu_vx_b, 2)
+GEN_VEXT_VX(vwaddu_vx_h, 4)
+GEN_VEXT_VX(vwaddu_vx_w, 8)
+GEN_VEXT_VX(vwsubu_vx_b, 2)
+GEN_VEXT_VX(vwsubu_vx_h, 4)
+GEN_VEXT_VX(vwsubu_vx_w, 8)
+GEN_VEXT_VX(vwadd_vx_b, 2)
+GEN_VEXT_VX(vwadd_vx_h, 4)
+GEN_VEXT_VX(vwadd_vx_w, 8)
+GEN_VEXT_VX(vwsub_vx_b, 2)
+GEN_VEXT_VX(vwsub_vx_h, 4)
+GEN_VEXT_VX(vwsub_vx_w, 8)
+GEN_VEXT_VX(vwaddu_wx_b, 2)
+GEN_VEXT_VX(vwaddu_wx_h, 4)
+GEN_VEXT_VX(vwaddu_wx_w, 8)
+GEN_VEXT_VX(vwsubu_wx_b, 2)
+GEN_VEXT_VX(vwsubu_wx_h, 4)
+GEN_VEXT_VX(vwsubu_wx_w, 8)
+GEN_VEXT_VX(vwadd_wx_b, 2)
+GEN_VEXT_VX(vwadd_wx_h, 4)

[PULL 23/25] target/riscv: rvv: Add option 'rvv_ta_all_1s' to enable optional tail agnostic behavior

2022-06-09 Thread Alistair Francis
From: eopXD 

According to v-spec, tail agnostic behavior can be either kept as
undisturbed or set elements' bits to all 1s. To distinguish the
difference of tail policies, QEMU should be able to simulate the tail
agnostic behavior as "set tail elements' bits to all 1s".

There are multiple possibility for agnostic elements according to
v-spec. The main intent of this patch-set tries to add option that
can distinguish between tail policies. Setting agnostic elements to
all 1s allows QEMU to express this.

This commit adds option 'rvv_ta_all_1s' is added to enable the
behavior, it is default as disabled.

Signed-off-by: eop Chen 
Reviewed-by: Frank Chang 
Reviewed-by: Weiwei Li 
Reviewed-by: Alistair Francis 
Message-Id: <165449614532.19704.7000832880482980398...@git.sr.ht>
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 0497af45cc..e5aa1e9c1b 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -918,6 +918,8 @@ static Property riscv_cpu_properties[] = {
 DEFINE_PROP_UINT64("resetvec", RISCVCPU, cfg.resetvec, DEFAULT_RSTVEC),
 
 DEFINE_PROP_BOOL("short-isa-string", RISCVCPU, cfg.short_isa_string, 
false),
+
+DEFINE_PROP_BOOL("rvv_ta_all_1s", RISCVCPU, cfg.rvv_ta_all_1s, false),
 DEFINE_PROP_END_OF_LIST(),
 };
 
-- 
2.36.1




[PULL 13/25] target/riscv: rvv: Add tail agnostic for vector load / store instructions

2022-06-09 Thread Alistair Francis
From: eopXD 

Destination register of unit-stride mask load and store instructions are
always written with a tail-agnostic policy.

A vector segment load / store instruction may contain fractional lmul
with nf * lmul > 1. The rest of the elements in the last register should
be treated as tail elements.

Signed-off-by: eop Chen 
Reviewed-by: Frank Chang 
Reviewed-by: Weiwei Li 
Acked-by: Alistair Francis 
Message-Id: <165449614532.19704.700083288048298039...@git.sr.ht>
Signed-off-by: Alistair Francis 
---
 target/riscv/translate.c|  2 +
 target/riscv/vector_helper.c| 60 +
 target/riscv/insn_trans/trans_rvv.c.inc |  6 +++
 3 files changed, 68 insertions(+)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 59f0ee9a50..b151c20674 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -95,6 +95,7 @@ typedef struct DisasContext {
 int8_t lmul;
 uint8_t sew;
 uint8_t vta;
+bool cfg_vta_all_1s;
 target_ulong vstart;
 bool vl_eq_vlmax;
 uint8_t ntemp;
@@ -1101,6 +1102,7 @@ static void riscv_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);
 ctx->lmul = sextract32(FIELD_EX32(tb_flags, TB_FLAGS, LMUL), 0, 3);
 ctx->vta = FIELD_EX32(tb_flags, TB_FLAGS, VTA) && cpu->cfg.rvv_ta_all_1s;
+ctx->cfg_vta_all_1s = cpu->cfg.rvv_ta_all_1s;
 ctx->vstart = env->vstart;
 ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
 ctx->misa_mxl_max = env->misa_mxl_max;
diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index e2a2979bad..ee28e1b92d 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -270,6 +270,9 @@ vext_ldst_stride(void *vd, void *v0, target_ulong base,
 uint32_t i, k;
 uint32_t nf = vext_nf(desc);
 uint32_t max_elems = vext_max_elems(desc, log2_esz);
+uint32_t esz = 1 << log2_esz;
+uint32_t total_elems = vext_get_total_elems(env, desc, esz);
+uint32_t vta = vext_vta(desc);
 
 for (i = env->vstart; i < env->vl; i++, env->vstart++) {
 if (!vm && !vext_elem_mask(v0, i)) {
@@ -284,6 +287,18 @@ vext_ldst_stride(void *vd, void *v0, target_ulong base,
 }
 }
 env->vstart = 0;
+/* set tail elements to 1s */
+for (k = 0; k < nf; ++k) {
+vext_set_elems_1s(vd, vta, (k * max_elems + env->vl) * esz,
+  (k * max_elems + max_elems) * esz);
+}
+if (nf * max_elems % total_elems != 0) {
+uint32_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
+uint32_t registers_used =
+((nf * max_elems) * esz + (vlenb - 1)) / vlenb;
+vext_set_elems_1s(vd, vta, (nf * max_elems) * esz,
+  registers_used * vlenb);
+}
 }
 
 #define GEN_VEXT_LD_STRIDE(NAME, ETYPE, LOAD_FN)\
@@ -329,6 +344,9 @@ vext_ldst_us(void *vd, target_ulong base, CPURISCVState 
*env, uint32_t desc,
 uint32_t i, k;
 uint32_t nf = vext_nf(desc);
 uint32_t max_elems = vext_max_elems(desc, log2_esz);
+uint32_t esz = 1 << log2_esz;
+uint32_t total_elems = vext_get_total_elems(env, desc, esz);
+uint32_t vta = vext_vta(desc);
 
 /* load bytes from guest memory */
 for (i = env->vstart; i < evl; i++, env->vstart++) {
@@ -340,6 +358,18 @@ vext_ldst_us(void *vd, target_ulong base, CPURISCVState 
*env, uint32_t desc,
 }
 }
 env->vstart = 0;
+/* set tail elements to 1s */
+for (k = 0; k < nf; ++k) {
+vext_set_elems_1s(vd, vta, (k * max_elems + evl) * esz,
+  (k * max_elems + max_elems) * esz);
+}
+if (nf * max_elems % total_elems != 0) {
+uint32_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
+uint32_t registers_used =
+((nf * max_elems) * esz + (vlenb - 1)) / vlenb;
+vext_set_elems_1s(vd, vta, (nf * max_elems) * esz,
+  registers_used * vlenb);
+}
 }
 
 /*
@@ -439,6 +469,9 @@ vext_ldst_index(void *vd, void *v0, target_ulong base,
 uint32_t nf = vext_nf(desc);
 uint32_t vm = vext_vm(desc);
 uint32_t max_elems = vext_max_elems(desc, log2_esz);
+uint32_t esz = 1 << log2_esz;
+uint32_t total_elems = vext_get_total_elems(env, desc, esz);
+uint32_t vta = vext_vta(desc);
 
 /* load bytes from guest memory */
 for (i = env->vstart; i < env->vl; i++, env->vstart++) {
@@ -454,6 +487,18 @@ vext_ldst_index(void *vd, void *v0, target_ulong base,
 }
 }
 env->vstart = 0;
+/* set tail elements to 1s */
+for (k = 0; k < nf; ++k) {
+vext_set_elems_1s(vd, vta, (k * max_elems + env->vl) * esz,
+  (k * max_elems + max_elems) * esz);
+}
+if (nf * max_elems % total_elems != 0) {
+uint32_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
+uint32_t registers_used =
+((nf * max_elems) * esz + (vlenb - 1)) / vlenb;

[PULL 19/25] target/riscv: rvv: Add tail agnostic for vector floating-point instructions

2022-06-09 Thread Alistair Francis
From: eopXD 

Compares write mask registers, and so always operate under a tail-
agnostic policy.

Signed-off-by: eop Chen 
Reviewed-by: Frank Chang 
Reviewed-by: Weiwei Li 
Acked-by: Alistair Francis 
Message-Id: <165449614532.19704.7000832880482980398...@git.sr.ht>
Signed-off-by: Alistair Francis 
---
 target/riscv/vector_helper.c| 440 +---
 target/riscv/insn_trans/trans_rvv.c.inc |  17 +
 2 files changed, 261 insertions(+), 196 deletions(-)

diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index 1fa93cf1f0..17390d8d06 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -2994,13 +2994,16 @@ static void do_##NAME(void *vd, void *vs1, void *vs2, 
int i,   \
 *((TD *)vd + HD(i)) = OP(s2, s1, >fp_status); \
 }
 
-#define GEN_VEXT_VV_ENV(NAME) \
+#define GEN_VEXT_VV_ENV(NAME, ESZ)\
 void HELPER(NAME)(void *vd, void *v0, void *vs1,  \
   void *vs2, CPURISCVState *env,  \
   uint32_t desc)  \
 { \
 uint32_t vm = vext_vm(desc);  \
 uint32_t vl = env->vl;\
+uint32_t total_elems =\
+vext_get_total_elems(env, desc, ESZ); \
+uint32_t vta = vext_vta(desc);\
 uint32_t i;   \
   \
 for (i = env->vstart; i < vl; i++) {  \
@@ -3010,14 +3013,17 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1,
  \
 do_##NAME(vd, vs1, vs2, i, env);  \
 } \
 env->vstart = 0;  \
+/* set tail elements to 1s */ \
+vext_set_elems_1s(vd, vta, vl * ESZ,  \
+  total_elems * ESZ); \
 }
 
 RVVCALL(OPFVV2, vfadd_vv_h, OP_UUU_H, H2, H2, H2, float16_add)
 RVVCALL(OPFVV2, vfadd_vv_w, OP_UUU_W, H4, H4, H4, float32_add)
 RVVCALL(OPFVV2, vfadd_vv_d, OP_UUU_D, H8, H8, H8, float64_add)
-GEN_VEXT_VV_ENV(vfadd_vv_h)
-GEN_VEXT_VV_ENV(vfadd_vv_w)
-GEN_VEXT_VV_ENV(vfadd_vv_d)
+GEN_VEXT_VV_ENV(vfadd_vv_h, 2)
+GEN_VEXT_VV_ENV(vfadd_vv_w, 4)
+GEN_VEXT_VV_ENV(vfadd_vv_d, 8)
 
 #define OPFVF2(NAME, TD, T1, T2, TX1, TX2, HD, HS2, OP)\
 static void do_##NAME(void *vd, uint64_t s1, void *vs2, int i, \
@@ -3027,13 +3033,16 @@ static void do_##NAME(void *vd, uint64_t s1, void *vs2, 
int i, \
 *((TD *)vd + HD(i)) = OP(s2, (TX1)(T1)s1, >fp_status);\
 }
 
-#define GEN_VEXT_VF(NAME) \
+#define GEN_VEXT_VF(NAME, ESZ)\
 void HELPER(NAME)(void *vd, void *v0, uint64_t s1,\
   void *vs2, CPURISCVState *env,  \
   uint32_t desc)  \
 { \
 uint32_t vm = vext_vm(desc);  \
 uint32_t vl = env->vl;\
+uint32_t total_elems =\
+vext_get_total_elems(env, desc, ESZ);  \
+uint32_t vta = vext_vta(desc);\
 uint32_t i;   \
   \
 for (i = env->vstart; i < vl; i++) {  \
@@ -3043,27 +3052,30 @@ void HELPER(NAME)(void *vd, void *v0, uint64_t s1,  
  \
 do_##NAME(vd, s1, vs2, i, env);   \
 } \
 env->vstart = 0;  \
+/* set tail elements to 1s */ \
+vext_set_elems_1s(vd, vta, vl * ESZ,  \
+  total_elems * ESZ); \
 }
 
 RVVCALL(OPFVF2, vfadd_vf_h, OP_UUU_H, H2, H2, float16_add)
 RVVCALL(OPFVF2, vfadd_vf_w, OP_UUU_W, H4, H4, float32_add)
 RVVCALL(OPFVF2, vfadd_vf_d, OP_UUU_D, H8, H8, float64_add)
-GEN_VEXT_VF(vfadd_vf_h)
-GEN_VEXT_VF(vfadd_vf_w)
-GEN_VEXT_VF(vfadd_vf_d)
+GEN_VEXT_VF(vfadd_vf_h, 2)
+GEN_VEXT_VF(vfadd_vf_w, 4)
+GEN_VEXT_VF(vfadd_vf_d, 8)
 
 RVVCALL(OPFVV2, vfsub_vv_h, OP_UUU_H, H2, H2, H2, float16_sub)
 RVVCALL(OPFVV2, vfsub_vv_w, OP_UUU_W, H4, H4, H4, float32_sub)
 RVVCALL(OPFVV2, vfsub_vv_d, OP_UUU_D, H8, H8, H8, float64_sub)
-GEN_VEXT_VV_ENV(vfsub_vv_h)
-GEN_VEXT_VV_ENV(vfsub_vv_w)
-GEN_VEXT_VV_ENV(vfsub_vv_d)
+GEN_VEXT_VV_ENV(vfsub_vv_h, 2)
+GEN_VEXT_VV_ENV(vfsub_vv_w, 4)
+GEN_VEXT_VV_ENV(vfsub_vv_d, 8)
 RVVCALL(OPFVF2, vfsub_vf_h, OP_UUU_H, H2, H2, float16_sub)
 RVVCALL(OPFVF2, vfsub_vf_w, OP_UUU_W, H4, H4, float32_sub)
 RVVCALL(OPFVF2, vfsub_vf_d, OP_UUU_D, H8, H8, float64_sub)

[PULL 12/25] target/riscv: rvv: Add tail agnostic for vv instructions

2022-06-09 Thread Alistair Francis
From: eopXD 

According to v-spec, tail agnostic behavior can be either kept as
undisturbed or set elements' bits to all 1s. To distinguish the
difference of tail policies, QEMU should be able to simulate the tail
agnostic behavior as "set tail elements' bits to all 1s".

There are multiple possibility for agnostic elements according to
v-spec. The main intent of this patch-set tries to add option that
can distinguish between tail policies. Setting agnostic elements to
all 1s allows QEMU to express this.

This is the first commit regarding the optional tail agnostic
behavior. Follow-up commits will add this optional behavior
for all rvv instructions.

Signed-off-by: eop Chen 
Reviewed-by: Frank Chang 
Reviewed-by: Weiwei Li 
Acked-by: Alistair Francis 
Message-Id: <165449614532.19704.700083288048298039...@git.sr.ht>
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h  |   2 +
 target/riscv/internals.h|   5 +-
 target/riscv/cpu_helper.c   |   2 +
 target/riscv/translate.c|   2 +
 target/riscv/vector_helper.c| 296 +---
 target/riscv/insn_trans/trans_rvv.c.inc |   3 +-
 6 files changed, 178 insertions(+), 132 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 194a58d760..7d6397acdf 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -412,6 +412,7 @@ struct RISCVCPUConfig {
 bool ext_zve32f;
 bool ext_zve64f;
 bool ext_zmmul;
+bool rvv_ta_all_1s;
 
 uint32_t mvendorid;
 uint64_t marchid;
@@ -567,6 +568,7 @@ FIELD(TB_FLAGS, XL, 20, 2)
 /* If PointerMasking should be applied */
 FIELD(TB_FLAGS, PM_MASK_ENABLED, 22, 1)
 FIELD(TB_FLAGS, PM_BASE_ENABLED, 23, 1)
+FIELD(TB_FLAGS, VTA, 24, 1)
 
 #ifdef TARGET_RISCV32
 #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
diff --git a/target/riscv/internals.h b/target/riscv/internals.h
index dbb322bfa7..512c6c30cf 100644
--- a/target/riscv/internals.h
+++ b/target/riscv/internals.h
@@ -24,8 +24,9 @@
 /* share data between vector helpers and decode code */
 FIELD(VDATA, VM, 0, 1)
 FIELD(VDATA, LMUL, 1, 3)
-FIELD(VDATA, NF, 4, 4)
-FIELD(VDATA, WD, 4, 1)
+FIELD(VDATA, VTA, 4, 1)
+FIELD(VDATA, NF, 5, 4)
+FIELD(VDATA, WD, 5, 1)
 
 /* float point classify helpers */
 target_ulong fclass_h(uint64_t frs1);
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 16c6045459..4a6700c890 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -65,6 +65,8 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong 
*pc,
 flags = FIELD_DP32(flags, TB_FLAGS, LMUL,
 FIELD_EX64(env->vtype, VTYPE, VLMUL));
 flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);
+flags = FIELD_DP32(flags, TB_FLAGS, VTA,
+FIELD_EX64(env->vtype, VTYPE, VTA));
 } else {
 flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
 }
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 55a4713af2..59f0ee9a50 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -94,6 +94,7 @@ typedef struct DisasContext {
  */
 int8_t lmul;
 uint8_t sew;
+uint8_t vta;
 target_ulong vstart;
 bool vl_eq_vlmax;
 uint8_t ntemp;
@@ -1099,6 +1100,7 @@ static void riscv_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
 ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);
 ctx->lmul = sextract32(FIELD_EX32(tb_flags, TB_FLAGS, LMUL), 0, 3);
+ctx->vta = FIELD_EX32(tb_flags, TB_FLAGS, VTA) && cpu->cfg.rvv_ta_all_1s;
 ctx->vstart = env->vstart;
 ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
 ctx->misa_mxl_max = env->misa_mxl_max;
diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index 3b79b9cbc2..e2a2979bad 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -122,6 +122,11 @@ static inline int32_t vext_lmul(uint32_t desc)
 return sextract32(FIELD_EX32(simd_data(desc), VDATA, LMUL), 0, 3);
 }
 
+static inline uint32_t vext_vta(uint32_t desc)
+{
+return FIELD_EX32(simd_data(desc), VDATA, VTA);
+}
+
 /*
  * Get the maximum number of elements can be operated.
  *
@@ -140,6 +145,21 @@ static inline uint32_t vext_max_elems(uint32_t desc, 
uint32_t log2_esz)
 return scale < 0 ? vlenb >> -scale : vlenb << scale;
 }
 
+/*
+ * Get number of total elements, including prestart, body and tail elements.
+ * Note that when LMUL < 1, the tail includes the elements past VLMAX that
+ * are held in the same vector register.
+ */
+static inline uint32_t vext_get_total_elems(CPURISCVState *env, uint32_t desc,
+uint32_t esz)
+{
+uint32_t vlenb = simd_maxsz(desc);
+uint32_t sew = 1 << FIELD_EX64(env->vtype, VTYPE, VSEW);
+int8_t emul = ctzl(esz) - ctzl(sew) + vext_lmul(desc) < 0 ? 0 :
+  ctzl(esz) - 

[PULL 22/25] target/riscv: rvv: Add tail agnostic for vector permutation instructions

2022-06-09 Thread Alistair Francis
From: eopXD 

Signed-off-by: eop Chen 
Reviewed-by: Frank Chang 
Reviewed-by: Weiwei Li 
Acked-by: Alistair Francis 
Message-Id: <165449614532.19704.7000832880482980398...@git.sr.ht>
Signed-off-by: Alistair Francis 
---
 target/riscv/vector_helper.c| 40 +
 target/riscv/insn_trans/trans_rvv.c.inc |  7 +++--
 2 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index 75b59cf917..a96fc49c71 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -4931,6 +4931,9 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, 
void *vs2, \
 { \
 uint32_t vm = vext_vm(desc);  \
 uint32_t vl = env->vl;\
+uint32_t esz = sizeof(ETYPE); \
+uint32_t total_elems = vext_get_total_elems(env, desc, esz);  \
+uint32_t vta = vext_vta(desc);\
 target_ulong offset = s1, i_min, i;   \
   \
 i_min = MAX(env->vstart, offset); \
@@ -4940,6 +4943,8 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, 
void *vs2, \
 } \
 *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(i - offset));  \
 } \
+/* set tail elements to 1s */ \
+vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);  \
 }
 
 /* vslideup.vx vd, vs2, rs1, vm # vd[i+rs1] = vs2[i] */
@@ -4955,6 +4960,9 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, 
void *vs2, \
 uint32_t vlmax = vext_max_elems(desc, ctzl(sizeof(ETYPE)));   \
 uint32_t vm = vext_vm(desc);  \
 uint32_t vl = env->vl;\
+uint32_t esz = sizeof(ETYPE); \
+uint32_t total_elems = vext_get_total_elems(env, desc, esz);  \
+uint32_t vta = vext_vta(desc);\
 target_ulong i_max, i;\
   \
 i_max = MAX(MIN(s1 < vlmax ? vlmax - s1 : 0, vl), env->vstart);   \
@@ -4971,6 +4979,8 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, 
void *vs2, \
 } \
   \
 env->vstart = 0;  \
+/* set tail elements to 1s */ \
+vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);  \
 }
 
 /* vslidedown.vx vd, vs2, rs1, vm # vd[i] = vs2[i+rs1] */
@@ -4986,6 +4996,9 @@ static void vslide1up_##BITWIDTH(void *vd, void *v0, 
target_ulong s1,   \
 typedef uint##BITWIDTH##_t ETYPE;   \
 uint32_t vm = vext_vm(desc);\
 uint32_t vl = env->vl;  \
+uint32_t esz = sizeof(ETYPE);   \
+uint32_t total_elems = vext_get_total_elems(env, desc, esz);\
+uint32_t vta = vext_vta(desc);  \
 uint32_t i; \
 \
 for (i = env->vstart; i < vl; i++) {\
@@ -4999,6 +5012,8 @@ static void vslide1up_##BITWIDTH(void *vd, void *v0, 
target_ulong s1,   \
 }   \
 }   \
 env->vstart = 0;\
+/* set tail elements to 1s */   \
+vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);\
 }
 
 GEN_VEXT_VSLIE1UP(8,  H1)
@@ -5026,6 +5041,9 @@ static void vslide1down_##BITWIDTH(void *vd, void *v0, 
target_ulong s1,   \
 typedef uint##BITWIDTH##_t ETYPE; \
 uint32_t vm = vext_vm(desc);  \
 uint32_t vl = env->vl;\
+uint32_t esz = sizeof(ETYPE);  

[PULL 24/25] target/riscv: Don't expose the CPU properties on names CPUs

2022-06-09 Thread Alistair Francis
From: Alistair Francis 

There are currently two types of RISC-V CPUs:
 - Generic CPUs (base or any) that allow complete custimisation
 - "Named" CPUs that match existing hardware

Users can use the base CPUs to custimise the extensions that they want, for
example -cpu rv64,v=true.

We originally exposed these as part of the named CPUs as well, but that was
by accident.

Exposing the CPU properties to named CPUs means that we accidently
enable extensions that don't exist on the CPUs by default. For example
the SiFive E CPU currently support the zba extension, which is a bug.

This patch instead only exposes the CPU extensions to the generic CPUs.

Signed-off-by: Alistair Francis 
Reviewed-by: Bin Meng 
Message-Id: <20220608061437.314434-1-alistair.fran...@opensource.wdc.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.c | 57 +-
 1 file changed, 46 insertions(+), 11 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index e5aa1e9c1b..05e6521351 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -118,6 +118,8 @@ static const char * const riscv_intr_names[] = {
 "reserved"
 };
 
+static void register_cpu_props(DeviceState *dev);
+
 const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
 {
 if (async) {
@@ -161,6 +163,7 @@ static void riscv_any_cpu_init(Object *obj)
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
 #endif
 set_priv_version(env, PRIV_VERSION_1_12_0);
+register_cpu_props(DEVICE(obj));
 }
 
 #if defined(TARGET_RISCV64)
@@ -169,6 +172,7 @@ static void rv64_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV64, 0);
+register_cpu_props(DEVICE(obj));
 }
 
 static void rv64_sifive_u_cpu_init(Object *obj)
@@ -181,9 +185,11 @@ static void rv64_sifive_u_cpu_init(Object *obj)
 static void rv64_sifive_e_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
 set_priv_version(env, PRIV_VERSION_1_10_0);
-qdev_prop_set_bit(DEVICE(obj), "mmu", false);
+cpu->cfg.mmu = false;
 }
 
 static void rv128_base_cpu_init(Object *obj)
@@ -197,6 +203,7 @@ static void rv128_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV128, 0);
+register_cpu_props(DEVICE(obj));
 }
 #else
 static void rv32_base_cpu_init(Object *obj)
@@ -204,6 +211,7 @@ static void rv32_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV32, 0);
+register_cpu_props(DEVICE(obj));
 }
 
 static void rv32_sifive_u_cpu_init(Object *obj)
@@ -216,27 +224,33 @@ static void rv32_sifive_u_cpu_init(Object *obj)
 static void rv32_sifive_e_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 set_misa(env, MXL_RV32, RVI | RVM | RVA | RVC | RVU);
 set_priv_version(env, PRIV_VERSION_1_10_0);
-qdev_prop_set_bit(DEVICE(obj), "mmu", false);
+cpu->cfg.mmu = false;
 }
 
 static void rv32_ibex_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 set_misa(env, MXL_RV32, RVI | RVM | RVC | RVU);
 set_priv_version(env, PRIV_VERSION_1_10_0);
-qdev_prop_set_bit(DEVICE(obj), "mmu", false);
-qdev_prop_set_bit(DEVICE(obj), "x-epmp", true);
+cpu->cfg.mmu = false;
+cpu->cfg.epmp = true;
 }
 
 static void rv32_imafcu_nommu_cpu_init(Object *obj)
 {
 CPURISCVState *env = _CPU(obj)->env;
+RISCVCPU *cpu = RISCV_CPU(obj);
+
 set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVC | RVU);
 set_priv_version(env, PRIV_VERSION_1_10_0);
 set_resetvec(env, DEFAULT_RSTVEC);
-qdev_prop_set_bit(DEVICE(obj), "mmu", false);
+cpu->cfg.mmu = false;
 }
 #endif
 
@@ -249,6 +263,7 @@ static void riscv_host_cpu_init(Object *obj)
 #elif defined(TARGET_RISCV64)
 set_misa(env, MXL_RV64, 0);
 #endif
+register_cpu_props(DEVICE(obj));
 }
 #endif
 
@@ -836,6 +851,12 @@ static void riscv_cpu_init(Object *obj)
 {
 RISCVCPU *cpu = RISCV_CPU(obj);
 
+cpu->cfg.ext_counters = true;
+cpu->cfg.ext_ifencei = true;
+cpu->cfg.ext_icsr = true;
+cpu->cfg.mmu = true;
+cpu->cfg.pmp = true;
+
 cpu_set_cpustate_pointers(cpu);
 
 #ifndef CONFIG_USER_ONLY
@@ -844,7 +865,7 @@ static void riscv_cpu_init(Object *obj)
 #endif /* CONFIG_USER_ONLY */
 }
 
-static Property riscv_cpu_properties[] = {
+static Property riscv_cpu_extensions[] = {
 /* Defaults for standard extensions */
 DEFINE_PROP_BOOL("i", RISCVCPU, cfg.ext_i, true),
 DEFINE_PROP_BOOL("e", RISCVCPU, cfg.ext_e, false),
@@ -867,17 +888,12 @@ static Property riscv_cpu_properties[] = {
 DEFINE_PROP_BOOL("Zve64f", RISCVCPU, 

[PULL 20/25] target/riscv: rvv: Add tail agnostic for vector reduction instructions

2022-06-09 Thread Alistair Francis
From: eopXD 

Signed-off-by: eop Chen 
Reviewed-by: Frank Chang 
Reviewed-by: Weiwei Li 
Acked-by: Alistair Francis 
Message-Id: <165449614532.19704.7000832880482980398...@git.sr.ht>
Signed-off-by: Alistair Francis 
---
 target/riscv/vector_helper.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index 17390d8d06..174a548ac2 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -4535,6 +4535,9 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1,  
\
 { \
 uint32_t vm = vext_vm(desc);  \
 uint32_t vl = env->vl;\
+uint32_t esz = sizeof(TD);\
+uint32_t vlenb = simd_maxsz(desc);\
+uint32_t vta = vext_vta(desc);\
 uint32_t i;   \
 TD s1 =  *((TD *)vs1 + HD(0));\
   \
@@ -4547,6 +4550,8 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1,  
\
 } \
 *((TD *)vd + HD(0)) = s1; \
 env->vstart = 0;  \
+/* set tail elements to 1s */ \
+vext_set_elems_1s(vd, vta, esz, vlenb);   \
 }
 
 /* vd[0] = sum(vs1[0], vs2[*]) */
@@ -4616,6 +4621,9 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1,  
 \
 {  \
 uint32_t vm = vext_vm(desc);   \
 uint32_t vl = env->vl; \
+uint32_t esz = sizeof(TD); \
+uint32_t vlenb = simd_maxsz(desc); \
+uint32_t vta = vext_vta(desc); \
 uint32_t i;\
 TD s1 =  *((TD *)vs1 + HD(0)); \
\
@@ -4628,6 +4636,8 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1,  
 \
 }  \
 *((TD *)vd + HD(0)) = s1;  \
 env->vstart = 0;   \
+/* set tail elements to 1s */  \
+vext_set_elems_1s(vd, vta, esz, vlenb);\
 }
 
 /* Unordered sum */
@@ -4652,6 +4662,9 @@ void HELPER(vfwredsum_vs_h)(void *vd, void *v0, void *vs1,
 {
 uint32_t vm = vext_vm(desc);
 uint32_t vl = env->vl;
+uint32_t esz = sizeof(uint32_t);
+uint32_t vlenb = simd_maxsz(desc);
+uint32_t vta = vext_vta(desc);
 uint32_t i;
 uint32_t s1 =  *((uint32_t *)vs1 + H4(0));
 
@@ -4665,6 +4678,8 @@ void HELPER(vfwredsum_vs_h)(void *vd, void *v0, void *vs1,
 }
 *((uint32_t *)vd + H4(0)) = s1;
 env->vstart = 0;
+/* set tail elements to 1s */
+vext_set_elems_1s(vd, vta, esz, vlenb);
 }
 
 void HELPER(vfwredsum_vs_w)(void *vd, void *v0, void *vs1,
@@ -4672,6 +4687,9 @@ void HELPER(vfwredsum_vs_w)(void *vd, void *v0, void *vs1,
 {
 uint32_t vm = vext_vm(desc);
 uint32_t vl = env->vl;
+uint32_t esz = sizeof(uint64_t);
+uint32_t vlenb = simd_maxsz(desc);
+uint32_t vta = vext_vta(desc);
 uint32_t i;
 uint64_t s1 =  *((uint64_t *)vs1);
 
@@ -4685,6 +4703,8 @@ void HELPER(vfwredsum_vs_w)(void *vd, void *v0, void *vs1,
 }
 *((uint64_t *)vd) = s1;
 env->vstart = 0;
+/* set tail elements to 1s */
+vext_set_elems_1s(vd, vta, esz, vlenb);
 }
 
 /*
-- 
2.36.1




[PULL 11/25] target/riscv: rvv: Early exit when vstart >= vl

2022-06-09 Thread Alistair Francis
From: eopXD 

According to v-spec (section 5.4):
When vstart ≥ vl, there are no body elements, and no elements are
updated in any destination vector register group, including that
no tail elements are updated with agnostic values.

vmsbf.m, vmsif.m, vmsof.m, viota.m, vcompress instructions themselves
require vstart to be zero. So they don't need the early exit.

Signed-off-by: eop Chen 
Reviewed-by: Frank Chang 
Reviewed-by: Weiwei Li 
Acked-by: Alistair Francis 
Message-Id: <165449614532.19704.700083288048298039...@git.sr.ht>
Signed-off-by: Alistair Francis 
---
 target/riscv/insn_trans/trans_rvv.c.inc | 27 +
 1 file changed, 27 insertions(+)

diff --git a/target/riscv/insn_trans/trans_rvv.c.inc 
b/target/riscv/insn_trans/trans_rvv.c.inc
index 391c61fe93..6750f5d04a 100644
--- a/target/riscv/insn_trans/trans_rvv.c.inc
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
@@ -652,6 +652,7 @@ static bool ldst_us_trans(uint32_t vd, uint32_t rs1, 
uint32_t data,
 
 TCGLabel *over = gen_new_label();
 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
+tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
 
 dest = tcg_temp_new_ptr();
 mask = tcg_temp_new_ptr();
@@ -818,6 +819,7 @@ static bool ldst_stride_trans(uint32_t vd, uint32_t rs1, 
uint32_t rs2,
 
 TCGLabel *over = gen_new_label();
 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
+tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
 
 dest = tcg_temp_new_ptr();
 mask = tcg_temp_new_ptr();
@@ -925,6 +927,7 @@ static bool ldst_index_trans(uint32_t vd, uint32_t rs1, 
uint32_t vs2,
 
 TCGLabel *over = gen_new_label();
 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
+tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
 
 dest = tcg_temp_new_ptr();
 mask = tcg_temp_new_ptr();
@@ -1067,6 +1070,7 @@ static bool ldff_trans(uint32_t vd, uint32_t rs1, 
uint32_t data,
 
 TCGLabel *over = gen_new_label();
 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
+tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
 
 dest = tcg_temp_new_ptr();
 mask = tcg_temp_new_ptr();
@@ -1225,6 +1229,7 @@ do_opivv_gvec(DisasContext *s, arg_rmrr *a, GVecGen3Fn 
*gvec_fn,
 }
 
 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
+tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
 
 if (a->vm && s->vl_eq_vlmax) {
 gvec_fn(s->sew, vreg_ofs(s, a->rd),
@@ -1272,6 +1277,7 @@ static bool opivx_trans(uint32_t vd, uint32_t rs1, 
uint32_t vs2, uint32_t vm,
 
 TCGLabel *over = gen_new_label();
 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
+tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
 
 dest = tcg_temp_new_ptr();
 mask = tcg_temp_new_ptr();
@@ -1436,6 +1442,7 @@ static bool opivi_trans(uint32_t vd, uint32_t imm, 
uint32_t vs2, uint32_t vm,
 
 TCGLabel *over = gen_new_label();
 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
+tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
 
 dest = tcg_temp_new_ptr();
 mask = tcg_temp_new_ptr();
@@ -1522,6 +1529,7 @@ static bool do_opivv_widen(DisasContext *s, arg_rmrr *a,
 uint32_t data = 0;
 TCGLabel *over = gen_new_label();
 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
+tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
 
 data = FIELD_DP32(data, VDATA, VM, a->vm);
 data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
@@ -1602,6 +1610,7 @@ static bool do_opiwv_widen(DisasContext *s, arg_rmrr *a,
 uint32_t data = 0;
 TCGLabel *over = gen_new_label();
 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
+tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
 
 data = FIELD_DP32(data, VDATA, VM, a->vm);
 data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
@@ -1679,6 +1688,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a)
 \
 }; \
 TCGLabel *over = gen_new_label();  \
 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);  \
+tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
\
 data = FIELD_DP32(data, VDATA, VM, a->vm); \
 data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
@@ -1860,6 +1870,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a)
 \
 }; \
 TCGLabel *over = gen_new_label();  \
 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);  \
+tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
\
 data = FIELD_DP32(data, VDATA, VM, a->vm); \
 

[PULL 18/25] target/riscv: rvv: Add tail agnostic for vector fix-point arithmetic instructions

2022-06-09 Thread Alistair Francis
From: eopXD 

Signed-off-by: eop Chen 
Reviewed-by: Frank Chang 
Reviewed-by: Weiwei Li 
Acked-by: Alistair Francis 
Message-Id: <165449614532.19704.7000832880482980398...@git.sr.ht>
Signed-off-by: Alistair Francis 
---
 target/riscv/vector_helper.c | 220 ++-
 1 file changed, 114 insertions(+), 106 deletions(-)

diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index 128238786e..1fa93cf1f0 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -2103,10 +2103,12 @@ static inline void
 vext_vv_rm_2(void *vd, void *v0, void *vs1, void *vs2,
  CPURISCVState *env,
  uint32_t desc,
- opivv2_rm_fn *fn)
+ opivv2_rm_fn *fn, uint32_t esz)
 {
 uint32_t vm = vext_vm(desc);
 uint32_t vl = env->vl;
+uint32_t total_elems = vext_get_total_elems(env, desc, esz);
+uint32_t vta = vext_vta(desc);
 
 switch (env->vxrm) {
 case 0: /* rnu */
@@ -2126,15 +2128,17 @@ vext_vv_rm_2(void *vd, void *v0, void *vs1, void *vs2,
  env, vl, vm, 3, fn);
 break;
 }
+/* set tail elements to 1s */
+vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);
 }
 
 /* generate helpers for fixed point instructions with OPIVV format */
-#define GEN_VEXT_VV_RM(NAME)\
+#define GEN_VEXT_VV_RM(NAME, ESZ)   \
 void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
   CPURISCVState *env, uint32_t desc)\
 {   \
 vext_vv_rm_2(vd, v0, vs1, vs2, env, desc,   \
- do_##NAME);\
+ do_##NAME, ESZ);   \
 }
 
 static inline uint8_t saddu8(CPURISCVState *env, int vxrm, uint8_t a, uint8_t 
b)
@@ -2184,10 +2188,10 @@ RVVCALL(OPIVV2_RM, vsaddu_vv_b, OP_UUU_B, H1, H1, H1, 
saddu8)
 RVVCALL(OPIVV2_RM, vsaddu_vv_h, OP_UUU_H, H2, H2, H2, saddu16)
 RVVCALL(OPIVV2_RM, vsaddu_vv_w, OP_UUU_W, H4, H4, H4, saddu32)
 RVVCALL(OPIVV2_RM, vsaddu_vv_d, OP_UUU_D, H8, H8, H8, saddu64)
-GEN_VEXT_VV_RM(vsaddu_vv_b)
-GEN_VEXT_VV_RM(vsaddu_vv_h)
-GEN_VEXT_VV_RM(vsaddu_vv_w)
-GEN_VEXT_VV_RM(vsaddu_vv_d)
+GEN_VEXT_VV_RM(vsaddu_vv_b, 1)
+GEN_VEXT_VV_RM(vsaddu_vv_h, 2)
+GEN_VEXT_VV_RM(vsaddu_vv_w, 4)
+GEN_VEXT_VV_RM(vsaddu_vv_d, 8)
 
 typedef void opivx2_rm_fn(void *vd, target_long s1, void *vs2, int i,
   CPURISCVState *env, int vxrm);
@@ -2220,10 +2224,12 @@ static inline void
 vext_vx_rm_2(void *vd, void *v0, target_long s1, void *vs2,
  CPURISCVState *env,
  uint32_t desc,
- opivx2_rm_fn *fn)
+ opivx2_rm_fn *fn, uint32_t esz)
 {
 uint32_t vm = vext_vm(desc);
 uint32_t vl = env->vl;
+uint32_t total_elems = vext_get_total_elems(env, desc, esz);
+uint32_t vta = vext_vta(desc);
 
 switch (env->vxrm) {
 case 0: /* rnu */
@@ -2243,25 +2249,27 @@ vext_vx_rm_2(void *vd, void *v0, target_long s1, void 
*vs2,
  env, vl, vm, 3, fn);
 break;
 }
+/* set tail elements to 1s */
+vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);
 }
 
 /* generate helpers for fixed point instructions with OPIVX format */
-#define GEN_VEXT_VX_RM(NAME)  \
+#define GEN_VEXT_VX_RM(NAME, ESZ) \
 void HELPER(NAME)(void *vd, void *v0, target_ulong s1,\
 void *vs2, CPURISCVState *env, uint32_t desc) \
 { \
 vext_vx_rm_2(vd, v0, s1, vs2, env, desc,  \
- do_##NAME);  \
+ do_##NAME, ESZ); \
 }
 
 RVVCALL(OPIVX2_RM, vsaddu_vx_b, OP_UUU_B, H1, H1, saddu8)
 RVVCALL(OPIVX2_RM, vsaddu_vx_h, OP_UUU_H, H2, H2, saddu16)
 RVVCALL(OPIVX2_RM, vsaddu_vx_w, OP_UUU_W, H4, H4, saddu32)
 RVVCALL(OPIVX2_RM, vsaddu_vx_d, OP_UUU_D, H8, H8, saddu64)
-GEN_VEXT_VX_RM(vsaddu_vx_b)
-GEN_VEXT_VX_RM(vsaddu_vx_h)
-GEN_VEXT_VX_RM(vsaddu_vx_w)
-GEN_VEXT_VX_RM(vsaddu_vx_d)
+GEN_VEXT_VX_RM(vsaddu_vx_b, 1)
+GEN_VEXT_VX_RM(vsaddu_vx_h, 2)
+GEN_VEXT_VX_RM(vsaddu_vx_w, 4)
+GEN_VEXT_VX_RM(vsaddu_vx_d, 8)
 
 static inline int8_t sadd8(CPURISCVState *env, int vxrm, int8_t a, int8_t b)
 {
@@ -2307,19 +2315,19 @@ RVVCALL(OPIVV2_RM, vsadd_vv_b, OP_SSS_B, H1, H1, H1, 
sadd8)
 RVVCALL(OPIVV2_RM, vsadd_vv_h, OP_SSS_H, H2, H2, H2, sadd16)
 RVVCALL(OPIVV2_RM, vsadd_vv_w, OP_SSS_W, H4, H4, H4, sadd32)
 RVVCALL(OPIVV2_RM, vsadd_vv_d, OP_SSS_D, H8, H8, H8, sadd64)
-GEN_VEXT_VV_RM(vsadd_vv_b)
-GEN_VEXT_VV_RM(vsadd_vv_h)
-GEN_VEXT_VV_RM(vsadd_vv_w)
-GEN_VEXT_VV_RM(vsadd_vv_d)
+GEN_VEXT_VV_RM(vsadd_vv_b, 1)
+GEN_VEXT_VV_RM(vsadd_vv_h, 2)
+GEN_VEXT_VV_RM(vsadd_vv_w, 4)
+GEN_VEXT_VV_RM(vsadd_vv_d, 8)
 
 RVVCALL(OPIVX2_RM, vsadd_vx_b, OP_SSS_B, H1, H1, sadd8)
 

[PULL 10/25] target/riscv: rvv: Rename ambiguous esz

2022-06-09 Thread Alistair Francis
From: eopXD 

No functional change intended in this commit.

Signed-off-by: eop Chen 
Reviewed-by: Frank Chang 
Reviewed-by: Weiwei Li 
Reviewed-by: Alistair Francis 
Message-Id: <165449614532.19704.700083288048298039...@git.sr.ht>
Signed-off-by: Alistair Francis 
---
 target/riscv/vector_helper.c | 76 ++--
 1 file changed, 38 insertions(+), 38 deletions(-)

diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index 60840325c4..3b79b9cbc2 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -125,9 +125,9 @@ static inline int32_t vext_lmul(uint32_t desc)
 /*
  * Get the maximum number of elements can be operated.
  *
- * esz: log2 of element size in bytes.
+ * log2_esz: log2 of element size in bytes.
  */
-static inline uint32_t vext_max_elems(uint32_t desc, uint32_t esz)
+static inline uint32_t vext_max_elems(uint32_t desc, uint32_t log2_esz)
 {
 /*
  * As simd_desc support at most 2048 bytes, the max vlen is 1024 bits.
@@ -136,7 +136,7 @@ static inline uint32_t vext_max_elems(uint32_t desc, 
uint32_t esz)
 uint32_t vlenb = simd_maxsz(desc);
 
 /* Return VLMAX */
-int scale = vext_lmul(desc) - esz;
+int scale = vext_lmul(desc) - log2_esz;
 return scale < 0 ? vlenb >> -scale : vlenb << scale;
 }
 
@@ -231,11 +231,11 @@ vext_ldst_stride(void *vd, void *v0, target_ulong base,
  target_ulong stride, CPURISCVState *env,
  uint32_t desc, uint32_t vm,
  vext_ldst_elem_fn *ldst_elem,
- uint32_t esz, uintptr_t ra)
+ uint32_t log2_esz, uintptr_t ra)
 {
 uint32_t i, k;
 uint32_t nf = vext_nf(desc);
-uint32_t max_elems = vext_max_elems(desc, esz);
+uint32_t max_elems = vext_max_elems(desc, log2_esz);
 
 for (i = env->vstart; i < env->vl; i++, env->vstart++) {
 if (!vm && !vext_elem_mask(v0, i)) {
@@ -244,7 +244,7 @@ vext_ldst_stride(void *vd, void *v0, target_ulong base,
 
 k = 0;
 while (k < nf) {
-target_ulong addr = base + stride * i + (k << esz);
+target_ulong addr = base + stride * i + (k << log2_esz);
 ldst_elem(env, adjust_addr(env, addr), i + k * max_elems, vd, ra);
 k++;
 }
@@ -289,18 +289,18 @@ GEN_VEXT_ST_STRIDE(vsse64_v, int64_t, ste_d)
 /* unmasked unit-stride load and store operation*/
 static void
 vext_ldst_us(void *vd, target_ulong base, CPURISCVState *env, uint32_t desc,
- vext_ldst_elem_fn *ldst_elem, uint32_t esz, uint32_t evl,
+ vext_ldst_elem_fn *ldst_elem, uint32_t log2_esz, uint32_t evl,
  uintptr_t ra)
 {
 uint32_t i, k;
 uint32_t nf = vext_nf(desc);
-uint32_t max_elems = vext_max_elems(desc, esz);
+uint32_t max_elems = vext_max_elems(desc, log2_esz);
 
 /* load bytes from guest memory */
 for (i = env->vstart; i < evl; i++, env->vstart++) {
 k = 0;
 while (k < nf) {
-target_ulong addr = base + ((i * nf + k) << esz);
+target_ulong addr = base + ((i * nf + k) << log2_esz);
 ldst_elem(env, adjust_addr(env, addr), i + k * max_elems, vd, ra);
 k++;
 }
@@ -399,12 +399,12 @@ vext_ldst_index(void *vd, void *v0, target_ulong base,
 void *vs2, CPURISCVState *env, uint32_t desc,
 vext_get_index_addr get_index_addr,
 vext_ldst_elem_fn *ldst_elem,
-uint32_t esz, uintptr_t ra)
+uint32_t log2_esz, uintptr_t ra)
 {
 uint32_t i, k;
 uint32_t nf = vext_nf(desc);
 uint32_t vm = vext_vm(desc);
-uint32_t max_elems = vext_max_elems(desc, esz);
+uint32_t max_elems = vext_max_elems(desc, log2_esz);
 
 /* load bytes from guest memory */
 for (i = env->vstart; i < env->vl; i++, env->vstart++) {
@@ -414,7 +414,7 @@ vext_ldst_index(void *vd, void *v0, target_ulong base,
 
 k = 0;
 while (k < nf) {
-abi_ptr addr = get_index_addr(base, i, vs2) + (k << esz);
+abi_ptr addr = get_index_addr(base, i, vs2) + (k << log2_esz);
 ldst_elem(env, adjust_addr(env, addr), i + k * max_elems, vd, ra);
 k++;
 }
@@ -480,13 +480,13 @@ static inline void
 vext_ldff(void *vd, void *v0, target_ulong base,
   CPURISCVState *env, uint32_t desc,
   vext_ldst_elem_fn *ldst_elem,
-  uint32_t esz, uintptr_t ra)
+  uint32_t log2_esz, uintptr_t ra)
 {
 void *host;
 uint32_t i, k, vl = 0;
 uint32_t nf = vext_nf(desc);
 uint32_t vm = vext_vm(desc);
-uint32_t max_elems = vext_max_elems(desc, esz);
+uint32_t max_elems = vext_max_elems(desc, log2_esz);
 target_ulong addr, offset, remain;
 
 /* probe every access*/
@@ -494,12 +494,12 @@ vext_ldff(void *vd, void *v0, target_ulong base,
 if (!vm && !vext_elem_mask(v0, i)) {
 continue;
 }
-addr = adjust_addr(env, base + i 

[PULL 07/25] target/riscv/debug.c: keep experimental rv128 support working

2022-06-09 Thread Alistair Francis
From: Frédéric Pétrot 

Add an MXL_RV128 case in two switches so that no error is triggered when
using the -cpu x-rv128 option.

Signed-off-by: Frédéric Pétrot 
Acked-by: Alistair Francis 
Reviewed-by: Bin Meng 
Message-Id: <20220602155246.38837-1-frederic.pet...@univ-grenoble-alpes.fr>
Signed-off-by: Alistair Francis 
---
 target/riscv/debug.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index 2f2a51c732..fc6e13222f 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -77,6 +77,7 @@ static inline target_ulong trigger_type(CPURISCVState *env,
 tdata1 = RV32_TYPE(type);
 break;
 case MXL_RV64:
+case MXL_RV128:
 tdata1 = RV64_TYPE(type);
 break;
 default:
@@ -123,6 +124,7 @@ static target_ulong tdata1_validate(CPURISCVState *env, 
target_ulong val,
 tdata1 = RV32_TYPE(t);
 break;
 case MXL_RV64:
+case MXL_RV128:
 type = extract64(val, 60, 4);
 dmode = extract64(val, 59, 1);
 tdata1 = RV64_TYPE(t);
-- 
2.36.1




[PULL 09/25] target/riscv: rvv: Prune redundant access_type parameter passed

2022-06-09 Thread Alistair Francis
From: eopXD 

No functional change intended in this commit.

Signed-off-by: eop Chen 
Reviewed-by: Alistair Francis 
Message-Id: <165449614532.19704.700083288048298039...@git.sr.ht>
Signed-off-by: Alistair Francis 
---
 target/riscv/vector_helper.c | 35 ---
 1 file changed, 16 insertions(+), 19 deletions(-)

diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index 85dd611cd9..60840325c4 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -231,7 +231,7 @@ vext_ldst_stride(void *vd, void *v0, target_ulong base,
  target_ulong stride, CPURISCVState *env,
  uint32_t desc, uint32_t vm,
  vext_ldst_elem_fn *ldst_elem,
- uint32_t esz, uintptr_t ra, MMUAccessType access_type)
+ uint32_t esz, uintptr_t ra)
 {
 uint32_t i, k;
 uint32_t nf = vext_nf(desc);
@@ -259,7 +259,7 @@ void HELPER(NAME)(void *vd, void * v0, target_ulong base,   
\
 {   \
 uint32_t vm = vext_vm(desc);\
 vext_ldst_stride(vd, v0, base, stride, env, desc, vm, LOAD_FN,  \
- ctzl(sizeof(ETYPE)), GETPC(), MMU_DATA_LOAD);  \
+ ctzl(sizeof(ETYPE)), GETPC()); \
 }
 
 GEN_VEXT_LD_STRIDE(vlse8_v,  int8_t,  lde_b)
@@ -274,7 +274,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong base,
\
 {   \
 uint32_t vm = vext_vm(desc);\
 vext_ldst_stride(vd, v0, base, stride, env, desc, vm, STORE_FN, \
- ctzl(sizeof(ETYPE)), GETPC(), MMU_DATA_STORE); \
+ ctzl(sizeof(ETYPE)), GETPC()); \
 }
 
 GEN_VEXT_ST_STRIDE(vsse8_v,  int8_t,  ste_b)
@@ -290,7 +290,7 @@ GEN_VEXT_ST_STRIDE(vsse64_v, int64_t, ste_d)
 static void
 vext_ldst_us(void *vd, target_ulong base, CPURISCVState *env, uint32_t desc,
  vext_ldst_elem_fn *ldst_elem, uint32_t esz, uint32_t evl,
- uintptr_t ra, MMUAccessType access_type)
+ uintptr_t ra)
 {
 uint32_t i, k;
 uint32_t nf = vext_nf(desc);
@@ -319,14 +319,14 @@ void HELPER(NAME##_mask)(void *vd, void *v0, target_ulong 
base, \
 {   \
 uint32_t stride = vext_nf(desc) << ctzl(sizeof(ETYPE)); \
 vext_ldst_stride(vd, v0, base, stride, env, desc, false, LOAD_FN,   \
- ctzl(sizeof(ETYPE)), GETPC(), MMU_DATA_LOAD);  \
+ ctzl(sizeof(ETYPE)), GETPC()); \
 }   \
 \
 void HELPER(NAME)(void *vd, void *v0, target_ulong base,\
   CPURISCVState *env, uint32_t desc)\
 {   \
 vext_ldst_us(vd, base, env, desc, LOAD_FN,  \
- ctzl(sizeof(ETYPE)), env->vl, GETPC(), MMU_DATA_LOAD); \
+ ctzl(sizeof(ETYPE)), env->vl, GETPC());\
 }
 
 GEN_VEXT_LD_US(vle8_v,  int8_t,  lde_b)
@@ -340,14 +340,14 @@ void HELPER(NAME##_mask)(void *vd, void *v0, target_ulong 
base,  \
 {\
 uint32_t stride = vext_nf(desc) << ctzl(sizeof(ETYPE));  \
 vext_ldst_stride(vd, v0, base, stride, env, desc, false, STORE_FN,   \
- ctzl(sizeof(ETYPE)), GETPC(), MMU_DATA_STORE);  \
+ ctzl(sizeof(ETYPE)), GETPC());  \
 }\
  \
 void HELPER(NAME)(void *vd, void *v0, target_ulong base, \
   CPURISCVState *env, uint32_t desc) \
 {\
 vext_ldst_us(vd, base, env, desc, STORE_FN,  \
- ctzl(sizeof(ETYPE)), env->vl, GETPC(), MMU_DATA_STORE); \
+ ctzl(sizeof(ETYPE)), env->vl, GETPC()); \
 }
 
 GEN_VEXT_ST_US(vse8_v,  int8_t,  ste_b)
@@ -364,7 +364,7 @@ void HELPER(vlm_v)(void *vd, void *v0, target_ulong base,
 /* evl = ceil(vl/8) */
 uint8_t evl = (env->vl + 7) >> 3;
 vext_ldst_us(vd, base, env, desc, lde_b,
- 0, evl, GETPC(), MMU_DATA_LOAD);
+ 0, evl, GETPC());
 }
 
 void HELPER(vsm_v)(void *vd, void *v0, target_ulong base,
@@ -373,7 +373,7 @@ void HELPER(vsm_v)(void *vd, void *v0, 

[PULL 17/25] target/riscv: rvv: Add tail agnostic for vector integer merge and move instructions

2022-06-09 Thread Alistair Francis
From: eopXD 

Signed-off-by: eop Chen 
Reviewed-by: Frank Chang 
Reviewed-by: Weiwei Li 
Acked-by: Alistair Francis 
Message-Id: <165449614532.19704.7000832880482980398...@git.sr.ht>
Signed-off-by: Alistair Francis 
---
 target/riscv/vector_helper.c| 20 
 target/riscv/insn_trans/trans_rvv.c.inc | 12 
 2 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index a64506bf02..128238786e 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -1969,6 +1969,9 @@ void HELPER(NAME)(void *vd, void *vs1, CPURISCVState 
*env,   \
   uint32_t desc) \
 {\
 uint32_t vl = env->vl;   \
+uint32_t esz = sizeof(ETYPE);\
+uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
+uint32_t vta = vext_vta(desc);   \
 uint32_t i;  \
  \
 for (i = env->vstart; i < vl; i++) { \
@@ -1976,6 +1979,8 @@ void HELPER(NAME)(void *vd, void *vs1, CPURISCVState 
*env,   \
 *((ETYPE *)vd + H(i)) = s1;  \
 }\
 env->vstart = 0; \
+/* set tail elements to 1s */\
+vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
 }
 
 GEN_VEXT_VMV_VV(vmv_v_v_b, int8_t,  H1)
@@ -1988,12 +1993,17 @@ void HELPER(NAME)(void *vd, uint64_t s1, CPURISCVState 
*env, \
   uint32_t desc) \
 {\
 uint32_t vl = env->vl;   \
+uint32_t esz = sizeof(ETYPE);\
+uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
+uint32_t vta = vext_vta(desc);   \
 uint32_t i;  \
  \
 for (i = env->vstart; i < vl; i++) { \
 *((ETYPE *)vd + H(i)) = (ETYPE)s1;   \
 }\
 env->vstart = 0; \
+/* set tail elements to 1s */\
+vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
 }
 
 GEN_VEXT_VMV_VX(vmv_v_x_b, int8_t,  H1)
@@ -2006,6 +2016,9 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void 
*vs2,  \
   CPURISCVState *env, uint32_t desc) \
 {\
 uint32_t vl = env->vl;   \
+uint32_t esz = sizeof(ETYPE);\
+uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
+uint32_t vta = vext_vta(desc);   \
 uint32_t i;  \
  \
 for (i = env->vstart; i < vl; i++) { \
@@ -2013,6 +2026,8 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void 
*vs2,  \
 *((ETYPE *)vd + H(i)) = *(vt + H(i));\
 }\
 env->vstart = 0; \
+/* set tail elements to 1s */\
+vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
 }
 
 GEN_VEXT_VMERGE_VV(vmerge_vvm_b, int8_t,  H1)
@@ -2025,6 +2040,9 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1,
   \
   void *vs2, CPURISCVState *env, uint32_t desc)  \
 {\
 uint32_t vl = env->vl;   \
+uint32_t esz = sizeof(ETYPE);\
+uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
+uint32_t vta = vext_vta(desc);   \
 uint32_t i;  \
  \
 for (i = env->vstart; i < vl; i++) { \
@@ -2034,6 +2052,8 @@ void 

[PULL 05/25] hw/core/loader: return image sizes as ssize_t

2022-06-09 Thread Alistair Francis
From: Jamie Iles 

Various loader functions return an int which limits images to 2GB which
is fine for things like a BIOS/kernel image, but if we want to be able
to load memory images or large ramdisks then any file over 2GB would
silently fail to load.

Cc: Luc Michel 
Signed-off-by: Jamie Iles 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Luc Michel 
Reviewed-by: Alistair Francis 
Message-Id: <2021141141.3295094-2-ja...@nuviainc.com>
Signed-off-by: Alistair Francis 
---
 include/hw/loader.h  | 55 +--
 hw/arm/armv7m.c  |  2 +-
 hw/arm/boot.c|  8 ++--
 hw/core/generic-loader.c |  2 +-
 hw/core/loader.c | 81 +---
 hw/i386/x86.c|  2 +-
 hw/riscv/boot.c  |  5 ++-
 7 files changed, 80 insertions(+), 75 deletions(-)

diff --git a/include/hw/loader.h b/include/hw/loader.h
index 5572108ba5..70248e0da7 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -40,8 +40,8 @@ ssize_t load_image_size(const char *filename, void *addr, 
size_t size);
  *
  * Returns the size of the loaded image on success, -1 otherwise.
  */
-int load_image_targphys_as(const char *filename,
-   hwaddr addr, uint64_t max_sz, AddressSpace *as);
+ssize_t load_image_targphys_as(const char *filename,
+   hwaddr addr, uint64_t max_sz, AddressSpace *as);
 
 /**load_targphys_hex_as:
  * @filename: Path to the .hex file
@@ -53,14 +53,15 @@ int load_image_targphys_as(const char *filename,
  *
  * Returns the size of the loaded .hex file on success, -1 otherwise.
  */
-int load_targphys_hex_as(const char *filename, hwaddr *entry, AddressSpace 
*as);
+ssize_t load_targphys_hex_as(const char *filename, hwaddr *entry,
+ AddressSpace *as);
 
 /** load_image_targphys:
  * Same as load_image_targphys_as(), but doesn't allow the caller to specify
  * an AddressSpace.
  */
-int load_image_targphys(const char *filename, hwaddr,
-uint64_t max_sz);
+ssize_t load_image_targphys(const char *filename, hwaddr,
+uint64_t max_sz);
 
 /**
  * load_image_mr: load an image into a memory region
@@ -73,7 +74,7 @@ int load_image_targphys(const char *filename, hwaddr,
  * If the file is larger than the memory region's size the call will fail.
  * Returns -1 on failure, or the size of the file.
  */
-int load_image_mr(const char *filename, MemoryRegion *mr);
+ssize_t load_image_mr(const char *filename, MemoryRegion *mr);
 
 /* This is the limit on the maximum uncompressed image size that
  * load_image_gzipped_buffer() and load_image_gzipped() will read. It prevents
@@ -81,9 +82,9 @@ int load_image_mr(const char *filename, MemoryRegion *mr);
  */
 #define LOAD_IMAGE_MAX_GUNZIP_BYTES (256 << 20)
 
-int load_image_gzipped_buffer(const char *filename, uint64_t max_sz,
-  uint8_t **buffer);
-int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz);
+ssize_t load_image_gzipped_buffer(const char *filename, uint64_t max_sz,
+  uint8_t **buffer);
+ssize_t load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz);
 
 #define ELF_LOAD_FAILED   -1
 #define ELF_LOAD_NOT_ELF  -2
@@ -183,8 +184,8 @@ ssize_t load_elf(const char *filename,
  */
 void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp);
 
-int load_aout(const char *filename, hwaddr addr, int max_sz,
-  int bswap_needed, hwaddr target_page_size);
+ssize_t load_aout(const char *filename, hwaddr addr, int max_sz,
+  int bswap_needed, hwaddr target_page_size);
 
 #define LOAD_UIMAGE_LOADADDR_INVALID (-1)
 
@@ -205,19 +206,19 @@ int load_aout(const char *filename, hwaddr addr, int 
max_sz,
  *
  * Returns the size of the loaded image on success, -1 otherwise.
  */
-int load_uimage_as(const char *filename, hwaddr *ep,
-   hwaddr *loadaddr, int *is_linux,
-   uint64_t (*translate_fn)(void *, uint64_t),
-   void *translate_opaque, AddressSpace *as);
+ssize_t load_uimage_as(const char *filename, hwaddr *ep,
+   hwaddr *loadaddr, int *is_linux,
+   uint64_t (*translate_fn)(void *, uint64_t),
+   void *translate_opaque, AddressSpace *as);
 
 /** load_uimage:
  * Same as load_uimage_as(), but doesn't allow the caller to specify an
  * AddressSpace.
  */
-int load_uimage(const char *filename, hwaddr *ep,
-hwaddr *loadaddr, int *is_linux,
-uint64_t (*translate_fn)(void *, uint64_t),
-void *translate_opaque);
+ssize_t load_uimage(const char *filename, hwaddr *ep,
+hwaddr *loadaddr, int *is_linux,
+uint64_t (*translate_fn)(void *, uint64_t),
+void *translate_opaque);
 
 /**
  * load_ramdisk_as:
@@ -232,15 +233,15 @@ int 

[PULL 15/25] target/riscv: rvv: Add tail agnostic for vector integer shift instructions

2022-06-09 Thread Alistair Francis
From: eopXD 

Signed-off-by: eop Chen 
Reviewed-by: Frank Chang 
Reviewed-by: Weiwei Li 
Acked-by: Alistair Francis 
Message-Id: <165449614532.19704.700083288048298039...@git.sr.ht>
Signed-off-by: Alistair Francis 
---
 target/riscv/vector_helper.c| 11 +++
 target/riscv/insn_trans/trans_rvv.c.inc |  3 ++-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index 7cdb5d12af..056c2a1c7e 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -1271,6 +1271,9 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1,  
\
 { \
 uint32_t vm = vext_vm(desc);  \
 uint32_t vl = env->vl;\
+uint32_t esz = sizeof(TS1);   \
+uint32_t total_elems = vext_get_total_elems(env, desc, esz);  \
+uint32_t vta = vext_vta(desc);\
 uint32_t i;   \
   \
 for (i = env->vstart; i < vl; i++) {  \
@@ -1282,6 +1285,8 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1,  
\
 *((TS1 *)vd + HS1(i)) = OP(s2, s1 & MASK);\
 } \
 env->vstart = 0;  \
+/* set tail elements to 1s */ \
+vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);  \
 }
 
 GEN_VEXT_SHIFT_VV(vsll_vv_b, uint8_t,  uint8_t, H1, H1, DO_SLL, 0x7)
@@ -1306,6 +1311,10 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1,   
   \
 {   \
 uint32_t vm = vext_vm(desc);\
 uint32_t vl = env->vl;  \
+uint32_t esz = sizeof(TD);  \
+uint32_t total_elems =  \
+vext_get_total_elems(env, desc, esz);   \
+uint32_t vta = vext_vta(desc);  \
 uint32_t i; \
 \
 for (i = env->vstart; i < vl; i++) {\
@@ -1316,6 +1325,8 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1,
  \
 *((TD *)vd + HD(i)) = OP(s2, s1 & MASK);\
 }   \
 env->vstart = 0;\
+/* set tail elements to 1s */   \
+vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);\
 }
 
 GEN_VEXT_SHIFT_VX(vsll_vx_b, uint8_t, int8_t, H1, H1, DO_SLL, 0x7)
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc 
b/target/riscv/insn_trans/trans_rvv.c.inc
index 22edf6228d..dbe687fb73 100644
--- a/target/riscv/insn_trans/trans_rvv.c.inc
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
@@ -1831,7 +1831,7 @@ do_opivx_gvec_shift(DisasContext *s, arg_rmrr *a, 
GVecGen2sFn32 *gvec_fn,
 return false;
 }
 
-if (a->vm && s->vl_eq_vlmax) {
+if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
 TCGv_i32 src1 = tcg_temp_new_i32();
 
 tcg_gen_trunc_tl_i32(src1, get_gpr(s, a->rs1, EXT_NONE));
@@ -1890,6 +1890,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a)
 \
\
 data = FIELD_DP32(data, VDATA, VM, a->vm); \
 data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
+data = FIELD_DP32(data, VDATA, VTA, s->vta);   \
 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,   \
-- 
2.36.1




[PULL 06/25] target/riscv: Wake on VS-level external interrupts

2022-06-09 Thread Alistair Francis
From: Andrew Bresticker 

Whether or not VSEIP is pending isn't reflected in env->mip and must
instead be determined from hstatus.vgein and hgeip. As a result a
CPU in WFI won't wake on a VSEIP, which violates the WFI behavior as
specified in the privileged ISA. Just use riscv_cpu_all_pending()
instead, which already accounts for VSEIP.

Signed-off-by: Andrew Bresticker 
Reviewed-by: Alistair Francis 
Message-Id: <20220531210544.181322-1-abres...@rivosinc.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h| 1 +
 target/riscv/cpu.c| 2 +-
 target/riscv/cpu_helper.c | 2 +-
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 890d33cebb..194a58d760 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -489,6 +489,7 @@ int riscv_cpu_gdb_read_register(CPUState *cpu, GByteArray 
*buf, int reg);
 int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 int riscv_cpu_hviprio_index2irq(int index, int *out_irq, int *out_rdzero);
 uint8_t riscv_cpu_default_priority(int irq);
+uint64_t riscv_cpu_all_pending(CPURISCVState *env);
 int riscv_cpu_mirq_pending(CPURISCVState *env);
 int riscv_cpu_sirq_pending(CPURISCVState *env);
 int riscv_cpu_vsirq_pending(CPURISCVState *env);
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index bcbba3fbd5..0497af45cc 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -391,7 +391,7 @@ static bool riscv_cpu_has_work(CPUState *cs)
  * Definition of the WFI instruction requires it to ignore the privilege
  * mode and delegation registers, but respect individual enables
  */
-return (env->mip & env->mie) != 0;
+return riscv_cpu_all_pending(env) != 0;
 #else
 return true;
 #endif
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index d99fac9d2d..16c6045459 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -340,7 +340,7 @@ static int riscv_cpu_pending_to_irq(CPURISCVState *env,
 return best_irq;
 }
 
-static uint64_t riscv_cpu_all_pending(CPURISCVState *env)
+uint64_t riscv_cpu_all_pending(CPURISCVState *env)
 {
 uint32_t gein = get_field(env->hstatus, HSTATUS_VGEIN);
 uint64_t vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
-- 
2.36.1




[PULL 03/25] hw/riscv: virt: Generate fw_cfg DT node correctly

2022-06-09 Thread Alistair Francis
From: Atish Patra 

fw_cfg DT node is generated after the create_fdt without any check
if the DT is being loaded from the commandline. This results in
FDT_ERR_EXISTS error if dtb is loaded from the commandline.

Generate fw_cfg node only if the DT is not loaded from the commandline.

Signed-off-by: Atish Patra 
Reviewed-by: Alistair Francis 
Message-Id: <20220526203500.847165-1-ati...@rivosinc.com>
Signed-off-by: Alistair Francis 
---
 hw/riscv/virt.c | 28 ++--
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 293e9c95b7..bc424dd2f5 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -975,6 +975,23 @@ static void create_fdt_flash(RISCVVirtState *s, const 
MemMapEntry *memmap)
 g_free(name);
 }
 
+static void create_fdt_fw_cfg(RISCVVirtState *s, const MemMapEntry *memmap)
+{
+char *nodename;
+MachineState *mc = MACHINE(s);
+hwaddr base = memmap[VIRT_FW_CFG].base;
+hwaddr size = memmap[VIRT_FW_CFG].size;
+
+nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base);
+qemu_fdt_add_subnode(mc->fdt, nodename);
+qemu_fdt_setprop_string(mc->fdt, nodename,
+"compatible", "qemu,fw-cfg-mmio");
+qemu_fdt_setprop_sized_cells(mc->fdt, nodename, "reg",
+ 2, base, 2, size);
+qemu_fdt_setprop(mc->fdt, nodename, "dma-coherent", NULL, 0);
+g_free(nodename);
+}
+
 static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
uint64_t mem_size, const char *cmdline, bool is_32_bit)
 {
@@ -1023,6 +1040,7 @@ static void create_fdt(RISCVVirtState *s, const 
MemMapEntry *memmap,
 create_fdt_rtc(s, memmap, irq_mmio_phandle);
 
 create_fdt_flash(s, memmap);
+create_fdt_fw_cfg(s, memmap);
 
 update_bootargs:
 if (cmdline && *cmdline) {
@@ -1082,22 +1100,12 @@ static inline DeviceState *gpex_pcie_init(MemoryRegion 
*sys_mem,
 static FWCfgState *create_fw_cfg(const MachineState *mc)
 {
 hwaddr base = virt_memmap[VIRT_FW_CFG].base;
-hwaddr size = virt_memmap[VIRT_FW_CFG].size;
 FWCfgState *fw_cfg;
-char *nodename;
 
 fw_cfg = fw_cfg_init_mem_wide(base + 8, base, 8, base + 16,
   _space_memory);
 fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)mc->smp.cpus);
 
-nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base);
-qemu_fdt_add_subnode(mc->fdt, nodename);
-qemu_fdt_setprop_string(mc->fdt, nodename,
-"compatible", "qemu,fw-cfg-mmio");
-qemu_fdt_setprop_sized_cells(mc->fdt, nodename, "reg",
- 2, base, 2, size);
-qemu_fdt_setprop(mc->fdt, nodename, "dma-coherent", NULL, 0);
-g_free(nodename);
 return fw_cfg;
 }
 
-- 
2.36.1




[PULL 04/25] hw/intc: sifive_plic: Avoid overflowing the addr_config buffer

2022-06-09 Thread Alistair Francis
From: Alistair Francis 

Since commit ad40be27 "target/riscv: Support start kernel directly by
KVM" we have been overflowing the addr_config on "M,MS..."
configurations, as reported https://gitlab.com/qemu-project/qemu/-/issues/1050.

This commit changes the loop in sifive_plic_create() from iterating over
the number of harts to just iterating over the addr_config. The
addr_config is based on the hart_config, and will contain interrup details
for all harts. This way we can't iterate past the end of addr_config.

Fixes: ad40be27084536 ("target/riscv: Support start kernel directly by KVM")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1050
Signed-off-by: Alistair Francis 
Reviewed-by: Mingwang Li 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20220601013631.196854-1-alistair.fran...@opensource.wdc.com>
---
 hw/intc/sifive_plic.c | 19 +--
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c
index eebbcf33d4..56d60e9ac9 100644
--- a/hw/intc/sifive_plic.c
+++ b/hw/intc/sifive_plic.c
@@ -431,7 +431,7 @@ DeviceState *sifive_plic_create(hwaddr addr, char 
*hart_config,
 uint32_t context_stride, uint32_t aperture_size)
 {
 DeviceState *dev = qdev_new(TYPE_SIFIVE_PLIC);
-int i, j = 0;
+int i;
 SiFivePLICState *plic;
 
 assert(enable_stride == (enable_stride & -enable_stride));
@@ -451,18 +451,17 @@ DeviceState *sifive_plic_create(hwaddr addr, char 
*hart_config,
 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
 
 plic = SIFIVE_PLIC(dev);
-for (i = 0; i < num_harts; i++) {
-CPUState *cpu = qemu_get_cpu(hartid_base + i);
 
-if (plic->addr_config[j].mode == PLICMode_M) {
-j++;
-qdev_connect_gpio_out(dev, num_harts + i,
+for (i = 0; i < plic->num_addrs; i++) {
+int cpu_num = plic->addr_config[i].hartid;
+CPUState *cpu = qemu_get_cpu(hartid_base + cpu_num);
+
+if (plic->addr_config[i].mode == PLICMode_M) {
+qdev_connect_gpio_out(dev, num_harts + cpu_num,
   qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT));
 }
-
-if (plic->addr_config[j].mode == PLICMode_S) {
-j++;
-qdev_connect_gpio_out(dev, i,
+if (plic->addr_config[i].mode == PLICMode_S) {
+qdev_connect_gpio_out(dev, cpu_num,
   qdev_get_gpio_in(DEVICE(cpu), IRQ_S_EXT));
 }
 }
-- 
2.36.1




[PULL 02/25] target/riscv: add support for zmmul extension v0.1

2022-06-09 Thread Alistair Francis
From: Weiwei Li 

Add support for the zmmul extension v0.1. This extension includes all
multiplication operations from the M extension but not the divide ops.

Signed-off-by: Weiwei Li 
Signed-off-by: Junqiang Wang 
Reviewed-by: Víctor Colombo 
Reviewed-by: Alistair Francis 
Message-Id: <20220531030732.3850-1-liwei...@iscas.ac.cn>
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h  |  1 +
 target/riscv/cpu.c  |  7 +++
 target/riscv/insn_trans/trans_rvm.c.inc | 18 --
 3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index f08c3e8813..890d33cebb 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -411,6 +411,7 @@ struct RISCVCPUConfig {
 bool ext_zhinxmin;
 bool ext_zve32f;
 bool ext_zve64f;
+bool ext_zmmul;
 
 uint32_t mvendorid;
 uint64_t marchid;
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index a91253d4bd..bcbba3fbd5 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -600,6 +600,11 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 cpu->cfg.ext_ifencei = true;
 }
 
+if (cpu->cfg.ext_m && cpu->cfg.ext_zmmul) {
+warn_report("Zmmul will override M");
+cpu->cfg.ext_m = false;
+}
+
 if (cpu->cfg.ext_i && cpu->cfg.ext_e) {
 error_setg(errp,
"I and E extensions are incompatible");
@@ -905,6 +910,7 @@ static Property riscv_cpu_properties[] = {
 
 /* These are experimental so mark with 'x-' */
 DEFINE_PROP_BOOL("x-j", RISCVCPU, cfg.ext_j, false),
+DEFINE_PROP_BOOL("x-zmmul", RISCVCPU, cfg.ext_zmmul, false),
 /* ePMP 0.9.3 */
 DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
 DEFINE_PROP_BOOL("x-aia", RISCVCPU, cfg.aia, false),
@@ -1031,6 +1037,7 @@ static void riscv_isa_string_ext(RISCVCPU *cpu, char 
**isa_str, int max_str_len)
 struct isa_ext_data isa_edata_arr[] = {
 ISA_EDATA_ENTRY(zicsr, ext_icsr),
 ISA_EDATA_ENTRY(zifencei, ext_ifencei),
+ISA_EDATA_ENTRY(zmmul, ext_zmmul),
 ISA_EDATA_ENTRY(zfh, ext_zfh),
 ISA_EDATA_ENTRY(zfhmin, ext_zfhmin),
 ISA_EDATA_ENTRY(zfinx, ext_zfinx),
diff --git a/target/riscv/insn_trans/trans_rvm.c.inc 
b/target/riscv/insn_trans/trans_rvm.c.inc
index 16b029edf0..ec7f705aab 100644
--- a/target/riscv/insn_trans/trans_rvm.c.inc
+++ b/target/riscv/insn_trans/trans_rvm.c.inc
@@ -18,6 +18,12 @@
  * this program.  If not, see .
  */
 
+#define REQUIRE_M_OR_ZMMUL(ctx) do {  \
+if (!ctx->cfg_ptr->ext_zmmul && !has_ext(ctx, RVM)) { \
+return false; \
+} \
+} while (0)
+
 static void gen_mulhu_i128(TCGv r2, TCGv r3, TCGv al, TCGv ah, TCGv bl, TCGv 
bh)
 {
 TCGv tmpl = tcg_temp_new();
@@ -65,7 +71,7 @@ static void gen_mul_i128(TCGv rl, TCGv rh,
 
 static bool trans_mul(DisasContext *ctx, arg_mul *a)
 {
-REQUIRE_EXT(ctx, RVM);
+REQUIRE_M_OR_ZMMUL(ctx);
 return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl, gen_mul_i128);
 }
 
@@ -109,7 +115,7 @@ static void gen_mulh_w(TCGv ret, TCGv s1, TCGv s2)
 
 static bool trans_mulh(DisasContext *ctx, arg_mulh *a)
 {
-REQUIRE_EXT(ctx, RVM);
+REQUIRE_M_OR_ZMMUL(ctx);
 return gen_arith_per_ol(ctx, a, EXT_SIGN, gen_mulh, gen_mulh_w,
 gen_mulh_i128);
 }
@@ -161,7 +167,7 @@ static void gen_mulhsu_w(TCGv ret, TCGv arg1, TCGv arg2)
 
 static bool trans_mulhsu(DisasContext *ctx, arg_mulhsu *a)
 {
-REQUIRE_EXT(ctx, RVM);
+REQUIRE_M_OR_ZMMUL(ctx);
 return gen_arith_per_ol(ctx, a, EXT_NONE, gen_mulhsu, gen_mulhsu_w,
 gen_mulhsu_i128);
 }
@@ -176,7 +182,7 @@ static void gen_mulhu(TCGv ret, TCGv s1, TCGv s2)
 
 static bool trans_mulhu(DisasContext *ctx, arg_mulhu *a)
 {
-REQUIRE_EXT(ctx, RVM);
+REQUIRE_M_OR_ZMMUL(ctx);
 /* gen_mulh_w works for either sign as input. */
 return gen_arith_per_ol(ctx, a, EXT_ZERO, gen_mulhu, gen_mulh_w,
 gen_mulhu_i128);
@@ -349,7 +355,7 @@ static bool trans_remu(DisasContext *ctx, arg_remu *a)
 static bool trans_mulw(DisasContext *ctx, arg_mulw *a)
 {
 REQUIRE_64_OR_128BIT(ctx);
-REQUIRE_EXT(ctx, RVM);
+REQUIRE_M_OR_ZMMUL(ctx);
 ctx->ol = MXL_RV32;
 return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl, NULL);
 }
@@ -389,7 +395,7 @@ static bool trans_remuw(DisasContext *ctx, arg_remuw *a)
 static bool trans_muld(DisasContext *ctx, arg_muld *a)
 {
 REQUIRE_128BIT(ctx);
-REQUIRE_EXT(ctx, RVM);
+REQUIRE_M_OR_ZMMUL(ctx);
 ctx->ol = MXL_RV64;
 return gen_arith(ctx, a, EXT_SIGN, tcg_gen_mul_tl, NULL);
 }
-- 
2.36.1




[PULL 01/25] MAINTAINERS: Cover hw/core/uboot_image.h within Generic Loader section

2022-06-09 Thread Alistair Francis
From: Alistair Francis 

Signed-off-by: Alistair Francis 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20220509091339.26016-1-alistair.fran...@wdc.com>
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 5580a36b68..b3af081c51 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2198,6 +2198,7 @@ Generic Loader
 M: Alistair Francis 
 S: Maintained
 F: hw/core/generic-loader.c
+F: hw/core/uboot_image.h
 F: include/hw/core/generic-loader.h
 F: docs/system/generic-loader.rst
 
-- 
2.36.1




[PULL 08/25] target/riscv: rvv: Prune redundant ESZ, DSZ parameter passed

2022-06-09 Thread Alistair Francis
From: eopXD 

No functional change intended in this commit.

Signed-off-by: eop Chen 
Reviewed-by: Frank Chang 
Reviewed-by: Weiwei Li 
Reviewed-by: Alistair Francis 
Message-Id: <165449614532.19704.700083288048298039...@git.sr.ht>
Signed-off-by: Alistair Francis 
---
 target/riscv/vector_helper.c | 1132 +-
 1 file changed, 565 insertions(+), 567 deletions(-)

diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index 576b14e5a3..85dd611cd9 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -710,7 +710,6 @@ RVVCALL(OPIVV2, vsub_vv_d, OP_SSS_D, H8, H8, H8, DO_SUB)
 
 static void do_vext_vv(void *vd, void *v0, void *vs1, void *vs2,
CPURISCVState *env, uint32_t desc,
-   uint32_t esz, uint32_t dsz,
opivv2_fn *fn)
 {
 uint32_t vm = vext_vm(desc);
@@ -727,23 +726,23 @@ static void do_vext_vv(void *vd, void *v0, void *vs1, 
void *vs2,
 }
 
 /* generate the helpers for OPIVV */
-#define GEN_VEXT_VV(NAME, ESZ, DSZ)   \
+#define GEN_VEXT_VV(NAME) \
 void HELPER(NAME)(void *vd, void *v0, void *vs1,  \
   void *vs2, CPURISCVState *env,  \
   uint32_t desc)  \
 { \
-do_vext_vv(vd, v0, vs1, vs2, env, desc, ESZ, DSZ, \
+do_vext_vv(vd, v0, vs1, vs2, env, desc,   \
do_##NAME);\
 }
 
-GEN_VEXT_VV(vadd_vv_b, 1, 1)
-GEN_VEXT_VV(vadd_vv_h, 2, 2)
-GEN_VEXT_VV(vadd_vv_w, 4, 4)
-GEN_VEXT_VV(vadd_vv_d, 8, 8)
-GEN_VEXT_VV(vsub_vv_b, 1, 1)
-GEN_VEXT_VV(vsub_vv_h, 2, 2)
-GEN_VEXT_VV(vsub_vv_w, 4, 4)
-GEN_VEXT_VV(vsub_vv_d, 8, 8)
+GEN_VEXT_VV(vadd_vv_b)
+GEN_VEXT_VV(vadd_vv_h)
+GEN_VEXT_VV(vadd_vv_w)
+GEN_VEXT_VV(vadd_vv_d)
+GEN_VEXT_VV(vsub_vv_b)
+GEN_VEXT_VV(vsub_vv_h)
+GEN_VEXT_VV(vsub_vv_w)
+GEN_VEXT_VV(vsub_vv_d)
 
 typedef void opivx2_fn(void *vd, target_long s1, void *vs2, int i);
 
@@ -773,7 +772,6 @@ RVVCALL(OPIVX2, vrsub_vx_d, OP_SSS_D, H8, H8, DO_RSUB)
 
 static void do_vext_vx(void *vd, void *v0, target_long s1, void *vs2,
CPURISCVState *env, uint32_t desc,
-   uint32_t esz, uint32_t dsz,
opivx2_fn fn)
 {
 uint32_t vm = vext_vm(desc);
@@ -790,27 +788,27 @@ static void do_vext_vx(void *vd, void *v0, target_long 
s1, void *vs2,
 }
 
 /* generate the helpers for OPIVX */
-#define GEN_VEXT_VX(NAME, ESZ, DSZ)   \
+#define GEN_VEXT_VX(NAME) \
 void HELPER(NAME)(void *vd, void *v0, target_ulong s1,\
   void *vs2, CPURISCVState *env,  \
   uint32_t desc)  \
 { \
-do_vext_vx(vd, v0, s1, vs2, env, desc, ESZ, DSZ,  \
+do_vext_vx(vd, v0, s1, vs2, env, desc,\
do_##NAME);\
 }
 
-GEN_VEXT_VX(vadd_vx_b, 1, 1)
-GEN_VEXT_VX(vadd_vx_h, 2, 2)
-GEN_VEXT_VX(vadd_vx_w, 4, 4)
-GEN_VEXT_VX(vadd_vx_d, 8, 8)
-GEN_VEXT_VX(vsub_vx_b, 1, 1)
-GEN_VEXT_VX(vsub_vx_h, 2, 2)
-GEN_VEXT_VX(vsub_vx_w, 4, 4)
-GEN_VEXT_VX(vsub_vx_d, 8, 8)
-GEN_VEXT_VX(vrsub_vx_b, 1, 1)
-GEN_VEXT_VX(vrsub_vx_h, 2, 2)
-GEN_VEXT_VX(vrsub_vx_w, 4, 4)
-GEN_VEXT_VX(vrsub_vx_d, 8, 8)
+GEN_VEXT_VX(vadd_vx_b)
+GEN_VEXT_VX(vadd_vx_h)
+GEN_VEXT_VX(vadd_vx_w)
+GEN_VEXT_VX(vadd_vx_d)
+GEN_VEXT_VX(vsub_vx_b)
+GEN_VEXT_VX(vsub_vx_h)
+GEN_VEXT_VX(vsub_vx_w)
+GEN_VEXT_VX(vsub_vx_d)
+GEN_VEXT_VX(vrsub_vx_b)
+GEN_VEXT_VX(vrsub_vx_h)
+GEN_VEXT_VX(vrsub_vx_w)
+GEN_VEXT_VX(vrsub_vx_d)
 
 void HELPER(vec_rsubs8)(void *d, void *a, uint64_t b, uint32_t desc)
 {
@@ -889,30 +887,30 @@ RVVCALL(OPIVV2, vwadd_wv_w, WOP_WSSS_W, H8, H4, H4, 
DO_ADD)
 RVVCALL(OPIVV2, vwsub_wv_b, WOP_WSSS_B, H2, H1, H1, DO_SUB)
 RVVCALL(OPIVV2, vwsub_wv_h, WOP_WSSS_H, H4, H2, H2, DO_SUB)
 RVVCALL(OPIVV2, vwsub_wv_w, WOP_WSSS_W, H8, H4, H4, DO_SUB)
-GEN_VEXT_VV(vwaddu_vv_b, 1, 2)
-GEN_VEXT_VV(vwaddu_vv_h, 2, 4)
-GEN_VEXT_VV(vwaddu_vv_w, 4, 8)
-GEN_VEXT_VV(vwsubu_vv_b, 1, 2)
-GEN_VEXT_VV(vwsubu_vv_h, 2, 4)
-GEN_VEXT_VV(vwsubu_vv_w, 4, 8)
-GEN_VEXT_VV(vwadd_vv_b, 1, 2)
-GEN_VEXT_VV(vwadd_vv_h, 2, 4)
-GEN_VEXT_VV(vwadd_vv_w, 4, 8)
-GEN_VEXT_VV(vwsub_vv_b, 1, 2)
-GEN_VEXT_VV(vwsub_vv_h, 2, 4)
-GEN_VEXT_VV(vwsub_vv_w, 4, 8)
-GEN_VEXT_VV(vwaddu_wv_b, 1, 2)
-GEN_VEXT_VV(vwaddu_wv_h, 2, 4)
-GEN_VEXT_VV(vwaddu_wv_w, 4, 8)
-GEN_VEXT_VV(vwsubu_wv_b, 1, 2)
-GEN_VEXT_VV(vwsubu_wv_h, 2, 4)
-GEN_VEXT_VV(vwsubu_wv_w, 4, 8)
-GEN_VEXT_VV(vwadd_wv_b, 1, 2)
-GEN_VEXT_VV(vwadd_wv_h, 2, 4)
-GEN_VEXT_VV(vwadd_wv_w, 4, 8)
-GEN_VEXT_VV(vwsub_wv_b, 1, 2)
-GEN_VEXT_VV(vwsub_wv_h, 2, 4)
-GEN_VEXT_VV(vwsub_wv_w, 4, 8)
+GEN_VEXT_VV(vwaddu_vv_b)
+GEN_VEXT_VV(vwaddu_vv_h)
+GEN_VEXT_VV(vwaddu_vv_w)
+GEN_VEXT_VV(vwsubu_vv_b)

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

2022-06-09 Thread Alistair Francis
From: Alistair Francis 

The following changes since commit 9cc1bf1ebca550f8d90f967ccd2b6d2e00e81387:

  Merge tag 'pull-xen-20220609' of 
https://xenbits.xen.org/git-http/people/aperard/qemu-dm into staging 
(2022-06-09 08:25:17 -0700)

are available in the Git repository at:

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

for you to fetch changes up to 07314158f6aa4d2589520c194a7531b9364a8d54:

  target/riscv: trans_rvv: Avoid assert for RV32 and e64 (2022-06-10 09:42:12 
+1000)


Fourth RISC-V PR for QEMU 7.1

* Update MAINTAINERS
* Add support for Zmmul extension
* Fixup FDT errors when supplying device tree from the command line for virt 
machine
* Avoid overflowing the addr_config buffer in the SiFive PLIC
* Support -device loader addresses above 2GB
* Correctly wake from WFI on VS-level external interrupts
* Fixes for RV128 support
* Support Vector extension tail agnostic setting elements' bits to all 1s
* Don't expose the CPU properties on named CPUs
* Fix vector extension assert for RV32


Alistair Francis (4):
  MAINTAINERS: Cover hw/core/uboot_image.h within Generic Loader section
  hw/intc: sifive_plic: Avoid overflowing the addr_config buffer
  target/riscv: Don't expose the CPU properties on names CPUs
  target/riscv: trans_rvv: Avoid assert for RV32 and e64

Andrew Bresticker (1):
  target/riscv: Wake on VS-level external interrupts

Atish Patra (1):
  hw/riscv: virt: Generate fw_cfg DT node correctly

Frédéric Pétrot (1):
  target/riscv/debug.c: keep experimental rv128 support working

Jamie Iles (1):
  hw/core/loader: return image sizes as ssize_t

Weiwei Li (1):
  target/riscv: add support for zmmul extension v0.1

eopXD (16):
  target/riscv: rvv: Prune redundant ESZ, DSZ parameter passed
  target/riscv: rvv: Prune redundant access_type parameter passed
  target/riscv: rvv: Rename ambiguous esz
  target/riscv: rvv: Early exit when vstart >= vl
  target/riscv: rvv: Add tail agnostic for vv instructions
  target/riscv: rvv: Add tail agnostic for vector load / store instructions
  target/riscv: rvv: Add tail agnostic for vx, vvm, vxm instructions
  target/riscv: rvv: Add tail agnostic for vector integer shift instructions
  target/riscv: rvv: Add tail agnostic for vector integer comparison 
instructions
  target/riscv: rvv: Add tail agnostic for vector integer merge and move 
instructions
  target/riscv: rvv: Add tail agnostic for vector fix-point arithmetic 
instructions
  target/riscv: rvv: Add tail agnostic for vector floating-point 
instructions
  target/riscv: rvv: Add tail agnostic for vector reduction instructions
  target/riscv: rvv: Add tail agnostic for vector mask instructions
  target/riscv: rvv: Add tail agnostic for vector permutation instructions
  target/riscv: rvv: Add option 'rvv_ta_all_1s' to enable optional tail 
agnostic behavior

 include/hw/loader.h |   55 +-
 target/riscv/cpu.h  |4 +
 target/riscv/internals.h|6 +-
 hw/arm/armv7m.c |2 +-
 hw/arm/boot.c   |8 +-
 hw/core/generic-loader.c|2 +-
 hw/core/loader.c|   81 +-
 hw/i386/x86.c   |2 +-
 hw/intc/sifive_plic.c   |   19 +-
 hw/riscv/boot.c |5 +-
 hw/riscv/virt.c |   28 +-
 target/riscv/cpu.c  |   68 +-
 target/riscv/cpu_helper.c   |4 +-
 target/riscv/debug.c|2 +
 target/riscv/translate.c|4 +
 target/riscv/vector_helper.c| 1588 +++
 target/riscv/insn_trans/trans_rvm.c.inc |   18 +-
 target/riscv/insn_trans/trans_rvv.c.inc |  106 ++-
 MAINTAINERS |1 +
 19 files changed, 1244 insertions(+), 759 deletions(-)



about QOP

2022-06-09 Thread Liu Jaloo
Dear Paul Brook:
in qemu/tcg/README:
"
...
QOP code generator written by Paul Brook.
...
"

Is there some text about QOP? or basically what QOP stands for?

I can't find out anything about QOP from Google. thanks.


Re: [PATCH v2 1/2] QIOChannelSocket: Reduce ifdefs to improve readability

2022-06-09 Thread Leonardo Bras Soares Passos
Hello Daniel,

On Thu, Jun 9, 2022 at 5:10 AM Daniel P. Berrangé  wrote:
>
> On Wed, Jun 08, 2022 at 06:04:02PM -0300, Leonardo Bras wrote:
> > During implementation of MSG_ZEROCOPY feature, a lot of #ifdefs were
> > introduced, particularly at qio_channel_socket_writev().
> >
> > Rewrite some of those changes so it's easier to read.
> >   ...
> > Signed-off-by: Leonardo Bras 
> > ---
> >  io/channel-socket.c | 6 +++---
> >  1 file changed, 3 insertions(+), 3 deletions(-)
> >
> > diff --git a/io/channel-socket.c b/io/channel-socket.c
> > index dc9c165de1..ef7c7cfbac 100644
> > --- a/io/channel-socket.c
> > +++ b/io/channel-socket.c
> > @@ -554,6 +554,7 @@ static ssize_t qio_channel_socket_writev(QIOChannel 
> > *ioc,
> >  size_t fdsize = sizeof(int) * nfds;
> >  struct cmsghdr *cmsg;
> >  int sflags = 0;
> > +bool zero_copy_enabled = false;
> >
> >  memset(control, 0, CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS));
> >
> > @@ -581,6 +582,7 @@ static ssize_t qio_channel_socket_writev(QIOChannel 
> > *ioc,
> >  #ifdef QEMU_MSG_ZEROCOPY
> >  if (flags & QIO_CHANNEL_WRITE_FLAG_ZERO_COPY) {
> >  sflags = MSG_ZEROCOPY;
> > +zero_copy_enabled = true;
> >  }
>
> There should be a
>
>  #else
> error_setg(errp, "Zero copy not supported on this platform");
> return -1;
>  #endif
>

IIUC, if done as suggested, it will break every non-zero-copy call of
qio_channel_socket_writev();

I think you are suggesting something like :

if (flags & QIO_CHANNEL_WRITE_FLAG_ZERO_COPY) {
#ifdef QEMU_MSG_ZEROCOPY
sflags = MSG_ZEROCOPY;
zero_copy_enabled = true; // I know you suggested this out,
just for example purposes
#else
error_setg(errp, "Zero copy not supported on this platform");
return -1;
#endif
}

Which is supposed to fail if QIO_CHANNEL_WRITE_FLAG_ZERO_COPY is specified, but
qemu does not support it at compile time.

If I get the part above correctly, it would not be necessary, as
qio_channel_socket_writev() is
called only by qio_channel_writev_full(), which tests:

if ((flags & QIO_CHANNEL_WRITE_FLAG_ZERO_COPY) &&
!qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY)) {
error_setg_errno(errp, EINVAL,
 "Requested Zero Copy feature is not available");
return -1;
}

and QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY is only set in
qio_channel_socket_connect_sync(), and is conditional to QEMU_MSG_ZEROCOPY
being enabled during compile time. Meaning it's the same test as
before mentioned, but
failing earlier.

> >  #endif
> >
> > @@ -592,15 +594,13 @@ static ssize_t qio_channel_socket_writev(QIOChannel 
> > *ioc,
> >  return QIO_CHANNEL_ERR_BLOCK;
> >  case EINTR:
> >  goto retry;
> > -#ifdef QEMU_MSG_ZEROCOPY
> >  case ENOBUFS:
> > -if (sflags & MSG_ZEROCOPY) {
> > +if (zero_copy_enabled) {
>
> if (flags & QIO_CHANNEL_WRITE_FLAG_ZERO_COPY)
>
> avoids the #ifdef without needing to add yet another
> variable expressing what's already expressed in both
> 'flags' and 'sflags'.

Yes, it does, but at the cost of not compiling-out the zero-copy part
when it's not supported,
since the QIO_CHANNEL_WRITE_FLAG_ZERO_COPY comes as a parameter. This ends up
meaning there will be at least one extra test for every time this
function is called (the one in the next patch).

An option would be testing sflags & MSG_ZEROCOPY, which would
compile-out zero-copy code
if it's not supported, but there was a bug in some distros where
MSG_ZEROCOPY is not defined,
causing the build to fail.

I understand the idea of reusing those variables instead of creating a
new one, but this boolean
variable will most certainly be compiled-out in this function, and
will allow compiling out the
zero-copy code where it's not supported.

Best regards,
Leo


>
> >  error_setg_errno(errp, errno,
> >   "Process can't lock enough memory for 
> > using MSG_ZEROCOPY");
> >  return -1;
> >  }
> >  break;
> > -#endif
> >  }
> >
> >  error_setg_errno(errp, errno,
> > --
> > 2.36.1
> >
>
> With regards,
> Daniel
> --
> |: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
> |: https://libvirt.org -o-https://fstop138.berrange.com :|
> |: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|
>




Re: [PATCH v15 4/9] linux-user: Add LoongArch syscall support

2022-06-09 Thread gaosong

Hi Xuerui.

Thanks for you comments.

On 2022/6/9 下午6:04, WANG Xuerui wrote:

On 2022/6/9 10:42, Song Gao wrote:

We should disable '__BITS_PER_LONG' at [1] before run gensyscalls.sh

  [1] arch/loongarch/include/uapi/asm/bitsperlong.h


I'm not sure why this is necessary, is this for building on 32-bit 
where __BITS_PER_LONG are (incorrectly) reflecting the host bitness?

See gensyscalls.sh  read_includes()

__BITS_PRE_LONG had been defined in  '-D__BITS_PER_LONG=${bits}' .

If this is the case, arch/riscv uses the same trick (they are defining 
__BITS_PER_LONG as (__SIZEOF_POINTER__ * 8), which is essentially the 
same), so they should fail without the hack described here as well. I 
don't know if something else could be tweaked to get rid of this hack 
(currently unable to investigate deeper for you, taking a break 
reviewing this in the middle of my day job). 


See gensyscall.sh  read_includes()

-D_UAPI_ASM_$(upper ${arch})_BITSPERLONG_H \

and kernel arch/riscv/include/uapi/asm/bitsperlong.h

#ifndef _UAPI_ASM_RISCV_BITSPERLONG_H
#define _UAPI_ASM_RISCV_BITSPERLONG_H

So riscv couldn't  get  " warning: "__BITS_PER_LONG" redefined"

For fix it ,

@@ -44,6 +46,7 @@ read_includes()

  cpp -P -nostdinc -fdirectives-only \
 -D_UAPI_ASM_$(upper ${arch})_BITSPERLONG_H \
+    -D__ASM_$(upper ${arch})_BITSPERLONG_H \
 -D__BITS_PER_LONG=${bits} \
 -I${linux}/arch/${arch}/include/uapi/ \
 -I${linux}/include/uapi \

How about this?

Thanks.
Song Gao


hw/display: Add nVidia GeForce (NV25) emulation

2022-06-09 Thread Block Roads
Hello, At least one machines, the PC (i440fx machine), have an NV25 graphic chip by default (GeForce4 Ti 4200) and It must be pbus, pcrtc, pfb, pfifo, pgraph, pmc, pramdac, and ptimer same as NV2A GPU. It must be NV25 vendor ID and device ID to 10DE:0253. But sadly, I don’t have an patch emulation of NV25 VGA chips, but QEMU devs will create NV25 emulation. It must be 2D/3D card support to play any games.



Re: [PATCH v6 0/8] KVM: mm: fd-based approach for supporting KVM guest private memory

2022-06-09 Thread Marc Orr
On Tue, Jun 7, 2022 at 7:22 PM Chao Peng  wrote:
>
> On Tue, Jun 07, 2022 at 05:55:46PM -0700, Marc Orr wrote:
> > On Tue, Jun 7, 2022 at 12:01 AM Chao Peng  
> > wrote:
> > >
> > > On Mon, Jun 06, 2022 at 01:09:50PM -0700, Vishal Annapurve wrote:
> > > > >
> > > > > Private memory map/unmap and conversion
> > > > > ---
> > > > > Userspace's map/unmap operations are done by fallocate() ioctl on the
> > > > > backing store fd.
> > > > >   - map: default fallocate() with mode=0.
> > > > >   - unmap: fallocate() with FALLOC_FL_PUNCH_HOLE.
> > > > > The map/unmap will trigger above memfile_notifier_ops to let KVM 
> > > > > map/unmap
> > > > > secondary MMU page tables.
> > > > >
> > > > 
> > > > >QEMU: https://github.com/chao-p/qemu/tree/privmem-v6
> > > > >
> > > > > An example QEMU command line for TDX test:
> > > > > -object tdx-guest,id=tdx \
> > > > > -object memory-backend-memfd-private,id=ram1,size=2G \
> > > > > -machine 
> > > > > q35,kvm-type=tdx,pic=no,kernel_irqchip=split,memory-encryption=tdx,memory-backend=ram1
> > > > >
> > > >
> > > > There should be more discussion around double allocation scenarios
> > > > when using the private fd approach. A malicious guest or buggy
> > > > userspace VMM can cause physical memory getting allocated for both
> > > > shared (memory accessible from host) and private fds backing the guest
> > > > memory.
> > > > Userspace VMM will need to unback the shared guest memory while
> > > > handling the conversion from shared to private in order to prevent
> > > > double allocation even with malicious guests or bugs in userspace VMM.
> > >
> > > I don't know how malicious guest can cause that. The initial design of
> > > this serie is to put the private/shared memory into two different
> > > address spaces and gives usersapce VMM the flexibility to convert
> > > between the two. It can choose respect the guest conversion request or
> > > not.
> >
> > For example, the guest could maliciously give a device driver a
> > private page so that a host-side virtual device will blindly write the
> > private page.
>
> With this patch series, it's actually even not possible for userspace VMM
> to allocate private page by a direct write, it's basically unmapped from
> there. If it really wants to, it should so something special, by intention,
> that's basically the conversion, which we should allow.

I think Vishal did a better job to explain this scenario in his last
reply than I did.

> > > It's possible for a usrspace VMM to cause double allocation if it fails
> > > to call the unback operation during the conversion, this may be a bug
> > > or not. Double allocation may not be a wrong thing, even in conception.
> > > At least TDX allows you to use half shared half private in guest, means
> > > both shared/private can be effective. Unbacking the memory is just the
> > > current QEMU implementation choice.
> >
> > Right. But the idea is that this patch series should accommodate all
> > of the CVM architectures. Or at least that's what I know was
> > envisioned last time we discussed this topic for SNP [*].
>
> AFAICS, this series should work for both TDX and SNP, and other CVM
> architectures. I don't see where TDX can work but SNP cannot, or I
> missed something here?

Agreed. I was just responding to the "At least TDX..." bit. Sorry for
any confusion.

> >
> > Regardless, it's important to ensure that the VM respects its memory
> > budget. For example, within Google, we run VMs inside of containers.
> > So if we double allocate we're going to OOM. This seems acceptable for
> > an early version of CVMs. But ultimately, I think we need a more
> > robust way to ensure that the VM operates within its memory container.
> > Otherwise, the OOM is going to be hard to diagnose and distinguish
> > from a real OOM.
>
> Thanks for bringing this up. But in my mind I still think userspace VMM
> can do and it's its responsibility to guarantee that, if that is hard
> required. By design, userspace VMM is the decision-maker for page
> conversion and has all the necessary information to know which page is
> shared/private. It also has the necessary knobs to allocate/free the
> physical pages for guest memory. Definitely, we should make userspace
> VMM more robust.

Vishal and Sean did a better job to articulate the concern in their
most recent replies.



Re: [PATCH] target/riscv: trans_rvv: Avoid assert for RV32 and e64

2022-06-09 Thread Alistair Francis
On Thu, Jun 9, 2022 at 9:47 AM Alistair Francis
 wrote:
>
> From: Alistair Francis 
>
> When running a 32-bit guest, with a e64 vmv.v.x and vl_eq_vlmax set to
> true the `tcg_debug_assert(vece <= MO_32)` will be triggered inside
> tcg_gen_gvec_dup_i32().
>
> This patch checks that condition and instead uses tcg_gen_gvec_dup_i64()
> is required.
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1028
> Suggested-by: Robert Bu 
> Signed-off-by: Alistair Francis 

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
>  target/riscv/insn_trans/trans_rvv.c.inc | 12 ++--
>  1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/target/riscv/insn_trans/trans_rvv.c.inc 
> b/target/riscv/insn_trans/trans_rvv.c.inc
> index 391c61fe93..6b27d8e91e 100644
> --- a/target/riscv/insn_trans/trans_rvv.c.inc
> +++ b/target/riscv/insn_trans/trans_rvv.c.inc
> @@ -2097,8 +2097,16 @@ static bool trans_vmv_v_x(DisasContext *s, arg_vmv_v_x 
> *a)
>  s1 = get_gpr(s, a->rs1, EXT_SIGN);
>
>  if (s->vl_eq_vlmax) {
> -tcg_gen_gvec_dup_tl(s->sew, vreg_ofs(s, a->rd),
> -MAXSZ(s), MAXSZ(s), s1);
> +if (get_xl(s) == MXL_RV32 && s->sew == MO_64) {
> +TCGv_i64 s1_i64 = tcg_temp_new_i64();
> +tcg_gen_ext_tl_i64(s1_i64, s1);
> +tcg_gen_gvec_dup_i64(s->sew, vreg_ofs(s, a->rd),
> + MAXSZ(s), MAXSZ(s), s1_i64);
> +tcg_temp_free_i64(s1_i64);
> +} else {
> +tcg_gen_gvec_dup_tl(s->sew, vreg_ofs(s, a->rd),
> +MAXSZ(s), MAXSZ(s), s1);
> +}
>  } else {
>  TCGv_i32 desc;
>  TCGv_i64 s1_i64 = tcg_temp_new_i64();
> --
> 2.36.1
>



Re: [PATCH v2 41/71] target/arm: Add infrastructure for disas_sme

2022-06-09 Thread Richard Henderson

On 6/9/22 08:35, Peter Maydell wrote:

+if (!disas_sme(s, insn)) {
+unallocated_encoding(s);
+}
+break;


I still think we should check bit 31 here.


We don't do anything similar over in a32, where we've done the full conversion:

if (disas_a32_uncond(s, insn) ||

disas_vfp_uncond(s, insn) ||

disas_neon_dp(s, insn) ||

disas_neon_ls(s, insn) ||

disas_neon_shared(s, insn)) {

return;

}


and there's nothing else within major opcode 0 to conflict.

But if you insist, ok.


r~



[PATCH v2 1/2] target/arm: Adjust format test in scr_write

2022-06-09 Thread Richard Henderson
Because reset always initializes the AA64 version, SCR_EL3,
test the mode of EL3 instead of the type of the cpreg.

Signed-off-by: Richard Henderson 
---
 target/arm/helper.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index ac9942d750..d6818f281a 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -1738,12 +1738,14 @@ static void scr_write(CPUARMState *env, const 
ARMCPRegInfo *ri, uint64_t value)
 uint32_t valid_mask = 0x3fff;
 ARMCPU *cpu = env_archcpu(env);
 
-if (ri->state == ARM_CP_STATE_AA64) {
-if (arm_feature(env, ARM_FEATURE_AARCH64) &&
-!cpu_isar_feature(aa64_aa32_el1, cpu)) {
-value |= SCR_FW | SCR_AW;   /* these two bits are RES1.  */
-}
-valid_mask &= ~SCR_NET;
+/*
+ * Because SCR_EL3 is the "real" cpreg and SCR is the alias, reset always
+ * passes the reginfo for SCR_EL3, which has type ARM_CP_STATE_AA64.
+ * Instead, choose the format based on the mode of EL3.
+ */
+if (arm_el_is_aa64(env, 3)) {
+value |= SCR_FW | SCR_AW;  /* RES1 */
+valid_mask &= ~SCR_NET;/* RES0 */
 
 if (cpu_isar_feature(aa64_ras, cpu)) {
 valid_mask |= SCR_TERR;
-- 
2.34.1




[PATCH v2 2/2] target/arm: SCR_EL3.RW is RAO/WI without AArch32 EL[12]

2022-06-09 Thread Richard Henderson
Since DDI0487F.a, the RW bit is RAO/WI.  When specifically
targeting such a cpu, e.g. cortex-a76, it is legitimate to
ignore the bit within the secure monitor.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1062
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h| 5 +
 target/arm/helper.c | 4 
 2 files changed, 9 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 78dbcb5592..c489519923 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3978,6 +3978,11 @@ static inline bool isar_feature_aa64_aa32_el1(const 
ARMISARegisters *id)
 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL1) >= 2;
 }
 
+static inline bool isar_feature_aa64_aa32_el2(const ARMISARegisters *id)
+{
+return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL2) >= 2;
+}
+
 static inline bool isar_feature_aa64_ras(const ARMISARegisters *id)
 {
 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) != 0;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index d6818f281a..0d1670f89b 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -1747,6 +1747,10 @@ static void scr_write(CPUARMState *env, const 
ARMCPRegInfo *ri, uint64_t value)
 value |= SCR_FW | SCR_AW;  /* RES1 */
 valid_mask &= ~SCR_NET;/* RES0 */
 
+if (!cpu_isar_feature(aa64_aa32_el1, cpu) &&
+!cpu_isar_feature(aa64_aa32_el2, cpu)) {
+value |= SCR_RW;   /* RAO/WI*/
+}
 if (cpu_isar_feature(aa64_ras, cpu)) {
 valid_mask |= SCR_TERR;
 }
-- 
2.34.1




[PATCH v2 0/2] target/arm: SCR_EL3 RES0, RAO/WI tweaks

2022-06-09 Thread Richard Henderson
Adjust RW, fixing #1062, and adjusting bits [4:2].

Changes for v2:
  * Fix patch 1 vs reset.


r~

Richard Henderson (2):
  target/arm: Adjust format test in scr_write
  target/arm: SCR_EL3.RW is RAO/WI without AArch32 EL[12]

 target/arm/cpu.h|  5 +
 target/arm/helper.c | 18 --
 2 files changed, 17 insertions(+), 6 deletions(-)

-- 
2.34.1




[PATCH] tests/qtest: Reduce npcm7xx_sdhci test image size

2022-06-09 Thread Hao Wu
Creating 1GB image for a simple qtest is unnecessary
and could lead to failures. We reduce the image size
to 1MB to reduce the test overhead.

Signed-off-by: Hao Wu 
---
 tests/qtest/npcm7xx_sdhci-test.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/qtest/npcm7xx_sdhci-test.c b/tests/qtest/npcm7xx_sdhci-test.c
index aa35a77e8d..5d68540e52 100644
--- a/tests/qtest/npcm7xx_sdhci-test.c
+++ b/tests/qtest/npcm7xx_sdhci-test.c
@@ -24,7 +24,7 @@
 #define NPCM7XX_REG_SIZE 0x100
 #define NPCM7XX_MMC_BA 0xF0842000
 #define NPCM7XX_BLK_SIZE 512
-#define NPCM7XX_TEST_IMAGE_SIZE (1 << 30)
+#define NPCM7XX_TEST_IMAGE_SIZE (1 << 20)
 
 char *sd_path;
 
-- 
2.36.1.476.g0c4daa206d-goog




Re: [PATCH v5] tests/qtest: add qtests for npcm7xx sdhci

2022-06-09 Thread Hao Wu
Hi,

We did some experiments on this issue. It looks like the image size
restriction is in firmware. So in qtest we can make it
much smaller (e.g. 1MB) and the test still passes. We can send a patch with
this change if necessary.

On Thu, May 26, 2022 at 9:21 AM Patrick Venture  wrote:

>
>
> On Thu, May 26, 2022 at 8:54 AM Peter Maydell 
> wrote:
>
>> On Fri, 25 Feb 2022 at 17:45, Hao Wu  wrote:
>> >
>> > From: Shengtan Mao 
>> >
>> > Reviewed-by: Hao Wu 
>> > Reviewed-by: Chris Rauer 
>> > Signed-off-by: Shengtan Mao 
>> > Signed-off-by: Patrick Venture 
>>
>> Hi; John Snow tells me that this test fails in the tests/vm/netbsd
>> VM (you can test this with 'make vm-build-netbsd') because the
>> assert() on the ftruncate() call fails:
>>
>> > +ret = ftruncate(fd, NPCM7XX_TEST_IMAGE_SIZE);
>> > +g_assert_cmpint(ret, ==, 0);
>>
>> > +#define NPCM7XX_TEST_IMAGE_SIZE (1 << 30)
>>
>> I haven't investigated the exact cause, but this is a
>> gigabyte, right? That's a pretty massive file for a test case to
>> create -- can we make the test use a more sensible size of
>> sd card image ?
>>
>
> It looks like the nuvoton part had an issue with a smaller image size, but
> we can resurrect that thread and poke at it a bit and see what shakes out.
>
>
>>
>> thanks
>> -- PMM
>>
>


[PATCH v3 22/23] target/arm: Move arm_debug_target_el to debug_helper.c

2022-06-09 Thread Richard Henderson
This function is no longer used outside debug_helper.c.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h  | 21 -
 target/arm/debug_helper.c | 21 +
 2 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 719613ad9e..161ac9fa2e 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2986,27 +2986,6 @@ typedef enum ARMASIdx {
 ARMASIdx_TagS = 3,
 } ARMASIdx;
 
-/* Return the Exception Level targeted by debug exceptions. */
-static inline int arm_debug_target_el(CPUARMState *env)
-{
-bool secure = arm_is_secure(env);
-bool route_to_el2 = false;
-
-if (arm_is_el2_enabled(env)) {
-route_to_el2 = env->cp15.hcr_el2 & HCR_TGE ||
-   env->cp15.mdcr_el2 & MDCR_TDE;
-}
-
-if (route_to_el2) {
-return 2;
-} else if (arm_feature(env, ARM_FEATURE_EL3) &&
-   !arm_el_is_aa64(env, 3) && secure) {
-return 3;
-} else {
-return 1;
-}
-}
-
 static inline bool arm_v7m_csselr_razwi(ARMCPU *cpu)
 {
 /* If all the CLIDR.Ctypem bits are 0 there are no caches, and
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index 26004df99b..b18a6bd3a2 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -12,6 +12,27 @@
 #include "exec/helper-proto.h"
 
 
+/* Return the Exception Level targeted by debug exceptions. */
+static int arm_debug_target_el(CPUARMState *env)
+{
+bool secure = arm_is_secure(env);
+bool route_to_el2 = false;
+
+if (arm_is_el2_enabled(env)) {
+route_to_el2 = env->cp15.hcr_el2 & HCR_TGE ||
+   env->cp15.mdcr_el2 & MDCR_TDE;
+}
+
+if (route_to_el2) {
+return 2;
+} else if (arm_feature(env, ARM_FEATURE_EL3) &&
+   !arm_el_is_aa64(env, 3) && secure) {
+return 3;
+} else {
+return 1;
+}
+}
+
 /*
  * Raise an exception to the debug target el.
  * Modify syndrome to indicate when origin and target EL are the same.
-- 
2.34.1




[PATCH v3 17/23] target/arm: Introduce gen_exception

2022-06-09 Thread Richard Henderson
Create a new wrapper function that passes the default
exception target to gen_exception_el.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index edb7d3f394..5a48937ede 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1093,6 +1093,11 @@ static void gen_exception_el(int excp, uint32_t 
syndrome, uint32_t target_el)
   tcg_constant_i32(target_el));
 }
 
+static void gen_exception(DisasContext *s, int excp, uint32_t syndrome)
+{
+gen_exception_el(excp, syndrome, default_exception_el(s));
+}
+
 static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp,
 uint32_t syn, TCGv_i32 tcg_el)
 {
@@ -9758,8 +9763,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cpu)
 switch (dc->base.is_jmp) {
 case DISAS_SWI:
 gen_ss_advance(dc);
-gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
- default_exception_el(dc));
+gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
 break;
 case DISAS_HVC:
 gen_ss_advance(dc);
@@ -9828,8 +9832,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cpu)
 gen_helper_yield(cpu_env);
 break;
 case DISAS_SWI:
-gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
- default_exception_el(dc));
+gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
 break;
 case DISAS_HVC:
 gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
-- 
2.34.1




[PATCH v3 16/23] target/arm: Rename gen_exception to gen_exception_el

2022-06-09 Thread Richard Henderson
Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index fc5eafaeeb..edb7d3f394 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1086,7 +1086,7 @@ static void gen_exception_internal_insn(DisasContext *s, 
uint32_t pc, int excp)
 s->base.is_jmp = DISAS_NORETURN;
 }
 
-static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
+static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el)
 {
 gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
   tcg_constant_i32(syndrome),
@@ -9758,16 +9758,16 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cpu)
 switch (dc->base.is_jmp) {
 case DISAS_SWI:
 gen_ss_advance(dc);
-gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
-  default_exception_el(dc));
+gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
+ default_exception_el(dc));
 break;
 case DISAS_HVC:
 gen_ss_advance(dc);
-gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
+gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
 break;
 case DISAS_SMC:
 gen_ss_advance(dc);
-gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
+gen_exception_el(EXCP_SMC, syn_aa32_smc(), 3);
 break;
 case DISAS_NEXT:
 case DISAS_TOO_MANY:
@@ -9828,14 +9828,14 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cpu)
 gen_helper_yield(cpu_env);
 break;
 case DISAS_SWI:
-gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
-  default_exception_el(dc));
+gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
+ default_exception_el(dc));
 break;
 case DISAS_HVC:
-gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
+gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
 break;
 case DISAS_SMC:
-gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
+gen_exception_el(EXCP_SMC, syn_aa32_smc(), 3);
 break;
 }
 }
-- 
2.34.1




Re: [RFC PATCH v2 2/8] qapi: net: introduce a way to bypass qemu_opts_parse_noisily()

2022-06-09 Thread Laurent Vivier

On 13/05/2022 13:21, Markus Armbruster wrote:

Laurent Vivier  writes:


As qemu_opts_parse_noisily() flattens the QAPI structures ("type" field
of Netdev structure can collides with "type" field of SocketAddress),


To remember how this works, I have to write a more verbose version of
the above.  Why not post it then, so here goes.

qemu_init() passes the argument of -netdev, -nic, and -net to
net_client_parse().

net_client_parse() parses with qemu_opts_parse_noisily(), passing
QemuOptsList qemu_netdev_opts for -netdev, qemu_nic_opts for -nic, and
qemu_net_opts for -net.  Their desc[] are all empty, which means any
keys are accepted.  The result of the parse (a QemuOpts) is stored in
the QemuOptsList.

Note that QemuOpts is flat by design.  In some places, we layer non-flat
on top using dotted keys convention, but not here.

net_init_clients() iterates over the stored QemuOpts, and passes them to
net_init_netdev(), net_param_nic(), or net_init_client(), respectively.

These functions pass the QemuOpts to net_client_init().  They also do
other things with the QemuOpts, which we can ignore here.

net_client_init() uses the opts visitor to convert the (flat) QemOpts to
a (non-flat) QAPI object Netdev.  Netdev is also the argument of QMP
command netdev_add.

The opts visitor was an early attempt to support QAPI in
(QemuOpts-based) CLI.  It restricts QAPI types to a certain shape; see
commit eb7ee2cbeb "qapi: introduce OptsVisitor".

A more modern way to support QAPI is qobject_input_visitor_new_str().
It uses keyval_parse() instead of QemuOpts for KEY=VALUE,... syntax, and
it also supports JSON syntax.  The former isn't quite as expressive as
JSON, but it's a lot closer than QemuOpts + opts visitor.


we introduce a way to bypass qemu_opts_parse_noisily() and use directly
visit_type_Netdev() to parse the backend parameters.


This commit paves the way to use of the modern way instead.


I'm going to copy your analysis to the commit message of the patch.




Signed-off-by: Laurent Vivier 
---
  net/net.c | 54 ++
  1 file changed, 54 insertions(+)

diff --git a/net/net.c b/net/net.c
index 58c05c200622..2aab7167316c 100644
--- a/net/net.c
+++ b/net/net.c
@@ -54,6 +54,7 @@
  #include "net/colo-compare.h"
  #include "net/filter.h"
  #include "qapi/string-output-visitor.h"
+#include "qapi/qobject-input-visitor.h"
  
  /* Net bridge is currently not supported for W32. */

  #if !defined(_WIN32)
@@ -63,6 +64,17 @@
  static VMChangeStateEntry *net_change_state_entry;
  static QTAILQ_HEAD(, NetClientState) net_clients;
  
+typedef struct NetdevQueueEntry {

+bool is_netdev;
+Netdev *nd;
+Location loc;
+QSIMPLEQ_ENTRY(NetdevQueueEntry) entry;
+} NetdevQueueEntry;
+
+typedef QSIMPLEQ_HEAD(, NetdevQueueEntry) NetdevQueue;
+
+static NetdevQueue nd_queue = QSIMPLEQ_HEAD_INITIALIZER(nd_queue);
+
  /***/
  /* network device redirectors */
  
@@ -1559,6 +1571,19 @@ int net_init_clients(Error **errp)
  
  QTAILQ_INIT(_clients);
  
+while (!QSIMPLEQ_EMPTY(_queue)) {

+NetdevQueueEntry *nd = QSIMPLEQ_FIRST(_queue);
+
+QSIMPLEQ_REMOVE_HEAD(_queue, entry);
+loc_push_restore(>loc);
+if (net_client_init1(nd->nd, nd->is_netdev, errp) < 0) {


I think you need to loc_pop() here.


+return -1;
+}


Since the only caller passes _fatal, I'd be tempted to ditch the
@errp argument, and simply do

net_client_init1(nd->nd, nd->is_netdev, _fatal);

It's what we do for -blockdev, -device, and -object.


I've added a patch to remove the @errp from the net_init_clients() arguments.




+loc_pop(>loc);
+qapi_free_Netdev(nd->nd);
+g_free(nd);
+}
+
  if (qemu_opts_foreach(qemu_find_opts("netdev"),
net_init_netdev, NULL, errp)) {
  return -1;
@@ -1575,8 +1600,37 @@ int net_init_clients(Error **errp)
  return 0;
  }
  
+/*

+ * netdev_is_modern() returns true when the backend needs to bypass
+ * qemu_opts_parse_noisily()
+ */
+static bool netdev_is_modern(const char *optarg)
+{
+return false;
+}
+
  int net_client_parse(QemuOptsList *opts_list, const char *optarg)
  {
+if (netdev_is_modern(optarg)) {
+/*
+ * We need to bypass qemu_opts_parse_noisily() to accept
+ * new style object like addr.type=inet in SocketAddress
+ */


I'm not sure this will makes sense to future readers.

What about "Use modern, more expressive syntax"?


Done.




+Visitor *v;
+NetdevQueueEntry *nd;
+
+v = qobject_input_visitor_new_str(optarg, "type",
+  _fatal);
+nd = g_new(NetdevQueueEntry, 1);
+visit_type_Netdev(v, NULL, >nd, _fatal);
+visit_free(v);
+loc_save(>loc);
+nd->is_netdev = strcmp(opts_list->name, 

[PATCH v3 18/23] target/arm: Introduce gen_exception_el_v

2022-06-09 Thread Richard Henderson
Split out a common helper function for gen_exception_el
and gen_exception_insn_el_v.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 5a48937ede..fcb6ee648b 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1086,11 +1086,15 @@ static void gen_exception_internal_insn(DisasContext 
*s, uint32_t pc, int excp)
 s->base.is_jmp = DISAS_NORETURN;
 }
 
-static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el)
+static void gen_exception_el_v(int excp, uint32_t syndrome, TCGv_i32 tcg_el)
 {
 gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
-  tcg_constant_i32(syndrome),
-  tcg_constant_i32(target_el));
+  tcg_constant_i32(syndrome), tcg_el);
+}
+
+static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el)
+{
+gen_exception_el_v(excp, syndrome, tcg_constant_i32(target_el));
 }
 
 static void gen_exception(DisasContext *s, int excp, uint32_t syndrome)
@@ -1107,8 +,7 @@ static void gen_exception_insn_el_v(DisasContext *s, 
uint64_t pc, int excp,
 gen_set_condexec(s);
 gen_set_pc_im(s, pc);
 }
-gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
-  tcg_constant_i32(syn), tcg_el);
+gen_exception_el_v(excp, syn, tcg_el);
 s->base.is_jmp = DISAS_NORETURN;
 }
 
-- 
2.34.1




[PATCH v3 21/23] target/arm: Create raise_exception_debug

2022-06-09 Thread Richard Henderson
Handle the debug vs current el exception test in one place.
Leave EXCP_BKPT alone, since that treats debug < current differently.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/debug_helper.c | 44 +--
 1 file changed, 24 insertions(+), 20 deletions(-)

diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index a3a1b98de2..26004df99b 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -12,6 +12,26 @@
 #include "exec/helper-proto.h"
 
 
+/*
+ * Raise an exception to the debug target el.
+ * Modify syndrome to indicate when origin and target EL are the same.
+ */
+G_NORETURN static void
+raise_exception_debug(CPUARMState *env, uint32_t excp, uint32_t syndrome)
+{
+int debug_el = arm_debug_target_el(env);
+int cur_el = arm_current_el(env);
+
+/*
+ * If singlestep is targeting a lower EL than the current one, then
+ * DisasContext.ss_active must be false and we can never get here.
+ * Similarly for watchpoint and breakpoint matches.
+ */
+assert(debug_el >= cur_el);
+syndrome |= (debug_el == cur_el) << ARM_EL_EC_SHIFT;
+raise_exception(env, excp, syndrome, debug_el);
+}
+
 /* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */
 static bool aa64_generate_debug_exceptions(CPUARMState *env)
 {
@@ -418,19 +438,16 @@ void arm_debug_excp_handler(CPUState *cs)
 if (wp_hit) {
 if (wp_hit->flags & BP_CPU) {
 bool wnr = (wp_hit->flags & BP_WATCHPOINT_HIT_WRITE) != 0;
-bool same_el = arm_debug_target_el(env) == arm_current_el(env);
 
 cs->watchpoint_hit = NULL;
 
 env->exception.fsr = arm_debug_exception_fsr(env);
 env->exception.vaddress = wp_hit->hitaddr;
-raise_exception(env, EXCP_DATA_ABORT,
-syn_watchpoint(same_el, 0, wnr),
-arm_debug_target_el(env));
+raise_exception_debug(env, EXCP_DATA_ABORT,
+  syn_watchpoint(0, 0, wnr));
 }
 } else {
 uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
-bool same_el = (arm_debug_target_el(env) == arm_current_el(env));
 
 /*
  * (1) GDB breakpoints should be handled first.
@@ -450,9 +467,7 @@ void arm_debug_excp_handler(CPUState *cs)
  * exception/security level.
  */
 env->exception.vaddress = 0;
-raise_exception(env, EXCP_PREFETCH_ABORT,
-syn_breakpoint(same_el),
-arm_debug_target_el(env));
+raise_exception_debug(env, EXCP_PREFETCH_ABORT, syn_breakpoint(0));
 }
 }
 
@@ -489,18 +504,7 @@ void HELPER(exception_bkpt_insn)(CPUARMState *env, 
uint32_t syndrome)
 
 void HELPER(exception_swstep)(CPUARMState *env, uint32_t syndrome)
 {
-int debug_el = arm_debug_target_el(env);
-int cur_el = arm_current_el(env);
-
-/*
- * If singlestep is targeting a lower EL than the current one, then
- * DisasContext.ss_active must be false and we can never get here.
- */
-assert(debug_el >= cur_el);
-if (debug_el == cur_el) {
-syndrome |= 1 << ARM_EL_EC_SHIFT;
-}
-raise_exception(env, EXCP_UDEF, syndrome, debug_el);
+raise_exception_debug(env, EXCP_UDEF, syndrome);
 }
 
 #if !defined(CONFIG_USER_ONLY)
-- 
2.34.1




[PATCH v3 15/23] target/arm: Move gen_exception to translate.c

2022-06-09 Thread Richard Henderson
This function is not required by any other translation file.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/translate.h | 8 
 target/arm/translate.c | 7 +++
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/target/arm/translate.h b/target/arm/translate.h
index 8685f55e80..850bcdc155 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -328,14 +328,6 @@ static inline void gen_ss_advance(DisasContext *s)
 }
 }
 
-static inline void gen_exception(int excp, uint32_t syndrome,
- uint32_t target_el)
-{
-gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
-  tcg_constant_i32(syndrome),
-  tcg_constant_i32(target_el));
-}
-
 /* Generate an architectural singlestep exception */
 static inline void gen_swstep_exception(DisasContext *s, int isv, int ex)
 {
diff --git a/target/arm/translate.c b/target/arm/translate.c
index b8a8972bac..fc5eafaeeb 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1086,6 +1086,13 @@ static void gen_exception_internal_insn(DisasContext *s, 
uint32_t pc, int excp)
 s->base.is_jmp = DISAS_NORETURN;
 }
 
+static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
+{
+gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
+  tcg_constant_i32(syndrome),
+  tcg_constant_i32(target_el));
+}
+
 static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp,
 uint32_t syn, TCGv_i32 tcg_el)
 {
-- 
2.34.1




[PATCH v3 20/23] target/arm: Remove default_exception_el

2022-06-09 Thread Richard Henderson
This function is no longer used.  At the same time, remove
DisasContext.secure_routed_to_el3, as it in turn becomes unused.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/translate.h | 16 
 target/arm/translate-a64.c |  5 -
 target/arm/translate.c |  5 -
 3 files changed, 26 deletions(-)

diff --git a/target/arm/translate.h b/target/arm/translate.h
index 850bcdc155..88dc18a034 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -43,8 +43,6 @@ typedef struct DisasContext {
 int fp_excp_el; /* FP exception EL or 0 if enabled */
 int sve_excp_el; /* SVE exception EL or 0 if enabled */
 int vl;  /* current vector length in bytes */
-/* Flag indicating that exceptions from secure mode are routed to EL3. */
-bool secure_routed_to_el3;
 bool vfp_enabled; /* FP enabled via FPSCR.EN */
 int vec_len;
 int vec_stride;
@@ -199,20 +197,6 @@ static inline int get_mem_index(DisasContext *s)
 return arm_to_core_mmu_idx(s->mmu_idx);
 }
 
-/* Function used to determine the target exception EL when otherwise not known
- * or default.
- */
-static inline int default_exception_el(DisasContext *s)
-{
-/* If we are coming from secure EL0 in a system with a 32-bit EL3, then
- * there is no secure EL1, so we route exceptions to EL3.  Otherwise,
- * exceptions can only be routed to ELs above 1, so we target the higher of
- * 1 or the current EL.
- */
-return (s->mmu_idx == ARMMMUIdx_SE10_0 && s->secure_routed_to_el3)
-? 3 : MAX(1, s->current_el);
-}
-
 static inline void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
 {
 /* We don't need to save all of the syndrome so we mask and shift
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 4f6181a548..4c64546090 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -14585,11 +14585,6 @@ static void 
aarch64_tr_init_disas_context(DisasContextBase *dcbase,
 dc->condjmp = 0;
 
 dc->aarch64 = true;
-/* If we are coming from secure EL0 in a system with a 32-bit EL3, then
- * there is no secure EL1, so we route exceptions to EL3.
- */
-dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
-   !arm_el_is_aa64(env, 3);
 dc->thumb = false;
 dc->sctlr_b = 0;
 dc->be_data = EX_TBFLAG_ANY(tb_flags, BE_DATA) ? MO_BE : MO_LE;
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 81c27e7c70..6617de775f 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -9319,11 +9319,6 @@ static void arm_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 dc->condjmp = 0;
 
 dc->aarch64 = false;
-/* If we are coming from secure EL0 in a system with a 32-bit EL3, then
- * there is no secure EL1, so we route exceptions to EL3.
- */
-dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
-   !arm_el_is_aa64(env, 3);
 dc->thumb = EX_TBFLAG_AM32(tb_flags, THUMB);
 dc->be_data = EX_TBFLAG_ANY(tb_flags, BE_DATA) ? MO_BE : MO_LE;
 condexec = EX_TBFLAG_AM32(tb_flags, CONDEXEC);
-- 
2.34.1




Re: [PATCH v6 0/8] KVM: mm: fd-based approach for supporting KVM guest private memory

2022-06-09 Thread Sean Christopherson
On Wed, Jun 08, 2022, Vishal Annapurve wrote:
> ...
> > With this patch series, it's actually even not possible for userspace VMM
> > to allocate private page by a direct write, it's basically unmapped from
> > there. If it really wants to, it should so something special, by intention,
> > that's basically the conversion, which we should allow.
> >
> 
> A VM can pass GPA backed by private pages to userspace VMM and when
> Userspace VMM accesses the backing hva there will be pages allocated
> to back the shared fd causing 2 sets of pages backing the same guest
> memory range.
> 
> > Thanks for bringing this up. But in my mind I still think userspace VMM
> > can do and it's its responsibility to guarantee that, if that is hard
> > required.

That was my initial reaction too, but there are unfortunate side effects to 
punting
this to userspace. 

> By design, userspace VMM is the decision-maker for page
> > conversion and has all the necessary information to know which page is
> > shared/private. It also has the necessary knobs to allocate/free the
> > physical pages for guest memory. Definitely, we should make userspace
> > VMM more robust.
> 
> Making Userspace VMM more robust to avoid double allocation can get
> complex, it will have to keep track of all in-use (by Userspace VMM)
> shared fd memory to disallow conversion from shared to private and
> will have to ensure that all guest supplied addresses belong to shared
> GPA ranges.

IMO, the complexity argument isn't sufficient justfication for introducing new
kernel functionality.  If multiple processes are accessing guest memory then 
there
already needs to be some amount of coordination, i.e. it can't be _that_ 
complex.

My concern with forcing userspace to fully handle unmapping shared memory is 
that
it may lead to additional performance overhead and/or noisy neighbor issues, 
even
if all guests are well-behaved.

Unnmapping arbitrary ranges will fragment the virtual address space and consume
more memory for all the result VMAs.  The extra memory consumption isn't that 
big
of a deal, and it will be self-healing to some extent as VMAs will get merged 
when
the holes are filled back in (if the guest converts back to shared), but it's 
still
less than desirable.

More concerning is having to take mmap_lock for write for every conversion, 
which
is very problematic for configurations where a single userspace process maps 
memory
belong to multiple VMs.  Unmapping and remapping on every conversion will 
create a
bottleneck, especially if a VM has sub-optimal behavior and is converting pages 
at
a high rate.

One argument is that userspace can simply rely on cgroups to detect misbehaving
guests, but (a) those types of OOMs will be a nightmare to debug and (b) an OOM
kill from the host is typically considered a _host_ issue and will be treated as
a missed SLO.

An idea for handling this in the kernel without too much complexity would be to
add F_SEAL_FAULT_ALLOCATIONS (terrible name) that would prevent page faults from
allocating pages, i.e. holes can only be filled by an explicit fallocate().  
Minor
faults, e.g. due to NUMA balancing stupidity, and major faults due to swap would
still work, but writes to previously unreserved/unallocated memory would get a
SIGSEGV on something it has mapped.  That would allow the userspace VMM to 
prevent
unintentional allocations without having to coordinate unmapping/remapping 
across
multiple processes.



[PATCH v3 23/23] target/arm: Fix Secure PL1 tests in fp_exception_el

2022-06-09 Thread Richard Henderson
We were using arm_is_secure and is_a64, which are
tests against the current EL, as opposed to
arm_el_is_aa64 and arm_is_secure_below_el3, which
can be applied to a different EL than current.
Consolidate the two tests.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/helper.c | 23 +--
 1 file changed, 9 insertions(+), 14 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 2b2c1998fd..b95aa53474 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -10879,27 +10879,22 @@ int fp_exception_el(CPUARMState *env, int cur_el)
 int fpen = FIELD_EX64(env->cp15.cpacr_el1, CPACR_EL1, FPEN);
 
 switch (fpen) {
+case 1:
+if (cur_el != 0) {
+break;
+}
+/* fall through */
 case 0:
 case 2:
-if (cur_el == 0 || cur_el == 1) {
-/* Trap to PL1, which might be EL1 or EL3 */
-if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
-return 3;
-}
-return 1;
-}
-if (cur_el == 3 && !is_a64(env)) {
-/* Secure PL1 running at EL3 */
+/* Trap from Secure PL0 or PL1 to Secure PL1. */
+if (!arm_el_is_aa64(env, 3)
+&& (cur_el == 3 || arm_is_secure_below_el3(env))) {
 return 3;
 }
-break;
-case 1:
-if (cur_el == 0) {
+if (cur_el <= 1) {
 return 1;
 }
 break;
-case 3:
-break;
 }
 }
 
-- 
2.34.1




[PATCH v3 19/23] target/arm: Introduce helper_exception_with_syndrome

2022-06-09 Thread Richard Henderson
With the helper we can use exception_target_el at runtime,
instead of default_exception_el at translate time.
While we're at it, remove the DisasContext parameter from
gen_exception, as it is no longer used.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/helper.h|  1 +
 target/arm/op_helper.c | 10 ++
 target/arm/translate.c | 18 +-
 3 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/target/arm/helper.h b/target/arm/helper.h
index db7447d233..07d45faf49 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -45,6 +45,7 @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32)
 DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
i32, i32, i32, i32)
 DEF_HELPER_2(exception_internal, noreturn, env, i32)
+DEF_HELPER_3(exception_with_syndrome, noreturn, env, i32, i32)
 DEF_HELPER_4(exception_with_syndrome_el, noreturn, env, i32, i32, i32)
 DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32)
 DEF_HELPER_2(exception_swstep, noreturn, env, i32)
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 8a6a3b8551..c5bde1cfcc 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -399,6 +399,16 @@ void HELPER(exception_with_syndrome_el)(CPUARMState *env, 
uint32_t excp,
 raise_exception(env, excp, syndrome, target_el);
 }
 
+/*
+ * Raise an exception with the specified syndrome register value
+ * to the default target el.
+ */
+void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp,
+ uint32_t syndrome)
+{
+raise_exception(env, excp, syndrome, exception_target_el(env));
+}
+
 uint32_t HELPER(cpsr_read)(CPUARMState *env)
 {
 return cpsr_read(env) & ~CPSR_EXEC;
diff --git a/target/arm/translate.c b/target/arm/translate.c
index fcb6ee648b..81c27e7c70 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1097,9 +1097,10 @@ static void gen_exception_el(int excp, uint32_t 
syndrome, uint32_t target_el)
 gen_exception_el_v(excp, syndrome, tcg_constant_i32(target_el));
 }
 
-static void gen_exception(DisasContext *s, int excp, uint32_t syndrome)
+static void gen_exception(int excp, uint32_t syndrome)
 {
-gen_exception_el(excp, syndrome, default_exception_el(s));
+gen_helper_exception_with_syndrome(cpu_env, tcg_constant_i32(excp),
+   tcg_constant_i32(syndrome));
 }
 
 static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp,
@@ -1123,7 +1124,14 @@ void gen_exception_insn_el(DisasContext *s, uint64_t pc, 
int excp,
 
 void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn)
 {
-gen_exception_insn_el(s, pc, excp, syn, default_exception_el(s));
+if (s->aarch64) {
+gen_a64_set_pc_im(pc);
+} else {
+gen_set_condexec(s);
+gen_set_pc_im(s, pc);
+}
+gen_exception(excp, syn);
+s->base.is_jmp = DISAS_NORETURN;
 }
 
 static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
@@ -9766,7 +9774,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cpu)
 switch (dc->base.is_jmp) {
 case DISAS_SWI:
 gen_ss_advance(dc);
-gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
+gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
 break;
 case DISAS_HVC:
 gen_ss_advance(dc);
@@ -9835,7 +9843,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cpu)
 gen_helper_yield(cpu_env);
 break;
 case DISAS_SWI:
-gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
+gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
 break;
 case DISAS_HVC:
 gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
-- 
2.34.1




Re: [PATCH RFC 4/5] cpu: Allow cpu_synchronize_all_post_init() to take an errp

2022-06-09 Thread Peter Xu
On Wed, Jun 08, 2022 at 06:05:28PM +0100, Dr. David Alan Gilbert wrote:
> > @@ -2005,7 +2005,17 @@ static void loadvm_postcopy_handle_run_bh(void 
> > *opaque)
> >  /* TODO we should move all of this lot into postcopy_ram.c or a shared 
> > code
> >   * in migration.c
> >   */
> > -cpu_synchronize_all_post_init();
> > +cpu_synchronize_all_post_init(_err);
> > +if (local_err) {
> > +/*
> > + * TODO: a better way to do this is to tell the src that we cannot
> > + * run the VM here so hopefully we can keep the VM running on src
> > + * and immediately halt the switch-over.  But that needs work.
> 
> Yes, I think it is possible; unlike some of the later errors in the same
> function, in this case we know no disks/network/etc have been touched,
> so we should be able to recover.
> I wonder if we can move the postcopy_state_set(POSTCOPY_INCOMING_RUNNING)
> out of loadvm_postcopy_handle_run to after this point.
> 
> We've already got the return path, so we should be able to signal the
> failure unless we're very unlucky.

Right.  It's just that for the new ACK we may need to modify the return
path protocol for sure, because none of the existing ones can notify such
an information.

One idea is to reuse MIG_RP_MSG_RESUME_ACK, it was only used for postcopy
recovery before to do the final handshake with offload=1 only (which is
defined as MIGRATION_RESUME_ACK_VALUE).  We could try to fill in the
payload with some !1 value, to tell the source that we NACK the migration
then src fails the migration as long as possible?

That seems to be even compatibile with one old qemu migrating to a new qemu
scenario, because when the old qemu notices the MIG_RP_MSG_RESUME_ACK
message with !1 payload, it'll mark the rp bad:

  if (migrate_handle_rp_resume_ack(ms, tmp32)) {
  mark_source_rp_bad(ms);
  goto out;
  }

  static int migrate_handle_rp_resume_ack(MigrationState *s, uint32_t value)
  {
  trace_source_return_path_thread_resume_ack(value);
  
  if (value != MIGRATION_RESUME_ACK_VALUE) {
  error_report("%s: illegal resume_ack value %"PRIu32,
   __func__, value);
  return -1;
  }
  ...
  }

If it looks generally good, I can try with such a change in v2.

Thanks,

-- 
Peter Xu




[PATCH v3 08/23] target/arm: Move arm_debug_exception_fsr to debug_helper.c

2022-06-09 Thread Richard Henderson
This function now now only used in debug_helper.c, so there is
no reason to have a declaration in a header.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/internals.h| 25 -
 target/arm/debug_helper.c | 26 ++
 2 files changed, 26 insertions(+), 25 deletions(-)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index 02fa70f75a..6f94f3019d 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -793,31 +793,6 @@ static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx 
mmu_idx)
 return >cp15.tcr_el[regime_el(env, mmu_idx)];
 }
 
-/* Return the FSR value for a debug exception (watchpoint, hardware
- * breakpoint or BKPT insn) targeting the specified exception level.
- */
-static inline uint32_t arm_debug_exception_fsr(CPUARMState *env)
-{
-ARMMMUFaultInfo fi = { .type = ARMFault_Debug };
-int target_el = arm_debug_target_el(env);
-bool using_lpae = false;
-
-if (target_el == 2 || arm_el_is_aa64(env, target_el)) {
-using_lpae = true;
-} else {
-if (arm_feature(env, ARM_FEATURE_LPAE) &&
-(env->cp15.tcr_el[target_el].raw_tcr & TTBCR_EAE)) {
-using_lpae = true;
-}
-}
-
-if (using_lpae) {
-return arm_fi_to_lfsc();
-} else {
-return arm_fi_to_sfsc();
-}
-}
-
 /**
  * arm_num_brps: Return number of implemented breakpoints.
  * Note that the ID register BRPS field is "number of bps - 1",
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index 80dff0788b..a743061e89 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -379,6 +379,32 @@ bool arm_debug_check_watchpoint(CPUState *cs, 
CPUWatchpoint *wp)
 return check_watchpoints(cpu);
 }
 
+/*
+ * Return the FSR value for a debug exception (watchpoint, hardware
+ * breakpoint or BKPT insn) targeting the specified exception level.
+ */
+static uint32_t arm_debug_exception_fsr(CPUARMState *env)
+{
+ARMMMUFaultInfo fi = { .type = ARMFault_Debug };
+int target_el = arm_debug_target_el(env);
+bool using_lpae = false;
+
+if (target_el == 2 || arm_el_is_aa64(env, target_el)) {
+using_lpae = true;
+} else {
+if (arm_feature(env, ARM_FEATURE_LPAE) &&
+(env->cp15.tcr_el[target_el].raw_tcr & TTBCR_EAE)) {
+using_lpae = true;
+}
+}
+
+if (using_lpae) {
+return arm_fi_to_lfsc();
+} else {
+return arm_fi_to_sfsc();
+}
+}
+
 void arm_debug_excp_handler(CPUState *cs)
 {
 /*
-- 
2.34.1




[PATCH v3 12/23] target/arm: Introduce gen_exception_insn

2022-06-09 Thread Richard Henderson
Create a new wrapper function that passes the default
exception target to gen_exception_insn_el.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/translate.h|  1 +
 target/arm/translate-a64.c| 15 ++-
 target/arm/translate-m-nocp.c |  3 +--
 target/arm/translate-mve.c|  3 +--
 target/arm/translate.c| 29 +
 5 files changed, 22 insertions(+), 29 deletions(-)

diff --git a/target/arm/translate.h b/target/arm/translate.h
index 9ae76535ad..4575af6e1c 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -281,6 +281,7 @@ MemOp pow2_align(unsigned i);
 void unallocated_encoding(DisasContext *s);
 void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp,
uint32_t syn, uint32_t target_el);
+void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn);
 
 /* Return state of Alternate Half-precision flag, caller frees result */
 static inline TCGv_i32 get_ahp_flag(void)
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 14bc80dba0..0581118f56 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1816,8 +1816,7 @@ static void gen_sysreg_undef(DisasContext *s, bool isread,
 } else {
 syndrome = syn_uncategorized();
 }
-gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syndrome,
-  default_exception_el(s));
+gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syndrome);
 }
 
 /* MRS - move from system register
@@ -2069,8 +2068,8 @@ static void disas_exc(DisasContext *s, uint32_t insn)
 switch (op2_ll) {
 case 1: /* SVC */
 gen_ss_advance(s);
-gen_exception_insn_el(s, s->base.pc_next, EXCP_SWI,
-  syn_aa64_svc(imm16), 
default_exception_el(s));
+gen_exception_insn(s, s->base.pc_next, EXCP_SWI,
+   syn_aa64_svc(imm16));
 break;
 case 2: /* HVC */
 if (s->current_el == 0) {
@@ -14725,8 +14724,7 @@ static void aarch64_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cpu)
  * Illegal execution state. This has priority over BTI
  * exceptions, but comes after instruction abort exceptions.
  */
-gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
-  syn_illegalstate(), default_exception_el(s));
+gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_illegalstate());
 return;
 }
 
@@ -14757,9 +14755,8 @@ static void aarch64_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cpu)
 if (s->btype != 0
 && s->guarded_page
 && !btype_destination_ok(insn, s->bt, s->btype)) {
-gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
-  syn_btitrap(s->btype),
-  default_exception_el(s));
+gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
+   syn_btitrap(s->btype));
 return;
 }
 } else {
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
index 636bfb1788..4029d7fdd4 100644
--- a/target/arm/translate-m-nocp.c
+++ b/target/arm/translate-m-nocp.c
@@ -765,8 +765,7 @@ static bool trans_NOCP(DisasContext *s, arg_nocp *a)
 }
 
 if (a->cp != 10) {
-gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
-  syn_uncategorized(), default_exception_el(s));
+gen_exception_insn(s, s->pc_curr, EXCP_NOCP, syn_uncategorized());
 return true;
 }
 
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
index 5aec2a1555..0cf1b5ea4f 100644
--- a/target/arm/translate-mve.c
+++ b/target/arm/translate-mve.c
@@ -100,8 +100,7 @@ bool mve_eci_check(DisasContext *s)
 return true;
 default:
 /* Reserved value: INVSTATE UsageFault */
-gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, 
syn_uncategorized(),
-  default_exception_el(s));
+gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized());
 return false;
 }
 }
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 44f462a3a3..c7d422b541 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1106,6 +1106,11 @@ void gen_exception_insn_el(DisasContext *s, uint64_t pc, 
int excp,
 gen_exception_insn_el_v(s, pc, excp, syn, tcg_constant_i32(target_el));
 }
 
+void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn)
+{
+gen_exception_insn_el(s, pc, excp, syn, default_exception_el(s));
+}
+
 static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
 {
 gen_set_condexec(s);
@@ -1117,8 +1122,7 @@ static void 

[PATCH v3 06/23] target/arm: Use is_a64 in arm_generate_debug_exceptions

2022-06-09 Thread Richard Henderson
Use the accessor rather than the raw structure member.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/debug_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index 20a0e4261a..a18a09a0c3 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -99,7 +99,7 @@ static bool aa32_generate_debug_exceptions(CPUARMState *env)
  */
 bool arm_generate_debug_exceptions(CPUARMState *env)
 {
-if (env->aarch64) {
+if (is_a64(env)) {
 return aa64_generate_debug_exceptions(env);
 } else {
 return aa32_generate_debug_exceptions(env);
-- 
2.34.1




[PATCH v3 14/23] target/arm: Remove TBFLAG_ANY.DEBUG_TARGET_EL

2022-06-09 Thread Richard Henderson
We no longer need this value during translation,
as it is now handled within the helpers.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h   |  6 ++
 target/arm/translate.h |  2 --
 target/arm/helper.c| 12 ++--
 target/arm/translate-a64.c |  1 -
 target/arm/translate.c |  1 -
 5 files changed, 4 insertions(+), 18 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 50b5a9c9fd..719613ad9e 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3104,11 +3104,9 @@ FIELD(TBFLAG_ANY, BE_DATA, 3, 1)
 FIELD(TBFLAG_ANY, MMUIDX, 4, 4)
 /* Target EL if we take a floating-point-disabled exception */
 FIELD(TBFLAG_ANY, FPEXC_EL, 8, 2)
-/* For A-profile only, target EL for debug exceptions.  */
-FIELD(TBFLAG_ANY, DEBUG_TARGET_EL, 10, 2)
 /* Memory operations require alignment: SCTLR_ELx.A or CCR.UNALIGN_TRP */
-FIELD(TBFLAG_ANY, ALIGN_MEM, 12, 1)
-FIELD(TBFLAG_ANY, PSTATE__IL, 13, 1)
+FIELD(TBFLAG_ANY, ALIGN_MEM, 10, 1)
+FIELD(TBFLAG_ANY, PSTATE__IL, 11, 1)
 
 /*
  * Bit usage when in AArch32 state, both A- and M-profile.
diff --git a/target/arm/translate.h b/target/arm/translate.h
index 890e73194c..8685f55e80 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -59,8 +59,6 @@ typedef struct DisasContext {
  */
 uint32_t svc_imm;
 int current_el;
-/* Debug target exception level for single-step exceptions */
-int debug_target_el;
 GHashTable *cp_regs;
 uint64_t features; /* CPU features bits */
 bool aarch64;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index ac9942d750..2b2c1998fd 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11102,18 +11102,10 @@ static CPUARMTBFlags rebuild_hflags_m32(CPUARMState 
*env, int fp_el,
 return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
 }
 
-static CPUARMTBFlags rebuild_hflags_aprofile(CPUARMState *env)
-{
-CPUARMTBFlags flags = {};
-
-DP_TBFLAG_ANY(flags, DEBUG_TARGET_EL, arm_debug_target_el(env));
-return flags;
-}
-
 static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
 ARMMMUIdx mmu_idx)
 {
-CPUARMTBFlags flags = rebuild_hflags_aprofile(env);
+CPUARMTBFlags flags = {};
 int el = arm_current_el(env);
 
 if (arm_sctlr(env, el) & SCTLR_A) {
@@ -11139,7 +11131,7 @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState 
*env, int fp_el,
 static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
 ARMMMUIdx mmu_idx)
 {
-CPUARMTBFlags flags = rebuild_hflags_aprofile(env);
+CPUARMTBFlags flags = {};
 ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
 uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
 uint64_t sctlr;
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 0581118f56..4f6181a548 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -14645,7 +14645,6 @@ static void 
aarch64_tr_init_disas_context(DisasContextBase *dcbase,
 dc->ss_active = EX_TBFLAG_ANY(tb_flags, SS_ACTIVE);
 dc->pstate_ss = EX_TBFLAG_ANY(tb_flags, PSTATE__SS);
 dc->is_ldex = false;
-dc->debug_target_el = EX_TBFLAG_ANY(tb_flags, DEBUG_TARGET_EL);
 
 /* Bound the number of insns to execute to those left on the page.  */
 bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
diff --git a/target/arm/translate.c b/target/arm/translate.c
index c7d422b541..b8a8972bac 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -9350,7 +9350,6 @@ static void arm_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 dc->v7m_lspact = EX_TBFLAG_M32(tb_flags, LSPACT);
 dc->mve_no_pred = EX_TBFLAG_M32(tb_flags, MVE_NO_PRED);
 } else {
-dc->debug_target_el = EX_TBFLAG_ANY(tb_flags, DEBUG_TARGET_EL);
 dc->sctlr_b = EX_TBFLAG_A32(tb_flags, SCTLR__B);
 dc->hstr_active = EX_TBFLAG_A32(tb_flags, HSTR_ACTIVE);
 dc->ns = EX_TBFLAG_A32(tb_flags, NS);
-- 
2.34.1




[PATCH v3 03/23] target/arm: Move exception_target_el out of line

2022-06-09 Thread Richard Henderson
Move the function to op_helper.c, near raise_exception.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/internals.h | 16 +---
 target/arm/op_helper.c | 15 +++
 2 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index a1bae4588a..af9de2dbe5 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1098,21 +1098,6 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, 
uint64_t va,
 int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx);
 int aa64_va_parameter_tbid(uint64_t tcr, ARMMMUIdx mmu_idx);
 
-static inline int exception_target_el(CPUARMState *env)
-{
-int target_el = MAX(1, arm_current_el(env));
-
-/*
- * No such thing as secure EL1 if EL3 is aarch32,
- * so update the target EL to EL3 in this case.
- */
-if (arm_is_secure(env) && !arm_el_is_aa64(env, 3) && target_el == 1) {
-target_el = 3;
-}
-
-return target_el;
-}
-
 /* Determine if allocation tags are available.  */
 static inline bool allocation_tag_access_enabled(CPUARMState *env, int el,
  uint64_t sctlr)
@@ -1339,6 +1324,7 @@ void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu);
 bool el_is_in_host(CPUARMState *env, int el);
 
 void aa32_max_features(ARMCPU *cpu);
+int exception_target_el(CPUARMState *env);
 
 /* Powers of 2 for sve_vq_map et al. */
 #define SVE_VQ_POW2_MAP \
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index c4bd668870..97c8c9ec77 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -28,6 +28,21 @@
 #define SIGNBIT (uint32_t)0x8000
 #define SIGNBIT64 ((uint64_t)1 << 63)
 
+int exception_target_el(CPUARMState *env)
+{
+int target_el = MAX(1, arm_current_el(env));
+
+/*
+ * No such thing as secure EL1 if EL3 is aarch32,
+ * so update the target EL to EL3 in this case.
+ */
+if (arm_is_secure(env) && !arm_el_is_aa64(env, 3) && target_el == 1) {
+target_el = 3;
+}
+
+return target_el;
+}
+
 void raise_exception(CPUARMState *env, uint32_t excp,
  uint32_t syndrome, uint32_t target_el)
 {
-- 
2.34.1




[PATCH v3 10/23] target/arm: Introduce gen_exception_insn_el_v

2022-06-09 Thread Richard Henderson
Create a function below gen_exception_insn that takes
the target_el as a TCGv_i32, replacing gen_exception_el.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 27 ---
 1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index dc033600c0..9cb31663dd 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1086,8 +1086,8 @@ static void gen_exception_internal_insn(DisasContext *s, 
uint32_t pc, int excp)
 s->base.is_jmp = DISAS_NORETURN;
 }
 
-void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
-uint32_t syn, uint32_t target_el)
+static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp,
+uint32_t syn, TCGv_i32 tcg_el)
 {
 if (s->aarch64) {
 gen_a64_set_pc_im(pc);
@@ -1095,10 +1095,17 @@ void gen_exception_insn(DisasContext *s, uint64_t pc, 
int excp,
 gen_set_condexec(s);
 gen_set_pc_im(s, pc);
 }
-gen_exception(excp, syn, target_el);
+gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
+  tcg_constant_i32(syn), tcg_el);
 s->base.is_jmp = DISAS_NORETURN;
 }
 
+void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
+uint32_t syn, uint32_t target_el)
+{
+gen_exception_insn_el_v(s, pc, excp, syn, tcg_constant_i32(target_el));
+}
+
 static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
 {
 gen_set_condexec(s);
@@ -1114,17 +1121,6 @@ void unallocated_encoding(DisasContext *s)
default_exception_el(s));
 }
 
-static void gen_exception_el(DisasContext *s, int excp, uint32_t syn,
- TCGv_i32 tcg_el)
-{
-gen_set_condexec(s);
-gen_set_pc_im(s, s->pc_curr);
-gen_helper_exception_with_syndrome_el(cpu_env,
-  tcg_constant_i32(excp),
-  tcg_constant_i32(syn), tcg_el);
-s->base.is_jmp = DISAS_NORETURN;
-}
-
 /* Force a TB lookup after an instruction that changes the CPU state.  */
 void gen_lookup_tb(DisasContext *s)
 {
@@ -2847,7 +2843,8 @@ static bool msr_banked_access_decode(DisasContext *s, int 
r, int sysm, int rn,
 tcg_el = tcg_constant_i32(3);
 }
 
-gen_exception_el(s, EXCP_UDEF, syn_uncategorized(), tcg_el);
+gen_exception_insn_el_v(s, s->pc_curr, EXCP_UDEF,
+syn_uncategorized(), tcg_el);
 tcg_temp_free_i32(tcg_el);
 return false;
 }
-- 
2.34.1




[PATCH v3 11/23] target/arm: Rename gen_exception_insn to gen_exception_insn_el

2022-06-09 Thread Richard Henderson
Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/translate.h|  4 ++--
 target/arm/translate-a64.c| 36 
 target/arm/translate-m-nocp.c | 16 +++---
 target/arm/translate-mve.c|  4 ++--
 target/arm/translate-vfp.c|  6 +++---
 target/arm/translate.c| 39 ++-
 6 files changed, 53 insertions(+), 52 deletions(-)

diff --git a/target/arm/translate.h b/target/arm/translate.h
index c57830126b..9ae76535ad 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -279,8 +279,8 @@ void arm_jump_cc(DisasCompare *cmp, TCGLabel *label);
 void arm_gen_test_cc(int cc, TCGLabel *label);
 MemOp pow2_align(unsigned i);
 void unallocated_encoding(DisasContext *s);
-void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
-uint32_t syn, uint32_t target_el);
+void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp,
+   uint32_t syn, uint32_t target_el);
 
 /* Return state of Alternate Half-precision flag, caller frees result */
 static inline TCGv_i32 get_ahp_flag(void)
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index e752589090..14bc80dba0 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1161,9 +1161,9 @@ static bool fp_access_check(DisasContext *s)
 assert(!s->fp_access_checked);
 s->fp_access_checked = true;
 
-gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
-   syn_fp_access_trap(1, 0xe, false, 0),
-   s->fp_excp_el);
+gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
+  syn_fp_access_trap(1, 0xe, false, 0),
+  s->fp_excp_el);
 return false;
 }
 s->fp_access_checked = true;
@@ -1179,8 +1179,8 @@ bool sve_access_check(DisasContext *s)
 assert(!s->sve_access_checked);
 s->sve_access_checked = true;
 
-gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
-   syn_sve_access_trap(), s->sve_excp_el);
+gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
+  syn_sve_access_trap(), s->sve_excp_el);
 return false;
 }
 s->sve_access_checked = true;
@@ -1816,8 +1816,8 @@ static void gen_sysreg_undef(DisasContext *s, bool isread,
 } else {
 syndrome = syn_uncategorized();
 }
-gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syndrome,
-   default_exception_el(s));
+gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syndrome,
+  default_exception_el(s));
 }
 
 /* MRS - move from system register
@@ -2069,8 +2069,8 @@ static void disas_exc(DisasContext *s, uint32_t insn)
 switch (op2_ll) {
 case 1: /* SVC */
 gen_ss_advance(s);
-gen_exception_insn(s, s->base.pc_next, EXCP_SWI,
-   syn_aa64_svc(imm16), default_exception_el(s));
+gen_exception_insn_el(s, s->base.pc_next, EXCP_SWI,
+  syn_aa64_svc(imm16), 
default_exception_el(s));
 break;
 case 2: /* HVC */
 if (s->current_el == 0) {
@@ -2083,8 +2083,8 @@ static void disas_exc(DisasContext *s, uint32_t insn)
 gen_a64_set_pc_im(s->pc_curr);
 gen_helper_pre_hvc(cpu_env);
 gen_ss_advance(s);
-gen_exception_insn(s, s->base.pc_next, EXCP_HVC,
-   syn_aa64_hvc(imm16), 2);
+gen_exception_insn_el(s, s->base.pc_next, EXCP_HVC,
+  syn_aa64_hvc(imm16), 2);
 break;
 case 3: /* SMC */
 if (s->current_el == 0) {
@@ -2094,8 +2094,8 @@ static void disas_exc(DisasContext *s, uint32_t insn)
 gen_a64_set_pc_im(s->pc_curr);
 gen_helper_pre_smc(cpu_env, tcg_constant_i32(syn_aa64_smc(imm16)));
 gen_ss_advance(s);
-gen_exception_insn(s, s->base.pc_next, EXCP_SMC,
-   syn_aa64_smc(imm16), 3);
+gen_exception_insn_el(s, s->base.pc_next, EXCP_SMC,
+  syn_aa64_smc(imm16), 3);
 break;
 default:
 unallocated_encoding(s);
@@ -14725,8 +14725,8 @@ static void aarch64_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cpu)
  * Illegal execution state. This has priority over BTI
  * exceptions, but comes after instruction abort exceptions.
  */
-gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
-   syn_illegalstate(), default_exception_el(s));
+gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
+  

[PATCH v3 07/23] target/arm: Move exception_bkpt_insn to debug_helper.c

2022-06-09 Thread Richard Henderson
Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/debug_helper.c | 31 +++
 target/arm/op_helper.c| 29 -
 2 files changed, 31 insertions(+), 29 deletions(-)

diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index a18a09a0c3..80dff0788b 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -430,6 +430,37 @@ void arm_debug_excp_handler(CPUState *cs)
 }
 }
 
+/*
+ * Raise an EXCP_BKPT with the specified syndrome register value,
+ * targeting the correct exception level for debug exceptions.
+ */
+void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
+{
+int debug_el = arm_debug_target_el(env);
+int cur_el = arm_current_el(env);
+
+/* FSR will only be used if the debug target EL is AArch32. */
+env->exception.fsr = arm_debug_exception_fsr(env);
+/*
+ * FAR is UNKNOWN: clear vaddress to avoid potentially exposing
+ * values to the guest that it shouldn't be able to see at its
+ * exception/security level.
+ */
+env->exception.vaddress = 0;
+/*
+ * Other kinds of architectural debug exception are ignored if
+ * they target an exception level below the current one (in QEMU
+ * this is checked by arm_generate_debug_exceptions()). Breakpoint
+ * instructions are special because they always generate an exception
+ * to somewhere: if they can't go to the configured debug exception
+ * level they are taken to the current exception level.
+ */
+if (debug_el < cur_el) {
+debug_el = cur_el;
+}
+raise_exception(env, EXCP_BKPT, syndrome, debug_el);
+}
+
 #if !defined(CONFIG_USER_ONLY)
 
 vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len)
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 97c8c9ec77..2a8bdc2cbf 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -399,35 +399,6 @@ void HELPER(exception_with_syndrome)(CPUARMState *env, 
uint32_t excp,
 raise_exception(env, excp, syndrome, target_el);
 }
 
-/* Raise an EXCP_BKPT with the specified syndrome register value,
- * targeting the correct exception level for debug exceptions.
- */
-void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
-{
-int debug_el = arm_debug_target_el(env);
-int cur_el = arm_current_el(env);
-
-/* FSR will only be used if the debug target EL is AArch32. */
-env->exception.fsr = arm_debug_exception_fsr(env);
-/* FAR is UNKNOWN: clear vaddress to avoid potentially exposing
- * values to the guest that it shouldn't be able to see at its
- * exception/security level.
- */
-env->exception.vaddress = 0;
-/*
- * Other kinds of architectural debug exception are ignored if
- * they target an exception level below the current one (in QEMU
- * this is checked by arm_generate_debug_exceptions()). Breakpoint
- * instructions are special because they always generate an exception
- * to somewhere: if they can't go to the configured debug exception
- * level they are taken to the current exception level.
- */
-if (debug_el < cur_el) {
-debug_el = cur_el;
-}
-raise_exception(env, EXCP_BKPT, syndrome, debug_el);
-}
-
 uint32_t HELPER(cpsr_read)(CPUARMState *env)
 {
 return cpsr_read(env) & ~CPSR_EXEC;
-- 
2.34.1




[PATCH v3 09/23] target/arm: Rename helper_exception_with_syndrome

2022-06-09 Thread Richard Henderson
Rename to helper_exception_with_syndrome_el, to emphasize
that the target el is a parameter.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/helper.h| 2 +-
 target/arm/translate.h | 6 +++---
 target/arm/op_helper.c | 6 +++---
 target/arm/translate.c | 6 +++---
 4 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/target/arm/helper.h b/target/arm/helper.h
index 5161cdf73d..5a6802e3fa 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -45,7 +45,7 @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32)
 DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
i32, i32, i32, i32)
 DEF_HELPER_2(exception_internal, noreturn, env, i32)
-DEF_HELPER_4(exception_with_syndrome, noreturn, env, i32, i32, i32)
+DEF_HELPER_4(exception_with_syndrome_el, noreturn, env, i32, i32, i32)
 DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32)
 DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl)
 DEF_HELPER_1(setend, void, env)
diff --git a/target/arm/translate.h b/target/arm/translate.h
index f473a21ed4..c57830126b 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -332,9 +332,9 @@ static inline void gen_ss_advance(DisasContext *s)
 static inline void gen_exception(int excp, uint32_t syndrome,
  uint32_t target_el)
 {
-gen_helper_exception_with_syndrome(cpu_env, tcg_constant_i32(excp),
-   tcg_constant_i32(syndrome),
-   tcg_constant_i32(target_el));
+gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
+  tcg_constant_i32(syndrome),
+  tcg_constant_i32(target_el));
 }
 
 /* Generate an architectural singlestep exception */
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 2a8bdc2cbf..8a6a3b8551 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -381,7 +381,7 @@ void HELPER(yield)(CPUARMState *env)
  * those EXCP values which are special cases for QEMU to interrupt
  * execution and not to be used for exceptions which are passed to
  * the guest (those must all have syndrome information and thus should
- * use exception_with_syndrome).
+ * use exception_with_syndrome*).
  */
 void HELPER(exception_internal)(CPUARMState *env, uint32_t excp)
 {
@@ -393,8 +393,8 @@ void HELPER(exception_internal)(CPUARMState *env, uint32_t 
excp)
 }
 
 /* Raise an exception with the specified syndrome register value */
-void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp,
- uint32_t syndrome, uint32_t target_el)
+void HELPER(exception_with_syndrome_el)(CPUARMState *env, uint32_t excp,
+uint32_t syndrome, uint32_t target_el)
 {
 raise_exception(env, excp, syndrome, target_el);
 }
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 87a899d638..dc033600c0 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1119,9 +1119,9 @@ static void gen_exception_el(DisasContext *s, int excp, 
uint32_t syn,
 {
 gen_set_condexec(s);
 gen_set_pc_im(s, s->pc_curr);
-gen_helper_exception_with_syndrome(cpu_env,
-   tcg_constant_i32(excp),
-   tcg_constant_i32(syn), tcg_el);
+gen_helper_exception_with_syndrome_el(cpu_env,
+  tcg_constant_i32(excp),
+  tcg_constant_i32(syn), tcg_el);
 s->base.is_jmp = DISAS_NORETURN;
 }
 
-- 
2.34.1




[PATCH v3 13/23] target/arm: Create helper_exception_swstep

2022-06-09 Thread Richard Henderson
Move the computation from gen_swstep_exception into a helper.

This fixes a bug when:
  - MDSCR_EL1.KDE == 1 to enable debug exceptions within EL_D itself
  - we singlestep an ERET from EL_D to some lower EL

Previously we were computing 'same el' based on the EL which
executed the ERET instruction, whereas it ought to be computed
based on the EL to which ERET returned.  This happens naturally
with the new helper, which runs after EL has been changed.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/helper.h   |  1 +
 target/arm/translate.h| 12 +++-
 target/arm/debug_helper.c | 16 
 3 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/target/arm/helper.h b/target/arm/helper.h
index 5a6802e3fa..db7447d233 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -47,6 +47,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
 DEF_HELPER_2(exception_internal, noreturn, env, i32)
 DEF_HELPER_4(exception_with_syndrome_el, noreturn, env, i32, i32, i32)
 DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32)
+DEF_HELPER_2(exception_swstep, noreturn, env, i32)
 DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl)
 DEF_HELPER_1(setend, void, env)
 DEF_HELPER_2(wfi, void, env, i32)
diff --git a/target/arm/translate.h b/target/arm/translate.h
index 4575af6e1c..890e73194c 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -341,15 +341,9 @@ static inline void gen_exception(int excp, uint32_t 
syndrome,
 /* Generate an architectural singlestep exception */
 static inline void gen_swstep_exception(DisasContext *s, int isv, int ex)
 {
-bool same_el = (s->debug_target_el == s->current_el);
-
-/*
- * If singlestep is targeting a lower EL than the current one,
- * then s->ss_active must be false and we can never get here.
- */
-assert(s->debug_target_el >= s->current_el);
-
-gen_exception(EXCP_UDEF, syn_swstep(same_el, isv, ex), s->debug_target_el);
+/* Fill in the same_el field of the syndrome in the helper. */
+uint32_t syn = syn_swstep(false, isv, ex);
+gen_helper_exception_swstep(cpu_env, tcg_constant_i32(syn));
 }
 
 /*
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index a743061e89..a3a1b98de2 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -487,6 +487,22 @@ void HELPER(exception_bkpt_insn)(CPUARMState *env, 
uint32_t syndrome)
 raise_exception(env, EXCP_BKPT, syndrome, debug_el);
 }
 
+void HELPER(exception_swstep)(CPUARMState *env, uint32_t syndrome)
+{
+int debug_el = arm_debug_target_el(env);
+int cur_el = arm_current_el(env);
+
+/*
+ * If singlestep is targeting a lower EL than the current one, then
+ * DisasContext.ss_active must be false and we can never get here.
+ */
+assert(debug_el >= cur_el);
+if (debug_el == cur_el) {
+syndrome |= 1 << ARM_EL_EC_SHIFT;
+}
+raise_exception(env, EXCP_UDEF, syndrome, debug_el);
+}
+
 #if !defined(CONFIG_USER_ONLY)
 
 vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len)
-- 
2.34.1




Re: [PATCH v2 24/25] target/arm: Rearrange Secure PL1 test in arm_debug_target_el

2022-06-09 Thread Richard Henderson

On 6/9/22 09:53, Peter Maydell wrote:

On Tue, 7 Jun 2022 at 04:06, Richard Henderson
 wrote:


Not a bug, because arm_is_el2_enabled tests for secure,
and SCR_EL3.EEL2 cannot be set for AArch32, however the
ordering of the tests looks odd.  Mirror the structure
over in exception_target_el().


I think the code is following the ordering in the
DebugTarget() and DebugTargetFrom() pseudocode (or else some other
equivalent function in an older version of the Arm ARM...)


Fair enough.


I think you're also relying on there being no secure EL2
if EL3 is AArch32 (otherwise an exception from secure EL0
might need to be routed to secure EL2, not EL3).


Correct, though I don't imagine SEL2 will ever apply to A32.

I'll drop the patch though.


r~



[PATCH v3 05/23] target/arm: Move arm_generate_debug_exceptions out of line

2022-06-09 Thread Richard Henderson
Move arm_generate_debug_exceptions and its two subroutines,
{aa32,aa64}_generate_debug_exceptions into debug_helper.c,
and the one interface declaration to internals.h.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h  | 91 -
 target/arm/internals.h|  1 +
 target/arm/debug_helper.c | 94 +++
 3 files changed, 95 insertions(+), 91 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index bb1dc3289a..50b5a9c9fd 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3015,97 +3015,6 @@ static inline bool arm_v7m_csselr_razwi(ARMCPU *cpu)
 return (cpu->clidr & R_V7M_CLIDR_CTYPE_ALL_MASK) != 0;
 }
 
-/* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */
-static inline bool aa64_generate_debug_exceptions(CPUARMState *env)
-{
-int cur_el = arm_current_el(env);
-int debug_el;
-
-if (cur_el == 3) {
-return false;
-}
-
-/* MDCR_EL3.SDD disables debug events from Secure state */
-if (arm_is_secure_below_el3(env)
-&& extract32(env->cp15.mdcr_el3, 16, 1)) {
-return false;
-}
-
-/*
- * Same EL to same EL debug exceptions need MDSCR_KDE enabled
- * while not masking the (D)ebug bit in DAIF.
- */
-debug_el = arm_debug_target_el(env);
-
-if (cur_el == debug_el) {
-return extract32(env->cp15.mdscr_el1, 13, 1)
-&& !(env->daif & PSTATE_D);
-}
-
-/* Otherwise the debug target needs to be a higher EL */
-return debug_el > cur_el;
-}
-
-static inline bool aa32_generate_debug_exceptions(CPUARMState *env)
-{
-int el = arm_current_el(env);
-
-if (el == 0 && arm_el_is_aa64(env, 1)) {
-return aa64_generate_debug_exceptions(env);
-}
-
-if (arm_is_secure(env)) {
-int spd;
-
-if (el == 0 && (env->cp15.sder & 1)) {
-/* SDER.SUIDEN means debug exceptions from Secure EL0
- * are always enabled. Otherwise they are controlled by
- * SDCR.SPD like those from other Secure ELs.
- */
-return true;
-}
-
-spd = extract32(env->cp15.mdcr_el3, 14, 2);
-switch (spd) {
-case 1:
-/* SPD == 0b01 is reserved, but behaves as 0b00. */
-case 0:
-/* For 0b00 we return true if external secure invasive debug
- * is enabled. On real hardware this is controlled by external
- * signals to the core. QEMU always permits debug, and behaves
- * as if DBGEN, SPIDEN, NIDEN and SPNIDEN are all tied high.
- */
-return true;
-case 2:
-return false;
-case 3:
-return true;
-}
-}
-
-return el != 2;
-}
-
-/* Return true if debugging exceptions are currently enabled.
- * This corresponds to what in ARM ARM pseudocode would be
- *if UsingAArch32() then
- *return AArch32.GenerateDebugExceptions()
- *else
- *return AArch64.GenerateDebugExceptions()
- * We choose to push the if() down into this function for clarity,
- * since the pseudocode has it at all callsites except for the one in
- * CheckSoftwareStep(), where it is elided because both branches would
- * always return the same value.
- */
-static inline bool arm_generate_debug_exceptions(CPUARMState *env)
-{
-if (env->aarch64) {
-return aa64_generate_debug_exceptions(env);
-} else {
-return aa32_generate_debug_exceptions(env);
-}
-}
-
 static inline bool arm_sctlr_b(CPUARMState *env)
 {
 return
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 64e2c1dfad..02fa70f75a 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1326,6 +1326,7 @@ bool el_is_in_host(CPUARMState *env, int el);
 void aa32_max_features(ARMCPU *cpu);
 int exception_target_el(CPUARMState *env);
 bool arm_singlestep_active(CPUARMState *env);
+bool arm_generate_debug_exceptions(CPUARMState *env);
 
 /* Powers of 2 for sve_vq_map et al. */
 #define SVE_VQ_POW2_MAP \
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index 1abf41c5f8..20a0e4261a 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -12,6 +12,100 @@
 #include "exec/helper-proto.h"
 
 
+/* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */
+static bool aa64_generate_debug_exceptions(CPUARMState *env)
+{
+int cur_el = arm_current_el(env);
+int debug_el;
+
+if (cur_el == 3) {
+return false;
+}
+
+/* MDCR_EL3.SDD disables debug events from Secure state */
+if (arm_is_secure_below_el3(env)
+&& extract32(env->cp15.mdcr_el3, 16, 1)) {
+return false;
+}
+
+/*
+ * Same EL to same EL debug exceptions need MDSCR_KDE enabled
+ * while not masking the (D)ebug bit in DAIF.
+ */
+debug_el = arm_debug_target_el(env);
+
+if (cur_el == 

[PATCH v3 04/23] target/arm: Move arm_singlestep_active out of line

2022-06-09 Thread Richard Henderson
Move the function to debug_helper.c, and the
declaration to internals.h.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h  | 10 --
 target/arm/internals.h|  1 +
 target/arm/debug_helper.c | 12 
 3 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 78dbcb5592..bb1dc3289a 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3106,16 +3106,6 @@ static inline bool 
arm_generate_debug_exceptions(CPUARMState *env)
 }
 }
 
-/* Is single-stepping active? (Note that the "is EL_D AArch64?" check
- * implicitly means this always returns false in pre-v8 CPUs.)
- */
-static inline bool arm_singlestep_active(CPUARMState *env)
-{
-return extract32(env->cp15.mdscr_el1, 0, 1)
-&& arm_el_is_aa64(env, arm_debug_target_el(env))
-&& arm_generate_debug_exceptions(env);
-}
-
 static inline bool arm_sctlr_b(CPUARMState *env)
 {
 return
diff --git a/target/arm/internals.h b/target/arm/internals.h
index af9de2dbe5..64e2c1dfad 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1325,6 +1325,7 @@ bool el_is_in_host(CPUARMState *env, int el);
 
 void aa32_max_features(ARMCPU *cpu);
 int exception_target_el(CPUARMState *env);
+bool arm_singlestep_active(CPUARMState *env);
 
 /* Powers of 2 for sve_vq_map et al. */
 #define SVE_VQ_POW2_MAP \
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index 46893697cc..1abf41c5f8 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -11,6 +11,18 @@
 #include "exec/exec-all.h"
 #include "exec/helper-proto.h"
 
+
+/*
+ * Is single-stepping active? (Note that the "is EL_D AArch64?" check
+ * implicitly means this always returns false in pre-v8 CPUs.)
+ */
+bool arm_singlestep_active(CPUARMState *env)
+{
+return extract32(env->cp15.mdscr_el1, 0, 1)
+&& arm_el_is_aa64(env, arm_debug_target_el(env))
+&& arm_generate_debug_exceptions(env);
+}
+
 /* Return true if the linked breakpoint entry lbn passes its checks */
 static bool linked_bp_matches(ARMCPU *cpu, int lbn)
 {
-- 
2.34.1




[PATCH v3 02/23] target/arm: Add coproc parameter to syn_fp_access_trap

2022-06-09 Thread Richard Henderson
With ARMv8, this field is always RES0.
With ARMv7, targeting EL2 and TA=0, it is always 0xA.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/syndrome.h  |  7 ---
 target/arm/translate-a64.c |  3 ++-
 target/arm/translate-vfp.c | 14 --
 3 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
index 0cb26dde7d..c105f9e6ba 100644
--- a/target/arm/syndrome.h
+++ b/target/arm/syndrome.h
@@ -185,12 +185,13 @@ static inline uint32_t syn_cp15_rrt_trap(int cv, int 
cond, int opc1, int crm,
 | (rt2 << 10) | (rt << 5) | (crm << 1) | isread;
 }
 
-static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_16bit)
+static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_16bit,
+  int coproc)
 {
-/* AArch32 FP trap or any AArch64 FP/SIMD trap: TA == 0 coproc == 0xa */
+/* AArch32 FP trap or any AArch64 FP/SIMD trap: TA == 0 */
 return (EC_ADVSIMDFPACCESSTRAP << ARM_EL_EC_SHIFT)
 | (is_16bit ? 0 : ARM_EL_IL)
-| (cv << 24) | (cond << 20) | 0xa;
+| (cv << 24) | (cond << 20) | coproc;
 }
 
 static inline uint32_t syn_simd_access_trap(int cv, int cond, bool is_16bit)
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index d438fb89e7..e752589090 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1162,7 +1162,8 @@ static bool fp_access_check(DisasContext *s)
 s->fp_access_checked = true;
 
 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
-   syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
+   syn_fp_access_trap(1, 0xe, false, 0),
+   s->fp_excp_el);
 return false;
 }
 s->fp_access_checked = true;
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
index 40a513b822..0f797c56fd 100644
--- a/target/arm/translate-vfp.c
+++ b/target/arm/translate-vfp.c
@@ -219,8 +219,18 @@ static void gen_update_fp_context(DisasContext *s)
 static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
 {
 if (s->fp_excp_el) {
-gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
-   syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
+/*
+ * The full syndrome is only used for HSR when HCPTR traps:
+ * For v8, when TA==0, coproc is RES0.
+ * For v7, any use of a Floating-point instruction or access
+ * to a Floating-point Extension register that is trapped to
+ * Hyp mode because of a trap configured in the HCPTR sets
+ * this field to 0xA.
+ */
+int coproc = arm_dc_feature(s, ARM_FEATURE_V8) ? 0 : 0xa;
+uint32_t syn = syn_fp_access_trap(1, 0xe, false, coproc);
+
+gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn, s->fp_excp_el);
 return false;
 }
 
-- 
2.34.1




[PATCH v3 01/23] target/arm: Mark exception helpers as noreturn

2022-06-09 Thread Richard Henderson
Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/helper.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/target/arm/helper.h b/target/arm/helper.h
index b1334e0c42..5161cdf73d 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -44,9 +44,9 @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32)
 
 DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
i32, i32, i32, i32)
-DEF_HELPER_2(exception_internal, void, env, i32)
-DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32)
-DEF_HELPER_2(exception_bkpt_insn, void, env, i32)
+DEF_HELPER_2(exception_internal, noreturn, env, i32)
+DEF_HELPER_4(exception_with_syndrome, noreturn, env, i32, i32, i32)
+DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32)
 DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl)
 DEF_HELPER_1(setend, void, env)
 DEF_HELPER_2(wfi, void, env, i32)
-- 
2.34.1




[PATCH v3 00/23] target/arm: tidy exception routing

2022-06-09 Thread Richard Henderson
This is mostly code movement at this point, out of headers
and into op_helper.c and debug_helper.c.

Changes for v3:
  * Drop helper_exception_advsimdfp_access.
  * Drop Rearrange Secure PL1 test in arm_debug_target_el.
  * Improve patch comment for helper_exception_swstep.

All patches are reviewed.


r~


Richard Henderson (23):
  target/arm: Mark exception helpers as noreturn
  target/arm: Add coproc parameter to syn_fp_access_trap
  target/arm: Move exception_target_el out of line
  target/arm: Move arm_singlestep_active out of line
  target/arm: Move arm_generate_debug_exceptions out of line
  target/arm: Use is_a64 in arm_generate_debug_exceptions
  target/arm: Move exception_bkpt_insn to debug_helper.c
  target/arm: Move arm_debug_exception_fsr to debug_helper.c
  target/arm: Rename helper_exception_with_syndrome
  target/arm: Introduce gen_exception_insn_el_v
  target/arm: Rename gen_exception_insn to gen_exception_insn_el
  target/arm: Introduce gen_exception_insn
  target/arm: Create helper_exception_swstep
  target/arm: Remove TBFLAG_ANY.DEBUG_TARGET_EL
  target/arm: Move gen_exception to translate.c
  target/arm: Rename gen_exception to gen_exception_el
  target/arm: Introduce gen_exception
  target/arm: Introduce gen_exception_el_v
  target/arm: Introduce helper_exception_with_syndrome
  target/arm: Remove default_exception_el
  target/arm: Create raise_exception_debug
  target/arm: Move arm_debug_target_el to debug_helper.c
  target/arm: Fix Secure PL1 tests in fp_exception_el

 target/arm/cpu.h  | 128 +---
 target/arm/helper.h   |   8 +-
 target/arm/internals.h|  43 +--
 target/arm/syndrome.h |   7 +-
 target/arm/translate.h|  43 +--
 target/arm/debug_helper.c | 220 --
 target/arm/helper.c   |  35 ++
 target/arm/op_helper.c|  52 
 target/arm/translate-a64.c|  34 ++
 target/arm/translate-m-nocp.c |  15 ++-
 target/arm/translate-mve.c|   3 +-
 target/arm/translate-vfp.c|  18 ++-
 target/arm/translate.c| 106 
 13 files changed, 360 insertions(+), 352 deletions(-)

-- 
2.34.1




Re: [PATCH v2 1/2] hw: m25p80: add WP# pin and SRWD bit for write protection

2022-06-09 Thread Francisco Iglesias
Hi Iris,

Looks good some, a couple of comments below.

On [2022 Jun 08] Wed 20:13:19, Iris Chen wrote:
> From: Iris Chen 
> 
> Signed-off-by: Iris Chen 
> ---
> Addressed all comments from V1. The biggest change: removed 
> object_class_property_add.
> 
>  hw/block/m25p80.c | 37 +++
>  tests/qtest/aspeed_smc-test.c |  2 ++
>  2 files changed, 39 insertions(+)
> 
> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
> index 81ba3da4df..1a20bd55d4 100644
> --- a/hw/block/m25p80.c
> +++ b/hw/block/m25p80.c
> @@ -27,12 +27,14 @@
>  #include "hw/qdev-properties.h"
>  #include "hw/qdev-properties-system.h"
>  #include "hw/ssi/ssi.h"
> +#include "hw/irq.h"
>  #include "migration/vmstate.h"
>  #include "qemu/bitops.h"
>  #include "qemu/log.h"
>  #include "qemu/module.h"
>  #include "qemu/error-report.h"
>  #include "qapi/error.h"
> +#include "qapi/visitor.h"
>  #include "trace.h"
>  #include "qom/object.h"
>  
> @@ -472,11 +474,13 @@ struct Flash {
>  uint8_t spansion_cr2v;
>  uint8_t spansion_cr3v;
>  uint8_t spansion_cr4v;
> +bool wp_level;
>  bool write_enable;
>  bool four_bytes_address_mode;
>  bool reset_enable;
>  bool quad_enable;
>  bool aai_enable;
> +bool status_register_write_disabled;
>  uint8_t ear;
>  
>  int64_t dirty_page;
> @@ -723,6 +727,21 @@ static void complete_collecting_data(Flash *s)
>  flash_erase(s, s->cur_addr, s->cmd_in_progress);
>  break;
>  case WRSR:
> +/*
> + * If WP# is low and status_register_write_disabled is high,
> + * status register writes are disabled.
> + * This is also called "hardware protected mode" (HPM). All other
> + * combinations of the two states are called "software protected 
> mode"
> + * (SPM), and status register writes are permitted.
> + */
> +if ((s->wp_level == 0 && s->status_register_write_disabled)
> +|| !s->write_enable) {

'write_enable' needs to be true in 'decode_new_cmd' when issueing the WRSR
command, otherwise the state machinery will not advance to this function
(meaning that above check for !s->write_enable will never hit as far as I can
tell). A suggestion is to move the check for wp_level and
status_reg_wr_disabled into 'decode_new_cmd' to for keeping it consistent.

> +qemu_log_mask(LOG_GUEST_ERROR,
> +  "M25P80: Status register write is disabled!\n");
> +break;
> +}
> +s->status_register_write_disabled = extract32(s->data[0], 7, 1);
> +
>  switch (get_man(s)) {
>  case MAN_SPANSION:
>  s->quad_enable = !!(s->data[1] & 0x02);
> @@ -1195,6 +1214,8 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>  
>  case RDSR:
>  s->data[0] = (!!s->write_enable) << 1;
> +s->data[0] |= (!!s->status_register_write_disabled) << 7;
> +
>  if (get_man(s) == MAN_MACRONIX || get_man(s) == MAN_ISSI) {
>  s->data[0] |= (!!s->quad_enable) << 6;
>  }
> @@ -1484,6 +1505,14 @@ static uint32_t m25p80_transfer8(SSIPeripheral *ss, 
> uint32_t tx)
>  return r;
>  }
>  
> +static void m25p80_write_protect_pin_irq_handler(void *opaque, int n, int 
> level)
> +{
> +Flash *s = M25P80(opaque);
> +/* WP# is just a single pin. */
> +assert(n == 0);
> +s->wp_level = !!level;
> +}
> +
>  static void m25p80_realize(SSIPeripheral *ss, Error **errp)
>  {
>  Flash *s = M25P80(ss);
> @@ -1515,12 +1544,18 @@ static void m25p80_realize(SSIPeripheral *ss, Error 
> **errp)
>  s->storage = blk_blockalign(NULL, s->size);
>  memset(s->storage, 0xFF, s->size);
>  }
> +
> +qdev_init_gpio_in_named(DEVICE(s),
> +m25p80_write_protect_pin_irq_handler, "WP#", 1);
>  }
>  
>  static void m25p80_reset(DeviceState *d)
>  {
>  Flash *s = M25P80(d);
>  
> +s->wp_level = true;
> +s->status_register_write_disabled = false;
> +
>  reset_memory(s);
>  }
>  
> @@ -1601,6 +1636,8 @@ static const VMStateDescription vmstate_m25p80 = {
>  VMSTATE_UINT8(needed_bytes, Flash),
>  VMSTATE_UINT8(cmd_in_progress, Flash),
>  VMSTATE_UINT32(cur_addr, Flash),
> +VMSTATE_BOOL(wp_level, Flash),
> +VMSTATE_BOOL(status_register_write_disabled, Flash),

Above needs to be added through a subsection, you can see commit 465ef47abe3
for an example an also read about this in docs/devel/migration.rst.

Thank you,
Best regads,
Francisco Iglesias


>  VMSTATE_BOOL(write_enable, Flash),
>  VMSTATE_BOOL(reset_enable, Flash),
>  VMSTATE_UINT8(ear, Flash),
> diff --git a/tests/qtest/aspeed_smc-test.c b/tests/qtest/aspeed_smc-test.c
> index ec233315e6..c5d97d4410 100644
> --- a/tests/qtest/aspeed_smc-test.c
> +++ b/tests/qtest/aspeed_smc-test.c
> @@ -56,7 +56,9 @@ enum {
>  BULK_ERASE = 0xc7,
>  READ = 0x03,
>  PP = 0x02,
> +WRSR = 0x1,
> 

Re: [PULL 00/18] Block layer patches

2022-06-09 Thread Richard Henderson

On 6/9/22 10:21, Kevin Wolf wrote:

The following changes since commit 028f2361d0c2d28d6f918fe618f389228ac22b60:

   Merge tag 'pull-target-arm-20220609' of 
https://git.linaro.org/people/pmaydell/qemu-arm into staging (2022-06-09 
06:47:03 -0700)

are available in the Git repository at:

   git://repo.or.cz/qemu/kevin.git tags/for-upstream

for you to fetch changes up to 7f9a8b3342ff00d3398fdc08264948762d748edb:

   nbd: Drop dead code spotted by Coverity (2022-06-09 18:07:17 +0200)


Block layer patches

- Add vduse-blk export
- Dirty bitmaps: Fix and improve bitmap merge
- gluster: correctly set max_pdiscard
- rbd: report a better error when namespace does not exist
- aio_wait_kick: add missing memory barrier
- Code cleanups


Several sets of compile failures:

https://gitlab.com/qemu-project/qemu/-/jobs/2571008901

../subprojects/libvduse/libvduse.c:578:20: error: unused function 
'vring_used_flags_set_bit' [-Werror,-Wunused-function]

static inline void vring_used_flags_set_bit(VduseVirtq *vq, int mask)
   ^
../subprojects/libvduse/libvduse.c:587:20: error: unused function 
'vring_used_flags_unset_bit' [-Werror,-Wunused-function]

static inline void vring_used_flags_unset_bit(VduseVirtq *vq, int mask)
   ^

https://gitlab.com/qemu-project/qemu/-/jobs/2571008908

../meson.build:1652:2: ERROR: Tried to use 'add_global_arguments' after a build target has 
been declared.


https://gitlab.com/qemu-project/qemu/-/jobs/2571008833

../subprojects/libvduse/libvduse.c:325:20: error: cast to pointer from integer of 
different size [-Werror=int-to-pointer-cast]

  325 | munmap((void *)dev->regions[i].mmap_addr,
  |^
../subprojects/libvduse/libvduse.c: In function 'vduse_dev_create':
../subprojects/libvduse/libvduse.c:1318:54: error: format '%lu' expects argument of type 
'long unsigned int', but argument 3 has type 'uint64_t' {aka 'long long unsigned int'} 
[-Werror=format=]

 1318 | fprintf(stderr, "Failed to set api version %lu: %s\n",
  |~~^
  |  |
  |  long unsigned int
  |%llu
 1319 | version, strerror(errno));
  | ~~~
  | |
  | uint64_t {aka long long unsigned int}


r~



Re: [PATCH v15 8/9] target/loongarch: Adjust functions and structure to support user-mode

2022-06-09 Thread Richard Henderson

On 6/8/22 19:42, Song Gao wrote:

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 85c11a60d4..ee42707868 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -93,8 +93,7 @@ DEF_HELPER_2(frint_d, i64, env, i64)
  
  DEF_HELPER_FLAGS_2(set_rounding_mode, TCG_CALL_NO_RWG, void, env, i32)
  
-DEF_HELPER_1(rdtime_d, i64, env)

-
+#ifndef CONFIG_USER_ONLY
  /* CSRs helper */
  DEF_HELPER_1(csrrd_pgd, i64, env)
  DEF_HELPER_1(csrrd_tval, i64, env)
@@ -128,3 +127,5 @@ DEF_HELPER_4(lddir, tl, env, tl, tl, i32)
  DEF_HELPER_4(ldpte, void, env, tl, tl, i32)
  DEF_HELPER_1(ertn, void, env)
  DEF_HELPER_1(idle, void, env)
+DEF_HELPER_1(rdtime_d, i64, env)
+#endif


This is wrong.


  static bool trans_rdtimel_w(DisasContext *ctx, arg_rdtimel_w *a)
  {
+#ifdef CONFIG_USER_ONLY
+return cpu_get_host_ticks();


This is very wrong.  You're calling cpu_get_host_ticks at translation time.
There are no changes required during translation.

You should in fact be calling cpu_get_host_ticks in helper_rdtime_d.


  void helper_asrtle_d(CPULoongArchState *env, target_ulong rj, target_ulong rk)
  {
  if (rj > rk) {
+#ifdef CONFIG_USER_ONLY
+cpu_loop_exit_sigsegv(env_cpu(env), GETPC(),
+  MMU_DATA_LOAD, true, GETPC());
+#else
  do_raise_exception(env, EXCCODE_ADEM, GETPC());
+#endif


This change is wrong.  First, the kernel's do_ade raises SIGBUS.  Second, GETPC() is a 
host address, not a guest address.  Third, this highlights the fact that the existing 
system code is wrong, and should be setting badvaddr.


You need to
(1) set badvaddr here, and then
(2) handle EXCCODE_ADEM in linux-user/loongarch/cpu_loop.c to 
force_fix_fault(TARGET_SIGBUS, TARGET_BUS_ADRERR, env->badvaddr).



  void helper_asrtgt_d(CPULoongArchState *env, target_ulong rj, target_ulong rk)
  {
  if (rj <= rk) {
+#ifdef CONFIG_USER_ONLY
+cpu_loop_exit_sigsegv(env_cpu(env), GETPC(),
+  MMU_DATA_LOAD, true, GETPC());
+#else
  do_raise_exception(env, EXCCODE_ADEM, GETPC());
+#endif
  }
  }


Likewise.


r~



Re: [PATCH v2 1/2] hw: m25p80: add WP# pin and SRWD bit for write protection

2022-06-09 Thread Peter Delevoryas


> On Jun 9, 2022, at 12:22 PM, Francisco Iglesias  
> wrote:
> 
> Hi Iris,
> 
> Looks good some, a couple of comments below.
> 
> On [2022 Jun 08] Wed 20:13:19, Iris Chen wrote:
>> From: Iris Chen 
>> 
>> Signed-off-by: Iris Chen 
>> ---
>> Addressed all comments from V1. The biggest change: removed 
>> object_class_property_add.
>> 
>> hw/block/m25p80.c | 37 +++
>> tests/qtest/aspeed_smc-test.c |  2 ++
>> 2 files changed, 39 insertions(+)
>> 
>> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
>> index 81ba3da4df..1a20bd55d4 100644
>> --- a/hw/block/m25p80.c
>> +++ b/hw/block/m25p80.c
>> @@ -27,12 +27,14 @@
>> #include "hw/qdev-properties.h"
>> #include "hw/qdev-properties-system.h"
>> #include "hw/ssi/ssi.h"
>> +#include "hw/irq.h"
>> #include "migration/vmstate.h"
>> #include "qemu/bitops.h"
>> #include "qemu/log.h"
>> #include "qemu/module.h"
>> #include "qemu/error-report.h"
>> #include "qapi/error.h"
>> +#include "qapi/visitor.h"
>> #include "trace.h"
>> #include "qom/object.h"
>> 
>> @@ -472,11 +474,13 @@ struct Flash {
>> uint8_t spansion_cr2v;
>> uint8_t spansion_cr3v;
>> uint8_t spansion_cr4v;
>> +bool wp_level;
>> bool write_enable;
>> bool four_bytes_address_mode;
>> bool reset_enable;
>> bool quad_enable;
>> bool aai_enable;
>> +bool status_register_write_disabled;
>> uint8_t ear;
>> 
>> int64_t dirty_page;
>> @@ -723,6 +727,21 @@ static void complete_collecting_data(Flash *s)
>> flash_erase(s, s->cur_addr, s->cmd_in_progress);
>> break;
>> case WRSR:
>> +/*
>> + * If WP# is low and status_register_write_disabled is high,
>> + * status register writes are disabled.
>> + * This is also called "hardware protected mode" (HPM). All other
>> + * combinations of the two states are called "software protected 
>> mode"
>> + * (SPM), and status register writes are permitted.
>> + */
>> +if ((s->wp_level == 0 && s->status_register_write_disabled)
>> +|| !s->write_enable) {
> 
> 'write_enable' needs to be true in 'decode_new_cmd' when issueing the WRSR
> command, otherwise the state machinery will not advance to this function
> (meaning that above check for !s->write_enable will never hit as far as I can
> tell). A suggestion is to move the check for wp_level and
> status_reg_wr_disabled into 'decode_new_cmd' to for keeping it consistent.

Oh good catch! Yes actually, in our fork, we also removed the write_enable
guard in decode_new_cmd. We either need both checks in decode_new_cmd,
or both checks in complete_collecting_data.

I think we had some difficulty deciding whether to block command decoding,
or to decode and ignore the command if restrictions are enabled.

The reason being that, in the qtest, the WRSR command code gets ignored, and
then the subsequent write data gets interpreted as some random command code.
We had elected to decode and ignore the command, but I think the
datasheet actually describes that the command won’t be decoded successfully,
so you’re probably right, we should put this logic in decode_new_cmd.

Most likely, the qtest will also need to be modified to reset the transfer
state machine after a blocked write command. I can’t remember if
exiting and re-entering user mode is sufficient for that, but something
like that is probably possible.

Thanks for catching this!
Peter

> 
>> +qemu_log_mask(LOG_GUEST_ERROR,
>> +  "M25P80: Status register write is disabled!\n");
>> +break;
>> +}
>> +s->status_register_write_disabled = extract32(s->data[0], 7, 1);
>> +
>> switch (get_man(s)) {
>> case MAN_SPANSION:
>> s->quad_enable = !!(s->data[1] & 0x02);
>> @@ -1195,6 +1214,8 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>> 
>> case RDSR:
>> s->data[0] = (!!s->write_enable) << 1;
>> +s->data[0] |= (!!s->status_register_write_disabled) << 7;
>> +
>> if (get_man(s) == MAN_MACRONIX || get_man(s) == MAN_ISSI) {
>> s->data[0] |= (!!s->quad_enable) << 6;
>> }
>> @@ -1484,6 +1505,14 @@ static uint32_t m25p80_transfer8(SSIPeripheral *ss, 
>> uint32_t tx)
>> return r;
>> }
>> 
>> +static void m25p80_write_protect_pin_irq_handler(void *opaque, int n, int 
>> level)
>> +{
>> +Flash *s = M25P80(opaque);
>> +/* WP# is just a single pin. */
>> +assert(n == 0);
>> +s->wp_level = !!level;
>> +}
>> +
>> static void m25p80_realize(SSIPeripheral *ss, Error **errp)
>> {
>> Flash *s = M25P80(ss);
>> @@ -1515,12 +1544,18 @@ static void m25p80_realize(SSIPeripheral *ss, Error 
>> **errp)
>> s->storage = blk_blockalign(NULL, s->size);
>> memset(s->storage, 0xFF, s->size);
>> }
>> +
>> +qdev_init_gpio_in_named(DEVICE(s),
>> +m25p80_write_protect_pin_irq_handler, "WP#", 1);
>> }
>> 
>> static void 

Re: [PATCH 1/2] hw/nvme: Implement shadow doorbell buffer support

2022-06-09 Thread John Levon
On Thu, Jun 09, 2022 at 07:27:57PM +0200, Klaus Jensen wrote:

> > It's not just unnecessary, but enabling shadow doorbells on admin queues 
> > will
> > actively break device implementations (such as SPDK), which have had to 
> > presume
> > that driver implementations don't use shadow doorbells for the admin queue.
> 
> I'm ok with following the concensus here, but we all agree that this is
> a blatant spec violation that ended up manifesting itself down the
> stack, right?

Yup. I've been meaning to try following up to get the spec updated to reflect
reality, but haven't made progress there yet.

> So... if QEMU wants to be compliant here, I guess we could ask the
> kernel to introduce a quirk for *compliant* controllers. Now, THAT would
> be a first! Not sure if I am being serious or not here ;)

:)

regards
john



Re: [PATCH 2/2] semihosting/config: Merge --semihosting-config option groups

2022-06-09 Thread Luc Michel
On 20:00 Thu 26 May , Peter Maydell wrote:
> Currently we mishandle the --semihosting-config option if the
> user specifies it on the command line more than once. For
> example with:
>  --semihosting-config target=gdb --semihosting-config arg=foo,arg=bar
> 
> the function qemu_semihosting_config_options() is called twice, once
> for each argument.  But that function expects to be called only once,
> and it always unconditionally sets the semihosting.enabled,
> semihost_chardev and semihosting.target variables.  This means that
> if any of those options were set anywhere except the last
> --semihosting-config option on the command line, those settings are
> ignored.  In the example above, 'target=gdb' in the first option is
> overridden by an implied default 'target=auto' in the second.
> 
> The QemuOptsList machinery has a flag for handling this kind of
> "option group is setting global state": by setting
>  .merge_lists = true;
> we make the machinery merge all the --semihosting-config arguments
> the user passes into a single set of options and call our
> qemu_semihosting_config_options() just once.
> 
> Signed-off-by: Peter Maydell 

Reviewed-by: Luc Michel 

> ---
>  semihosting/config.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/semihosting/config.c b/semihosting/config.c
> index 50d82108e6e..3afacf54ab2 100644
> --- a/semihosting/config.c
> +++ b/semihosting/config.c
> @@ -27,6 +27,7 @@
>  
>  QemuOptsList qemu_semihosting_config_opts = {
>  .name = "semihosting-config",
> +.merge_lists = true,
>  .implied_opt_name = "enable",
>  .head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head),
>  .desc = {
> -- 
> 2.25.1
> 
> 

-- 



Re: [PATCH 1/2] gdbstub: Don't use GDB syscalls if no GDB is attached

2022-06-09 Thread Luc Michel
On 20:00 Thu 26 May , Peter Maydell wrote:
> In two places in gdbstub.c we look at gdbserver_state.init to decide
> whether we're going to do a semihosting syscall via the gdb remote
> protocol:
>  * when setting up, if the user didn't explicitly select either
>native semihosting or gdb semihosting, we autoselect, with the
>intended behaviour "use gdb if gdb is connected"
>  * when the semihosting layer attempts to do a syscall via gdb, we
>silently ignore it if the gdbstub wasn't actually set up
> 
> However, if the user's commandline sets up the gdbstub but tells QEMU
> to start rather than waiting for a GDB to connect (eg using '-s' but
> not '-S'), then we will have gdbserver_state.init true but no actual
> connection; an attempt to use gdb syscalls will then crash because we
> try to use gdbserver_state.c_cpu when it hasn't been set up:
> 
> #0  0x76803ba8 in qemu_cpu_kick (cpu=0x0) at ../../softmmu/cpus.c:457
> #1  0x76c03913 in gdb_do_syscallv (cb=0x76c19944 ,
> fmt=0x77573b7e "", va=0x756294c0) at ../../gdbstub.c:2946
> #2  0x76c19c3a in common_semi_gdb_syscall (cs=0x783fe060,
> cb=0x76c19944 , fmt=0x77573b75 "isatty,%x")
> at ../../semihosting/arm-compat-semi.c:494
> #3  0x76c1a064 in gdb_isattyfn (cs=0x783fe060, gf=0x786a3690)
> at ../../semihosting/arm-compat-semi.c:636
> #4  0x76c1b20f in do_common_semihosting (cs=0x783fe060)
> at ../../semihosting/arm-compat-semi.c:967
> #5  0x7693a037 in handle_semihosting (cs=0x783fe060)
> at ../../target/arm/helper.c:10316
> 
> You can probably also get into this state via some odd
> corner cases involving connecting a GDB and then telling it
> to detach from all the vCPUs.
> 
> Abstract out the test into a new gdb_attached() function
> which returns true only if there's actually a GDB connected
> to the debug stub and attached to at least one vCPU.
> 
> Reported-by: Liviu Ionescu 
> Signed-off-by: Peter Maydell 

Reviewed-by: Luc Michel 

> ---
> Silently doing nothing in gdb_do_syscallv(), never calling the
> callback function, is kind of dodgy.  But it's what the code is doing
> already, and besides it's not clear what we should do if the user
> specifically says "semihosting calls via the gdb stub" and then
> doesn't connect gdb...
> ---
>  gdbstub.c | 14 +++---
>  1 file changed, 11 insertions(+), 3 deletions(-)
> 
> diff --git a/gdbstub.c b/gdbstub.c
> index a3ff8702cef..88a34c8f522 100644
> --- a/gdbstub.c
> +++ b/gdbstub.c
> @@ -443,6 +443,15 @@ static int get_char(void)
>  }
>  #endif
>  
> +/*
> + * Return true if there is a GDB currently connected to the stub
> + * and attached to a CPU
> + */
> +static bool gdb_attached(void)
> +{
> +return gdbserver_state.init && gdbserver_state.c_cpu;
> +}
> +
>  static enum {
>  GDB_SYS_UNKNOWN,
>  GDB_SYS_ENABLED,
> @@ -464,8 +473,7 @@ int use_gdb_syscalls(void)
>  /* -semihosting-config target=auto */
>  /* On the first call check if gdb is connected and remember. */
>  if (gdb_syscall_mode == GDB_SYS_UNKNOWN) {
> -gdb_syscall_mode = gdbserver_state.init ?
> -GDB_SYS_ENABLED : GDB_SYS_DISABLED;
> +gdb_syscall_mode = gdb_attached() ? GDB_SYS_ENABLED : 
> GDB_SYS_DISABLED;
>  }
>  return gdb_syscall_mode == GDB_SYS_ENABLED;
>  }
> @@ -2886,7 +2894,7 @@ void gdb_do_syscallv(gdb_syscall_complete_cb cb, const 
> char *fmt, va_list va)
>  target_ulong addr;
>  uint64_t i64;
>  
> -if (!gdbserver_state.init) {
> +if (!gdb_attached()) {
>  return;
>  }
>  
> -- 
> 2.25.1
> 
> 

-- 
+-+--+
| Luc MICHEL  | TIMA Lab / SLS Team  |
| | Phone: +33 4 76 57 43 34 |
+-+--+



Re: [PATCH 2/2] linux-aio: explain why max batch is checked in laio_io_unplug()

2022-06-09 Thread Stefano Garzarella

On Thu, Jun 09, 2022 at 05:47:12PM +0100, Stefan Hajnoczi wrote:

It may not be obvious why laio_io_unplug() checks max batch. I discussed
this with Stefano and have added a comment summarizing the reason.

Cc: Stefano Garzarella 
Cc: Kevin Wolf 
Signed-off-by: Stefan Hajnoczi 
---
block/linux-aio.c | 6 ++
1 file changed, 6 insertions(+)

diff --git a/block/linux-aio.c b/block/linux-aio.c
index 6078da7e42..9c2393a2f7 100644
--- a/block/linux-aio.c
+++ b/block/linux-aio.c
@@ -365,6 +365,12 @@ void laio_io_unplug(BlockDriverState *bs, LinuxAioState *s,
assert(s->io_q.plugged);
s->io_q.plugged--;

+/*
+ * Why max batch checking is performed here:
+ * Another BDS may have queued requests with a higher dev_max_batch and
+ * therefore in_queue could now exceed our dev_max_batch. Re-check the max
+ * batch so we can honor our device's dev_max_batch.
+ */
if (s->io_q.in_queue >= laio_max_batch(s, dev_max_batch) ||
(!s->io_q.plugged &&
 !s->io_q.blocked && !QSIMPLEQ_EMPTY(>io_q.pending))) {
--
2.36.1



I should have added that...

Reviewed-by: Stefano Garzarella 




Re: [PATCH 1/2] linux-aio: fix unbalanced plugged counter in laio_io_unplug()

2022-06-09 Thread Stefano Garzarella

On Thu, Jun 09, 2022 at 05:47:11PM +0100, Stefan Hajnoczi wrote:

Every laio_io_plug() call has a matching laio_io_unplug() call. There is
a plugged counter that tracks the number of levels of plugging and
allows for nesting.

The plugged counter must reflect the balance between laio_io_plug() and
laio_io_unplug() calls accurately. Otherwise I/O stalls occur since
io_submit(2) calls are skipped while plugged.



We can add a Fixes tag:

Fixes: 68d7946648 ("linux-aio: add `dev_max_batch` parameter to 
laio_io_unplug()")


Reported-by: Nikolay Tenev 
Cc: Stefano Garzarella 
Signed-off-by: Stefan Hajnoczi 
---
block/linux-aio.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/block/linux-aio.c b/block/linux-aio.c
index 4c423fcccf..6078da7e42 100644
--- a/block/linux-aio.c
+++ b/block/linux-aio.c
@@ -363,8 +363,10 @@ void laio_io_unplug(BlockDriverState *bs, LinuxAioState *s,
uint64_t dev_max_batch)
{
assert(s->io_q.plugged);
+s->io_q.plugged--;
+
if (s->io_q.in_queue >= laio_max_batch(s, dev_max_batch) ||
-(--s->io_q.plugged == 0 &&
+(!s->io_q.plugged &&
 !s->io_q.blocked && !QSIMPLEQ_EMPTY(>io_q.pending))) {
ioq_submit(s);
}
--
2.36.1



Thanks for fixing this issue!

Reviewed-by: Stefano Garzarella 




Re: [PULL 0/3] xen queue 2022-06-09

2022-06-09 Thread Richard Henderson

On 6/9/22 07:01, Anthony PERARD via wrote:

The following changes since commit 05911658cb46d907fb38cbc0b48d2b652237dc28:

   Merge tag 'vfio-updates-20220608.0' of 
https://gitlab.com/alex.williamson/qemu into staging (2022-06-08 13:38:54 -0700)

are available in the Git repository at:

   https://xenbits.xen.org/git-http/people/aperard/qemu-dm.git 
tags/pull-xen-20220609

for you to fetch changes up to 6a8a8b62bdc8e3d7c5fc0f82ef4583707183b12f:

   include/hw/ide: Unexport pci_piix3_xen_ide_unplug() (2022-06-09 14:47:42 
+0100)


Xen patches

- PIIX3-IDE Xen cleanup


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


r~





Bernhard Beschow (3):
   hw/ide/piix: Remove redundant "piix3-ide-xen" device class
   hw/ide/piix: Add some documentation to pci_piix3_xen_ide_unplug()
   include/hw/ide: Unexport pci_piix3_xen_ide_unplug()

  hw/i386/pc_piix.c  |  3 +--
  hw/i386/xen/xen_platform.c | 48 +-
  hw/ide/piix.c  | 42 
  include/hw/ide.h   |  3 ---
  4 files changed, 48 insertions(+), 48 deletions(-)






[PULL 02/18] block: get rid of blk->guest_block_size

2022-06-09 Thread Kevin Wolf
From: Stefan Hajnoczi 

Commit 1b7fd729559c ("block: rename buffer_alignment to
guest_block_size") noted:

  At this point, the field is set by the device emulation, but completely
  ignored by the block layer.

The last time the value of buffer_alignment/guest_block_size was
actually used was before commit 339064d50639 ("block: Don't use guest
sector size for qemu_blockalign()").

This value has not been used since 2013. Get rid of it.

Cc: Xie Yongji 
Signed-off-by: Stefan Hajnoczi 
Message-Id: <20220518130945.2657905-1-stefa...@redhat.com>
Reviewed-by: Paul Durrant 
Reviewed-by: Eric Blake 
Reviewed-by: Alberto Faria 
Signed-off-by: Kevin Wolf 
---
 include/sysemu/block-backend-io.h|  1 -
 block/block-backend.c| 10 --
 block/export/vhost-user-blk-server.c |  1 -
 hw/block/virtio-blk.c|  1 -
 hw/block/xen-block.c |  1 -
 hw/ide/core.c|  1 -
 hw/scsi/scsi-disk.c  |  1 -
 hw/scsi/scsi-generic.c   |  1 -
 8 files changed, 17 deletions(-)

diff --git a/include/sysemu/block-backend-io.h 
b/include/sysemu/block-backend-io.h
index 6517c39295..ccef514023 100644
--- a/include/sysemu/block-backend-io.h
+++ b/include/sysemu/block-backend-io.h
@@ -72,7 +72,6 @@ void blk_error_action(BlockBackend *blk, BlockErrorAction 
action,
 void blk_iostatus_set_err(BlockBackend *blk, int error);
 int blk_get_max_iov(BlockBackend *blk);
 int blk_get_max_hw_iov(BlockBackend *blk);
-void blk_set_guest_block_size(BlockBackend *blk, int align);
 
 void blk_io_plug(BlockBackend *blk);
 void blk_io_unplug(BlockBackend *blk);
diff --git a/block/block-backend.c b/block/block-backend.c
index e0e1aff4b1..d4abdf8faa 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -56,9 +56,6 @@ struct BlockBackend {
 const BlockDevOps *dev_ops;
 void *dev_opaque;
 
-/* the block size for which the guest device expects atomicity */
-int guest_block_size;
-
 /* If the BDS tree is removed, some of its options are stored here (which
  * can be used to restore those options in the new BDS on insert) */
 BlockBackendRootState root_state;
@@ -998,7 +995,6 @@ void blk_detach_dev(BlockBackend *blk, DeviceState *dev)
 blk->dev = NULL;
 blk->dev_ops = NULL;
 blk->dev_opaque = NULL;
-blk->guest_block_size = 512;
 blk_set_perm(blk, 0, BLK_PERM_ALL, _abort);
 blk_unref(blk);
 }
@@ -2100,12 +2096,6 @@ int blk_get_max_iov(BlockBackend *blk)
 return blk->root->bs->bl.max_iov;
 }
 
-void blk_set_guest_block_size(BlockBackend *blk, int align)
-{
-IO_CODE();
-blk->guest_block_size = align;
-}
-
 void *blk_try_blockalign(BlockBackend *blk, size_t size)
 {
 IO_CODE();
diff --git a/block/export/vhost-user-blk-server.c 
b/block/export/vhost-user-blk-server.c
index a129204c44..b2e458ade3 100644
--- a/block/export/vhost-user-blk-server.c
+++ b/block/export/vhost-user-blk-server.c
@@ -495,7 +495,6 @@ static int vu_blk_exp_create(BlockExport *exp, 
BlockExportOptions *opts,
 return -EINVAL;
 }
 vexp->blk_size = logical_block_size;
-blk_set_guest_block_size(exp->blk, logical_block_size);
 
 if (vu_opts->has_num_queues) {
 num_queues = vu_opts->num_queues;
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index cd804795c6..e9ba752f6b 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -1228,7 +1228,6 @@ static void virtio_blk_device_realize(DeviceState *dev, 
Error **errp)
 
 s->change = qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
 blk_set_dev_ops(s->blk, _block_ops, s);
-blk_set_guest_block_size(s->blk, s->conf.conf.logical_block_size);
 
 blk_iostatus_enable(s->blk);
 
diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c
index 674953f1ad..345b284d70 100644
--- a/hw/block/xen-block.c
+++ b/hw/block/xen-block.c
@@ -243,7 +243,6 @@ static void xen_block_realize(XenDevice *xendev, Error 
**errp)
 }
 
 blk_set_dev_ops(blk, _block_dev_ops, blockdev);
-blk_set_guest_block_size(blk, conf->logical_block_size);
 
 if (conf->discard_granularity == -1) {
 conf->discard_granularity = conf->physical_block_size;
diff --git a/hw/ide/core.c b/hw/ide/core.c
index c2caa54285..7cbc0a54a7 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2548,7 +2548,6 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, 
IDEDriveKind kind,
 s->smart_selftest_count = 0;
 if (kind == IDE_CD) {
 blk_set_dev_ops(blk, _cd_block_ops, s);
-blk_set_guest_block_size(blk, 2048);
 } else {
 if (!blk_is_inserted(s->blk)) {
 error_setg(errp, "Device needs media, but drive is empty");
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 072686ed58..91acb5c0ce 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -2419,7 +2419,6 @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
 } else {
 blk_set_dev_ops(s->qdev.conf.blk, 

[PULL 01/18] block: drop unused bdrv_co_drain() API

2022-06-09 Thread Kevin Wolf
From: Stefan Hajnoczi 

bdrv_co_drain() has not been used since commit 9a0cec664eef ("mirror:
use bdrv_drained_begin/bdrv_drained_end") in 2016. Remove it so there
are fewer drain scenarios to worry about.

Use bdrv_drained_begin()/bdrv_drained_end() instead. They are "mixed"
functions that can be called from coroutine context. Unlike
bdrv_co_drain(), these functions provide control of the length of the
drained section, which is usually the right thing.

Signed-off-by: Stefan Hajnoczi 
Message-Id: <20220521122714.3837731-1-stefa...@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito 
Reviewed-by: Alberto Faria 
Signed-off-by: Kevin Wolf 
---
 include/block/block-io.h |  1 -
 block/io.c   | 15 ---
 2 files changed, 16 deletions(-)

diff --git a/include/block/block-io.h b/include/block/block-io.h
index 62c84f0519..053a27141a 100644
--- a/include/block/block-io.h
+++ b/include/block/block-io.h
@@ -270,7 +270,6 @@ void bdrv_drained_end_no_poll(BlockDriverState *bs, int 
*drained_end_counter);
cond); })
 
 void bdrv_drain(BlockDriverState *bs);
-void coroutine_fn bdrv_co_drain(BlockDriverState *bs);
 
 int generated_co_wrapper
 bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
diff --git a/block/io.c b/block/io.c
index 789e6373d5..1e9bf09a49 100644
--- a/block/io.c
+++ b/block/io.c
@@ -588,21 +588,6 @@ void bdrv_unapply_subtree_drain(BdrvChild *child, 
BlockDriverState *old_parent)
 BDRV_POLL_WHILE(child->bs, qatomic_read(_end_counter) > 0);
 }
 
-/*
- * Wait for pending requests to complete on a single BlockDriverState subtree,
- * and suspend block driver's internal I/O until next request arrives.
- *
- * Note that unlike bdrv_drain_all(), the caller must hold the BlockDriverState
- * AioContext.
- */
-void coroutine_fn bdrv_co_drain(BlockDriverState *bs)
-{
-IO_OR_GS_CODE();
-assert(qemu_in_coroutine());
-bdrv_drained_begin(bs);
-bdrv_drained_end(bs);
-}
-
 void bdrv_drain(BlockDriverState *bs)
 {
 IO_OR_GS_CODE();
-- 
2.35.3




[PULL 05/18] block: simplify handling of try to merge different sized bitmaps

2022-06-09 Thread Kevin Wolf
From: Vladimir Sementsov-Ogievskiy 

We have too much logic to simply check that bitmaps are of the same
size. Let's just define that hbitmap_merge() and
bdrv_dirty_bitmap_merge_internal() require their argument bitmaps be of
same size, this simplifies things.

Let's look through the callers:

For backup_init_bcs_bitmap() we already assert that merge can't fail.

In bdrv_reclaim_dirty_bitmap_locked() we gracefully handle the error
that can't happen: successor always has same size as its parent, drop
this logic.

In bdrv_merge_dirty_bitmap() we already has assertion and separate
check. Make the check explicit and improve error message.

Signed-off-by: Vladimir Sementsov-Ogievskiy 
Reviewed-by: Nikita Lapshin 
Reviewed-by: Kevin Wolf 
Message-Id: <20220517111206.23585-4-v.sementsov...@mail.ru>
Signed-off-by: Kevin Wolf 
---
 include/block/block_int-io.h |  2 +-
 include/qemu/hbitmap.h   | 15 ++-
 block/backup.c   |  6 ++
 block/dirty-bitmap.c | 26 +++---
 util/hbitmap.c   | 25 +++--
 5 files changed, 23 insertions(+), 51 deletions(-)

diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
index bb454200e5..ded29e7494 100644
--- a/include/block/block_int-io.h
+++ b/include/block/block_int-io.h
@@ -102,7 +102,7 @@ bool blk_dev_is_tray_open(BlockBackend *blk);
 void bdrv_set_dirty(BlockDriverState *bs, int64_t offset, int64_t bytes);
 
 void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out);
-bool bdrv_dirty_bitmap_merge_internal(BdrvDirtyBitmap *dest,
+void bdrv_dirty_bitmap_merge_internal(BdrvDirtyBitmap *dest,
   const BdrvDirtyBitmap *src,
   HBitmap **backup, bool lock);
 
diff --git a/include/qemu/hbitmap.h b/include/qemu/hbitmap.h
index 5bd986aa44..af4e4ab746 100644
--- a/include/qemu/hbitmap.h
+++ b/include/qemu/hbitmap.h
@@ -76,20 +76,9 @@ void hbitmap_truncate(HBitmap *hb, uint64_t size);
  *
  * Store result of merging @a and @b into @result.
  * @result is allowed to be equal to @a or @b.
- *
- * Return true if the merge was successful,
- *false if it was not attempted.
- */
-bool hbitmap_merge(const HBitmap *a, const HBitmap *b, HBitmap *result);
-
-/**
- * hbitmap_can_merge:
- *
- * hbitmap_can_merge(a, b) && hbitmap_can_merge(a, result) is sufficient and
- * necessary for hbitmap_merge will not fail.
- *
+ * All bitmaps must have same size.
  */
-bool hbitmap_can_merge(const HBitmap *a, const HBitmap *b);
+void hbitmap_merge(const HBitmap *a, const HBitmap *b, HBitmap *result);
 
 /**
  * hbitmap_empty:
diff --git a/block/backup.c b/block/backup.c
index 5cfd0b999c..b2b649e305 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -228,15 +228,13 @@ out:
 
 static void backup_init_bcs_bitmap(BackupBlockJob *job)
 {
-bool ret;
 uint64_t estimate;
 BdrvDirtyBitmap *bcs_bitmap = block_copy_dirty_bitmap(job->bcs);
 
 if (job->sync_mode == MIRROR_SYNC_MODE_BITMAP) {
 bdrv_clear_dirty_bitmap(bcs_bitmap, NULL);
-ret = bdrv_dirty_bitmap_merge_internal(bcs_bitmap, job->sync_bitmap,
-   NULL, true);
-assert(ret);
+bdrv_dirty_bitmap_merge_internal(bcs_bitmap, job->sync_bitmap, NULL,
+ true);
 } else if (job->sync_mode == MIRROR_SYNC_MODE_TOP) {
 /*
  * We can't hog the coroutine to initialize this thoroughly.
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index da1b91166f..bf3dc0512a 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -309,10 +309,7 @@ BdrvDirtyBitmap 
*bdrv_reclaim_dirty_bitmap_locked(BdrvDirtyBitmap *parent,
 return NULL;
 }
 
-if (!hbitmap_merge(parent->bitmap, successor->bitmap, parent->bitmap)) {
-error_setg(errp, "Merging of parent and successor bitmap failed");
-return NULL;
-}
+hbitmap_merge(parent->bitmap, successor->bitmap, parent->bitmap);
 
 parent->disabled = successor->disabled;
 parent->busy = false;
@@ -912,13 +909,15 @@ bool bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const 
BdrvDirtyBitmap *src,
 goto out;
 }
 
-if (!hbitmap_can_merge(dest->bitmap, src->bitmap)) {
-error_setg(errp, "Bitmaps are incompatible and can't be merged");
+if (bdrv_dirty_bitmap_size(src) != bdrv_dirty_bitmap_size(dest)) {
+error_setg(errp, "Bitmaps are of different sizes (destination size is 
%"
+   PRId64 ", source size is %" PRId64 ") and can't be merged",
+   bdrv_dirty_bitmap_size(dest), bdrv_dirty_bitmap_size(src));
 goto out;
 }
 
-ret = bdrv_dirty_bitmap_merge_internal(dest, src, backup, false);
-assert(ret);
+bdrv_dirty_bitmap_merge_internal(dest, src, backup, false);
+ret = true;
 
 out:
 bdrv_dirty_bitmaps_unlock(dest->bs);
@@ -932,17 +931,16 @@ out:
 /**
  * 

[PULL 07/18] block/export: Fix incorrect length passed to vu_queue_push()

2022-06-09 Thread Kevin Wolf
From: Xie Yongji 

Now the req->size is set to the correct value only
when handling VIRTIO_BLK_T_GET_ID request. This patch
fixes it.

Signed-off-by: Xie Yongji 
Message-Id: <20220523084611.91-3-xieyon...@bytedance.com>
Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Kevin Wolf 
---
 block/export/vhost-user-blk-server.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/block/export/vhost-user-blk-server.c 
b/block/export/vhost-user-blk-server.c
index b2e458ade3..19c6ee51d3 100644
--- a/block/export/vhost-user-blk-server.c
+++ b/block/export/vhost-user-blk-server.c
@@ -60,8 +60,7 @@ static void vu_blk_req_complete(VuBlkReq *req)
 {
 VuDev *vu_dev = >server->vu_dev;
 
-/* IO size with 1 extra status byte */
-vu_queue_push(vu_dev, req->vq, >elem, req->size + 1);
+vu_queue_push(vu_dev, req->vq, >elem, req->size);
 vu_queue_notify(vu_dev, req->vq);
 
 free(req);
@@ -207,6 +206,7 @@ static void coroutine_fn vu_blk_virtio_process_req(void 
*opaque)
 goto err;
 }
 
+req->size = iov_size(in_iov, in_num);
 /* We always touch the last byte, so just see how big in_iov is.  */
 req->in = (void *)in_iov[in_num - 1].iov_base
   + in_iov[in_num - 1].iov_len
@@ -267,7 +267,6 @@ static void coroutine_fn vu_blk_virtio_process_req(void 
*opaque)
   VIRTIO_BLK_ID_BYTES);
 snprintf(elem->in_sg[0].iov_base, size, "%s", "vhost_user_blk");
 req->in->status = VIRTIO_BLK_S_OK;
-req->size = elem->in_sg[0].iov_len;
 break;
 }
 case VIRTIO_BLK_T_DISCARD:
-- 
2.35.3




[PULL 04/18] block: improve block_dirty_bitmap_merge(): don't allocate extra bitmap

2022-06-09 Thread Kevin Wolf
From: Vladimir Sementsov-Ogievskiy 

We don't need extra bitmap. All we need is to backup the original
bitmap when we do first merge. So, drop extra temporary bitmap and work
directly with target and backup.

Still to keep old semantics, that on failure target is unchanged and
user don't need to restore, we need a local_backup variable and do
restore ourselves on failure path.

Signed-off-by: Vladimir Sementsov-Ogievskiy 
Message-Id: <20220517111206.23585-3-v.sementsov...@mail.ru>
Reviewed-by: Eric Blake 
Signed-off-by: Kevin Wolf 
---
 block/monitor/bitmap-qmp-cmds.c | 41 +
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/block/monitor/bitmap-qmp-cmds.c b/block/monitor/bitmap-qmp-cmds.c
index bd10468596..282363606f 100644
--- a/block/monitor/bitmap-qmp-cmds.c
+++ b/block/monitor/bitmap-qmp-cmds.c
@@ -261,8 +261,9 @@ BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, 
const char *target,
   HBitmap **backup, Error **errp)
 {
 BlockDriverState *bs;
-BdrvDirtyBitmap *dst, *src, *anon;
+BdrvDirtyBitmap *dst, *src;
 BlockDirtyBitmapOrStrList *lst;
+HBitmap *local_backup = NULL;
 
 GLOBAL_STATE_CODE();
 
@@ -271,12 +272,6 @@ BdrvDirtyBitmap *block_dirty_bitmap_merge(const char 
*node, const char *target,
 return NULL;
 }
 
-anon = bdrv_create_dirty_bitmap(bs, bdrv_dirty_bitmap_granularity(dst),
-NULL, errp);
-if (!anon) {
-return NULL;
-}
-
 for (lst = bms; lst; lst = lst->next) {
 switch (lst->value->type) {
 const char *name, *node;
@@ -285,8 +280,7 @@ BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, 
const char *target,
 src = bdrv_find_dirty_bitmap(bs, name);
 if (!src) {
 error_setg(errp, "Dirty bitmap '%s' not found", name);
-dst = NULL;
-goto out;
+goto fail;
 }
 break;
 case QTYPE_QDICT:
@@ -294,29 +288,36 @@ BdrvDirtyBitmap *block_dirty_bitmap_merge(const char 
*node, const char *target,
 name = lst->value->u.external.name;
 src = block_dirty_bitmap_lookup(node, name, NULL, errp);
 if (!src) {
-dst = NULL;
-goto out;
+goto fail;
 }
 break;
 default:
 abort();
 }
 
-if (!bdrv_merge_dirty_bitmap(anon, src, NULL, errp)) {
-dst = NULL;
-goto out;
+/* We do backup only for first merge operation */
+if (!bdrv_merge_dirty_bitmap(dst, src,
+ local_backup ? NULL : _backup,
+ errp))
+{
+goto fail;
 }
 }
 
-/* Merge into dst; dst is unchanged on failure. */
-if (!bdrv_merge_dirty_bitmap(dst, anon, backup, errp)) {
-dst = NULL;
-goto out;
+if (backup) {
+*backup = local_backup;
+} else {
+hbitmap_free(local_backup);
 }
 
- out:
-bdrv_release_dirty_bitmap(anon);
 return dst;
+
+fail:
+if (local_backup) {
+bdrv_restore_dirty_bitmap(dst, local_backup);
+}
+
+return NULL;
 }
 
 void qmp_block_dirty_bitmap_merge(const char *node, const char *target,
-- 
2.35.3




Re: What to do with the nanomips disassembler (was: [PATCH] disas: Remove libvixl disassembler)

2022-06-09 Thread Thomas Huth

On 09/06/2022 18.31, Vince Del Vecchio wrote:

On Thu, Jun 9, 2022 at 10:34AM, Thomas Huth wrote:

On 09/06/2022 16.15, Claudio Fontana wrote:

On 6/9/22 13:27, Claudio Fontana wrote:

On 6/9/22 10:57, Daniel P. Berrangé wrote:

On Thu, Jun 09, 2022 at 10:47:24AM +0200, Thomas Huth wrote:

On 08/06/2022 17.51, Paolo Bonzini wrote:

On 6/3/22 19:35, Thomas Huth wrote:

On 03/06/2022 19.26, Claudio Fontana wrote:

[...]

maybe something we can now drop if there are no more C++ users?


I thought about that, too, but we still have disas/nanomips.cpp
left and the Windows-related files in qga/vss-win32/* .


That is pure C++ so it does not need the extra complication of
"detect whether the C and C++ compiler are ABI-compatible"
(typically due to different libasan/libtsan implementation between
gcc and clang).  So it's really just nanoMIPS that's left.


Ok, so the next theoretical question is: If we get rid of the
nanomips.cpp file or convert it to plain C, would we then simplify
the code in configure again (and forbid C++ for the main QEMU
code), or would we rather keep the current settings in case we want
to re-introduce more C++ code again in the future?


It doesn't feel very compelling to have just 1 source file that's
C++ in QEMU. I'm curious how we ended up with this nanomips.cpp
file - perhaps it originated from another project that was C++ based
?

The code itself doesn't look like it especially needs to be using
C++. There's just 1 class there and every method is associated
with that class, and external entry point from the rest of QEMU is
just one boring method. Feels like it could easily have been done in
C.

Personally I'd prefer it to be converted to C, and if we want to add
any C++ in future it should be justified & debated on its merits,
rather than as an artifact of any historical artifacts such as the
code in configure happening to still exist.


I'll take a look at it, maybe I can turn it to C fairly quickly.


It seems to be generated code, getting the original authors involved in the 
thread.


Not sure whether the original mips folks are still around ... but the folks 
from MediaTek recently expressed their interest in nanoMIPS:

  
https://lore.kernel.org/qemu-devel/20220504110403.613168-8-stefan.pe...@syrmia.com/


Maybe they could help with the nanoMIPS disassembler?

I know it's likely a lot of work, but the best solution would maybe be to add 
nanoMIPS support to capstone instead, then other projects could benefit from 
the support in this library, too...

If I googled that right, there is a LLVM implementation of nanoMIPS available 
here:

  
https://github.com/milos1397/nanomips-outliner/tree/master/llvm/lib/Target/Mips


... so maybe that could be used as input for capstone (which is based on llvm)?

  Thomas


Yes, we are working on an LLVM port for nanoMIPS.  It's functionally complete 
and pretty usable, although we're still tuning performance.  The more official 
location is https://github.com/MediaTek-Labs/llvm-project.

However, for now we're still using the binutils assembler; there's no encoding 
information in the current LLVM description.  We have tentative plans to work 
on encoding and integrated-as later this year.  Correct me if I'm wrong, but I 
would assume that, before that's available, it's not feasible to use capstone?


I'm also not very familiar with the way capstone translated the information 
from LLVM into its disassembler source files, but I guess you're right - 
this likely cannot work yet.



Regardless, I think we can look at converting the existing disassembler from 
C++ to C.  That would address the current concern, right?


Right - if it's not too much of a hassle that would be great!

 Thomas




Re: [PATCH 17/20] migration: remove the QEMUFileOps 'get_buffer' callback

2022-06-09 Thread Daniel P . Berrangé
On Thu, Jun 09, 2022 at 05:46:29PM +0100, Dr. David Alan Gilbert wrote:
> * Daniel P. Berrangé (berra...@redhat.com) wrote:
> > This directly implements the get_buffer logic using QIOChannel APIs.
> > 
> > Signed-off-by: Daniel P. Berrangé 
> > ---
> >  migration/qemu-file-channel.c | 29 -
> >  migration/qemu-file.c | 18 --
> >  migration/qemu-file.h |  9 -
> >  3 files changed, 16 insertions(+), 40 deletions(-)
> > 
> > diff --git a/migration/qemu-file-channel.c b/migration/qemu-file-channel.c
> > index 8ff58e81f9..7b32831752 100644
> > --- a/migration/qemu-file-channel.c
> > +++ b/migration/qemu-file-channel.c
> > @@ -74,34 +74,6 @@ static ssize_t channel_writev_buffer(void *opaque,
> >  }
> >  
> >  
> > -static ssize_t channel_get_buffer(void *opaque,
> > -  uint8_t *buf,
> > -  int64_t pos,
> > -  size_t size,
> > -  Error **errp)
> > -{
> > -QIOChannel *ioc = QIO_CHANNEL(opaque);
> > -ssize_t ret;
> > -
> > -do {
> > -ret = qio_channel_read(ioc, (char *)buf, size, errp);
> > -if (ret < 0) {
> > -if (ret == QIO_CHANNEL_ERR_BLOCK) {
> > -if (qemu_in_coroutine()) {
> > -qio_channel_yield(ioc, G_IO_IN);
> > -} else {
> > -qio_channel_wait(ioc, G_IO_IN);
> > -}
> > -} else {
> > -return -EIO;
> > -}
> > -}
> > -} while (ret == QIO_CHANNEL_ERR_BLOCK);
> > -
> > -return ret;
> > -}
> > -
> > -
> >  static QEMUFile *channel_get_input_return_path(void *opaque)
> >  {
> >  QIOChannel *ioc = QIO_CHANNEL(opaque);
> > @@ -117,7 +89,6 @@ static QEMUFile *channel_get_output_return_path(void 
> > *opaque)
> >  }
> >  
> >  static const QEMUFileOps channel_input_ops = {
> > -.get_buffer = channel_get_buffer,
> >  .get_return_path = channel_get_input_return_path,
> >  };
> >  
> > diff --git a/migration/qemu-file.c b/migration/qemu-file.c
> > index a855ce33dc..e024b43851 100644
> > --- a/migration/qemu-file.c
> > +++ b/migration/qemu-file.c
> > @@ -374,8 +374,22 @@ static ssize_t qemu_fill_buffer(QEMUFile *f)
> >  return 0;
> >  }
> >  
> > -len = f->ops->get_buffer(f->ioc, f->buf + pending, 
> > f->total_transferred,
> > - IO_BUF_SIZE - pending, _error);
> > +do {
> > +len = qio_channel_read(f->ioc,
> 
> Yes, I think that's OK - not that 'len' is an int where 'ret'
> was a ssize_t; but I think our buffers are guranteed to be 'small'.

There are a few places in qemu-file.c where we're fast & loose
with int rather than size_t, that are probably worth cleaning.

> Reviewed-by: Dr. David Alan Gilbert 

With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH 1/2] hw/nvme: Implement shadow doorbell buffer support

2022-06-09 Thread Klaus Jensen
On Jun  9 16:52, John Levon wrote:
> On Thu, Jun 09, 2022 at 08:29:30AM -0600, Keith Busch wrote:
> 
> > On Wed, Jun 08, 2022 at 10:55:30PM +0200, Klaus Jensen wrote:
> > > 
> > > Keith, is this a bug in the kernel? If the code here would expect the
> > > doorbell buffer to be updated for the admin queue as well, would we
> > > break?
> > 
> > The admin queue has to be created before db buffer can be set up, so we 
> > can't
> > rely on it. And this is a performance feature. Admin commands have never 
> > been
> > considered performant, so we decided not to consider it though the spec 
> > allows
> > it.

It's not really a question of whether or not the spec *allows* it. If
our device chooses to be compliant here, then it will read invalid
doorbell values if drivers doesnt update the admin doorbell buffer.

> 
> It's not just unnecessary, but enabling shadow doorbells on admin queues will
> actively break device implementations (such as SPDK), which have had to 
> presume
> that driver implementations don't use shadow doorbells for the admin queue.
> 

I'm ok with following the concensus here, but we all agree that this is
a blatant spec violation that ended up manifesting itself down the
stack, right?

So... if QEMU wants to be compliant here, I guess we could ask the
kernel to introduce a quirk for *compliant* controllers. Now, THAT would
be a first! Not sure if I am being serious or not here ;)


signature.asc
Description: PGP signature


Re: [PATCH 20/20] migration: remove the QEMUFileOps abstraction

2022-06-09 Thread Dr. David Alan Gilbert
* Daniel P. Berrangé (berra...@redhat.com) wrote:
> Now that all QEMUFile callbacks are removed, the entire concept can be
> deleted.
> 
> Signed-off-by: Daniel P. Berrangé 

I think that's OK, there's one nit - you remove qemu_get_fd from one of
the headers; I think that probably belongs in an earlier patch.

Other than that,


Reviewed-by: Dr. David Alan Gilbert 

> ---
>  migration/channel.c   |  4 +--
>  migration/colo.c  |  5 ++--
>  migration/meson.build |  1 -
>  migration/migration.c |  7 ++---
>  migration/qemu-file-channel.c | 53 ---
>  migration/qemu-file-channel.h | 32 -
>  migration/qemu-file.c | 20 ++---
>  migration/qemu-file.h |  8 ++
>  migration/ram.c   |  3 +-
>  migration/rdma.c  |  5 ++--
>  migration/savevm.c| 11 
>  tests/unit/test-vmstate.c |  5 ++--
>  12 files changed, 27 insertions(+), 127 deletions(-)
>  delete mode 100644 migration/qemu-file-channel.c
>  delete mode 100644 migration/qemu-file-channel.h
> 
> diff --git a/migration/channel.c b/migration/channel.c
> index a162d00fea..90087d8986 100644
> --- a/migration/channel.c
> +++ b/migration/channel.c
> @@ -14,7 +14,7 @@
>  #include "channel.h"
>  #include "tls.h"
>  #include "migration.h"
> -#include "qemu-file-channel.h"
> +#include "qemu-file.h"
>  #include "trace.h"
>  #include "qapi/error.h"
>  #include "io/channel-tls.h"
> @@ -85,7 +85,7 @@ void migration_channel_connect(MigrationState *s,
>  return;
>  }
>  } else {
> -QEMUFile *f = qemu_fopen_channel_output(ioc);
> +QEMUFile *f = qemu_file_new_output(ioc);
>  
>  migration_ioc_register_yank(ioc);
>  
> diff --git a/migration/colo.c b/migration/colo.c
> index 5f7071b3cd..2b71722fd6 100644
> --- a/migration/colo.c
> +++ b/migration/colo.c
> @@ -14,7 +14,6 @@
>  #include "sysemu/sysemu.h"
>  #include "qapi/error.h"
>  #include "qapi/qapi-commands-migration.h"
> -#include "qemu-file-channel.h"
>  #include "migration.h"
>  #include "qemu-file.h"
>  #include "savevm.h"
> @@ -559,7 +558,7 @@ static void colo_process_checkpoint(MigrationState *s)
>  goto out;
>  }
>  bioc = qio_channel_buffer_new(COLO_BUFFER_BASE_SIZE);
> -fb = qemu_fopen_channel_output(QIO_CHANNEL(bioc));
> +fb = qemu_file_new_output(QIO_CHANNEL(bioc));
>  object_unref(OBJECT(bioc));
>  
>  qemu_mutex_lock_iothread();
> @@ -873,7 +872,7 @@ void *colo_process_incoming_thread(void *opaque)
>  colo_incoming_start_dirty_log();
>  
>  bioc = qio_channel_buffer_new(COLO_BUFFER_BASE_SIZE);
> -fb = qemu_fopen_channel_input(QIO_CHANNEL(bioc));
> +fb = qemu_file_new_input(QIO_CHANNEL(bioc));
>  object_unref(OBJECT(bioc));
>  
>  qemu_mutex_lock_iothread();
> diff --git a/migration/meson.build b/migration/meson.build
> index 8d309f5849..690487cf1a 100644
> --- a/migration/meson.build
> +++ b/migration/meson.build
> @@ -4,7 +4,6 @@ migration_files = files(
>'xbzrle.c',
>'vmstate-types.c',
>'vmstate.c',
> -  'qemu-file-channel.c',
>'qemu-file.c',
>'yank_functions.c',
>  )
> diff --git a/migration/migration.c b/migration/migration.c
> index ab1e9610ef..8a30ef17d9 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -30,7 +30,6 @@
>  #include "migration/misc.h"
>  #include "migration.h"
>  #include "savevm.h"
> -#include "qemu-file-channel.h"
>  #include "qemu-file.h"
>  #include "migration/vmstate.h"
>  #include "block/block.h"
> @@ -722,7 +721,7 @@ void migration_ioc_process_incoming(QIOChannel *ioc, 
> Error **errp)
>  
>  if (!mis->from_src_file) {
>  /* The first connection (multifd may have multiple) */
> -QEMUFile *f = qemu_fopen_channel_input(ioc);
> +QEMUFile *f = qemu_file_new_input(ioc);
>  
>  if (!migration_incoming_setup(f, errp)) {
>  return;
> @@ -3081,7 +3080,7 @@ static int postcopy_start(MigrationState *ms)
>   */
>  bioc = qio_channel_buffer_new(4096);
>  qio_channel_set_name(QIO_CHANNEL(bioc), "migration-postcopy-buffer");
> -fb = qemu_fopen_channel_output(QIO_CHANNEL(bioc));
> +fb = qemu_file_new_output(QIO_CHANNEL(bioc));
>  object_unref(OBJECT(bioc));
>  
>  /*
> @@ -3970,7 +3969,7 @@ static void *bg_migration_thread(void *opaque)
>   */
>  s->bioc = qio_channel_buffer_new(512 * 1024);
>  qio_channel_set_name(QIO_CHANNEL(s->bioc), "vmstate-buffer");
> -fb = qemu_fopen_channel_output(QIO_CHANNEL(s->bioc));
> +fb = qemu_file_new_output(QIO_CHANNEL(s->bioc));
>  object_unref(OBJECT(s->bioc));
>  
>  update_iteration_initial_status(s);
> diff --git a/migration/qemu-file-channel.c b/migration/qemu-file-channel.c
> deleted file mode 100644
> index 51717c1137..00
> --- a/migration/qemu-file-channel.c
> +++ /dev/null
> @@ -1,53 +0,0 @@
> -/*
> - * QEMUFile backend for 

Re: [PATCH v2 24/25] target/arm: Rearrange Secure PL1 test in arm_debug_target_el

2022-06-09 Thread Peter Maydell
On Tue, 7 Jun 2022 at 04:06, Richard Henderson
 wrote:
>
> Not a bug, because arm_is_el2_enabled tests for secure,
> and SCR_EL3.EEL2 cannot be set for AArch32, however the
> ordering of the tests looks odd.  Mirror the structure
> over in exception_target_el().

I think the code is following the ordering in the
DebugTarget() and DebugTargetFrom() pseudocode (or else some other
equivalent function in an older version of the Arm ARM...)

> Signed-off-by: Richard Henderson 
> ---
>  target/arm/debug_helper.c | 30 --
>  1 file changed, 16 insertions(+), 14 deletions(-)
>
> diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
> index b18a6bd3a2..59dfcb5d5c 100644
> --- a/target/arm/debug_helper.c
> +++ b/target/arm/debug_helper.c
> @@ -15,22 +15,24 @@
>  /* Return the Exception Level targeted by debug exceptions. */
>  static int arm_debug_target_el(CPUARMState *env)
>  {
> -bool secure = arm_is_secure(env);
> -bool route_to_el2 = false;
> -
> -if (arm_is_el2_enabled(env)) {
> -route_to_el2 = env->cp15.hcr_el2 & HCR_TGE ||
> -   env->cp15.mdcr_el2 & MDCR_TDE;
> -}
> -
> -if (route_to_el2) {
> -return 2;
> -} else if (arm_feature(env, ARM_FEATURE_EL3) &&
> -   !arm_el_is_aa64(env, 3) && secure) {
> +/*
> + * No such thing as secure EL1 if EL3 is AArch32.
> + * Remap Secure PL1 to EL3.
> + */

I think you're also relying on there being no secure EL2
if EL3 is AArch32 (otherwise an exception from secure EL0
might need to be routed to secure EL2, not EL3).

> +if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
>  return 3;
> -} else {
> -return 1;
>  }
> +
> +/*
> + * HCR.TGE redirects EL0 exceptions from EL1 to EL2.
> + * MDCR.TDE redirects both EL0 and EL1 debug exceptions to EL2.
> + */
> +if (arm_is_el2_enabled(env) &&
> +(env->cp15.hcr_el2 & HCR_TGE || env->cp15.mdcr_el2 & MDCR_TDE)) {
> +return 2;
> +}
> +
> +return 1;
>  }

Anyway, if you prefer this way around
Reviewed-by: Peter Maydell 

though I think there is usually some value in following
the pseudocode's arrangement.

thanks
-- PMM



[PULL 10/18] libvduse: Add VDUSE (vDPA Device in Userspace) library

2022-06-09 Thread Kevin Wolf
From: Xie Yongji 

VDUSE [1] is a linux framework that makes it possible to implement
software-emulated vDPA devices in userspace. This adds a library
as a subproject to help implementing VDUSE backends in QEMU.

[1] https://www.kernel.org/doc/html/latest/userspace-api/vduse.html

Signed-off-by: Xie Yongji 
Message-Id: <20220523084611.91-6-xieyon...@bytedance.com>
Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Kevin Wolf 
---
 meson_options.txt   |2 +
 subprojects/libvduse/include/atomic.h   |1 +
 subprojects/libvduse/include/compiler.h |1 +
 subprojects/libvduse/libvduse.h |  235 
 subprojects/libvduse/libvduse.c | 1167 +++
 MAINTAINERS |5 +
 meson.build |   15 +
 scripts/meson-buildoptions.sh   |3 +
 subprojects/libvduse/linux-headers/linux|1 +
 subprojects/libvduse/meson.build|   10 +
 subprojects/libvduse/standard-headers/linux |1 +
 11 files changed, 1441 insertions(+)
 create mode 12 subprojects/libvduse/include/atomic.h
 create mode 12 subprojects/libvduse/include/compiler.h
 create mode 100644 subprojects/libvduse/libvduse.h
 create mode 100644 subprojects/libvduse/libvduse.c
 create mode 12 subprojects/libvduse/linux-headers/linux
 create mode 100644 subprojects/libvduse/meson.build
 create mode 12 subprojects/libvduse/standard-headers/linux

diff --git a/meson_options.txt b/meson_options.txt
index 2de94af037..50da8dea94 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -253,6 +253,8 @@ option('virtfs', type: 'feature', value: 'auto',
description: 'virtio-9p support')
 option('virtiofsd', type: 'feature', value: 'auto',
description: 'build virtiofs daemon (virtiofsd)')
+option('libvduse', type: 'feature', value: 'auto',
+   description: 'build VDUSE Library')
 
 option('capstone', type: 'feature', value: 'auto',
description: 'Whether and how to find the capstone library')
diff --git a/subprojects/libvduse/include/atomic.h 
b/subprojects/libvduse/include/atomic.h
new file mode 12
index 00..8c2be64f7b
--- /dev/null
+++ b/subprojects/libvduse/include/atomic.h
@@ -0,0 +1 @@
+../../../include/qemu/atomic.h
\ No newline at end of file
diff --git a/subprojects/libvduse/include/compiler.h 
b/subprojects/libvduse/include/compiler.h
new file mode 12
index 00..de7b70697c
--- /dev/null
+++ b/subprojects/libvduse/include/compiler.h
@@ -0,0 +1 @@
+../../../include/qemu/compiler.h
\ No newline at end of file
diff --git a/subprojects/libvduse/libvduse.h b/subprojects/libvduse/libvduse.h
new file mode 100644
index 00..6c2fe98213
--- /dev/null
+++ b/subprojects/libvduse/libvduse.h
@@ -0,0 +1,235 @@
+/*
+ * VDUSE (vDPA Device in Userspace) library
+ *
+ * Copyright (C) 2022 Bytedance Inc. and/or its affiliates. All rights 
reserved.
+ *
+ * Author:
+ *   Xie Yongji 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later.  See the COPYING file in the top-level directory.
+ */
+
+#ifndef LIBVDUSE_H
+#define LIBVDUSE_H
+
+#include 
+#include 
+
+#define VIRTQUEUE_MAX_SIZE 1024
+
+/* VDUSE device structure */
+typedef struct VduseDev VduseDev;
+
+/* Virtqueue structure */
+typedef struct VduseVirtq VduseVirtq;
+
+/* Some operation of VDUSE backend */
+typedef struct VduseOps {
+/* Called when virtqueue can be processed */
+void (*enable_queue)(VduseDev *dev, VduseVirtq *vq);
+/* Called when virtqueue processing should be stopped */
+void (*disable_queue)(VduseDev *dev, VduseVirtq *vq);
+} VduseOps;
+
+/* Describing elements of the I/O buffer */
+typedef struct VduseVirtqElement {
+/* Descriptor table index */
+unsigned int index;
+/* Number of physically-contiguous device-readable descriptors */
+unsigned int out_num;
+/* Number of physically-contiguous device-writable descriptors */
+unsigned int in_num;
+/* Array to store physically-contiguous device-writable descriptors */
+struct iovec *in_sg;
+/* Array to store physically-contiguous device-readable descriptors */
+struct iovec *out_sg;
+} VduseVirtqElement;
+
+
+/**
+ * vduse_get_virtio_features:
+ *
+ * Get supported virtio features
+ *
+ * Returns: supported feature bits
+ */
+uint64_t vduse_get_virtio_features(void);
+
+/**
+ * vduse_queue_get_dev:
+ * @vq: specified virtqueue
+ *
+ * Get corresponding VDUSE device from the virtqueue.
+ *
+ * Returns: a pointer to VDUSE device on success, NULL on failure.
+ */
+VduseDev *vduse_queue_get_dev(VduseVirtq *vq);
+
+/**
+ * vduse_queue_get_fd:
+ * @vq: specified virtqueue
+ *
+ * Get the kick fd for the virtqueue.
+ *
+ * Returns: file descriptor on success, -1 on failure.
+ */
+int vduse_queue_get_fd(VduseVirtq *vq);
+
+/**
+ * vduse_queue_pop:
+ * @vq: specified virtqueue
+ * @sz: the size of struct to return (must be >= VduseVirtqElement)
+ *
+ * Pop an 

[PULL 16/18] block/gluster: correctly set max_pdiscard

2022-06-09 Thread Kevin Wolf
From: Fabian Ebner 

On 64-bit platforms, assigning SIZE_MAX to the int64_t max_pdiscard
results in a negative value, and the following assertion would trigger
down the line (it's not the same max_pdiscard, but computed from the
other one):
qemu-system-x86_64: ../block/io.c:3166: bdrv_co_pdiscard: Assertion
`max_pdiscard >= bs->bl.request_alignment' failed.

On 32-bit platforms, it's fine to keep using SIZE_MAX.

The assertion in qemu_gluster_co_pdiscard() is checking that the value
of 'bytes' can safely be passed to glfs_discard_async(), which takes a
size_t for the argument in question, so it is kept as is. And since
max_pdiscard is still <= SIZE_MAX, relying on max_pdiscard is still
fine.

Fixes: 0c8022876f ("block: use int64_t instead of int in driver discard 
handlers")
Cc: qemu-sta...@nongnu.org
Signed-off-by: Fabian Ebner 
Message-Id: <20220520075922.43972-1-f.eb...@proxmox.com>
Reviewed-by: Eric Blake 
Reviewed-by: Stefano Garzarella 
Reviewed-by: Vladimir Sementsov-Ogievskiy 
Signed-off-by: Kevin Wolf 
---
 block/gluster.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/block/gluster.c b/block/gluster.c
index 398976bc66..b60213ab80 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -891,7 +891,7 @@ out:
 static void qemu_gluster_refresh_limits(BlockDriverState *bs, Error **errp)
 {
 bs->bl.max_transfer = GLUSTER_MAX_TRANSFER;
-bs->bl.max_pdiscard = SIZE_MAX;
+bs->bl.max_pdiscard = MIN(SIZE_MAX, INT64_MAX);
 }
 
 static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
-- 
2.35.3




Re: [PATCH 18/20] migration: remove the QEMUFileOps 'writev_buffer' callback

2022-06-09 Thread Dr. David Alan Gilbert
* Daniel P. Berrangé (berra...@redhat.com) wrote:
> This directly implements the writev_buffer logic using QIOChannel APIs.
> 
> Signed-off-by: Daniel P. Berrangé 
> ---
>  migration/qemu-file-channel.c | 43 ---
>  migration/qemu-file.c | 24 +++
>  migration/qemu-file.h |  9 
>  3 files changed, 8 insertions(+), 68 deletions(-)
> 
> diff --git a/migration/qemu-file-channel.c b/migration/qemu-file-channel.c
> index 7b32831752..2e139f7bcd 100644
> --- a/migration/qemu-file-channel.c
> +++ b/migration/qemu-file-channel.c
> @@ -32,48 +32,6 @@
>  #include "yank_functions.h"
>  
>  
> -static ssize_t channel_writev_buffer(void *opaque,
> - struct iovec *iov,
> - int iovcnt,
> - int64_t pos,
> - Error **errp)
> -{
> -QIOChannel *ioc = QIO_CHANNEL(opaque);
> -ssize_t done = 0;
> -struct iovec *local_iov = g_new(struct iovec, iovcnt);
> -struct iovec *local_iov_head = local_iov;
> -unsigned int nlocal_iov = iovcnt;
> -
> -nlocal_iov = iov_copy(local_iov, nlocal_iov,
> -  iov, iovcnt,
> -  0, iov_size(iov, iovcnt));
> -
> -while (nlocal_iov > 0) {
> -ssize_t len;
> -len = qio_channel_writev(ioc, local_iov, nlocal_iov, errp);
> -if (len == QIO_CHANNEL_ERR_BLOCK) {
> -if (qemu_in_coroutine()) {
> -qio_channel_yield(ioc, G_IO_OUT);
> -} else {
> -qio_channel_wait(ioc, G_IO_OUT);
> -}
> -continue;

I wondered where that code went, but it turns out it's already copied
into qio_channel_writev_full_all, so:


Reviewed-by: Dr. David Alan Gilbert 

> -}
> -if (len < 0) {
> -done = -EIO;
> -goto cleanup;
> -}
> -
> -iov_discard_front(_iov, _iov, len);
> -done += len;
> -}
> -
> - cleanup:
> -g_free(local_iov_head);
> -return done;
> -}
> -
> -
>  static QEMUFile *channel_get_input_return_path(void *opaque)
>  {
>  QIOChannel *ioc = QIO_CHANNEL(opaque);
> @@ -94,7 +52,6 @@ static const QEMUFileOps channel_input_ops = {
>  
>  
>  static const QEMUFileOps channel_output_ops = {
> -.writev_buffer = channel_writev_buffer,
>  .get_return_path = channel_get_output_return_path,
>  };
>  
> diff --git a/migration/qemu-file.c b/migration/qemu-file.c
> index e024b43851..72a6f58af5 100644
> --- a/migration/qemu-file.c
> +++ b/migration/qemu-file.c
> @@ -245,10 +245,6 @@ static void qemu_iovec_release_ram(QEMUFile *f)
>   */
>  void qemu_fflush(QEMUFile *f)
>  {
> -ssize_t ret = 0;
> -ssize_t expect = 0;
> -Error *local_error = NULL;
> -
>  if (!qemu_file_is_writable(f)) {
>  return;
>  }
> @@ -257,22 +253,18 @@ void qemu_fflush(QEMUFile *f)
>  return;
>  }
>  if (f->iovcnt > 0) {
> -expect = iov_size(f->iov, f->iovcnt);
> -ret = f->ops->writev_buffer(f->ioc, f->iov, f->iovcnt, 
> f->total_transferred,
> -_error);
> +Error *local_error = NULL;
> +if (qio_channel_writev_all(f->ioc,
> +   f->iov, f->iovcnt,
> +   _error) < 0) {
> +qemu_file_set_error_obj(f, -EIO, local_error);
> +} else {
> +f->total_transferred += iov_size(f->iov, f->iovcnt);
> +}
>  
>  qemu_iovec_release_ram(f);
>  }
>  
> -if (ret >= 0) {
> -f->total_transferred += ret;
> -}
> -/* We expect the QEMUFile write impl to send the full
> - * data set we requested, so sanity check that.
> - */
> -if (ret != expect) {
> -qemu_file_set_error_obj(f, ret < 0 ? ret : -EIO, local_error);
> -}
>  f->buf_index = 0;
>  f->iovcnt = 0;
>  }
> diff --git a/migration/qemu-file.h b/migration/qemu-file.h
> index cd49184c00..542c637934 100644
> --- a/migration/qemu-file.h
> +++ b/migration/qemu-file.h
> @@ -29,14 +29,6 @@
>  #include "exec/cpu-common.h"
>  #include "io/channel.h"
>  
> -/*
> - * This function writes an iovec to file. The handler must write all
> - * of the data or return a negative errno value.
> - */
> -typedef ssize_t (QEMUFileWritevBufferFunc)(void *opaque, struct iovec *iov,
> -   int iovcnt, int64_t pos,
> -   Error **errp);
> -
>  /*
>   * This function provides hooks around different
>   * stages of RAM migration.
> @@ -69,7 +61,6 @@ typedef size_t (QEMURamSaveFunc)(QEMUFile *f,
>  typedef QEMUFile *(QEMURetPathFunc)(void *opaque);
>  
>  typedef struct QEMUFileOps {
> -QEMUFileWritevBufferFunc *writev_buffer;
>  QEMURetPathFunc *get_return_path;
>  } QEMUFileOps;
>  
> -- 
> 2.36.1
> 
-- 
Dr. David Alan Gilbert / 

  1   2   3   4   5   >