[PATCH v5 09/22] target/riscv: Adjust csr write mask with XLEN

2021-11-24 Thread LIU Zhiwei
Write mask is representing the bits we care about.

Signed-off-by: LIU Zhiwei 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/insn_trans/trans_rvi.c.inc | 4 ++--
 target/riscv/op_helper.c| 3 ++-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index e51dbc41c5..40c81421f2 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -486,7 +486,7 @@ static bool trans_csrrw(DisasContext *ctx, arg_csrrw *a)
 return do_csrw(ctx, a->csr, src);
 }
 
-TCGv mask = tcg_constant_tl(-1);
+TCGv mask = tcg_constant_tl(get_xl(ctx) == MXL_RV32 ? UINT32_MAX : -1);
 return do_csrrw(ctx, a->rd, a->csr, src, mask);
 }
 
@@ -537,7 +537,7 @@ static bool trans_csrrwi(DisasContext *ctx, arg_csrrwi *a)
 return do_csrw(ctx, a->csr, src);
 }
 
-TCGv mask = tcg_constant_tl(-1);
+TCGv mask = tcg_constant_tl(get_xl(ctx) == MXL_RV32 ? UINT32_MAX : -1);
 return do_csrrw(ctx, a->rd, a->csr, src, mask);
 }
 
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 095d39671b..acfad598e1 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -50,7 +50,8 @@ target_ulong helper_csrr(CPURISCVState *env, int csr)
 
 void helper_csrw(CPURISCVState *env, int csr, target_ulong src)
 {
-RISCVException ret = riscv_csrrw(env, csr, NULL, src, -1);
+target_ulong mask = env->xl == MXL_RV32 ? UINT32_MAX : -1;
+RISCVException ret = riscv_csrrw(env, csr, NULL, src, mask);
 
 if (ret != RISCV_EXCP_NONE) {
 riscv_raise_exception(env, ret, GETPC());
-- 
2.25.1




[PATCH v5 05/22] target/riscv: Ignore the pc bits above XLEN

2021-11-24 Thread LIU Zhiwei
The read from PC for translation is in cpu_get_tb_cpu_state, before translation.

Signed-off-by: LIU Zhiwei 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu_helper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index b6cddf8648..9c3838bddf 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -71,7 +71,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong 
*pc,
 {
 uint32_t flags = 0;
 
-*pc = env->pc;
+*pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
 *cs_base = 0;
 
 if (riscv_has_ext(env, RVV)) {
@@ -127,7 +127,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong 
*pc,
 }
 #endif
 
-flags = FIELD_DP32(flags, TB_FLAGS, XL, cpu_get_xl(env));
+flags = FIELD_DP32(flags, TB_FLAGS, XL, env->xl);
 
 *pflags = flags;
 }
-- 
2.25.1




[PATCH v5 12/22] target/riscv: Calculate address according to XLEN

2021-11-24 Thread LIU Zhiwei
Define one common function to compute a canonical address from a register
plus offset. Merge gen_pm_adjust_address into this function.

Signed-off-by: LIU Zhiwei 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/insn_trans/trans_rva.c.inc |  9 +++--
 target/riscv/insn_trans/trans_rvd.c.inc | 19 ++---
 target/riscv/insn_trans/trans_rvf.c.inc | 19 ++---
 target/riscv/insn_trans/trans_rvi.c.inc | 18 ++---
 target/riscv/translate.c| 27 -
 5 files changed, 22 insertions(+), 70 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rva.c.inc 
b/target/riscv/insn_trans/trans_rva.c.inc
index 40fe132b04..1f64b8d332 100644
--- a/target/riscv/insn_trans/trans_rva.c.inc
+++ b/target/riscv/insn_trans/trans_rva.c.inc
@@ -20,12 +20,11 @@
 
 static bool gen_lr(DisasContext *ctx, arg_atomic *a, MemOp mop)
 {
-TCGv src1 = get_gpr(ctx, a->rs1, EXT_ZERO);
+TCGv src1 = get_address(ctx, a->rs1, 0);
 
 if (a->rl) {
 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
 }
-src1 = gen_pm_adjust_address(ctx, src1);
 tcg_gen_qemu_ld_tl(load_val, src1, ctx->mem_idx, mop);
 if (a->aq) {
 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
@@ -44,8 +43,7 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp 
mop)
 TCGLabel *l1 = gen_new_label();
 TCGLabel *l2 = gen_new_label();
 
-src1 = get_gpr(ctx, a->rs1, EXT_ZERO);
-src1 = gen_pm_adjust_address(ctx, src1);
+src1 = get_address(ctx, a->rs1, 0);
 tcg_gen_brcond_tl(TCG_COND_NE, load_res, src1, l1);
 
 /*
@@ -83,10 +81,9 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a,
 MemOp mop)
 {
 TCGv dest = dest_gpr(ctx, a->rd);
-TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
+TCGv src1 = get_address(ctx, a->rs1, 0);
 TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
 
-src1 = gen_pm_adjust_address(ctx, src1);
 func(dest, src1, src2, ctx->mem_idx, mop);
 
 gen_set_gpr(ctx, a->rd, dest);
diff --git a/target/riscv/insn_trans/trans_rvd.c.inc 
b/target/riscv/insn_trans/trans_rvd.c.inc
index 64fb0046f7..88a491375c 100644
--- a/target/riscv/insn_trans/trans_rvd.c.inc
+++ b/target/riscv/insn_trans/trans_rvd.c.inc
@@ -25,14 +25,7 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a)
 REQUIRE_FPU;
 REQUIRE_EXT(ctx, RVD);
 
-addr = get_gpr(ctx, a->rs1, EXT_NONE);
-if (a->imm) {
-TCGv temp = temp_new(ctx);
-tcg_gen_addi_tl(temp, addr, a->imm);
-addr = temp;
-}
-addr = gen_pm_adjust_address(ctx, addr);
-
+addr = get_address(ctx, a->rs1, a->imm);
 tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], addr, ctx->mem_idx, MO_TEQ);
 
 mark_fs_dirty(ctx);
@@ -46,16 +39,8 @@ static bool trans_fsd(DisasContext *ctx, arg_fsd *a)
 REQUIRE_FPU;
 REQUIRE_EXT(ctx, RVD);
 
-addr = get_gpr(ctx, a->rs1, EXT_NONE);
-if (a->imm) {
-TCGv temp = temp_new(ctx);
-tcg_gen_addi_tl(temp, addr, a->imm);
-addr = temp;
-}
-addr = gen_pm_adjust_address(ctx, addr);
-
+addr = get_address(ctx, a->rs1, a->imm);
 tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEQ);
-
 return true;
 }
 
diff --git a/target/riscv/insn_trans/trans_rvf.c.inc 
b/target/riscv/insn_trans/trans_rvf.c.inc
index b5459249c4..0aac87f7db 100644
--- a/target/riscv/insn_trans/trans_rvf.c.inc
+++ b/target/riscv/insn_trans/trans_rvf.c.inc
@@ -31,14 +31,7 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a)
 REQUIRE_FPU;
 REQUIRE_EXT(ctx, RVF);
 
-addr = get_gpr(ctx, a->rs1, EXT_NONE);
-if (a->imm) {
-TCGv temp = temp_new(ctx);
-tcg_gen_addi_tl(temp, addr, a->imm);
-addr = temp;
-}
-addr = gen_pm_adjust_address(ctx, addr);
-
+addr = get_address(ctx, a->rs1, a->imm);
 dest = cpu_fpr[a->rd];
 tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_TEUL);
 gen_nanbox_s(dest, dest);
@@ -54,16 +47,8 @@ static bool trans_fsw(DisasContext *ctx, arg_fsw *a)
 REQUIRE_FPU;
 REQUIRE_EXT(ctx, RVF);
 
-addr = get_gpr(ctx, a->rs1, EXT_NONE);
-if (a->imm) {
-TCGv temp = tcg_temp_new();
-tcg_gen_addi_tl(temp, addr, a->imm);
-addr = temp;
-}
-addr = gen_pm_adjust_address(ctx, addr);
-
+addr = get_address(ctx, a->rs1, a->imm);
 tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEUL);
-
 return true;
 }
 
diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index 40c81421f2..cb73a2f1ee 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -137,14 +137,7 @@ static bool trans_bgeu(DisasContext *ctx, arg_bgeu *a)
 static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop)
 {
 TCGv dest = dest_gpr(ctx, a->rd);
-TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
-
-if (a->imm) {
-TCGv temp = temp_new(ctx);
-tcg_gen_addi_tl(temp, 

[PATCH v5 10/22] target/riscv: Create current pm fields in env

2021-11-24 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.c|  1 +
 target/riscv/cpu.h|  4 
 target/riscv/cpu_helper.c | 43 +++
 target/riscv/csr.c| 19 +
 target/riscv/machine.c| 10 +
 5 files changed, 77 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index b6ca3fb883..61ef88752c 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -394,6 +394,7 @@ static void riscv_cpu_reset(DeviceState *dev)
 env->mmte |= (PM_EXT_INITIAL | MMTE_M_PM_CURRENT);
 #endif
 env->xl = riscv_cpu_mxl(env);
+riscv_cpu_update_mask(env);
 cs->exception_index = RISCV_EXCP_NONE;
 env->load_res = -1;
 set_default_nan_mode(1, >fp_status);
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 412339dbad..28006b782f 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -251,6 +251,8 @@ struct CPURISCVState {
 target_ulong upmmask;
 target_ulong upmbase;
 #endif
+target_ulong cur_pmmask;
+target_ulong cur_pmbase;
 
 float_status fp_status;
 
@@ -442,6 +444,8 @@ static inline uint32_t vext_get_vlmax(RISCVCPU *cpu, 
target_ulong vtype)
 void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
   target_ulong *cs_base, uint32_t *pflags);
 
+void riscv_cpu_update_mask(CPURISCVState *env);
+
 RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask);
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 9c3838bddf..d74199b49b 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -132,6 +132,48 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong 
*pc,
 *pflags = flags;
 }
 
+void riscv_cpu_update_mask(CPURISCVState *env)
+{
+target_ulong mask = -1, base = 0;
+/*
+ * TODO: Current RVJ spec does not specify
+ * how the extension interacts with XLEN.
+ */
+#ifndef CONFIG_USER_ONLY
+if (riscv_has_ext(env, RVJ)) {
+switch (env->priv) {
+case PRV_M:
+if (env->mmte & M_PM_ENABLE) {
+mask = env->mpmmask;
+base = env->mpmbase;
+}
+break;
+case PRV_S:
+if (env->mmte & S_PM_ENABLE) {
+mask = env->spmmask;
+base = env->spmbase;
+}
+break;
+case PRV_U:
+if (env->mmte & U_PM_ENABLE) {
+mask = env->upmmask;
+base = env->upmbase;
+}
+break;
+default:
+g_assert_not_reached();
+}
+}
+#endif
+if (env->xl == MXL_RV32) {
+env->cur_pmmask = mask & UINT32_MAX;
+env->cur_pmbase = base & UINT32_MAX;
+} else {
+env->cur_pmmask = mask;
+env->cur_pmbase = base;
+}
+}
+
 #ifndef CONFIG_USER_ONLY
 static int riscv_cpu_local_irq_pending(CPURISCVState *env)
 {
@@ -331,6 +373,7 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong 
newpriv)
 /* tlb_flush is unnecessary as mode is contained in mmu_idx */
 env->priv = newpriv;
 env->xl = cpu_get_xl(env);
+riscv_cpu_update_mask(env);
 
 /*
  * Clear the load reservation - otherwise a reservation placed in one
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index bfafd3bd96..68da5d2173 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1516,6 +1516,7 @@ static RISCVException write_mmte(CPURISCVState *env, int 
csrno,
 /* hardwiring pm.instruction bit to 0, since it's not supported yet */
 wpri_val &= ~(MMTE_M_PM_INSN | MMTE_S_PM_INSN | MMTE_U_PM_INSN);
 env->mmte = wpri_val | PM_EXT_DIRTY;
+riscv_cpu_update_mask(env);
 
 /* Set XS and SD bits, since PM CSRs are dirty */
 mstatus = env->mstatus | MSTATUS_XS;
@@ -1591,6 +1592,9 @@ static RISCVException write_mpmmask(CPURISCVState *env, 
int csrno,
 uint64_t mstatus;
 
 env->mpmmask = val;
+if ((env->priv == PRV_M) && (env->mmte & M_PM_ENABLE)) {
+env->cur_pmmask = val;
+}
 env->mmte |= PM_EXT_DIRTY;
 
 /* Set XS and SD bits, since PM CSRs are dirty */
@@ -1616,6 +1620,9 @@ static RISCVException write_spmmask(CPURISCVState *env, 
int csrno,
 return RISCV_EXCP_NONE;
 }
 env->spmmask = val;
+if ((env->priv == PRV_S) && (env->mmte & S_PM_ENABLE)) {
+env->cur_pmmask = val;
+}
 env->mmte |= PM_EXT_DIRTY;
 
 /* Set XS and SD bits, since PM CSRs are dirty */
@@ -1641,6 +1648,9 @@ static RISCVException write_upmmask(CPURISCVState *env, 
int csrno,
 return RISCV_EXCP_NONE;
 }
 env->upmmask = val;
+if ((env->priv == PRV_U) && (env->mmte & U_PM_ENABLE)) {
+env->cur_pmmask = val;
+}
 env->mmte |= PM_EXT_DIRTY;
 
 /* Set XS and SD bits, since PM CSRs are dirty */
@@ -1662,6 +1672,9 @@ 

[PATCH v5 00/22] Support UXL filed in xstatus

2021-11-24 Thread LIU Zhiwei
In this patch set, we process the pc reigsters writes,
gdb reads and writes, and address calculation under
different UXLEN settings.

The patch set v5 fix an error in v4: miss to select gdb core xml according
to mxl. Besides, add xl field in CPURISCVState, so that we can remove many
redundant riscv_cpu_xl calls. It will also benefit other extensions.
The last new change is to calculate the number of PMP configuration in
one pmpcfgx CSR according to mxl.

Patch 1, 4, 21, have not been reviewed. Others have been reviewed or acked.

v5:
  Add xl field in env to clear up redundant riscv_cpu_xl
  Adjust pmpcfg access with mxl
  Select gdb core xml according to mxl 

v4:
  Support SSTATUS64_UXL write
  Bump vmstate version for vill split

v3:
  Merge gen_pm_adjust_address into a canonical address function
  Adjust address for RVA with XLEN
  Split pm_enabled into pm_mask_enabled and pm_base_enabled
  Replace array of pm tcg globals with one scalar tcg global
  Split and change patch sequence

v2:
  Split out vill from vtype
  Remove context switch when xlen changes at exception
  Use XL instead of OL in many places
  Use pointer masking and XLEN for vector address
  Define an common fuction to calculate address for lds


LIU Zhiwei (22):
  target/riscv: Adjust pmpcfg access with mxl
  target/riscv: Don't save pc when exception return
  target/riscv: Sign extend pc for different XLEN
  target/riscv: Create xl field in env
  target/riscv: Ignore the pc bits above XLEN
  target/riscv: Extend pc for runtime pc write
  target/riscv: Use gdb xml according to max mxlen
  target/riscv: Relax debug check for pm write
  target/riscv: Adjust csr write mask with XLEN
  target/riscv: Create current pm fields in env
  target/riscv: Alloc tcg global for cur_pm[mask|base]
  target/riscv: Calculate address according to XLEN
  target/riscv: Split pm_enabled into mask and base
  target/riscv: Split out the vill from vtype
  target/riscv: Fix RESERVED field length in VTYPE
  target/riscv: Adjust vsetvl according to XLEN
  target/riscv: Remove VILL field in VTYPE
  target/riscv: Ajdust vector atomic check with XLEN
  target/riscv: Fix check range for first fault only
  target/riscv: Adjust vector address with mask
  target/riscv: Adjust scalar reg in vector with XLEN
  target/riscv: Enable uxl field write

 target/riscv/cpu.c| 27 ++-
 target/riscv/cpu.h| 19 -
 target/riscv/cpu_bits.h   |  2 +
 target/riscv/cpu_helper.c | 65 
 target/riscv/csr.c| 63 ++-
 target/riscv/gdbstub.c| 71 -
 target/riscv/helper.h |  4 +-
 .../riscv/insn_trans/trans_privileged.c.inc   |  7 +-
 target/riscv/insn_trans/trans_rva.c.inc   |  9 +--
 target/riscv/insn_trans/trans_rvd.c.inc   | 19 +
 target/riscv/insn_trans/trans_rvf.c.inc   | 19 +
 target/riscv/insn_trans/trans_rvi.c.inc   | 22 +-
 target/riscv/insn_trans/trans_rvv.c.inc   | 47 +++
 target/riscv/machine.c| 20 -
 target/riscv/op_helper.c  |  7 +-
 target/riscv/pmp.c| 12 +--
 target/riscv/translate.c  | 77 +--
 target/riscv/vector_helper.c  | 37 +
 18 files changed, 333 insertions(+), 194 deletions(-)

-- 
2.25.1




[PATCH v5 03/22] target/riscv: Sign extend pc for different XLEN

2021-11-24 Thread LIU Zhiwei
When pc is written, it is sign-extended to fill the widest supported XLEN.

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

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 1d57bc97b5..a6a73ced9e 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -150,16 +150,24 @@ static void gen_check_nanbox_s(TCGv_i64 out, TCGv_i64 in)
 tcg_gen_movcond_i64(TCG_COND_GEU, out, in, t_max, in, t_nan);
 }
 
+static void gen_set_pc(DisasContext *ctx, target_ulong dest)
+{
+if (get_xl(ctx) == MXL_RV32) {
+dest = (int32_t)dest;
+}
+tcg_gen_movi_tl(cpu_pc, dest);
+}
+
 static void generate_exception(DisasContext *ctx, int excp)
 {
-tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
+gen_set_pc(ctx, ctx->base.pc_next);
 gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp));
 ctx->base.is_jmp = DISAS_NORETURN;
 }
 
 static void generate_exception_mtval(DisasContext *ctx, int excp)
 {
-tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
+gen_set_pc(ctx, ctx->base.pc_next);
 tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr));
 gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp));
 ctx->base.is_jmp = DISAS_NORETURN;
@@ -179,10 +187,10 @@ static void gen_goto_tb(DisasContext *ctx, int n, 
target_ulong dest)
 {
 if (translator_use_goto_tb(>base, dest)) {
 tcg_gen_goto_tb(n);
-tcg_gen_movi_tl(cpu_pc, dest);
+gen_set_pc(ctx, dest);
 tcg_gen_exit_tb(ctx->base.tb, n);
 } else {
-tcg_gen_movi_tl(cpu_pc, dest);
+gen_set_pc(ctx, dest);
 tcg_gen_lookup_and_goto_ptr();
 }
 }
-- 
2.25.1




[PATCH v5 07/22] target/riscv: Use gdb xml according to max mxlen

2021-11-24 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.c |  3 ++
 target/riscv/gdbstub.c | 71 +++---
 2 files changed, 55 insertions(+), 19 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 3e394d08e4..b6ca3fb883 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -421,6 +421,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 RISCVCPU *cpu = RISCV_CPU(dev);
 CPURISCVState *env = >env;
 RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
+CPUClass *cc = CPU_CLASS(mcc);
 int priv_version = 0;
 Error *local_err = NULL;
 
@@ -471,9 +472,11 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 switch (env->misa_mxl_max) {
 #ifdef TARGET_RISCV64
 case MXL_RV64:
+cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
 break;
 #endif
 case MXL_RV32:
+cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
 break;
 default:
 g_assert_not_reached();
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 23429179e2..afc4c13171 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -24,11 +24,23 @@ int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray 
*mem_buf, int n)
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = >env;
+target_ulong tmp;
 
 if (n < 32) {
-return gdb_get_regl(mem_buf, env->gpr[n]);
+tmp = env->gpr[n];
 } else if (n == 32) {
-return gdb_get_regl(mem_buf, env->pc);
+tmp = env->pc;
+} else {
+return 0;
+}
+
+switch (env->misa_mxl_max) {
+case MXL_RV32:
+return gdb_get_reg32(mem_buf, tmp);
+case MXL_RV64:
+return gdb_get_reg64(mem_buf, tmp);
+default:
+g_assert_not_reached();
 }
 return 0;
 }
@@ -37,18 +49,32 @@ int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t 
*mem_buf, int n)
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = >env;
-
-if (n == 0) {
-/* discard writes to x0 */
-return sizeof(target_ulong);
-} else if (n < 32) {
-env->gpr[n] = ldtul_p(mem_buf);
-return sizeof(target_ulong);
+int length = 0;
+target_ulong tmp;
+
+switch (env->misa_mxl_max) {
+case MXL_RV32:
+tmp = (int32_t)ldl_p(mem_buf);
+length = 4;
+break;
+case MXL_RV64:
+if (env->xl < MXL_RV64) {
+tmp = (int32_t)ldq_p(mem_buf);
+} else {
+tmp = ldq_p(mem_buf);
+}
+length = 8;
+break;
+default:
+g_assert_not_reached();
+}
+if (n > 0 && n < 32) {
+env->gpr[n] = tmp;
 } else if (n == 32) {
-env->pc = ldtul_p(mem_buf);
-return sizeof(target_ulong);
+env->pc = tmp;
 }
-return 0;
+
+return length;
 }
 
 static int riscv_gdb_get_fpu(CPURISCVState *env, GByteArray *buf, int n)
@@ -198,13 +224,20 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState 
*cs)
 gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
  36, "riscv-32bit-fpu.xml", 0);
 }
-#if defined(TARGET_RISCV32)
-gdb_register_coprocessor(cs, riscv_gdb_get_virtual, riscv_gdb_set_virtual,
- 1, "riscv-32bit-virtual.xml", 0);
-#elif defined(TARGET_RISCV64)
-gdb_register_coprocessor(cs, riscv_gdb_get_virtual, riscv_gdb_set_virtual,
- 1, "riscv-64bit-virtual.xml", 0);
-#endif
+switch (env->misa_mxl_max) {
+case MXL_RV32:
+gdb_register_coprocessor(cs, riscv_gdb_get_virtual,
+ riscv_gdb_set_virtual,
+ 1, "riscv-32bit-virtual.xml", 0);
+break;
+case MXL_RV64:
+gdb_register_coprocessor(cs, riscv_gdb_get_virtual,
+ riscv_gdb_set_virtual,
+ 1, "riscv-64bit-virtual.xml", 0);
+break;
+default:
+g_assert_not_reached();
+}
 
 gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
  riscv_gen_dynamic_csr_xml(cs, cs->gdb_num_regs),
-- 
2.25.1




[PATCH v5 01/22] target/riscv: Adjust pmpcfg access with mxl

2021-11-24 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
---
 target/riscv/csr.c | 18 ++
 target/riscv/pmp.c | 12 
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 9f41954894..ce20c3a970 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1407,9 +1407,22 @@ static RISCVException write_mseccfg(CPURISCVState *env, 
int csrno,
 return RISCV_EXCP_NONE;
 }
 
+static bool check_pmp_reg_index(CPURISCVState *env, uint32_t reg_index)
+{
+if ((reg_index & 1) && (riscv_cpu_mxl(env) == MXL_RV64)) {
+return false;
+}
+return true;
+}
+
 static RISCVException read_pmpcfg(CPURISCVState *env, int csrno,
   target_ulong *val)
 {
+uint32_t reg_index = csrno - CSR_PMPCFG0;
+
+if (!check_pmp_reg_index(env, reg_index)) {
+return RISCV_EXCP_ILLEGAL_INST;
+}
 *val = pmpcfg_csr_read(env, csrno - CSR_PMPCFG0);
 return RISCV_EXCP_NONE;
 }
@@ -1417,6 +1430,11 @@ static RISCVException read_pmpcfg(CPURISCVState *env, 
int csrno,
 static RISCVException write_pmpcfg(CPURISCVState *env, int csrno,
target_ulong val)
 {
+uint32_t reg_index = csrno - CSR_PMPCFG0;
+
+if (!check_pmp_reg_index(env, reg_index)) {
+return RISCV_EXCP_ILLEGAL_INST;
+}
 pmpcfg_csr_write(env, csrno - CSR_PMPCFG0, val);
 return RISCV_EXCP_NONE;
 }
diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
index 54abf42583..81b61bb65c 100644
--- a/target/riscv/pmp.c
+++ b/target/riscv/pmp.c
@@ -463,16 +463,11 @@ void pmpcfg_csr_write(CPURISCVState *env, uint32_t 
reg_index,
 {
 int i;
 uint8_t cfg_val;
+int pmpcfg_nums = 2 << riscv_cpu_mxl(env);
 
 trace_pmpcfg_csr_write(env->mhartid, reg_index, val);
 
-if ((reg_index & 1) && (sizeof(target_ulong) == 8)) {
-qemu_log_mask(LOG_GUEST_ERROR,
-  "ignoring pmpcfg write - incorrect address\n");
-return;
-}
-
-for (i = 0; i < sizeof(target_ulong); i++) {
+for (i = 0; i < pmpcfg_nums; i++) {
 cfg_val = (val >> 8 * i)  & 0xff;
 pmp_write_cfg(env, (reg_index * 4) + i, cfg_val);
 }
@@ -490,8 +485,9 @@ target_ulong pmpcfg_csr_read(CPURISCVState *env, uint32_t 
reg_index)
 int i;
 target_ulong cfg_val = 0;
 target_ulong val = 0;
+int pmpcfg_nums = 2 << riscv_cpu_mxl(env);
 
-for (i = 0; i < sizeof(target_ulong); i++) {
+for (i = 0; i < pmpcfg_nums; i++) {
 val = pmp_read_cfg(env, (reg_index * 4) + i);
 cfg_val |= (val << (i * 8));
 }
-- 
2.25.1




[PATCH v5 02/22] target/riscv: Don't save pc when exception return

2021-11-24 Thread LIU Zhiwei
As pc will be written by the xepc in exception return, just ignore
pc in translation.

Signed-off-by: LIU Zhiwei 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/helper.h  | 4 ++--
 target/riscv/insn_trans/trans_privileged.c.inc | 7 ++-
 target/riscv/op_helper.c   | 4 ++--
 3 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index c7a5376227..c5098380dd 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -67,8 +67,8 @@ DEF_HELPER_2(csrr, tl, env, int)
 DEF_HELPER_3(csrw, void, env, int, tl)
 DEF_HELPER_4(csrrw, tl, env, int, tl, tl)
 #ifndef CONFIG_USER_ONLY
-DEF_HELPER_2(sret, tl, env, tl)
-DEF_HELPER_2(mret, tl, env, tl)
+DEF_HELPER_1(sret, tl, env)
+DEF_HELPER_1(mret, tl, env)
 DEF_HELPER_1(wfi, void, env)
 DEF_HELPER_1(tlb_flush, void, env)
 #endif
diff --git a/target/riscv/insn_trans/trans_privileged.c.inc 
b/target/riscv/insn_trans/trans_privileged.c.inc
index 75c6ef80a6..6077bbbf11 100644
--- a/target/riscv/insn_trans/trans_privileged.c.inc
+++ b/target/riscv/insn_trans/trans_privileged.c.inc
@@ -74,10 +74,8 @@ static bool trans_uret(DisasContext *ctx, arg_uret *a)
 static bool trans_sret(DisasContext *ctx, arg_sret *a)
 {
 #ifndef CONFIG_USER_ONLY
-tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
-
 if (has_ext(ctx, RVS)) {
-gen_helper_sret(cpu_pc, cpu_env, cpu_pc);
+gen_helper_sret(cpu_pc, cpu_env);
 tcg_gen_exit_tb(NULL, 0); /* no chaining */
 ctx->base.is_jmp = DISAS_NORETURN;
 } else {
@@ -92,8 +90,7 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a)
 static bool trans_mret(DisasContext *ctx, arg_mret *a)
 {
 #ifndef CONFIG_USER_ONLY
-tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
-gen_helper_mret(cpu_pc, cpu_env, cpu_pc);
+gen_helper_mret(cpu_pc, cpu_env);
 tcg_gen_exit_tb(NULL, 0); /* no chaining */
 ctx->base.is_jmp = DISAS_NORETURN;
 return true;
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index ee7c24efe7..095d39671b 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -71,7 +71,7 @@ target_ulong helper_csrrw(CPURISCVState *env, int csr,
 
 #ifndef CONFIG_USER_ONLY
 
-target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
+target_ulong helper_sret(CPURISCVState *env)
 {
 uint64_t mstatus;
 target_ulong prev_priv, prev_virt;
@@ -132,7 +132,7 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong 
cpu_pc_deb)
 return retpc;
 }
 
-target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
+target_ulong helper_mret(CPURISCVState *env)
 {
 if (!(env->priv >= PRV_M)) {
 riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
-- 
2.25.1




[PATCH v5 06/22] target/riscv: Extend pc for runtime pc write

2021-11-24 Thread LIU Zhiwei
In some cases, we must restore the guest PC to the address of the start of
the TB, such as when the instruction counter hits zero. So extend pc register
according to current xlen for these cases.

Signed-off-by: LIU Zhiwei 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.c | 22 +++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 5c757ce33a..3e394d08e4 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -319,7 +319,12 @@ static void riscv_cpu_set_pc(CPUState *cs, vaddr value)
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = >env;
-env->pc = value;
+
+if (env->xl == MXL_RV32) {
+env->pc = (int32_t)value;
+} else {
+env->pc = value;
+}
 }
 
 static void riscv_cpu_synchronize_from_tb(CPUState *cs,
@@ -327,7 +332,13 @@ static void riscv_cpu_synchronize_from_tb(CPUState *cs,
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = >env;
-env->pc = tb->pc;
+RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
+
+if (xl == MXL_RV32) {
+env->pc = (int32_t)tb->pc;
+} else {
+env->pc = tb->pc;
+}
 }
 
 static bool riscv_cpu_has_work(CPUState *cs)
@@ -348,7 +359,12 @@ static bool riscv_cpu_has_work(CPUState *cs)
 void restore_state_to_opc(CPURISCVState *env, TranslationBlock *tb,
   target_ulong *data)
 {
-env->pc = data[0];
+RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
+if (xl == MXL_RV32) {
+env->pc = (int32_t)data[0];
+} else {
+env->pc = data[0];
+}
 }
 
 static void riscv_cpu_reset(DeviceState *dev)
-- 
2.25.1




Re: [PATCH 1/2] hw/arm/virt: Rename default_bus_bypass_iommu

2021-11-24 Thread Jean-Philippe Brucker
Hi Markus,

On Thu, Nov 25, 2021 at 08:11:04AM +0100, Markus Armbruster wrote:
> Peter, this patch fixes a bug that became a regression when the fix
> missed 6.1.  It's been stuck on the list since August.  Please have a
> look, and if it's good, get it merged.  I'll ask the i386/pc maintainers
> to do the same for PATCH 2.

Both fixes have been merged in v6.2 (9dad363a223d and 739b38630c45)

Thanks,
Jean

> 
> Jean-Philippe Brucker  writes:
> 
> > Since commit d8fb7d0969d5 ("vl: switch -M parsing to keyval"), machine
> > parameter definitions cannot use underscores, because keyval_dashify()
> > transforms them to dashes and the parser doesn't find the parameter.
> >
> > This affects option default_bus_bypass_iommu which was introduced in the
> > same release:
> >
> > $ qemu-system-aarch64 -M virt,default_bus_bypass_iommu=on
> > qemu-system-aarch64: Property 'virt-6.1-machine.default-bus-bypass-iommu' 
> > not found
> >
> > Rename the parameter to "default-bus-bypass-iommu". Passing
> > "default_bus_bypass_iommu" is still valid since the underscore are
> > transformed automatically.
> >
> > Fixes: 6d7a85483a06 ("hw/arm/virt: Add default_bus_bypass_iommu machine 
> > option")
> > Signed-off-by: Jean-Philippe Brucker 
> > ---
> >  hw/arm/virt.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> > index b4598d3fe6..7075cdc15e 100644
> > --- a/hw/arm/virt.c
> > +++ b/hw/arm/virt.c
> > @@ -2671,10 +2671,10 @@ static void virt_machine_class_init(ObjectClass 
> > *oc, void *data)
> >"Set the IOMMU type. "
> >"Valid values are none and 
> > smmuv3");
> >  
> > -object_class_property_add_bool(oc, "default_bus_bypass_iommu",
> > +object_class_property_add_bool(oc, "default-bus-bypass-iommu",
> > virt_get_default_bus_bypass_iommu,
> > virt_set_default_bus_bypass_iommu);
> > -object_class_property_set_description(oc, "default_bus_bypass_iommu",
> > +object_class_property_set_description(oc, "default-bus-bypass-iommu",
> >"Set on/off to enable/disable "
> >"bypass_iommu for default root 
> > bus");
> 



[PATCH for-7.0 2/4] hw/nvme: add zone attribute get/set helpers

2021-11-24 Thread Klaus Jensen
From: Klaus Jensen 

Add some get/set helpers for zone attributes.

Signed-off-by: Klaus Jensen 
---
 hw/nvme/ctrl.c   | 4 ++--
 include/block/nvme.h | 4 
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index 489d586ab9d7..7ac6ec50a0d1 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -295,7 +295,7 @@ static void nvme_assign_zone_state(NvmeNamespace *ns, 
NvmeZone *zone,
 case NVME_ZONE_STATE_READ_ONLY:
 break;
 default:
-zone->d.za = 0;
+NVME_ZA_CLEAR_ALL(zone->d.za);
 }
 }
 
@@ -3356,7 +3356,7 @@ static uint16_t nvme_set_zd_ext(NvmeNamespace *ns, 
NvmeZone *zone)
 return status;
 }
 nvme_aor_inc_active(ns);
-zone->d.za |= NVME_ZA_ZD_EXT_VALID;
+NVME_ZA_SET(zone->d.za, NVME_ZA_ZD_EXT_VALID);
 nvme_assign_zone_state(ns, zone, NVME_ZONE_STATE_CLOSED);
 return NVME_SUCCESS;
 }
diff --git a/include/block/nvme.h b/include/block/nvme.h
index 2ee227760265..2b8b906466ab 100644
--- a/include/block/nvme.h
+++ b/include/block/nvme.h
@@ -1407,6 +1407,10 @@ enum NvmeZoneAttr {
 NVME_ZA_ZD_EXT_VALID = 1 << 7,
 };
 
+#define NVME_ZA_SET(za, attrs)   ((za) |= (attrs))
+#define NVME_ZA_CLEAR(za, attrs) ((za) &= ~(attrs))
+#define NVME_ZA_CLEAR_ALL(za)((za) = 0x0)
+
 typedef struct QEMU_PACKED NvmeZoneReportHeader {
 uint64_tnr_zones;
 uint8_t rsvd[56];
-- 
2.34.0




[PATCH for-7.0 3/4] hw/nvme: add ozcs enum

2021-11-24 Thread Klaus Jensen
From: Klaus Jensen 

Add enumeration for OZCS values.

Signed-off-by: Klaus Jensen 
---
 hw/nvme/ns.c | 3 ++-
 include/block/nvme.h | 4 
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c
index 8b5f98c76180..356b6c1c2f14 100644
--- a/hw/nvme/ns.c
+++ b/hw/nvme/ns.c
@@ -266,7 +266,8 @@ static void nvme_ns_init_zoned(NvmeNamespace *ns)
 id_ns_z->mar = cpu_to_le32(ns->params.max_active_zones - 1);
 id_ns_z->mor = cpu_to_le32(ns->params.max_open_zones - 1);
 id_ns_z->zoc = 0;
-id_ns_z->ozcs = ns->params.cross_zone_read ? 0x01 : 0x00;
+id_ns_z->ozcs = ns->params.cross_zone_read ?
+NVME_ID_NS_ZONED_OZCS_RAZB : 0x00;
 
 for (i = 0; i <= ns->id_ns.nlbaf; i++) {
 id_ns_z->lbafe[i].zsze = cpu_to_le64(ns->zone_size);
diff --git a/include/block/nvme.h b/include/block/nvme.h
index 2b8b906466ab..d33ff2c184cf 100644
--- a/include/block/nvme.h
+++ b/include/block/nvme.h
@@ -1351,6 +1351,10 @@ typedef struct QEMU_PACKED NvmeIdNsZoned {
 uint8_t vs[256];
 } NvmeIdNsZoned;
 
+enum NvmeIdNsZonedOzcs {
+NVME_ID_NS_ZONED_OZCS_RAZB= 1 << 0,
+};
+
 /*Deallocate Logical Block Features*/
 #define NVME_ID_NS_DLFEAT_GUARD_CRC(dlfeat)   ((dlfeat) & 0x10)
 #define NVME_ID_NS_DLFEAT_WRITE_ZEROES(dlfeat)((dlfeat) & 0x08)
-- 
2.34.0




[PATCH for-7.0 4/4] hw/nvme: add support for zoned random write area

2021-11-24 Thread Klaus Jensen
From: Klaus Jensen 

Add support for TP 4076 ("Zoned Random Write Area"), v2021.08.23
("Ratified").

This adds three new namespace parameters: "zoned.numzrwa" (number of
zrwa resources, i.e. number of zones that can have a zrwa),
"zoned.zrwas" (zrwa size in LBAs), "zoned.zrwafg" (granularity in LBAs
for flushes).

Signed-off-by: Klaus Jensen 
---
 hw/nvme/ctrl.c   | 171 ++-
 hw/nvme/ns.c |  58 +++
 hw/nvme/nvme.h   |  10 +++
 hw/nvme/trace-events |   1 +
 include/block/nvme.h |  17 -
 5 files changed, 237 insertions(+), 20 deletions(-)

diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index 7ac6ec50a0d1..4c9b303dfdca 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -299,26 +299,37 @@ static void nvme_assign_zone_state(NvmeNamespace *ns, 
NvmeZone *zone,
 }
 }
 
-/*
- * Check if we can open a zone without exceeding open/active limits.
- * AOR stands for "Active and Open Resources" (see TP 4053 section 2.5).
- */
-static int nvme_aor_check(NvmeNamespace *ns, uint32_t act, uint32_t opn)
+static uint16_t nvme_zns_check_resources(NvmeNamespace *ns, uint32_t act,
+ uint32_t opn, uint32_t zrwa)
 {
 if (ns->params.max_active_zones != 0 &&
 ns->nr_active_zones + act > ns->params.max_active_zones) {
 trace_pci_nvme_err_insuff_active_res(ns->params.max_active_zones);
 return NVME_ZONE_TOO_MANY_ACTIVE | NVME_DNR;
 }
+
 if (ns->params.max_open_zones != 0 &&
 ns->nr_open_zones + opn > ns->params.max_open_zones) {
 trace_pci_nvme_err_insuff_open_res(ns->params.max_open_zones);
 return NVME_ZONE_TOO_MANY_OPEN | NVME_DNR;
 }
 
+if (zrwa > ns->zns.numzrwa) {
+return NVME_NOZRWA | NVME_DNR;
+}
+
 return NVME_SUCCESS;
 }
 
+/*
+ * Check if we can open a zone without exceeding open/active limits.
+ * AOR stands for "Active and Open Resources" (see TP 4053 section 2.5).
+ */
+static uint16_t nvme_aor_check(NvmeNamespace *ns, uint32_t act, uint32_t opn)
+{
+return nvme_zns_check_resources(ns, act, opn, 0);
+}
+
 static bool nvme_addr_is_cmb(NvmeCtrl *n, hwaddr addr)
 {
 hwaddr hi, lo;
@@ -1605,9 +1616,19 @@ static uint16_t nvme_check_zone_write(NvmeNamespace *ns, 
NvmeZone *zone,
 return status;
 }
 
-if (unlikely(slba != zone->w_ptr)) {
-trace_pci_nvme_err_write_not_at_wp(slba, zone->d.zslba, zone->w_ptr);
-return NVME_ZONE_INVALID_WRITE;
+if (zone->d.za & NVME_ZA_ZRWA_VALID) {
+uint64_t ezrwa = zone->w_ptr + 2 * ns->zns.zrwas;
+
+if (slba < zone->w_ptr || slba + nlb > ezrwa) {
+trace_pci_nvme_err_zone_invalid_write(slba, zone->w_ptr);
+return NVME_ZONE_INVALID_WRITE;
+}
+} else {
+if (unlikely(slba != zone->w_ptr)) {
+trace_pci_nvme_err_write_not_at_wp(slba, zone->d.zslba,
+   zone->w_ptr);
+return NVME_ZONE_INVALID_WRITE;
+}
 }
 
 if (unlikely((slba + nlb) > zcap)) {
@@ -1687,6 +1708,14 @@ static uint16_t nvme_zrm_finish(NvmeNamespace *ns, 
NvmeZone *zone)
 /* fallthrough */
 case NVME_ZONE_STATE_CLOSED:
 nvme_aor_dec_active(ns);
+
+if (zone->d.za & NVME_ZA_ZRWA_VALID) {
+NVME_ZA_CLEAR(zone->d.za, NVME_ZA_ZRWA_VALID);
+if (ns->params.numzrwa) {
+ns->zns.numzrwa++;
+}
+}
+
 /* fallthrough */
 case NVME_ZONE_STATE_EMPTY:
 nvme_assign_zone_state(ns, zone, NVME_ZONE_STATE_FULL);
@@ -1722,6 +1751,13 @@ static uint16_t nvme_zrm_reset(NvmeNamespace *ns, 
NvmeZone *zone)
 /* fallthrough */
 case NVME_ZONE_STATE_CLOSED:
 nvme_aor_dec_active(ns);
+
+if (zone->d.za & NVME_ZA_ZRWA_VALID) {
+if (ns->params.numzrwa) {
+ns->zns.numzrwa++;
+}
+}
+
 /* fallthrough */
 case NVME_ZONE_STATE_FULL:
 zone->w_ptr = zone->d.zslba;
@@ -1755,6 +1791,7 @@ static void nvme_zrm_auto_transition_zone(NvmeNamespace 
*ns)
 
 enum {
 NVME_ZRM_AUTO = 1 << 0,
+NVME_ZRM_ZRWA = 1 << 1,
 };
 
 static uint16_t nvme_zrm_open_flags(NvmeCtrl *n, NvmeNamespace *ns,
@@ -1773,7 +1810,8 @@ static uint16_t nvme_zrm_open_flags(NvmeCtrl *n, 
NvmeNamespace *ns,
 if (n->params.auto_transition_zones) {
 nvme_zrm_auto_transition_zone(ns);
 }
-status = nvme_aor_check(ns, act, 1);
+status = nvme_zns_check_resources(ns, act, 1,
+  (flags & NVME_ZRM_ZRWA) ? 1 : 0);
 if (status) {
 return status;
 }
@@ -1801,6 +1839,12 @@ static uint16_t nvme_zrm_open_flags(NvmeCtrl *n, 
NvmeNamespace *ns,
 /* fallthrough */
 
 case NVME_ZONE_STATE_EXPLICITLY_OPEN:
+if (flags & NVME_ZRM_ZRWA) {
+ns->zns.numzrwa--;
+
+NVME_ZA_SET(zone->d.za, 

[PATCH for-7.0 1/4] hw/nvme: add struct for zone management send

2021-11-24 Thread Klaus Jensen
From: Klaus Jensen 

Add struct for Zone Management Send in preparation for more zone send
flags.

Signed-off-by: Klaus Jensen 
---
 hw/nvme/ctrl.c   | 10 --
 include/block/nvme.h | 18 ++
 2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index 5f573c417b3d..489d586ab9d7 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -3593,26 +3593,24 @@ done:
 
 static uint16_t nvme_zone_mgmt_send(NvmeCtrl *n, NvmeRequest *req)
 {
-NvmeCmd *cmd = (NvmeCmd *)>cmd;
+NvmeZoneSendCmd *cmd = (NvmeZoneSendCmd *)>cmd;
 NvmeNamespace *ns = req->ns;
 NvmeZone *zone;
 NvmeZoneResetAIOCB *iocb;
 uint8_t *zd_ext;
-uint32_t dw13 = le32_to_cpu(cmd->cdw13);
 uint64_t slba = 0;
 uint32_t zone_idx = 0;
 uint16_t status;
-uint8_t action;
+uint8_t action = cmd->zsa;
 bool all;
 enum NvmeZoneProcessingMask proc_mask = NVME_PROC_CURRENT_ZONE;
 
-action = dw13 & 0xff;
-all = !!(dw13 & 0x100);
+all = cmd->zsflags[0] & NVME_ZSFLAG_SELECT_ALL;
 
 req->status = NVME_SUCCESS;
 
 if (!all) {
-status = nvme_get_mgmt_zone_slba_idx(ns, cmd, , _idx);
+status = nvme_get_mgmt_zone_slba_idx(ns, >cmd, , _idx);
 if (status) {
 return status;
 }
diff --git a/include/block/nvme.h b/include/block/nvme.h
index e3bd47bf76ab..2ee227760265 100644
--- a/include/block/nvme.h
+++ b/include/block/nvme.h
@@ -1433,6 +1433,20 @@ enum NvmeZoneType {
 NVME_ZONE_TYPE_SEQ_WRITE = 0x02,
 };
 
+typedef struct QEMU_PACKED NvmeZoneSendCmd {
+uint8_t opcode;
+uint8_t flags;
+uint16_tcid;
+uint32_tnsid;
+uint32_trsvd2[4];
+NvmeCmdDptr dptr;
+uint64_tslba;
+uint32_trsvd12;
+uint8_t zsa;
+uint8_t zsflags[3];
+uint32_trsvd14[2];
+} NvmeZoneSendCmd;
+
 enum NvmeZoneSendAction {
 NVME_ZONE_ACTION_RSD = 0x00,
 NVME_ZONE_ACTION_CLOSE   = 0x01,
@@ -1443,6 +1457,10 @@ enum NvmeZoneSendAction {
 NVME_ZONE_ACTION_SET_ZD_EXT  = 0x10,
 };
 
+enum {
+NVME_ZSFLAG_SELECT_ALL = 1 << 0,
+};
+
 typedef struct QEMU_PACKED NvmeZoneDescr {
 uint8_t zt;
 uint8_t zs;
-- 
2.34.0




[PATCH for-7.0 0/4] hw/nvme: zoned random write area

2021-11-24 Thread Klaus Jensen
From: Klaus Jensen 

This series adds support for a zoned random write area as standardized
in TP 4076 ("Zoned Random Write Area").

Klaus Jensen (4):
  hw/nvme: add struct for zone management send
  hw/nvme: add zone attribute get/set helpers
  hw/nvme: add ozcs enum
  hw/nvme: add support for zoned random write area

 hw/nvme/ctrl.c   | 185 ---
 hw/nvme/ns.c |  61 +-
 hw/nvme/nvme.h   |  10 +++
 hw/nvme/trace-events |   1 +
 include/block/nvme.h |  43 +-
 5 files changed, 271 insertions(+), 29 deletions(-)

-- 
2.34.0




Re: [PATCH v3 03/23] multifd: Rename used field to num

2021-11-24 Thread Juan Quintela
"Dr. David Alan Gilbert"  wrote:
> * Juan Quintela (quint...@redhat.com) wrote:
>> We will need to split it later in zero_num (number of zero pages) and
>> normal_num (number of normal pages).  This name is better.
>> 
>> Signed-off-by: Juan Quintela 
>> ---
>>  migration/multifd.h |  2 +-
>>  migration/multifd.c | 38 +++---
>>  2 files changed, 20 insertions(+), 20 deletions(-)
>> 
>> diff --git a/migration/multifd.h b/migration/multifd.h
>> index 15c50ca0b2..86820dd028 100644
>> --- a/migration/multifd.h
>> +++ b/migration/multifd.h
>> @@ -55,7 +55,7 @@ typedef struct {
>>  
>>  typedef struct {
>>  /* number of used pages */
>> -uint32_t used;
>> +uint32_t num;
>
> What does 'used' actually mean here?

We allocate 128 pages for each "packet".
But we can ben handled less than that (we are at the end of one
iteration, the end of a ramblock, ...).
That is what used mean.

But later on the series, we enter with normal pages, and zero pages, and
naming get really confusing.  So, I moved to use *_num for everything.

Even after all the series, I didn't rename everything on multifd, only
the fields that I have to use sooner or later.

Later, Juan.




Re: [PATCH v3 01/23] multifd: Delete useless operation

2021-11-24 Thread Juan Quintela
"Dr. David Alan Gilbert"  wrote:
> * Juan Quintela (quint...@redhat.com) wrote:
>> We are divining by page_size to multiply again in the only use.
>  ^--- typo
>> Once there, impreve the comments.
>   ^--- typo
>> 
>> Signed-off-by: Juan Quintela 
>
> OK, with the typo's fixed:

Thanks.

> Reviewed-by: Dr. David Alan Gilbert 
>
> but, could you also explain the  x 2 (that's no worse than the current
> code); is this defined somewhere in zlib?  I thought there was a routine
> that told you the worst case?

Nowhere.

There are pathological cases where it can be worse.  Not clear at all
how much (ok, for zlib it appears that it is on the order of dozen of
bytes, because it marks it as uncompressed on the worst possible case),
For zstd, there is not a clear/fast answer when you google.

As this buffer is held for the whole migration, it is one for thread,
this looked safe to me.  Notice that we are compressing 128 pages at a
time, so for it not to compress anything looks very pathological.

But as one says, better safe than sorry.

If anyone that knows more about zlib/zstd give me different values, I
will change that in an additional patch.

Later, Juan.




Re: [PATCH v3 02/23] migration: Never call twice qemu_target_page_size()

2021-11-24 Thread Juan Quintela
"Dr. David Alan Gilbert"  wrote:
> * Juan Quintela (quint...@redhat.com) wrote:
>> Signed-off-by: Juan Quintela 
>
> OK, not much difference

This was after "finishing" the series I realised that I was calling that
function around 30 times or so in that three files.  And as Richard
complained when I put that inside a loop, I just decided to optimize
all.  Once that I optimized it.

O:-)

> Reviewed-by: Dr. David Alan Gilbert 

Thanks, Juan.




Re: [PATCH 2/2] hw/i386: Rename default_bus_bypass_iommu

2021-11-24 Thread Michael S. Tsirkin
On Thu, Nov 25, 2021 at 08:12:25AM +0100, Markus Armbruster wrote:
> Michael & Marcel, this patch fixes a bug that became a regression when
> the fix missed 6.1.  It's been stuck on the list since August.  Please
> have a look, and if it's good, get it merged.


Thanks for the reminder. Jean-Philippe, Cc maintainers
will help patches get merged in a timely manner in the future.

>  I just asked the arm/virt
> maintainer to do the same for PATCH 1.

Some questions below.

> Jean-Philippe Brucker  writes:
> 
> > Since commit d8fb7d0969d5 ("vl: switch -M parsing to keyval"), machine
> > parameter definitions cannot use underscores, because keyval_dashify()
> > transforms them to dashes and the parser doesn't find the parameter.
> >
> > This affects option default_bus_bypass_iommu which was introduced in the
> > same release:
> >
> > $ qemu-system-x86_64 -M q35,default_bus_bypass_iommu=on
> > qemu-system-x86_64: Property 'pc-q35-6.1-machine.default-bus-bypass-iommu' 
> > not found

I don't see this behaviour. What did I miss?


> > Rename the parameter to "default-bus-bypass-iommu". Passing
> > "default_bus_bypass_iommu" is still valid since the underscore are
> > transformed automatically.
> >
> > Fixes: c9e96b04fc19 ("hw/i386: Add a default_bus_bypass_iommu pc machine 
> > option")
> > Signed-off-by: Jean-Philippe Brucker 
> > ---
> >  hw/i386/pc.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> > index fb24f000e7..ce4756ad59 100644
> > --- a/hw/i386/pc.c
> > +++ b/hw/i386/pc.c
> > @@ -1779,7 +1779,7 @@ static void pc_machine_class_init(ObjectClass *oc, 
> > void *data)
> >  object_class_property_add_bool(oc, "hpet",
> >  pc_machine_get_hpet, pc_machine_set_hpet);
> >  
> > -object_class_property_add_bool(oc, "default_bus_bypass_iommu",
> > +object_class_property_add_bool(oc, "default-bus-bypass-iommu",
> >  pc_machine_get_default_bus_bypass_iommu,
> >  pc_machine_set_default_bus_bypass_iommu);
> 
> 
> 




Re: SEV guest attestation

2021-11-24 Thread Sergio Lopez
On Wed, Nov 24, 2021 at 06:29:07PM +, Dr. David Alan Gilbert wrote:
> * Daniel P. Berrangé (berra...@redhat.com) wrote:
> > On Wed, Nov 24, 2021 at 11:34:16AM -0500, Tyler Fanelli wrote:
> > > Hi,
> > > 
> > > We recently discussed a way for remote SEV guest attestation through QEMU.
> > > My initial approach was to get data needed for attestation through 
> > > different
> > > QMP commands (all of which are already available, so no changes required
> > > there), deriving hashes and certificate data; and collecting all of this
> > > into a new QMP struct (SevLaunchStart, which would include the VM's 
> > > policy,
> > > secret, and GPA) which would need to be upstreamed into QEMU. Once this is
> > > provided, QEMU would then need to have support for attestation before a VM
> > > is started. Upon speaking to Dave about this proposal, he mentioned that
> > > this may not be the best approach, as some situations would render the
> > > attestation unavailable, such as the instance where a VM is running in a
> > > cloud, and a guest owner would like to perform attestation via QMP (a 
> > > likely
> > > scenario), yet a cloud provider cannot simply let anyone pass arbitrary 
> > > QMP
> > > commands, as this could be an issue.
> > 
> > As a general point, QMP is a low level QEMU implementation detail,
> > which is generally expected to be consumed exclusively on the host
> > by a privileged mgmt layer, which will in turn expose its own higher
> > level APIs to users or other apps. I would not expect to see QMP
> > exposed to anything outside of the privileged host layer.
> > 
> > We also use the QAPI protocol for QEMU guest agent commmunication,
> > however, that is a distinct service from QMP on the host. It shares
> > most infra with QMP but has a completely diffent command set. On the
> > host it is not consumed inside QEMU, but instead consumed by a
> > mgmt app like libvirt. 
> > 
> > > So I ask, does anyone involved in QEMU's SEV implementation have any input
> > > on a quality way to perform guest attestation? If so, I'd be interested.
> > 
> > I think what's missing is some clearer illustrations of how this
> > feature is expected to be consumed in some real world application
> > and the use cases we're trying to solve.
> > 
> > I'd like to understand how it should fit in with common libvirt
> > applications across the different virtualization management
> > scenarios - eg virsh (command line),  virt-manger (local desktop
> > GUI), cockpit (single host web mgmt), OpenStack (cloud mgmt), etc.
> > And of course any non-traditional virt use cases that might be
> > relevant such as Kata.
> 
> That's still not that clear; I know Alice and Sergio have some ideas
> (cc'd).
> There's also some standardisation efforts (e.g. 
> https://www.potaroo.net/ietf/html/ids-wg-rats.html 
> and https://www.ietf.org/archive/id/draft-ietf-rats-architecture-00.html
> ) - that I can't claim to fully understand.
> However, there are some themes that are emerging:
> 
>   a) One use is to only allow a VM to access some private data once we
> prove it's the VM we expect running in a secure/confidential system
>   b) (a) normally involves requesting some proof from the VM and then
> providing it some confidential data/a key if it's OK
>   c) RATs splits the problem up:
> 
> https://www.ietf.org/archive/id/draft-ietf-rats-architecture-00.html#name-architectural-overview
> I don't fully understand the split yet, but in principal there are
> at least a few different things:
> 
>   d) The comms layer
>   e) Something that validates the attestation message (i.e. the
> signatures are valid, the hashes all add up etc)
>   f) Something that knows what hashes to expect (i.e. oh that's a RHEL
> 8.4 kernel, or that's a valid kernel command line)
>   g) Something that holds some secrets that can be handed out if e & f
> are happy.
> 
>   There have also been proposals (e.g. Intel HTTPA) for an attestable
> connection after a VM is running; that's probably quite different from
> (g) but still involves (e) & (f).
> 
> In the simpler setups d,e,f,g probably live in one place; but it's not
> clear where they live - for example one scenario says that your cloud
> management layer holds some of them, another says you don't trust your
> cloud management layer and you keep them separate.
> 
> So I think all we're actually interested in at the moment, is (d) and
> (e) and the way for (g) to get the secret back to the guest.
> 
> Unfortunately the comms and the contents of them varies heavily with
> technology; in some you're talking to the qemu/hypervisor (SEV/SEV-ES)
> while in some you're talking to the guest after boot (SEV-SNP/TDX maybe
> SEV-ES in some cases).
> 
> So my expectation at the moment is libvirt needs to provide a transport
> layer for the comms, to enable an external validator to retrieve the
> measurements from the guest/hypervisor and provide data back if
> necessary.  Once this shakes out a bit, we might want libvirt to 

Re: [PATCH 2/2] hw/i386: Rename default_bus_bypass_iommu

2021-11-24 Thread Markus Armbruster
Michael & Marcel, this patch fixes a bug that became a regression when
the fix missed 6.1.  It's been stuck on the list since August.  Please
have a look, and if it's good, get it merged.  I just asked the arm/virt
maintainer to do the same for PATCH 1.

Jean-Philippe Brucker  writes:

> Since commit d8fb7d0969d5 ("vl: switch -M parsing to keyval"), machine
> parameter definitions cannot use underscores, because keyval_dashify()
> transforms them to dashes and the parser doesn't find the parameter.
>
> This affects option default_bus_bypass_iommu which was introduced in the
> same release:
>
> $ qemu-system-x86_64 -M q35,default_bus_bypass_iommu=on
> qemu-system-x86_64: Property 'pc-q35-6.1-machine.default-bus-bypass-iommu' 
> not found
>
> Rename the parameter to "default-bus-bypass-iommu". Passing
> "default_bus_bypass_iommu" is still valid since the underscore are
> transformed automatically.
>
> Fixes: c9e96b04fc19 ("hw/i386: Add a default_bus_bypass_iommu pc machine 
> option")
> Signed-off-by: Jean-Philippe Brucker 
> ---
>  hw/i386/pc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index fb24f000e7..ce4756ad59 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -1779,7 +1779,7 @@ static void pc_machine_class_init(ObjectClass *oc, void 
> *data)
>  object_class_property_add_bool(oc, "hpet",
>  pc_machine_get_hpet, pc_machine_set_hpet);
>  
> -object_class_property_add_bool(oc, "default_bus_bypass_iommu",
> +object_class_property_add_bool(oc, "default-bus-bypass-iommu",
>  pc_machine_get_default_bus_bypass_iommu,
>  pc_machine_set_default_bus_bypass_iommu);




Re: [PATCH 1/2] hw/arm/virt: Rename default_bus_bypass_iommu

2021-11-24 Thread Markus Armbruster
Peter, this patch fixes a bug that became a regression when the fix
missed 6.1.  It's been stuck on the list since August.  Please have a
look, and if it's good, get it merged.  I'll ask the i386/pc maintainers
to do the same for PATCH 2.

Jean-Philippe Brucker  writes:

> Since commit d8fb7d0969d5 ("vl: switch -M parsing to keyval"), machine
> parameter definitions cannot use underscores, because keyval_dashify()
> transforms them to dashes and the parser doesn't find the parameter.
>
> This affects option default_bus_bypass_iommu which was introduced in the
> same release:
>
> $ qemu-system-aarch64 -M virt,default_bus_bypass_iommu=on
> qemu-system-aarch64: Property 'virt-6.1-machine.default-bus-bypass-iommu' not 
> found
>
> Rename the parameter to "default-bus-bypass-iommu". Passing
> "default_bus_bypass_iommu" is still valid since the underscore are
> transformed automatically.
>
> Fixes: 6d7a85483a06 ("hw/arm/virt: Add default_bus_bypass_iommu machine 
> option")
> Signed-off-by: Jean-Philippe Brucker 
> ---
>  hw/arm/virt.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index b4598d3fe6..7075cdc15e 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -2671,10 +2671,10 @@ static void virt_machine_class_init(ObjectClass *oc, 
> void *data)
>"Set the IOMMU type. "
>"Valid values are none and 
> smmuv3");
>  
> -object_class_property_add_bool(oc, "default_bus_bypass_iommu",
> +object_class_property_add_bool(oc, "default-bus-bypass-iommu",
> virt_get_default_bus_bypass_iommu,
> virt_set_default_bus_bypass_iommu);
> -object_class_property_set_description(oc, "default_bus_bypass_iommu",
> +object_class_property_set_description(oc, "default-bus-bypass-iommu",
>"Set on/off to enable/disable "
>"bypass_iommu for default root 
> bus");




[PING][Ping] [PATCH v1 0/2] vl: flush all task from rcu queue before exiting

2021-11-24 Thread Denis Plotnikov

ping ping

On 19.11.2021 12:42, Denis Plotnikov wrote:


Ping!

On 15.11.2021 12:41, Denis Plotnikov wrote:

v1 -> v0:
  * move monitor cleanup to the very end of qemu cleanup [Paolo]

The goal is to notify management layer about device destruction on qemu 
shutdown.
Without this series DEVICE_DELETED event may not be sent because of stuck tasks
in the rcu thread. The rcu tasks may stuck on qemu shutdown because the rcu
not always have enough time to run them.


Denis Plotnikov (2):
   monitor: move monitor destruction to the very end of qemu cleanup
   vl: flush all task from rcu queue before exiting

  include/qemu/rcu.h |  1 +
  monitor/monitor.c  |  6 ++
  softmmu/runstate.c |  4 +++-
  util/rcu.c | 12 
  4 files changed, 22 insertions(+), 1 deletion(-)



Re: [PATCH 01/20] Hexagon HVX (target/hexagon) README

2021-11-24 Thread Rob Landley
On 7/26/21 8:59 AM, Taylor Simpson wrote:
> We're working on system mode support for Hexagon, and we plan to upstream it 
> when it is ready.
> 
> Thanks,
> Taylor

Any progress on this? (Is there a way for outsiders to track the status?)

Thanks,

Rob



Re: [PATCH] intel-iommu: ignore SNP bit in scalable mode

2021-11-24 Thread Peter Xu
On Thu, Nov 25, 2021 at 05:49:38AM +, Liu, Yi L wrote:
> > From: Peter Xu 
> > Sent: Thursday, November 25, 2021 12:31 PM
> > 
> > On Thu, Nov 25, 2021 at 04:03:34AM +, Liu, Yi L wrote:
> > > > From: Peter Xu 
> > > > Sent: Wednesday, November 24, 2021 3:57 PM
> > > >
> > > > On Wed, Nov 24, 2021 at 02:03:09PM +0800, Jason Wang wrote:
> > > > > When booting with scalable mode, I hit this error:
> > > > >
> > > > > qemu-system-x86_64: vtd_iova_to_slpte: detected splte reserve non-
> > > > zero iova=0xf002, level=0x1slpte=0x102681803)
> > > > > qemu-system-x86_64: vtd_iommu_translate: detected translation
> > failure
> > > > (dev=01:00:00, iova=0xf002)
> > > > > qemu-system-x86_64: New fault is not recorded due to compression
> > of
> > > > faults
> > > > >
> > > > > This is because the SNP bit is set since Linux kernel commit
> > > > > 6c00612d0cba1 ("iommu/vt-d: Report right snoop capability when
> > using
> > > > > FL for IOVA") where SNP bit is set if scalable mode is on though this
> > > > > seems to be an violation on the spec which said the SNP bit is
> > > > > considered to be reserved if SC is not supported.
> > > >
> > > > When I was reading that commit, I was actually confused by this change:
> > > >
> > > > ---8<---
> > > > diff --git a/drivers/iommu/intel/iommu.c
> > b/drivers/iommu/intel/iommu.c
> > > > index 956a02eb40b4..0ee5f1bd8af2 100644
> > > > --- a/drivers/iommu/intel/iommu.c
> > > > +++ b/drivers/iommu/intel/iommu.c
> > > > @@ -658,7 +658,14 @@ static int
> > domain_update_iommu_snooping(struct
> > > > intel_iommu *skip)
> > > > rcu_read_lock();
> > > > for_each_active_iommu(iommu, drhd) {
> > > > if (iommu != skip) {
> > > > -   if (!ecap_sc_support(iommu->ecap)) {
> > > > +   /*
> > > > +* If the hardware is operating in the scalable 
> > > > mode,
> > > > +* the snooping control is always supported 
> > > > since we
> > > > +* always set PASID-table-entry.PGSNP bit if 
> > > > the domain
> > > > +* is managed outside (UNMANAGED).
> > > > +*/
> > > > +   if (!sm_supported(iommu) &&
> > > > +   !ecap_sc_support(iommu->ecap)) {
> > > > ret = 0;
> > > > break;
> > > > }
> > > > ---8<---
> > > >
> > > > Does it mean that for some hardwares that has sm_supported()==true,
> > it'll
> > > > have  SC bit cleared in ecap register?  That sounds odd, and not sure 
> > > > why.
> > Maybe
> > > > Yi Liu or Yi Sun may know?
> > >
> > > scalable mode has no dependency on SC, so it's possible.
> > 
> > I see; thanks, Yi.
> > 
> > However then OTOH I don't understand above comment
> > 
> >   "If the hardware is operating in the scalable mode, the snooping control 
> > is
> >always supported since... "
> > 
> > Because the current qemu vt-d emulation should fall into the case that Yi
> > mentioned - we support initial scalable mode but no SC yet..
> 
> chapter 3.9 of 3.2 spec says below.
> 
> “If the remapping hardware is setup in scalable-mode (RTADDR_REG.TTM=01b)
> and the Page Snoop (PGSNP) field in PASID-table entry is Set, access to the
> final page is snooped.”
> 
> It means the PGSNP field is available under scalable mode. And spec also
> says below in chapter 96. of 3.2 spec.
> 
> "Requests snoop processor caches irrespective of, other attributes in the
> request or other fields in paging structure entries used to translate the
> request."
> 
> It means the PGSNP field of PASID table entry is the first class control
> of the snoop behaviour. Also it means the scalable mode has the snoop
> control by default. ^_^. So the comment in the above commit is correct
> since the policy of intel iommu driver is always setting the PGSNP bit.

I see.  Setting PGSNP bit in the pasid entry looks fine to me.

However IIUC what's triggering the crash (that Jason is fixing) is the guest
iommu driver "thinks" SC is supported since scalable is enabled (even if qemu
vIOMMU has declared ECAP.SC==0 there), then it'll update iommu_snooping bit,
then it'll try to attach the SNP bit in the 2nd level pgtable (intel_iommu_map):

if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
prot |= DMA_PTE_SNP;

So what I'm wondering is: whether the kernel should _not_ set SNP bit in the
2nd level pgtable, even if we set PGSNP in the pasid entry.. because as you
mentioned, the hardware (here the emulated vIOMMU) is allowed to have both
scalable==1 but sc==0 so it may recognize PGSNP in pasid entry but not the SNP
bit in pgtables.

If we'll skip pgtable SNP bit anyway for scalable mode, it looks weird to
explicitly set it too.

I think it's fine for Jason's solution to just skip checking SNP bit so we
ignore it in qemu, however just to double check we're on 

RE: [PATCH] intel-iommu: ignore SNP bit in scalable mode

2021-11-24 Thread Liu, Yi L
> From: Jason Wang 
> Sent: Wednesday, November 24, 2021 4:29 PM
> 
> On Wed, Nov 24, 2021 at 3:57 PM Peter Xu  wrote:
> >
> > On Wed, Nov 24, 2021 at 02:03:09PM +0800, Jason Wang wrote:
> > > When booting with scalable mode, I hit this error:
> > >
> > > qemu-system-x86_64: vtd_iova_to_slpte: detected splte reserve non-
> zero iova=0xf002, level=0x1slpte=0x102681803)
> > > qemu-system-x86_64: vtd_iommu_translate: detected translation
> failure (dev=01:00:00, iova=0xf002)
> > > qemu-system-x86_64: New fault is not recorded due to compression of
> faults
> > >
> > > This is because the SNP bit is set since Linux kernel commit
> > > 6c00612d0cba1 ("iommu/vt-d: Report right snoop capability when using
> > > FL for IOVA") where SNP bit is set if scalable mode is on though this
> > > seems to be an violation on the spec which said the SNP bit is
> > > considered to be reserved if SC is not supported.
> >
> > When I was reading that commit, I was actually confused by this change:
> >
> > ---8<---
> > diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
> > index 956a02eb40b4..0ee5f1bd8af2 100644
> > --- a/drivers/iommu/intel/iommu.c
> > +++ b/drivers/iommu/intel/iommu.c
> > @@ -658,7 +658,14 @@ static int
> domain_update_iommu_snooping(struct intel_iommu *skip)
> > rcu_read_lock();
> > for_each_active_iommu(iommu, drhd) {
> > if (iommu != skip) {
> > -   if (!ecap_sc_support(iommu->ecap)) {
> > +   /*
> > +* If the hardware is operating in the scalable 
> > mode,
> > +* the snooping control is always supported since we
> > +* always set PASID-table-entry.PGSNP bit if the 
> > domain
> > +* is managed outside (UNMANAGED).
> > +*/
> > +   if (!sm_supported(iommu) &&
> > +   !ecap_sc_support(iommu->ecap)) {
> > ret = 0;
> > break;
> > }
> > ---8<---
> >
> > Does it mean that for some hardwares that has sm_supported()==true,
> it'll have
> > SC bit cleared in ecap register?
> 
> I guess not, so it's probably only the problem of vIOMMU.
> 
> > That sounds odd, and not sure why.  Maybe Yi
> > Liu or Yi Sun may know?
> 
> Another interesting point is that, it looks to me after that commit
> SNP is used for the domain that is not UNMANAGED even if PGSNP is not
> set.

Per spec, if the PGSNP is set, it means the final page access is snooped.
If it's not set, then it's up to other bit to decide it. For detail, you may
refer to table 6 of chapter 3.9 in vtd 3.2 spec.

Regards,
Yi Liu




RE: [PATCH] intel-iommu: ignore SNP bit in scalable mode

2021-11-24 Thread Liu, Yi L
> From: Jason Wang 
> Sent: Wednesday, November 24, 2021 5:35 PM
> 
> On Wed, Nov 24, 2021 at 5:23 PM Peter Xu  wrote:
> >
> > On Wed, Nov 24, 2021 at 05:01:42PM +0800, Jason Wang wrote:
> > > > > > > -static bool vtd_slpte_nonzero_rsvd(uint64_t slpte, uint32_t
> level)
> > > > > > > +static bool vtd_slpte_nonzero_rsvd(IntelIOMMUState *s,
> > > > > > > +   uint64_t slpte, uint32_t 
> > > > > > > level)
> > > > > > >  {
> > > > > > >  uint64_t rsvd_mask = vtd_spte_rsvd[level];
> > > > > > >
> > > > > > > @@ -979,6 +980,10 @@ static bool
> vtd_slpte_nonzero_rsvd(uint64_t slpte, uint32_t level)
> > > > > > >  rsvd_mask = vtd_spte_rsvd_large[level];
> > > > > > >  }
> > > > > > >
> > > > > > > +if (s->scalable_mode) {
> > > > > > > +rsvd_mask &= ~VTD_SPTE_SNP;
> > > > > > > +}
> > > > > >
> > > > > > IMHO what we want to do is only to skip the leaves of pgtables on
> SNP, so maybe
> > > > > > we still want to keep checking the bit 11 reserved for e.g. common
> pgtable dir
> > > > > > entries?
> > >
> > > Maybe, but it's probably a question that can only be answered by
> > > Intel. I can change it for the next version if you stick.
> >
> > I'm reading vtd spec v3.1 (June 2019) here, and chap 9.8 told me they're
> > reserved bits for pgdir entries, as no SNP bit defined on pgdir entries.
> 
> Yes, you're right.

yeah. The SNP bit is only available in the leaf paging entry. e.g. for 4KB 
pages,
the SNP bit is in the PTE, but for 2MB pages, the SNP bit is in PDE, and etc.

Regards,
Yi Liu



RE: [PATCH] intel-iommu: ignore SNP bit in scalable mode

2021-11-24 Thread Liu, Yi L
> From: Peter Xu 
> Sent: Thursday, November 25, 2021 12:31 PM
> 
> On Thu, Nov 25, 2021 at 04:03:34AM +, Liu, Yi L wrote:
> > > From: Peter Xu 
> > > Sent: Wednesday, November 24, 2021 3:57 PM
> > >
> > > On Wed, Nov 24, 2021 at 02:03:09PM +0800, Jason Wang wrote:
> > > > When booting with scalable mode, I hit this error:
> > > >
> > > > qemu-system-x86_64: vtd_iova_to_slpte: detected splte reserve non-
> > > zero iova=0xf002, level=0x1slpte=0x102681803)
> > > > qemu-system-x86_64: vtd_iommu_translate: detected translation
> failure
> > > (dev=01:00:00, iova=0xf002)
> > > > qemu-system-x86_64: New fault is not recorded due to compression
> of
> > > faults
> > > >
> > > > This is because the SNP bit is set since Linux kernel commit
> > > > 6c00612d0cba1 ("iommu/vt-d: Report right snoop capability when
> using
> > > > FL for IOVA") where SNP bit is set if scalable mode is on though this
> > > > seems to be an violation on the spec which said the SNP bit is
> > > > considered to be reserved if SC is not supported.
> > >
> > > When I was reading that commit, I was actually confused by this change:
> > >
> > > ---8<---
> > > diff --git a/drivers/iommu/intel/iommu.c
> b/drivers/iommu/intel/iommu.c
> > > index 956a02eb40b4..0ee5f1bd8af2 100644
> > > --- a/drivers/iommu/intel/iommu.c
> > > +++ b/drivers/iommu/intel/iommu.c
> > > @@ -658,7 +658,14 @@ static int
> domain_update_iommu_snooping(struct
> > > intel_iommu *skip)
> > > rcu_read_lock();
> > > for_each_active_iommu(iommu, drhd) {
> > > if (iommu != skip) {
> > > -   if (!ecap_sc_support(iommu->ecap)) {
> > > +   /*
> > > +* If the hardware is operating in the scalable 
> > > mode,
> > > +* the snooping control is always supported since 
> > > we
> > > +* always set PASID-table-entry.PGSNP bit if the 
> > > domain
> > > +* is managed outside (UNMANAGED).
> > > +*/
> > > +   if (!sm_supported(iommu) &&
> > > +   !ecap_sc_support(iommu->ecap)) {
> > > ret = 0;
> > > break;
> > > }
> > > ---8<---
> > >
> > > Does it mean that for some hardwares that has sm_supported()==true,
> it'll
> > > have  SC bit cleared in ecap register?  That sounds odd, and not sure why.
> Maybe
> > > Yi Liu or Yi Sun may know?
> >
> > scalable mode has no dependency on SC, so it's possible.
> 
> I see; thanks, Yi.
> 
> However then OTOH I don't understand above comment
> 
>   "If the hardware is operating in the scalable mode, the snooping control is
>always supported since... "
> 
> Because the current qemu vt-d emulation should fall into the case that Yi
> mentioned - we support initial scalable mode but no SC yet..

chapter 3.9 of 3.2 spec says below.

“If the remapping hardware is setup in scalable-mode (RTADDR_REG.TTM=01b)
and the Page Snoop (PGSNP) field in PASID-table entry is Set, access to the
final page is snooped.”

It means the PGSNP field is available under scalable mode. And spec also
says below in chapter 96. of 3.2 spec.

"Requests snoop processor caches irrespective of, other attributes in the
request or other fields in paging structure entries used to translate the
request."

It means the PGSNP field of PASID table entry is the first class control
of the snoop behaviour. Also it means the scalable mode has the snoop
control by default. ^_^. So the comment in the above commit is correct
since the policy of intel iommu driver is always setting the PGSNP bit.
But spec is not so clear. Will reach out to make it more clearer in the
spec. thanks for catching it. :-)

Regards,
Yi Liu



Re: [PATCH] intel-iommu: ignore SNP bit in scalable mode

2021-11-24 Thread Peter Xu
On Thu, Nov 25, 2021 at 04:03:34AM +, Liu, Yi L wrote:
> > From: Peter Xu 
> > Sent: Wednesday, November 24, 2021 3:57 PM
> > 
> > On Wed, Nov 24, 2021 at 02:03:09PM +0800, Jason Wang wrote:
> > > When booting with scalable mode, I hit this error:
> > >
> > > qemu-system-x86_64: vtd_iova_to_slpte: detected splte reserve non-
> > zero iova=0xf002, level=0x1slpte=0x102681803)
> > > qemu-system-x86_64: vtd_iommu_translate: detected translation failure
> > (dev=01:00:00, iova=0xf002)
> > > qemu-system-x86_64: New fault is not recorded due to compression of
> > faults
> > >
> > > This is because the SNP bit is set since Linux kernel commit
> > > 6c00612d0cba1 ("iommu/vt-d: Report right snoop capability when using
> > > FL for IOVA") where SNP bit is set if scalable mode is on though this
> > > seems to be an violation on the spec which said the SNP bit is
> > > considered to be reserved if SC is not supported.
> > 
> > When I was reading that commit, I was actually confused by this change:
> > 
> > ---8<---
> > diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
> > index 956a02eb40b4..0ee5f1bd8af2 100644
> > --- a/drivers/iommu/intel/iommu.c
> > +++ b/drivers/iommu/intel/iommu.c
> > @@ -658,7 +658,14 @@ static int domain_update_iommu_snooping(struct
> > intel_iommu *skip)
> > rcu_read_lock();
> > for_each_active_iommu(iommu, drhd) {
> > if (iommu != skip) {
> > -   if (!ecap_sc_support(iommu->ecap)) {
> > +   /*
> > +* If the hardware is operating in the scalable 
> > mode,
> > +* the snooping control is always supported since we
> > +* always set PASID-table-entry.PGSNP bit if the 
> > domain
> > +* is managed outside (UNMANAGED).
> > +*/
> > +   if (!sm_supported(iommu) &&
> > +   !ecap_sc_support(iommu->ecap)) {
> > ret = 0;
> > break;
> > }
> > ---8<---
> > 
> > Does it mean that for some hardwares that has sm_supported()==true, it'll
> > have  SC bit cleared in ecap register?  That sounds odd, and not sure why.  
> > Maybe
> > Yi Liu or Yi Sun may know?
> 
> scalable mode has no dependency on SC, so it's possible.

I see; thanks, Yi.

However then OTOH I don't understand above comment 

  "If the hardware is operating in the scalable mode, the snooping control is
   always supported since... "

Because the current qemu vt-d emulation should fall into the case that Yi
mentioned - we support initial scalable mode but no SC yet..

Cc Baolu too.

-- 
Peter Xu




RE: [PATCH] intel-iommu: ignore SNP bit in scalable mode

2021-11-24 Thread Liu, Yi L
> From: Peter Xu 
> Sent: Wednesday, November 24, 2021 3:57 PM
> 
> On Wed, Nov 24, 2021 at 02:03:09PM +0800, Jason Wang wrote:
> > When booting with scalable mode, I hit this error:
> >
> > qemu-system-x86_64: vtd_iova_to_slpte: detected splte reserve non-
> zero iova=0xf002, level=0x1slpte=0x102681803)
> > qemu-system-x86_64: vtd_iommu_translate: detected translation failure
> (dev=01:00:00, iova=0xf002)
> > qemu-system-x86_64: New fault is not recorded due to compression of
> faults
> >
> > This is because the SNP bit is set since Linux kernel commit
> > 6c00612d0cba1 ("iommu/vt-d: Report right snoop capability when using
> > FL for IOVA") where SNP bit is set if scalable mode is on though this
> > seems to be an violation on the spec which said the SNP bit is
> > considered to be reserved if SC is not supported.
> 
> When I was reading that commit, I was actually confused by this change:
> 
> ---8<---
> diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
> index 956a02eb40b4..0ee5f1bd8af2 100644
> --- a/drivers/iommu/intel/iommu.c
> +++ b/drivers/iommu/intel/iommu.c
> @@ -658,7 +658,14 @@ static int domain_update_iommu_snooping(struct
> intel_iommu *skip)
> rcu_read_lock();
> for_each_active_iommu(iommu, drhd) {
> if (iommu != skip) {
> -   if (!ecap_sc_support(iommu->ecap)) {
> +   /*
> +* If the hardware is operating in the scalable mode,
> +* the snooping control is always supported since we
> +* always set PASID-table-entry.PGSNP bit if the 
> domain
> +* is managed outside (UNMANAGED).
> +*/
> +   if (!sm_supported(iommu) &&
> +   !ecap_sc_support(iommu->ecap)) {
> ret = 0;
> break;
> }
> ---8<---
> 
> Does it mean that for some hardwares that has sm_supported()==true, it'll
> have  SC bit cleared in ecap register?  That sounds odd, and not sure why.  
> Maybe
> Yi Liu or Yi Sun may know?

scalable mode has no dependency on SC, so it's possible.

> >
> > To unbreak the guest, ignore the SNP bit for scalable mode first. In
> > the future we may consider to add SC support.
> 
> Oh yes, I remembered the last time we discussed this.  Could you remind
> me what's missing for us to support SC?
> 
> IIUC, for common device emulations we can just declare SC==1, right?  As all
> the DMAs (including kernel accels like vhost) will be from host processors so
> there're no coherent issues with guest vcpu threads.
> 
> If that's correct, the only challenge is device assignment in any form (I am
> not familiar with vdpa; so perhaps that includes vfio, vpda and any other
> kind of assigning host devices to guest?), then we'll try to detect 
> IOMMU_CACHE
> capability from the host iommu groups that covers the assigned devices,
> and we only set SC==1 if we have cache coherency on all the devices?

above looks good to me. SC bit means SNP field available in leaf paging
structure. So we need to check the host side's SC capability for the assigned
devices, then decide whether set SC or not. Then guest iommu driver can
set the SNP bit per its policy.

btw. there is a discussion on the IOMMU_CACHE, it's considered to be
an incorrect usage to let it linked with no_snoop. So there may be some
cleanup later. anyhow, just let you two be aware of it.

https://lore.kernel.org/kvm/20210922234954.gb964...@nvidia.com/

Regards,
Yi Liu

> 
> >
> > Signed-off-by: Jason Wang 
> > ---
> >  hw/i386/intel_iommu.c  | 18 --
> >  hw/i386/intel_iommu_internal.h |  2 ++
> >  2 files changed, 14 insertions(+), 6 deletions(-)
> >
> > diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
> > index 294499ee20..3bcac56c3e 100644
> > --- a/hw/i386/intel_iommu.c
> > +++ b/hw/i386/intel_iommu.c
> > @@ -969,7 +969,8 @@ static dma_addr_t
> vtd_get_iova_pgtbl_base(IntelIOMMUState *s,
> >  static uint64_t vtd_spte_rsvd[5];
> >  static uint64_t vtd_spte_rsvd_large[5];
> >
> > -static bool vtd_slpte_nonzero_rsvd(uint64_t slpte, uint32_t level)
> > +static bool vtd_slpte_nonzero_rsvd(IntelIOMMUState *s,
> > +   uint64_t slpte, uint32_t level)
> >  {
> >  uint64_t rsvd_mask = vtd_spte_rsvd[level];
> >
> > @@ -979,6 +980,10 @@ static bool vtd_slpte_nonzero_rsvd(uint64_t slpte,
> uint32_t level)
> >  rsvd_mask = vtd_spte_rsvd_large[level];
> >  }
> >
> > +if (s->scalable_mode) {
> > +rsvd_mask &= ~VTD_SPTE_SNP;
> > +}
> 
> IMHO what we want to do is only to skip the leaves of pgtables on SNP, so
> maybe
> we still want to keep checking the bit 11 reserved for e.g. common pgtable
> dir
> entries?
> 
> To do so, how about directly modifying the vtd_spte_rsvd* fields in
> vtd_init()?
> I think we only need to modify 

Re: [PATCH v3 1/3] target/ppc: Fixed call to deferred exception

2021-11-24 Thread David Gibson
On Thu, Nov 25, 2021 at 01:49:46AM +0100, BALATON Zoltan wrote:
> On Wed, 24 Nov 2021, Lucas Mateus Castro (alqotel) wrote:
> > mtfsf, mtfsfi and mtfsb1 instructions call helper_float_check_status
> > after updating the value of FPSCR, but helper_float_check_status
> > checks fp_status and fp_status isn't updated based on FPSCR and
> > since the value of fp_status is reset earlier in the instruction,
> > it's always 0.
> > 
> > Because of this helper_float_check_status would change the FI bit to 0
> > as this bit checks if the last operation was inexact and
> > float_flag_inexact is always 0.
> > 
> > These instructions also don't throw exceptions correctly since
> > helper_float_check_status throw exceptions based on fp_status.
> > 
> > This commit created a new helper, helper_fpscr_check_status that checks
> > FPSCR value instead of fp_status and checks for a larger variety of
> > exceptions than do_float_check_status.
> > 
> > Since fp_status isn't used, gen_reset_fpstatus() was removed.
> > 
> > The hardware used to compare QEMU's behavior to was a Power9.
> > 
> > Signed-off-by: Lucas Mateus Castro (alqotel) 
> > ---
> > target/ppc/fpu_helper.c| 48 ++
> > target/ppc/helper.h|  1 +
> > target/ppc/translate/fp-impl.c.inc |  9 ++
> > 3 files changed, 52 insertions(+), 6 deletions(-)
> > 
> > diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
> > index c4896cecc8..bb72715827 100644
> > --- a/target/ppc/fpu_helper.c
> > +++ b/target/ppc/fpu_helper.c
> > @@ -414,6 +414,54 @@ void helper_store_fpscr(CPUPPCState *env, uint64_t 
> > val, uint32_t nibbles)
> > ppc_store_fpscr(env, val);
> > }
> > 
> > +void helper_fpscr_check_status(CPUPPCState *env)
> > +{
> > +CPUState *cs = env_cpu(env);
> > +target_ulong fpscr = env->fpscr;
> > +int error = 0;
> > +
> > +if ((fpscr & FP_OX) && (fpscr & FP_OE)) {
> > +error = POWERPC_EXCP_FP_OX;
> > +} else if ((fpscr & FP_UX) && (fpscr & FP_UE)) {
> > +error = POWERPC_EXCP_FP_UX;
> > +} else if ((fpscr & FP_XX) && (fpscr & FP_XE)) {
> > +error = POWERPC_EXCP_FP_XX;
> > +} else if ((fpscr & FP_ZX) && (fpscr & FP_ZE)) {
> 
> I wonder if these tests could be simplified by combining the masks if you
> want to test for both bits set so e.g. fpscr & (FP_ZX | FP_ZE) should be the
> same, shouldn't it?

No, it's not.  In fact your version is equivalent as a boolean to
((fpscr & FP_ZX) || (fpscr & FP_ZE))

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


signature.asc
Description: PGP signature


Re: [PATCH] target/ppc: fix Hash64 MMU update of PTE bit R

2021-11-24 Thread David Gibson
On Wed, Nov 24, 2021 at 09:00:46AM -0300, Leandro Lupori wrote:
> When updating the R bit of a PTE, the Hash64 MMU was using a wrong byte
> offset, causing the first byte of the adjacent PTE to be corrupted.
> This caused a panic when booting FreeBSD, using the Hash MMU.
> 
> Signed-off-by: Leandro Lupori 

Ouch, that's an embarrassing error :/.

Reviewed-by: David Gibson 

> ---
>  target/ppc/mmu-hash64.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
> index 19832c4b46..f165ac691a 100644
> --- a/target/ppc/mmu-hash64.c
> +++ b/target/ppc/mmu-hash64.c
> @@ -786,7 +786,7 @@ static void ppc_hash64_set_dsi(CPUState *cs, int mmu_idx, 
> uint64_t dar, uint64_t
>  
>  static void ppc_hash64_set_r(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte1)
>  {
> -hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 16;
> +hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 14;
>  
>  if (cpu->vhyp) {
>  PPCVirtualHypervisorClass *vhc =

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


signature.asc
Description: PGP signature


Re: [PATCH v11 19/26] linux-user: Add LoongArch signal support

2021-11-24 Thread gaosong

Hi  Richard,
On 2021/11/20 下午6:33, Richard Henderson wrote:

+/* this struct defines a stack used during syscall handling */
+typedef struct target_sigaltstack {
+    abi_long ss_sp;
+    abi_int ss_flags;
+    abi_ulong ss_size;
+} target_stack_t;
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK 1
+#define TARGET_SS_DISABLE 2
+
+#define TARGET_MINSIGSTKSZ    2048
+#define TARGET_SIGSTKSZ   8192


We should move these to generic/signal.h. 

Yes.
I also see that TARGET_SIGSTKSZ is not used.  I think  we should delete it.

Thanks
Song Gao


Re: [PATCH] intel-iommu: ignore SNP bit in scalable mode

2021-11-24 Thread Jason Wang
On Wed, Nov 24, 2021 at 6:10 PM Peter Xu  wrote:
>
> On Wed, Nov 24, 2021 at 05:35:18PM +0800, Jason Wang wrote:
> > On Wed, Nov 24, 2021 at 5:23 PM Peter Xu  wrote:
> > >
> > > On Wed, Nov 24, 2021 at 05:01:42PM +0800, Jason Wang wrote:
> > > > > > > > -static bool vtd_slpte_nonzero_rsvd(uint64_t slpte, uint32_t 
> > > > > > > > level)
> > > > > > > > +static bool vtd_slpte_nonzero_rsvd(IntelIOMMUState *s,
> > > > > > > > +   uint64_t slpte, uint32_t 
> > > > > > > > level)
> > > > > > > >  {
> > > > > > > >  uint64_t rsvd_mask = vtd_spte_rsvd[level];
> > > > > > > >
> > > > > > > > @@ -979,6 +980,10 @@ static bool 
> > > > > > > > vtd_slpte_nonzero_rsvd(uint64_t slpte, uint32_t level)
> > > > > > > >  rsvd_mask = vtd_spte_rsvd_large[level];
> > > > > > > >  }
> > > > > > > >
> > > > > > > > +if (s->scalable_mode) {
> > > > > > > > +rsvd_mask &= ~VTD_SPTE_SNP;
> > > > > > > > +}
> > > > > > >
> > > > > > > IMHO what we want to do is only to skip the leaves of pgtables on 
> > > > > > > SNP, so maybe
> > > > > > > we still want to keep checking the bit 11 reserved for e.g. 
> > > > > > > common pgtable dir
> > > > > > > entries?
> > > >
> > > > Maybe, but it's probably a question that can only be answered by
> > > > Intel. I can change it for the next version if you stick.
> > >
> > > I'm reading vtd spec v3.1 (June 2019) here, and chap 9.8 told me they're
> > > reserved bits for pgdir entries, as no SNP bit defined on pgdir entries.
> >
> > Yes, you're right.
> >
> > >
> > > >
> > > > > > >
> > > > > > > To do so, how about directly modifying the vtd_spte_rsvd* fields 
> > > > > > > in vtd_init()?
> > > > > > > I think we only need to modify 4k/2m/1g entries to mask bit 11, 
> > > > > > > they're:
> > > > > > >
> > > > > > >   - vtd_spte_rsvd[1] (4K)
> > > > > > >   - vtd_spte_rsvd_large[2] (2M)
> > > > > > >   - vtd_spte_rsvd_large[3] (1G)
> > > > > > >
> > > > > > > What do you think?  Then we avoid passing IntelIOMMUState* all 
> > > > > > > over too.
> > > >
> > > > I started a version like that:), it should work, I will change that if
> > > > it was agreed by everyone.
> > > >
> > > > The reason that I changed to pass IntelIOMMUState is that it results
> > > > in a smaller changeset. The reason is that I tend to introduce new
> > > > rsvd bits for SM mode since after checking vtd 3.3 it looks have
> > > > different reserved bit requirement than before (at least 1.2)
> > >
> > > Oh I thought changing vtd_spte_rsvd* should have smaller changeset 
> > > instead,
> > > hmm? :)
> > >
> > > IMHO it'll be:
> > >
> > >   if (s->scalable_mode) {
> > > vtd_spte_rsvd[1] &= ~BIT(11);
> > > vtd_spte_rsvd_large[2] &= ~BIT(11);
> > > vtd_spte_rsvd_large[3] &= ~BIT(11);
> > >   }
> > >
> > > Would that work?  Thanks,
> >
> > Works for sure, if we just want to fix the SNP bit.
> >
> > (I actually have a version like this as well). I can go this way
>
> Sounds good at least to me.  Thanks!
>
> >
> > The reason why I had another big changset is to align the reserved
> > bits to vtd 3.3. E.g it equires e.g bit 62 to be reserved 63 to be
> > ignored which seems not as strict as VTD_SL_IGN_COM. But it can be
> > addressed in the future.
>
> Ah I see.  We can do that later, or if the patch is ready anway IMHO we can
> have them fixed altogether too.
>
> It's weird that VT-d spec seems to be very prone to changes.. that's rare as a
> spec, and it even happened multiple times.

A side-effect is to bring troubles for the migration compatibility :(

>
> Another trivial thing: for that SNP bit code change, shall we also reference
> the Linux commit 6c00612d0cba ("iommu/vt-d: Report right snoop capability when
> using FL for IOVA", 2021-04-07) directly in the code as comment?  Just want to
> make sure we'll never forget why we added it as no one will be able to find a
> clue in the spec, meanwhile that explicit hint let us remember when we added 
> SC
> support we can drop it.

Adding BaoLu.

As discussed, according to my test with vIOMMU, there are side effect
of that commit which uses SNP even for the second level page table for
domains that is not IOMMU_DOMAIN_UNMANAGED. If I was wrong, we can
refer to that in the code.

Thanks

>
> --
> Peter Xu
>




[PATCH 2/2] virtio-balloon: correct used length

2021-11-24 Thread Jason Wang
Spec said:

"and len the total of bytes written into the buffer."

For inflateq, deflateq and statsq, we don't process in_sg so the used
length should be zero. For free_page_vq, since the pages could be
changed in the destination, we should make all pages used for safety.

Signed-off-by: Jason Wang 
---
 hw/virtio/virtio-balloon.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 17de2558cb..fb4426ac0c 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -231,7 +231,7 @@ static void balloon_stats_poll_cb(void *opaque)
 return;
 }
 
-virtqueue_push(s->svq, s->stats_vq_elem, s->stats_vq_offset);
+virtqueue_push(s->svq, s->stats_vq_elem, 0);
 virtio_notify(vdev, s->svq);
 g_free(s->stats_vq_elem);
 s->stats_vq_elem = NULL;
@@ -438,7 +438,7 @@ static void virtio_balloon_handle_output(VirtIODevice 
*vdev, VirtQueue *vq)
 memory_region_unref(section.mr);
 }
 
-virtqueue_push(vq, elem, offset);
+virtqueue_push(vq, elem, 0);
 virtio_notify(vdev, vq);
 g_free(elem);
 virtio_balloon_pbp_free();
@@ -510,6 +510,7 @@ static bool get_free_page_hints(VirtIOBalloon *dev)
 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
 VirtQueue *vq = dev->free_page_vq;
 bool ret = true;
+size_t used = 0;
 int i;
 
 while (dev->block_iothread) {
@@ -548,11 +549,12 @@ static bool get_free_page_hints(VirtIOBalloon *dev)
 for (i = 0; i < elem->in_num; i++) {
 qemu_guest_free_page_hint(elem->in_sg[i].iov_base,
   elem->in_sg[i].iov_len);
+used += elem->in_sg[i].iov_len;
 }
 }
 
 out:
-virtqueue_push(vq, elem, 1);
+virtqueue_push(vq, elem, used);
 g_free(elem);
 return ret;
 }
-- 
2.25.1




[PATCH 1/2] virito-balloon: process all in sgs for free_page_vq

2021-11-24 Thread Jason Wang
We only process the first in sg which may lead to the bitmap of the
pages belongs to following sgs were not cleared. This may result more
pages to be migrated. Fixing this by process all in sgs for
free_page_vq.

Signed-off-by: Jason Wang 
---
 hw/virtio/virtio-balloon.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index c6962fcbfe..17de2558cb 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -510,6 +510,7 @@ static bool get_free_page_hints(VirtIOBalloon *dev)
 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
 VirtQueue *vq = dev->free_page_vq;
 bool ret = true;
+int i;
 
 while (dev->block_iothread) {
 qemu_cond_wait(>free_page_cond, >free_page_lock);
@@ -544,8 +545,10 @@ static bool get_free_page_hints(VirtIOBalloon *dev)
 }
 
 if (elem->in_num && dev->free_page_hint_status == FREE_PAGE_HINT_S_START) {
-qemu_guest_free_page_hint(elem->in_sg[0].iov_base,
-  elem->in_sg[0].iov_len);
+for (i = 0; i < elem->in_num; i++) {
+qemu_guest_free_page_hint(elem->in_sg[i].iov_base,
+  elem->in_sg[i].iov_len);
+}
 }
 
 out:
-- 
2.25.1




Re: [PATCH for-7.0 v7 02/10] target/ppc: PMU basic cycle count for pseries TCG

2021-11-24 Thread Daniel Henrique Barboza




On 11/22/21 02:07, David Gibson wrote:

On Fri, Nov 19, 2021 at 03:22:08PM -0300, Daniel Henrique Barboza wrote:

This patch adds the barebones of the PMU logic by enabling cycle
counting. The overall logic goes as follows:

- a helper is added to control the PMU state on each MMCR0 write. This
allows for the PMU to start/stop as the frozen counter bit (MMCR0_FC)
is cleared or set;

- MMCR0 reg initial value is set to 0x8000 (MMCR0_FC set) to avoid
having to spin the PMU right at system init;

- to retrieve the events that are being profiled, getPMUEventType() will
check the current MMCR1 value and return the appropriate PMUEventType.
For PMCs 1-4, event 0x2 is the implementation dependent value of
PMU_EVENT_INSTRUCTIONS and event 0x1E is the implementation dependent
value of PMU_EVENT_CYCLES. These events are supported by IBM Power chips
since Power8, at least, and the Linux Perf driver makes use of these
events until kernel v5.15. For PMC1, event 0xF0 is the architected
PowerISA event for cycles. Event 0xFE is the architected PowerISA event
for instructions;

- the intended usage is to freeze the counters by setting MMCR0_FC, do
any additional setting of events to be counted via MMCR1 and enable
the PMU by zeroing MMCR0_FC. Software must freeze counters to read the
results - on the fly reading of the PMCs will return the starting value
of each one. This act of unfreezing the PMU, counting cycles and then
freezing the PMU again is being called a cycle count session.

Given that the base CPU frequency is fixed at 1Ghz for both powernv and
pseries clock, cycle calculation assumes that 1 nanosecond equals 1 CPU
cycle. Cycle value is then calculated by subtracting the current time
the PMU was frozen against the time in which the PMU started spining.

The counter specific frozen bits MMCR0_FC14 and MMCR0_FC56 were also
added as a mean to further control which PMCs were supposed to be
counting cycles during the session.

Signed-off-by: Daniel Henrique Barboza 
---
  target/ppc/cpu.h |  20 +
  target/ppc/cpu_init.c|   6 +-
  target/ppc/helper.h  |   1 +
  target/ppc/power8-pmu-regs.c.inc |  23 -
  target/ppc/power8-pmu.c  | 149 +++
  target/ppc/spr_tcg.h |   1 +
  6 files changed, 196 insertions(+), 4 deletions(-)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 04ef9300af..233fd8a9ca 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -360,6 +360,9 @@ typedef enum {
  #define MMCR0_FCECE  PPC_BIT(38) /* FC on Enabled Cond or Event */
  #define MMCR0_PMCC0  PPC_BIT(44) /* PMC Control bit 0 */
  #define MMCR0_PMCC1  PPC_BIT(45) /* PMC Control bit 1 */
+#define MMCR0_PMCC   PPC_BITMASK(44, 45) /* PMC Control */
+#define MMCR0_FC14   PPC_BIT(58) /* PMC Freeze Counters 1-4 bit */
+#define MMCR0_FC56   PPC_BIT(59) /* PMC Freeze Counters 5-6 bit */
  /* MMCR0 userspace r/w mask */
  #define MMCR0_UREG_MASK (MMCR0_FC | MMCR0_PMAO | MMCR0_PMAE)
  /* MMCR2 userspace r/w mask */
@@ -372,6 +375,17 @@ typedef enum {
  #define MMCR2_UREG_MASK (MMCR2_FC1P0 | MMCR2_FC2P0 | MMCR2_FC3P0 | \
   MMCR2_FC4P0 | MMCR2_FC5P0 | MMCR2_FC6P0)
  
+#define MMCR1_EVT_SIZE 8

+/* extract64() does a right shift before extracting */
+#define MMCR1_PMC1SEL_START 32
+#define MMCR1_PMC1EVT_EXTR (64 - MMCR1_PMC1SEL_START - MMCR1_EVT_SIZE)
+#define MMCR1_PMC2SEL_START 40
+#define MMCR1_PMC2EVT_EXTR (64 - MMCR1_PMC2SEL_START - MMCR1_EVT_SIZE)
+#define MMCR1_PMC3SEL_START 48
+#define MMCR1_PMC3EVT_EXTR (64 - MMCR1_PMC3SEL_START - MMCR1_EVT_SIZE)
+#define MMCR1_PMC4SEL_START 56
+#define MMCR1_PMC4EVT_EXTR (64 - MMCR1_PMC4SEL_START - MMCR1_EVT_SIZE)
+
  /* LPCR bits */
  #define LPCR_VPM0 PPC_BIT(0)
  #define LPCR_VPM1 PPC_BIT(1)
@@ -1206,6 +1220,12 @@ struct CPUPPCState {
   * when counting cycles.
   */
  QEMUTimer *pmu_cyc_overflow_timers[PMU_TIMERS_NUM];
+
+/*
+ * PMU base time value used by the PMU to calculate
+ * running cycles.
+ */
+uint64_t pmu_base_time;
  };
  
  #define SET_FIT_PERIOD(a_, b_, c_, d_)  \

diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 9610e65c76..e0b6fe4057 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -6821,8 +6821,8 @@ static void register_book3s_pmu_sup_sprs(CPUPPCState *env)
  {
  spr_register_kvm(env, SPR_POWER_MMCR0, "MMCR0",
   SPR_NOACCESS, SPR_NOACCESS,
- _read_generic, _write_generic,
- KVM_REG_PPC_MMCR0, 0x);
+ _read_generic, _write_MMCR0,
+ KVM_REG_PPC_MMCR0, 0x8000);
  spr_register_kvm(env, SPR_POWER_MMCR1, "MMCR1",
   SPR_NOACCESS, SPR_NOACCESS,
   _read_generic, _write_generic,
@@ -6870,7 +6870,7 @@ static void register_book3s_pmu_user_sprs(CPUPPCState 
*env)
  spr_register(env, 

Re: [PATCH v3 3/3] target/ppc: ppc_store_fpscr doesn't update bits 0 to 28 and 52

2021-11-24 Thread BALATON Zoltan

On Wed, 24 Nov 2021, Lucas Mateus Castro (alqotel) wrote:

This commit fixes the difference reported in the bug in the reserved
bit 52, it does this by adding this bit to the mask of bits to not be
directly altered in the ppc_store_fpscr function (the hardware used to
compare to QEMU was a Power9).

The bits 0 to 27 were also added to the mask, as they are marked as
reserved in the PowerISA and bit 28 is a reserved extension of the DRN
field (bits 29:31) but can't be set using mtfsfi, while the other DRN
bits may be set using mtfsfi instruction, so bit 28 was also added to
the mask.

Although this is a difference reported in the bug, since it's a reserved
bit it may be a "don't care" case, as put in the bug report. Looking at
the ISA it doesn't explicitly mentions this bit can't be set, like it


doesn't explicitly mention (no s needed)

Regards,
BALATON Zoltan


does for FEX and VX, so I'm unsure if this is necessary.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/266
Signed-off-by: Lucas Mateus Castro (alqotel) 
---
target/ppc/cpu.c | 2 +-
target/ppc/cpu.h | 4 
2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/target/ppc/cpu.c b/target/ppc/cpu.c
index f933d9f2bd..d7b42bae52 100644
--- a/target/ppc/cpu.c
+++ b/target/ppc/cpu.c
@@ -112,7 +112,7 @@ static inline void fpscr_set_rounding_mode(CPUPPCState *env)

void ppc_store_fpscr(CPUPPCState *env, target_ulong val)
{
-val &= ~(FP_VX | FP_FEX);
+val &= FPSCR_MTFS_MASK;
if (val & FPSCR_IX) {
val |= FP_VX;
}
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index e946da5f3a..441d3dce19 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -759,6 +759,10 @@ enum {
  FP_VXZDZ  | FP_VXIMZ  | FP_VXVC   | FP_VXSOFT | \
  FP_VXSQRT | FP_VXCVI)

+/* FPSCR bits that can be set by mtfsf, mtfsfi and mtfsb1 */
+#define FPSCR_MTFS_MASK (~(MAKE_64BIT_MASK(36, 28) | PPC_BIT(28) |\
+   FP_FEX | FP_VX | PPC_BIT(52)))
+
/*/
/* Vector status and control register */
#define VSCR_NJ 16 /* Vector non-java */





Re: [PATCH v3 1/3] target/ppc: Fixed call to deferred exception

2021-11-24 Thread BALATON Zoltan

On Wed, 24 Nov 2021, Lucas Mateus Castro (alqotel) wrote:

mtfsf, mtfsfi and mtfsb1 instructions call helper_float_check_status
after updating the value of FPSCR, but helper_float_check_status
checks fp_status and fp_status isn't updated based on FPSCR and
since the value of fp_status is reset earlier in the instruction,
it's always 0.

Because of this helper_float_check_status would change the FI bit to 0
as this bit checks if the last operation was inexact and
float_flag_inexact is always 0.

These instructions also don't throw exceptions correctly since
helper_float_check_status throw exceptions based on fp_status.

This commit created a new helper, helper_fpscr_check_status that checks
FPSCR value instead of fp_status and checks for a larger variety of
exceptions than do_float_check_status.

Since fp_status isn't used, gen_reset_fpstatus() was removed.

The hardware used to compare QEMU's behavior to was a Power9.

Signed-off-by: Lucas Mateus Castro (alqotel) 
---
target/ppc/fpu_helper.c| 48 ++
target/ppc/helper.h|  1 +
target/ppc/translate/fp-impl.c.inc |  9 ++
3 files changed, 52 insertions(+), 6 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index c4896cecc8..bb72715827 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -414,6 +414,54 @@ void helper_store_fpscr(CPUPPCState *env, uint64_t val, 
uint32_t nibbles)
ppc_store_fpscr(env, val);
}

+void helper_fpscr_check_status(CPUPPCState *env)
+{
+CPUState *cs = env_cpu(env);
+target_ulong fpscr = env->fpscr;
+int error = 0;
+
+if ((fpscr & FP_OX) && (fpscr & FP_OE)) {
+error = POWERPC_EXCP_FP_OX;
+} else if ((fpscr & FP_UX) && (fpscr & FP_UE)) {
+error = POWERPC_EXCP_FP_UX;
+} else if ((fpscr & FP_XX) && (fpscr & FP_XE)) {
+error = POWERPC_EXCP_FP_XX;
+} else if ((fpscr & FP_ZX) && (fpscr & FP_ZE)) {


I wonder if these tests could be simplified by combining the masks if you 
want to test for both bits set so e.g. fpscr & (FP_ZX | FP_ZE) should be 
the same, shouldn't it?


Regards,
BALATON Zoltan


+error = POWERPC_EXCP_FP_ZX;
+} else if (fpscr & FP_VE) {
+if (fpscr & FP_VXSOFT) {
+error = POWERPC_EXCP_FP_VXSOFT;
+} else if (fpscr & FP_VXSNAN) {
+error = POWERPC_EXCP_FP_VXSNAN;
+} else if (fpscr & FP_VXISI) {
+error = POWERPC_EXCP_FP_VXISI;
+} else if (fpscr & FP_VXIDI) {
+error = POWERPC_EXCP_FP_VXIDI;
+} else if (fpscr & FP_VXZDZ) {
+error = POWERPC_EXCP_FP_VXZDZ;
+} else if (fpscr & FP_VXIMZ) {
+error = POWERPC_EXCP_FP_VXIMZ;
+} else if (fpscr & FP_VXVC) {
+error = POWERPC_EXCP_FP_VXVC;
+} else if (fpscr & FP_VXSQRT) {
+error = POWERPC_EXCP_FP_VXSQRT;
+} else if (fpscr & FP_VXCVI) {
+error = POWERPC_EXCP_FP_VXCVI;
+} else {
+return;
+}
+} else {
+return;
+}
+cs->exception_index = POWERPC_EXCP_PROGRAM;
+env->error_code = error | POWERPC_EXCP_FP;
+/* Deferred floating-point exception after target FPSCR update */
+if (fp_exceptions_enabled(env)) {
+raise_exception_err_ra(env, cs->exception_index,
+   env->error_code, GETPC());
+}
+}
+
static void do_float_check_status(CPUPPCState *env, uintptr_t raddr)
{
CPUState *cs = env_cpu(env);
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 627811cefc..632a81c676 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -63,6 +63,7 @@ DEF_HELPER_FLAGS_1(cntlzw32, TCG_CALL_NO_RWG_SE, i32, i32)
DEF_HELPER_FLAGS_2(brinc, TCG_CALL_NO_RWG_SE, tl, tl, tl)

DEF_HELPER_1(float_check_status, void, env)
+DEF_HELPER_1(fpscr_check_status, void, env)
DEF_HELPER_1(reset_fpstatus, void, env)
DEF_HELPER_2(compute_fprf_float64, void, env, i64)
DEF_HELPER_3(store_fpscr, void, env, i64, i32)
diff --git a/target/ppc/translate/fp-impl.c.inc 
b/target/ppc/translate/fp-impl.c.inc
index d1dbb1b96b..ca195fd9d2 100644
--- a/target/ppc/translate/fp-impl.c.inc
+++ b/target/ppc/translate/fp-impl.c.inc
@@ -769,7 +769,6 @@ static void gen_mtfsb1(DisasContext *ctx)
return;
}
crb = 31 - crbD(ctx->opcode);
-gen_reset_fpstatus();
/* XXX: we pretend we can only do IEEE floating-point computations */
if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
TCGv_i32 t0;
@@ -782,7 +781,7 @@ static void gen_mtfsb1(DisasContext *ctx)
tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
}
/* We can raise a deferred exception */
-gen_helper_float_check_status(cpu_env);
+gen_helper_fpscr_check_status(cpu_env);
}

/* mtfsf */
@@ -803,7 +802,6 @@ static void gen_mtfsf(DisasContext *ctx)
gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
return;
}
-gen_reset_fpstatus();
if (l) {

Re: [RFC PATCH 0/2] QEMU/openbios: PPC Software TLB support in the G4 family

2021-11-24 Thread BALATON Zoltan

On Wed, 24 Nov 2021, Fabiano Rosas wrote:

Fabiano Rosas  writes:


Hi all,

We have this bug in QEMU which indicates that we haven't been able to
run openbios on a 7450 cpu for quite a long time:

https://gitlab.com/qemu-project/qemu/-/issues/86

OK:
  $ ./qemu-system-ppc -serial mon:stdio -nographic -cpu 7410

 >> =
 >> OpenBIOS 1.1 [Nov 1 2021 20:36]
  ...

NOK:
  $ ./qemu-system-ppc -serial mon:stdio -nographic -cpu 7450 -d int


This CPU appears in PowerMac G4 so maybe better use -machine mac99,via=pmu 
with it as it's strange to put it in a g3beige but that may not matter for 
reproducing the problem.


As for guests, those running on the said PowerMac G4 should have support 
for these CPUs so maybe you can try some Mac OS X versions (or maybe 
MorphOS but that is not the best for debugging as there's no source 
available nor any help from its owners but just to see if it boots it may 
be sufficient, it should work on real PowerMac G4). According to 
 this CPU was used 
in  
and it runs up to Mac OS 10.4.11. (Although OpenBIOS sets the device tree 
according to a PowerMac3,1 so not sure it's entirely correct for the 
PowerMac3,5 that has a 7450 CPU and if it matters for Mac OS X.)


I asked about this before but got no reply back then:
https://lists.nongnu.org/archive/html/qemu-ppc/2020-03/msg00292.html

This was because pegasos2 should have 7447 but it did not work so 
currently I've set it to 7400 which also works. The original board 
firmware had some problem detecting it but I think that only results in 
wrong CPU speed shown which is only a cosmetic problem, otherwise it seems 
to work. Since pegasos2 does not use OpenBIOS but either VOF or the 
board's original firmware it may be an alternative way to test at least 
7447 which the firmware and guests running on that board should work with. 
At least Debian 8.11 powerpc version had support for pegasos2 and should 
boot, I'm not sure newer versions still work. More info on pegasos2 can be 
found at:
http://zero.eik.bme.hu/~balaton/qemu/amiga/#morphos 
and

https://osdn.net/projects/qmiga/wiki/SubprojectPegasos2

I don't remember what problem I had with 7447 but if it does not work with 
pegasos2 then maybe there's some other problem with it too. I think it was 
maybe related to TLBs but I don't know and had no time to try again so I 
could be entirely wrong about this.


Regards,
BALATON Zoltan


  Raise exception at fff08cc4 => 004e (00)
  QEMU: Terminated

The actual issue is straightforward. There is a non-architected
feature that QEMU has enabled by default that openbios doesn't know
about. From the user manual:

"The MPC7540 has a set of implementation-specific registers,
exceptions, and instructions that facilitate very efficient software
searching of the page tables in memory for when software table
searching is enabled (HID0[STEN] = 1). This section describes those
resources and provides three example code sequences that can be used
in a MPC7540 system for an efficient search of the translation tables
in software. These three code sequences can be used as handlers for
the three exceptions requiring access to the PTEs in the page tables
in memory in this case-instruction TLB miss, data TLB miss on load,
and data TLB miss on store exceptions."

The current state:

1) QEMU does not check HID0[STEN] and makes the feature always enabled
by setting these cpus with the POWERPC_MMU_SOFT_74xx MMU model,
instead of the generic POWERPC_MMU_32B.

2) openbios does not recognize the PVRs for those cpus and also does
not have any handlers for the software TLB exceptions (vectors 0x1000,
0x1100, 0x1200).

Some assumptions (correct me if I'm wrong please):

- openbios is the only firmware we use for the following cpus: 7441,
7445, 7450, 7451, 7455, 7457, 7447, 7447a, 7448.
- without openbios, we cannot have a guest running on these cpus.

So to bring 7450 back to life we would need to either:

a) find another firmware/guest OS code that supports the feature;

b) implement the switching of the feature in QEMU and have the guest
code enable it only when supported. That would take some fiddling with
the MMU code to: merge POWERPC_MMU_SOFT_74xx into POWERPC_MMU_32B,
check the HID0[STEN] bit, figure out how to switch from HW TLB miss to
SW TLB miss on demand, block access to the TLBMISS register (and
others) when the feature is off, and so on;

c) leave the feature enabled in QEMU and implement the software TLB
miss handlers in openbios. The UM provides sample code, so this is
easy;

d) remove support for software TLB search for the 7450 family and
switch the cpus to the POWERPC_MMU_32B model. This is by far the
easiest solution, but could cause problems for any (which?) guest OS
code that actually uses the feature. All of the existing code for the
POWERPC_MMU_SOFT_74xx 

Re: [PATCH-for-6.2 2/2] tests/qtest/fdc-test: Add a regression test for CVE-2021-3507

2021-11-24 Thread John Snow
On Tue, Nov 23, 2021 at 11:08 AM Hanna Reitz  wrote:

> On 18.11.21 12:57, Philippe Mathieu-Daudé wrote:
> > Add the reproducer from
> https://gitlab.com/qemu-project/qemu/-/issues/339
> >
> > Without the previous commit, when running 'make check-qtest-i386'
> > with QEMU configured with '--enable-sanitizers' we get:
> >
> >==4028352==ERROR: AddressSanitizer: heap-buffer-overflow on address
> 0x61962a00 at pc 0x5626d03c491a bp 0x7ffdb4199410 sp 0x7ffdb4198bc0
> >READ of size 786432 at 0x61962a00 thread T0
> >#0 0x5626d03c4919 in __asan_memcpy (qemu-system-i386+0x1e65919)
> >#1 0x5626d1c023cc in flatview_write_continue
> softmmu/physmem.c:2787:13
> >#2 0x5626d1bf0c0f in flatview_write softmmu/physmem.c:2822:14
> >#3 0x5626d1bf0798 in address_space_write softmmu/physmem.c:2914:18
> >#4 0x5626d1bf0f37 in address_space_rw softmmu/physmem.c:2924:16
> >#5 0x5626d1bf14c8 in cpu_physical_memory_rw
> softmmu/physmem.c:2933:5
> >#6 0x5626d0bd5649 in cpu_physical_memory_write
> include/exec/cpu-common.h:82:5
> >#7 0x5626d0bd0a07 in i8257_dma_write_memory hw/dma/i8257.c:452:9
> >#8 0x5626d09f825d in fdctrl_transfer_handler
> hw/block/fdc.c:1616:13
> >#9 0x5626d0a048b4 in fdctrl_start_transfer hw/block/fdc.c:1539:13
> >#10 0x5626d09f4c3e in fdctrl_write_data hw/block/fdc.c:2266:13
> >#11 0x5626d09f22f7 in fdctrl_write hw/block/fdc.c:829:9
> >#12 0x5626d1c20bc5 in portio_write softmmu/ioport.c:207:17
> >
> >0x61962a00 is located 0 bytes to the right of 512-byte region
> [0x61962800,0x61962a00)
> >allocated by thread T0 here:
> >#0 0x5626d03c66ec in posix_memalign (qemu-system-i386+0x1e676ec)
> >#1 0x5626d2b988d4 in qemu_try_memalign util/oslib-posix.c:210:11
> >#2 0x5626d2b98b0c in qemu_memalign util/oslib-posix.c:226:27
> >#3 0x5626d09fbaf0 in fdctrl_realize_common hw/block/fdc.c:2341:20
> >#4 0x5626d0a150ed in isabus_fdc_realize hw/block/fdc-isa.c:113:5
> >#5 0x5626d2367935 in device_set_realized hw/core/qdev.c:531:13
> >
> >SUMMARY: AddressSanitizer: heap-buffer-overflow
> (qemu-system-i386+0x1e65919) in __asan_memcpy
> >Shadow bytes around the buggy address:
> >  0x0c32800044f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
> >  0x0c3280004500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> >  0x0c3280004510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> >  0x0c3280004520: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> >  0x0c3280004530: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> >=>0x0c3280004540:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
> >  0x0c3280004550: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
> >  0x0c3280004560: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
> >  0x0c3280004570: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
> >  0x0c3280004580: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
> >  0x0c3280004590: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
> >Shadow byte legend (one shadow byte represents 8 application bytes):
> >  Addressable:   00
> >  Heap left redzone:   fa
> >  Freed heap region:   fd
> >==4028352==ABORTING
> >
> > Reported-by: Alexander Bulekov 
> > Signed-off-by: Philippe Mathieu-Daudé 
> > ---
> >   tests/qtest/fdc-test.c | 20 
> >   1 file changed, 20 insertions(+)
> >
> > diff --git a/tests/qtest/fdc-test.c b/tests/qtest/fdc-test.c
> > index 26b69f7c5cd..f164d972d10 100644
> > --- a/tests/qtest/fdc-test.c
> > +++ b/tests/qtest/fdc-test.c
> > @@ -546,6 +546,25 @@ static void fuzz_registers(void)
> >   }
> >   }
> >
> > +static void test_cve_2021_3507(void)
> > +{
> > +QTestState *s;
> > +
> > +s = qtest_initf("-nographic -m 32M -nodefaults "
> > +"-drive file=%s,format=raw,if=floppy", test_image);
> > +qtest_outl(s, 0x9, 0x0a0206);
> > +qtest_outw(s, 0x3f4, 0x1600);
> > +qtest_outw(s, 0x3f4, 0x);
> > +qtest_outw(s, 0x3f4, 0x);
> > +qtest_outw(s, 0x3f4, 0x);
> > +qtest_outw(s, 0x3f4, 0x0200);
> > +qtest_outw(s, 0x3f4, 0x0200);
> > +qtest_outw(s, 0x3f4, 0x);
> > +qtest_outw(s, 0x3f4, 0x);
> > +qtest_outw(s, 0x3f4, 0x);
>
> No idea what this does (looks like a 256-byte sector read read from
> sector 2 with EOT=0), but hits the problem and reproduces for me.
>
> Unfortunately, I have the exact same problem with test_image as I did in
> the other series.
>
> Hanna
>
> > +qtest_quit(s);
> > +}
> > +
> >   int main(int argc, char **argv)
> >   {
> >   int fd;
> > @@ -576,6 +595,7 @@ int main(int argc, char **argv)
> >   qtest_add_func("/fdc/read_no_dma_18", test_read_no_dma_18);
> >   qtest_add_func("/fdc/read_no_dma_19", test_read_no_dma_19);
> >   qtest_add_func("/fdc/fuzz-registers", fuzz_registers);
> > +

Re: [PATCH v4 0/3] hw/block/fdc: Fix CVE-2021-20196

2021-11-24 Thread John Snow
On Wed, Nov 24, 2021 at 11:15 AM Philippe Mathieu-Daudé 
wrote:

> Since v3:
> - Preliminary extract blk_create_empty_drive()
> - qtest checks qtest_check_clang_sanitizer() enabled
> - qtest uses null-co:// driver instead of file
>
> Philippe Mathieu-Daudé (3):
>   hw/block/fdc: Extract blk_create_empty_drive()
>   hw/block/fdc: Kludge missing floppy drive to fix CVE-2021-20196
>   tests/qtest/fdc-test: Add a regression test for CVE-2021-20196
>
>  hw/block/fdc.c | 23 ---
>  tests/qtest/fdc-test.c | 38 ++
>  2 files changed, 58 insertions(+), 3 deletions(-)
>
> --
> 2.33.1
>
>
I'm testing this now. I'm going to take your word for it. If Hanna is fine
with the block-layer components of the fix, I'll probably take it, but I
will be sending a patch to remove myself as maintainer in the process,
since I don't have the time to do the "proper fix" for these devices, and
haven't for quite some time.

--js


Re: [RFC PATCH 0/2] QEMU/openbios: PPC Software TLB support in the G4 family

2021-11-24 Thread Fabiano Rosas
Fabiano Rosas  writes:

> Hi all,
>
> We have this bug in QEMU which indicates that we haven't been able to
> run openbios on a 7450 cpu for quite a long time:
>
> https://gitlab.com/qemu-project/qemu/-/issues/86
>
> OK:
>   $ ./qemu-system-ppc -serial mon:stdio -nographic -cpu 7410
>
>   >> =
>   >> OpenBIOS 1.1 [Nov 1 2021 20:36]
>   ...
>
> NOK:
>   $ ./qemu-system-ppc -serial mon:stdio -nographic -cpu 7450 -d int
>   Raise exception at fff08cc4 => 004e (00)
>   QEMU: Terminated
>
> The actual issue is straightforward. There is a non-architected
> feature that QEMU has enabled by default that openbios doesn't know
> about. From the user manual:
>
> "The MPC7540 has a set of implementation-specific registers,
> exceptions, and instructions that facilitate very efficient software
> searching of the page tables in memory for when software table
> searching is enabled (HID0[STEN] = 1). This section describes those
> resources and provides three example code sequences that can be used
> in a MPC7540 system for an efficient search of the translation tables
> in software. These three code sequences can be used as handlers for
> the three exceptions requiring access to the PTEs in the page tables
> in memory in this case-instruction TLB miss, data TLB miss on load,
> and data TLB miss on store exceptions."
>
> The current state:
>
> 1) QEMU does not check HID0[STEN] and makes the feature always enabled
> by setting these cpus with the POWERPC_MMU_SOFT_74xx MMU model,
> instead of the generic POWERPC_MMU_32B.
>
> 2) openbios does not recognize the PVRs for those cpus and also does
> not have any handlers for the software TLB exceptions (vectors 0x1000,
> 0x1100, 0x1200).
>
> Some assumptions (correct me if I'm wrong please):
>
> - openbios is the only firmware we use for the following cpus: 7441,
> 7445, 7450, 7451, 7455, 7457, 7447, 7447a, 7448.
> - without openbios, we cannot have a guest running on these cpus.
>
> So to bring 7450 back to life we would need to either:
>
> a) find another firmware/guest OS code that supports the feature;
>
> b) implement the switching of the feature in QEMU and have the guest
> code enable it only when supported. That would take some fiddling with
> the MMU code to: merge POWERPC_MMU_SOFT_74xx into POWERPC_MMU_32B,
> check the HID0[STEN] bit, figure out how to switch from HW TLB miss to
> SW TLB miss on demand, block access to the TLBMISS register (and
> others) when the feature is off, and so on;
>
> c) leave the feature enabled in QEMU and implement the software TLB
> miss handlers in openbios. The UM provides sample code, so this is
> easy;
>
> d) remove support for software TLB search for the 7450 family and
> switch the cpus to the POWERPC_MMU_32B model. This is by far the
> easiest solution, but could cause problems for any (which?) guest OS
> code that actually uses the feature. All of the existing code for the
> POWERPC_MMU_SOFT_74xx MMU model would probably be removed since it
> would be dead code then;
>
> Option (c) seemed to me like a good compromise so this is a patch
> series for openbios doing that and also adding the necessary PVRs so
> we can get a working guest with these cpus without too much effort.
>
> I have also a patch for QEMU adding basic sanity check tests for the
> 7400 and 7450 families. I'll send that separately to the QEMU ml.
>
> Fabiano Rosas (2):
>   ppc: Add support for MPC7450 software TLB miss interrupts
>   ppc: Add PVRs for the MPC7450 family
>
>  arch/ppc/qemu/init.c  |  52 ++
>  arch/ppc/qemu/start.S | 236 +-
>  2 files changed, 285 insertions(+), 3 deletions(-)

(Adding Mark because his email got somehow dropped from the original
message)

So with these patches in OpenBIOS we could get a bit further and call
into the Linux kernel using the same image as the one used for the
7400. However there seems to be no support for the 7450 software TLB in
the kernel. There are only handlers for the 4xx, 8xx and 603 which are
different code altogether. There's no mention of the TLBMISS and
PTEHI/LO registers in the code as well.

Do we know of any guest OS that implements the 7450 software TLB at
vectors 0x1000, 0x1100 and 0x1200? Otherwise replacing the
POWERPC_MMU_SOFT_74xx model with POWERPC_MMU_32B might be the only way
of getting an OS to run in the 7450 family.



Re: [PATCH] target/ppc: fix Hash64 MMU update of PTE bit R

2021-11-24 Thread Leandro Lupori

On 24/11/2021 16:52, Cédric Le Goater wrote:
It can be reproduced by trying to boot this iso: 
https://download.freebsd.org/ftp/snapshots/powerpc/powerpc64/ISO-IMAGES/14.0/FreeBSD-14.0-CURRENT-powerpc-powerpc64-20211028-4827bf76bce-250301-disc1.iso.xz 



It is easier to reproduce it using power8/powernv8.


power8 only has Hash MMU. I understand that FreeBSD also supports power9
processor. with radix ? and XIVE ?



Right, FreeBSD supports POWER9 with Radix, that is now the default MMU 
choice. To select Hash MMU, you need to pass radix_mmu=0 to kernel 
command line.

FreeBSD supports XIVE too, but only for PowerNV.

BTW, when trying to boot with Radix instead of Hash, a different issue 
happens. Boot goes further, but then programs start to get SIGILL or 
SIGSEGV.



Thanks,

C.


Thanks,
Leandro



[PATCH v2] hw/intc/arm_gicv3: Update cached state after LPI state changes

2021-11-24 Thread Peter Maydell
The logic of gicv3_redist_update() is as follows:
 * it must be called in any code path that changes the state of
   (only) redistributor interrupts
 * if it finds a redistributor interrupt that is (now) higher
   priority than the previous highest-priority pending interrupt,
   then this must be the new highest-priority pending interrupt
 * if it does *not* find a better redistributor interrupt, then:
- if the previous state was "no interrupts pending" then
  the new state is still "no interrupts pending"
- if the previous best interrupt was not a redistributor
  interrupt then that remains the best interrupt
- if the previous best interrupt *was* a redistributor interrupt,
  then the new best interrupt must be some non-redistributor
  interrupt, but we don't know which so must do a full scan

In commit 17fb5e36aabd4b2c125 we effectively added the LPI interrupts
as a kind of "redistributor interrupt" for this purpose, by adding
cs->hpplpi to the set of things that gicv3_redist_update() considers
before it gives up and decides to do a full scan of distributor
interrupts. However we didn't quite get this right:
 * the condition check for "was the previous best interrupt a
   redistributor interrupt" must be updated to include LPIs
   in what it considers to be redistributor interrupts
 * every code path which updates the LPI state which
   gicv3_redist_update() checks must also call gicv3_redist_update():
   this is cs->hpplpi and the GICR_CTLR ENABLE_LPIS bit

This commit fixes this by:
 * correcting the test on cs->hppi.irq in gicv3_redist_update()
 * making gicv3_redist_update_lpi() always call gicv3_redist_update()
 * introducing a new gicv3_redist_update_lpi_only() for the one
   callsite (the post-load hook) which must not call
   gicv3_redist_update()
 * making gicv3_redist_lpi_pending() always call gicv3_redist_update(),
   either directly or via gicv3_redist_update_lpi()
 * removing a couple of now-unnecessary calls to gicv3_redist_update()
   from some callers of those two functions
 * calling gicv3_redist_update() when the GICR_CTLR ENABLE_LPIS
   bit is cleared

(This means that the not-file-local gicv3_redist_* LPI related
functions now all take care of the updates of internally cached
GICv3 information, in the same way the older functions
gicv3_redist_set_irq() and gicv3_redist_send_sgi() do.)

The visible effect of this bug was that when the guest acknowledged
an LPI by reading ICC_IAR1_EL1, we marked it as not pending in the
LPI data structure but still left it in cs->hppi so we would offer it
to the guest again.  In particular for setups using an emulated GICv3
and ITS and using devices which use LPIs (ie PCI devices) a Linux
guest would complain "irq 54: nobody cared" and then hang.  (The hang
was intermittent, presumably depending on the timing between
different interrupts arriving and being completed.)

Signed-off-by: Peter Maydell 
---
I think this is now a proper fix for the problem. Testing
definitely welcomed... The commit message makes it sound like a bit
of a "several things in one patch" change, but it isn't really IMHO:
I just erred on the side of being very verbose in the description...
---
 hw/intc/gicv3_internal.h   | 17 +
 hw/intc/arm_gicv3.c|  6 --
 hw/intc/arm_gicv3_redist.c | 14 ++
 3 files changed, 31 insertions(+), 6 deletions(-)

diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
index a0369dace7b..70f34ee4955 100644
--- a/hw/intc/gicv3_internal.h
+++ b/hw/intc/gicv3_internal.h
@@ -463,7 +463,24 @@ void gicv3_dist_set_irq(GICv3State *s, int irq, int level);
 void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level);
 void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level);
 void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level);
+/**
+ * gicv3_redist_update_lpi:
+ * @cs: GICv3CPUState
+ *
+ * Scan the LPI pending table and recalculate the highest priority
+ * pending LPI and also the overall highest priority pending interrupt.
+ */
 void gicv3_redist_update_lpi(GICv3CPUState *cs);
+/**
+ * gicv3_redist_update_lpi_only:
+ * @cs: GICv3CPUState
+ *
+ * Scan the LPI pending table and recalculate cs->hpplpi only,
+ * without calling gicv3_redist_update() to recalculate the overall
+ * highest priority pending interrupt. This should be called after
+ * an incoming migration has loaded new state.
+ */
+void gicv3_redist_update_lpi_only(GICv3CPUState *cs);
 void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns);
 void gicv3_init_cpuif(GICv3State *s);
 
diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
index c6282984b1e..9f5f815db9b 100644
--- a/hw/intc/arm_gicv3.c
+++ b/hw/intc/arm_gicv3.c
@@ -186,7 +186,9 @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs)
  * interrupt has reduced in priority and any other interrupt could
  * now be the new best one).
  */
-if (!seenbetter && cs->hppi.prio != 0xff && 

Re: [PATCH] target/ppc: fix Hash64 MMU update of PTE bit R

2021-11-24 Thread Cédric Le Goater

On 11/24/21 20:42, Daniel Henrique Barboza wrote:



On 11/24/21 16:17, Leandro Lupori wrote:

​​


    On 11/24/21 14:40, Daniel Henrique Barboza wrote:
    >
    >
    > On 11/24/21 09:00, Leandro Lupori wrote:
    >> When updating the R bit of a PTE, the Hash64 MMU was using a wrong byte
    >> offset, causing the first byte of the adjacent PTE to be corrupted.
    >> This caused a panic when booting FreeBSD, using the Hash MMU.

    I wonder how we never hit this issue before. Are you testing PowerNV
    and/or pSeries  ?

    Could you share a FreeBDS image with us ?

​I've hit this issue while testing PowerNV. With pSeries it doesn't happen.

It can be reproduced by trying to boot this iso: 
https://download.freebsd.org/ftp/snapshots/powerpc/powerpc64/ISO-IMAGES/14.0/FreeBSD-14.0-CURRENT-powerpc-powerpc64-20211028-4827bf76bce-250301-disc1.iso.xz

It is easier to reproduce it using power8/powernv8.
​

    > If you add a "Fixes:" tag with the commit that introduced the code you're
    > fixing, we can push it right away as a bug fix in 6.2 (assuming it doesn't
    > break anything else, of course).
    >
    > The commit to be fixed in the case seems to be a2dd4e83e76b ("ppc/hash64:
    > Rework R and C bit  updates")

    Indeed.

​​Right.

    > One more comment below:
    >
    >>
    >> Signed-off-by: Leandro Lupori 
    >> ---
    >>   target/ppc/mmu-hash64.c | 2 +-
    >>   1 file changed, 1 insertion(+), 1 deletion(-)
    >>
    >> diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
    >> index 19832c4b46..f165ac691a 100644
    >> --- a/target/ppc/mmu-hash64.c
    >> +++ b/target/ppc/mmu-hash64.c
    >> @@ -786,7 +786,7 @@ static void ppc_hash64_set_dsi(CPUState *cs, int 
mmu_idx, uint64_t dar, uint64_t
    >>   static void ppc_hash64_set_r(PowerPCCPU *cpu, hwaddr ptex, uint64_t 
pte1)
    >>   {
    >> -    hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 16;
    >> +    hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 14;
    >
    > Instead of adding a '14' you should add a new #define in mmu-hash64.h 
with this
    > value, something like "HPTE64_R_R_SHIFT". This will avoid hardcoding 
literals
    > around the code and forcing us to go to the ISA every time we wonder 
what's
    > an apparently random number represents. There's also a "HPTE64_R_R" 
defined
    > there but I'm not sure if it's usable here, so feel free to create a new
    > macro if needed.
    >
    > In that note, the original commit that added this code also added a lot of
    > hardcoded "15" values for the C bit update in spapr_hpte_set_c() and
    > ppc_hash64_set_c(), and a "14" value like you're changing here in 
spapr_hpte_set_r().
    > If you're feeling generous I believe that another patch replacing these 
hardcoded values
    > with bit shift macros  is warranted as well.

​What about creating HPTE64_R_R_BYTEand HPTE64_R_C_BYTE, with the values 14 and 
15, respectively,
to make it clear that these are byte offsets within a PTE?


 _BYTE_OFFSET may be ?


Looks good to me.


Please update pSeries while you are it. I think HASH_PTE_SIZE_64 / 2
deserves an offset.

Thanks,

C.



Re: [PATCH] target/ppc: fix Hash64 MMU update of PTE bit R

2021-11-24 Thread Daniel Henrique Barboza




On 11/24/21 16:17, Leandro Lupori wrote:

​​


On 11/24/21 14:40, Daniel Henrique Barboza wrote:
>
>
> On 11/24/21 09:00, Leandro Lupori wrote:
>> When updating the R bit of a PTE, the Hash64 MMU was using a wrong byte
>> offset, causing the first byte of the adjacent PTE to be corrupted.
>> This caused a panic when booting FreeBSD, using the Hash MMU.

I wonder how we never hit this issue before. Are you testing PowerNV
and/or pSeries  ?

Could you share a FreeBDS image with us ?

​I've hit this issue while testing PowerNV. With pSeries it doesn't happen.

It can be reproduced by trying to boot this iso: 
https://download.freebsd.org/ftp/snapshots/powerpc/powerpc64/ISO-IMAGES/14.0/FreeBSD-14.0-CURRENT-powerpc-powerpc64-20211028-4827bf76bce-250301-disc1.iso.xz

It is easier to reproduce it using power8/powernv8.
​

> If you add a "Fixes:" tag with the commit that introduced the code you're
> fixing, we can push it right away as a bug fix in 6.2 (assuming it doesn't
> break anything else, of course).
>
> The commit to be fixed in the case seems to be a2dd4e83e76b ("ppc/hash64:
> Rework R and C bit  updates")

Indeed.

​​Right.

> One more comment below:
>
>>
>> Signed-off-by: Leandro Lupori 
>> ---
>>   target/ppc/mmu-hash64.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
>> index 19832c4b46..f165ac691a 100644
>> --- a/target/ppc/mmu-hash64.c
>> +++ b/target/ppc/mmu-hash64.c
>> @@ -786,7 +786,7 @@ static void ppc_hash64_set_dsi(CPUState *cs, int 
mmu_idx, uint64_t dar, uint64_t
>>   static void ppc_hash64_set_r(PowerPCCPU *cpu, hwaddr ptex, uint64_t 
pte1)
>>   {
>> -    hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 16;
>> +    hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 14;
>
> Instead of adding a '14' you should add a new #define in mmu-hash64.h 
with this
> value, something like "HPTE64_R_R_SHIFT". This will avoid hardcoding 
literals
> around the code and forcing us to go to the ISA every time we wonder 
what's
> an apparently random number represents. There's also a "HPTE64_R_R" 
defined
> there but I'm not sure if it's usable here, so feel free to create a new
> macro if needed.
>
> In that note, the original commit that added this code also added a lot of
> hardcoded "15" values for the C bit update in spapr_hpte_set_c() and
> ppc_hash64_set_c(), and a "14" value like you're changing here in 
spapr_hpte_set_r().
> If you're feeling generous I believe that another patch replacing these 
hardcoded values
> with bit shift macros  is warranted as well.

​What about creating HPTE64_R_R_BYTEand HPTE64_R_C_BYTE, with the values 14 and 
15, respectively,
to make it clear that these are byte offsets within a PTE?


Looks good to me.


Daniel




May be for 7.0 though ?

Thanks,

C.





Re: Other pages for docs/devel/ [Was: Re: ... Update URLs of "SubmitAPatch" ...]

2021-11-24 Thread Paolo Bonzini

On 11/19/21 11:15, Kashyap Chamarthy wrote:

Noted; so these two pages:

-https://www.qemu.org/contribute/security-process/
-https://www.qemu.org/contribute/report-a-bug/

What about these two other pages (which are also linked to from the
"contribute"[1] part of the website)?  Do they belong to docs/devel?  If
not, should they be part of 'qemu-web', instead of the wiki?

 -https://wiki.qemu.org/Contribute/FAQ
 -https://wiki.qemu.org/Documentation/GettingStartedDevelopers


Yes, I suppose all of these can be moved to docs/devel.

Paolo



[PATCH 22/23] python: remove the old QMP package

2021-11-24 Thread John Snow
Thank you for your service!

Signed-off-by: John Snow 
---
 python/PACKAGE.rst  |   4 +-
 python/README.rst   |   2 +-
 python/qemu/qmp/README.rst  |   9 -
 python/qemu/qmp/__init__.py | 396 
 python/qemu/qmp/py.typed|   0
 python/setup.cfg|   3 +-
 6 files changed, 4 insertions(+), 410 deletions(-)
 delete mode 100644 python/qemu/qmp/README.rst
 delete mode 100644 python/qemu/qmp/__init__.py
 delete mode 100644 python/qemu/qmp/py.typed

diff --git a/python/PACKAGE.rst b/python/PACKAGE.rst
index b0b86cc4c3..ddfa9ba3f5 100644
--- a/python/PACKAGE.rst
+++ b/python/PACKAGE.rst
@@ -8,11 +8,11 @@ to change at any time.
 Usage
 -
 
-The ``qemu.qmp`` subpackage provides a library for communicating with
+The ``qemu.aqmp`` subpackage provides a library for communicating with
 QMP servers. The ``qemu.machine`` subpackage offers rudimentary
 facilities for launching and managing QEMU processes. Refer to each
 package's documentation
-(``>>> help(qemu.qmp)``, ``>>> help(qemu.machine)``)
+(``>>> help(qemu.aqmp)``, ``>>> help(qemu.machine)``)
 for more information.
 
 Contributing
diff --git a/python/README.rst b/python/README.rst
index fcf74f69ea..eb5213337d 100644
--- a/python/README.rst
+++ b/python/README.rst
@@ -3,7 +3,7 @@ QEMU Python Tooling
 
 This directory houses Python tooling used by the QEMU project to build,
 configure, and test QEMU. It is organized by namespace (``qemu``), and
-then by package (e.g. ``qemu/machine``, ``qemu/qmp``, etc).
+then by package (e.g. ``qemu/machine``, ``qemu/aqmp``, etc).
 
 ``setup.py`` is used by ``pip`` to install this tooling to the current
 environment. ``setup.cfg`` provides the packaging configuration used by
diff --git a/python/qemu/qmp/README.rst b/python/qemu/qmp/README.rst
deleted file mode 100644
index 5bfb82535f..00
--- a/python/qemu/qmp/README.rst
+++ /dev/null
@@ -1,9 +0,0 @@
-qemu.qmp package
-
-
-This package provides a library used for connecting to and communicating
-with QMP servers. It is used extensively by iotests, vm tests,
-avocado tests, and other utilities in the ./scripts directory. It is
-not a fully-fledged SDK and is subject to change at any time.
-
-See the documentation in ``__init__.py`` for more information.
diff --git a/python/qemu/qmp/__init__.py b/python/qemu/qmp/__init__.py
deleted file mode 100644
index 4e08641154..00
--- a/python/qemu/qmp/__init__.py
+++ /dev/null
@@ -1,396 +0,0 @@
-"""
-QEMU Monitor Protocol (QMP) development library & tooling.
-
-This package provides a fairly low-level class for communicating to QMP
-protocol servers, as implemented by QEMU, the QEMU Guest Agent, and the
-QEMU Storage Daemon. This library is not intended for production use.
-
-`QEMUMonitorProtocol` is the primary class of interest, and all errors
-raised derive from `QMPError`.
-"""
-
-# Copyright (C) 2009, 2010 Red Hat Inc.
-#
-# Authors:
-#  Luiz Capitulino 
-#
-# This work is licensed under the terms of the GNU GPL, version 2.  See
-# the COPYING file in the top-level directory.
-
-import errno
-import json
-import logging
-import socket
-import struct
-from types import TracebackType
-from typing import (
-Any,
-Dict,
-List,
-Optional,
-TextIO,
-Tuple,
-Type,
-TypeVar,
-Union,
-cast,
-)
-
-
-#: QMPMessage is an entire QMP message of any kind.
-QMPMessage = Dict[str, Any]
-
-#: QMPReturnValue is the 'return' value of a command.
-QMPReturnValue = object
-
-#: QMPObject is any object in a QMP message.
-QMPObject = Dict[str, object]
-
-# QMPMessage can be outgoing commands or incoming events/returns.
-# QMPReturnValue is usually a dict/json object, but due to QAPI's
-# 'returns-whitelist', it can actually be anything.
-#
-# {'return': {}} is a QMPMessage,
-# {} is the QMPReturnValue.
-
-
-InternetAddrT = Tuple[str, int]
-UnixAddrT = str
-SocketAddrT = Union[InternetAddrT, UnixAddrT]
-
-
-class QMPError(Exception):
-"""
-QMP base exception
-"""
-
-
-class QMPConnectError(QMPError):
-"""
-QMP connection exception
-"""
-
-
-class QMPCapabilitiesError(QMPError):
-"""
-QMP negotiate capabilities exception
-"""
-
-
-class QMPTimeoutError(QMPError):
-"""
-QMP timeout exception
-"""
-
-
-class QMPProtocolError(QMPError):
-"""
-QMP protocol error; unexpected response
-"""
-
-
-class QMPResponseError(QMPError):
-"""
-Represents erroneous QMP monitor reply
-"""
-def __init__(self, reply: QMPMessage):
-try:
-desc = reply['error']['desc']
-except KeyError:
-desc = reply
-super().__init__(desc)
-self.reply = reply
-
-
-class QEMUMonitorProtocol:
-"""
-Provide an API to connect to QEMU via QEMU Monitor Protocol (QMP) and then
-allow to handle commands and events.
-"""
-
-#: Logger object for debugging messages
-logger = logging.getLogger('QMP')
-
-def __init__(self, 

Re: [PATCH v3 03/23] multifd: Rename used field to num

2021-11-24 Thread Dr. David Alan Gilbert
* Juan Quintela (quint...@redhat.com) wrote:
> We will need to split it later in zero_num (number of zero pages) and
> normal_num (number of normal pages).  This name is better.
> 
> Signed-off-by: Juan Quintela 
> ---
>  migration/multifd.h |  2 +-
>  migration/multifd.c | 38 +++---
>  2 files changed, 20 insertions(+), 20 deletions(-)
> 
> diff --git a/migration/multifd.h b/migration/multifd.h
> index 15c50ca0b2..86820dd028 100644
> --- a/migration/multifd.h
> +++ b/migration/multifd.h
> @@ -55,7 +55,7 @@ typedef struct {
>  
>  typedef struct {
>  /* number of used pages */
> -uint32_t used;
> +uint32_t num;

What does 'used' actually mean here?

Dave

>  /* number of allocated pages */
>  uint32_t allocated;
>  /* global number of generated multifd packets */
> diff --git a/migration/multifd.c b/migration/multifd.c
> index 8125d0015c..8ea86d81dc 100644
> --- a/migration/multifd.c
> +++ b/migration/multifd.c
> @@ -252,7 +252,7 @@ static MultiFDPages_t *multifd_pages_init(size_t size)
>  
>  static void multifd_pages_clear(MultiFDPages_t *pages)
>  {
> -pages->used = 0;
> +pages->num = 0;
>  pages->allocated = 0;
>  pages->packet_num = 0;
>  pages->block = NULL;
> @@ -270,7 +270,7 @@ static void multifd_send_fill_packet(MultiFDSendParams *p)
>  
>  packet->flags = cpu_to_be32(p->flags);
>  packet->pages_alloc = cpu_to_be32(p->pages->allocated);
> -packet->pages_used = cpu_to_be32(p->pages->used);
> +packet->pages_used = cpu_to_be32(p->pages->num);
>  packet->next_packet_size = cpu_to_be32(p->next_packet_size);
>  packet->packet_num = cpu_to_be64(p->packet_num);
>  
> @@ -278,7 +278,7 @@ static void multifd_send_fill_packet(MultiFDSendParams *p)
>  strncpy(packet->ramblock, p->pages->block->idstr, 256);
>  }
>  
> -for (i = 0; i < p->pages->used; i++) {
> +for (i = 0; i < p->pages->num; i++) {
>  /* there are architectures where ram_addr_t is 32 bit */
>  uint64_t temp = p->pages->offset[i];
>  
> @@ -332,18 +332,18 @@ static int multifd_recv_unfill_packet(MultiFDRecvParams 
> *p, Error **errp)
>  p->pages = multifd_pages_init(packet->pages_alloc);
>  }
>  
> -p->pages->used = be32_to_cpu(packet->pages_used);
> -if (p->pages->used > packet->pages_alloc) {
> +p->pages->num = be32_to_cpu(packet->pages_used);
> +if (p->pages->num > packet->pages_alloc) {
>  error_setg(errp, "multifd: received packet "
> "with %d pages and expected maximum pages are %d",
> -   p->pages->used, packet->pages_alloc) ;
> +   p->pages->num, packet->pages_alloc) ;
>  return -1;
>  }
>  
>  p->next_packet_size = be32_to_cpu(packet->next_packet_size);
>  p->packet_num = be64_to_cpu(packet->packet_num);
>  
> -if (p->pages->used == 0) {
> +if (p->pages->num == 0) {
>  return 0;
>  }
>  
> @@ -356,7 +356,7 @@ static int multifd_recv_unfill_packet(MultiFDRecvParams 
> *p, Error **errp)
>  return -1;
>  }
>  
> -for (i = 0; i < p->pages->used; i++) {
> +for (i = 0; i < p->pages->num; i++) {
>  uint64_t offset = be64_to_cpu(packet->offset[i]);
>  
>  if (offset > (block->used_length - page_size)) {
> @@ -443,13 +443,13 @@ static int multifd_send_pages(QEMUFile *f)
>  }
>  qemu_mutex_unlock(>mutex);
>  }
> -assert(!p->pages->used);
> +assert(!p->pages->num);
>  assert(!p->pages->block);
>  
>  p->packet_num = multifd_send_state->packet_num++;
>  multifd_send_state->pages = p->pages;
>  p->pages = pages;
> -transferred = ((uint64_t) pages->used) * qemu_target_page_size()
> +transferred = ((uint64_t) pages->num) * qemu_target_page_size()
>  + p->packet_len;
>  qemu_file_update_transfer(f, transferred);
>  ram_counters.multifd_bytes += transferred;
> @@ -469,12 +469,12 @@ int multifd_queue_page(QEMUFile *f, RAMBlock *block, 
> ram_addr_t offset)
>  }
>  
>  if (pages->block == block) {
> -pages->offset[pages->used] = offset;
> -pages->iov[pages->used].iov_base = block->host + offset;
> -pages->iov[pages->used].iov_len = qemu_target_page_size();
> -pages->used++;
> +pages->offset[pages->num] = offset;
> +pages->iov[pages->num].iov_base = block->host + offset;
> +pages->iov[pages->num].iov_len = qemu_target_page_size();
> +pages->num++;
>  
> -if (pages->used < pages->allocated) {
> +if (pages->num < pages->allocated) {
>  return 1;
>  }
>  }
> @@ -586,7 +586,7 @@ void multifd_send_sync_main(QEMUFile *f)
>  if (!migrate_use_multifd()) {
>  return;
>  }
> -if (multifd_send_state->pages->used) {
> +if (multifd_send_state->pages->num) {
>  if (multifd_send_pages(f) < 0) {
>  error_report("%s: multifd_send_pages fail", 

Re: [PATCH] target/ppc: fix Hash64 MMU update of PTE bit R

2021-11-24 Thread Cédric Le Goater

It can be reproduced by trying to boot this iso: 
https://download.freebsd.org/ftp/snapshots/powerpc/powerpc64/ISO-IMAGES/14.0/FreeBSD-14.0-CURRENT-powerpc-powerpc64-20211028-4827bf76bce-250301-disc1.iso.xz

It is easier to reproduce it using power8/powernv8.


power8 only has Hash MMU. I understand that FreeBSD also supports power9
processor. with radix ? and XIVE ?

Thanks,

C.



[PATCH 23/23] python: re-enable pylint duplicate-code warnings

2021-11-24 Thread John Snow
With the old library gone, there's nothing duplicated in the tree, so
the warning suppression can be removed.

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

diff --git a/python/setup.cfg b/python/setup.cfg
index 5140a5b322..c341e922c2 100644
--- a/python/setup.cfg
+++ b/python/setup.cfg
@@ -114,7 +114,6 @@ ignore_missing_imports = True
 disable=consider-using-f-string,
 too-many-function-args,  # mypy handles this with less false positives.
 no-member,  # mypy also handles this better.
-duplicate-code,  # To be removed by the end of this patch series.
 
 [pylint.basic]
 # Good variable names which should always be accepted, separated by a comma.
-- 
2.31.1




[PATCH 19/23] python/aqmp: take QMPBadPortError and parse_address from qemu.qmp

2021-11-24 Thread John Snow
Shift these definitions over from the qmp package to the async qmp
package.

Signed-off-by: John Snow 
---
 python/qemu/aqmp/aqmp_tui.py |  2 +-
 python/qemu/aqmp/legacy.py   | 30 ++
 python/qemu/qmp/__init__.py  | 26 --
 3 files changed, 27 insertions(+), 31 deletions(-)

diff --git a/python/qemu/aqmp/aqmp_tui.py b/python/qemu/aqmp/aqmp_tui.py
index a2929f771c..184a3e4690 100644
--- a/python/qemu/aqmp/aqmp_tui.py
+++ b/python/qemu/aqmp/aqmp_tui.py
@@ -35,8 +35,8 @@
 import urwid
 import urwid_readline
 
-from ..qmp import QEMUMonitorProtocol, QMPBadPortError
 from .error import ProtocolError
+from .legacy import QEMUMonitorProtocol, QMPBadPortError
 from .message import DeserializationError, Message, UnexpectedTypeError
 from .protocol import ConnectError, Runstate
 from .qmp_client import ExecInterruptedError, QMPClient
diff --git a/python/qemu/aqmp/legacy.py b/python/qemu/aqmp/legacy.py
index 5d358d63db..c8183de19a 100644
--- a/python/qemu/aqmp/legacy.py
+++ b/python/qemu/aqmp/legacy.py
@@ -22,9 +22,6 @@
 from .qmp_client import QMPClient
 
 
-# (Temporarily) Re-export QMPBadPortError
-QMPBadPortError = qemu.qmp.QMPBadPortError
-
 #: QMPMessage is an entire QMP message of any kind.
 QMPMessage = Dict[str, Any]
 
@@ -45,6 +42,12 @@
 # pylint: disable=missing-docstring
 
 
+class QMPBadPortError(AQMPError):
+"""
+Unable to parse socket address: Port was non-numerical.
+"""
+
+
 class QEMUMonitorProtocol(qemu.qmp.QEMUMonitorProtocol):
 def __init__(self, address: SocketAddrT,
  server: bool = False,
@@ -72,7 +75,26 @@ def _get_greeting(self) -> Optional[QMPMessage]:
 return None
 
 # __enter__ and __exit__ need no changes
-# parse_address needs no changes
+
+@classmethod
+def parse_address(cls, address: str) -> SocketAddrT:
+"""
+Parse a string into a QMP address.
+
+Figure out if the argument is in the port:host form.
+If it's not, it's probably a file path.
+"""
+components = address.split(':')
+if len(components) == 2:
+try:
+port = int(components[1])
+except ValueError:
+msg = f"Bad port: '{components[1]}' in '{address}'."
+raise QMPBadPortError(msg) from None
+return (components[0], port)
+
+# Treat as filepath.
+return address
 
 def connect(self, negotiate: bool = True) -> Optional[QMPMessage]:
 self._aqmp.await_greeting = negotiate
diff --git a/python/qemu/qmp/__init__.py b/python/qemu/qmp/__init__.py
index 358c0971d0..4e08641154 100644
--- a/python/qemu/qmp/__init__.py
+++ b/python/qemu/qmp/__init__.py
@@ -102,12 +102,6 @@ def __init__(self, reply: QMPMessage):
 self.reply = reply
 
 
-class QMPBadPortError(QMPError):
-"""
-Unable to parse socket address: Port was non-numerical.
-"""
-
-
 class QEMUMonitorProtocol:
 """
 Provide an API to connect to QEMU via QEMU Monitor Protocol (QMP) and then
@@ -237,26 +231,6 @@ def __exit__(self,
 # Implement context manager exit function.
 self.close()
 
-@classmethod
-def parse_address(cls, address: str) -> SocketAddrT:
-"""
-Parse a string into a QMP address.
-
-Figure out if the argument is in the port:host form.
-If it's not, it's probably a file path.
-"""
-components = address.split(':')
-if len(components) == 2:
-try:
-port = int(components[1])
-except ValueError:
-msg = f"Bad port: '{components[1]}' in '{address}'."
-raise QMPBadPortError(msg) from None
-return (components[0], port)
-
-# Treat as filepath.
-return address
-
 def connect(self, negotiate: bool = True) -> Optional[QMPMessage]:
 """
 Connect to the QMP Monitor and perform capabilities negotiation.
-- 
2.31.1




[PATCH 21/23] python/aqmp: copy qmp docstrings to qemu.aqmp.legacy

2021-11-24 Thread John Snow
Copy the docstrings out of qemu.qmp, adjusting them as necessary to
more accurately reflect the current state of this class.

Signed-off-by: John Snow 
---
 python/qemu/aqmp/legacy.py | 110 ++---
 1 file changed, 102 insertions(+), 8 deletions(-)

diff --git a/python/qemu/aqmp/legacy.py b/python/qemu/aqmp/legacy.py
index 71f3d378db..5f7955ac5d 100644
--- a/python/qemu/aqmp/legacy.py
+++ b/python/qemu/aqmp/legacy.py
@@ -1,9 +1,23 @@
 """
-Sync QMP Wrapper
+(Legacy) Sync QMP Wrapper
 
-This class pretends to be qemu.qmp.QEMUMonitorProtocol.
+This module provides the `QEMUMonitorProtocol` class, which is a
+synchronous wrapper around `QMPClient`.
+
+Its design closely resembles that of the original QEMUMonitorProtocol
+class, originally written by Luiz Capitulino.
 """
 
+# Copyright (C) 2009, 2010, 2021 Red Hat Inc.
+#
+# Authors:
+#  Luiz Capitulino 
+#  John Snow 
+#
+# This work is licensed under the terms of the GNU GPL, version 2.
+# See the COPYING file in the top-level directory.
+
+
 import asyncio
 from types import TracebackType
 from typing import (
@@ -39,9 +53,6 @@
 # {} is the QMPReturnValue.
 
 
-# pylint: disable=missing-docstring
-
-
 class QMPBadPortError(AQMPError):
 """
 Unable to parse socket address: Port was non-numerical.
@@ -49,6 +60,21 @@ class QMPBadPortError(AQMPError):
 
 
 class QEMUMonitorProtocol:
+"""
+Provide an API to connect to QEMU via QEMU Monitor Protocol (QMP)
+and then allow to handle commands and events.
+
+:param address:  QEMU address, can be either a unix socket path (string)
+ or a tuple in the form ( address, port ) for a TCP
+ connection
+:param server:   Deprecated, ignored. (See 'accept')
+:param nickname: Optional nickname used for logging.
+
+..note::
+No connection is established during `__init__`, this is done by
+the `connect()` or `accept()` methods.
+"""
+
 def __init__(self, address: SocketAddrT,
  server: bool = False,  # pylint: disable=unused-argument
  nickname: Optional[str] = None):
@@ -108,6 +134,12 @@ def parse_address(cls, address: str) -> SocketAddrT:
 return address
 
 def connect(self, negotiate: bool = True) -> Optional[QMPMessage]:
+"""
+Connect to the QMP Monitor and perform capabilities negotiation.
+
+:return: QMP greeting dict, or None if negotiate is false
+:raise ConnectError: on connection errors
+"""
 self._aqmp.await_greeting = negotiate
 self._aqmp.negotiate = negotiate
 
@@ -117,6 +149,16 @@ def connect(self, negotiate: bool = True) -> 
Optional[QMPMessage]:
 return self._get_greeting()
 
 def accept(self, timeout: Optional[float] = 15.0) -> QMPMessage:
+"""
+Await connection from QMP Monitor and perform capabilities negotiation.
+
+:param timeout:
+timeout in seconds (nonnegative float number, or None).
+If None, there is no timeout, and this may block forever.
+
+:return: QMP greeting dict
+:raise ConnectError: on connection errors
+"""
 self._aqmp.await_greeting = True
 self._aqmp.negotiate = True
 
@@ -130,6 +172,12 @@ def accept(self, timeout: Optional[float] = 15.0) -> 
QMPMessage:
 return ret
 
 def cmd_obj(self, qmp_cmd: QMPMessage) -> QMPMessage:
+"""
+Send a QMP command to the QMP Monitor.
+
+:param qmp_cmd: QMP command to be sent as a Python dict
+:return: QMP response as a Python dict
+"""
 return dict(
 self._sync(
 # pylint: disable=protected-access
@@ -148,9 +196,9 @@ def cmd(self, name: str,
 """
 Build a QMP command and send it to the QMP Monitor.
 
-@param name: command name (string)
-@param args: command arguments (dict)
-@param cmd_id: command id (dict, list, string or int)
+:param name: command name (string)
+:param args: command arguments (dict)
+:param cmd_id: command id (dict, list, string or int)
 """
 qmp_cmd: QMPMessage = {'execute': name}
 if args:
@@ -160,6 +208,9 @@ def cmd(self, name: str,
 return self.cmd_obj(qmp_cmd)
 
 def command(self, cmd: str, **kwds: object) -> QMPReturnValue:
+"""
+Build and send a QMP command to the monitor, report errors if any
+"""
 return self._sync(
 self._aqmp.execute(cmd, kwds),
 self._timeout
@@ -167,6 +218,19 @@ def command(self, cmd: str, **kwds: object) -> 
QMPReturnValue:
 
 def pull_event(self,
wait: Union[bool, float] = False) -> Optional[QMPMessage]:
+"""
+Pulls a single event.
+
+:param wait:
+If False or 0, do not wait. Return None if no events ready.
+If True, wait forever until the next event.
+Otherwise, 

[PATCH 13/23] scripts/cpu-x86-uarch-abi: switch to AQMP

2021-11-24 Thread John Snow
Signed-off-by: John Snow 
---
 scripts/cpu-x86-uarch-abi.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/scripts/cpu-x86-uarch-abi.py b/scripts/cpu-x86-uarch-abi.py
index 8963d90f0b..c262d2f027 100644
--- a/scripts/cpu-x86-uarch-abi.py
+++ b/scripts/cpu-x86-uarch-abi.py
@@ -6,7 +6,7 @@
 # compatibility levels for each CPU model.
 #
 
-from qemu import qmp
+from qemu.aqmp.legacy import QEMUMonitorProtocol
 import sys
 
 if len(sys.argv) != 2:
@@ -66,7 +66,7 @@
 
 
 sock = sys.argv[1]
-shell = qmp.QEMUMonitorProtocol(sock)
+shell = QEMUMonitorProtocol(sock)
 shell.connect()
 
 models = shell.cmd("query-cpu-definitions")
-- 
2.31.1




[PATCH 18/23] python: temporarily silence pylint duplicate-code warnings

2021-11-24 Thread John Snow
The next several commits copy some code from qemu.qmp to qemu.aqmp, then
delete qemu.qmp. In the interim, to prevent test failures, the duplicate
code detection needs to be silenced to prevent bisect problems with CI
testing.

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

diff --git a/python/setup.cfg b/python/setup.cfg
index 168a79c867..510df23698 100644
--- a/python/setup.cfg
+++ b/python/setup.cfg
@@ -115,6 +115,7 @@ ignore_missing_imports = True
 disable=consider-using-f-string,
 too-many-function-args,  # mypy handles this with less false positives.
 no-member,  # mypy also handles this better.
+duplicate-code,  # To be removed by the end of this patch series.
 
 [pylint.basic]
 # Good variable names which should always be accepted, separated by a comma.
-- 
2.31.1




[PATCH 14/23] scripts/render-block-graph: switch to AQMP

2021-11-24 Thread John Snow
Creating an instance of qemu.aqmp.ExecuteError is too involved here, so
just drop the specificity down to a generic AQMPError.

Signed-off-by: John Snow 
---
 scripts/render_block_graph.py | 8 +++-
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/scripts/render_block_graph.py b/scripts/render_block_graph.py
index da6acf050d..d2f3a72348 100755
--- a/scripts/render_block_graph.py
+++ b/scripts/render_block_graph.py
@@ -25,10 +25,8 @@
 from graphviz import Digraph
 
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'python'))
-from qemu.qmp import (
-QEMUMonitorProtocol,
-QMPResponseError,
-)
+from qemu.aqmp import AQMPError
+from qemu.aqmp.legacy import QEMUMonitorProtocol
 
 
 def perm(arr):
@@ -105,7 +103,7 @@ def command(self, cmd):
 reply = json.loads(subprocess.check_output(ar))
 
 if 'error' in reply:
-raise QMPResponseError(reply)
+raise AQMPError(reply)
 
 return reply['return']
 
-- 
2.31.1




[PATCH 08/23] python/qmp: switch qmp-shell to AQMP

2021-11-24 Thread John Snow
We have a replacement for async QMP, but it doesn't have feature parity
yet. For now, then, port the old tool onto the new backend.

Signed-off-by: John Snow 
---
 python/qemu/aqmp/legacy.py   |  3 +++
 python/qemu/qmp/qmp_shell.py | 31 +--
 2 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/python/qemu/aqmp/legacy.py b/python/qemu/aqmp/legacy.py
index 9431fe9330..5d358d63db 100644
--- a/python/qemu/aqmp/legacy.py
+++ b/python/qemu/aqmp/legacy.py
@@ -22,6 +22,9 @@
 from .qmp_client import QMPClient
 
 
+# (Temporarily) Re-export QMPBadPortError
+QMPBadPortError = qemu.qmp.QMPBadPortError
+
 #: QMPMessage is an entire QMP message of any kind.
 QMPMessage = Dict[str, Any]
 
diff --git a/python/qemu/qmp/qmp_shell.py b/python/qemu/qmp/qmp_shell.py
index e7d7eb18f1..2260ae016e 100644
--- a/python/qemu/qmp/qmp_shell.py
+++ b/python/qemu/qmp/qmp_shell.py
@@ -95,8 +95,13 @@
 Sequence,
 )
 
-from qemu import qmp
-from qemu.qmp import QMPMessage
+from qemu.aqmp import AQMPError, ConnectError, SocketAddrT
+from qemu.aqmp.legacy import (
+QEMUMonitorProtocol,
+QMPBadPortError,
+QMPMessage,
+QMPObject,
+)
 
 
 LOG = logging.getLogger(__name__)
@@ -125,7 +130,7 @@ def complete(self, text: str, state: int) -> Optional[str]:
 return None
 
 
-class QMPShellError(qmp.QMPError):
+class QMPShellError(AQMPError):
 """
 QMP Shell Base error class.
 """
@@ -153,7 +158,7 @@ def visit_Name(cls,  # pylint: disable=invalid-name
 return node
 
 
-class QMPShell(qmp.QEMUMonitorProtocol):
+class QMPShell(QEMUMonitorProtocol):
 """
 QMPShell provides a basic readline-based QMP shell.
 
@@ -161,7 +166,7 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 :param pretty: Pretty-print QMP messages.
 :param verbose: Echo outgoing QMP messages to console.
 """
-def __init__(self, address: qmp.SocketAddrT,
+def __init__(self, address: SocketAddrT,
  pretty: bool = False, verbose: bool = False):
 super().__init__(address)
 self._greeting: Optional[QMPMessage] = None
@@ -237,7 +242,7 @@ def _parse_value(cls, val: str) -> object:
 
 def _cli_expr(self,
   tokens: Sequence[str],
-  parent: qmp.QMPObject) -> None:
+  parent: QMPObject) -> None:
 for arg in tokens:
 (key, sep, val) = arg.partition('=')
 if sep != '=':
@@ -403,7 +408,7 @@ class HMPShell(QMPShell):
 :param pretty: Pretty-print QMP messages.
 :param verbose: Echo outgoing QMP messages to console.
 """
-def __init__(self, address: qmp.SocketAddrT,
+def __init__(self, address: SocketAddrT,
  pretty: bool = False, verbose: bool = False):
 super().__init__(address, pretty, verbose)
 self._cpu_index = 0
@@ -512,19 +517,17 @@ def main() -> None:
 
 try:
 address = shell_class.parse_address(args.qmp_server)
-except qmp.QMPBadPortError:
+except QMPBadPortError:
 parser.error(f"Bad port number: {args.qmp_server}")
 return  # pycharm doesn't know error() is noreturn
 
 with shell_class(address, args.pretty, args.verbose) as qemu:
 try:
 qemu.connect(negotiate=not args.skip_negotiation)
-except qmp.QMPConnectError:
-die("Didn't get QMP greeting message")
-except qmp.QMPCapabilitiesError:
-die("Couldn't negotiate capabilities")
-except OSError as err:
-die(f"Couldn't connect to {args.qmp_server}: {err!s}")
+except ConnectError as err:
+if isinstance(err.exc, OSError):
+die(f"Couldn't connect to {args.qmp_server}: {err!s}")
+die(str(err))
 
 for _ in qemu.repl():
 pass
-- 
2.31.1




[PATCH 20/23] python/aqmp: fully separate from qmp.QEMUMonitorProtocol

2021-11-24 Thread John Snow
After this patch, qemu.aqmp.legacy.QEMUMonitorProtocol no longer
inherits from qemu.qmp.QEMUMonitorProtocol. To do this, several
inherited methods need to be explicitly re-defined.

Signed-off-by: John Snow 
---
 python/qemu/aqmp/legacy.py | 38 --
 1 file changed, 32 insertions(+), 6 deletions(-)

diff --git a/python/qemu/aqmp/legacy.py b/python/qemu/aqmp/legacy.py
index c8183de19a..71f3d378db 100644
--- a/python/qemu/aqmp/legacy.py
+++ b/python/qemu/aqmp/legacy.py
@@ -5,18 +5,18 @@
 """
 
 import asyncio
+from types import TracebackType
 from typing import (
 Any,
 Awaitable,
 Dict,
 List,
 Optional,
+Type,
 TypeVar,
 Union,
 )
 
-import qemu.qmp
-
 from .error import AQMPError
 from .protocol import Runstate, SocketAddrT
 from .qmp_client import QMPClient
@@ -48,9 +48,9 @@ class QMPBadPortError(AQMPError):
 """
 
 
-class QEMUMonitorProtocol(qemu.qmp.QEMUMonitorProtocol):
+class QEMUMonitorProtocol:
 def __init__(self, address: SocketAddrT,
- server: bool = False,
+ server: bool = False,  # pylint: disable=unused-argument
  nickname: Optional[str] = None):
 
 # pylint: disable=super-init-not-called
@@ -74,7 +74,18 @@ def _get_greeting(self) -> Optional[QMPMessage]:
 return self._aqmp.greeting._asdict()
 return None
 
-# __enter__ and __exit__ need no changes
+def __enter__(self: _T) -> _T:
+# Implement context manager enter function.
+return self
+
+def __exit__(self,
+ # pylint: disable=duplicate-code
+ # see https://github.com/PyCQA/pylint/issues/3619
+ exc_type: Optional[Type[BaseException]],
+ exc_val: Optional[BaseException],
+ exc_tb: Optional[TracebackType]) -> None:
+# Implement context manager exit function.
+self.close()
 
 @classmethod
 def parse_address(cls, address: str) -> SocketAddrT:
@@ -131,7 +142,22 @@ def cmd_obj(self, qmp_cmd: QMPMessage) -> QMPMessage:
 )
 )
 
-# Default impl of cmd() delegates to cmd_obj
+def cmd(self, name: str,
+args: Optional[Dict[str, object]] = None,
+cmd_id: Optional[object] = None) -> QMPMessage:
+"""
+Build a QMP command and send it to the QMP Monitor.
+
+@param name: command name (string)
+@param args: command arguments (dict)
+@param cmd_id: command id (dict, list, string or int)
+"""
+qmp_cmd: QMPMessage = {'execute': name}
+if args:
+qmp_cmd['arguments'] = args
+if cmd_id:
+qmp_cmd['id'] = cmd_id
+return self.cmd_obj(qmp_cmd)
 
 def command(self, cmd: str, **kwds: object) -> QMPReturnValue:
 return self._sync(
-- 
2.31.1




[PATCH 17/23] iotests: switch to AQMP

2021-11-24 Thread John Snow
Simply import the type defition from the new location.

Signed-off-by: John Snow 
---
 tests/qemu-iotests/iotests.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 83bfedb902..cb21aebe36 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -37,7 +37,7 @@
 from contextlib import contextmanager
 
 from qemu.machine import qtest
-from qemu.qmp import QMPMessage
+from qemu.aqmp.legacy import QMPMessage
 
 # Use this logger for logging messages directly from the iotests module
 logger = logging.getLogger('qemu.iotests')
-- 
2.31.1




[PATCH 09/23] python: move qmp utilities to python/qemu/utils

2021-11-24 Thread John Snow
In order to upload a QMP package to PyPI, I want to remove any scripts
that I am not 100% confident I want to support upstream, beyond our
castle walls.

Move most of our QMP utilities into the utils package so we can split
them out from the PyPI upload.

Signed-off-by: John Snow 
---
 python/qemu/{qmp => utils}/qemu_ga_client.py |  0
 python/qemu/{qmp => utils}/qom.py|  0
 python/qemu/{qmp => utils}/qom_common.py |  0
 python/qemu/{qmp => utils}/qom_fuse.py   |  0
 python/setup.cfg | 16 
 scripts/qmp/qemu-ga-client   |  2 +-
 scripts/qmp/qom-fuse |  2 +-
 scripts/qmp/qom-get  |  2 +-
 scripts/qmp/qom-list |  2 +-
 scripts/qmp/qom-set  |  2 +-
 scripts/qmp/qom-tree |  2 +-
 11 files changed, 14 insertions(+), 14 deletions(-)
 rename python/qemu/{qmp => utils}/qemu_ga_client.py (100%)
 rename python/qemu/{qmp => utils}/qom.py (100%)
 rename python/qemu/{qmp => utils}/qom_common.py (100%)
 rename python/qemu/{qmp => utils}/qom_fuse.py (100%)

diff --git a/python/qemu/qmp/qemu_ga_client.py 
b/python/qemu/utils/qemu_ga_client.py
similarity index 100%
rename from python/qemu/qmp/qemu_ga_client.py
rename to python/qemu/utils/qemu_ga_client.py
diff --git a/python/qemu/qmp/qom.py b/python/qemu/utils/qom.py
similarity index 100%
rename from python/qemu/qmp/qom.py
rename to python/qemu/utils/qom.py
diff --git a/python/qemu/qmp/qom_common.py b/python/qemu/utils/qom_common.py
similarity index 100%
rename from python/qemu/qmp/qom_common.py
rename to python/qemu/utils/qom_common.py
diff --git a/python/qemu/qmp/qom_fuse.py b/python/qemu/utils/qom_fuse.py
similarity index 100%
rename from python/qemu/qmp/qom_fuse.py
rename to python/qemu/utils/qom_fuse.py
diff --git a/python/setup.cfg b/python/setup.cfg
index 417e937839..78421411d2 100644
--- a/python/setup.cfg
+++ b/python/setup.cfg
@@ -60,13 +60,13 @@ tui =
 
 [options.entry_points]
 console_scripts =
-qom = qemu.qmp.qom:main
-qom-set = qemu.qmp.qom:QOMSet.entry_point
-qom-get = qemu.qmp.qom:QOMGet.entry_point
-qom-list = qemu.qmp.qom:QOMList.entry_point
-qom-tree = qemu.qmp.qom:QOMTree.entry_point
-qom-fuse = qemu.qmp.qom_fuse:QOMFuse.entry_point [fuse]
-qemu-ga-client = qemu.qmp.qemu_ga_client:main
+qom = qemu.utils.qom:main
+qom-set = qemu.utils.qom:QOMSet.entry_point
+qom-get = qemu.utils.qom:QOMGet.entry_point
+qom-list = qemu.utils.qom:QOMList.entry_point
+qom-tree = qemu.utils.qom:QOMTree.entry_point
+qom-fuse = qemu.utils.qom_fuse:QOMFuse.entry_point [fuse]
+qemu-ga-client = qemu.utils.qemu_ga_client:main
 qmp-shell = qemu.qmp.qmp_shell:main
 aqmp-tui = qemu.aqmp.aqmp_tui:main [tui]
 
@@ -80,7 +80,7 @@ python_version = 3.6
 warn_unused_configs = True
 namespace_packages = True
 
-[mypy-qemu.qmp.qom_fuse]
+[mypy-qemu.utils.qom_fuse]
 # fusepy has no type stubs:
 allow_subclassing_any = True
 
diff --git a/scripts/qmp/qemu-ga-client b/scripts/qmp/qemu-ga-client
index 102fd2cad9..56edd0234a 100755
--- a/scripts/qmp/qemu-ga-client
+++ b/scripts/qmp/qemu-ga-client
@@ -4,7 +4,7 @@ import os
 import sys
 
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
-from qemu.qmp import qemu_ga_client
+from qemu.utils import qemu_ga_client
 
 
 if __name__ == '__main__':
diff --git a/scripts/qmp/qom-fuse b/scripts/qmp/qom-fuse
index a58c8ef979..d453807b27 100755
--- a/scripts/qmp/qom-fuse
+++ b/scripts/qmp/qom-fuse
@@ -4,7 +4,7 @@ import os
 import sys
 
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
-from qemu.qmp.qom_fuse import QOMFuse
+from qemu.utils.qom_fuse import QOMFuse
 
 
 if __name__ == '__main__':
diff --git a/scripts/qmp/qom-get b/scripts/qmp/qom-get
index e4f3e0c013..04ebe052e8 100755
--- a/scripts/qmp/qom-get
+++ b/scripts/qmp/qom-get
@@ -4,7 +4,7 @@ import os
 import sys
 
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
-from qemu.qmp.qom import QOMGet
+from qemu.utils.qom import QOMGet
 
 
 if __name__ == '__main__':
diff --git a/scripts/qmp/qom-list b/scripts/qmp/qom-list
index 7a071a54e1..853b85a8d3 100755
--- a/scripts/qmp/qom-list
+++ b/scripts/qmp/qom-list
@@ -4,7 +4,7 @@ import os
 import sys
 
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
-from qemu.qmp.qom import QOMList
+from qemu.utils.qom import QOMList
 
 
 if __name__ == '__main__':
diff --git a/scripts/qmp/qom-set b/scripts/qmp/qom-set
index 9ca9e2ba10..06820feec4 100755
--- a/scripts/qmp/qom-set
+++ b/scripts/qmp/qom-set
@@ -4,7 +4,7 @@ import os
 import sys
 
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
-from qemu.qmp.qom import QOMSet
+from qemu.utils.qom import QOMSet
 
 
 if __name__ == '__main__':
diff --git a/scripts/qmp/qom-tree b/scripts/qmp/qom-tree
index 

[PATCH 07/23] python/qmp: switch qom tools to AQMP

2021-11-24 Thread John Snow
Signed-off-by: John Snow 
---
 python/qemu/qmp/qom.py|  5 +++--
 python/qemu/qmp/qom_common.py |  7 ---
 python/qemu/qmp/qom_fuse.py   | 11 ++-
 3 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/python/qemu/qmp/qom.py b/python/qemu/qmp/qom.py
index 8ff28a8343..bb5d1a78f5 100644
--- a/python/qemu/qmp/qom.py
+++ b/python/qemu/qmp/qom.py
@@ -32,7 +32,8 @@
 
 import argparse
 
-from . import QMPResponseError
+from qemu.aqmp import ExecuteError
+
 from .qom_common import QOMCommand
 
 
@@ -233,7 +234,7 @@ def _list_node(self, path: str) -> None:
 rsp = self.qmp.command('qom-get', path=path,
property=item.name)
 print(f"  {item.name}: {rsp} ({item.type})")
-except QMPResponseError as err:
+except ExecuteError as err:
 print(f"  {item.name}:  ({item.type})")
 print('')
 for item in items:
diff --git a/python/qemu/qmp/qom_common.py b/python/qemu/qmp/qom_common.py
index a59ae1a2a1..b145157258 100644
--- a/python/qemu/qmp/qom_common.py
+++ b/python/qemu/qmp/qom_common.py
@@ -27,7 +27,8 @@
 TypeVar,
 )
 
-from . import QEMUMonitorProtocol, QMPError
+from qemu.aqmp import AQMPError
+from qemu.aqmp.legacy import QEMUMonitorProtocol
 
 
 # The following is needed only for a type alias.
@@ -82,7 +83,7 @@ class QOMCommand:
 
 def __init__(self, args: argparse.Namespace):
 if args.socket is None:
-raise QMPError("No QMP socket path or address given")
+raise AQMPError("No QMP socket path or address given")
 self.qmp = QEMUMonitorProtocol(
 QEMUMonitorProtocol.parse_address(args.socket)
 )
@@ -161,7 +162,7 @@ def command_runner(
 try:
 cmd = cls(args)
 return cmd.run()
-except QMPError as err:
+except AQMPError as err:
 print(f"{type(err).__name__}: {err!s}", file=sys.stderr)
 return -1
 
diff --git a/python/qemu/qmp/qom_fuse.py b/python/qemu/qmp/qom_fuse.py
index 43f4671fdb..653a76b93b 100644
--- a/python/qemu/qmp/qom_fuse.py
+++ b/python/qemu/qmp/qom_fuse.py
@@ -48,7 +48,8 @@
 import fuse
 from fuse import FUSE, FuseOSError, Operations
 
-from . import QMPResponseError
+from qemu.aqmp import ExecuteError
+
 from .qom_common import QOMCommand
 
 
@@ -99,7 +100,7 @@ def is_object(self, path: str) -> bool:
 try:
 self.qom_list(path)
 return True
-except QMPResponseError:
+except ExecuteError:
 return False
 
 def is_property(self, path: str) -> bool:
@@ -112,7 +113,7 @@ def is_property(self, path: str) -> bool:
 if item.name == prop:
 return True
 return False
-except QMPResponseError:
+except ExecuteError:
 return False
 
 def is_link(self, path: str) -> bool:
@@ -125,7 +126,7 @@ def is_link(self, path: str) -> bool:
 if item.name == prop and item.link:
 return True
 return False
-except QMPResponseError:
+except ExecuteError:
 return False
 
 def read(self, path: str, size: int, offset: int, fh: IO[bytes]) -> bytes:
@@ -138,7 +139,7 @@ def read(self, path: str, size: int, offset: int, fh: 
IO[bytes]) -> bytes:
 try:
 data = str(self.qmp.command('qom-get', path=path, property=prop))
 data += '\n'  # make values shell friendly
-except QMPResponseError as err:
+except ExecuteError as err:
 raise FuseOSError(EPERM) from err
 
 if offset > len(data):
-- 
2.31.1




[PATCH 15/23] scripts/bench-block-job: switch to AQMP

2021-11-24 Thread John Snow
For this commit, we only need to remove accommodations for the
synchronous QMP library.

Signed-off-by: John Snow 
---
 scripts/simplebench/bench_block_job.py | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/scripts/simplebench/bench_block_job.py 
b/scripts/simplebench/bench_block_job.py
index a403c35b08..af9d1646a4 100755
--- a/scripts/simplebench/bench_block_job.py
+++ b/scripts/simplebench/bench_block_job.py
@@ -27,7 +27,6 @@
 
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
 from qemu.machine import QEMUMachine
-from qemu.qmp import QMPConnectError
 from qemu.aqmp import ConnectError
 
 
@@ -50,7 +49,7 @@ def bench_block_job(cmd, cmd_args, qemu_args):
 vm.launch()
 except OSError as e:
 return {'error': 'popen failed: ' + str(e)}
-except (QMPConnectError, ConnectError, socket.timeout):
+except (ConnectError, socket.timeout):
 return {'error': 'qemu failed: ' + str(vm.get_log())}
 
 try:
-- 
2.31.1




[PATCH 12/23] scripts/cpu-x86-uarch-abi: fix CLI parsing

2021-11-24 Thread John Snow
Signed-off-by: John Snow 
---
 scripts/cpu-x86-uarch-abi.py | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/scripts/cpu-x86-uarch-abi.py b/scripts/cpu-x86-uarch-abi.py
index 08acc52a81..8963d90f0b 100644
--- a/scripts/cpu-x86-uarch-abi.py
+++ b/scripts/cpu-x86-uarch-abi.py
@@ -9,7 +9,7 @@
 from qemu import qmp
 import sys
 
-if len(sys.argv) != 1:
+if len(sys.argv) != 2:
 print("syntax: %s QMP-SOCK\n\n" % __file__ +
   "Where QMP-SOCK points to a QEMU process such as\n\n" +
   " # qemu-system-x86_64 -qmp unix:/tmp/qmp,server,nowait " +
@@ -66,7 +66,6 @@
 
 
 sock = sys.argv[1]
-cmd = sys.argv[2]
 shell = qmp.QEMUMonitorProtocol(sock)
 shell.connect()
 
-- 
2.31.1




[PATCH 06/23] python/qmp: switch qemu-ga-client to AQMP

2021-11-24 Thread John Snow
Signed-off-by: John Snow 
---
 python/qemu/qmp/qemu_ga_client.py | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/python/qemu/qmp/qemu_ga_client.py 
b/python/qemu/qmp/qemu_ga_client.py
index b3e1d98c9e..15ed430c61 100644
--- a/python/qemu/qmp/qemu_ga_client.py
+++ b/python/qemu/qmp/qemu_ga_client.py
@@ -37,8 +37,8 @@
 # the COPYING file in the top-level directory.
 
 import argparse
+import asyncio
 import base64
-import errno
 import os
 import random
 import sys
@@ -50,8 +50,8 @@
 Sequence,
 )
 
-from qemu import qmp
-from qemu.qmp import SocketAddrT
+from qemu.aqmp import ConnectError, SocketAddrT
+from qemu.aqmp.legacy import QEMUMonitorProtocol
 
 
 # This script has not seen many patches or careful attention in quite
@@ -61,7 +61,7 @@
 # pylint: disable=missing-docstring
 
 
-class QemuGuestAgent(qmp.QEMUMonitorProtocol):
+class QemuGuestAgent(QEMUMonitorProtocol):
 def __getattr__(self, name: str) -> Callable[..., Any]:
 def wrapper(**kwds: object) -> object:
 return self.command('guest-' + name.replace('_', '-'), **kwds)
@@ -149,7 +149,7 @@ def ping(self, timeout: Optional[float]) -> bool:
 self.qga.settimeout(timeout)
 try:
 self.qga.ping()
-except TimeoutError:
+except asyncio.TimeoutError:
 return False
 return True
 
@@ -172,7 +172,7 @@ def suspend(self, mode: str) -> None:
 try:
 getattr(self.qga, 'suspend' + '_' + mode)()
 # On error exception will raise
-except TimeoutError:
+except asyncio.TimeoutError:
 # On success command will timed out
 return
 
@@ -182,7 +182,7 @@ def shutdown(self, mode: str = 'powerdown') -> None:
 
 try:
 self.qga.shutdown(mode=mode)
-except TimeoutError:
+except asyncio.TimeoutError:
 pass
 
 
@@ -277,7 +277,7 @@ def _cmd_reboot(client: QemuGuestAgentClient, args: 
Sequence[str]) -> None:
 
 def send_command(address: str, cmd: str, args: Sequence[str]) -> None:
 if not os.path.exists(address):
-print('%s not found' % address)
+print(f"'{address}' not found. (Is QEMU running?)")
 sys.exit(1)
 
 if cmd not in commands:
@@ -287,10 +287,10 @@ def send_command(address: str, cmd: str, args: 
Sequence[str]) -> None:
 
 try:
 client = QemuGuestAgentClient(address)
-except OSError as err:
+except ConnectError as err:
 print(err)
-if err.errno == errno.ECONNREFUSED:
-print('Hint: qemu is not running?')
+if isinstance(err.exc, ConnectionError):
+print('(Is QEMU running?)')
 sys.exit(1)
 
 if cmd == 'fsfreeze' and args[0] == 'freeze':
-- 
2.31.1




[PATCH 16/23] iotests/mirror-top-perms: switch to AQMP

2021-11-24 Thread John Snow
Signed-off-by: John Snow 

---

Note: I still need to adjust the logging. The problem now is that the
logging messages include the PID of the test process, so they need to be
filtered out. I'll investigate that for a follow-up, or for v2.

I could just add yet another filtering function somewhere, but I think
it's getting out of hand with how many filters and loggers there are, so
I want to give it a slightly more serious treatment instead of a
hackjob.

Signed-off-by: John Snow 
---
 tests/qemu-iotests/tests/mirror-top-perms | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/tests/qemu-iotests/tests/mirror-top-perms 
b/tests/qemu-iotests/tests/mirror-top-perms
index 0a51a613f3..f394931a00 100755
--- a/tests/qemu-iotests/tests/mirror-top-perms
+++ b/tests/qemu-iotests/tests/mirror-top-perms
@@ -23,7 +23,6 @@ import os
 
 from qemu.aqmp import ConnectError
 from qemu.machine import machine
-from qemu.qmp import QMPConnectError
 
 import iotests
 from iotests import change_log_level, qemu_img
@@ -101,13 +100,13 @@ class TestMirrorTopPerms(iotests.QMPTestCase):
 self.vm_b.add_device('virtio-blk,drive=drive0,share-rw=on')
 try:
 # Silence AQMP errors temporarily.
-# TODO: Remove this and just allow the errors to be logged when
-# AQMP fully replaces QMP.
+# TODO: Remove change_log_level and allow the errors to be logged.
+#   This necessitates a PID filter on *all* logging output.
 with change_log_level('qemu.aqmp'):
 self.vm_b.launch()
 print('ERROR: VM B launched successfully, '
   'this should not have happened')
-except (QMPConnectError, ConnectError):
+except ConnectError:
 assert 'Is another process using the image' in self.vm_b.get_log()
 
 result = self.vm.qmp('block-job-cancel',
-- 
2.31.1




[PATCH 10/23] python: move qmp-shell under the AQMP package

2021-11-24 Thread John Snow
Signed-off-by: John Snow 
---
 python/README.rst  | 2 +-
 python/qemu/{qmp => aqmp}/qmp_shell.py | 0
 python/setup.cfg   | 2 +-
 scripts/qmp/qmp-shell  | 2 +-
 4 files changed, 3 insertions(+), 3 deletions(-)
 rename python/qemu/{qmp => aqmp}/qmp_shell.py (100%)

diff --git a/python/README.rst b/python/README.rst
index 9c1fceaee7..fcf74f69ea 100644
--- a/python/README.rst
+++ b/python/README.rst
@@ -59,7 +59,7 @@ Package installation also normally provides executable 
console scripts,
 so that tools like ``qmp-shell`` are always available via $PATH. To
 invoke them without installation, you can invoke e.g.:
 
-``> PYTHONPATH=~/src/qemu/python python3 -m qemu.qmp.qmp_shell``
+``> PYTHONPATH=~/src/qemu/python python3 -m qemu.aqmp.qmp_shell``
 
 The mappings between console script name and python module path can be
 found in ``setup.cfg``.
diff --git a/python/qemu/qmp/qmp_shell.py b/python/qemu/aqmp/qmp_shell.py
similarity index 100%
rename from python/qemu/qmp/qmp_shell.py
rename to python/qemu/aqmp/qmp_shell.py
diff --git a/python/setup.cfg b/python/setup.cfg
index 78421411d2..168a79c867 100644
--- a/python/setup.cfg
+++ b/python/setup.cfg
@@ -67,7 +67,7 @@ console_scripts =
 qom-tree = qemu.utils.qom:QOMTree.entry_point
 qom-fuse = qemu.utils.qom_fuse:QOMFuse.entry_point [fuse]
 qemu-ga-client = qemu.utils.qemu_ga_client:main
-qmp-shell = qemu.qmp.qmp_shell:main
+qmp-shell = qemu.aqmp.qmp_shell:main
 aqmp-tui = qemu.aqmp.aqmp_tui:main [tui]
 
 [flake8]
diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index 4a20f97db7..31b19d73e2 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -4,7 +4,7 @@ import os
 import sys
 
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
-from qemu.qmp import qmp_shell
+from qemu.aqmp import qmp_shell
 
 
 if __name__ == '__main__':
-- 
2.31.1




[PATCH 03/23] python/aqmp: copy type definitions from qmp

2021-11-24 Thread John Snow
Copy the remaining type definitions from QMP into the qemu.aqmp.legacy
module. Now, most users don't need to import anything else but
qemu.aqmp.legacy.

Signed-off-by: John Snow 
---
 python/qemu/aqmp/legacy.py   | 22 --
 python/qemu/aqmp/protocol.py | 16 ++--
 2 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/python/qemu/aqmp/legacy.py b/python/qemu/aqmp/legacy.py
index 2ccb136b02..9431fe9330 100644
--- a/python/qemu/aqmp/legacy.py
+++ b/python/qemu/aqmp/legacy.py
@@ -6,7 +6,9 @@
 
 import asyncio
 from typing import (
+Any,
 Awaitable,
+Dict,
 List,
 Optional,
 TypeVar,
@@ -14,13 +16,29 @@
 )
 
 import qemu.qmp
-from qemu.qmp import QMPMessage, QMPReturnValue, SocketAddrT
 
 from .error import AQMPError
-from .protocol import Runstate
+from .protocol import Runstate, SocketAddrT
 from .qmp_client import QMPClient
 
 
+#: QMPMessage is an entire QMP message of any kind.
+QMPMessage = Dict[str, Any]
+
+#: QMPReturnValue is the 'return' value of a command.
+QMPReturnValue = object
+
+#: QMPObject is any object in a QMP message.
+QMPObject = Dict[str, object]
+
+# QMPMessage can be outgoing commands or incoming events/returns.
+# QMPReturnValue is usually a dict/json object, but due to QAPI's
+# 'returns-whitelist', it can actually be anything.
+#
+# {'return': {}} is a QMPMessage,
+# {} is the QMPReturnValue.
+
+
 # pylint: disable=missing-docstring
 
 
diff --git a/python/qemu/aqmp/protocol.py b/python/qemu/aqmp/protocol.py
index 5190b33b13..42a897e2fe 100644
--- a/python/qemu/aqmp/protocol.py
+++ b/python/qemu/aqmp/protocol.py
@@ -46,6 +46,10 @@
 _TaskFN = Callable[[], Awaitable[None]]  # aka ``async def func() -> None``
 _FutureT = TypeVar('_FutureT', bound=Optional['asyncio.Future[Any]'])
 
+InternetAddrT = Tuple[str, int]
+UnixAddrT = str
+SocketAddrT = Union[UnixAddrT, InternetAddrT]
+
 
 class Runstate(Enum):
 """Protocol session runstate."""
@@ -257,7 +261,7 @@ async def runstate_changed(self) -> Runstate:
 
 @upper_half
 @require(Runstate.IDLE)
-async def accept(self, address: Union[str, Tuple[str, int]],
+async def accept(self, address: SocketAddrT,
  ssl: Optional[SSLContext] = None) -> None:
 """
 Accept a connection and begin processing message queues.
@@ -275,7 +279,7 @@ async def accept(self, address: Union[str, Tuple[str, int]],
 
 @upper_half
 @require(Runstate.IDLE)
-async def connect(self, address: Union[str, Tuple[str, int]],
+async def connect(self, address: SocketAddrT,
   ssl: Optional[SSLContext] = None) -> None:
 """
 Connect to the server and begin processing message queues.
@@ -337,7 +341,7 @@ def _set_state(self, state: Runstate) -> None:
 
 @upper_half
 async def _new_session(self,
-   address: Union[str, Tuple[str, int]],
+   address: SocketAddrT,
ssl: Optional[SSLContext] = None,
accept: bool = False) -> None:
 """
@@ -397,7 +401,7 @@ async def _new_session(self,
 @upper_half
 async def _establish_connection(
 self,
-address: Union[str, Tuple[str, int]],
+address: SocketAddrT,
 ssl: Optional[SSLContext] = None,
 accept: bool = False
 ) -> None:
@@ -424,7 +428,7 @@ async def _establish_connection(
 await self._do_connect(address, ssl)
 
 @upper_half
-async def _do_accept(self, address: Union[str, Tuple[str, int]],
+async def _do_accept(self, address: SocketAddrT,
  ssl: Optional[SSLContext] = None) -> None:
 """
 Acting as the transport server, accept a single connection.
@@ -482,7 +486,7 @@ async def _client_connected_cb(reader: asyncio.StreamReader,
 self.logger.debug("Connection accepted.")
 
 @upper_half
-async def _do_connect(self, address: Union[str, Tuple[str, int]],
+async def _do_connect(self, address: SocketAddrT,
   ssl: Optional[SSLContext] = None) -> None:
 """
 Acting as the transport client, initiate a connection to a server.
-- 
2.31.1




[PATCH 11/23] python/machine: permanently switch to AQMP

2021-11-24 Thread John Snow
Remove the QEMU_PYTHON_LEGACY_QMP environment variable, making the
switch permanent. Update Exceptions and import paths as necessary.

Signed-off-by: John Snow 
---
 python/qemu/machine/machine.py | 18 +++---
 python/qemu/machine/qtest.py   |  2 +-
 2 files changed, 8 insertions(+), 12 deletions(-)

diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
index 67ab06ca2b..21fb4a4f30 100644
--- a/python/qemu/machine/machine.py
+++ b/python/qemu/machine/machine.py
@@ -40,21 +40,16 @@
 TypeVar,
 )
 
-from qemu.qmp import (  # pylint: disable=import-error
+from qemu.aqmp import SocketAddrT
+from qemu.aqmp.legacy import (
+QEMUMonitorProtocol,
 QMPMessage,
 QMPReturnValue,
-SocketAddrT,
 )
 
 from . import console_socket
 
 
-if os.environ.get('QEMU_PYTHON_LEGACY_QMP'):
-from qemu.qmp import QEMUMonitorProtocol
-else:
-from qemu.aqmp.legacy import QEMUMonitorProtocol
-
-
 LOG = logging.getLogger(__name__)
 
 
@@ -710,8 +705,9 @@ def events_wait(self,
 :param timeout: Optional timeout, in seconds.
 See QEMUMonitorProtocol.pull_event.
 
-:raise QMPTimeoutError: If timeout was non-zero and no matching events
-were found.
+:raise asyncio.TimeoutError:
+If timeout was non-zero and no matching events were found.
+
 :return: A QMP event matching the filter criteria.
  If timeout was 0 and no event matched, None.
 """
@@ -734,7 +730,7 @@ def _match(event: QMPMessage) -> bool:
 event = self._qmp.pull_event(wait=timeout)
 if event is None:
 # NB: None is only returned when timeout is false-ish.
-# Timeouts raise QMPTimeoutError instead!
+# Timeouts raise asyncio.TimeoutError instead!
 break
 if _match(event):
 return event
diff --git a/python/qemu/machine/qtest.py b/python/qemu/machine/qtest.py
index f2f9aaa5e5..817c8a5425 100644
--- a/python/qemu/machine/qtest.py
+++ b/python/qemu/machine/qtest.py
@@ -26,7 +26,7 @@
 TextIO,
 )
 
-from qemu.qmp import SocketAddrT  # pylint: disable=import-error
+from qemu.aqmp.protocol import SocketAddrT
 
 from .machine import QEMUMachine
 
-- 
2.31.1




[PATCH 04/23] python/aqmp: add SocketAddrT to package root

2021-11-24 Thread John Snow
It's a commonly needed definition, it can be re-exported by the root.

Signed-off-by: John Snow 
---
 python/qemu/aqmp/__init__.py | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/python/qemu/aqmp/__init__.py b/python/qemu/aqmp/__init__.py
index 880d5b6fa7..c6fa2dda58 100644
--- a/python/qemu/aqmp/__init__.py
+++ b/python/qemu/aqmp/__init__.py
@@ -26,7 +26,12 @@
 from .error import AQMPError
 from .events import EventListener
 from .message import Message
-from .protocol import ConnectError, Runstate, StateError
+from .protocol import (
+ConnectError,
+Runstate,
+SocketAddrT,
+StateError,
+)
 from .qmp_client import ExecInterruptedError, ExecuteError, QMPClient
 
 
@@ -48,4 +53,7 @@
 'ConnectError',
 'ExecuteError',
 'ExecInterruptedError',
+
+# Type aliases
+'SocketAddrT',
 )
-- 
2.31.1




[PATCH 02/23] python/aqmp: handle asyncio.TimeoutError on execute()

2021-11-24 Thread John Snow
This exception can be injected into any await statement. If we are
canceled via timeout, we want to clear the pending execution record on
our way out.

Signed-off-by: John Snow 
---
 python/qemu/aqmp/qmp_client.py | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/python/qemu/aqmp/qmp_client.py b/python/qemu/aqmp/qmp_client.py
index 8105e29fa8..6a985ffe30 100644
--- a/python/qemu/aqmp/qmp_client.py
+++ b/python/qemu/aqmp/qmp_client.py
@@ -435,7 +435,11 @@ async def _issue(self, msg: Message) -> Union[None, str]:
 msg_id = msg['id']
 
 self._pending[msg_id] = asyncio.Queue(maxsize=1)
-await self._outgoing.put(msg)
+try:
+await self._outgoing.put(msg)
+except:
+del self._pending[msg_id]
+raise
 
 return msg_id
 
@@ -452,9 +456,9 @@ async def _reply(self, msg_id: Union[str, None]) -> Message:
 was lost, or some other problem.
 """
 queue = self._pending[msg_id]
-result = await queue.get()
 
 try:
+result = await queue.get()
 if isinstance(result, ExecInterruptedError):
 raise result
 return result
-- 
2.31.1




[PATCH 05/23] python/qemu-ga-client: update instructions to newer CLI syntax

2021-11-24 Thread John Snow
Signed-off-by: John Snow 
---
 python/qemu/qmp/qemu_ga_client.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python/qemu/qmp/qemu_ga_client.py 
b/python/qemu/qmp/qemu_ga_client.py
index 67ac0b4211..b3e1d98c9e 100644
--- a/python/qemu/qmp/qemu_ga_client.py
+++ b/python/qemu/qmp/qemu_ga_client.py
@@ -5,7 +5,7 @@
 
 Start QEMU with:
 
-# qemu [...] -chardev socket,path=/tmp/qga.sock,server,wait=off,id=qga0 \
+# qemu [...] -chardev socket,path=/tmp/qga.sock,server=on,wait=off,id=qga0 \
   -device virtio-serial \
   -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0
 
-- 
2.31.1




[PATCH 01/23] python/aqmp: add __del__ method to legacy interface

2021-11-24 Thread John Snow
asyncio can complain *very* loudly if you forget to back out of things
gracefully before the garbage collector starts destroying objects that
contain live references to asyncio Tasks.

The usual fix is just to remember to call aqmp.disconnect(), but for the
sake of the legacy wrapper and quick, one-off scripts where a graceful
shutdown is not necessarily of paramount imporance, add a courtesy
cleanup that will trigger prior to seeing screenfuls of confusing
asyncio tracebacks.

Note that we can't *always* save you from yourself; depending on when
the GC runs, you might just seriously be out of luck. The best we can do
in this case is to gently remind you to clean up after yourself.

(Still much better than multiple pages of incomprehensible python
warnings for the crime of forgetting to put your toys away.)

Signed-off-by: John Snow 
---
 python/qemu/aqmp/legacy.py | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/python/qemu/aqmp/legacy.py b/python/qemu/aqmp/legacy.py
index 9e7b9fb80b..2ccb136b02 100644
--- a/python/qemu/aqmp/legacy.py
+++ b/python/qemu/aqmp/legacy.py
@@ -16,6 +16,8 @@
 import qemu.qmp
 from qemu.qmp import QMPMessage, QMPReturnValue, SocketAddrT
 
+from .error import AQMPError
+from .protocol import Runstate
 from .qmp_client import QMPClient
 
 
@@ -136,3 +138,19 @@ def settimeout(self, timeout: Optional[float]) -> None:
 
 def send_fd_scm(self, fd: int) -> None:
 self._aqmp.send_fd_scm(fd)
+
+def __del__(self) -> None:
+if self._aqmp.runstate == Runstate.IDLE:
+return
+
+if not self._aloop.is_running():
+self.close()
+else:
+# Garbage collection ran while the event loop was running.
+# Nothing we can do about it now, but if we don't raise our
+# own error, the user will be treated to a lot of traceback
+# they might not understand.
+raise AQMPError(
+"QEMUMonitorProtocol.close()"
+" was not called before object was garbage collected"
+)
-- 
2.31.1




[PATCH 00/23] Python: delete qemu.qmp package

2021-11-24 Thread John Snow
GitLab: https://gitlab.com/jsnow/qemu/-/commits/python-qmp-legacy-switch
CI: https://gitlab.com/jsnow/qemu/-/pipelines/415801786

NOT intended for 6.2.

This series swaps out qemu.qmp for qemu.aqmp permanently, instead of
hiding it behind an environment variable toggle. This leaves us with
just one QMP library to worry about.

The series is organized like this:

- 01-02: Fixes and improvements to Async QMP
- 03-11: Switch python/* users to use AQMP exclusively
- 12-17: Switch other users to use AQMP exclusively
- 18-23: Finalize the switchover, delete python/qemu/qmp.

Optional notes about the broader process of moving Python infrastructure
onto PyPI are below, though it isn't required reading for reviewing this
series. Consider it a newsletter from the Python dungeon:

I was asked what the timeline for actually uploading anything to PyPI
was. This series is part of my answer, but the steps look like this:

Phase I:
- Refactor everything in-tree to be a bona-fide python package  [Done]
- Add unit testing and CI for all QEMU python packages  [Done]
- Develop a version of QMP intended for public support via PyPI [Done]

Phase II:
- Switch machine.py and iotests to using async QMP by default   [Done]
- Fix bugs in qemu.aqmp discovered during RC testing   [Ongoing]
- Remove qemu.qmp in favor of qemu.aqmp[This Series]
- Rename qemu.aqmp back to qemu.qmp
- Add a proper "sync" version of qemu.aqmp.QMPClient   [In Progress]
  designed to be more supportable via PyPI
  current status: it's functional, but there are some FIXMEs.
- Pivot in-tree users of qemu.(a)qmp.legacy to qemu.qmp.sync,
  -OR- move the "legacy" wrapper outside of the qmp package and into utils.
  (The goal is simply to avoid uploading the legacy wrapper to PyPI.)

Phase III:
- Fork python/qemu/qmp into its own git repo, with its own pkg version
- Add sphinx doc generation to qemu.qmp repo and add readthedocs integration
  [Doc generation is 95% done on a branch, needs polish. RTD is untouched.]
- Convert in-tree users of qemu.qmp to pull the dependency from either
  PyPI or a git URL. I think I'd like to avoid using git submodules ...

That's broadly it. There's some code to do for the sync bridge to make
the design tidier, but the goal there is to move a lot of the QMP event
wrangling functions we have scattered across qmp, machine, and even
iotests into a more central location with much stronger support.

A lot of this will hopefully move pretty fast once the tree re-opens.

One of the remaining skeletons in the closet that I have not yet fully
addressed is how I will be moving remaining in-tree users of the QMP
package onto a PyPI dependency. That's probably where most of the work
will actually be; adding a python virtual environment to iotests et al.

John Snow (23):
  python/aqmp: add __del__ method to legacy interface
  python/aqmp: handle asyncio.TimeoutError on execute()
  python/aqmp: copy type definitions from qmp
  python/aqmp: add SocketAddrT to package root
  python/qemu-ga-client: update instructions to newer CLI syntax
  python/qmp: switch qemu-ga-client to AQMP
  python/qmp: switch qom tools to AQMP
  python/qmp: switch qmp-shell to AQMP
  python: move qmp utilities to python/qemu/utils
  python: move qmp-shell under the AQMP package
  python/machine: permanently switch to AQMP
  scripts/cpu-x86-uarch-abi: fix CLI parsing
  scripts/cpu-x86-uarch-abi: switch to AQMP
  scripts/render-block-graph: switch to AQMP
  scripts/bench-block-job: switch to AQMP
  iotests/mirror-top-perms: switch to AQMP
  iotests: switch to AQMP
  python: temporarily silence pylint duplicate-code warnings
  python/aqmp: take QMPBadPortError and parse_address from qemu.qmp
  python/aqmp: fully separate from qmp.QEMUMonitorProtocol
  python/aqmp: copy qmp docstrings to qemu.aqmp.legacy
  python: remove the old QMP package
  python: re-enable pylint duplicate-code warnings

 python/PACKAGE.rst   |   4 +-
 python/README.rst|   4 +-
 python/qemu/qmp/README.rst   |   9 -
 python/qemu/aqmp/__init__.py |  10 +-
 python/qemu/aqmp/aqmp_tui.py |   2 +-
 python/qemu/aqmp/legacy.py   | 203 -
 python/qemu/aqmp/protocol.py |  16 +-
 python/qemu/aqmp/qmp_client.py   |   8 +-
 python/qemu/{qmp => aqmp}/qmp_shell.py   |  31 +-
 python/qemu/machine/machine.py   |  18 +-
 python/qemu/machine/qtest.py |   2 +-
 python/qemu/qmp/__init__.py  | 422 ---
 python/qemu/qmp/py.typed |   0
 python/qemu/{qmp => utils}/qemu_ga_client.py |  24 +-
 python/qemu/{qmp => utils}/qom.py|   5 +-
 python/qemu/{qmp => utils}/qom_common.py |   7 +-
 python/qemu/{qmp => utils}/qom_fuse.py   |  11 +-
 python/setup.cfg |  21 +-
 scripts/cpu-x86-uarch-abi.py |   7 +-
 

Re: [PATCH] target/ppc: fix Hash64 MMU update of PTE bit R

2021-11-24 Thread Leandro Lupori
​​

On 11/24/21 14:40, Daniel Henrique Barboza wrote:
>
>
> On 11/24/21 09:00, Leandro Lupori wrote:
>> When updating the R bit of a PTE, the Hash64 MMU was using a wrong byte
>> offset, causing the first byte of the adjacent PTE to be corrupted.
>> This caused a panic when booting FreeBSD, using the Hash MMU.

I wonder how we never hit this issue before. Are you testing PowerNV
and/or pSeries  ?

Could you share a FreeBDS image with us ?
​I've hit this issue while testing PowerNV. With pSeries it doesn't happen.

It can be reproduced by trying to boot this iso: 
https://download.freebsd.org/ftp/snapshots/powerpc/powerpc64/ISO-IMAGES/14.0/FreeBSD-14.0-CURRENT-powerpc-powerpc64-20211028-4827bf76bce-250301-disc1.iso.xz

It is easier to reproduce it using power8/powernv8.
​
> If you add a "Fixes:" tag with the commit that introduced the code you're
> fixing, we can push it right away as a bug fix in 6.2 (assuming it doesn't
> break anything else, of course).
>
> The commit to be fixed in the case seems to be a2dd4e83e76b ("ppc/hash64:
> Rework R and C bit updates")

Indeed.
​​Right.

> One more comment below:
>
>>
>> Signed-off-by: Leandro Lupori 
>> ---
>>   target/ppc/mmu-hash64.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
>> index 19832c4b46..f165ac691a 100644
>> --- a/target/ppc/mmu-hash64.c
>> +++ b/target/ppc/mmu-hash64.c
>> @@ -786,7 +786,7 @@ static void ppc_hash64_set_dsi(CPUState *cs, int 
>> mmu_idx, uint64_t dar, uint64_t
>>   static void ppc_hash64_set_r(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte1)
>>   {
>> -hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 16;
>> +hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 14;
>
> Instead of adding a '14' you should add a new #define in mmu-hash64.h with 
> this
> value, something like "HPTE64_R_R_SHIFT". This will avoid hardcoding literals
> around the code and forcing us to go to the ISA every time we wonder what's
> an apparently random number represents. There's also a "HPTE64_R_R" defined
> there but I'm not sure if it's usable here, so feel free to create a new
> macro if needed.
>
> In that note, the original commit that added this code also added a lot of
> hardcoded "15" values for the C bit update in spapr_hpte_set_c() and
> ppc_hash64_set_c(), and a "14" value like you're changing here in 
> spapr_hpte_set_r().
> If you're feeling generous I believe that another patch replacing these 
> hardcoded values
> with bit shift macros is warranted as well.
​What about creating HPTE64_R_R_BYTE and HPTE64_R_C_BYTE, with the values 14 
and 15, respectively,
to make it clear that these are byte offsets within a PTE?

May be for 7.0 though ?

Thanks,

C.



Re: [PATCH v2 04/11] 9p: darwin: Handle struct dirent differences

2021-11-24 Thread Christian Schoenebeck
On Mittwoch, 24. November 2021 16:45:30 CET Michael Roitzsch wrote:
> Hi,
> 
> > Are you sure d_seekoff doesn't work on macOS?
> 
> I just tried on an APFS volume on macOS Monterey and d_seekoff is always 0,
> while telldir() outputs useful values.
> > Because using telldir() instead
> > is not the same thing. Accessing d_*off is just POD access, whereas
> > telldir() is a syscall.
> 
> I am not sure this is the case. I have tried a quick test program:
> 
> #include 
> 
> int main(void)
> {
>   int result = 0;
>   DIR *dir = opendir(".");
>   while (readdir(dir)) {
>   result += telldir(dir);
>   }
>   closedir(dir);
>   return result;
> }
> 
> I ran it with 'sudo dtruss ./test', which should give me a trace of the
> system calls. The relevant portion is:
> 
> open_nocancel(".\0", 0x114, 0x0)   = 3 0
> sysctlbyname(kern.secure_kernel, 0x12, 0x7FF7BE49810C, 0x7FF7BE498110,
> 0x0)   = 0 0 fstatfs64(0x3, 0x7FF7BE498110, 0x0)   = 0 0
> getdirentries64(0x3, 0x7FF4A5808A00, 0x2000)   = 1472 0
> close_nocancel(0x3)= 0 0
> 
> The directory has more than 30 entries, but the loop does not appear to
> cause individual system calls. Instead, readdir() and telldir() appear to
> be library functions powered by this getdirentries64 syscall.

Right, telldir() is part of Apple's libc, no (fs) syscall involved:
https://opensource.apple.com/source/Libc/Libc-167/gen.subproj/telldir.c.auto.html

However instead of changing the (fs driver independent) 9p server [9p.c] code
and using fidp there, I would probably rather address this issue for macOS in
the individual fs drivers [9p-local.c, 9p-synth.c, 9p-proxy.c] directly on
dirent instead, and not rely on fidp not having mutated on server.

And please make sure the 9p test cases pass.

Best regards,
Christian Schoenebeck





Re: [PATCH v3 01/23] multifd: Delete useless operation

2021-11-24 Thread Dr. David Alan Gilbert
* Juan Quintela (quint...@redhat.com) wrote:
> We are divining by page_size to multiply again in the only use.
 ^--- typo
> Once there, impreve the comments.
  ^--- typo
> 
> Signed-off-by: Juan Quintela 

OK, with the typo's fixed:

Reviewed-by: Dr. David Alan Gilbert 

but, could you also explain the  x 2 (that's no worse than the current
code); is this defined somewhere in zlib?  I thought there was a routine
that told you the worst case?

Dave
> ---
>  migration/multifd-zlib.c | 13 -
>  migration/multifd-zstd.c | 13 -
>  2 files changed, 8 insertions(+), 18 deletions(-)
> 
> diff --git a/migration/multifd-zlib.c b/migration/multifd-zlib.c
> index ab4ba75d75..3fc7813b44 100644
> --- a/migration/multifd-zlib.c
> +++ b/migration/multifd-zlib.c
> @@ -42,7 +42,6 @@ struct zlib_data {
>   */
>  static int zlib_send_setup(MultiFDSendParams *p, Error **errp)
>  {
> -uint32_t page_count = MULTIFD_PACKET_SIZE / qemu_target_page_size();
>  struct zlib_data *z = g_malloc0(sizeof(struct zlib_data));
>  z_stream *zs = >zs;
>  
> @@ -54,9 +53,8 @@ static int zlib_send_setup(MultiFDSendParams *p, Error 
> **errp)
>  error_setg(errp, "multifd %d: deflate init failed", p->id);
>  return -1;
>  }
> -/* We will never have more than page_count pages */
> -z->zbuff_len = page_count * qemu_target_page_size();
> -z->zbuff_len *= 2;
> +/* To be safe, we reserve twice the size of the packet */
> +z->zbuff_len = MULTIFD_PACKET_SIZE * 2;
>  z->zbuff = g_try_malloc(z->zbuff_len);
>  if (!z->zbuff) {
>  deflateEnd(>zs);
> @@ -180,7 +178,6 @@ static int zlib_send_write(MultiFDSendParams *p, uint32_t 
> used, Error **errp)
>   */
>  static int zlib_recv_setup(MultiFDRecvParams *p, Error **errp)
>  {
> -uint32_t page_count = MULTIFD_PACKET_SIZE / qemu_target_page_size();
>  struct zlib_data *z = g_malloc0(sizeof(struct zlib_data));
>  z_stream *zs = >zs;
>  
> @@ -194,10 +191,8 @@ static int zlib_recv_setup(MultiFDRecvParams *p, Error 
> **errp)
>  error_setg(errp, "multifd %d: inflate init failed", p->id);
>  return -1;
>  }
> -/* We will never have more than page_count pages */
> -z->zbuff_len = page_count * qemu_target_page_size();
> -/* We know compression "could" use more space */
> -z->zbuff_len *= 2;
> +/* To be safe, we reserve twice the size of the packet */
> +z->zbuff_len = MULTIFD_PACKET_SIZE * 2;
>  z->zbuff = g_try_malloc(z->zbuff_len);
>  if (!z->zbuff) {
>  inflateEnd(zs);
> diff --git a/migration/multifd-zstd.c b/migration/multifd-zstd.c
> index 693bddf8c9..cc3b8869c0 100644
> --- a/migration/multifd-zstd.c
> +++ b/migration/multifd-zstd.c
> @@ -47,7 +47,6 @@ struct zstd_data {
>   */
>  static int zstd_send_setup(MultiFDSendParams *p, Error **errp)
>  {
> -uint32_t page_count = MULTIFD_PACKET_SIZE / qemu_target_page_size();
>  struct zstd_data *z = g_new0(struct zstd_data, 1);
>  int res;
>  
> @@ -67,9 +66,8 @@ static int zstd_send_setup(MultiFDSendParams *p, Error 
> **errp)
> p->id, ZSTD_getErrorName(res));
>  return -1;
>  }
> -/* We will never have more than page_count pages */
> -z->zbuff_len = page_count * qemu_target_page_size();
> -z->zbuff_len *= 2;
> +/* To be safe, we reserve twice the size of the packet */
> +z->zbuff_len = MULTIFD_PACKET_SIZE * 2;
>  z->zbuff = g_try_malloc(z->zbuff_len);
>  if (!z->zbuff) {
>  ZSTD_freeCStream(z->zcs);
> @@ -191,7 +189,6 @@ static int zstd_send_write(MultiFDSendParams *p, uint32_t 
> used, Error **errp)
>   */
>  static int zstd_recv_setup(MultiFDRecvParams *p, Error **errp)
>  {
> -uint32_t page_count = MULTIFD_PACKET_SIZE / qemu_target_page_size();
>  struct zstd_data *z = g_new0(struct zstd_data, 1);
>  int ret;
>  
> @@ -212,10 +209,8 @@ static int zstd_recv_setup(MultiFDRecvParams *p, Error 
> **errp)
>  return -1;
>  }
>  
> -/* We will never have more than page_count pages */
> -z->zbuff_len = page_count * qemu_target_page_size();
> -/* We know compression "could" use more space */
> -z->zbuff_len *= 2;
> +/* To be safe, we reserve twice the size of the packet */
> +z->zbuff_len = MULTIFD_PACKET_SIZE * 2;
>  z->zbuff = g_try_malloc(z->zbuff_len);
>  if (!z->zbuff) {
>  ZSTD_freeDStream(z->zds);
> -- 
> 2.33.1
> 
-- 
Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK




Re: [PATCH] target/ppc: fix Hash64 MMU update of PTE bit R

2021-11-24 Thread Daniel Henrique Barboza




On 11/24/21 15:42, Cédric Le Goater wrote:

On 11/24/21 14:40, Daniel Henrique Barboza wrote:



On 11/24/21 09:00, Leandro Lupori wrote:

When updating the R bit of a PTE, the Hash64 MMU was using a wrong byte
offset, causing the first byte of the adjacent PTE to be corrupted.
This caused a panic when booting FreeBSD, using the Hash MMU.


I wonder how we never hit this issue before. Are you testing PowerNV
and/or pSeries  ?

Could you share a FreeBDS image with us ?


If you add a "Fixes:" tag with the commit that introduced the code you're
fixing, we can push it right away as a bug fix in 6.2 (assuming it doesn't
break anything else, of course).

The commit to be fixed in the case seems to be a2dd4e83e76b ("ppc/hash64:
Rework R and C bit updates")


Indeed.


One more comment below:



Signed-off-by: Leandro Lupori 
---
  target/ppc/mmu-hash64.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index 19832c4b46..f165ac691a 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -786,7 +786,7 @@ static void ppc_hash64_set_dsi(CPUState *cs, int mmu_idx, 
uint64_t dar, uint64_t
  static void ppc_hash64_set_r(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte1)
  {
-    hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 16;
+    hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 14;


Instead of adding a '14' you should add a new #define in mmu-hash64.h with this
value, something like "HPTE64_R_R_SHIFT". This will avoid hardcoding literals
around the code and forcing us to go to the ISA every time we wonder what's
an apparently random number represents. There's also a "HPTE64_R_R" defined
there but I'm not sure if it's usable here, so feel free to create a new
macro if needed.

In that note, the original commit that added this code also added a lot of
hardcoded "15" values for the C bit update in spapr_hpte_set_c() and
ppc_hash64_set_c(), and a "14" value like you're changing here in 
spapr_hpte_set_r().
If you're feeling generous I believe that another patch replacing these 
hardcoded values
with bit shift macros is warranted as well.


May be for 7.0 though ?



Yeah, this extra cleanup I proposed can be postponed to 7.0 in case someone 
wants
to give it a go.


Daniel





Thanks,

C.





Re: [PATCH] target/ppc: fix Hash64 MMU update of PTE bit R

2021-11-24 Thread Cédric Le Goater

On 11/24/21 14:40, Daniel Henrique Barboza wrote:



On 11/24/21 09:00, Leandro Lupori wrote:

When updating the R bit of a PTE, the Hash64 MMU was using a wrong byte
offset, causing the first byte of the adjacent PTE to be corrupted.
This caused a panic when booting FreeBSD, using the Hash MMU.


I wonder how we never hit this issue before. Are you testing PowerNV
and/or pSeries  ?

Could you share a FreeBDS image with us ?


If you add a "Fixes:" tag with the commit that introduced the code you're
fixing, we can push it right away as a bug fix in 6.2 (assuming it doesn't
break anything else, of course).

The commit to be fixed in the case seems to be a2dd4e83e76b ("ppc/hash64:
Rework R and C bit updates")


Indeed.


One more comment below:



Signed-off-by: Leandro Lupori 
---
  target/ppc/mmu-hash64.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index 19832c4b46..f165ac691a 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -786,7 +786,7 @@ static void ppc_hash64_set_dsi(CPUState *cs, int mmu_idx, 
uint64_t dar, uint64_t
  static void ppc_hash64_set_r(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte1)
  {
-    hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 16;
+    hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 14;


Instead of adding a '14' you should add a new #define in mmu-hash64.h with this
value, something like "HPTE64_R_R_SHIFT". This will avoid hardcoding literals
around the code and forcing us to go to the ISA every time we wonder what's
an apparently random number represents. There's also a "HPTE64_R_R" defined
there but I'm not sure if it's usable here, so feel free to create a new
macro if needed.

In that note, the original commit that added this code also added a lot of
hardcoded "15" values for the C bit update in spapr_hpte_set_c() and
ppc_hash64_set_c(), and a "14" value like you're changing here in 
spapr_hpte_set_r().
If you're feeling generous I believe that another patch replacing these 
hardcoded values
with bit shift macros is warranted as well.


May be for 7.0 though ?

Thanks,

C.




Re: [RFC PATCH v3] hw/nvme:Adding Support for namespace management

2021-11-24 Thread Lukasz Maniak
On Tue, Nov 23, 2021 at 11:11:37AM +0100, Lukasz Maniak wrote:
> On Wed, Nov 10, 2021 at 04:56:29PM +0530, Naveen wrote:
> > From: Naveen Nagar 
> > 
> > This patch supports namespace management : create and delete operations
> > This patch has been tested with the following command and size of image
> > file for unallocated namespaces is taken as 0GB. ns_create will look into
> > the list of unallocated namespaces and it will initialize the same and 
> > return the nsid of the same. A new mandatory field has been added called
> > tnvmcap and we have ensured that the total capacity of namespace created
> > does not exceed tnvmcap
> > 
> > -device nvme-subsys,id=subsys0,tnvmcap=8
> > -device nvme,serial=foo,id=nvme0,subsys=subsys0
> > -device nvme,serial=bar,id=nvme1,subsys=subsys0
> > 
> > -drive id=ns1,file=ns1.img,if=none
> > -device nvme-ns,drive=ns1,bus=nvme0,nsid=1,zoned=false,shared=true
> > -drive id=ns2,file=ns2.img,if=none
> > -device nvme-ns,drive=ns2,bus=nvme0,nsid=2,zoned=false,shared=true
> > -drive id=ns3,file=ns3.img,if=none
> > -device nvme-ns,drive=ns3,bus=nvme0,nsid=3,zoned=false,shared=true
> > -drive id=ns4,file=ns4.img,if=none
> > -device nvme-ns,drive=ns4,bus=nvme0,nsid=4,zoned=false,shared=true
> > 
> > Please review and suggest if any changes are required.
> > 
> > Signed-off-by: Naveen Nagar 
> > 
> > Since v2:
> > -Lukasz Maniak found a bug in namespace attachment and proposed 
> >  solution is added
> > 
> 
> Hi Naveen,
> 
> The current implementation is inconsistent and thus has a bug related to
> unvmcap support.
> 
> Namespaces are pre-allocated after boot, and the initial namespace size
> is the size of the associated blockdev. If the blockdevs are non-zero
> sized then the first deletion of the namespaces associated with them
> will increment unvmcap by their size. This will make unvmcap greater
> than tnvmcap.
> 
> While the easiest way would be to prohibit the use of non-zero sized
> blockdev with namespace management, doing so would limit the
> functionality of the namespaces itself, which we would like to avoid.
> 
> This fix below addresses issues related to unvmcap and non-zero block
> devices. The unvmcap value will be properly updated on both the first
> and subsequent controllers added to the subsystem regardless of the
> order in which nvme-ns is defined on the command line before or after
> the controller definition. Additionally, if the block device size of any
> namespace causes the unvmcap to be exceeded, an error will be returned
> at the namespace definition point.
> 
> The fix is based on v3 based on v6.1.0, as v3 does not apply to master.
> 
> ---
>  hw/nvme/ctrl.c |  7 +++
>  hw/nvme/ns.c   | 23 ---
>  2 files changed, 27 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
> index 63ea2fcb14..dc0ad4155b 100644
> --- a/hw/nvme/ctrl.c
> +++ b/hw/nvme/ctrl.c
> @@ -6594,6 +6594,7 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice 
> *pci_dev)
>  NvmeIdCtrl *id = >id_ctrl;
>  uint8_t *pci_conf = pci_dev->config;
>  uint64_t cap = ldq_le_p(>bar.cap);
> +int i;
>  
>  id->vid = cpu_to_le16(pci_get_word(pci_conf + PCI_VENDOR_ID));
>  id->ssvid = cpu_to_le16(pci_get_word(pci_conf + 
> PCI_SUBSYSTEM_VENDOR_ID));
> @@ -6672,6 +6673,12 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice 
> *pci_dev)
>  id->cmic |= NVME_CMIC_MULTI_CTRL;
>  id->tnvmcap = n->subsys->params.tnvmcap * GiB;
>  id->unvmcap = n->subsys->params.tnvmcap * GiB;
> +
> +for (i = 0; i < ARRAY_SIZE(n->subsys->namespaces); i++) {
> +if (n->subsys->namespaces[i]) {
> +id->unvmcap -= le64_to_cpu(n->subsys->namespaces[i]->size);
> +}
> +}
>  }
>  
>  NVME_CAP_SET_MQES(cap, 0x7ff);
> diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c
> index f62a695132..c87d7f5bd6 100644
> --- a/hw/nvme/ns.c
> +++ b/hw/nvme/ns.c
> @@ -140,9 +140,12 @@ lbaf_found:
>  return 0;
>  }
>  
> -static int nvme_ns_init_blk(NvmeNamespace *ns, Error **errp)
> +static int nvme_ns_init_blk(NvmeNamespace *ns, NvmeSubsystem *subsys,
> +Error **errp)
>  {
>  bool read_only;
> +NvmeCtrl *ctrl;
> +int i;
>  
>  if (!blkconf_blocksizes(>blkconf, errp)) {
>  return -1;
> @@ -164,6 +167,21 @@ static int nvme_ns_init_blk(NvmeNamespace *ns, Error 
> **errp)
>  return -1;
>  }
>  
> +if (subsys) {
> +for (i = 0; i < ARRAY_SIZE(subsys->ctrls); i++) {
> +ctrl = nvme_subsys_ctrl(subsys, i);
> +
> +if (ctrl) {
> +if (ctrl->id_ctrl.unvmcap < le64_to_cpu(ns->size)) {
> +error_setg(errp, "blockdev size %ld exceeds subsystem's "
> + "unallocated capacity", ns->size);
> +} else {
> +ctrl->id_ctrl.unvmcap -= le64_to_cpu(ns->size);
> +}
> +}
> +}
> +}

[PATCH for-7.0 v8 28/31] linux-user: Add safe syscall handling for loongarch64 hosts

2021-11-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 linux-user/host/loongarch64/hostdep.h | 14 
 .../host/loongarch64/safe-syscall.inc.S   | 80 +++
 2 files changed, 94 insertions(+)
 create mode 100644 linux-user/host/loongarch64/hostdep.h
 create mode 100644 linux-user/host/loongarch64/safe-syscall.inc.S

diff --git a/linux-user/host/loongarch64/hostdep.h 
b/linux-user/host/loongarch64/hostdep.h
new file mode 100644
index 00..4f692a68b9
--- /dev/null
+++ b/linux-user/host/loongarch64/hostdep.h
@@ -0,0 +1,14 @@
+/*
+ * hostdep.h : things which are dependent on the host architecture
+ *
+ * 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 LOONGARCH64_HOSTDEP_H
+#define LOONGARCH64_HOSTDEP_H
+
+/* We have a safe-syscall.inc.S */
+#define HAVE_SAFE_SYSCALL
+
+#endif
diff --git a/linux-user/host/loongarch64/safe-syscall.inc.S 
b/linux-user/host/loongarch64/safe-syscall.inc.S
new file mode 100644
index 00..bb530248b3
--- /dev/null
+++ b/linux-user/host/loongarch64/safe-syscall.inc.S
@@ -0,0 +1,80 @@
+/*
+ * safe-syscall.inc.S : host-specific assembly fragment
+ * to handle signals occurring at the same time as system calls.
+ * This is intended to be included by linux-user/safe-syscall.S
+ *
+ * Ported to LoongArch by WANG Xuerui 
+ *
+ * Based on safe-syscall.inc.S code for every other architecture,
+ * originally written by Richard Henderson 
+ * Copyright (C) 2018 Linaro, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+   .global safe_syscall_base
+   .global safe_syscall_start
+   .global safe_syscall_end
+   .type   safe_syscall_base, @function
+   .type   safe_syscall_start, @function
+   .type   safe_syscall_end, @function
+
+   /*
+* This is the entry point for making a system call. The calling
+* convention here is that of a C varargs function with the
+* first argument an 'int *' to the signal_pending flag, the
+* second one the system call number (as a 'long'), and all further
+* arguments being syscall arguments (also 'long').
+* We return a long which is the syscall's return value, which
+* may be negative-errno on failure. Conversion to the
+* -1-and-errno-set convention is done by the calling wrapper.
+*/
+safe_syscall_base:
+   .cfi_startproc
+   /*
+* The syscall calling convention is nearly the same as C:
+* we enter with a0 == *signal_pending
+*   a1 == syscall number
+*   a2 ... a7 == syscall arguments
+*   and return the result in a0
+* and the syscall instruction needs
+*   a7 == syscall number
+*   a0 ... a5 == syscall arguments
+*   and returns the result in a0
+* Shuffle everything around appropriately.
+*/
+   move$t0, $a0/* signal_pending pointer */
+   move$t1, $a1/* syscall number */
+   move$a0, $a2/* syscall arguments */
+   move$a1, $a3
+   move$a2, $a4
+   move$a3, $a5
+   move$a4, $a6
+   move$a5, $a7
+   move$a7, $t1
+
+   /*
+* This next sequence of code works in conjunction with the
+* rewind_if_safe_syscall_function(). If a signal is taken
+* and the interrupted PC is anywhere between 'safe_syscall_start'
+* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
+* The code sequence must therefore be able to cope with this, and
+* the syscall instruction must be the final one in the sequence.
+*/
+safe_syscall_start:
+   /* If signal_pending is non-zero, don't do the call */
+   ld.w$t1, $t0, 0
+   bnez$t1, 0f
+   syscall 0
+safe_syscall_end:
+   /* code path for having successfully executed the syscall */
+   jr  $ra
+
+0:
+   /* code path when we didn't execute the syscall */
+   li.w$a0, -TARGET_ERESTARTSYS
+   jr  $ra
+   .cfi_endproc
+
+   .size   safe_syscall_base, .-safe_syscall_base
-- 
2.34.0




[ANNOUNCE] QEMU 6.2.0-rc2 is now available

2021-11-24 Thread Michael Roth
Hello,

On behalf of the QEMU Team, I'd like to announce the availability of the
third release candidate for the QEMU 6.2 release. This release is meant
for testing purposes and should not be used in a production environment.

  http://download.qemu-project.org/qemu-6.2.0-rc2.tar.xz
  http://download.qemu-project.org/qemu-6.2.0-rc2.tar.xz.sig

You can help improve the quality of the QEMU 6.2 release by testing this
release and reporting bugs using our GitLab issue tracker:

  https://gitlab.com/qemu-project/qemu/-/issues

The release plan, as well a documented known issues for release
candidates, are available at:

  http://wiki.qemu.org/Planning/6.2

Please add entries to the ChangeLog for the 6.2 release below:

  http://wiki.qemu.org/ChangeLog/6.2

Thank you to everyone involved!

Changes since rc1:

14d02cfbe4: Update version for v6.2.0-rc2 release (Richard Henderson)
4dd218fd07: iotests/149: Skip on unsupported ciphers (Hanna Reitz)
cb5a24d7f6: iotests: Use aes-128-cbc (Hanna Reitz)
22c36b75c8: block/vvfat.c fix leak when failure occurs (Daniella Lee)
0763788868: linux-user/signal.c: Create a common rewind_if_in_safe_syscall 
(Warner Losh)
c6cda6a44a: linux-user: Add host_signal_set_pc to set pc in mcontext (Warner 
Losh)
a57cb3e23d: python/aqmp: fix send_fd_scm for python 3.6.x (John Snow)
206439cd89: scripts/device-crash-test: Use a QMP timeout (John Snow)
1611e6cf4e: python/machine: handle "fast" QEMU terminations (John Snow)
b1ca991993: python/machine: move more variable initializations to _pre_launch 
(John Snow)
72b17fe715: python/machine: add instance disambiguator to default nickname 
(John Snow)
6eeb3de7e1: python/machine: remove _remove_monitor_sockfile property (John Snow)
87bf1fe5cb: python/machine: add @sock_dir property (John Snow)
33a0c404fb: hw/intc/arm_gicv3_its: Revert version increments in vmstate_its 
(Eric Auger)
c5ba621954: docs: Render binary names as monospaced text (Philippe 
Mathieu-Daudé)
eff708a876: docs: Use double quotes instead of single quotes for COLO (Rao, Lei)
8f75cae2dd: docs: Drop deprecated 'props' from object-add (Rao, Lei)
b980c1aec6: Fix some typos in documentation (found by codespell) (Stefan Weil)
93e86b1664: docs: List more commit-message tags in "submitting-a-patch" 
(Kashyap Chamarthy)
cd6b1674d6: docs: Fix botched rST conversion of 'submitting-a-patch.rst' 
(Kashyap Chamarthy)
4825eaae4f: Revert "arm: tcg: Adhere to SMCCC 1.3 section 5.2" (Peter Maydell)
e35574226a: nbd/server: Simplify zero and trim (Eric Blake)
1644cccea5: nbd/server: Don't complain on certain client disconnects (Eric 
Blake)
b9e5628ca5: microvm: check g_file_set_contents() return value (Gerd Hoffmann)
1b38ccc9a1: microvm: add missing g_free() call (Gerd Hoffmann)
d612405ed2: hw/i386/microvm: Reduce annoying debug message in 
dt_setup_microvm() (Philippe Mathieu-Daudé)
4067691a2f: migration: fix dump-vmstate with modules (Laurent Vivier)
2e572baf65: ui/vnc-clipboard: fix adding notifier twice (Vladimir 
Sementsov-Ogievskiy)
c3abdb2faf: ui/gtk: graphic_hw_gl_flushed after closing dmabuf->fence_fd 
(Dongwon Kim)
f14aab420c: ui: fix incorrect pointer position on highdpi with gtk (Alexander 
Orzechowski)
4323118cad: ui: fix incorrect scaling on highdpi with gtk/opengl (Alexander 
Orzechowski)
802ae45e94: linux-user: fix Coverity CID 1464101 (Laurent Vivier)
526e744302: hw/misc/sifive_u_otp: Do not reset OTP content on hardware reset 
(Philippe Mathieu-Daudé)
6b717a8d44: hw/misc/sifive_u_otp: Use IF_PFLASH for the OTP device instead of 
IF_NONE (Thomas Huth)
aee14c77f4: linux-user: Rewrite do_getdents, do_getdents64 (Richard Henderson)
1962cb0029: linux-user: Fix member types of target_dirent64 (Richard Henderson)
540a736f54: linux-user: Always use flexible arrays for dirent d_name (Richard 
Henderson)
fd08ddb9cb: linux-user: Split out do_getdents, do_getdents64 (Richard Henderson)
319e89cdc3: escc: update the R_SPEC register SPEC_ALLSENT bit when writing to 
W_TXCTRL1 (Mark Cave-Ayland)
c29cd47e82: escc: always set STATUS_TXEMPTY in R_STATUS on device reset (Mark 
Cave-Ayland)
fdc6e16818: chardev/wctable: don't free the instance in wctablet_chr_finalize 
(Daniil Tatianin)
fbab8cc24d: meson.build: Support ncurses on MacOS and OpenBSD (Stefan Weil)
5135fe7110: docs: Spell QEMU all caps (Philippe Mathieu-Daudé)
283191640c: qtest/am53c974-test: add test for reset before transfer (Mark 
Cave-Ayland)
3f26c97577: esp: ensure that async_len is reset to 0 during esp_hard_reset() 
(Mark Cave-Ayland)
0cc4965049: nvmm: Fix support for stable version (nia)
e2c57529c9: hw/nvme: fix buffer overrun in nvme_changed_nslist (CVE-2021-3947) 
(Klaus Jensen)
916b0f0b52: hw/nvme: change nvme-ns 'shared' default (Klaus Jensen)
9fc6e86e8b: hw/nvme: reattach subsystem namespaces on hotplug (Hannes Reinecke)
0656fbc7dd: net/colo-compare.c: Fix incorrect return when input wrong size 
(Zhang Chen)
fb5eca4a57: net/colo-compare.c: Fix ACK track reverse issue (Zhang Chen)
d05dcd94ae: net: vmxnet3: validate configuration 

Re: [PATCH v3 02/23] migration: Never call twice qemu_target_page_size()

2021-11-24 Thread Dr. David Alan Gilbert
* Juan Quintela (quint...@redhat.com) wrote:
> Signed-off-by: Juan Quintela 

OK, not much difference

Reviewed-by: Dr. David Alan Gilbert 

> ---
>  migration/migration.c | 7 ---
>  migration/multifd.c   | 7 ---
>  migration/savevm.c| 5 +++--
>  3 files changed, 11 insertions(+), 8 deletions(-)
> 
> diff --git a/migration/migration.c b/migration/migration.c
> index 2c1edb2cb9..3de11ae921 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -996,6 +996,8 @@ static void populate_time_info(MigrationInfo *info, 
> MigrationState *s)
>  
>  static void populate_ram_info(MigrationInfo *info, MigrationState *s)
>  {
> +size_t page_size = qemu_target_page_size();
> +
>  info->has_ram = true;
>  info->ram = g_malloc0(sizeof(*info->ram));
>  info->ram->transferred = ram_counters.transferred;
> @@ -1004,12 +1006,11 @@ static void populate_ram_info(MigrationInfo *info, 
> MigrationState *s)
>  /* legacy value.  It is not used anymore */
>  info->ram->skipped = 0;
>  info->ram->normal = ram_counters.normal;
> -info->ram->normal_bytes = ram_counters.normal *
> -qemu_target_page_size();
> +info->ram->normal_bytes = ram_counters.normal * page_size;
>  info->ram->mbps = s->mbps;
>  info->ram->dirty_sync_count = ram_counters.dirty_sync_count;
>  info->ram->postcopy_requests = ram_counters.postcopy_requests;
> -info->ram->page_size = qemu_target_page_size();
> +info->ram->page_size = page_size;
>  info->ram->multifd_bytes = ram_counters.multifd_bytes;
>  info->ram->pages_per_second = s->pages_per_second;
>  
> diff --git a/migration/multifd.c b/migration/multifd.c
> index 7c9deb1921..8125d0015c 100644
> --- a/migration/multifd.c
> +++ b/migration/multifd.c
> @@ -289,7 +289,8 @@ static void multifd_send_fill_packet(MultiFDSendParams *p)
>  static int multifd_recv_unfill_packet(MultiFDRecvParams *p, Error **errp)
>  {
>  MultiFDPacket_t *packet = p->packet;
> -uint32_t pages_max = MULTIFD_PACKET_SIZE / qemu_target_page_size();
> +size_t page_size = qemu_target_page_size();
> +uint32_t pages_max = MULTIFD_PACKET_SIZE / page_size;
>  RAMBlock *block;
>  int i;
>  
> @@ -358,14 +359,14 @@ static int multifd_recv_unfill_packet(MultiFDRecvParams 
> *p, Error **errp)
>  for (i = 0; i < p->pages->used; i++) {
>  uint64_t offset = be64_to_cpu(packet->offset[i]);
>  
> -if (offset > (block->used_length - qemu_target_page_size())) {
> +if (offset > (block->used_length - page_size)) {
>  error_setg(errp, "multifd: offset too long %" PRIu64
> " (max " RAM_ADDR_FMT ")",
> offset, block->used_length);
>  return -1;
>  }
>  p->pages->iov[i].iov_base = block->host + offset;
> -p->pages->iov[i].iov_len = qemu_target_page_size();
> +p->pages->iov[i].iov_len = page_size;
>  }
>  
>  return 0;
> diff --git a/migration/savevm.c b/migration/savevm.c
> index d59e976d50..0bef031acb 100644
> --- a/migration/savevm.c
> +++ b/migration/savevm.c
> @@ -1685,6 +1685,7 @@ static int 
> loadvm_postcopy_handle_advise(MigrationIncomingState *mis,
>  {
>  PostcopyState ps = postcopy_state_set(POSTCOPY_INCOMING_ADVISE);
>  uint64_t remote_pagesize_summary, local_pagesize_summary, remote_tps;
> +size_t page_size = qemu_target_page_size();
>  Error *local_err = NULL;
>  
>  trace_loadvm_postcopy_handle_advise();
> @@ -1741,13 +1742,13 @@ static int 
> loadvm_postcopy_handle_advise(MigrationIncomingState *mis,
>  }
>  
>  remote_tps = qemu_get_be64(mis->from_src_file);
> -if (remote_tps != qemu_target_page_size()) {
> +if (remote_tps != page_size) {
>  /*
>   * Again, some differences could be dealt with, but for now keep it
>   * simple.
>   */
>  error_report("Postcopy needs matching target page sizes (s=%d 
> d=%zd)",
> - (int)remote_tps, qemu_target_page_size());
> + (int)remote_tps, page_size);
>  return -1;
>  }
>  
> -- 
> 2.33.1
> 
-- 
Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK




[PATCH for-7.0 v8 17/31] tcg/loongarch64: Implement add/sub ops

2021-11-24 Thread WANG Xuerui
The neg_i{32,64} ops is fully expressible with sub, so omitted for
simplicity.

Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 tcg/loongarch64/tcg-target-con-set.h |  2 ++
 tcg/loongarch64/tcg-target.c.inc | 38 
 2 files changed, 40 insertions(+)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index 42f8e28741..4b8ce85897 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -18,6 +18,8 @@ C_O0_I1(r)
 C_O1_I1(r, r)
 C_O1_I2(r, r, rC)
 C_O1_I2(r, r, ri)
+C_O1_I2(r, r, rI)
 C_O1_I2(r, r, rU)
 C_O1_I2(r, r, rW)
 C_O1_I2(r, 0, rZ)
+C_O1_I2(r, rZ, rN)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index d0a24cc009..0e6b241097 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -687,6 +687,36 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 }
 break;
 
+case INDEX_op_add_i32:
+if (c2) {
+tcg_out_opc_addi_w(s, a0, a1, a2);
+} else {
+tcg_out_opc_add_w(s, a0, a1, a2);
+}
+break;
+case INDEX_op_add_i64:
+if (c2) {
+tcg_out_opc_addi_d(s, a0, a1, a2);
+} else {
+tcg_out_opc_add_d(s, a0, a1, a2);
+}
+break;
+
+case INDEX_op_sub_i32:
+if (c2) {
+tcg_out_opc_addi_w(s, a0, a1, -a2);
+} else {
+tcg_out_opc_sub_w(s, a0, a1, a2);
+}
+break;
+case INDEX_op_sub_i64:
+if (c2) {
+tcg_out_opc_addi_d(s, a0, a1, -a2);
+} else {
+tcg_out_opc_sub_d(s, a0, a1, a2);
+}
+break;
+
 case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
 case INDEX_op_mov_i64:
 default:
@@ -748,6 +778,10 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_rotr_i64:
 return C_O1_I2(r, r, ri);
 
+case INDEX_op_add_i32:
+case INDEX_op_add_i64:
+return C_O1_I2(r, r, rI);
+
 case INDEX_op_and_i32:
 case INDEX_op_and_i64:
 case INDEX_op_nor_i32:
@@ -770,6 +804,10 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 /* Must deposit into the same register as input */
 return C_O1_I2(r, 0, rZ);
 
+case INDEX_op_sub_i32:
+case INDEX_op_sub_i64:
+return C_O1_I2(r, rZ, rN);
+
 default:
 g_assert_not_reached();
 }
-- 
2.34.0




[PATCH for-7.0 v8 29/31] linux-user: Implement CPU-specific signal handler for loongarch64 hosts

2021-11-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 linux-user/host/loongarch64/host-signal.h | 87 +++
 1 file changed, 87 insertions(+)
 create mode 100644 linux-user/host/loongarch64/host-signal.h

diff --git a/linux-user/host/loongarch64/host-signal.h 
b/linux-user/host/loongarch64/host-signal.h
new file mode 100644
index 00..05e2c82371
--- /dev/null
+++ b/linux-user/host/loongarch64/host-signal.h
@@ -0,0 +1,87 @@
+/*
+ * host-signal.h: signal info dependent on the host architecture
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ * Copyright (c) 2021 WANG Xuerui 
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef LOONGARCH64_HOST_SIGNAL_H
+#define LOONGARCH64_HOST_SIGNAL_H
+
+static inline uintptr_t host_signal_pc(ucontext_t *uc)
+{
+return uc->uc_mcontext.__pc;
+}
+
+static inline void host_signal_set_pc(ucontext_t *uc, uintptr_t pc)
+{
+uc->uc_mcontext.__pc = pc;
+}
+
+static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
+{
+const uint32_t *pinsn = (const uint32_t *)host_signal_pc(uc);
+uint32_t insn = pinsn[0];
+
+/* Detect store by reading the instruction at the program counter.  */
+switch ((insn >> 26) & 0b11) {
+case 0b001000: /* {ll,sc}.[wd] */
+switch ((insn >> 24) & 0b11) {
+case 0b01: /* sc.w */
+case 0b11: /* sc.d */
+return true;
+}
+break;
+case 0b001001: /* {ld,st}ox4.[wd] ({ld,st}ptr.[wd]) */
+switch ((insn >> 24) & 0b11) {
+case 0b01: /* stox4.w (stptr.w) */
+case 0b11: /* stox4.d (stptr.d) */
+return true;
+}
+break;
+case 0b001010: /* {ld,st}.* family */
+switch ((insn >> 22) & 0b) {
+case 0b0100: /* st.b */
+case 0b0101: /* st.h */
+case 0b0110: /* st.w */
+case 0b0111: /* st.d */
+case 0b1101: /* fst.s */
+case 0b: /* fst.d */
+return true;
+}
+break;
+case 0b001110: /* indexed, atomic, bounds-checking memory operations */
+uint32_t sel = (insn >> 15) & 0b111;
+
+switch (sel) {
+case 0b010: /* stx.b */
+case 0b0101000: /* stx.h */
+case 0b011: /* stx.w */
+case 0b0111000: /* stx.d */
+case 0b111: /* fstx.s */
+case 0b000: /* fstx.d */
+case 0b00011101100: /* fstgt.s */
+case 0b00011101101: /* fstgt.d */
+case 0b00011101110: /* fstle.s */
+case 0b0001110: /* fstle.d */
+case 0b0001000: /* stgt.b */
+case 0b0001001: /* stgt.h */
+case 0b0001010: /* stgt.w */
+case 0b0001011: /* stgt.d */
+case 0b0001100: /* stle.b */
+case 0b0001101: /* stle.h */
+case 0b0001110: /* stle.w */
+case 0b000: /* stle.d */
+case 0b0001100 ... 0b00011100011: /* am* insns */
+return true;
+}
+break;
+}
+
+return false;
+}
+
+#endif
-- 
2.34.0




[PATCH for-7.0 v8 31/31] tests/docker: Add gentoo-loongarch64-cross image and run cross builds in GitLab

2021-11-24 Thread WANG Xuerui
  $(if $V,,--quiet) --no-cache
\
+   --registry $(DOCKER_REGISTRY) --extra-files 
\
+   
$(DOCKER_FILES_DIR)/gentoo-loongarch64-cross.docker.d/build-toolchain.sh, \
+   "BUILD", "gentoo-loongarch64-cross"),   
\
+   $(call quiet-command,   
\
+   $(DOCKER_SCRIPT) fetch $(if $V,,--quiet)
\
+   qemu/gentoo-loongarch64-cross 
$(DOCKER_REGISTRY),   \
+   "FETCH", "gentoo-loongarch64-cross")
\
+   $(call quiet-command,   
\
+   $(DOCKER_SCRIPT) update $(if $V,,--quiet)   
\
+   qemu/gentoo-loongarch64-cross 
--add-current-user,   \
+   "PREPARE", "gentoo-loongarch64-cross"))
+
+
 debian-toolchain-run = \
$(if $(NOCACHE),\
$(call quiet-command,   \
diff --git a/tests/docker/dockerfiles/gentoo-loongarch64-cross.docker 
b/tests/docker/dockerfiles/gentoo-loongarch64-cross.docker
new file mode 100644
index 00..c02d25101b
--- /dev/null
+++ b/tests/docker/dockerfiles/gentoo-loongarch64-cross.docker
@@ -0,0 +1,19 @@
+#
+# Docker LoongArch64 cross-compiler target
+#
+# This docker target is used for building loongarch64 tests. As it also
+# needs to be able to build QEMU itself in CI we include it's
+# build-deps. It is also a "stand-alone" image so as not to be
+# triggered by re-builds on other base images given it takes a long
+# time to build.
+#
+
+FROM docker.io/gentoo/stage3:20211124
+
+ADD build-toolchain.sh /root/build-toolchain.sh
+RUN cd /root && ./build-toolchain.sh
+
+# Specify the cross prefix for this image (see tests/docker/common.rc)
+ENV QEMU_CONFIGURE_OPTS --cross-prefix=loongarch64-unknown-linux-gnu-
+# We don't have target support at the moment, so just verify that things build
+ENV DEF_TARGET_LIST x86_64-softmmu,x86_64-linux-user
diff --git 
a/tests/docker/dockerfiles/gentoo-loongarch64-cross.docker.d/build-toolchain.sh 
b/tests/docker/dockerfiles/gentoo-loongarch64-cross.docker.d/build-toolchain.sh
new file mode 100755
index 00..94292a014d
--- /dev/null
+++ 
b/tests/docker/dockerfiles/gentoo-loongarch64-cross.docker.d/build-toolchain.sh
@@ -0,0 +1,125 @@
+#!/bin/bash
+
+set -e
+
+TRIPLE=loongarch64-unknown-linux-gnu
+CROSSDEV_OV=/opt/crossdev-overlay
+LOONGSON_OV=/opt/loongson-overlay
+CROSS_EMERGE="${TRIPLE}-emerge"
+
+# this will break on non-SMP machines, but no one should build this image
+# on such machine in the first place
+J=$(expr $(nproc) / 2)
+echo "MAKEOPTS=\"-j${J} -l${J}\"" >> /etc/portage/make.conf
+echo "EGIT_CLONE_TYPE=shallow" >> /etc/portage/make.conf
+
+# these features are not supported in Docker
+export FEATURES="-ipc-sandbox -network-sandbox"
+
+# populate Portage tree
+GENTOO_MIRROR='https://bouncer.gentoo.org/fetch/root/all'
+PORTAGE_SNAPSHOT_FILE=gentoo-20211123.tar.xz
+pushd /tmp
+wget "${GENTOO_MIRROR}/snapshots/${PORTAGE_SNAPSHOT_FILE}"
+
+mkdir -p /var/db/repos/gentoo
+pushd /var/db/repos/gentoo
+tar -xf "/tmp/${PORTAGE_SNAPSHOT_FILE}" --strip-components=1
+popd
+
+rm "$PORTAGE_SNAPSHOT_FILE"
+popd
+
+emerge -j crossdev dev-vcs/git
+
+# prepare for crossdev
+mkdir /etc/portage/repos.conf
+crossdev -t "$TRIPLE" --ov-output "$CROSSDEV_OV" --init-target
+
+git clone https://github.com/xen0n/loongson-overlay.git "$LOONGSON_OV"
+pushd "$LOONGSON_OV"
+git checkout 075db64f56efab0108f8b82a5868fb58760d54a0
+popd
+
+pushd "${CROSSDEV_OV}/cross-${TRIPLE}"
+rm binutils gcc glibc linux-headers
+ln -s "${LOONGSON_OV}/sys-devel/binutils" .
+ln -s "${LOONGSON_OV}/sys-devel/gcc" .
+ln -s "${LOONGSON_OV}/sys-libs/glibc" .
+ln -s "${LOONGSON_OV}/sys-kernel/linux-headers" .
+popd
+
+cat > "${CROSSDEV_OV}/metadata/layout.conf" < repos.conf/loongson.conf <

[PATCH for-7.0 v8 30/31] configure, meson.build: Mark support for loongarch64 hosts

2021-11-24 Thread WANG Xuerui
Example output of `uname -a` on an initial Gentoo LA64 port, running
the upstream submission version of Linux (with some very minor patches
not influencing output here):

> Linux  5.14.0-10342-g37a00851b145 #5 SMP PREEMPT Tue Aug 10 
> 12:56:24 PM CST 2021 loongarch64 GNU/Linux

And the same on the vendor-supplied Loongnix 20 system, with an early
in-house port of Linux, and using the old-world ABI:

> Linux  4.19.167-rc5.lnd.1-loongson-3 #1 SMP Sat Apr 17 07:32:32 UTC 
> 2021 loongarch64 loongarch64 loongarch64 GNU/Linux

So a name of "loongarch64" matches both, fortunately.

Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 configure   | 7 ++-
 meson.build | 2 +-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/configure b/configure
index 48c21775f3..23c366a69a 100755
--- a/configure
+++ b/configure
@@ -581,6 +581,8 @@ elif check_define __arm__ ; then
   cpu="arm"
 elif check_define __aarch64__ ; then
   cpu="aarch64"
+elif check_define __loongarch64 ; then
+  cpu="loongarch64"
 else
   cpu=$(uname -m)
 fi
@@ -589,7 +591,7 @@ ARCH=
 # Normalise host CPU name and set ARCH.
 # Note that this case should only have supported host CPUs, not guests.
 case "$cpu" in
-  ppc|ppc64|s390x|sparc64|x32|riscv)
+  ppc|ppc64|s390x|sparc64|x32|riscv|loongarch64)
   ;;
   ppc64le)
 ARCH="ppc64"
@@ -3770,6 +3772,9 @@ if test "$linux" = "yes" ; then
   aarch64)
 linux_arch=arm64
 ;;
+  loongarch*)
+linux_arch=loongarch
+;;
   mips64)
 linux_arch=mips
 ;;
diff --git a/meson.build b/meson.build
index 96de1a6ef9..a6fa0d879e 100644
--- a/meson.build
+++ b/meson.build
@@ -56,7 +56,7 @@ python = import('python').find_installation()
 
 supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 
'sunos', 'linux']
 supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv', 'x86', 'x86_64',
-  'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64']
+  'arm', 'aarch64', 'loongarch64', 'mips', 'mips64', 'sparc', 'sparc64']
 
 cpu = host_machine.cpu_family()
 
-- 
2.34.0




[PATCH for-7.0 v8 22/31] tcg/loongarch64: Implement simple load/store ops

2021-11-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 tcg/loongarch64/tcg-target-con-set.h |   1 +
 tcg/loongarch64/tcg-target.c.inc | 131 +++
 2 files changed, 132 insertions(+)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index a2ec61237e..e54ca9b2de 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -15,6 +15,7 @@
  * tcg-target-con-str.h; the constraint combination is inclusive or.
  */
 C_O0_I1(r)
+C_O0_I2(rZ, r)
 C_O0_I2(rZ, rZ)
 C_O1_I1(r, r)
 C_O1_I2(r, r, rC)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index e470d7e145..fec22cfaf6 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -565,6 +565,73 @@ static void tcg_out_call(TCGContext *s, const 
tcg_insn_unit *arg)
 tcg_out_call_int(s, arg, false);
 }
 
+/*
+ * Load/store helpers
+ */
+
+static void tcg_out_ldst(TCGContext *s, LoongArchInsn opc, TCGReg data,
+ TCGReg addr, intptr_t offset)
+{
+intptr_t imm12 = sextreg(offset, 0, 12);
+
+if (offset != imm12) {
+intptr_t diff = offset - (uintptr_t)s->code_ptr;
+
+if (addr == TCG_REG_ZERO && diff == (int32_t)diff) {
+imm12 = sextreg(diff, 0, 12);
+tcg_out_opc_pcaddu12i(s, TCG_REG_TMP2, (diff - imm12) >> 12);
+} else {
+tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP2, offset - imm12);
+if (addr != TCG_REG_ZERO) {
+tcg_out_opc_add_d(s, TCG_REG_TMP2, TCG_REG_TMP2, addr);
+}
+}
+addr = TCG_REG_TMP2;
+}
+
+switch (opc) {
+case OPC_LD_B:
+case OPC_LD_BU:
+case OPC_LD_H:
+case OPC_LD_HU:
+case OPC_LD_W:
+case OPC_LD_WU:
+case OPC_LD_D:
+case OPC_ST_B:
+case OPC_ST_H:
+case OPC_ST_W:
+case OPC_ST_D:
+tcg_out32(s, encode_djsk12_insn(opc, data, addr, imm12));
+break;
+default:
+g_assert_not_reached();
+}
+}
+
+static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
+   TCGReg arg1, intptr_t arg2)
+{
+bool is_32bit = type == TCG_TYPE_I32;
+tcg_out_ldst(s, is_32bit ? OPC_LD_W : OPC_LD_D, arg, arg1, arg2);
+}
+
+static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
+   TCGReg arg1, intptr_t arg2)
+{
+bool is_32bit = type == TCG_TYPE_I32;
+tcg_out_ldst(s, is_32bit ? OPC_ST_W : OPC_ST_D, arg, arg1, arg2);
+}
+
+static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
+TCGReg base, intptr_t ofs)
+{
+if (val == 0) {
+tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
+return true;
+}
+return false;
+}
+
 /*
  * Entry-points
  */
@@ -913,6 +980,49 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 tcg_out_setcond(s, args[3], a0, a1, a2, c2);
 break;
 
+case INDEX_op_ld8s_i32:
+case INDEX_op_ld8s_i64:
+tcg_out_ldst(s, OPC_LD_B, a0, a1, a2);
+break;
+case INDEX_op_ld8u_i32:
+case INDEX_op_ld8u_i64:
+tcg_out_ldst(s, OPC_LD_BU, a0, a1, a2);
+break;
+case INDEX_op_ld16s_i32:
+case INDEX_op_ld16s_i64:
+tcg_out_ldst(s, OPC_LD_H, a0, a1, a2);
+break;
+case INDEX_op_ld16u_i32:
+case INDEX_op_ld16u_i64:
+tcg_out_ldst(s, OPC_LD_HU, a0, a1, a2);
+break;
+case INDEX_op_ld_i32:
+case INDEX_op_ld32s_i64:
+tcg_out_ldst(s, OPC_LD_W, a0, a1, a2);
+break;
+case INDEX_op_ld32u_i64:
+tcg_out_ldst(s, OPC_LD_WU, a0, a1, a2);
+break;
+case INDEX_op_ld_i64:
+tcg_out_ldst(s, OPC_LD_D, a0, a1, a2);
+break;
+
+case INDEX_op_st8_i32:
+case INDEX_op_st8_i64:
+tcg_out_ldst(s, OPC_ST_B, a0, a1, a2);
+break;
+case INDEX_op_st16_i32:
+case INDEX_op_st16_i64:
+tcg_out_ldst(s, OPC_ST_H, a0, a1, a2);
+break;
+case INDEX_op_st_i32:
+case INDEX_op_st32_i64:
+tcg_out_ldst(s, OPC_ST_W, a0, a1, a2);
+break;
+case INDEX_op_st_i64:
+tcg_out_ldst(s, OPC_ST_D, a0, a1, a2);
+break;
+
 case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
 case INDEX_op_mov_i64:
 case INDEX_op_call: /* Always emitted via tcg_out_call.  */
@@ -927,6 +1037,15 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_goto_ptr:
 return C_O0_I1(r);
 
+case INDEX_op_st8_i32:
+case INDEX_op_st8_i64:
+case INDEX_op_st16_i32:
+case INDEX_op_st16_i64:
+case INDEX_op_st32_i64:
+case INDEX_op_st_i32:
+case INDEX_op_st_i64:
+return C_O0_I2(rZ, r);
+
 case INDEX_op_brcond_i32:
 case INDEX_op_brcond_i64:
 return C_O0_I2(rZ, rZ);
@@ -954,6 +1073,18 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case 

[PATCH for-7.0 v8 26/31] tcg/loongarch64: Implement tcg_target_init

2021-11-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 27 +++
 1 file changed, 27 insertions(+)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 2d066a035d..ff167d686b 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1604,3 +1604,30 @@ static void tcg_target_qemu_prologue(TCGContext *s)
 tcg_out_opc_addi_d(s, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
 tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_RA, 0);
 }
+
+static void tcg_target_init(TCGContext *s)
+{
+tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS;
+tcg_target_available_regs[TCG_TYPE_I64] = ALL_GENERAL_REGS;
+
+tcg_target_call_clobber_regs = ALL_GENERAL_REGS;
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0);
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1);
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2);
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S3);
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S4);
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S5);
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S6);
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S7);
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S8);
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S9);
+
+s->reserved_regs = 0;
+tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO);
+tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0);
+tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1);
+tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2);
+tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
+tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP);
+tcg_regset_set_reg(s->reserved_regs, TCG_REG_RESERVED);
+}
-- 
2.34.0




[PATCH for-7.0 v8 24/31] tcg/loongarch64: Implement tcg_target_qemu_prologue

2021-11-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 68 
 1 file changed, 68 insertions(+)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index c92587c823..a806e3352e 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -968,6 +968,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg 
*args)
  * Entry-points
  */
 
+static const tcg_insn_unit *tb_ret_addr;
+
 static void tcg_out_op(TCGContext *s, TCGOpcode opc,
const TCGArg args[TCG_MAX_OP_ARGS],
const int const_args[TCG_MAX_OP_ARGS])
@@ -1517,3 +1519,69 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 g_assert_not_reached();
 }
 }
+
+static const int tcg_target_callee_save_regs[] = {
+TCG_REG_S0, /* used for the global env (TCG_AREG0) */
+TCG_REG_S1,
+TCG_REG_S2,
+TCG_REG_S3,
+TCG_REG_S4,
+TCG_REG_S5,
+TCG_REG_S6,
+TCG_REG_S7,
+TCG_REG_S8,
+TCG_REG_S9,
+TCG_REG_RA, /* should be last for ABI compliance */
+};
+
+/* Stack frame parameters.  */
+#define REG_SIZE   (TCG_TARGET_REG_BITS / 8)
+#define SAVE_SIZE  ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE)
+#define TEMP_SIZE  (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
+#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \
+ + TCG_TARGET_STACK_ALIGN - 1) \
+& -TCG_TARGET_STACK_ALIGN)
+#define SAVE_OFS   (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE)
+
+/* We're expecting to be able to use an immediate for frame allocation.  */
+QEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7ff);
+
+/* Generate global QEMU prologue and epilogue code */
+static void tcg_target_qemu_prologue(TCGContext *s)
+{
+int i;
+
+tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE);
+
+/* TB prologue */
+tcg_out_opc_addi_d(s, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE);
+for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
+tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
+   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
+}
+
+#if !defined(CONFIG_SOFTMMU)
+if (USE_GUEST_BASE) {
+tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base);
+tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
+}
+#endif
+
+/* Call generated code */
+tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
+tcg_out_opc_jirl(s, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0);
+
+/* Return path for goto_ptr. Set return value to 0 */
+tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
+tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_A0, TCG_REG_ZERO);
+
+/* TB epilogue */
+tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
+for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
+tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
+   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
+}
+
+tcg_out_opc_addi_d(s, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
+tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_RA, 0);
+}
-- 
2.34.0




[PATCH for-7.0 v8 11/31] tcg/loongarch64: Implement sign-/zero-extension ops

2021-11-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 tcg/loongarch64/tcg-target-con-set.h |  1 +
 tcg/loongarch64/tcg-target.c.inc | 82 
 tcg/loongarch64/tcg-target.h | 24 
 3 files changed, 95 insertions(+), 12 deletions(-)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index 5cc4407367..7e459490ea 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -15,3 +15,4 @@
  * tcg-target-con-str.h; the constraint combination is inclusive or.
  */
 C_O0_I1(r)
+C_O1_I1(r, r)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 17f869dbd2..0c075c7521 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -382,6 +382,36 @@ static void tcg_out_movi(TCGContext *s, TCGType type, 
TCGReg rd,
 }
 }
 
+static void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg)
+{
+tcg_out_opc_andi(s, ret, arg, 0xff);
+}
+
+static void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg)
+{
+tcg_out_opc_bstrpick_w(s, ret, arg, 0, 15);
+}
+
+static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
+{
+tcg_out_opc_bstrpick_d(s, ret, arg, 0, 31);
+}
+
+static void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
+{
+tcg_out_opc_sext_b(s, ret, arg);
+}
+
+static void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg)
+{
+tcg_out_opc_sext_h(s, ret, arg);
+}
+
+static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg)
+{
+tcg_out_opc_addi_w(s, ret, arg, 0);
+}
+
 /*
  * Entry-points
  */
@@ -391,6 +421,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
const int const_args[TCG_MAX_OP_ARGS])
 {
 TCGArg a0 = args[0];
+TCGArg a1 = args[1];
 
 switch (opc) {
 case INDEX_op_mb:
@@ -401,6 +432,41 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 tcg_out_opc_jirl(s, TCG_REG_ZERO, a0, 0);
 break;
 
+case INDEX_op_ext8s_i32:
+case INDEX_op_ext8s_i64:
+tcg_out_ext8s(s, a0, a1);
+break;
+
+case INDEX_op_ext8u_i32:
+case INDEX_op_ext8u_i64:
+tcg_out_ext8u(s, a0, a1);
+break;
+
+case INDEX_op_ext16s_i32:
+case INDEX_op_ext16s_i64:
+tcg_out_ext16s(s, a0, a1);
+break;
+
+case INDEX_op_ext16u_i32:
+case INDEX_op_ext16u_i64:
+tcg_out_ext16u(s, a0, a1);
+break;
+
+case INDEX_op_ext32u_i64:
+case INDEX_op_extu_i32_i64:
+tcg_out_ext32u(s, a0, a1);
+break;
+
+case INDEX_op_ext32s_i64:
+case INDEX_op_extrl_i64_i32:
+case INDEX_op_ext_i32_i64:
+tcg_out_ext32s(s, a0, a1);
+break;
+
+case INDEX_op_extrh_i64_i32:
+tcg_out_opc_srai_d(s, a0, a1, 32);
+break;
+
 case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
 case INDEX_op_mov_i64:
 default:
@@ -414,6 +480,22 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_goto_ptr:
 return C_O0_I1(r);
 
+case INDEX_op_ext8s_i32:
+case INDEX_op_ext8s_i64:
+case INDEX_op_ext8u_i32:
+case INDEX_op_ext8u_i64:
+case INDEX_op_ext16s_i32:
+case INDEX_op_ext16s_i64:
+case INDEX_op_ext16u_i32:
+case INDEX_op_ext16u_i64:
+case INDEX_op_ext32s_i64:
+case INDEX_op_ext32u_i64:
+case INDEX_op_extu_i32_i64:
+case INDEX_op_extrl_i64_i32:
+case INDEX_op_extrh_i64_i32:
+case INDEX_op_ext_i32_i64:
+return C_O1_I1(r, r);
+
 default:
 g_assert_not_reached();
 }
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index 5fc097b3c1..2b7d5a19b9 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -107,10 +107,10 @@ typedef enum {
 #define TCG_TARGET_HAS_muls2_i320
 #define TCG_TARGET_HAS_muluh_i320
 #define TCG_TARGET_HAS_mulsh_i320
-#define TCG_TARGET_HAS_ext8s_i320
-#define TCG_TARGET_HAS_ext16s_i32   0
-#define TCG_TARGET_HAS_ext8u_i320
-#define TCG_TARGET_HAS_ext16u_i32   0
+#define TCG_TARGET_HAS_ext8s_i321
+#define TCG_TARGET_HAS_ext16s_i32   1
+#define TCG_TARGET_HAS_ext8u_i321
+#define TCG_TARGET_HAS_ext16u_i32   1
 #define TCG_TARGET_HAS_bswap16_i32  0
 #define TCG_TARGET_HAS_bswap32_i32  0
 #define TCG_TARGET_HAS_not_i32  0
@@ -138,14 +138,14 @@ typedef enum {
 #define TCG_TARGET_HAS_extract_i64  0
 #define TCG_TARGET_HAS_sextract_i64 0
 #define TCG_TARGET_HAS_extract2_i64 0
-#define TCG_TARGET_HAS_extrl_i64_i320
-#define TCG_TARGET_HAS_extrh_i64_i320
-#define TCG_TARGET_HAS_ext8s_i640
-#define TCG_TARGET_HAS_ext16s_i64   0
-#define TCG_TARGET_HAS_ext32s_i64   0
-#define TCG_TARGET_HAS_ext8u_i640
-#define TCG_TARGET_HAS_ext16u_i64   0
-#define TCG_TARGET_HAS_ext32u_i64   0
+#define 

[PATCH for-7.0 v8 12/31] tcg/loongarch64: Implement not/and/or/xor/nor/andc/orc ops

2021-11-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 tcg/loongarch64/tcg-target-con-set.h |  2 +
 tcg/loongarch64/tcg-target.c.inc | 88 
 tcg/loongarch64/tcg-target.h | 16 ++---
 3 files changed, 98 insertions(+), 8 deletions(-)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index 7e459490ea..9ac24b8ad0 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -16,3 +16,5 @@
  */
 C_O0_I1(r)
 C_O1_I1(r, r)
+C_O1_I2(r, r, rC)
+C_O1_I2(r, r, rU)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 0c075c7521..d610b83c37 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -422,6 +422,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 {
 TCGArg a0 = args[0];
 TCGArg a1 = args[1];
+TCGArg a2 = args[2];
+int c2 = const_args[2];
 
 switch (opc) {
 case INDEX_op_mb:
@@ -467,6 +469,68 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 tcg_out_opc_srai_d(s, a0, a1, 32);
 break;
 
+case INDEX_op_not_i32:
+case INDEX_op_not_i64:
+tcg_out_opc_nor(s, a0, a1, TCG_REG_ZERO);
+break;
+
+case INDEX_op_nor_i32:
+case INDEX_op_nor_i64:
+if (c2) {
+tcg_out_opc_ori(s, a0, a1, a2);
+tcg_out_opc_nor(s, a0, a0, TCG_REG_ZERO);
+} else {
+tcg_out_opc_nor(s, a0, a1, a2);
+}
+break;
+
+case INDEX_op_andc_i32:
+case INDEX_op_andc_i64:
+if (c2) {
+/* guaranteed to fit due to constraint */
+tcg_out_opc_andi(s, a0, a1, ~a2);
+} else {
+tcg_out_opc_andn(s, a0, a1, a2);
+}
+break;
+
+case INDEX_op_orc_i32:
+case INDEX_op_orc_i64:
+if (c2) {
+/* guaranteed to fit due to constraint */
+tcg_out_opc_ori(s, a0, a1, ~a2);
+} else {
+tcg_out_opc_orn(s, a0, a1, a2);
+}
+break;
+
+case INDEX_op_and_i32:
+case INDEX_op_and_i64:
+if (c2) {
+tcg_out_opc_andi(s, a0, a1, a2);
+} else {
+tcg_out_opc_and(s, a0, a1, a2);
+}
+break;
+
+case INDEX_op_or_i32:
+case INDEX_op_or_i64:
+if (c2) {
+tcg_out_opc_ori(s, a0, a1, a2);
+} else {
+tcg_out_opc_or(s, a0, a1, a2);
+}
+break;
+
+case INDEX_op_xor_i32:
+case INDEX_op_xor_i64:
+if (c2) {
+tcg_out_opc_xori(s, a0, a1, a2);
+} else {
+tcg_out_opc_xor(s, a0, a1, a2);
+}
+break;
+
 case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
 case INDEX_op_mov_i64:
 default:
@@ -494,8 +558,32 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_extrl_i64_i32:
 case INDEX_op_extrh_i64_i32:
 case INDEX_op_ext_i32_i64:
+case INDEX_op_not_i32:
+case INDEX_op_not_i64:
 return C_O1_I1(r, r);
 
+case INDEX_op_andc_i32:
+case INDEX_op_andc_i64:
+case INDEX_op_orc_i32:
+case INDEX_op_orc_i64:
+/*
+ * LoongArch insns for these ops don't have reg-imm forms, but we
+ * can express using andi/ori if ~constant satisfies
+ * TCG_CT_CONST_U12.
+ */
+return C_O1_I2(r, r, rC);
+
+case INDEX_op_and_i32:
+case INDEX_op_and_i64:
+case INDEX_op_nor_i32:
+case INDEX_op_nor_i64:
+case INDEX_op_or_i32:
+case INDEX_op_or_i64:
+case INDEX_op_xor_i32:
+case INDEX_op_xor_i64:
+/* LoongArch reg-imm bitops have their imms ZERO-extended */
+return C_O1_I2(r, r, rU);
+
 default:
 g_assert_not_reached();
 }
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index 2b7d5a19b9..cb1739a54a 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -113,13 +113,13 @@ typedef enum {
 #define TCG_TARGET_HAS_ext16u_i32   1
 #define TCG_TARGET_HAS_bswap16_i32  0
 #define TCG_TARGET_HAS_bswap32_i32  0
-#define TCG_TARGET_HAS_not_i32  0
+#define TCG_TARGET_HAS_not_i32  1
 #define TCG_TARGET_HAS_neg_i32  0
-#define TCG_TARGET_HAS_andc_i32 0
-#define TCG_TARGET_HAS_orc_i32  0
+#define TCG_TARGET_HAS_andc_i32 1
+#define TCG_TARGET_HAS_orc_i32  1
 #define TCG_TARGET_HAS_eqv_i32  0
 #define TCG_TARGET_HAS_nand_i32 0
-#define TCG_TARGET_HAS_nor_i32  0
+#define TCG_TARGET_HAS_nor_i32  1
 #define TCG_TARGET_HAS_clz_i32  0
 #define TCG_TARGET_HAS_ctz_i32  0
 #define TCG_TARGET_HAS_ctpop_i320
@@ -149,13 +149,13 @@ typedef enum {
 #define TCG_TARGET_HAS_bswap16_i64  0
 #define TCG_TARGET_HAS_bswap32_i64  0
 #define TCG_TARGET_HAS_bswap64_i64  0
-#define TCG_TARGET_HAS_not_i64  

[PATCH for-7.0 v8 27/31] tcg/loongarch64: Register the JIT

2021-11-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 44 
 1 file changed, 44 insertions(+)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index ff167d686b..8ce30ecae5 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1631,3 +1631,47 @@ static void tcg_target_init(TCGContext *s)
 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP);
 tcg_regset_set_reg(s->reserved_regs, TCG_REG_RESERVED);
 }
+
+typedef struct {
+DebugFrameHeader h;
+uint8_t fde_def_cfa[4];
+uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
+} DebugFrame;
+
+#define ELF_HOST_MACHINE EM_LOONGARCH
+
+static const DebugFrame debug_frame = {
+.h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */
+.h.cie.id = -1,
+.h.cie.version = 1,
+.h.cie.code_align = 1,
+.h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */
+.h.cie.return_column = TCG_REG_RA,
+
+/* Total FDE size does not include the "len" member.  */
+.h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
+
+.fde_def_cfa = {
+12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ...  */
+(FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
+(FRAME_SIZE >> 7)
+},
+.fde_reg_ofs = {
+0x80 + 23, 11,  /* DW_CFA_offset, s0, -88 */
+0x80 + 24, 10,  /* DW_CFA_offset, s1, -80 */
+0x80 + 25, 9,   /* DW_CFA_offset, s2, -72 */
+0x80 + 26, 8,   /* DW_CFA_offset, s3, -64 */
+0x80 + 27, 7,   /* DW_CFA_offset, s4, -56 */
+0x80 + 28, 6,   /* DW_CFA_offset, s5, -48 */
+0x80 + 29, 5,   /* DW_CFA_offset, s6, -40 */
+0x80 + 30, 4,   /* DW_CFA_offset, s7, -32 */
+0x80 + 31, 3,   /* DW_CFA_offset, s8, -24 */
+0x80 + 22, 2,   /* DW_CFA_offset, s9, -16 */
+0x80 + 1 , 1,   /* DW_CFA_offset, ra, -8 */
+}
+};
+
+void tcg_register_jit(const void *buf, size_t buf_size)
+{
+tcg_register_jit_int(buf, buf_size, _frame, sizeof(debug_frame));
+}
-- 
2.34.0




[PATCH for-7.0 v8 18/31] tcg/loongarch64: Implement mul/mulsh/muluh/div/divu/rem/remu ops

2021-11-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 tcg/loongarch64/tcg-target-con-set.h |  1 +
 tcg/loongarch64/tcg-target.c.inc | 65 
 tcg/loongarch64/tcg-target.h | 16 +++
 3 files changed, 74 insertions(+), 8 deletions(-)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index 4b8ce85897..fb56f3a295 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -23,3 +23,4 @@ C_O1_I2(r, r, rU)
 C_O1_I2(r, r, rW)
 C_O1_I2(r, 0, rZ)
 C_O1_I2(r, rZ, rN)
+C_O1_I2(r, rZ, rZ)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 0e6b241097..67f07a3853 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -717,6 +717,55 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 }
 break;
 
+case INDEX_op_mul_i32:
+tcg_out_opc_mul_w(s, a0, a1, a2);
+break;
+case INDEX_op_mul_i64:
+tcg_out_opc_mul_d(s, a0, a1, a2);
+break;
+
+case INDEX_op_mulsh_i32:
+tcg_out_opc_mulh_w(s, a0, a1, a2);
+break;
+case INDEX_op_mulsh_i64:
+tcg_out_opc_mulh_d(s, a0, a1, a2);
+break;
+
+case INDEX_op_muluh_i32:
+tcg_out_opc_mulh_wu(s, a0, a1, a2);
+break;
+case INDEX_op_muluh_i64:
+tcg_out_opc_mulh_du(s, a0, a1, a2);
+break;
+
+case INDEX_op_div_i32:
+tcg_out_opc_div_w(s, a0, a1, a2);
+break;
+case INDEX_op_div_i64:
+tcg_out_opc_div_d(s, a0, a1, a2);
+break;
+
+case INDEX_op_divu_i32:
+tcg_out_opc_div_wu(s, a0, a1, a2);
+break;
+case INDEX_op_divu_i64:
+tcg_out_opc_div_du(s, a0, a1, a2);
+break;
+
+case INDEX_op_rem_i32:
+tcg_out_opc_mod_w(s, a0, a1, a2);
+break;
+case INDEX_op_rem_i64:
+tcg_out_opc_mod_d(s, a0, a1, a2);
+break;
+
+case INDEX_op_remu_i32:
+tcg_out_opc_mod_wu(s, a0, a1, a2);
+break;
+case INDEX_op_remu_i64:
+tcg_out_opc_mod_du(s, a0, a1, a2);
+break;
+
 case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
 case INDEX_op_mov_i64:
 default:
@@ -808,6 +857,22 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_sub_i64:
 return C_O1_I2(r, rZ, rN);
 
+case INDEX_op_mul_i32:
+case INDEX_op_mul_i64:
+case INDEX_op_mulsh_i32:
+case INDEX_op_mulsh_i64:
+case INDEX_op_muluh_i32:
+case INDEX_op_muluh_i64:
+case INDEX_op_div_i32:
+case INDEX_op_div_i64:
+case INDEX_op_divu_i32:
+case INDEX_op_divu_i64:
+case INDEX_op_rem_i32:
+case INDEX_op_rem_i64:
+case INDEX_op_remu_i32:
+case INDEX_op_remu_i64:
+return C_O1_I2(r, rZ, rZ);
+
 default:
 g_assert_not_reached();
 }
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index e59c2a7bec..2ac2c342c7 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -93,8 +93,8 @@ typedef enum {
 
 /* optional instructions */
 #define TCG_TARGET_HAS_movcond_i32  0
-#define TCG_TARGET_HAS_div_i32  0
-#define TCG_TARGET_HAS_rem_i32  0
+#define TCG_TARGET_HAS_div_i32  1
+#define TCG_TARGET_HAS_rem_i32  1
 #define TCG_TARGET_HAS_div2_i32 0
 #define TCG_TARGET_HAS_rot_i32  1
 #define TCG_TARGET_HAS_deposit_i32  1
@@ -105,8 +105,8 @@ typedef enum {
 #define TCG_TARGET_HAS_sub2_i32 0
 #define TCG_TARGET_HAS_mulu2_i320
 #define TCG_TARGET_HAS_muls2_i320
-#define TCG_TARGET_HAS_muluh_i320
-#define TCG_TARGET_HAS_mulsh_i320
+#define TCG_TARGET_HAS_muluh_i321
+#define TCG_TARGET_HAS_mulsh_i321
 #define TCG_TARGET_HAS_ext8s_i321
 #define TCG_TARGET_HAS_ext16s_i32   1
 #define TCG_TARGET_HAS_ext8u_i321
@@ -130,8 +130,8 @@ typedef enum {
 
 /* 64-bit operations */
 #define TCG_TARGET_HAS_movcond_i64  0
-#define TCG_TARGET_HAS_div_i64  0
-#define TCG_TARGET_HAS_rem_i64  0
+#define TCG_TARGET_HAS_div_i64  1
+#define TCG_TARGET_HAS_rem_i64  1
 #define TCG_TARGET_HAS_div2_i64 0
 #define TCG_TARGET_HAS_rot_i64  1
 #define TCG_TARGET_HAS_deposit_i64  1
@@ -163,8 +163,8 @@ typedef enum {
 #define TCG_TARGET_HAS_sub2_i64 0
 #define TCG_TARGET_HAS_mulu2_i640
 #define TCG_TARGET_HAS_muls2_i640
-#define TCG_TARGET_HAS_muluh_i640
-#define TCG_TARGET_HAS_mulsh_i640
+#define TCG_TARGET_HAS_muluh_i641
+#define TCG_TARGET_HAS_mulsh_i641
 
 /* not defined -- call should be eliminated at compile time */
 void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
-- 
2.34.0




[PATCH for-7.0 v8 08/31] tcg/loongarch64: Implement the memory barrier op

2021-11-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 tcg/loongarch64/tcg-target.c.inc | 32 
 1 file changed, 32 insertions(+)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index fbacaef862..f12955723d 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -234,3 +234,35 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
 g_assert_not_reached();
 }
 }
+
+#include "tcg-insn-defs.c.inc"
+
+/*
+ * TCG intrinsics
+ */
+
+static void tcg_out_mb(TCGContext *s, TCGArg a0)
+{
+/* Baseline LoongArch only has the full barrier, unfortunately.  */
+tcg_out_opc_dbar(s, 0);
+}
+
+/*
+ * Entry-points
+ */
+
+static void tcg_out_op(TCGContext *s, TCGOpcode opc,
+   const TCGArg args[TCG_MAX_OP_ARGS],
+   const int const_args[TCG_MAX_OP_ARGS])
+{
+TCGArg a0 = args[0];
+
+switch (opc) {
+case INDEX_op_mb:
+tcg_out_mb(s, a0);
+break;
+
+default:
+g_assert_not_reached();
+}
+}
-- 
2.34.0




[PATCH for-7.0 v8 25/31] tcg/loongarch64: Implement exit_tb/goto_tb

2021-11-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index a806e3352e..2d066a035d 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -980,6 +980,25 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 int c2 = const_args[2];
 
 switch (opc) {
+case INDEX_op_exit_tb:
+/* Reuse the zeroing that exists for goto_ptr.  */
+if (a0 == 0) {
+tcg_out_call_int(s, tcg_code_gen_epilogue, true);
+} else {
+tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0);
+tcg_out_call_int(s, tb_ret_addr, true);
+}
+break;
+
+case INDEX_op_goto_tb:
+assert(s->tb_jmp_insn_offset == 0);
+/* indirect jump method */
+tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO,
+   (uintptr_t)(s->tb_jmp_target_addr + a0));
+tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_TMP0, 0);
+set_jmp_reset_offset(s, a0);
+break;
+
 case INDEX_op_mb:
 tcg_out_mb(s, a0);
 break;
-- 
2.34.0




[PATCH for-7.0 v8 23/31] tcg/loongarch64: Add softmmu load/store helpers, implement qemu_ld/qemu_st ops

2021-11-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target-con-set.h |   2 +
 tcg/loongarch64/tcg-target.c.inc | 353 +++
 2 files changed, 355 insertions(+)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index e54ca9b2de..349c672687 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -17,7 +17,9 @@
 C_O0_I1(r)
 C_O0_I2(rZ, r)
 C_O0_I2(rZ, rZ)
+C_O0_I2(LZ, L)
 C_O1_I1(r, r)
+C_O1_I1(r, L)
 C_O1_I2(r, r, rC)
 C_O1_I2(r, r, ri)
 C_O1_I2(r, r, rI)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index fec22cfaf6..c92587c823 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -117,6 +117,11 @@ static const int tcg_target_call_oarg_regs[] = {
 TCG_REG_A1,
 };
 
+#ifndef CONFIG_SOFTMMU
+#define USE_GUEST_BASE (guest_base != 0)
+#define TCG_GUEST_BASE_REG TCG_REG_S1
+#endif
+
 #define TCG_CT_CONST_ZERO  0x100
 #define TCG_CT_CONST_S12   0x200
 #define TCG_CT_CONST_N12   0x400
@@ -632,6 +637,333 @@ static bool tcg_out_sti(TCGContext *s, TCGType type, 
TCGArg val,
 return false;
 }
 
+/*
+ * Load/store helpers for SoftMMU, and qemu_ld/st implementations
+ */
+
+#if defined(CONFIG_SOFTMMU)
+#include "../tcg-ldst.c.inc"
+
+/*
+ * helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
+ * MemOpIdx oi, uintptr_t ra)
+ */
+static void * const qemu_ld_helpers[4] = {
+[MO_8]  = helper_ret_ldub_mmu,
+[MO_16] = helper_le_lduw_mmu,
+[MO_32] = helper_le_ldul_mmu,
+[MO_64] = helper_le_ldq_mmu,
+};
+
+/*
+ * helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
+ * uintxx_t val, MemOpIdx oi,
+ * uintptr_t ra)
+ */
+static void * const qemu_st_helpers[4] = {
+[MO_8]  = helper_ret_stb_mmu,
+[MO_16] = helper_le_stw_mmu,
+[MO_32] = helper_le_stl_mmu,
+[MO_64] = helper_le_stq_mmu,
+};
+
+/* We expect to use a 12-bit negative offset from ENV.  */
+QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
+QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -(1 << 11));
+
+static bool tcg_out_goto(TCGContext *s, const tcg_insn_unit *target)
+{
+tcg_out_opc_b(s, 0);
+return reloc_br_sd10k16(s->code_ptr - 1, target);
+}
+
+/*
+ * Emits common code for TLB addend lookup, that eventually loads the
+ * addend in TCG_REG_TMP2.
+ */
+static void tcg_out_tlb_load(TCGContext *s, TCGReg addrl, MemOpIdx oi,
+ tcg_insn_unit **label_ptr, bool is_load)
+{
+MemOp opc = get_memop(oi);
+unsigned s_bits = opc & MO_SIZE;
+unsigned a_bits = get_alignment_bits(opc);
+tcg_target_long compare_mask;
+int mem_index = get_mmuidx(oi);
+int fast_ofs = TLB_MASK_TABLE_OFS(mem_index);
+int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask);
+int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table);
+
+tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs);
+tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs);
+
+tcg_out_opc_srli_d(s, TCG_REG_TMP2, addrl,
+TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
+tcg_out_opc_and(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0);
+tcg_out_opc_add_d(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1);
+
+/* Load the tlb comparator and the addend.  */
+tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_TMP0, TCG_REG_TMP2,
+   is_load ? offsetof(CPUTLBEntry, addr_read)
+   : offsetof(CPUTLBEntry, addr_write));
+tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2,
+   offsetof(CPUTLBEntry, addend));
+
+/* We don't support unaligned accesses.  */
+if (a_bits < s_bits) {
+a_bits = s_bits;
+}
+/* Clear the non-page, non-alignment bits from the address.  */
+compare_mask = (tcg_target_long)TARGET_PAGE_MASK | ((1 << a_bits) - 1);
+tcg_out_movi(s, TCG_TYPE_TL, TCG_REG_TMP1, compare_mask);
+tcg_out_opc_and(s, TCG_REG_TMP1, TCG_REG_TMP1, addrl);
+
+/* Compare masked address with the TLB entry.  */
+label_ptr[0] = s->code_ptr;
+tcg_out_opc_bne(s, TCG_REG_TMP0, TCG_REG_TMP1, 0);
+
+/* TLB Hit - addend in TCG_REG_TMP2, ready for use.  */
+}
+
+static void add_qemu_ldst_label(TCGContext *s, int is_ld, MemOpIdx oi,
+TCGType type,
+TCGReg datalo, TCGReg addrlo,
+void *raddr, tcg_insn_unit **label_ptr)
+{
+TCGLabelQemuLdst *label = new_ldst_label(s);
+
+label->is_ld = is_ld;
+label->oi = oi;
+label->type = type;
+label->datalo_reg = datalo;
+label->datahi_reg = 0; /* unused */
+label->addrlo_reg = addrlo;
+label->addrhi_reg = 0; /* unused */
+label->raddr = tcg_splitwx_to_rx(raddr);
+label->label_ptr[0] = label_ptr[0];
+}
+
+static bool 

[PATCH for-7.0 v8 21/31] tcg/loongarch64: Implement tcg_out_call

2021-11-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 34 
 1 file changed, 34 insertions(+)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 682bf76ceb..e470d7e145 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -532,6 +532,39 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, 
TCGReg arg1,
 tcg_out32(s, encode_djsk16_insn(op, arg1, arg2, 0));
 }
 
+static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool 
tail)
+{
+TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA;
+ptrdiff_t offset = tcg_pcrel_diff(s, arg);
+
+tcg_debug_assert((offset & 3) == 0);
+if (offset == sextreg(offset, 0, 28)) {
+/* short jump: +/- 256MiB */
+if (tail) {
+tcg_out_opc_b(s, offset >> 2);
+} else {
+tcg_out_opc_bl(s, offset >> 2);
+}
+} else if (offset == sextreg(offset, 0, 38)) {
+/* long jump: +/- 256GiB */
+tcg_target_long lo = sextreg(offset, 0, 18);
+tcg_target_long hi = offset - lo;
+tcg_out_opc_pcaddu18i(s, TCG_REG_TMP0, hi >> 18);
+tcg_out_opc_jirl(s, link, TCG_REG_TMP0, lo >> 2);
+} else {
+/* far jump: 64-bit */
+tcg_target_long lo = sextreg((tcg_target_long)arg, 0, 18);
+tcg_target_long hi = (tcg_target_long)arg - lo;
+tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, hi);
+tcg_out_opc_jirl(s, link, TCG_REG_TMP0, lo >> 2);
+}
+}
+
+static void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg)
+{
+tcg_out_call_int(s, arg, false);
+}
+
 /*
  * Entry-points
  */
@@ -882,6 +915,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 
 case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
 case INDEX_op_mov_i64:
+case INDEX_op_call: /* Always emitted via tcg_out_call.  */
 default:
 g_assert_not_reached();
 }
-- 
2.34.0




[PATCH for-7.0 v8 19/31] tcg/loongarch64: Implement br/brcond ops

2021-11-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 tcg/loongarch64/tcg-target-con-set.h |  1 +
 tcg/loongarch64/tcg-target.c.inc | 53 
 2 files changed, 54 insertions(+)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index fb56f3a295..367689c2e2 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -15,6 +15,7 @@
  * tcg-target-con-str.h; the constraint combination is inclusive or.
  */
 C_O0_I1(r)
+C_O0_I2(rZ, rZ)
 C_O1_I1(r, r)
 C_O1_I2(r, r, rC)
 C_O1_I2(r, r, ri)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 67f07a3853..816b16f10f 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -434,6 +434,44 @@ static void tcg_out_clzctz(TCGContext *s, LoongArchInsn 
opc,
 tcg_out_opc_or(s, a0, TCG_REG_TMP0, a0);
 }
 
+/*
+ * Branch helpers
+ */
+
+static const struct {
+LoongArchInsn op;
+bool swap;
+} tcg_brcond_to_loongarch[] = {
+[TCG_COND_EQ] =  { OPC_BEQ,  false },
+[TCG_COND_NE] =  { OPC_BNE,  false },
+[TCG_COND_LT] =  { OPC_BGT,  true  },
+[TCG_COND_GE] =  { OPC_BLE,  true  },
+[TCG_COND_LE] =  { OPC_BLE,  false },
+[TCG_COND_GT] =  { OPC_BGT,  false },
+[TCG_COND_LTU] = { OPC_BGTU, true  },
+[TCG_COND_GEU] = { OPC_BLEU, true  },
+[TCG_COND_LEU] = { OPC_BLEU, false },
+[TCG_COND_GTU] = { OPC_BGTU, false }
+};
+
+static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
+   TCGReg arg2, TCGLabel *l)
+{
+LoongArchInsn op = tcg_brcond_to_loongarch[cond].op;
+
+tcg_debug_assert(op != 0);
+
+if (tcg_brcond_to_loongarch[cond].swap) {
+TCGReg t = arg1;
+arg1 = arg2;
+arg2 = t;
+}
+
+/* all conditional branch insns belong to DJSk16-format */
+tcg_out_reloc(s, s->code_ptr, R_LOONGARCH_BR_SK16, l, 0);
+tcg_out32(s, encode_djsk16_insn(op, arg1, arg2, 0));
+}
+
 /*
  * Entry-points
  */
@@ -456,6 +494,17 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 tcg_out_opc_jirl(s, TCG_REG_ZERO, a0, 0);
 break;
 
+case INDEX_op_br:
+tcg_out_reloc(s, s->code_ptr, R_LOONGARCH_BR_SD10K16, arg_label(a0),
+  0);
+tcg_out_opc_b(s, 0);
+break;
+
+case INDEX_op_brcond_i32:
+case INDEX_op_brcond_i64:
+tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
+break;
+
 case INDEX_op_ext8s_i32:
 case INDEX_op_ext8s_i64:
 tcg_out_ext8s(s, a0, a1);
@@ -779,6 +828,10 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_goto_ptr:
 return C_O0_I1(r);
 
+case INDEX_op_brcond_i32:
+case INDEX_op_brcond_i64:
+return C_O0_I2(rZ, rZ);
+
 case INDEX_op_ext8s_i32:
 case INDEX_op_ext8s_i64:
 case INDEX_op_ext8u_i32:
-- 
2.34.0




  1   2   3   4   >