[PATCH v3 08/16] tcg/loongarch64: Lower mul_vec to vmul

2023-09-01 Thread Jiajie Chen
Signed-off-by: Jiajie Chen 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 8 
 tcg/loongarch64/tcg-target.h | 2 +-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 1e196bb68f..6905775698 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1665,6 +1665,9 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 static const LoongArchInsn neg_vec_insn[4] = {
 OPC_VNEG_B, OPC_VNEG_H, OPC_VNEG_W, OPC_VNEG_D
 };
+static const LoongArchInsn mul_vec_insn[4] = {
+OPC_VMUL_B, OPC_VMUL_H, OPC_VMUL_W, OPC_VMUL_D
+};
 
 a0 = args[0];
 a1 = args[1];
@@ -1798,6 +1801,9 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 case INDEX_op_neg_vec:
 tcg_out32(s, encode_vdvj_insn(neg_vec_insn[vece], a0, a1));
 break;
+case INDEX_op_mul_vec:
+tcg_out32(s, encode_vdvjvk_insn(mul_vec_insn[vece], a0, a1, a2));
+break;
 case INDEX_op_dupm_vec:
 tcg_out_dupm_vec(s, type, vece, a0, a1, a2);
 break;
@@ -1824,6 +1830,7 @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, 
unsigned vece)
 case INDEX_op_nor_vec:
 case INDEX_op_not_vec:
 case INDEX_op_neg_vec:
+case INDEX_op_mul_vec:
 return 1;
 default:
 return 0;
@@ -1998,6 +2005,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_orc_vec:
 case INDEX_op_xor_vec:
 case INDEX_op_nor_vec:
+case INDEX_op_mul_vec:
 return C_O1_I2(w, w, w);
 
 case INDEX_op_not_vec:
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index 64c72d0857..2c2266ed31 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -185,7 +185,7 @@ extern bool use_lsx_instructions;
 #define TCG_TARGET_HAS_nand_vec 0
 #define TCG_TARGET_HAS_nor_vec  1
 #define TCG_TARGET_HAS_eqv_vec  0
-#define TCG_TARGET_HAS_mul_vec  0
+#define TCG_TARGET_HAS_mul_vec  1
 #define TCG_TARGET_HAS_shi_vec  0
 #define TCG_TARGET_HAS_shs_vec  0
 #define TCG_TARGET_HAS_shv_vec  0
-- 
2.42.0




[PATCH v3 10/16] tcg/loongarch64: Lower vector saturated ops

2023-09-01 Thread Jiajie Chen
Lower the following ops:

- ssadd_vec
- usadd_vec
- sssub_vec
- ussub_vec

Signed-off-by: Jiajie Chen 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 32 
 tcg/loongarch64/tcg-target.h |  2 +-
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 3ffc1691cd..89db41002c 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1680,6 +1680,18 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 static const LoongArchInsn umax_vec_insn[4] = {
 OPC_VMAX_BU, OPC_VMAX_HU, OPC_VMAX_WU, OPC_VMAX_DU
 };
+static const LoongArchInsn ssadd_vec_insn[4] = {
+OPC_VSADD_B, OPC_VSADD_H, OPC_VSADD_W, OPC_VSADD_D
+};
+static const LoongArchInsn usadd_vec_insn[4] = {
+OPC_VSADD_BU, OPC_VSADD_HU, OPC_VSADD_WU, OPC_VSADD_DU
+};
+static const LoongArchInsn sssub_vec_insn[4] = {
+OPC_VSSUB_B, OPC_VSSUB_H, OPC_VSSUB_W, OPC_VSSUB_D
+};
+static const LoongArchInsn ussub_vec_insn[4] = {
+OPC_VSSUB_BU, OPC_VSSUB_HU, OPC_VSSUB_WU, OPC_VSSUB_DU
+};
 
 a0 = args[0];
 a1 = args[1];
@@ -1828,6 +1840,18 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 case INDEX_op_umax_vec:
 tcg_out32(s, encode_vdvjvk_insn(umax_vec_insn[vece], a0, a1, a2));
 break;
+case INDEX_op_ssadd_vec:
+tcg_out32(s, encode_vdvjvk_insn(ssadd_vec_insn[vece], a0, a1, a2));
+break;
+case INDEX_op_usadd_vec:
+tcg_out32(s, encode_vdvjvk_insn(usadd_vec_insn[vece], a0, a1, a2));
+break;
+case INDEX_op_sssub_vec:
+tcg_out32(s, encode_vdvjvk_insn(sssub_vec_insn[vece], a0, a1, a2));
+break;
+case INDEX_op_ussub_vec:
+tcg_out32(s, encode_vdvjvk_insn(ussub_vec_insn[vece], a0, a1, a2));
+break;
 case INDEX_op_dupm_vec:
 tcg_out_dupm_vec(s, type, vece, a0, a1, a2);
 break;
@@ -1859,6 +1883,10 @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, 
unsigned vece)
 case INDEX_op_smax_vec:
 case INDEX_op_umin_vec:
 case INDEX_op_umax_vec:
+case INDEX_op_ssadd_vec:
+case INDEX_op_usadd_vec:
+case INDEX_op_sssub_vec:
+case INDEX_op_ussub_vec:
 return 1;
 default:
 return 0;
@@ -2038,6 +2066,10 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_smax_vec:
 case INDEX_op_umin_vec:
 case INDEX_op_umax_vec:
+case INDEX_op_ssadd_vec:
+case INDEX_op_usadd_vec:
+case INDEX_op_sssub_vec:
+case INDEX_op_ussub_vec:
 return C_O1_I2(w, w, w);
 
 case INDEX_op_not_vec:
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index ec725aaeaa..fa14558275 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -192,7 +192,7 @@ extern bool use_lsx_instructions;
 #define TCG_TARGET_HAS_roti_vec 0
 #define TCG_TARGET_HAS_rots_vec 0
 #define TCG_TARGET_HAS_rotv_vec 0
-#define TCG_TARGET_HAS_sat_vec  0
+#define TCG_TARGET_HAS_sat_vec  1
 #define TCG_TARGET_HAS_minmax_vec   1
 #define TCG_TARGET_HAS_bitsel_vec   0
 #define TCG_TARGET_HAS_cmpsel_vec   0
-- 
2.42.0




[PATCH v3 05/16] tcg/loongarch64: Lower add/sub_vec to vadd/vsub

2023-09-01 Thread Jiajie Chen
Lower the following ops:

- add_vec
- sub_vec

Signed-off-by: Jiajie Chen 
---
 tcg/loongarch64/tcg-target-con-set.h |  1 +
 tcg/loongarch64/tcg-target-con-str.h |  1 +
 tcg/loongarch64/tcg-target.c.inc | 60 
 3 files changed, 62 insertions(+)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index 8c8ea5d919..2d5dce75c3 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -32,4 +32,5 @@ C_O1_I2(r, rZ, ri)
 C_O1_I2(r, rZ, rJ)
 C_O1_I2(r, rZ, rZ)
 C_O1_I2(w, w, wM)
+C_O1_I2(w, w, wA)
 C_O1_I4(r, rZ, rJ, rZ, rZ)
diff --git a/tcg/loongarch64/tcg-target-con-str.h 
b/tcg/loongarch64/tcg-target-con-str.h
index a8a1c44014..2ba9c135ac 100644
--- a/tcg/loongarch64/tcg-target-con-str.h
+++ b/tcg/loongarch64/tcg-target-con-str.h
@@ -27,3 +27,4 @@ CONST('Z', TCG_CT_CONST_ZERO)
 CONST('C', TCG_CT_CONST_C12)
 CONST('W', TCG_CT_CONST_WSZ)
 CONST('M', TCG_CT_CONST_VCMP)
+CONST('A', TCG_CT_CONST_VADD)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 129dd92910..0edcf5be35 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -177,6 +177,7 @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind 
kind, int slot)
 #define TCG_CT_CONST_C12   0x1000
 #define TCG_CT_CONST_WSZ   0x2000
 #define TCG_CT_CONST_VCMP  0x4000
+#define TCG_CT_CONST_VADD  0x8000
 
 #define ALL_GENERAL_REGS   MAKE_64BIT_MASK(0, 32)
 #define ALL_VECTOR_REGSMAKE_64BIT_MASK(32, 32)
@@ -214,6 +215,9 @@ static bool tcg_target_const_match(int64_t val, TCGType 
type, int ct, int vece)
 if ((ct & TCG_CT_CONST_VCMP) && -0x10 <= vec_val && vec_val <= 0x1f) {
 return true;
 }
+if ((ct & TCG_CT_CONST_VADD) && -0x1f <= vec_val && vec_val <= 0x1f) {
+return true;
+}
 return false;
 }
 
@@ -1646,6 +1650,18 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 [TCG_COND_LTU] = {OPC_VSLTI_BU, OPC_VSLTI_HU, OPC_VSLTI_WU, 
OPC_VSLTI_DU},
 };
 LoongArchInsn insn;
+static const LoongArchInsn add_vec_insn[4] = {
+OPC_VADD_B, OPC_VADD_H, OPC_VADD_W, OPC_VADD_D
+};
+static const LoongArchInsn add_vec_imm_insn[4] = {
+OPC_VADDI_BU, OPC_VADDI_HU, OPC_VADDI_WU, OPC_VADDI_DU
+};
+static const LoongArchInsn sub_vec_insn[4] = {
+OPC_VSUB_B, OPC_VSUB_H, OPC_VSUB_W, OPC_VSUB_D
+};
+static const LoongArchInsn sub_vec_imm_insn[4] = {
+OPC_VSUBI_BU, OPC_VSUBI_HU, OPC_VSUBI_WU, OPC_VSUBI_DU
+};
 
 a0 = args[0];
 a1 = args[1];
@@ -1712,6 +1728,44 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 }
 tcg_out32(s, encode_vdvjvk_insn(insn, a0, a1, a2));
 break;
+case INDEX_op_add_vec:
+if (const_args[2]) {
+int64_t value = sextract64(a2, 0, 8 << vece);
+/* Try vaddi/vsubi */
+if (0 <= value && value <= 0x1f) {
+tcg_out32(s, encode_vdvjuk5_insn(add_vec_imm_insn[vece], a0, \
+ a1, value));
+break;
+} else if (-0x1f <= value && value < 0) {
+tcg_out32(s, encode_vdvjuk5_insn(sub_vec_imm_insn[vece], a0, \
+ a1, -value));
+break;
+}
+
+/* constraint TCG_CT_CONST_VADD ensures unreachable */
+g_assert_not_reached();
+}
+tcg_out32(s, encode_vdvjvk_insn(add_vec_insn[vece], a0, a1, a2));
+break;
+case INDEX_op_sub_vec:
+if (const_args[2]) {
+int64_t value = sextract64(a2, 0, 8 << vece);
+/* Try vaddi/vsubi */
+if (0 <= value && value <= 0x1f) {
+tcg_out32(s, encode_vdvjuk5_insn(sub_vec_imm_insn[vece], a0, \
+ a1, value));
+break;
+} else if (-0x1f <= value && value < 0) {
+tcg_out32(s, encode_vdvjuk5_insn(add_vec_imm_insn[vece], a0, \
+ a1, -value));
+break;
+}
+
+/* constraint TCG_CT_CONST_VADD ensures unreachable */
+g_assert_not_reached();
+}
+tcg_out32(s, encode_vdvjvk_insn(sub_vec_insn[vece], a0, a1, a2));
+break;
 case INDEX_op_dupm_vec:
 tcg_out_dupm_vec(s, type, vece, a0, a1, a2);
 break;
@@ -1728,6 +1782,8 @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, 
unsigned vece)
 case INDEX_op_dup_vec:
 case INDEX_op_dupm_vec:
 case INDEX_op_cmp_vec:
+case INDEX_op_add_vec:
+case INDEX_op_sub_vec:
 return 1;
 default:
 return 0;
@@ -1892,6 +1948,10 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_cmp_vec:
 return C_O1_I2(w, w, wM);
 
+case INDEX_op_add_vec:
+case INDEX_op_sub_vec:
+

[PATCH v3 07/16] tcg/loongarch64: Lower neg_vec to vneg

2023-09-01 Thread Jiajie Chen
Signed-off-by: Jiajie Chen 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 8 
 tcg/loongarch64/tcg-target.h | 2 +-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 133b0f7113..1e196bb68f 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1662,6 +1662,9 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 static const LoongArchInsn sub_vec_imm_insn[4] = {
 OPC_VSUBI_BU, OPC_VSUBI_HU, OPC_VSUBI_WU, OPC_VSUBI_DU
 };
+static const LoongArchInsn neg_vec_insn[4] = {
+OPC_VNEG_B, OPC_VNEG_H, OPC_VNEG_W, OPC_VNEG_D
+};
 
 a0 = args[0];
 a1 = args[1];
@@ -1792,6 +1795,9 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 }
 tcg_out32(s, encode_vdvjvk_insn(sub_vec_insn[vece], a0, a1, a2));
 break;
+case INDEX_op_neg_vec:
+tcg_out32(s, encode_vdvj_insn(neg_vec_insn[vece], a0, a1));
+break;
 case INDEX_op_dupm_vec:
 tcg_out_dupm_vec(s, type, vece, a0, a1, a2);
 break;
@@ -1817,6 +1823,7 @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, 
unsigned vece)
 case INDEX_op_xor_vec:
 case INDEX_op_nor_vec:
 case INDEX_op_not_vec:
+case INDEX_op_neg_vec:
 return 1;
 default:
 return 0;
@@ -1994,6 +2001,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 return C_O1_I2(w, w, w);
 
 case INDEX_op_not_vec:
+case INDEX_op_neg_vec:
 return C_O1_I1(w, w);
 
 default:
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index f9c5cb12ca..64c72d0857 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -178,7 +178,7 @@ extern bool use_lsx_instructions;
 #define TCG_TARGET_HAS_v256 0
 
 #define TCG_TARGET_HAS_not_vec  1
-#define TCG_TARGET_HAS_neg_vec  0
+#define TCG_TARGET_HAS_neg_vec  1
 #define TCG_TARGET_HAS_abs_vec  0
 #define TCG_TARGET_HAS_andc_vec 1
 #define TCG_TARGET_HAS_orc_vec  1
-- 
2.42.0




[PATCH v3 14/16] tcg/loongarch64: Lower rotv_vec ops to LSX

2023-09-01 Thread Jiajie Chen
Lower the following ops:

- rotrv_vec
- rotlv_vec

Signed-off-by: Jiajie Chen 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 14 ++
 tcg/loongarch64/tcg-target.h |  2 +-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 8ac008b907..95359b1757 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1710,6 +1710,9 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 static const LoongArchInsn sari_vec_insn[4] = {
 OPC_VSRAI_B, OPC_VSRAI_H, OPC_VSRAI_W, OPC_VSRAI_D
 };
+static const LoongArchInsn rotrv_vec_insn[4] = {
+OPC_VROTR_B, OPC_VROTR_H, OPC_VROTR_W, OPC_VROTR_D
+};
 
 a0 = args[0];
 a1 = args[1];
@@ -1889,6 +1892,15 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 case INDEX_op_sari_vec:
 tcg_out32(s, encode_vdvjuk3_insn(sari_vec_insn[vece], a0, a1, a2));
 break;
+case INDEX_op_rotrv_vec:
+tcg_out32(s, encode_vdvjvk_insn(rotrv_vec_insn[vece], a0, a1, a2));
+break;
+case INDEX_op_rotlv_vec:
+/* rotlv_vec a1, a2 = rotrv_vec a1, -a2 */
+tcg_out32(s, encode_vdvj_insn(neg_vec_insn[vece], temp_vec, a2));
+tcg_out32(s, encode_vdvjvk_insn(rotrv_vec_insn[vece], a0, a1,
+temp_vec));
+break;
 case INDEX_op_bitsel_vec:
 /* vbitsel vd, vj, vk, va = bitsel_vec vd, va, vk, vj */
 tcg_out_opc_vbitsel_v(s, a0, a3, a2, a1);
@@ -2118,6 +2130,8 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_shlv_vec:
 case INDEX_op_shrv_vec:
 case INDEX_op_sarv_vec:
+case INDEX_op_rotrv_vec:
+case INDEX_op_rotlv_vec:
 return C_O1_I2(w, w, w);
 
 case INDEX_op_not_vec:
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index d7b806e252..d5c69bc192 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -191,7 +191,7 @@ extern bool use_lsx_instructions;
 #define TCG_TARGET_HAS_shv_vec  1
 #define TCG_TARGET_HAS_roti_vec 0
 #define TCG_TARGET_HAS_rots_vec 0
-#define TCG_TARGET_HAS_rotv_vec 0
+#define TCG_TARGET_HAS_rotv_vec 1
 #define TCG_TARGET_HAS_sat_vec  1
 #define TCG_TARGET_HAS_minmax_vec   1
 #define TCG_TARGET_HAS_bitsel_vec   1
-- 
2.42.0




[PATCH v3 02/16] tcg/loongarch64: Lower basic tcg vec ops to LSX

2023-09-01 Thread Jiajie Chen
LSX support on host cpu is detected via hwcap.

Lower the following ops to LSX:

- dup_vec
- dupi_vec
- dupm_vec
- ld_vec
- st_vec

Signed-off-by: Jiajie Chen 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target-con-set.h |   2 +
 tcg/loongarch64/tcg-target-con-str.h |   1 +
 tcg/loongarch64/tcg-target.c.inc | 219 ++-
 tcg/loongarch64/tcg-target.h |  38 -
 tcg/loongarch64/tcg-target.opc.h |  12 ++
 5 files changed, 270 insertions(+), 2 deletions(-)
 create mode 100644 tcg/loongarch64/tcg-target.opc.h

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index c2bde44613..37b3f80bf9 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(w, r)
 C_O1_I1(r, r)
+C_O1_I1(w, r)
 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-con-str.h 
b/tcg/loongarch64/tcg-target-con-str.h
index 6e9ccca3ad..81b8d40278 100644
--- a/tcg/loongarch64/tcg-target-con-str.h
+++ b/tcg/loongarch64/tcg-target-con-str.h
@@ -14,6 +14,7 @@
  * REGS(letter, register_mask)
  */
 REGS('r', ALL_GENERAL_REGS)
+REGS('w', ALL_VECTOR_REGS)
 
 /*
  * Define constraint letters for constants:
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index baf5fc3819..150278e112 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -32,6 +32,8 @@
 #include "../tcg-ldst.c.inc"
 #include 
 
+bool use_lsx_instructions;
+
 #ifdef CONFIG_DEBUG_TCG
 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
 "zero",
@@ -65,7 +67,39 @@ static const char * const 
tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
 "s5",
 "s6",
 "s7",
-"s8"
+"s8",
+"vr0",
+"vr1",
+"vr2",
+"vr3",
+"vr4",
+"vr5",
+"vr6",
+"vr7",
+"vr8",
+"vr9",
+"vr10",
+"vr11",
+"vr12",
+"vr13",
+"vr14",
+"vr15",
+"vr16",
+"vr17",
+"vr18",
+"vr19",
+"vr20",
+"vr21",
+"vr22",
+"vr23",
+"vr24",
+"vr25",
+"vr26",
+"vr27",
+"vr28",
+"vr29",
+"vr30",
+"vr31",
 };
 #endif
 
@@ -102,6 +136,15 @@ static const int tcg_target_reg_alloc_order[] = {
 TCG_REG_A2,
 TCG_REG_A1,
 TCG_REG_A0,
+
+/* Vector registers */
+TCG_REG_V0, TCG_REG_V1, TCG_REG_V2, TCG_REG_V3,
+TCG_REG_V4, TCG_REG_V5, TCG_REG_V6, TCG_REG_V7,
+TCG_REG_V8, TCG_REG_V9, TCG_REG_V10, TCG_REG_V11,
+TCG_REG_V12, TCG_REG_V13, TCG_REG_V14, TCG_REG_V15,
+TCG_REG_V16, TCG_REG_V17, TCG_REG_V18, TCG_REG_V19,
+TCG_REG_V20, TCG_REG_V21, TCG_REG_V22, TCG_REG_V23,
+/* V24 - V31 are caller-saved, and skipped.  */
 };
 
 static const int tcg_target_call_iarg_regs[] = {
@@ -135,6 +178,7 @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind 
kind, int slot)
 #define TCG_CT_CONST_WSZ   0x2000
 
 #define ALL_GENERAL_REGS   MAKE_64BIT_MASK(0, 32)
+#define ALL_VECTOR_REGSMAKE_64BIT_MASK(32, 32)
 
 static inline tcg_target_long sextreg(tcg_target_long val, int pos, int len)
 {
@@ -1486,6 +1530,154 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 }
 }
 
+static bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece,
+TCGReg rd, TCGReg rs)
+{
+switch (vece) {
+case MO_8:
+tcg_out_opc_vreplgr2vr_b(s, rd, rs);
+break;
+case MO_16:
+tcg_out_opc_vreplgr2vr_h(s, rd, rs);
+break;
+case MO_32:
+tcg_out_opc_vreplgr2vr_w(s, rd, rs);
+break;
+case MO_64:
+tcg_out_opc_vreplgr2vr_d(s, rd, rs);
+break;
+default:
+g_assert_not_reached();
+}
+return true;
+}
+
+static bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece,
+ TCGReg r, TCGReg base, intptr_t offset)
+{
+/* Handle imm overflow and division (vldrepl.d imm is divided by 8) */
+if (offset < -0x800 || offset > 0x7ff || \
+(offset & ((1 << vece) - 1)) != 0) {
+tcg_out_addi(s, TCG_TYPE_I64, TCG_REG_TMP0, base, offset);
+base = TCG_REG_TMP0;
+offset = 0;
+}
+offset >>= vece;
+
+switch (vece) {
+case MO_8:
+tcg_out_opc_vldrepl_b(s, r, base, offset);
+break;
+case MO_16:
+tcg_out_opc_vldrepl_h(s, r, base, offset);
+break;
+case MO_32:
+tcg_out_opc_vldrepl_w(s, r, base, offset);
+break;
+case MO_64:
+tcg_out_opc_vldrepl_d(s, r, base, offset);
+break;
+default:
+g_assert_not_reached();
+}
+return true;
+}
+
+static void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece,
+ TCGReg rd, int64_t v64)
+{
+/* Try vldi if imm can fit */
+int64_t value = sextract64(v64, 0, 8 << vece);
+if (-0x200 <= value && value <= 0x1FF) {
+

[PATCH v3 06/16] tcg/loongarch64: Lower vector bitwise operations

2023-09-01 Thread Jiajie Chen
Lower the following ops:

- and_vec
- andc_vec
- or_vec
- orc_vec
- xor_vec
- nor_vec
- not_vec

Signed-off-by: Jiajie Chen 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target-con-set.h |  2 ++
 tcg/loongarch64/tcg-target.c.inc | 44 
 tcg/loongarch64/tcg-target.h |  8 ++---
 3 files changed, 50 insertions(+), 4 deletions(-)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index 2d5dce75c3..3f530ad4d8 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -20,6 +20,7 @@ C_O0_I2(rZ, rZ)
 C_O0_I2(w, r)
 C_O1_I1(r, r)
 C_O1_I1(w, r)
+C_O1_I1(w, w)
 C_O1_I2(r, r, rC)
 C_O1_I2(r, r, ri)
 C_O1_I2(r, r, rI)
@@ -31,6 +32,7 @@ C_O1_I2(r, 0, rZ)
 C_O1_I2(r, rZ, ri)
 C_O1_I2(r, rZ, rJ)
 C_O1_I2(r, rZ, rZ)
+C_O1_I2(w, w, w)
 C_O1_I2(w, w, wM)
 C_O1_I2(w, w, wA)
 C_O1_I4(r, rZ, rJ, rZ, rZ)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 0edcf5be35..133b0f7113 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1689,6 +1689,32 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 tcg_out_opc_vldx(s, a0, a1, temp);
 }
 break;
+case INDEX_op_and_vec:
+tcg_out_opc_vand_v(s, a0, a1, a2);
+break;
+case INDEX_op_andc_vec:
+/*
+ * vandn vd, vj, vk: vd = vk & ~vj
+ * andc_vec vd, vj, vk: vd = vj & ~vk
+ * vk and vk are swapped
+ */
+tcg_out_opc_vandn_v(s, a0, a2, a1);
+break;
+case INDEX_op_or_vec:
+tcg_out_opc_vor_v(s, a0, a1, a2);
+break;
+case INDEX_op_orc_vec:
+tcg_out_opc_vorn_v(s, a0, a1, a2);
+break;
+case INDEX_op_xor_vec:
+tcg_out_opc_vxor_v(s, a0, a1, a2);
+break;
+case INDEX_op_nor_vec:
+tcg_out_opc_vnor_v(s, a0, a1, a2);
+break;
+case INDEX_op_not_vec:
+tcg_out_opc_vnor_v(s, a0, a1, a1);
+break;
 case INDEX_op_cmp_vec:
 TCGCond cond = args[3];
 if (const_args[2]) {
@@ -1784,6 +1810,13 @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, 
unsigned vece)
 case INDEX_op_cmp_vec:
 case INDEX_op_add_vec:
 case INDEX_op_sub_vec:
+case INDEX_op_and_vec:
+case INDEX_op_andc_vec:
+case INDEX_op_or_vec:
+case INDEX_op_orc_vec:
+case INDEX_op_xor_vec:
+case INDEX_op_nor_vec:
+case INDEX_op_not_vec:
 return 1;
 default:
 return 0;
@@ -1952,6 +1985,17 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_sub_vec:
 return C_O1_I2(w, w, wA);
 
+case INDEX_op_and_vec:
+case INDEX_op_andc_vec:
+case INDEX_op_or_vec:
+case INDEX_op_orc_vec:
+case INDEX_op_xor_vec:
+case INDEX_op_nor_vec:
+return C_O1_I2(w, w, w);
+
+case INDEX_op_not_vec:
+return C_O1_I1(w, w);
+
 default:
 g_assert_not_reached();
 }
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index daaf38ee31..f9c5cb12ca 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -177,13 +177,13 @@ extern bool use_lsx_instructions;
 #define TCG_TARGET_HAS_v128 use_lsx_instructions
 #define TCG_TARGET_HAS_v256 0
 
-#define TCG_TARGET_HAS_not_vec  0
+#define TCG_TARGET_HAS_not_vec  1
 #define TCG_TARGET_HAS_neg_vec  0
 #define TCG_TARGET_HAS_abs_vec  0
-#define TCG_TARGET_HAS_andc_vec 0
-#define TCG_TARGET_HAS_orc_vec  0
+#define TCG_TARGET_HAS_andc_vec 1
+#define TCG_TARGET_HAS_orc_vec  1
 #define TCG_TARGET_HAS_nand_vec 0
-#define TCG_TARGET_HAS_nor_vec  0
+#define TCG_TARGET_HAS_nor_vec  1
 #define TCG_TARGET_HAS_eqv_vec  0
 #define TCG_TARGET_HAS_mul_vec  0
 #define TCG_TARGET_HAS_shi_vec  0
-- 
2.42.0




[PATCH v3 13/16] tcg/loongarch64: Lower vector shift integer ops

2023-09-01 Thread Jiajie Chen
Lower the following ops:

- shli_vec
- shrv_vec
- sarv_vec

Signed-off-by: Jiajie Chen 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 21 +
 tcg/loongarch64/tcg-target.h |  2 +-
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 2db4369a9e..8ac008b907 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1701,6 +1701,15 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 static const LoongArchInsn sarv_vec_insn[4] = {
 OPC_VSRA_B, OPC_VSRA_H, OPC_VSRA_W, OPC_VSRA_D
 };
+static const LoongArchInsn shli_vec_insn[4] = {
+OPC_VSLLI_B, OPC_VSLLI_H, OPC_VSLLI_W, OPC_VSLLI_D
+};
+static const LoongArchInsn shri_vec_insn[4] = {
+OPC_VSRLI_B, OPC_VSRLI_H, OPC_VSRLI_W, OPC_VSRLI_D
+};
+static const LoongArchInsn sari_vec_insn[4] = {
+OPC_VSRAI_B, OPC_VSRAI_H, OPC_VSRAI_W, OPC_VSRAI_D
+};
 
 a0 = args[0];
 a1 = args[1];
@@ -1871,6 +1880,15 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 case INDEX_op_sarv_vec:
 tcg_out32(s, encode_vdvjvk_insn(sarv_vec_insn[vece], a0, a1, a2));
 break;
+case INDEX_op_shli_vec:
+tcg_out32(s, encode_vdvjuk3_insn(shli_vec_insn[vece], a0, a1, a2));
+break;
+case INDEX_op_shri_vec:
+tcg_out32(s, encode_vdvjuk3_insn(shri_vec_insn[vece], a0, a1, a2));
+break;
+case INDEX_op_sari_vec:
+tcg_out32(s, encode_vdvjuk3_insn(sari_vec_insn[vece], a0, a1, a2));
+break;
 case INDEX_op_bitsel_vec:
 /* vbitsel vd, vj, vk, va = bitsel_vec vd, va, vk, vj */
 tcg_out_opc_vbitsel_v(s, a0, a3, a2, a1);
@@ -2104,6 +2122,9 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 
 case INDEX_op_not_vec:
 case INDEX_op_neg_vec:
+case INDEX_op_shli_vec:
+case INDEX_op_shri_vec:
+case INDEX_op_sari_vec:
 return C_O1_I1(w, w);
 
 case INDEX_op_bitsel_vec:
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index bc56939a57..d7b806e252 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -186,7 +186,7 @@ extern bool use_lsx_instructions;
 #define TCG_TARGET_HAS_nor_vec  1
 #define TCG_TARGET_HAS_eqv_vec  0
 #define TCG_TARGET_HAS_mul_vec  1
-#define TCG_TARGET_HAS_shi_vec  0
+#define TCG_TARGET_HAS_shi_vec  1
 #define TCG_TARGET_HAS_shs_vec  0
 #define TCG_TARGET_HAS_shv_vec  1
 #define TCG_TARGET_HAS_roti_vec 0
-- 
2.42.0




[PATCH v3 16/16] tcg/loongarch64: Implement 128-bit load & store

2023-09-01 Thread Jiajie Chen
If LSX is available, use LSX instructions to implement 128-bit load &
store.

Signed-off-by: Jiajie Chen 
---
 tcg/loongarch64/tcg-target-con-set.h |  2 ++
 tcg/loongarch64/tcg-target.c.inc | 42 
 tcg/loongarch64/tcg-target.h |  2 +-
 3 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index 914572d21b..77d62e38e7 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -18,6 +18,7 @@ C_O0_I1(r)
 C_O0_I2(rZ, r)
 C_O0_I2(rZ, rZ)
 C_O0_I2(w, r)
+C_O0_I3(r, r, r)
 C_O1_I1(r, r)
 C_O1_I1(w, r)
 C_O1_I1(w, w)
@@ -37,3 +38,4 @@ C_O1_I2(w, w, wM)
 C_O1_I2(w, w, wA)
 C_O1_I3(w, w, w, w)
 C_O1_I4(r, rZ, rJ, rZ, rZ)
+C_O2_I1(r, r, r)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 2b001598e2..9d999ef58c 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1081,6 +1081,31 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg 
data_reg, TCGReg addr_reg,
 }
 }
 
+static void tcg_out_qemu_ldst_i128(TCGContext *s, TCGReg data_lo, TCGReg 
data_hi,
+   TCGReg addr_reg, MemOpIdx oi, bool is_ld)
+{
+TCGLabelQemuLdst *ldst;
+HostAddress h;
+
+ldst = prepare_host_addr(s, , addr_reg, oi, true);
+if (is_ld) {
+tcg_out_opc_vldx(s, TCG_VEC_TMP0, h.base, h.index);
+tcg_out_opc_vpickve2gr_d(s, data_lo, TCG_VEC_TMP0, 0);
+tcg_out_opc_vpickve2gr_d(s, data_hi, TCG_VEC_TMP0, 1);
+} else {
+tcg_out_opc_vinsgr2vr_d(s, TCG_VEC_TMP0, data_lo, 0);
+tcg_out_opc_vinsgr2vr_d(s, TCG_VEC_TMP0, data_hi, 1);
+tcg_out_opc_vstx(s, TCG_VEC_TMP0, h.base, h.index);
+}
+
+if (ldst) {
+ldst->type = TCG_TYPE_I128;
+ldst->datalo_reg = data_lo;
+ldst->datahi_reg = data_hi;
+ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
+}
+}
+
 /*
  * Entry-points
  */
@@ -1145,6 +1170,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 TCGArg a0 = args[0];
 TCGArg a1 = args[1];
 TCGArg a2 = args[2];
+TCGArg a3 = args[3];
 int c2 = const_args[2];
 
 switch (opc) {
@@ -1507,6 +1533,10 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 case INDEX_op_qemu_ld_a64_i64:
 tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I64);
 break;
+case INDEX_op_qemu_ld_a32_i128:
+case INDEX_op_qemu_ld_a64_i128:
+tcg_out_qemu_ldst_i128(s, a0, a1, a2, a3, true);
+break;
 case INDEX_op_qemu_st_a32_i32:
 case INDEX_op_qemu_st_a64_i32:
 tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I32);
@@ -1515,6 +1545,10 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 case INDEX_op_qemu_st_a64_i64:
 tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I64);
 break;
+case INDEX_op_qemu_st_a32_i128:
+case INDEX_op_qemu_st_a64_i128:
+tcg_out_qemu_ldst_i128(s, a0, a1, a2, a3, false);
+break;
 
 case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
 case INDEX_op_mov_i64:
@@ -1995,6 +2029,14 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_qemu_st_a64_i64:
 return C_O0_I2(rZ, r);
 
+case INDEX_op_qemu_ld_a32_i128:
+case INDEX_op_qemu_ld_a64_i128:
+return C_O2_I1(r, r, r);
+
+case INDEX_op_qemu_st_a32_i128:
+case INDEX_op_qemu_st_a64_i128:
+return C_O0_I3(r, r, r);
+
 case INDEX_op_brcond_i32:
 case INDEX_op_brcond_i64:
 return C_O0_I2(rZ, rZ);
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index 67b0a95532..03017672f6 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -171,7 +171,7 @@ extern bool use_lsx_instructions;
 #define TCG_TARGET_HAS_muluh_i641
 #define TCG_TARGET_HAS_mulsh_i641
 
-#define TCG_TARGET_HAS_qemu_ldst_i128   0
+#define TCG_TARGET_HAS_qemu_ldst_i128   use_lsx_instructions
 
 #define TCG_TARGET_HAS_v64  0
 #define TCG_TARGET_HAS_v128 use_lsx_instructions
-- 
2.42.0




[PATCH v3 12/16] tcg/loongarch64: Lower bitsel_vec to vbitsel

2023-09-01 Thread Jiajie Chen
Signed-off-by: Jiajie Chen 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target-con-set.h |  1 +
 tcg/loongarch64/tcg-target.c.inc | 11 ++-
 tcg/loongarch64/tcg-target.h |  2 +-
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index 3f530ad4d8..914572d21b 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -35,4 +35,5 @@ C_O1_I2(r, rZ, rZ)
 C_O1_I2(w, w, w)
 C_O1_I2(w, w, wM)
 C_O1_I2(w, w, wA)
+C_O1_I3(w, w, w, w)
 C_O1_I4(r, rZ, rJ, rZ, rZ)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index ef1cd7c621..2db4369a9e 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1631,7 +1631,7 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
const int const_args[TCG_MAX_OP_ARGS])
 {
 TCGType type = vecl + TCG_TYPE_V64;
-TCGArg a0, a1, a2;
+TCGArg a0, a1, a2, a3;
 TCGReg temp = TCG_REG_TMP0;
 TCGReg temp_vec = TCG_VEC_TMP0;
 
@@ -1705,6 +1705,7 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 a0 = args[0];
 a1 = args[1];
 a2 = args[2];
+a3 = args[3];
 
 /* Currently only supports V128 */
 tcg_debug_assert(type == TCG_TYPE_V128);
@@ -1870,6 +1871,10 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 case INDEX_op_sarv_vec:
 tcg_out32(s, encode_vdvjvk_insn(sarv_vec_insn[vece], a0, a1, a2));
 break;
+case INDEX_op_bitsel_vec:
+/* vbitsel vd, vj, vk, va = bitsel_vec vd, va, vk, vj */
+tcg_out_opc_vbitsel_v(s, a0, a3, a2, a1);
+break;
 case INDEX_op_dupm_vec:
 tcg_out_dupm_vec(s, type, vece, a0, a1, a2);
 break;
@@ -1908,6 +1913,7 @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, 
unsigned vece)
 case INDEX_op_shlv_vec:
 case INDEX_op_shrv_vec:
 case INDEX_op_sarv_vec:
+case INDEX_op_bitsel_vec:
 return 1;
 default:
 return 0;
@@ -2100,6 +2106,9 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_neg_vec:
 return C_O1_I1(w, w);
 
+case INDEX_op_bitsel_vec:
+return C_O1_I3(w, w, w, w);
+
 default:
 g_assert_not_reached();
 }
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index 7e9fb61c47..bc56939a57 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -194,7 +194,7 @@ extern bool use_lsx_instructions;
 #define TCG_TARGET_HAS_rotv_vec 0
 #define TCG_TARGET_HAS_sat_vec  1
 #define TCG_TARGET_HAS_minmax_vec   1
-#define TCG_TARGET_HAS_bitsel_vec   0
+#define TCG_TARGET_HAS_bitsel_vec   1
 #define TCG_TARGET_HAS_cmpsel_vec   0
 
 #define TCG_TARGET_DEFAULT_MO (0)
-- 
2.42.0




[PATCH v3 11/16] tcg/loongarch64: Lower vector shift vector ops

2023-09-01 Thread Jiajie Chen
Lower the following ops:

- shlv_vec
- shrv_vec
- sarv_vec

Signed-off-by: Jiajie Chen 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 24 
 tcg/loongarch64/tcg-target.h |  2 +-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 89db41002c..ef1cd7c621 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1692,6 +1692,15 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 static const LoongArchInsn ussub_vec_insn[4] = {
 OPC_VSSUB_BU, OPC_VSSUB_HU, OPC_VSSUB_WU, OPC_VSSUB_DU
 };
+static const LoongArchInsn shlv_vec_insn[4] = {
+OPC_VSLL_B, OPC_VSLL_H, OPC_VSLL_W, OPC_VSLL_D
+};
+static const LoongArchInsn shrv_vec_insn[4] = {
+OPC_VSRL_B, OPC_VSRL_H, OPC_VSRL_W, OPC_VSRL_D
+};
+static const LoongArchInsn sarv_vec_insn[4] = {
+OPC_VSRA_B, OPC_VSRA_H, OPC_VSRA_W, OPC_VSRA_D
+};
 
 a0 = args[0];
 a1 = args[1];
@@ -1852,6 +1861,15 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 case INDEX_op_ussub_vec:
 tcg_out32(s, encode_vdvjvk_insn(ussub_vec_insn[vece], a0, a1, a2));
 break;
+case INDEX_op_shlv_vec:
+tcg_out32(s, encode_vdvjvk_insn(shlv_vec_insn[vece], a0, a1, a2));
+break;
+case INDEX_op_shrv_vec:
+tcg_out32(s, encode_vdvjvk_insn(shrv_vec_insn[vece], a0, a1, a2));
+break;
+case INDEX_op_sarv_vec:
+tcg_out32(s, encode_vdvjvk_insn(sarv_vec_insn[vece], a0, a1, a2));
+break;
 case INDEX_op_dupm_vec:
 tcg_out_dupm_vec(s, type, vece, a0, a1, a2);
 break;
@@ -1887,6 +1905,9 @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, 
unsigned vece)
 case INDEX_op_usadd_vec:
 case INDEX_op_sssub_vec:
 case INDEX_op_ussub_vec:
+case INDEX_op_shlv_vec:
+case INDEX_op_shrv_vec:
+case INDEX_op_sarv_vec:
 return 1;
 default:
 return 0;
@@ -2070,6 +2091,9 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_usadd_vec:
 case INDEX_op_sssub_vec:
 case INDEX_op_ussub_vec:
+case INDEX_op_shlv_vec:
+case INDEX_op_shrv_vec:
+case INDEX_op_sarv_vec:
 return C_O1_I2(w, w, w);
 
 case INDEX_op_not_vec:
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index fa14558275..7e9fb61c47 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -188,7 +188,7 @@ extern bool use_lsx_instructions;
 #define TCG_TARGET_HAS_mul_vec  1
 #define TCG_TARGET_HAS_shi_vec  0
 #define TCG_TARGET_HAS_shs_vec  0
-#define TCG_TARGET_HAS_shv_vec  0
+#define TCG_TARGET_HAS_shv_vec  1
 #define TCG_TARGET_HAS_roti_vec 0
 #define TCG_TARGET_HAS_rots_vec 0
 #define TCG_TARGET_HAS_rotv_vec 0
-- 
2.42.0




[PATCH v3 04/16] tcg/loongarch64: Lower cmp_vec to vseq/vsle/vslt

2023-09-01 Thread Jiajie Chen
Signed-off-by: Jiajie Chen 
---
 tcg/loongarch64/tcg-target-con-set.h |  1 +
 tcg/loongarch64/tcg-target-con-str.h |  1 +
 tcg/loongarch64/tcg-target.c.inc | 65 
 3 files changed, 67 insertions(+)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index 37b3f80bf9..8c8ea5d919 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -31,4 +31,5 @@ C_O1_I2(r, 0, rZ)
 C_O1_I2(r, rZ, ri)
 C_O1_I2(r, rZ, rJ)
 C_O1_I2(r, rZ, rZ)
+C_O1_I2(w, w, wM)
 C_O1_I4(r, rZ, rJ, rZ, rZ)
diff --git a/tcg/loongarch64/tcg-target-con-str.h 
b/tcg/loongarch64/tcg-target-con-str.h
index 81b8d40278..a8a1c44014 100644
--- a/tcg/loongarch64/tcg-target-con-str.h
+++ b/tcg/loongarch64/tcg-target-con-str.h
@@ -26,3 +26,4 @@ CONST('U', TCG_CT_CONST_U12)
 CONST('Z', TCG_CT_CONST_ZERO)
 CONST('C', TCG_CT_CONST_C12)
 CONST('W', TCG_CT_CONST_WSZ)
+CONST('M', TCG_CT_CONST_VCMP)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 07a0326e5d..129dd92910 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -176,6 +176,7 @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind 
kind, int slot)
 #define TCG_CT_CONST_U12   0x800
 #define TCG_CT_CONST_C12   0x1000
 #define TCG_CT_CONST_WSZ   0x2000
+#define TCG_CT_CONST_VCMP  0x4000
 
 #define ALL_GENERAL_REGS   MAKE_64BIT_MASK(0, 32)
 #define ALL_VECTOR_REGSMAKE_64BIT_MASK(32, 32)
@@ -209,6 +210,10 @@ static bool tcg_target_const_match(int64_t val, TCGType 
type, int ct, int vece)
 if ((ct & TCG_CT_CONST_WSZ) && val == (type == TCG_TYPE_I32 ? 32 : 64)) {
 return true;
 }
+int64_t vec_val = sextract64(val, 0, 8 << vece);
+if ((ct & TCG_CT_CONST_VCMP) && -0x10 <= vec_val && vec_val <= 0x1f) {
+return true;
+}
 return false;
 }
 
@@ -1624,6 +1629,23 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 TCGType type = vecl + TCG_TYPE_V64;
 TCGArg a0, a1, a2;
 TCGReg temp = TCG_REG_TMP0;
+TCGReg temp_vec = TCG_VEC_TMP0;
+
+static const LoongArchInsn cmp_vec_insn[16][4] = {
+[TCG_COND_EQ] = {OPC_VSEQ_B, OPC_VSEQ_H, OPC_VSEQ_W, OPC_VSEQ_D},
+[TCG_COND_LE] = {OPC_VSLE_B, OPC_VSLE_H, OPC_VSLE_W, OPC_VSLE_D},
+[TCG_COND_LEU] = {OPC_VSLE_BU, OPC_VSLE_HU, OPC_VSLE_WU, OPC_VSLE_DU},
+[TCG_COND_LT] = {OPC_VSLT_B, OPC_VSLT_H, OPC_VSLT_W, OPC_VSLT_D},
+[TCG_COND_LTU] = {OPC_VSLT_BU, OPC_VSLT_HU, OPC_VSLT_WU, OPC_VSLT_DU},
+};
+static const LoongArchInsn cmp_vec_imm_insn[16][4] = {
+[TCG_COND_EQ] = {OPC_VSEQI_B, OPC_VSEQI_H, OPC_VSEQI_W, OPC_VSEQI_D},
+[TCG_COND_LE] = {OPC_VSLEI_B, OPC_VSLEI_H, OPC_VSLEI_W, OPC_VSLEI_D},
+[TCG_COND_LEU] = {OPC_VSLEI_BU, OPC_VSLEI_HU, OPC_VSLEI_WU, 
OPC_VSLEI_DU},
+[TCG_COND_LT] = {OPC_VSLTI_B, OPC_VSLTI_H, OPC_VSLTI_W, OPC_VSLTI_D},
+[TCG_COND_LTU] = {OPC_VSLTI_BU, OPC_VSLTI_HU, OPC_VSLTI_WU, 
OPC_VSLTI_DU},
+};
+LoongArchInsn insn;
 
 a0 = args[0];
 a1 = args[1];
@@ -1651,6 +1673,45 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 tcg_out_opc_vldx(s, a0, a1, temp);
 }
 break;
+case INDEX_op_cmp_vec:
+TCGCond cond = args[3];
+if (const_args[2]) {
+/*
+ * cmp_vec dest, src, value
+ * Try vseqi/vslei/vslti
+ */
+int64_t value = sextract64(a2, 0, 8 << vece);
+if ((cond == TCG_COND_EQ || cond == TCG_COND_LE || \
+ cond == TCG_COND_LT) && (-0x10 <= value && value <= 0x0f)) {
+tcg_out32(s, encode_vdvjsk5_insn(cmp_vec_imm_insn[cond][vece], 
\
+ a0, a1, value));
+break;
+} else if ((cond == TCG_COND_LEU || cond == TCG_COND_LTU) &&
+(0x00 <= value && value <= 0x1f)) {
+tcg_out32(s, encode_vdvjuk5_insn(cmp_vec_imm_insn[cond][vece], 
\
+ a0, a1, value));
+break;
+}
+
+/*
+ * Fallback to:
+ * dupi_vec temp, a2
+ * cmp_vec a0, a1, temp, cond
+ */
+tcg_out_dupi_vec(s, type, vece, temp_vec, a2);
+a2 = temp_vec;
+}
+
+insn = cmp_vec_insn[cond][vece];
+if (insn == 0) {
+TCGArg t;
+t = a1, a1 = a2, a2 = t;
+cond = tcg_swap_cond(cond);
+insn = cmp_vec_insn[cond][vece];
+tcg_debug_assert(insn != 0);
+}
+tcg_out32(s, encode_vdvjvk_insn(insn, a0, a1, a2));
+break;
 case INDEX_op_dupm_vec:
 tcg_out_dupm_vec(s, type, vece, a0, a1, a2);
 break;
@@ -1666,6 +1727,7 @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, 
unsigned vece)
 case INDEX_op_st_vec:
 case INDEX_op_dup_vec:
 case 

[PATCH v3 09/16] tcg/loongarch64: Lower vector min max ops

2023-09-01 Thread Jiajie Chen
Lower the following ops:

- smin_vec
- smax_vec
- umin_vec
- umax_vec

Signed-off-by: Jiajie Chen 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 32 
 tcg/loongarch64/tcg-target.h |  2 +-
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 6905775698..3ffc1691cd 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1668,6 +1668,18 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 static const LoongArchInsn mul_vec_insn[4] = {
 OPC_VMUL_B, OPC_VMUL_H, OPC_VMUL_W, OPC_VMUL_D
 };
+static const LoongArchInsn smin_vec_insn[4] = {
+OPC_VMIN_B, OPC_VMIN_H, OPC_VMIN_W, OPC_VMIN_D
+};
+static const LoongArchInsn umin_vec_insn[4] = {
+OPC_VMIN_BU, OPC_VMIN_HU, OPC_VMIN_WU, OPC_VMIN_DU
+};
+static const LoongArchInsn smax_vec_insn[4] = {
+OPC_VMAX_B, OPC_VMAX_H, OPC_VMAX_W, OPC_VMAX_D
+};
+static const LoongArchInsn umax_vec_insn[4] = {
+OPC_VMAX_BU, OPC_VMAX_HU, OPC_VMAX_WU, OPC_VMAX_DU
+};
 
 a0 = args[0];
 a1 = args[1];
@@ -1804,6 +1816,18 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 case INDEX_op_mul_vec:
 tcg_out32(s, encode_vdvjvk_insn(mul_vec_insn[vece], a0, a1, a2));
 break;
+case INDEX_op_smin_vec:
+tcg_out32(s, encode_vdvjvk_insn(smin_vec_insn[vece], a0, a1, a2));
+break;
+case INDEX_op_smax_vec:
+tcg_out32(s, encode_vdvjvk_insn(smax_vec_insn[vece], a0, a1, a2));
+break;
+case INDEX_op_umin_vec:
+tcg_out32(s, encode_vdvjvk_insn(umin_vec_insn[vece], a0, a1, a2));
+break;
+case INDEX_op_umax_vec:
+tcg_out32(s, encode_vdvjvk_insn(umax_vec_insn[vece], a0, a1, a2));
+break;
 case INDEX_op_dupm_vec:
 tcg_out_dupm_vec(s, type, vece, a0, a1, a2);
 break;
@@ -1831,6 +1855,10 @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, 
unsigned vece)
 case INDEX_op_not_vec:
 case INDEX_op_neg_vec:
 case INDEX_op_mul_vec:
+case INDEX_op_smin_vec:
+case INDEX_op_smax_vec:
+case INDEX_op_umin_vec:
+case INDEX_op_umax_vec:
 return 1;
 default:
 return 0;
@@ -2006,6 +2034,10 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_xor_vec:
 case INDEX_op_nor_vec:
 case INDEX_op_mul_vec:
+case INDEX_op_smin_vec:
+case INDEX_op_smax_vec:
+case INDEX_op_umin_vec:
+case INDEX_op_umax_vec:
 return C_O1_I2(w, w, w);
 
 case INDEX_op_not_vec:
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index 2c2266ed31..ec725aaeaa 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -193,7 +193,7 @@ extern bool use_lsx_instructions;
 #define TCG_TARGET_HAS_rots_vec 0
 #define TCG_TARGET_HAS_rotv_vec 0
 #define TCG_TARGET_HAS_sat_vec  0
-#define TCG_TARGET_HAS_minmax_vec   0
+#define TCG_TARGET_HAS_minmax_vec   1
 #define TCG_TARGET_HAS_bitsel_vec   0
 #define TCG_TARGET_HAS_cmpsel_vec   0
 
-- 
2.42.0




[PATCH v3 15/16] tcg/loongarch64: Lower rotli_vec to vrotri

2023-09-01 Thread Jiajie Chen
Signed-off-by: Jiajie Chen 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 21 +
 tcg/loongarch64/tcg-target.h |  2 +-
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 95359b1757..2b001598e2 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1901,6 +1901,26 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 tcg_out32(s, encode_vdvjvk_insn(rotrv_vec_insn[vece], a0, a1,
 temp_vec));
 break;
+case INDEX_op_rotli_vec:
+/* rotli_vec a1, a2 = rotri_vec a1, -a2 */
+a2 = extract32(-a2, 0, 3 + vece);
+switch (vece) {
+case MO_8:
+tcg_out_opc_vrotri_b(s, a0, a1, a2);
+break;
+case MO_16:
+tcg_out_opc_vrotri_h(s, a0, a1, a2);
+break;
+case MO_32:
+tcg_out_opc_vrotri_w(s, a0, a1, a2);
+break;
+case MO_64:
+tcg_out_opc_vrotri_d(s, a0, a1, a2);
+break;
+default:
+g_assert_not_reached();
+}
+break;
 case INDEX_op_bitsel_vec:
 /* vbitsel vd, vj, vk, va = bitsel_vec vd, va, vk, vj */
 tcg_out_opc_vbitsel_v(s, a0, a3, a2, a1);
@@ -2139,6 +2159,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_shli_vec:
 case INDEX_op_shri_vec:
 case INDEX_op_sari_vec:
+case INDEX_op_rotli_vec:
 return C_O1_I1(w, w);
 
 case INDEX_op_bitsel_vec:
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index d5c69bc192..67b0a95532 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -189,7 +189,7 @@ extern bool use_lsx_instructions;
 #define TCG_TARGET_HAS_shi_vec  1
 #define TCG_TARGET_HAS_shs_vec  0
 #define TCG_TARGET_HAS_shv_vec  1
-#define TCG_TARGET_HAS_roti_vec 0
+#define TCG_TARGET_HAS_roti_vec 1
 #define TCG_TARGET_HAS_rots_vec 0
 #define TCG_TARGET_HAS_rotv_vec 1
 #define TCG_TARGET_HAS_sat_vec  1
-- 
2.42.0




[PATCH v3 00/16] Lower TCG vector ops to LSX

2023-09-01 Thread Jiajie Chen
This patch series allows qemu to utilize LSX instructions on LoongArch
machines to execute TCG vector ops.

Passed tcg tests with x86_64 and aarch64 cross compilers.

Changes since v2:

- Add vece argument to tcg_target_const_match() for const args of vector ops
- Use custom constraint for cmp_vec/add_vec/sub_vec for better const arg 
handling
- Implement 128-bit load & store using vldx/vstx

Changes since v1:

- Optimize dupi_vec/st_vec/ld_vec/cmp_vec/add_vec/sub_vec generation
- Lower not_vec/shi_vec/roti_vec/rotv_vec

Jiajie Chen (16):
  tcg/loongarch64: Import LSX instructions
  tcg/loongarch64: Lower basic tcg vec ops to LSX
  tcg: pass vece to tcg_target_const_match()
  tcg/loongarch64: Lower cmp_vec to vseq/vsle/vslt
  tcg/loongarch64: Lower add/sub_vec to vadd/vsub
  tcg/loongarch64: Lower vector bitwise operations
  tcg/loongarch64: Lower neg_vec to vneg
  tcg/loongarch64: Lower mul_vec to vmul
  tcg/loongarch64: Lower vector min max ops
  tcg/loongarch64: Lower vector saturated ops
  tcg/loongarch64: Lower vector shift vector ops
  tcg/loongarch64: Lower bitsel_vec to vbitsel
  tcg/loongarch64: Lower vector shift integer ops
  tcg/loongarch64: Lower rotv_vec ops to LSX
  tcg/loongarch64: Lower rotli_vec to vrotri
  tcg/loongarch64: Implement 128-bit load & store

 tcg/aarch64/tcg-target.c.inc |2 +-
 tcg/arm/tcg-target.c.inc |2 +-
 tcg/i386/tcg-target.c.inc|2 +-
 tcg/loongarch64/tcg-insn-defs.c.inc  | 6251 +-
 tcg/loongarch64/tcg-target-con-set.h |9 +
 tcg/loongarch64/tcg-target-con-str.h |3 +
 tcg/loongarch64/tcg-target.c.inc |  601 ++-
 tcg/loongarch64/tcg-target.h |   40 +-
 tcg/loongarch64/tcg-target.opc.h |   12 +
 tcg/mips/tcg-target.c.inc|2 +-
 tcg/ppc/tcg-target.c.inc |2 +-
 tcg/riscv/tcg-target.c.inc   |2 +-
 tcg/s390x/tcg-target.c.inc   |2 +-
 tcg/sparc64/tcg-target.c.inc |2 +-
 tcg/tcg.c|4 +-
 tcg/tci/tcg-target.c.inc |2 +-
 16 files changed, 6806 insertions(+), 132 deletions(-)
 create mode 100644 tcg/loongarch64/tcg-target.opc.h

-- 
2.42.0




[PATCH v3 03/16] tcg: pass vece to tcg_target_const_match()

2023-09-01 Thread Jiajie Chen
Pass vece to tcg_target_const_match() to allow correct interpretation of
const args of vector ops.

Signed-off-by: Jiajie Chen 
---
 tcg/aarch64/tcg-target.c.inc | 2 +-
 tcg/arm/tcg-target.c.inc | 2 +-
 tcg/i386/tcg-target.c.inc| 2 +-
 tcg/loongarch64/tcg-target.c.inc | 2 +-
 tcg/mips/tcg-target.c.inc| 2 +-
 tcg/ppc/tcg-target.c.inc | 2 +-
 tcg/riscv/tcg-target.c.inc   | 2 +-
 tcg/s390x/tcg-target.c.inc   | 2 +-
 tcg/sparc64/tcg-target.c.inc | 2 +-
 tcg/tcg.c| 4 ++--
 tcg/tci/tcg-target.c.inc | 2 +-
 11 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index 0931a69448..a1e2b6be16 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -272,7 +272,7 @@ static bool is_shimm1632(uint32_t v32, int *cmode, int 
*imm8)
 }
 }
 
-static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
+static bool tcg_target_const_match(int64_t val, TCGType type, int ct, int vece)
 {
 if (ct & TCG_CT_CONST) {
 return 1;
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
index acb5f23b54..76f1345002 100644
--- a/tcg/arm/tcg-target.c.inc
+++ b/tcg/arm/tcg-target.c.inc
@@ -509,7 +509,7 @@ static bool is_shimm1632(uint32_t v32, int *cmode, int 
*imm8)
  * mov operand2: values represented with x << (2 * y), x < 0x100
  * add, sub, eor...: ditto
  */
-static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
+static bool tcg_target_const_match(int64_t val, TCGType type, int ct, int vece)
 {
 if (ct & TCG_CT_CONST) {
 return 1;
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index 0c3d1e4cef..aed91e515e 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -198,7 +198,7 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
 }
 
 /* test if a constant matches the constraint */
-static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
+static bool tcg_target_const_match(int64_t val, TCGType type, int ct, int vece)
 {
 if (ct & TCG_CT_CONST) {
 return 1;
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 150278e112..07a0326e5d 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -186,7 +186,7 @@ static inline tcg_target_long sextreg(tcg_target_long val, 
int pos, int len)
 }
 
 /* test if a constant matches the constraint */
-static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
+static bool tcg_target_const_match(int64_t val, TCGType type, int ct, int vece)
 {
 if (ct & TCG_CT_CONST) {
 return true;
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index 9faa8bdf0b..c6662889f0 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -190,7 +190,7 @@ static bool is_p2m1(tcg_target_long val)
 }
 
 /* test if a constant matches the constraint */
-static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
+static bool tcg_target_const_match(int64_t val, TCGType type, int ct, int vece)
 {
 if (ct & TCG_CT_CONST) {
 return 1;
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index 090f11e71c..ccf245191d 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -261,7 +261,7 @@ static bool reloc_pc14(tcg_insn_unit *src_rw, const 
tcg_insn_unit *target)
 }
 
 /* test if a constant matches the constraint */
-static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
+static bool tcg_target_const_match(int64_t val, TCGType type, int ct, int vece)
 {
 if (ct & TCG_CT_CONST) {
 return 1;
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index 9be81c1b7b..3bd7959e7e 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -145,7 +145,7 @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind 
kind, int slot)
 #define sextreg  sextract64
 
 /* test if a constant matches the constraint */
-static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
+static bool tcg_target_const_match(int64_t val, TCGType type, int ct, int vece)
 {
 if (ct & TCG_CT_CONST) {
 return 1;
diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc
index ecd8aaf2a1..f4d3abcb71 100644
--- a/tcg/s390x/tcg-target.c.inc
+++ b/tcg/s390x/tcg-target.c.inc
@@ -540,7 +540,7 @@ static bool risbg_mask(uint64_t c)
 }
 
 /* Test if a constant matches the constraint. */
-static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
+static bool tcg_target_const_match(int64_t val, TCGType type, int ct, int vece)
 {
 if (ct & TCG_CT_CONST) {
 return 1;
diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc
index 81a08bb6c5..6b9be4c520 100644
--- a/tcg/sparc64/tcg-target.c.inc
+++ b/tcg/sparc64/tcg-target.c.inc
@@ -322,7 +322,7 @@ static bool 

Re: [PATCH v2 03/14] tcg/loongarch64: Lower cmp_vec to vseq/vsle/vslt

2023-09-01 Thread Jiajie Chen



On 2023/9/2 01:48, Richard Henderson wrote:

On 9/1/23 10:28, Jiajie Chen wrote:


On 2023/9/2 01:24, Richard Henderson wrote:

On 9/1/23 02:30, Jiajie Chen wrote:

Signed-off-by: Jiajie Chen 
---
  tcg/loongarch64/tcg-target-con-set.h |  1 +
  tcg/loongarch64/tcg-target.c.inc | 60 


  2 files changed, 61 insertions(+)


Reviewed-by: Richard Henderson 




diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h

index 37b3f80bf9..d04916db25 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -31,4 +31,5 @@ C_O1_I2(r, 0, rZ)
  C_O1_I2(r, rZ, ri)
  C_O1_I2(r, rZ, rJ)
  C_O1_I2(r, rZ, rZ)
+C_O1_I2(w, w, wJ)


Notes for improvement: 'J' is a signed 32-bit immediate.



I was wondering about the behavior of 'J' on i128 types: in 
tcg_target_const_match(), the argument type is int, so will the 
higher bits be truncated?


The argument is int64_t val.

The only constants that we allow for vectors are dupi, so all higher 
parts are the same as the lower part.



Consider the following scenario:


cmp_vec v128,e32,tmp4,tmp3,v128$0x

cmp_vec v128,e32,tmp4,tmp3,v128$0xfffefffe

cmp_vec v128,e8,tmp4,tmp3,v128$0xfefefefefefefefe


When matching constant constraint, the vector element width is unknown, 
so it cannot decide whether 0xfefefefefefefefe means e8 0xfe or e16 0xfefe.





Besides, tcg_target_const_match() does not know the vector element 
width.


No, it hadn't been required so far -- there are very few vector 
instructions that allow immediates.



r~




Re: [PATCH 0/8] move softmmu options processing from os-posix.c to vl.c

2023-09-01 Thread Paolo Bonzini
Queued, thanks.

Paolo




Re: [PATCH 20/20] target/riscv: add 'kvm_supported' class property

2023-09-01 Thread Daniel Henrique Barboza




On 8/31/23 09:47, Andrew Jones wrote:

On Fri, Aug 25, 2023 at 10:08:53AM -0300, Daniel Henrique Barboza wrote:

This follows the same idea of 'tcg_support' property added in the
previous patch. Note that we're now implementing the 'cpu_realizefn' for
the KVMAccel class since this verification is done in realize() time.

Supporting vendor CPUs with KVM is not possible. We rely on the
extension support of the KVM module running in the host, making it
impossible to guarantee that a vendor CPU will have all the required
extensions available. The only way to guarantee that a vendor CPU is KVM
compatible is running KVM in a host that has the same vendor CPU, and


Or to attempt to enable each extension which the vendor CPU expects and
to attempt to disable everything else. If all those actions succeed, then
we can override the ID registers with those of the CPU we want to model
and go for it. There's still risk, though, that the guest kernel will see
the ID registers of the model and attempt to apply some errata workaround
which may or may not work and/or crash the guest.


This can also happen when migrating the guest from a host that happens to have
an errata to one that doesn't have, regardless of the CPU type the guest
is using (host CPU vs vendor CPU). The guest would need a power cycle to
identify the current model ID.

We don't have the tooling needed to mitigate this risk in QEMU I'm afraid. Upper
layers like libvirt are more able to deal with it.




for this case we already have the 'host' CPU type.

We're better of declaring that all vendors CPUs are not KVM capable.
After this patch, running KVM accel with a vendor CPU will produce an
error like the following:

$ ./qemu-system-riscv64 -M virt,accel=kvm -cpu veyron-v1
qemu-system-riscv64: 'veyron-v1' CPU is not compatible with KVM acceleration


Shouldn't we at least check if the host matches the requested CPU first?
So, if we happen to be on a veyron-v1, then the veyron-v1 model should
be equivalent to 'host'. (They may not be 100% equivalent in practice, but
theoretically they should be, which means trying it and debugging the bugs
should improve the CPU models on both sides.)


If we're really going this route we would need to match host and vendor CPU
in the extension level, matching each vendor CPU extension with what the
CPU can provide, failing if the host can't provide all extensions the vendor
CPU requires. I wouldn't even bother checking for things like machine ID since
they can be easily impersonated (e.g. use a rv64 emulated host, edit mvendorid)
and can't be trusted.

TBH I am not thrilled with the idea of supporting vendor CPUs with KVM. The user
can pick the 'host' CPU to have the most capable KVM CPU available in the host,
and that is already not trivial to support in cases like live migration and so
on. Vendor CPU KVM support will promote things like:

"I tried to use a veyron-v2 KVM CPU in a veyron-v1 host, why is that not 
possible
it should be it's not fair"

"why can't I use a vendor X KVM CPU A into a vendor Y CPU B host it surely 
should
work since CPU A is older than CPU B right"

And then, even if we decide to support vendor CPUs with KVM in a feasible way, 
with
a lot of conditions and training wheels, we'll be so restrictive that the user 
will
be better of using the 'host' CPU anyway.


All this said, there's a lot going on in this series already and this vendor 
CPU + KVM
discussion might deserve its own RFC/thread. I'll drop this patch from the 
series to
give us time to discuss this properly. Let's leave it as is for now.


Thanks,

Daniel






Signed-off-by: Daniel Henrique Barboza 
---
  target/riscv/cpu-qom.h |  1 +
  target/riscv/cpu.c |  1 +
  target/riscv/kvm/kvm-cpu.c | 24 
  3 files changed, 26 insertions(+)

diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h
index e86b76f9fe..32d9bb07b4 100644
--- a/target/riscv/cpu-qom.h
+++ b/target/riscv/cpu-qom.h
@@ -72,5 +72,6 @@ struct RISCVCPUClass {
  
  bool user_extension_properties;

  bool tcg_supported;
+bool kvm_supported;
  };
  #endif /* RISCV_CPU_QOM_H */
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index f749ea2a2e..73302bb72a 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1646,6 +1646,7 @@ static void riscv_dynamic_cpu_class_init(ObjectClass *c, 
void *data)
  
  rcc->user_extension_properties = true;

  rcc->tcg_supported = true;
+rcc->kvm_supported = true;
  }
  
  static void riscv_vendor_cpu_class_init(ObjectClass *c, void *data)

diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
index 501384924b..85f3b8c80e 100644
--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -1289,6 +1289,7 @@ static void riscv_kvm_cpu_class_init(ObjectClass *c, void 
*data)
  RISCVCPUClass *rcc = RISCV_CPU_CLASS(c);
  
  rcc->user_extension_properties = true;

+rcc->kvm_supported = true;
  }
  
  static const TypeInfo 

[PULL 01/13] linux-user: Split out cpu/target_proc.h

2023-09-01 Thread Richard Henderson
Move the various open_cpuinfo functions into new files.
Move the m68k open_hardware function as well.
All other guest architectures get a boilerplate empty file.

Tested-by: Helge Deller 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 linux-user/aarch64/target_proc.h |   1 +
 linux-user/alpha/target_proc.h   |   1 +
 linux-user/arm/target_proc.h |   1 +
 linux-user/cris/target_proc.h|   1 +
 linux-user/hexagon/target_proc.h |   1 +
 linux-user/hppa/target_proc.h|  26 
 linux-user/i386/target_proc.h|   1 +
 linux-user/loongarch64/target_proc.h |   1 +
 linux-user/m68k/target_proc.h|  16 +++
 linux-user/microblaze/target_proc.h  |   1 +
 linux-user/mips/target_proc.h|   1 +
 linux-user/mips64/target_proc.h  |   1 +
 linux-user/nios2/target_proc.h   |   1 +
 linux-user/openrisc/target_proc.h|   1 +
 linux-user/ppc/target_proc.h |   1 +
 linux-user/riscv/target_proc.h   |  37 ++
 linux-user/s390x/target_proc.h   | 109 +
 linux-user/sh4/target_proc.h |   1 +
 linux-user/sparc/target_proc.h   |  16 +++
 linux-user/x86_64/target_proc.h  |   1 +
 linux-user/xtensa/target_proc.h  |   1 +
 linux-user/syscall.c | 176 +--
 22 files changed, 226 insertions(+), 170 deletions(-)
 create mode 100644 linux-user/aarch64/target_proc.h
 create mode 100644 linux-user/alpha/target_proc.h
 create mode 100644 linux-user/arm/target_proc.h
 create mode 100644 linux-user/cris/target_proc.h
 create mode 100644 linux-user/hexagon/target_proc.h
 create mode 100644 linux-user/hppa/target_proc.h
 create mode 100644 linux-user/i386/target_proc.h
 create mode 100644 linux-user/loongarch64/target_proc.h
 create mode 100644 linux-user/m68k/target_proc.h
 create mode 100644 linux-user/microblaze/target_proc.h
 create mode 100644 linux-user/mips/target_proc.h
 create mode 100644 linux-user/mips64/target_proc.h
 create mode 100644 linux-user/nios2/target_proc.h
 create mode 100644 linux-user/openrisc/target_proc.h
 create mode 100644 linux-user/ppc/target_proc.h
 create mode 100644 linux-user/riscv/target_proc.h
 create mode 100644 linux-user/s390x/target_proc.h
 create mode 100644 linux-user/sh4/target_proc.h
 create mode 100644 linux-user/sparc/target_proc.h
 create mode 100644 linux-user/x86_64/target_proc.h
 create mode 100644 linux-user/xtensa/target_proc.h

diff --git a/linux-user/aarch64/target_proc.h b/linux-user/aarch64/target_proc.h
new file mode 100644
index 00..43fe29ca72
--- /dev/null
+++ b/linux-user/aarch64/target_proc.h
@@ -0,0 +1 @@
+/* No target-specific /proc support */
diff --git a/linux-user/alpha/target_proc.h b/linux-user/alpha/target_proc.h
new file mode 100644
index 00..43fe29ca72
--- /dev/null
+++ b/linux-user/alpha/target_proc.h
@@ -0,0 +1 @@
+/* No target-specific /proc support */
diff --git a/linux-user/arm/target_proc.h b/linux-user/arm/target_proc.h
new file mode 100644
index 00..43fe29ca72
--- /dev/null
+++ b/linux-user/arm/target_proc.h
@@ -0,0 +1 @@
+/* No target-specific /proc support */
diff --git a/linux-user/cris/target_proc.h b/linux-user/cris/target_proc.h
new file mode 100644
index 00..43fe29ca72
--- /dev/null
+++ b/linux-user/cris/target_proc.h
@@ -0,0 +1 @@
+/* No target-specific /proc support */
diff --git a/linux-user/hexagon/target_proc.h b/linux-user/hexagon/target_proc.h
new file mode 100644
index 00..43fe29ca72
--- /dev/null
+++ b/linux-user/hexagon/target_proc.h
@@ -0,0 +1 @@
+/* No target-specific /proc support */
diff --git a/linux-user/hppa/target_proc.h b/linux-user/hppa/target_proc.h
new file mode 100644
index 00..9340c3b6af
--- /dev/null
+++ b/linux-user/hppa/target_proc.h
@@ -0,0 +1,26 @@
+/*
+ * HPPA specific proc functions for linux-user
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HPPA_TARGET_PROC_H
+#define HPPA_TARGET_PROC_H
+
+static int open_cpuinfo(CPUArchState *cpu_env, int fd)
+{
+int i, num_cpus;
+
+num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+for (i = 0; i < num_cpus; i++) {
+dprintf(fd, "processor\t: %d\n", i);
+dprintf(fd, "cpu family\t: PA-RISC 1.1e\n");
+dprintf(fd, "cpu\t\t: PA7300LC (PCX-L2)\n");
+dprintf(fd, "capabilities\t: os32\n");
+dprintf(fd, "model\t\t: 9000/778/B160L - "
+"Merlin L2 160 QEMU (9000/778/B160L)\n\n");
+}
+return 0;
+}
+#define HAVE_ARCH_PROC_CPUINFO
+
+#endif /* HPPA_TARGET_PROC_H */
diff --git a/linux-user/i386/target_proc.h b/linux-user/i386/target_proc.h
new file mode 100644
index 00..43fe29ca72
--- /dev/null
+++ b/linux-user/i386/target_proc.h
@@ -0,0 +1 @@
+/* No target-specific /proc support */
diff --git a/linux-user/loongarch64/target_proc.h 
b/linux-user/loongarch64/target_proc.h
new file mode 100644
index 00..43fe29ca72
--- /dev/null
+++ b/linux-user/loongarch64/target_proc.h
@@ -0,0 

[PULL 08/13] linux-user: Emulate the Anonymous: keyword in /proc/self/smaps

2023-09-01 Thread Richard Henderson
From: Ilya Leoshkevich 

Core dumps produced by gdb's gcore when connected to qemu's gdbstub
lack stack. The reason is that gdb includes only anonymous memory in
core dumps, which is distinguished by a non-0 Anonymous: value.

Consider the mappings with PAGE_ANON fully anonymous, and the mappings
without it fully non-anonymous.

Tested-by: Helge Deller 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Ilya Leoshkevich 
[rth: Update for open_self_maps_* rewrite]
Signed-off-by: Richard Henderson 
---
 linux-user/syscall.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 0641d8f433..8d96acd085 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8167,7 +8167,7 @@ static void open_self_maps_4(const struct 
open_self_maps_data *d,
 "Private_Clean: 0 kB\n"
 "Private_Dirty: 0 kB\n"
 "Referenced:0 kB\n"
-"Anonymous: 0 kB\n"
+"Anonymous: %lu kB\n"
 "LazyFree:  0 kB\n"
 "AnonHugePages: 0 kB\n"
 "ShmemPmdMapped:0 kB\n"
@@ -8180,6 +8180,7 @@ static void open_self_maps_4(const struct 
open_self_maps_data *d,
 "THPeligible:0\n"
 "VmFlags:%s%s%s%s%s%s%s%s\n",
 size_kb, page_size_kb, page_size_kb,
+(flags & PAGE_ANON ? size_kb : 0),
 (flags & PAGE_READ) ? " rd" : "",
 (flags & PAGE_WRITE_ORG) ? " wr" : "",
 (flags & PAGE_EXEC) ? " ex" : "",
-- 
2.34.1




[PULL 04/13] util/selfmap: Use dev_t and ino_t in MapInfo

2023-09-01 Thread Richard Henderson
Use dev_t instead of a string, and ino_t instead of uint64_t.
The latter is likely to be identical on modern systems but is
more type-correct for usage.

Tested-by: Helge Deller 
Reviewed-by: Ilya Leoshkevich 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/qemu/selfmap.h |  4 ++--
 linux-user/syscall.c   |  6 --
 util/selfmap.c | 12 +++-
 3 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/include/qemu/selfmap.h b/include/qemu/selfmap.h
index 7d938945cb..1690a74f4b 100644
--- a/include/qemu/selfmap.h
+++ b/include/qemu/selfmap.h
@@ -20,10 +20,10 @@ typedef struct {
 bool is_exec;
 bool is_priv;
 
+dev_t dev;
+ino_t inode;
 uint64_t offset;
-uint64_t inode;
 const char *path;
-char dev[];
 } MapInfo;
 
 /**
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index faad3a56df..a562920a84 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8160,13 +8160,15 @@ static int open_self_maps_1(CPUArchState *cpu_env, int 
fd, bool smaps)
 }
 
 count = dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr
-" %c%c%c%c %08" PRIx64 " %s %"PRId64,
+" %c%c%c%c %08" PRIx64 " %02x:%02x %"PRId64,
 h2g(min), h2g(max - 1) + 1,
 (flags & PAGE_READ) ? 'r' : '-',
 (flags & PAGE_WRITE_ORG) ? 'w' : '-',
 (flags & PAGE_EXEC) ? 'x' : '-',
 e->is_priv ? 'p' : 's',
-(uint64_t) e->offset, e->dev, e->inode);
+(uint64_t)e->offset,
+major(e->dev), minor(e->dev),
+(uint64_t)e->inode);
 if (path) {
 dprintf(fd, "%*s%s\n", 73 - count, "", path);
 } else {
diff --git a/util/selfmap.c b/util/selfmap.c
index 4db5b42651..483cb617e2 100644
--- a/util/selfmap.c
+++ b/util/selfmap.c
@@ -30,19 +30,21 @@ IntervalTreeRoot *read_self_maps(void)
 
 if (nfields > 4) {
 uint64_t start, end, offset, inode;
+unsigned dev_maj, dev_min;
 int errors = 0;
 const char *p;
 
 errors |= qemu_strtou64(fields[0], , 16, );
 errors |= qemu_strtou64(p + 1, NULL, 16, );
 errors |= qemu_strtou64(fields[2], NULL, 16, );
+errors |= qemu_strtoui(fields[3], , 16, _maj);
+errors |= qemu_strtoui(p + 1, NULL, 16, _min);
 errors |= qemu_strtou64(fields[4], NULL, 10, );
 
 if (!errors) {
-size_t dev_len, path_len;
+size_t path_len;
 MapInfo *e;
 
-dev_len = strlen(fields[3]) + 1;
 if (nfields == 6) {
 p = fields[5];
 p += strspn(p, " ");
@@ -52,11 +54,12 @@ IntervalTreeRoot *read_self_maps(void)
 path_len = 0;
 }
 
-e = g_malloc0(sizeof(*e) + dev_len + path_len);
+e = g_malloc0(sizeof(*e) + path_len);
 
 e->itree.start = start;
 e->itree.last = end - 1;
 e->offset = offset;
+e->dev = makedev(dev_maj, dev_min);
 e->inode = inode;
 
 e->is_read  = fields[1][0] == 'r';
@@ -64,9 +67,8 @@ IntervalTreeRoot *read_self_maps(void)
 e->is_exec  = fields[1][2] == 'x';
 e->is_priv  = fields[1][3] == 'p';
 
-memcpy(e->dev, fields[3], dev_len);
 if (path_len) {
-e->path = memcpy(e->dev + dev_len, p, path_len);
+e->path = memcpy(e + 1, p, path_len);
 }
 
 interval_tree_insert(>itree, root);
-- 
2.34.1




[PULL 02/13] linux-user: Emulate /proc/cpuinfo on aarch64 and arm

2023-09-01 Thread Richard Henderson
From: Helge Deller 

Add emulation for /proc/cpuinfo for arm architecture.
The output below mimics output as seen on debian porterboxes.

aarch64 output example:

processor   : 0
model name  : ARMv8 Processor rev 0 (v8l)
BogoMIPS: 100.00
Features: swp half thumb fast_mult vfp edsp neon vfpv3 tls vfpv4 idiva 
idivt vfpd32 lpae aes pmull sha1 sha2 crc32
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x1
CPU part: 0xd07
CPU revision: 0

arm 32-bit output example:

processor   : 0
model name  : ARMv7 Processor rev 5 (armv7l)
BogoMIPS: 100.00
Features: swp half thumb fast_mult vfp edsp thumbee neon vfpv3 tls 
vfpv4 idiva idivt vfpd32 lpae
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0f
CPU part: 0xc07
CPU revision: 5

Signed-off-by: Helge Deller 
Reviewed-by: Richard Henderson 
Message-Id: <20230803214450.647040-3-del...@gmx.de>
Signed-off-by: Richard Henderson 
---
 linux-user/aarch64/target_proc.h |   2 +-
 linux-user/arm/target_proc.h | 102 +++-
 linux-user/loader.h  |   6 +-
 linux-user/elfload.c | 130 ++-
 4 files changed, 233 insertions(+), 7 deletions(-)

diff --git a/linux-user/aarch64/target_proc.h b/linux-user/aarch64/target_proc.h
index 43fe29ca72..907df4dcd2 100644
--- a/linux-user/aarch64/target_proc.h
+++ b/linux-user/aarch64/target_proc.h
@@ -1 +1 @@
-/* No target-specific /proc support */
+#include "../arm/target_proc.h"
diff --git a/linux-user/arm/target_proc.h b/linux-user/arm/target_proc.h
index 43fe29ca72..ac75af9ca6 100644
--- a/linux-user/arm/target_proc.h
+++ b/linux-user/arm/target_proc.h
@@ -1 +1,101 @@
-/* No target-specific /proc support */
+/*
+ * Arm specific proc functions for linux-user
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef ARM_TARGET_PROC_H
+#define ARM_TARGET_PROC_H
+
+static int open_cpuinfo(CPUArchState *cpu_env, int fd)
+{
+ARMCPU *cpu = env_archcpu(cpu_env);
+int arch, midr_rev, midr_part, midr_var, midr_impl;
+target_ulong elf_hwcap = get_elf_hwcap();
+target_ulong elf_hwcap2 = get_elf_hwcap2();
+const char *elf_name;
+int num_cpus, len_part, len_var;
+
+#if TARGET_BIG_ENDIAN
+# define END_SUFFIX "b"
+#else
+# define END_SUFFIX "l"
+#endif
+
+arch = 8;
+elf_name = "v8" END_SUFFIX;
+midr_rev = FIELD_EX32(cpu->midr, MIDR_EL1, REVISION);
+midr_part = FIELD_EX32(cpu->midr, MIDR_EL1, PARTNUM);
+midr_var = FIELD_EX32(cpu->midr, MIDR_EL1, VARIANT);
+midr_impl = FIELD_EX32(cpu->midr, MIDR_EL1, IMPLEMENTER);
+len_part = 3;
+len_var = 1;
+
+#ifndef TARGET_AARCH64
+/* For simplicity, treat ARMv8 as an arm64 kernel with CONFIG_COMPAT. */
+if (!arm_feature(>env, ARM_FEATURE_V8)) {
+if (arm_feature(>env, ARM_FEATURE_V7)) {
+arch = 7;
+midr_var = (cpu->midr >> 16) & 0x7f;
+len_var = 2;
+if (arm_feature(>env, ARM_FEATURE_M)) {
+elf_name = "armv7m" END_SUFFIX;
+} else {
+elf_name = "armv7" END_SUFFIX;
+}
+} else {
+midr_part = cpu->midr >> 4;
+len_part = 7;
+if (arm_feature(>env, ARM_FEATURE_V6)) {
+arch = 6;
+elf_name = "armv6" END_SUFFIX;
+} else if (arm_feature(>env, ARM_FEATURE_V5)) {
+arch = 5;
+elf_name = "armv5t" END_SUFFIX;
+} else {
+arch = 4;
+elf_name = "armv4" END_SUFFIX;
+}
+}
+}
+#endif
+
+#undef END_SUFFIX
+
+num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+for (int i = 0; i < num_cpus; i++) {
+dprintf(fd,
+"processor\t: %d\n"
+"model name\t: ARMv%d Processor rev %d (%s)\n"
+"BogoMIPS\t: 100.00\n"
+"Features\t:",
+i, arch, midr_rev, elf_name);
+
+for (target_ulong j = elf_hwcap; j ; j &= j - 1) {
+dprintf(fd, " %s", elf_hwcap_str(ctz64(j)));
+}
+for (target_ulong j = elf_hwcap2; j ; j &= j - 1) {
+dprintf(fd, " %s", elf_hwcap2_str(ctz64(j)));
+}
+
+dprintf(fd, "\n"
+"CPU implementer\t: 0x%02x\n"
+"CPU architecture: %d\n"
+"CPU variant\t: 0x%0*x\n",
+midr_impl, arch, len_var, midr_var);
+if (arch >= 7) {
+dprintf(fd, "CPU part\t: 0x%0*x\n", len_part, midr_part);
+}
+dprintf(fd, "CPU revision\t: %d\n\n", midr_rev);
+}
+
+if (arch < 8) {
+dprintf(fd, "Hardware\t: QEMU v%s %s\n", QEMU_VERSION,
+cpu->dtb_compatible ? : "");
+dprintf(fd, "Revision\t: \n");
+dprintf(fd, "Serial\t\t: \n");
+}
+return 0;
+}
+#define HAVE_ARCH_PROC_CPUINFO
+
+#endif /* ARM_TARGET_PROC_H */
diff --git 

[PULL 00/13] linux-user patch queue

2023-09-01 Thread Richard Henderson
The following changes since commit 17780edd81d27fcfdb7a802efc870a99788bd2fc:

  Merge tag 'quick-fix-pull-request' of https://gitlab.com/bsdimp/qemu into 
staging (2023-08-31 10:06:29 -0400)

are available in the Git repository at:

  https://gitlab.com/rth7680/qemu.git tags/pull-lu-20230901

for you to fetch changes up to 044e95c81e750a0605deb12a20ee23bfde7dc9c8:

  linux-user: Track shm regions with an interval tree (2023-09-01 13:35:57 
-0700)


linux-user: Rewrite and improve /proc/pid/maps
linux-user: Fix shmdt and improve shm region tracking
linux-user: Remove ELF_START_MMAP and image_info.start_mmap


Helge Deller (2):
  linux-user: Emulate /proc/cpuinfo on aarch64 and arm
  linux-user: Emulate /proc/cpuinfo for Alpha

Ilya Leoshkevich (1):
  linux-user: Emulate the Anonymous: keyword in /proc/self/smaps

Richard Henderson (10):
  linux-user: Split out cpu/target_proc.h
  util/selfmap: Use dev_t and ino_t in MapInfo
  linux-user: Use walk_memory_regions for open_self_maps
  linux-user: Adjust brk for load_bias
  linux-user: Show heap address in /proc/pid/maps
  linux-user: Remove ELF_START_MMAP and image_info.start_mmap
  linux-user: Move shmat and shmdt implementations to mmap.c
  linux-user: Use WITH_MMAP_LOCK_GUARD in target_{shmat,shmdt}
  linux-user: Fix shmdt
  linux-user: Track shm regions with an interval tree

 include/qemu/selfmap.h   |   4 +-
 linux-user/aarch64/target_proc.h |   1 +
 linux-user/alpha/target_proc.h   |  67 +
 linux-user/arm/target_proc.h | 101 +++
 linux-user/cris/target_proc.h|   1 +
 linux-user/hexagon/target_proc.h |   1 +
 linux-user/hppa/target_proc.h|  26 ++
 linux-user/i386/target_proc.h|   1 +
 linux-user/loader.h  |   6 +-
 linux-user/loongarch64/target_proc.h |   1 +
 linux-user/m68k/target_proc.h|  16 ++
 linux-user/microblaze/target_proc.h  |   1 +
 linux-user/mips/target_proc.h|   1 +
 linux-user/mips64/target_proc.h  |   1 +
 linux-user/nios2/target_proc.h   |   1 +
 linux-user/openrisc/target_proc.h|   1 +
 linux-user/ppc/target_proc.h |   1 +
 linux-user/qemu.h|   1 -
 linux-user/riscv/target_proc.h   |  37 +++
 linux-user/s390x/target_proc.h   | 109 
 linux-user/sh4/target_proc.h |   1 +
 linux-user/sparc/target_proc.h   |  16 ++
 linux-user/user-mmap.h   |   4 +
 linux-user/x86_64/target_proc.h  |   1 +
 linux-user/xtensa/target_proc.h  |   1 +
 linux-user/elfload.c | 170 +---
 linux-user/mmap.c| 168 
 linux-user/syscall.c | 514 +--
 util/selfmap.c   |  12 +-
 29 files changed, 828 insertions(+), 437 deletions(-)
 create mode 100644 linux-user/aarch64/target_proc.h
 create mode 100644 linux-user/alpha/target_proc.h
 create mode 100644 linux-user/arm/target_proc.h
 create mode 100644 linux-user/cris/target_proc.h
 create mode 100644 linux-user/hexagon/target_proc.h
 create mode 100644 linux-user/hppa/target_proc.h
 create mode 100644 linux-user/i386/target_proc.h
 create mode 100644 linux-user/loongarch64/target_proc.h
 create mode 100644 linux-user/m68k/target_proc.h
 create mode 100644 linux-user/microblaze/target_proc.h
 create mode 100644 linux-user/mips/target_proc.h
 create mode 100644 linux-user/mips64/target_proc.h
 create mode 100644 linux-user/nios2/target_proc.h
 create mode 100644 linux-user/openrisc/target_proc.h
 create mode 100644 linux-user/ppc/target_proc.h
 create mode 100644 linux-user/riscv/target_proc.h
 create mode 100644 linux-user/s390x/target_proc.h
 create mode 100644 linux-user/sh4/target_proc.h
 create mode 100644 linux-user/sparc/target_proc.h
 create mode 100644 linux-user/x86_64/target_proc.h
 create mode 100644 linux-user/xtensa/target_proc.h



[PULL 09/13] linux-user: Remove ELF_START_MMAP and image_info.start_mmap

2023-09-01 Thread Richard Henderson
The start_mmap value is write-only.
Remove the field and the defines that populated it.
Logically, this has been replaced by task_unmapped_base.

Tested-by: Helge Deller 
Reviewed-by: Ilya Leoshkevich 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 linux-user/qemu.h|  1 -
 linux-user/elfload.c | 38 --
 2 files changed, 39 deletions(-)

diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 4f8b55e2fb..12f638336a 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -30,7 +30,6 @@ struct image_info {
 abi_ulong   start_data;
 abi_ulong   end_data;
 abi_ulong   brk;
-abi_ulong   start_mmap;
 abi_ulong   start_stack;
 abi_ulong   stack_limit;
 abi_ulong   entry;
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index d52d47c5c3..a5b28fa3e7 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -143,8 +143,6 @@ static uint32_t get_elf_hwcap(void)
 }
 
 #ifdef TARGET_X86_64
-#define ELF_START_MMAP 0x2ab000ULL
-
 #define ELF_CLASS  ELFCLASS64
 #define ELF_ARCH   EM_X86_64
 
@@ -221,8 +219,6 @@ static bool init_guest_commpage(void)
 #endif
 #else
 
-#define ELF_START_MMAP 0x8000
-
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
@@ -308,8 +304,6 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, 
const CPUX86State *en
 #ifndef TARGET_AARCH64
 /* 32 bit ARM definitions */
 
-#define ELF_START_MMAP 0x8000
-
 #define ELF_ARCHEM_ARM
 #define ELF_CLASS   ELFCLASS32
 #define EXSTACK_DEFAULT true
@@ -600,7 +594,6 @@ static const char *get_elf_platform(void)
 
 #else
 /* 64 bit ARM definitions */
-#define ELF_START_MMAP 0x8000
 
 #define ELF_ARCHEM_AARCH64
 #define ELF_CLASS   ELFCLASS64
@@ -871,7 +864,6 @@ const char *elf_hwcap2_str(uint32_t bit)
 #ifdef TARGET_SPARC
 #ifdef TARGET_SPARC64
 
-#define ELF_START_MMAP 0x8000
 #define ELF_HWCAP  (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \
 | HWCAP_SPARC_MULDIV | HWCAP_SPARC_V9)
 #ifndef TARGET_ABI32
@@ -883,7 +875,6 @@ const char *elf_hwcap2_str(uint32_t bit)
 #define ELF_CLASS   ELFCLASS64
 #define ELF_ARCHEM_SPARCV9
 #else
-#define ELF_START_MMAP 0x8000
 #define ELF_HWCAP  (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \
 | HWCAP_SPARC_MULDIV)
 #define ELF_CLASS   ELFCLASS32
@@ -905,7 +896,6 @@ static inline void init_thread(struct target_pt_regs *regs,
 #ifdef TARGET_PPC
 
 #define ELF_MACHINEPPC_ELF_MACHINE
-#define ELF_START_MMAP 0x8000
 
 #if defined(TARGET_PPC64)
 
@@ -1108,8 +1098,6 @@ static void elf_core_copy_regs(target_elf_gregset_t 
*regs, const CPUPPCState *en
 
 #ifdef TARGET_LOONGARCH64
 
-#define ELF_START_MMAP 0x8000
-
 #define ELF_CLASS   ELFCLASS64
 #define ELF_ARCHEM_LOONGARCH
 #define EXSTACK_DEFAULT true
@@ -1200,8 +1188,6 @@ static uint32_t get_elf_hwcap(void)
 
 #ifdef TARGET_MIPS
 
-#define ELF_START_MMAP 0x8000
-
 #ifdef TARGET_MIPS64
 #define ELF_CLASS   ELFCLASS64
 #else
@@ -1359,8 +1345,6 @@ static uint32_t get_elf_hwcap(void)
 
 #ifdef TARGET_MICROBLAZE
 
-#define ELF_START_MMAP 0x8000
-
 #define elf_check_arch(x) ( (x) == EM_MICROBLAZE || (x) == EM_MICROBLAZE_OLD)
 
 #define ELF_CLASS   ELFCLASS32
@@ -1401,8 +1385,6 @@ static void elf_core_copy_regs(target_elf_gregset_t 
*regs, const CPUMBState *env
 
 #ifdef TARGET_NIOS2
 
-#define ELF_START_MMAP 0x8000
-
 #define elf_check_arch(x) ((x) == EM_ALTERA_NIOS2)
 
 #define ELF_CLASS   ELFCLASS32
@@ -1498,8 +1480,6 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
 
 #ifdef TARGET_OPENRISC
 
-#define ELF_START_MMAP 0x0800
-
 #define ELF_ARCH EM_OPENRISC
 #define ELF_CLASS ELFCLASS32
 #define ELF_DATA  ELFDATA2MSB
@@ -1536,8 +1516,6 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
 
 #ifdef TARGET_SH4
 
-#define ELF_START_MMAP 0x8000
-
 #define ELF_CLASS ELFCLASS32
 #define ELF_ARCH  EM_SH
 
@@ -1618,8 +1596,6 @@ static uint32_t get_elf_hwcap(void)
 
 #ifdef TARGET_CRIS
 
-#define ELF_START_MMAP 0x8000
-
 #define ELF_CLASS ELFCLASS32
 #define ELF_ARCH  EM_CRIS
 
@@ -1635,8 +1611,6 @@ static inline void init_thread(struct target_pt_regs 
*regs,
 
 #ifdef TARGET_M68K
 
-#define ELF_START_MMAP 0x8000
-
 #define ELF_CLASS   ELFCLASS32
 #define ELF_ARCHEM_68K
 
@@ -1686,8 +1660,6 @@ static void elf_core_copy_regs(target_elf_gregset_t 
*regs, const CPUM68KState *e
 
 #ifdef TARGET_ALPHA
 
-#define ELF_START_MMAP (0x300ULL)
-
 #define ELF_CLASS  ELFCLASS64
 #define ELF_ARCH   EM_ALPHA
 
@@ -1705,8 +1677,6 @@ static inline void init_thread(struct target_pt_regs 
*regs,
 
 #ifdef TARGET_S390X
 
-#define ELF_START_MMAP (0x200ULL)
-
 #define ELF_CLASS  ELFCLASS64
 #define ELF_DATA   ELFDATA2MSB
 #define ELF_ARCH   EM_S390
@@ -1817,7 +1787,6 @@ 

[PULL 12/13] linux-user: Fix shmdt

2023-09-01 Thread Richard Henderson
If the shm region is not mapped at shmaddr, EINVAL.
Do not unmap the region until the syscall succeeds.
Use mmap_reserve_or_unmap to preserve reserved_va semantics.

Tested-by: Helge Deller 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 linux-user/mmap.c | 17 ++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index f45b2d307c..44116c014b 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -1102,14 +1102,25 @@ abi_long target_shmdt(abi_ulong shmaddr)
 /* shmdt pointers are always untagged */
 
 WITH_MMAP_LOCK_GUARD() {
-for (int i = 0; i < N_SHM_REGIONS; ++i) {
+int i;
+
+for (i = 0; i < N_SHM_REGIONS; ++i) {
 if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
-shm_regions[i].in_use = false;
-page_set_flags(shmaddr, shmaddr + shm_regions[i].size - 1, 0);
 break;
 }
 }
+if (i == N_SHM_REGIONS) {
+return -TARGET_EINVAL;
+}
+
 rv = get_errno(shmdt(g2h_untagged(shmaddr)));
+if (rv == 0) {
+abi_ulong size = shm_regions[i].size;
+
+shm_regions[i].in_use = false;
+page_set_flags(shmaddr, shmaddr + size - 1, 0);
+mmap_reserve_or_unmap(shmaddr, size);
+}
 }
 return rv;
 }
-- 
2.34.1




[PULL 07/13] linux-user: Show heap address in /proc/pid/maps

2023-09-01 Thread Richard Henderson
Tested-by: Helge Deller 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Ilya Leoshkevich 
Signed-off-by: Richard Henderson 
---
 linux-user/syscall.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 0b91f996b7..0641d8f433 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8125,6 +8125,8 @@ static void open_self_maps_4(const struct 
open_self_maps_data *d,
 
 if (test_stack(start, end, info->stack_limit)) {
 path = "[stack]";
+} else if (start == info->brk) {
+path = "[heap]";
 }
 
 /* Except null device (MAP_ANON), adjust offset for this fragment. */
-- 
2.34.1




[PULL 10/13] linux-user: Move shmat and shmdt implementations to mmap.c

2023-09-01 Thread Richard Henderson
Rename from do_* to target_*.  Fix some minor checkpatch errors.

Tested-by: Helge Deller 
Tested-by: Philippe Mathieu-Daudé 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Warner Losh 
Signed-off-by: Richard Henderson 
---
 linux-user/user-mmap.h |   4 ++
 linux-user/mmap.c  | 138 +++
 linux-user/syscall.c   | 143 ++---
 3 files changed, 146 insertions(+), 139 deletions(-)

diff --git a/linux-user/user-mmap.h b/linux-user/user-mmap.h
index 0f4883eb57..b94bcdcf83 100644
--- a/linux-user/user-mmap.h
+++ b/linux-user/user-mmap.h
@@ -58,4 +58,8 @@ abi_ulong mmap_find_vma(abi_ulong, abi_ulong, abi_ulong);
 void mmap_fork_start(void);
 void mmap_fork_end(int child);
 
+abi_ulong target_shmat(CPUArchState *cpu_env, int shmid,
+   abi_ulong shmaddr, int shmflg);
+abi_long target_shmdt(abi_ulong shmaddr);
+
 #endif /* LINUX_USER_USER_MMAP_H */
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 9aab48d4a3..3aeacd1ecd 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -17,6 +17,7 @@
  *  along with this program; if not, see .
  */
 #include "qemu/osdep.h"
+#include 
 #include "trace.h"
 #include "exec/log.h"
 #include "qemu.h"
@@ -27,6 +28,14 @@
 static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
 static __thread int mmap_lock_count;
 
+#define N_SHM_REGIONS  32
+
+static struct shm_region {
+abi_ulong start;
+abi_ulong size;
+bool in_use;
+} shm_regions[N_SHM_REGIONS];
+
 void mmap_lock(void)
 {
 if (mmap_lock_count++ == 0) {
@@ -981,3 +990,132 @@ abi_long target_madvise(abi_ulong start, abi_ulong 
len_in, int advice)
 
 return ret;
 }
+
+#ifndef TARGET_FORCE_SHMLBA
+/*
+ * For most architectures, SHMLBA is the same as the page size;
+ * some architectures have larger values, in which case they should
+ * define TARGET_FORCE_SHMLBA and provide a target_shmlba() function.
+ * This corresponds to the kernel arch code defining __ARCH_FORCE_SHMLBA
+ * and defining its own value for SHMLBA.
+ *
+ * The kernel also permits SHMLBA to be set by the architecture to a
+ * value larger than the page size without setting __ARCH_FORCE_SHMLBA;
+ * this means that addresses are rounded to the large size if
+ * SHM_RND is set but addresses not aligned to that size are not rejected
+ * as long as they are at least page-aligned. Since the only architecture
+ * which uses this is ia64 this code doesn't provide for that oddity.
+ */
+static inline abi_ulong target_shmlba(CPUArchState *cpu_env)
+{
+return TARGET_PAGE_SIZE;
+}
+#endif
+
+abi_ulong target_shmat(CPUArchState *cpu_env, int shmid,
+   abi_ulong shmaddr, int shmflg)
+{
+CPUState *cpu = env_cpu(cpu_env);
+abi_ulong raddr;
+void *host_raddr;
+struct shmid_ds shm_info;
+int i, ret;
+abi_ulong shmlba;
+
+/* shmat pointers are always untagged */
+
+/* find out the length of the shared memory segment */
+ret = get_errno(shmctl(shmid, IPC_STAT, _info));
+if (is_error(ret)) {
+/* can't get length, bail out */
+return ret;
+}
+
+shmlba = target_shmlba(cpu_env);
+
+if (shmaddr & (shmlba - 1)) {
+if (shmflg & SHM_RND) {
+shmaddr &= ~(shmlba - 1);
+} else {
+return -TARGET_EINVAL;
+}
+}
+if (!guest_range_valid_untagged(shmaddr, shm_info.shm_segsz)) {
+return -TARGET_EINVAL;
+}
+
+mmap_lock();
+
+/*
+ * We're mapping shared memory, so ensure we generate code for parallel
+ * execution and flush old translations.  This will work up to the level
+ * supported by the host -- anything that requires EXCP_ATOMIC will not
+ * be atomic with respect to an external process.
+ */
+if (!(cpu->tcg_cflags & CF_PARALLEL)) {
+cpu->tcg_cflags |= CF_PARALLEL;
+tb_flush(cpu);
+}
+
+if (shmaddr) {
+host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg);
+} else {
+abi_ulong mmap_start;
+
+/* In order to use the host shmat, we need to honor host SHMLBA.  */
+mmap_start = mmap_find_vma(0, shm_info.shm_segsz, MAX(SHMLBA, shmlba));
+
+if (mmap_start == -1) {
+errno = ENOMEM;
+host_raddr = (void *)-1;
+} else {
+host_raddr = shmat(shmid, g2h_untagged(mmap_start),
+   shmflg | SHM_REMAP);
+}
+}
+
+if (host_raddr == (void *)-1) {
+mmap_unlock();
+return get_errno((intptr_t)host_raddr);
+}
+raddr = h2g((uintptr_t)host_raddr);
+
+page_set_flags(raddr, raddr + shm_info.shm_segsz - 1,
+   PAGE_VALID | PAGE_RESET | PAGE_READ |
+   (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
+
+for (i = 0; i < N_SHM_REGIONS; i++) {
+if (!shm_regions[i].in_use) {
+shm_regions[i].in_use = true;
+shm_regions[i].start = 

[PULL 06/13] linux-user: Adjust brk for load_bias

2023-09-01 Thread Richard Henderson
PIE executables are usually linked at offset 0 and are
relocated somewhere during load.  The hiaddr needs to
be adjusted to keep the brk next to the executable.

Cc: qemu-sta...@nongnu.org
Fixes: 1f356e8c013 ("linux-user: Adjust initial brk when interpreter is close 
to executable")
Tested-by: Helge Deller 
Reviewed-by: Ilya Leoshkevich 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 linux-user/elfload.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 7c95098e3e..d52d47c5c3 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -3327,7 +3327,7 @@ static void load_elf_image(const char *image_name, int 
image_fd,
 info->start_data = -1;
 info->end_data = 0;
 /* Usual start for brk is after all sections of the main executable. */
-info->brk = TARGET_PAGE_ALIGN(hiaddr);
+info->brk = TARGET_PAGE_ALIGN(hiaddr + load_bias);
 info->elf_flags = ehdr->e_flags;
 
 prot_exec = PROT_EXEC;
-- 
2.34.1




[PULL 13/13] linux-user: Track shm regions with an interval tree

2023-09-01 Thread Richard Henderson
Remove the fixed size shm_regions[] array.
Remove references when other mappings completely remove
or replace a region.

Tested-by: Helge Deller 
Reviewed-by: Helge Deller 
Signed-off-by: Richard Henderson 
---
 linux-user/mmap.c | 81 +++
 1 file changed, 53 insertions(+), 28 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 44116c014b..8eaf57b208 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -24,18 +24,11 @@
 #include "user-internals.h"
 #include "user-mmap.h"
 #include "target_mman.h"
+#include "qemu/interval-tree.h"
 
 static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
 static __thread int mmap_lock_count;
 
-#define N_SHM_REGIONS  32
-
-static struct shm_region {
-abi_ulong start;
-abi_ulong size;
-bool in_use;
-} shm_regions[N_SHM_REGIONS];
-
 void mmap_lock(void)
 {
 if (mmap_lock_count++ == 0) {
@@ -73,6 +66,44 @@ void mmap_fork_end(int child)
 }
 }
 
+/* Protected by mmap_lock. */
+static IntervalTreeRoot shm_regions;
+
+static void shm_region_add(abi_ptr start, abi_ptr last)
+{
+IntervalTreeNode *i = g_new0(IntervalTreeNode, 1);
+
+i->start = start;
+i->last = last;
+interval_tree_insert(i, _regions);
+}
+
+static abi_ptr shm_region_find(abi_ptr start)
+{
+IntervalTreeNode *i;
+
+for (i = interval_tree_iter_first(_regions, start, start); i;
+ i = interval_tree_iter_next(i, start, start)) {
+if (i->start == start) {
+return i->last;
+}
+}
+return 0;
+}
+
+static void shm_region_rm_complete(abi_ptr start, abi_ptr last)
+{
+IntervalTreeNode *i, *n;
+
+for (i = interval_tree_iter_first(_regions, start, last); i; i = n) {
+n = interval_tree_iter_next(i, start, last);
+if (i->start >= start && i->last <= last) {
+interval_tree_remove(i, _regions);
+g_free(i);
+}
+}
+}
+
 /*
  * Validate target prot bitmask.
  * Return the prot bitmask for the host in *HOST_PROT.
@@ -729,6 +760,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
target_prot,
 page_set_flags(passthrough_last + 1, last, page_flags);
 }
 }
+shm_region_rm_complete(start, last);
  the_end:
 trace_target_mmap_complete(start);
 if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
@@ -826,6 +858,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
 mmap_lock();
 mmap_reserve_or_unmap(start, len);
 page_set_flags(start, start + len - 1, 0);
+shm_region_rm_complete(start, start + len - 1);
 mmap_unlock();
 
 return 0;
@@ -915,8 +948,10 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong 
old_size,
 new_addr = h2g(host_addr);
 prot = page_get_flags(old_addr);
 page_set_flags(old_addr, old_addr + old_size - 1, 0);
+shm_region_rm_complete(old_addr, old_addr + old_size - 1);
 page_set_flags(new_addr, new_addr + new_size - 1,
prot | PAGE_VALID | PAGE_RESET);
+shm_region_rm_complete(new_addr, new_addr + new_size - 1);
 }
 mmap_unlock();
 return new_addr;
@@ -1045,6 +1080,7 @@ abi_ulong target_shmat(CPUArchState *cpu_env, int shmid,
 
 WITH_MMAP_LOCK_GUARD() {
 void *host_raddr;
+abi_ulong last;
 
 if (shmaddr) {
 host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg);
@@ -1066,19 +1102,14 @@ abi_ulong target_shmat(CPUArchState *cpu_env, int shmid,
 return get_errno(-1);
 }
 raddr = h2g(host_raddr);
+last = raddr + shm_info.shm_segsz - 1;
 
-page_set_flags(raddr, raddr + shm_info.shm_segsz - 1,
+page_set_flags(raddr, last,
PAGE_VALID | PAGE_RESET | PAGE_READ |
(shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
 
-for (int i = 0; i < N_SHM_REGIONS; i++) {
-if (!shm_regions[i].in_use) {
-shm_regions[i].in_use = true;
-shm_regions[i].start = raddr;
-shm_regions[i].size = shm_info.shm_segsz;
-break;
-}
-}
+shm_region_rm_complete(raddr, last);
+shm_region_add(raddr, last);
 }
 
 /*
@@ -1102,23 +1133,17 @@ abi_long target_shmdt(abi_ulong shmaddr)
 /* shmdt pointers are always untagged */
 
 WITH_MMAP_LOCK_GUARD() {
-int i;
-
-for (i = 0; i < N_SHM_REGIONS; ++i) {
-if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
-break;
-}
-}
-if (i == N_SHM_REGIONS) {
+abi_ulong last = shm_region_find(shmaddr);
+if (last == 0) {
 return -TARGET_EINVAL;
 }
 
 rv = get_errno(shmdt(g2h_untagged(shmaddr)));
 if (rv == 0) {
-abi_ulong size = shm_regions[i].size;
+abi_ulong size = last - shmaddr + 1;
 
-shm_regions[i].in_use = false;
-

[PULL 11/13] linux-user: Use WITH_MMAP_LOCK_GUARD in target_{shmat, shmdt}

2023-09-01 Thread Richard Henderson
Move the CF_PARALLEL setting outside of the mmap lock.

Tested-by: Helge Deller 
Reviewed-by: Helge Deller 
Signed-off-by: Richard Henderson 
---
 linux-user/mmap.c | 98 ++-
 1 file changed, 46 insertions(+), 52 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 3aeacd1ecd..f45b2d307c 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -1017,9 +1017,8 @@ abi_ulong target_shmat(CPUArchState *cpu_env, int shmid,
 {
 CPUState *cpu = env_cpu(cpu_env);
 abi_ulong raddr;
-void *host_raddr;
 struct shmid_ds shm_info;
-int i, ret;
+int ret;
 abi_ulong shmlba;
 
 /* shmat pointers are always untagged */
@@ -1044,7 +1043,43 @@ abi_ulong target_shmat(CPUArchState *cpu_env, int shmid,
 return -TARGET_EINVAL;
 }
 
-mmap_lock();
+WITH_MMAP_LOCK_GUARD() {
+void *host_raddr;
+
+if (shmaddr) {
+host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg);
+} else {
+abi_ulong mmap_start;
+
+/* In order to use the host shmat, we need to honor host SHMLBA.  
*/
+mmap_start = mmap_find_vma(0, shm_info.shm_segsz,
+   MAX(SHMLBA, shmlba));
+
+if (mmap_start == -1) {
+return -TARGET_ENOMEM;
+}
+host_raddr = shmat(shmid, g2h_untagged(mmap_start),
+   shmflg | SHM_REMAP);
+}
+
+if (host_raddr == (void *)-1) {
+return get_errno(-1);
+}
+raddr = h2g(host_raddr);
+
+page_set_flags(raddr, raddr + shm_info.shm_segsz - 1,
+   PAGE_VALID | PAGE_RESET | PAGE_READ |
+   (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
+
+for (int i = 0; i < N_SHM_REGIONS; i++) {
+if (!shm_regions[i].in_use) {
+shm_regions[i].in_use = true;
+shm_regions[i].start = raddr;
+shm_regions[i].size = shm_info.shm_segsz;
+break;
+}
+}
+}
 
 /*
  * We're mapping shared memory, so ensure we generate code for parallel
@@ -1057,65 +1092,24 @@ abi_ulong target_shmat(CPUArchState *cpu_env, int shmid,
 tb_flush(cpu);
 }
 
-if (shmaddr) {
-host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg);
-} else {
-abi_ulong mmap_start;
-
-/* In order to use the host shmat, we need to honor host SHMLBA.  */
-mmap_start = mmap_find_vma(0, shm_info.shm_segsz, MAX(SHMLBA, shmlba));
-
-if (mmap_start == -1) {
-errno = ENOMEM;
-host_raddr = (void *)-1;
-} else {
-host_raddr = shmat(shmid, g2h_untagged(mmap_start),
-   shmflg | SHM_REMAP);
-}
-}
-
-if (host_raddr == (void *)-1) {
-mmap_unlock();
-return get_errno((intptr_t)host_raddr);
-}
-raddr = h2g((uintptr_t)host_raddr);
-
-page_set_flags(raddr, raddr + shm_info.shm_segsz - 1,
-   PAGE_VALID | PAGE_RESET | PAGE_READ |
-   (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
-
-for (i = 0; i < N_SHM_REGIONS; i++) {
-if (!shm_regions[i].in_use) {
-shm_regions[i].in_use = true;
-shm_regions[i].start = raddr;
-shm_regions[i].size = shm_info.shm_segsz;
-break;
-}
-}
-
-mmap_unlock();
 return raddr;
 }
 
 abi_long target_shmdt(abi_ulong shmaddr)
 {
-int i;
 abi_long rv;
 
 /* shmdt pointers are always untagged */
 
-mmap_lock();
-
-for (i = 0; i < N_SHM_REGIONS; ++i) {
-if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
-shm_regions[i].in_use = false;
-page_set_flags(shmaddr, shmaddr + shm_regions[i].size - 1, 0);
-break;
+WITH_MMAP_LOCK_GUARD() {
+for (int i = 0; i < N_SHM_REGIONS; ++i) {
+if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
+shm_regions[i].in_use = false;
+page_set_flags(shmaddr, shmaddr + shm_regions[i].size - 1, 0);
+break;
+}
 }
+rv = get_errno(shmdt(g2h_untagged(shmaddr)));
 }
-rv = get_errno(shmdt(g2h_untagged(shmaddr)));
-
-mmap_unlock();
-
 return rv;
 }
-- 
2.34.1




[PULL 05/13] linux-user: Use walk_memory_regions for open_self_maps

2023-09-01 Thread Richard Henderson
Replace the by-hand method of region identification with
the official user-exec interface.  Cross-check the region
provided to the callback with the interval tree from
read_self_maps().

Tested-by: Helge Deller 
Reviewed-by: Ilya Leoshkevich 
Signed-off-by: Richard Henderson 
---
 linux-user/syscall.c | 192 ++-
 1 file changed, 115 insertions(+), 77 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index a562920a84..0b91f996b7 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8095,12 +8095,66 @@ static int open_self_cmdline(CPUArchState *cpu_env, int 
fd)
 return 0;
 }
 
-static void show_smaps(int fd, unsigned long size)
-{
-unsigned long page_size_kb = TARGET_PAGE_SIZE >> 10;
-unsigned long size_kb = size >> 10;
+struct open_self_maps_data {
+TaskState *ts;
+IntervalTreeRoot *host_maps;
+int fd;
+bool smaps;
+};
 
-dprintf(fd, "Size:  %lu kB\n"
+/*
+ * Subroutine to output one line of /proc/self/maps,
+ * or one region of /proc/self/smaps.
+ */
+
+#ifdef TARGET_HPPA
+# define test_stack(S, E, L)  (E == L)
+#else
+# define test_stack(S, E, L)  (S == L)
+#endif
+
+static void open_self_maps_4(const struct open_self_maps_data *d,
+ const MapInfo *mi, abi_ptr start,
+ abi_ptr end, unsigned flags)
+{
+const struct image_info *info = d->ts->info;
+const char *path = mi->path;
+uint64_t offset;
+int fd = d->fd;
+int count;
+
+if (test_stack(start, end, info->stack_limit)) {
+path = "[stack]";
+}
+
+/* Except null device (MAP_ANON), adjust offset for this fragment. */
+offset = mi->offset;
+if (mi->dev) {
+uintptr_t hstart = (uintptr_t)g2h_untagged(start);
+offset += hstart - mi->itree.start;
+}
+
+count = dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr
+" %c%c%c%c %08" PRIx64 " %02x:%02x %"PRId64,
+start, end,
+(flags & PAGE_READ) ? 'r' : '-',
+(flags & PAGE_WRITE_ORG) ? 'w' : '-',
+(flags & PAGE_EXEC) ? 'x' : '-',
+mi->is_priv ? 'p' : 's',
+offset, major(mi->dev), minor(mi->dev),
+(uint64_t)mi->inode);
+if (path) {
+dprintf(fd, "%*s%s\n", 73 - count, "", path);
+} else {
+dprintf(fd, "\n");
+}
+
+if (d->smaps) {
+unsigned long size = end - start;
+unsigned long page_size_kb = TARGET_PAGE_SIZE >> 10;
+unsigned long size_kb = size >> 10;
+
+dprintf(fd, "Size:  %lu kB\n"
 "KernelPageSize:%lu kB\n"
 "MMUPageSize:   %lu kB\n"
 "Rss:   0 kB\n"
@@ -8121,91 +8175,75 @@ static void show_smaps(int fd, unsigned long size)
 "Swap:  0 kB\n"
 "SwapPss:   0 kB\n"
 "Locked:0 kB\n"
-"THPeligible:0\n", size_kb, page_size_kb, page_size_kb);
+"THPeligible:0\n"
+"VmFlags:%s%s%s%s%s%s%s%s\n",
+size_kb, page_size_kb, page_size_kb,
+(flags & PAGE_READ) ? " rd" : "",
+(flags & PAGE_WRITE_ORG) ? " wr" : "",
+(flags & PAGE_EXEC) ? " ex" : "",
+mi->is_priv ? "" : " sh",
+(flags & PAGE_READ) ? " mr" : "",
+(flags & PAGE_WRITE_ORG) ? " mw" : "",
+(flags & PAGE_EXEC) ? " me" : "",
+mi->is_priv ? "" : " ms");
+}
 }
 
-static int open_self_maps_1(CPUArchState *cpu_env, int fd, bool smaps)
+/*
+ * Callback for walk_memory_regions, when read_self_maps() fails.
+ * Proceed without the benefit of host /proc/self/maps cross-check.
+ */
+static int open_self_maps_3(void *opaque, target_ulong guest_start,
+target_ulong guest_end, unsigned long flags)
 {
-CPUState *cpu = env_cpu(cpu_env);
-TaskState *ts = cpu->opaque;
-IntervalTreeRoot *map_info = read_self_maps();
-IntervalTreeNode *s;
-int count;
+static const MapInfo mi = { .is_priv = true };
 
-for (s = interval_tree_iter_first(map_info, 0, -1); s;
- s = interval_tree_iter_next(s, 0, -1)) {
-MapInfo *e = container_of(s, MapInfo, itree);
+open_self_maps_4(opaque, , guest_start, guest_end, flags);
+return 0;
+}
 
-if (h2g_valid(e->itree.start)) {
-unsigned long min = e->itree.start;
-unsigned long max = e->itree.last + 1;
-int flags = page_get_flags(h2g(min));
-const char *path;
+/*
+ * Callback for walk_memory_regions, when read_self_maps() succeeds.
+ */
+static int open_self_maps_2(void *opaque, target_ulong guest_start,
+target_ulong guest_end, unsigned long flags)
+{
+

[PULL 03/13] linux-user: Emulate /proc/cpuinfo for Alpha

2023-09-01 Thread Richard Henderson
From: Helge Deller 

Add emulation for /proc/cpuinfo for the alpha architecture.

alpha output example:

(alpha-chroot)root@p100:/# cat /proc/cpuinfo
cpu : Alpha
cpu model   : ev67
cpu variation   : 0
cpu revision: 0
cpu serial number   : JA
system type : QEMU
system variation: QEMU_v8.0.92
system revision : 0
system serial number: AY
cycle frequency [Hz]: 25000
timer frequency [Hz]: 250.00
page size [bytes]   : 8192
phys. address bits  : 44
max. addr. space #  : 255
BogoMIPS: 2500.00
platform string : AlphaServer QEMU user-mode VM
cpus detected   : 8
cpus active : 4
cpu active mask : 0095
L1 Icache   : n/a
L1 Dcache   : n/a
L2 cache: n/a
L3 cache: n/a

Signed-off-by: Helge Deller 
Reviewed-by: Richard Henderson 
Message-Id: <20230803214450.647040-4-del...@gmx.de>
Signed-off-by: Richard Henderson 
---
 linux-user/alpha/target_proc.h | 68 +-
 1 file changed, 67 insertions(+), 1 deletion(-)

diff --git a/linux-user/alpha/target_proc.h b/linux-user/alpha/target_proc.h
index 43fe29ca72..dac37dffc9 100644
--- a/linux-user/alpha/target_proc.h
+++ b/linux-user/alpha/target_proc.h
@@ -1 +1,67 @@
-/* No target-specific /proc support */
+/*
+ * Alpha specific proc functions for linux-user
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef ALPHA_TARGET_PROC_H
+#define ALPHA_TARGET_PROC_H
+
+static int open_cpuinfo(CPUArchState *cpu_env, int fd)
+{
+int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
+int num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+unsigned long cpu_mask;
+char model[32];
+const char *p, *q;
+int t;
+
+p = object_class_get_name(OBJECT_CLASS(CPU_GET_CLASS(env_cpu(cpu_env;
+q = strchr(p, '-');
+t = q - p;
+assert(t < sizeof(model));
+memcpy(model, p, t);
+model[t] = 0;
+
+t = sched_getaffinity(getpid(), sizeof(cpu_mask), (cpu_set_t *)_mask);
+if (t < 0) {
+if (num_cpus >= sizeof(cpu_mask) * 8) {
+cpu_mask = -1;
+} else {
+cpu_mask = (1UL << num_cpus) - 1;
+}
+}
+
+dprintf(fd,
+"cpu\t\t\t: Alpha\n"
+"cpu model\t\t: %s\n"
+"cpu variation\t\t: 0\n"
+"cpu revision\t\t: 0\n"
+"cpu serial number\t: JA\n"
+"system type\t\t: QEMU\n"
+"system variation\t: QEMU_v" QEMU_VERSION "\n"
+"system revision\t\t: 0\n"
+"system serial number\t: AY\n"
+"cycle frequency [Hz]\t: 25000\n"
+"timer frequency [Hz]\t: 250.00\n"
+"page size [bytes]\t: %d\n"
+"phys. address bits\t: %d\n"
+"max. addr. space #\t: 255\n"
+"BogoMIPS\t\t: 2500.00\n"
+"kernel unaligned acc\t: 0 (pc=0,va=0)\n"
+"user unaligned acc\t: 0 (pc=0,va=0)\n"
+"platform string\t\t: AlphaServer QEMU user-mode VM\n"
+"cpus detected\t\t: %d\n"
+"cpus active\t\t: %d\n"
+"cpu active mask\t\t: %016lx\n"
+"L1 Icache\t\t: n/a\n"
+"L1 Dcache\t\t: n/a\n"
+"L2 cache\t\t: n/a\n"
+"L3 cache\t\t: n/a\n",
+model, TARGET_PAGE_SIZE, TARGET_PHYS_ADDR_SPACE_BITS,
+max_cpus, num_cpus, cpu_mask);
+
+return 0;
+}
+#define HAVE_ARCH_PROC_CPUINFO
+
+#endif /* ALPHA_TARGET_PROC_H */
-- 
2.34.1




[PATCH v2] target/arm: Do not use gen_mte_checkN in trans_STGP

2023-09-01 Thread Richard Henderson
STGP writes to tag memory, it does not check it.
This happened to work because we wrote tag memory first
so that the check always succeeded.

Signed-off-by: Richard Henderson 
---
 target/arm/tcg/translate-a64.c | 41 +-
 1 file changed, 15 insertions(+), 26 deletions(-)

diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 0b77c92437..c5de176b8b 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -3020,37 +3020,17 @@ static bool trans_STGP(DisasContext *s, arg_ldstpair *a)
 tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
 }
 
-if (!s->ata) {
-/*
- * TODO: We could rely on the stores below, at least for
- * system mode, if we arrange to add MO_ALIGN_16.
- */
-gen_helper_stg_stub(cpu_env, dirty_addr);
-} else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
-gen_helper_stg_parallel(cpu_env, dirty_addr, dirty_addr);
-} else {
-gen_helper_stg(cpu_env, dirty_addr, dirty_addr);
-}
-
-mop = finalize_memop(s, MO_64);
-clean_addr = gen_mte_checkN(s, dirty_addr, true, false, 2 << MO_64, mop);
-
+clean_addr = clean_data_tbi(s, dirty_addr);
 tcg_rt = cpu_reg(s, a->rt);
 tcg_rt2 = cpu_reg(s, a->rt2);
 
 /*
- * STGP is defined as two 8-byte memory operations and one tag operation.
- * We implement it as one single 16-byte memory operation for convenience.
- * Rebuild mop as for STP.
- * TODO: The atomicity with LSE2 is stronger than required.
- * Need a form of MO_ATOM_WITHIN16_PAIR that never requires
- * 16-byte atomicity.
+ * STGP is defined as two 8-byte memory operations, aligned to TAG_GRANULE,
+ * and one tag operation.  We implement it as one single aligned 16-byte
+ * memory operation for convenience.  Note that the alignment ensures
+ * MO_ATOM_IFALIGN_PAIR produces 8-byte atomicity for the memory store.
  */
-mop = MO_128;
-if (s->align_mem) {
-mop |= MO_ALIGN_8;
-}
-mop = finalize_memop_pair(s, mop);
+mop = finalize_memop_atom(s, MO_128 | MO_ALIGN, MO_ATOM_IFALIGN_PAIR);
 
 tmp = tcg_temp_new_i128();
 if (s->be_data == MO_LE) {
@@ -3060,6 +3040,15 @@ static bool trans_STGP(DisasContext *s, arg_ldstpair *a)
 }
 tcg_gen_qemu_st_i128(tmp, clean_addr, get_mem_index(s), mop);
 
+/* Perform the tag store, if tag access enabled. */
+if (s->ata) {
+if (tb_cflags(s->base.tb) & CF_PARALLEL) {
+gen_helper_stg_parallel(cpu_env, dirty_addr, dirty_addr);
+} else {
+gen_helper_stg(cpu_env, dirty_addr, dirty_addr);
+}
+}
+
 op_addr_ldstpair_post(s, a, dirty_addr, offset);
 return true;
 }
-- 
2.34.1




Re: [PATCH 2/8] os-posix: create and export os_set_runas()

2023-09-01 Thread Richard Henderson

On 9/1/23 03:12, Michael Tokarev wrote:

+/*
+ * Prepare to change user ID. optarg can be one of 3 forms:
+ *   - a username, in which case user ID will be changed to its uid,
+ * with primary and supplementary groups set up too;
+ *   - a nemeric uid, in which case only the uid will be set;


numeric.

Reviewed-by: Richard Henderson 

r~



Re: [PATCH 07/20] target/riscv/cpu.c: add .instance_post_init()

2023-09-01 Thread Daniel Henrique Barboza




On 8/31/23 08:00, Andrew Jones wrote:

On Fri, Aug 25, 2023 at 10:08:40AM -0300, Daniel Henrique Barboza wrote:

All generic CPUs call riscv_cpu_add_user_properties(). The 'max' CPU
calls riscv_init_max_cpu_extensions(). Both can be moved to a common
instance_post_init() callback, implemented in riscv_cpu_post_init(),
called by all CPUs. The call order then becomes:

riscv_cpu_init() -> cpu_init() of each CPU -> .instance_post_init()

A CPU class that wants to add user flags will let us know via the
'user_extension_properties' property. Likewise, 'cfg.max_features' will
determine if any given CPU, regardless of being the 'max' CPU or not,
wants to enable the maximum amount of extensions.

In the near future riscv_cpu_post_init() will call the init() function
of the current accelerator, providing a hook for KVM and TCG accel
classes to change the init() process of the CPU.

Signed-off-by: Daniel Henrique Barboza 
---
  target/riscv/cpu.c | 20 +++-
  1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index c35d58c64b..f67b782675 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -430,8 +430,6 @@ static void riscv_max_cpu_init(Object *obj)
  mlx = MXL_RV32;
  #endif
  set_misa(env, mlx, 0);
-riscv_cpu_add_user_properties(obj);
-riscv_init_max_cpu_extensions(obj);
  env->priv_ver = PRIV_VERSION_LATEST;
  #ifndef CONFIG_USER_ONLY
  set_satp_mode_max_supported(RISCV_CPU(obj), mlx == MXL_RV32 ?
@@ -445,7 +443,6 @@ static void rv64_base_cpu_init(Object *obj)
  CPURISCVState *env = _CPU(obj)->env;
  /* We set this in the realise function */
  set_misa(env, MXL_RV64, 0);
-riscv_cpu_add_user_properties(obj);
  /* Set latest version of privileged specification */
  env->priv_ver = PRIV_VERSION_LATEST;
  #ifndef CONFIG_USER_ONLY
@@ -569,7 +566,6 @@ static void rv128_base_cpu_init(Object *obj)
  CPURISCVState *env = _CPU(obj)->env;
  /* We set this in the realise function */
  set_misa(env, MXL_RV128, 0);
-riscv_cpu_add_user_properties(obj);
  /* Set latest version of privileged specification */
  env->priv_ver = PRIV_VERSION_LATEST;
  #ifndef CONFIG_USER_ONLY
@@ -582,7 +578,6 @@ static void rv32_base_cpu_init(Object *obj)
  CPURISCVState *env = _CPU(obj)->env;
  /* We set this in the realise function */
  set_misa(env, MXL_RV32, 0);
-riscv_cpu_add_user_properties(obj);
  /* Set latest version of privileged specification */
  env->priv_ver = PRIV_VERSION_LATEST;
  #ifndef CONFIG_USER_ONLY
@@ -1212,6 +1207,20 @@ static void riscv_cpu_set_irq(void *opaque, int irq, int 
level)
  }
  #endif /* CONFIG_USER_ONLY */
  
+static void riscv_cpu_post_init(Object *obj)

+{
+RISCVCPU *cpu = RISCV_CPU(obj);
+RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(cpu);
+
+if (rcc->user_extension_properties) {


It's not yet clear to me why we need 'user_extension_properties'. Can't we
just do the 'object_dynamic_cast(obj, TYPE_RISCV_DYNAMIC_CPU) != NULL'
check here?


I'll answer here but this also applies for patches 19 and 20.

The idea in my head was to create a flexible way of defining new CPU types in
the future that doesn't necessarily fits the 3 big molds we have: generic CPUs
(I'm considering 'max' CPU as a generic CPU on steroids), vendor CPUs and the
KVM only 'host' CPU. For example, it would be possible to create a vendor-style
CPU that has all extensions enabled and runs KVM.

This idea is probably better in my head than in reality, and there's a very high
chance that I'm adding extra stuff in the CPU class and we won't add any new
'funky' CPU type in the future to justify it.

I'll drop patches 5 and 6 with 'user_extension_properties' and 'max_features'
flag and do a regular CPU type check in post_init().'tcg_supported' in patch 19
is indeed a bit silly today since every CPU but 'host' will enable it, so we can
do a 'cpu is host' kind of check and live without it. We can still throw generic
errors in all these checks regardless of how we're doing the validation.

Patch 20 has another underlying discussion that I'd rather have there. Thanks,


Daniel








+riscv_cpu_add_user_properties(obj);
+}
+
+if (cpu->cfg.max_features) {


It's also not yet clear why we need max_features. I can't think of any
other models that want max_features besides 'max'. Checking the cpu type
here should be sufficient, no?


+riscv_init_max_cpu_extensions(obj);
+}
+}
+
  static void riscv_cpu_init(Object *obj)
  {
  RISCVCPU *cpu = RISCV_CPU(obj);
@@ -2019,6 +2028,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
  .instance_size = sizeof(RISCVCPU),
  .instance_align = __alignof__(RISCVCPU),
  .instance_init = riscv_cpu_init,
+.instance_post_init = riscv_cpu_post_init,
  .abstract = true,
  .class_size = sizeof(RISCVCPUClass),
  .class_init = riscv_cpu_class_init,
--
2.41.0





[PATCH v9 11/20] avocado, risc-v: add tuxboot tests for 'max' CPU

2023-09-01 Thread Daniel Henrique Barboza
Add smoke tests to ensure that we'll not break the 'max' CPU type when
adding new frozen/ratified RISC-V extensions.

Signed-off-by: Daniel Henrique Barboza 
---
 tests/avocado/tuxrun_baselines.py | 32 +++
 1 file changed, 32 insertions(+)

diff --git a/tests/avocado/tuxrun_baselines.py 
b/tests/avocado/tuxrun_baselines.py
index e12250eabb..c99bea6c0b 100644
--- a/tests/avocado/tuxrun_baselines.py
+++ b/tests/avocado/tuxrun_baselines.py
@@ -501,6 +501,38 @@ def test_riscv64(self):
 
 self.common_tuxrun(csums=sums)
 
+def test_riscv32_maxcpu(self):
+"""
+:avocado: tags=arch:riscv32
+:avocado: tags=machine:virt
+:avocado: tags=cpu:max
+:avocado: tags=tuxboot:riscv32
+"""
+sums = { "Image" :
+ 
"89599407d7334de629a40e7ad6503c73670359eb5f5ae9d686353a3d6deccbd5",
+ "fw_jump.elf" :
+ 
"f2ef28a0b77826f79d085d3e4aa686f1159b315eff9099a37046b18936676985",
+ "rootfs.ext4.zst" :
+ 
"7168d296d0283238ea73cd5a775b3dd608e55e04c7b92b76ecce31bb13108cba" }
+
+self.common_tuxrun(csums=sums)
+
+def test_riscv64_maxcpu(self):
+"""
+:avocado: tags=arch:riscv64
+:avocado: tags=machine:virt
+:avocado: tags=cpu:max
+:avocado: tags=tuxboot:riscv64
+"""
+sums = { "Image" :
+ 
"cd634badc65e52fb63465ec99e309c0de0369f0841b7d9486f9729e119bac25e",
+ "fw_jump.elf" :
+ 
"6e3373abcab4305fe151b564a4c71110d833c21f2c0a1753b7935459e36aedcf",
+ "rootfs.ext4.zst" :
+ 
"b18e3a3bdf27be03da0b285e84cb71bf09eca071c3a087b42884b6982ed679eb" }
+
+self.common_tuxrun(csums=sums)
+
 def test_s390(self):
 """
 :avocado: tags=arch:s390x
-- 
2.41.0




[PATCH v9 12/20] target/riscv: deprecate the 'any' CPU type

2023-09-01 Thread Daniel Henrique Barboza
The 'any' CPU type was introduced in commit dc5bd18fa5725 ("RISC-V CPU
Core Definition"), being around since the beginning. It's not an easy
CPU to use: it's undocumented and its name doesn't tell users much about
what the CPU is supposed to bring. 'git log' doesn't help us either in
knowing what was the original design of this CPU type.

The closest we have is a comment from Alistair [1] where he recalls from
memory that the 'any' CPU is supposed to behave like the newly added
'max' CPU. He also suggested that the 'any' CPU should be removed.

The default CPUs are rv32 and rv64, so removing the 'any' CPU will have
impact only on users that might have a script that uses '-cpu any'.
And those users are better off using the default CPUs or the new 'max'
CPU.

We would love to just remove the code and be done with it, but one does
not simply remove a feature in QEMU. We'll put the CPU in quarantine
first, letting users know that we have the intent of removing it in the
future.

[1] https://lists.gnu.org/archive/html/qemu-devel/2023-07/msg02891.html

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Alistair Francis 
Reviewed-by: Andrew Jones 
---
 docs/about/deprecated.rst | 12 
 target/riscv/cpu.c|  5 +
 2 files changed, 17 insertions(+)

diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index 92a2bafd2b..7277d4e8a4 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -371,6 +371,18 @@ QEMU's ``vhost`` feature, which would eliminate the high 
latency costs under
 which the 9p ``proxy`` backend currently suffers. However as of to date nobody
 has indicated plans for such kind of reimplementation unfortunately.
 
+RISC-V 'any' CPU type ``-cpu any`` (since 8.2)
+^^
+
+The 'any' CPU type was introduced back in 2018 and has been around since the
+initial RISC-V QEMU port. Its usage has always been unclear: users don't know
+what to expect from a CPU called 'any', and in fact the CPU does not do 
anything
+special that isn't already done by the default CPUs rv32/rv64.
+
+After the introduction of the 'max' CPU type, RISC-V now has a good coverage
+of generic CPUs: rv32 and rv64 as default CPUs and 'max' as a feature complete
+CPU for both 32 and 64 bit builds. Users are then discouraged to use the 'any'
+CPU type starting in 8.2.
 
 Block device options
 
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 365c2b3b56..0dae259e02 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1522,6 +1522,11 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
 Error *local_err = NULL;
 
+if (object_dynamic_cast(OBJECT(dev), TYPE_RISCV_CPU_ANY) != NULL) {
+warn_report("The 'any' CPU is deprecated and will be "
+"removed in the future.");
+}
+
 cpu_exec_realizefn(cs, _err);
 if (local_err != NULL) {
 error_propagate(errp, local_err);
-- 
2.41.0




[PATCH v9 01/20] target/riscv/cpu.c: split CPU options from riscv_cpu_extensions[]

2023-09-01 Thread Daniel Henrique Barboza
We'll add a new CPU type that will enable a considerable amount of
extensions. To make it easier for us we'll do a few cleanups in our
existing riscv_cpu_extensions[] array.

Start by splitting all CPU non-boolean options from it. Create a new
riscv_cpu_options[] array for them. Add all these properties in
riscv_cpu_add_user_properties() as it is already being done today.

'mmu' and 'pmp' aren't really extensions in the usual way we think about
RISC-V extensions. These are closer to CPU features/options, so move
both to riscv_cpu_options[] too. In the near future we'll need to match
all extensions with all entries in isa_edata_arr[], and so it happens
that both 'mmu' and 'pmp' do not have a riscv,isa string (thus, no priv
spec version restriction). This further emphasizes the point that these
are more a CPU option than an extension.

No functional changes made.

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Weiwei Li 
Reviewed-by: Alistair Francis 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu.c | 33 +++--
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index f227c7664e..fdbd8eb0b8 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1810,7 +1810,6 @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj)
 
 static Property riscv_cpu_extensions[] = {
 /* Defaults for standard extensions */
-DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16),
 DEFINE_PROP_BOOL("sscofpmf", RISCVCPU, cfg.ext_sscofpmf, false),
 DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
 DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
@@ -1823,15 +1822,8 @@ static Property riscv_cpu_extensions[] = {
 DEFINE_PROP_BOOL("Zve32f", RISCVCPU, cfg.ext_zve32f, false),
 DEFINE_PROP_BOOL("Zve64f", RISCVCPU, cfg.ext_zve64f, false),
 DEFINE_PROP_BOOL("Zve64d", RISCVCPU, cfg.ext_zve64d, false),
-DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
-DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
 DEFINE_PROP_BOOL("sstc", RISCVCPU, cfg.ext_sstc, true),
 
-DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec),
-DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec),
-DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
-DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
-
 DEFINE_PROP_BOOL("smstateen", RISCVCPU, cfg.ext_smstateen, false),
 DEFINE_PROP_BOOL("svadu", RISCVCPU, cfg.ext_svadu, true),
 DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
@@ -1862,9 +1854,7 @@ static Property riscv_cpu_extensions[] = {
 DEFINE_PROP_BOOL("zhinxmin", RISCVCPU, cfg.ext_zhinxmin, false),
 
 DEFINE_PROP_BOOL("zicbom", RISCVCPU, cfg.ext_icbom, true),
-DEFINE_PROP_UINT16("cbom_blocksize", RISCVCPU, cfg.cbom_blocksize, 64),
 DEFINE_PROP_BOOL("zicboz", RISCVCPU, cfg.ext_icboz, true),
-DEFINE_PROP_UINT16("cboz_blocksize", RISCVCPU, cfg.cboz_blocksize, 64),
 
 DEFINE_PROP_BOOL("zmmul", RISCVCPU, cfg.ext_zmmul, false),
 
@@ -1918,6 +1908,21 @@ static Property riscv_cpu_extensions[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static Property riscv_cpu_options[] = {
+DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16),
+
+DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
+DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
+
+DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec),
+DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec),
+
+DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
+DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
+
+DEFINE_PROP_UINT16("cbom_blocksize", RISCVCPU, cfg.cbom_blocksize, 64),
+DEFINE_PROP_UINT16("cboz_blocksize", RISCVCPU, cfg.cboz_blocksize, 64),
+};
 
 #ifndef CONFIG_USER_ONLY
 static void cpu_set_cfg_unavailable(Object *obj, Visitor *v,
@@ -1986,6 +1991,14 @@ static void riscv_cpu_add_user_properties(Object *obj)
 #endif
 qdev_property_add_static(dev, prop);
 }
+
+for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) {
+/* Check if KVM created the property already */
+if (object_property_find(obj, riscv_cpu_options[i].name)) {
+continue;
+}
+qdev_property_add_static(dev, _cpu_options[i]);
+}
 }
 
 static Property riscv_cpu_properties[] = {
-- 
2.41.0




[PATCH v9 16/20] target/riscv/cpu.c: use cpu_cfg_ext_auto_update() during realize()

2023-09-01 Thread Daniel Henrique Barboza
Let's change the other instances in realize() where we're enabling an
extension based on a certain criteria (e.g. it's a dependency of another
extension).

We're leaving icsr and ifencei being enabled during RVG for later -
we'll want to error out in that case. Every other extension enablement
during realize is now done via cpu_cfg_ext_auto_update().

The end goal is that only cpu init() functions will handle extension
flags directly via "cpu->cfg.ext_N = true|false".

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Alistair Francis 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu.c | 50 +++---
 1 file changed, 25 insertions(+), 25 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index a4876df5f4..eeaf69599e 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1193,7 +1193,7 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, 
Error **errp)
 }
 
 if (cpu->cfg.ext_zfh) {
-cpu->cfg.ext_zfhmin = true;
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zfhmin), true);
 }
 
 if (cpu->cfg.ext_zfhmin && !riscv_has_ext(env, RVF)) {
@@ -1219,17 +1219,17 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, 
Error **errp)
 }
 
 /* The V vector extension depends on the Zve64d extension */
-cpu->cfg.ext_zve64d = true;
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64d), true);
 }
 
 /* The Zve64d extension depends on the Zve64f extension */
 if (cpu->cfg.ext_zve64d) {
-cpu->cfg.ext_zve64f = true;
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64f), true);
 }
 
 /* The Zve64f extension depends on the Zve32f extension */
 if (cpu->cfg.ext_zve64f) {
-cpu->cfg.ext_zve32f = true;
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32f), true);
 }
 
 if (cpu->cfg.ext_zve64d && !riscv_has_ext(env, RVD)) {
@@ -1243,7 +1243,7 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, 
Error **errp)
 }
 
 if (cpu->cfg.ext_zvfh) {
-cpu->cfg.ext_zvfhmin = true;
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvfhmin), true);
 }
 
 if (cpu->cfg.ext_zvfhmin && !cpu->cfg.ext_zve32f) {
@@ -1273,7 +1273,7 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, 
Error **errp)
 
 /* Set the ISA extensions, checks should have happened above */
 if (cpu->cfg.ext_zhinx) {
-cpu->cfg.ext_zhinxmin = true;
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
 }
 
 if ((cpu->cfg.ext_zdinx || cpu->cfg.ext_zhinxmin) && !cpu->cfg.ext_zfinx) {
@@ -1294,12 +1294,12 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, 
Error **errp)
 }
 
 if (cpu->cfg.ext_zce) {
-cpu->cfg.ext_zca = true;
-cpu->cfg.ext_zcb = true;
-cpu->cfg.ext_zcmp = true;
-cpu->cfg.ext_zcmt = true;
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcb), true);
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcmp), true);
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcmt), true);
 if (riscv_has_ext(env, RVF) && env->misa_mxl_max == MXL_RV32) {
-cpu->cfg.ext_zcf = true;
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcf), true);
 }
 }
 
@@ -1367,26 +1367,26 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, 
Error **errp)
 }
 
 if (cpu->cfg.ext_zk) {
-cpu->cfg.ext_zkn = true;
-cpu->cfg.ext_zkr = true;
-cpu->cfg.ext_zkt = true;
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkn), true);
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkr), true);
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkt), true);
 }
 
 if (cpu->cfg.ext_zkn) {
-cpu->cfg.ext_zbkb = true;
-cpu->cfg.ext_zbkc = true;
-cpu->cfg.ext_zbkx = true;
-cpu->cfg.ext_zkne = true;
-cpu->cfg.ext_zknd = true;
-cpu->cfg.ext_zknh = true;
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkb), true);
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkc), true);
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkx), true);
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkne), true);
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zknd), true);
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zknh), true);
 }
 
 if (cpu->cfg.ext_zks) {
-cpu->cfg.ext_zbkb = true;
-cpu->cfg.ext_zbkc = true;
-cpu->cfg.ext_zbkx = true;
-cpu->cfg.ext_zksed = true;
-cpu->cfg.ext_zksh = true;
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkb), true);
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkc), true);
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkx), true);
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zksed), 

[PATCH v9 17/20] target/riscv/cpu.c: introduce RISCVCPUMultiExtConfig

2023-09-01 Thread Daniel Henrique Barboza
If we want to make better decisions when auto-enabling extensions during
realize() we need a way to tell if an user set an extension manually.
The RISC-V KVM driver has its own solution via a KVMCPUConfig struct
that has an 'user_set' flag that is set during the Property set()
callback. The set() callback also does init() time validations based on
the current KVM driver capabilities.

For TCG we would want a 'user_set' mechanic too, but we would look
ad-hoc via cpu_cfg_ext_auto_update() if a certain extension was user set
or not. If we copy what was made in the KVM side we would look for
'user_set' for one into 60+ extension structs spreaded in 3 arrays
(riscv_cpu_extensions, riscv_cpu_experimental_exts,
riscv_cpu_vendor_exts).

We'll still need an extension struct but we won't be using the
'user_set' flag:

- 'RISCVCPUMultiExtConfig' will be our specialized structure, similar to what
we're already doing with the MISA extensions in 'RISCVCPUMisaExtConfig'.
DEFINE_PROP_BOOL() for all 3 extensions arrays were replaced by
MULTI_EXT_CFG_BOOL(), a macro that will init our specialized struct;

- the 'multi_ext_user_opts' hash will be used to store the offset of each
extension that the user set via the set() callback, cpu_set_multi_ext_cfg().
For now we're just initializing and populating it - next patch will use
it to determine if a certain extension was user set;

- cpu_add_multi_ext_prop() is a new helper that will replace the
qdev_property_add_static() calls that our macros are doing to populate
user properties. The macro was renamed to ADD_CPU_MULTIEXT_PROPS_ARRAY()
for clarity. Note that the non-extension properties in
riscv_cpu_options[] still need to be declared via qdev().

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Alistair Francis 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu.c | 258 -
 1 file changed, 159 insertions(+), 99 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index eeaf69599e..1ca034e6da 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -162,6 +162,9 @@ static const struct isa_ext_data isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(xventanacondops, PRIV_VERSION_1_12_0, 
ext_XVentanaCondOps),
 };
 
+/* Hash that stores user set extensions */
+static GHashTable *multi_ext_user_opts;
+
 static bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset)
 {
 bool *ext_enabled = (void *)>cfg + ext_offset;
@@ -1718,6 +1721,8 @@ static void riscv_cpu_init(Object *obj)
 qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq,
   IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX);
 #endif /* CONFIG_USER_ONLY */
+
+multi_ext_user_opts = g_hash_table_new(NULL, g_direct_equal);
 }
 
 typedef struct RISCVCPUMisaExtConfig {
@@ -1869,108 +1874,118 @@ static void riscv_cpu_add_misa_properties(Object 
*cpu_obj)
 }
 }
 
-static Property riscv_cpu_extensions[] = {
+typedef struct RISCVCPUMultiExtConfig {
+const char *name;
+uint32_t offset;
+bool enabled;
+} RISCVCPUMultiExtConfig;
+
+#define MULTI_EXT_CFG_BOOL(_name, _prop, _defval) \
+{.name = _name, .offset = CPU_CFG_OFFSET(_prop), \
+ .enabled = _defval}
+
+static RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 /* Defaults for standard extensions */
-DEFINE_PROP_BOOL("sscofpmf", RISCVCPU, cfg.ext_sscofpmf, false),
-DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
-DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
-DEFINE_PROP_BOOL("Zihintntl", RISCVCPU, cfg.ext_zihintntl, true),
-DEFINE_PROP_BOOL("Zihintpause", RISCVCPU, cfg.ext_zihintpause, true),
-DEFINE_PROP_BOOL("Zawrs", RISCVCPU, cfg.ext_zawrs, true),
-DEFINE_PROP_BOOL("Zfa", RISCVCPU, cfg.ext_zfa, true),
-DEFINE_PROP_BOOL("Zfh", RISCVCPU, cfg.ext_zfh, false),
-DEFINE_PROP_BOOL("Zfhmin", RISCVCPU, cfg.ext_zfhmin, false),
-DEFINE_PROP_BOOL("Zve32f", RISCVCPU, cfg.ext_zve32f, false),
-DEFINE_PROP_BOOL("Zve64f", RISCVCPU, cfg.ext_zve64f, false),
-DEFINE_PROP_BOOL("Zve64d", RISCVCPU, cfg.ext_zve64d, false),
-DEFINE_PROP_BOOL("sstc", RISCVCPU, cfg.ext_sstc, true),
-
-DEFINE_PROP_BOOL("smstateen", RISCVCPU, cfg.ext_smstateen, false),
-DEFINE_PROP_BOOL("svadu", RISCVCPU, cfg.ext_svadu, true),
-DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
-DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
-DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
-
-DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true),
-DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true),
-DEFINE_PROP_BOOL("zbc", RISCVCPU, cfg.ext_zbc, true),
-DEFINE_PROP_BOOL("zbkb", RISCVCPU, cfg.ext_zbkb, false),
-DEFINE_PROP_BOOL("zbkc", RISCVCPU, cfg.ext_zbkc, false),
-DEFINE_PROP_BOOL("zbkx", RISCVCPU, cfg.ext_zbkx, false),
-DEFINE_PROP_BOOL("zbs", RISCVCPU, cfg.ext_zbs, true),
-DEFINE_PROP_BOOL("zk", RISCVCPU, cfg.ext_zk, false),
-DEFINE_PROP_BOOL("zkn", RISCVCPU, 

[PATCH v9 18/20] target/riscv: use isa_ext_update_enabled() in init_max_cpu_extensions()

2023-09-01 Thread Daniel Henrique Barboza
Before adding support to detect if an extension was user set we need to
handle how we're enabling extensions in riscv_init_max_cpu_extensions().
object_property_set_bool() calls the set() callback for the property,
and we're going to use this callback to set the 'multi_ext_user_opts'
hash.

This means that, as is today, all extensions we're setting for the 'max'
CPU will be seen as user set in the future. Let's change set_bool() to
isa_ext_update_enabled() that will just enable/disable the flag on a
certain offset.

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Alistair Francis 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1ca034e6da..617b861258 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -2172,24 +2172,24 @@ static void riscv_init_max_cpu_extensions(Object *obj)
 set_misa(env, env->misa_mxl, env->misa_ext | RVG | RVJ | RVV);
 
 for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
-object_property_set_bool(obj, prop->name, true, NULL);
+isa_ext_update_enabled(cpu, prop->offset, true);
 }
 
 /* set vector version */
 env->vext_ver = VEXT_VERSION_1_00_0;
 
 /* Zfinx is not compatible with F. Disable it */
-object_property_set_bool(obj, "zfinx", false, NULL);
-object_property_set_bool(obj, "zdinx", false, NULL);
-object_property_set_bool(obj, "zhinx", false, NULL);
-object_property_set_bool(obj, "zhinxmin", false, NULL);
+isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zfinx), false);
+isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zdinx), false);
+isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zhinx), false);
+isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zhinxmin), false);
 
-object_property_set_bool(obj, "zce", false, NULL);
-object_property_set_bool(obj, "zcmp", false, NULL);
-object_property_set_bool(obj, "zcmt", false, NULL);
+isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zce), false);
+isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcmp), false);
+isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcmt), false);
 
 if (env->misa_mxl != MXL_RV32) {
-object_property_set_bool(obj, "zcf", false, NULL);
+isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcf), false);
 }
 }
 
-- 
2.41.0




[PATCH v9 19/20] target/riscv/cpu.c: honor user choice in cpu_cfg_ext_auto_update()

2023-09-01 Thread Daniel Henrique Barboza
Add a new cpu_cfg_ext_is_user_set() helper to check if an extension was
set by the user in the command line. Use it inside
cpu_cfg_ext_auto_update() to verify if the user set a certain extension
and, if that's the case, do not change its value.

This will make us honor user choice instead of overwriting the values.
Users will then be informed whether they're using an incompatible set of
extensions instead of QEMU setting a magic value that works.

The reason why we're not implementing user choice for MISA extensions
right now is because, today, we do not silently change any MISA bit
during realize() time (we do warn when enabling bits if RVG is enabled).
We do that - a lot - with multi-letter extensions though, so we're
handling the most immediate concern first.

After this patch, we'll now error out if the user explicitly set 'zce' to true
and 'zca' to false:

$ ./build/qemu-system-riscv64 -M virt -cpu rv64,zce=true,zca=false -nographic
qemu-system-riscv64: Zcf/Zcd/Zcb/Zcmp/Zcmt extensions require Zca extension

This didn't happen before because we were enabling 'zca' if 'zce' was enabled
regardless if the user set 'zca' to false.

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Alistair Francis 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 617b861258..78382cb5f2 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -195,6 +195,12 @@ static int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
 g_assert_not_reached();
 }
 
+static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset)
+{
+return g_hash_table_contains(multi_ext_user_opts,
+ GUINT_TO_POINTER(ext_offset));
+}
+
 static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset,
 bool value)
 {
@@ -206,6 +212,10 @@ static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, 
uint32_t ext_offset,
 return;
 }
 
+if (cpu_cfg_ext_is_user_set(ext_offset)) {
+return;
+}
+
 if (value && env->priv_ver != PRIV_VERSION_LATEST) {
 /* Do not enable it if priv_ver is older than min_version */
 min_version = cpu_cfg_ext_get_min_version(ext_offset);
@@ -1847,6 +1857,12 @@ static RISCVCPUMisaExtConfig misa_ext_cfgs[] = {
 MISA_CFG(RVG, false),
 };
 
+/*
+ * We do not support user choice tracking for MISA
+ * extensions yet because, so far, we do not silently
+ * change MISA bits during realize() (RVG enables MISA
+ * bits but the user is warned about it).
+ */
 static void riscv_cpu_add_misa_properties(Object *cpu_obj)
 {
 int i;
-- 
2.41.0




[PATCH v9 09/20] target/riscv/cpu.c: limit cfg->vext_spec log message

2023-09-01 Thread Daniel Henrique Barboza
Inside riscv_cpu_validate_v() we're always throwing a log message if the
user didn't set a vector version via 'vext_spec'.

We're going to include one case with the 'max' CPU where env->vext_ver
will be set in the cpu_init(). But that alone will not stop the "vector
version is not specified" message from appearing. The usefulness of this
log message is debatable for the generic CPUs, but for a 'max' CPU type,
where we are supposed to deliver a CPU model with all features possible,
it's strange to force users to set 'vext_spec' to get rid of this
message.

Change riscv_cpu_validate_v() to not throw this log message if
env->vext_ver is already set.

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Alistair Francis 
Reviewed-by: Weiwei Li 
---
 target/riscv/cpu.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 8cd19a9b9c..3ba92c806b 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -959,8 +959,6 @@ static void riscv_cpu_disas_set_info(CPUState *s, 
disassemble_info *info)
 static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg,
  Error **errp)
 {
-int vext_version = VEXT_VERSION_1_00_0;
-
 if (!is_power_of_2(cfg->vlen)) {
 error_setg(errp, "Vector extension VLEN must be power of 2");
 return;
@@ -983,17 +981,18 @@ static void riscv_cpu_validate_v(CPURISCVState *env, 
RISCVCPUConfig *cfg,
 }
 if (cfg->vext_spec) {
 if (!g_strcmp0(cfg->vext_spec, "v1.0")) {
-vext_version = VEXT_VERSION_1_00_0;
+env->vext_ver = VEXT_VERSION_1_00_0;
 } else {
 error_setg(errp, "Unsupported vector spec version '%s'",
cfg->vext_spec);
 return;
 }
-} else {
+} else if (env->vext_ver == 0) {
 qemu_log("vector version is not specified, "
  "use the default value v1.0\n");
+
+env->vext_ver = VEXT_VERSION_1_00_0;
 }
-env->vext_ver = vext_version;
 }
 
 static void riscv_cpu_validate_priv_spec(RISCVCPU *cpu, Error **errp)
-- 
2.41.0




[PATCH v9 04/20] target/riscv: add DEFINE_PROP_END_OF_LIST() to riscv_cpu_options[]

2023-09-01 Thread Daniel Henrique Barboza
Add DEFINE_PROP_END_OF_LIST() and eliminate the ARRAY_SIZE() usage when
iterating in the riscv_cpu_options[] array, making it similar to what
we already do when working with riscv_cpu_extensions[].

We also have a more sophisticated motivation behind this change. In the
future we might need to export riscv_cpu_options[] to other files, and
ARRAY_LIST() doesn't work properly in that case because the array size
isn't exposed to the header file. Here's a future sight of what we would
deal with:

./target/riscv/kvm.c:1057:5: error: nested extern declaration of 
'riscv_cpu_add_misa_properties' [-Werror=nested-externs]
n file included from ../target/riscv/kvm.c:19:
home/danielhb/work/qemu/include/qemu/osdep.h:473:31: error: invalid application 
of 'sizeof' to incomplete type 'const RISCVCPUMultiExtConfig[]'
 473 | #define ARRAY_SIZE(x) ((sizeof(x) / sizeof((x)[0])) + \
 |   ^
./target/riscv/kvm.c:1047:29: note: in expansion of macro 'ARRAY_SIZE'
1047 | for (int i = 0; i < ARRAY_SIZE(_array); i++) { \
 | ^~
./target/riscv/kvm.c:1059:5: note: in expansion of macro 
'ADD_UNAVAIL_KVM_PROP_ARRAY'
1059 | ADD_UNAVAIL_KVM_PROP_ARRAY(obj, riscv_cpu_extensions);
 | ^~
home/danielhb/work/qemu/include/qemu/osdep.h:473:31: error: invalid application 
of 'sizeof' to incomplete type 'const RISCVCPUMultiExtConfig[]'
 473 | #define ARRAY_SIZE(x) ((sizeof(x) / sizeof((x)[0])) + \
 |   ^
./target/riscv/kvm.c:1047:29: note: in expansion of macro 'ARRAY_SIZE'
1047 | for (int i = 0; i < ARRAY_SIZE(_array); i++) { \

Homogenize the present and change the future by using
DEFINE_PROP_END_OF_LIST() in riscv_cpu_options[].

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 8e6d316500..8662414906 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1922,6 +1922,8 @@ static Property riscv_cpu_options[] = {
 
 DEFINE_PROP_UINT16("cbom_blocksize", RISCVCPU, cfg.cbom_blocksize, 64),
 DEFINE_PROP_UINT16("cboz_blocksize", RISCVCPU, cfg.cboz_blocksize, 64),
+
+DEFINE_PROP_END_OF_LIST(),
 };
 
 #ifndef CONFIG_USER_ONLY
@@ -1973,12 +1975,12 @@ static void riscv_cpu_add_kvm_properties(Object *obj)
 riscv_cpu_add_kvm_unavail_prop(obj, prop->name);
 }
 
-for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) {
+for (prop = riscv_cpu_options; prop && prop->name; prop++) {
 /* Check if KVM created the property already */
-if (object_property_find(obj, riscv_cpu_options[i].name)) {
+if (object_property_find(obj, prop->name)) {
 continue;
 }
-qdev_property_add_static(dev, _cpu_options[i]);
+qdev_property_add_static(dev, prop);
 }
 }
 #endif
@@ -2009,8 +2011,8 @@ static void riscv_cpu_add_user_properties(Object *obj)
 qdev_property_add_static(dev, prop);
 }
 
-for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) {
-qdev_property_add_static(dev, _cpu_options[i]);
+for (prop = riscv_cpu_options; prop && prop->name; prop++) {
+qdev_property_add_static(dev, prop);
 }
 }
 
-- 
2.41.0




[PATCH v9 10/20] target/riscv: add 'max' CPU type

2023-09-01 Thread Daniel Henrique Barboza
The 'max' CPU type is used by tooling to determine what's the most
capable CPU a current QEMU version implements. Other archs such as ARM
implements this type. Let's add it to RISC-V.

What we consider "most capable CPU" in this context are related to
ratified, non-vendor extensions. This means that we want the 'max' CPU
to enable all (possible) ratified extensions by default. The reasoning
behind this design is (1) vendor extensions can conflict with each other
and we won't play favorities deciding which one is default or not and
(2) non-ratified extensions are always prone to changes, not being
stable enough to be enabled by default.

All this said, we're still not able to enable all ratified extensions
due to conflicts between them. Zfinx and all its dependencies aren't
enabled because of a conflict with RVF. zce, zcmp and zcmt are also
disabled due to RVD conflicts. When running with 64 bits we're also
disabling zcf.

MISA bits RVG, RVJ and RVV are also being set manually since they're
default disabled.

This is the resulting 'riscv,isa' DT for this new CPU:

rv64imafdcvh_zicbom_zicboz_zicsr_zifencei_zihintpause_zawrs_zfa_
zfh_zfhmin_zca_zcb_zcd_zba_zbb_zbc_zbkb_zbkc_zbkx_zbs_zk_zkn_zknd_
zkne_zknh_zkr_zks_zksed_zksh_zkt_zve32f_zve64f_zve64d_
smstateen_sscofpmf_sstc_svadu_svinval_svnapot_svpbmt

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Weiwei Li 
Reviewed-by: Alistair Francis 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu-qom.h |  1 +
 target/riscv/cpu.c | 56 ++
 2 files changed, 57 insertions(+)

diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h
index 04af50983e..f3fbe37a2c 100644
--- a/target/riscv/cpu-qom.h
+++ b/target/riscv/cpu-qom.h
@@ -30,6 +30,7 @@
 #define CPU_RESOLVING_TYPE TYPE_RISCV_CPU
 
 #define TYPE_RISCV_CPU_ANY  RISCV_CPU_TYPE_NAME("any")
+#define TYPE_RISCV_CPU_MAX  RISCV_CPU_TYPE_NAME("max")
 #define TYPE_RISCV_CPU_BASE32   RISCV_CPU_TYPE_NAME("rv32")
 #define TYPE_RISCV_CPU_BASE64   RISCV_CPU_TYPE_NAME("rv64")
 #define TYPE_RISCV_CPU_BASE128  RISCV_CPU_TYPE_NAME("x-rv128")
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 3ba92c806b..365c2b3b56 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -259,6 +259,7 @@ static const char * const riscv_intr_names[] = {
 };
 
 static void riscv_cpu_add_user_properties(Object *obj);
+static void riscv_init_max_cpu_extensions(Object *obj);
 
 const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
 {
@@ -396,6 +397,25 @@ static void riscv_any_cpu_init(Object *obj)
 cpu->cfg.pmp = true;
 }
 
+static void riscv_max_cpu_init(Object *obj)
+{
+RISCVCPU *cpu = RISCV_CPU(obj);
+CPURISCVState *env = >env;
+RISCVMXL mlx = MXL_RV64;
+
+#ifdef TARGET_RISCV32
+mlx = MXL_RV32;
+#endif
+set_misa(env, mlx, 0);
+riscv_cpu_add_user_properties(obj);
+riscv_init_max_cpu_extensions(obj);
+env->priv_ver = PRIV_VERSION_LATEST;
+#ifndef CONFIG_USER_ONLY
+set_satp_mode_max_supported(RISCV_CPU(obj), mlx == MXL_RV32 ?
+VM_1_10_SV32 : VM_1_10_SV57);
+#endif
+}
+
 #if defined(TARGET_RISCV64)
 static void rv64_base_cpu_init(Object *obj)
 {
@@ -2036,6 +2056,41 @@ static void riscv_cpu_add_user_properties(Object *obj)
 riscv_cpu_add_qdev_prop_array(dev, riscv_cpu_experimental_exts);
 }
 
+/*
+ * The 'max' type CPU will have all possible ratified
+ * non-vendor extensions enabled.
+ */
+static void riscv_init_max_cpu_extensions(Object *obj)
+{
+RISCVCPU *cpu = RISCV_CPU(obj);
+CPURISCVState *env = >env;
+Property *prop;
+
+/* Enable RVG, RVJ and RVV that are disabled by default */
+set_misa(env, env->misa_mxl, env->misa_ext | RVG | RVJ | RVV);
+
+for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
+object_property_set_bool(obj, prop->name, true, NULL);
+}
+
+/* set vector version */
+env->vext_ver = VEXT_VERSION_1_00_0;
+
+/* Zfinx is not compatible with F. Disable it */
+object_property_set_bool(obj, "zfinx", false, NULL);
+object_property_set_bool(obj, "zdinx", false, NULL);
+object_property_set_bool(obj, "zhinx", false, NULL);
+object_property_set_bool(obj, "zhinxmin", false, NULL);
+
+object_property_set_bool(obj, "zce", false, NULL);
+object_property_set_bool(obj, "zcmp", false, NULL);
+object_property_set_bool(obj, "zcmt", false, NULL);
+
+if (env->misa_mxl != MXL_RV32) {
+object_property_set_bool(obj, "zcf", false, NULL);
+}
+}
+
 static Property riscv_cpu_properties[] = {
 DEFINE_PROP_BOOL("debug", RISCVCPU, cfg.debug, true),
 
@@ -2374,6 +2429,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 .abstract = true,
 },
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,  riscv_any_cpu_init),
+DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,  riscv_max_cpu_init),
 #if defined(CONFIG_KVM)
 DEFINE_CPU(TYPE_RISCV_CPU_HOST, 

[PATCH v9 15/20] target/riscv/cpu.c: introduce cpu_cfg_ext_auto_update()

2023-09-01 Thread Daniel Henrique Barboza
During realize() time we're activating a lot of extensions based on some
criteria, e.g.:

if (cpu->cfg.ext_zk) {
cpu->cfg.ext_zkn = true;
cpu->cfg.ext_zkr = true;
cpu->cfg.ext_zkt = true;
}

This practice resulted in at least one case where we ended up enabling
something we shouldn't: RVC enabling zca/zcd/zcf when using a CPU that
has priv_spec older than 1.12.0.

We're also not considering user choice. There's no way of doing it now
but this is about to change in the next few patches.

cpu_cfg_ext_auto_update() will check for priv version mismatches before
enabling extensions. If we have a mismatch between the current priv
version and the extension we want to enable, do not enable it. In the
near future, this same function will also consider user choice when
deciding if we're going to enable/disable an extension or not.

For now let's use it to handle zca/zcd/zcf enablement if RVC is enabled.

Signed-off-by: Daniel Henrique Barboza 
---
 target/riscv/cpu.c | 43 ---
 1 file changed, 40 insertions(+), 3 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 43c68e1792..a4876df5f4 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -177,6 +177,43 @@ static void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t 
ext_offset,
 *ext_enabled = en;
 }
 
+static int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
+{
+int i;
+
+for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
+if (isa_edata_arr[i].ext_enable_offset != ext_offset) {
+continue;
+}
+
+return isa_edata_arr[i].min_version;
+}
+
+g_assert_not_reached();
+}
+
+static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset,
+bool value)
+{
+CPURISCVState *env = >env;
+bool prev_val = isa_ext_is_enabled(cpu, ext_offset);
+int min_version;
+
+if (prev_val == value) {
+return;
+}
+
+if (value && env->priv_ver != PRIV_VERSION_LATEST) {
+/* Do not enable it if priv_ver is older than min_version */
+min_version = cpu_cfg_ext_get_min_version(ext_offset);
+if (env->priv_ver < min_version) {
+return;
+}
+}
+
+isa_ext_update_enabled(cpu, ext_offset, value);
+}
+
 const char * const riscv_int_regnames[] = {
 "x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
 "x7/t2",   "x8/s0",  "x9/s1",  "x10/a0", "x11/a1", "x12/a2",  "x13/a3",
@@ -1268,12 +1305,12 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, 
Error **errp)
 
 /* zca, zcd and zcf has a PRIV 1.12.0 restriction */
 if (riscv_has_ext(env, RVC) && env->priv_ver >= PRIV_VERSION_1_12_0) {
-cpu->cfg.ext_zca = true;
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
 if (riscv_has_ext(env, RVF) && env->misa_mxl_max == MXL_RV32) {
-cpu->cfg.ext_zcf = true;
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcf), true);
 }
 if (riscv_has_ext(env, RVD)) {
-cpu->cfg.ext_zcd = true;
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcd), true);
 }
 }
 
-- 
2.41.0




[PATCH v9 13/20] target/riscv/cpu.c: use offset in isa_ext_is_enabled/update_enabled

2023-09-01 Thread Daniel Henrique Barboza
We'll have future usage for a function where, given an offset of the
struct RISCVCPUConfig, the flag is updated to a certain val.

Change all existing callers to use edata->ext_enable_offset instead of
'edata'.

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Alistair Francis 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 0dae259e02..03e936348a 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -162,18 +162,17 @@ static const struct isa_ext_data isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(xventanacondops, PRIV_VERSION_1_12_0, 
ext_XVentanaCondOps),
 };
 
-static bool isa_ext_is_enabled(RISCVCPU *cpu,
-   const struct isa_ext_data *edata)
+static bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset)
 {
-bool *ext_enabled = (void *)>cfg + edata->ext_enable_offset;
+bool *ext_enabled = (void *)>cfg + ext_offset;
 
 return *ext_enabled;
 }
 
-static void isa_ext_update_enabled(RISCVCPU *cpu,
-   const struct isa_ext_data *edata, bool en)
+static void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset,
+   bool en)
 {
-bool *ext_enabled = (void *)>cfg + edata->ext_enable_offset;
+bool *ext_enabled = (void *)>cfg + ext_offset;
 
 *ext_enabled = en;
 }
@@ -1045,9 +1044,10 @@ static void 
riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
 
 /* Force disable extensions if priv spec version does not match */
 for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
-if (isa_ext_is_enabled(cpu, _edata_arr[i]) &&
+if (isa_ext_is_enabled(cpu, isa_edata_arr[i].ext_enable_offset) &&
 (env->priv_ver < isa_edata_arr[i].min_version)) {
-isa_ext_update_enabled(cpu, _edata_arr[i], false);
+isa_ext_update_enabled(cpu, isa_edata_arr[i].ext_enable_offset,
+   false);
 #ifndef CONFIG_USER_ONLY
 warn_report("disabling %s extension for hart 0x" TARGET_FMT_lx
 " because privilege spec version does not match",
@@ -2346,7 +2346,7 @@ static void riscv_isa_string_ext(RISCVCPU *cpu, char 
**isa_str,
 int i;
 
 for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
-if (isa_ext_is_enabled(cpu, _edata_arr[i])) {
+if (isa_ext_is_enabled(cpu, isa_edata_arr[i].ext_enable_offset)) {
 new = g_strconcat(old, "_", isa_edata_arr[i].name, NULL);
 g_free(old);
 old = new;
-- 
2.41.0




[PATCH v9 05/20] target/riscv/cpu.c: split non-ratified exts from riscv_cpu_extensions[]

2023-09-01 Thread Daniel Henrique Barboza
Create a new riscv_cpu_experimental_exts[] to store the non-ratified
extensions properties. Once they are ratified we'll move them back to
riscv_cpu_extensions[].

riscv_cpu_add_user_properties() and riscv_cpu_add_kvm_properties() are
changed to keep adding non-ratified properties to users.

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Alistair Francis 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu.c | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 8662414906..2349f813e4 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1881,8 +1881,11 @@ static Property riscv_cpu_extensions[] = {
 DEFINE_PROP_BOOL("xtheadsync", RISCVCPU, cfg.ext_xtheadsync, false),
 DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps, 
false),
 
-/* These are experimental so mark with 'x-' */
+DEFINE_PROP_END_OF_LIST(),
+};
 
+/* These are experimental so mark with 'x-' */
+static Property riscv_cpu_experimental_exts[] = {
 /* ePMP 0.9.3 */
 DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
 DEFINE_PROP_BOOL("x-smaia", RISCVCPU, cfg.ext_smaia, false),
@@ -1975,6 +1978,10 @@ static void riscv_cpu_add_kvm_properties(Object *obj)
 riscv_cpu_add_kvm_unavail_prop(obj, prop->name);
 }
 
+for (prop = riscv_cpu_experimental_exts; prop && prop->name; prop++) {
+riscv_cpu_add_kvm_unavail_prop(obj, prop->name);
+}
+
 for (prop = riscv_cpu_options; prop && prop->name; prop++) {
 /* Check if KVM created the property already */
 if (object_property_find(obj, prop->name)) {
@@ -2014,6 +2021,10 @@ static void riscv_cpu_add_user_properties(Object *obj)
 for (prop = riscv_cpu_options; prop && prop->name; prop++) {
 qdev_property_add_static(dev, prop);
 }
+
+for (prop = riscv_cpu_experimental_exts; prop && prop->name; prop++) {
+qdev_property_add_static(dev, prop);
+}
 }
 
 static Property riscv_cpu_properties[] = {
-- 
2.41.0




[PATCH v9 07/20] target/riscv/cpu.c: add riscv_cpu_add_qdev_prop_array()

2023-09-01 Thread Daniel Henrique Barboza
The code inside riscv_cpu_add_user_properties() became quite repetitive
after recent changes. Add a helper to hide the repetition away.

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu.c | 29 +
 1 file changed, 13 insertions(+), 16 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 86d536f242..d484d63bcd 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1951,6 +1951,15 @@ static void cpu_set_cfg_unavailable(Object *obj, Visitor 
*v,
 }
 #endif
 
+static void riscv_cpu_add_qdev_prop_array(DeviceState *dev, Property *array)
+{
+g_assert(array);
+
+for (Property *prop = array; prop && prop->name; prop++) {
+qdev_property_add_static(dev, prop);
+}
+}
+
 #ifndef CONFIG_USER_ONLY
 static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name)
 {
@@ -2007,7 +2016,6 @@ static void riscv_cpu_add_kvm_properties(Object *obj)
  */
 static void riscv_cpu_add_user_properties(Object *obj)
 {
-Property *prop;
 DeviceState *dev = DEVICE(obj);
 
 #ifndef CONFIG_USER_ONLY
@@ -2021,21 +2029,10 @@ static void riscv_cpu_add_user_properties(Object *obj)
 
 riscv_cpu_add_misa_properties(obj);
 
-for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
-qdev_property_add_static(dev, prop);
-}
-
-for (prop = riscv_cpu_options; prop && prop->name; prop++) {
-qdev_property_add_static(dev, prop);
-}
-
-for (prop = riscv_cpu_vendor_exts; prop && prop->name; prop++) {
-qdev_property_add_static(dev, prop);
-}
-
-for (prop = riscv_cpu_experimental_exts; prop && prop->name; prop++) {
-qdev_property_add_static(dev, prop);
-}
+riscv_cpu_add_qdev_prop_array(dev, riscv_cpu_extensions);
+riscv_cpu_add_qdev_prop_array(dev, riscv_cpu_options);
+riscv_cpu_add_qdev_prop_array(dev, riscv_cpu_vendor_exts);
+riscv_cpu_add_qdev_prop_array(dev, riscv_cpu_experimental_exts);
 }
 
 static Property riscv_cpu_properties[] = {
-- 
2.41.0




[PATCH v9 20/20] target/riscv/cpu.c: consider user option with RVG

2023-09-01 Thread Daniel Henrique Barboza
Enabling RVG will enable a set of extensions that we're not checking if
the user was okay enabling or not. And in this case we want to error
out, instead of ignoring, otherwise we will be inconsistent enabling RVG
without all its extensions.

After this patch, disabling ifencei or icsr while enabling RVG will
result in error:

$ ./build/qemu-system-riscv64 -M virt -cpu rv64,g=true,Zifencei=false 
--nographic
qemu-system-riscv64: RVG requires Zifencei but user set Zifencei to false

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.c | 18 --
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 78382cb5f2..be1c028095 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1153,9 +1153,23 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, 
Error **errp)
   riscv_has_ext(env, RVA) && riscv_has_ext(env, RVF) &&
   riscv_has_ext(env, RVD) &&
   cpu->cfg.ext_icsr && cpu->cfg.ext_ifencei)) {
+
+if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_icsr)) &&
+!cpu->cfg.ext_icsr) {
+error_setg(errp, "RVG requires Zicsr but user set Zicsr to false");
+return;
+}
+
+if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_ifencei)) &&
+!cpu->cfg.ext_ifencei) {
+error_setg(errp, "RVG requires Zifencei but user set "
+   "Zifencei to false");
+return;
+}
+
 warn_report("Setting G will also set IMAFD_Zicsr_Zifencei");
-cpu->cfg.ext_icsr = true;
-cpu->cfg.ext_ifencei = true;
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_icsr), true);
+cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_ifencei), true);
 
 env->misa_ext |= RVI | RVM | RVA | RVF | RVD;
 env->misa_ext_mask |= RVI | RVM | RVA | RVF | RVD;
-- 
2.41.0




[PATCH v9 06/20] target/riscv/cpu.c: split vendor exts from riscv_cpu_extensions[]

2023-09-01 Thread Daniel Henrique Barboza
Our goal is to make riscv_cpu_extensions[] hold only ratified,
non-vendor extensions.

Create a new riscv_cpu_vendor_exts[] array for them, changing
riscv_cpu_add_user_properties() and riscv_cpu_add_kvm_properties()
accordingly.

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Alistair Francis 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu.c | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 2349f813e4..86d536f242 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1867,7 +1867,10 @@ static Property riscv_cpu_extensions[] = {
 DEFINE_PROP_BOOL("zcmt", RISCVCPU, cfg.ext_zcmt, false),
 DEFINE_PROP_BOOL("zicond", RISCVCPU, cfg.ext_zicond, false),
 
-/* Vendor-specific custom extensions */
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static Property riscv_cpu_vendor_exts[] = {
 DEFINE_PROP_BOOL("xtheadba", RISCVCPU, cfg.ext_xtheadba, false),
 DEFINE_PROP_BOOL("xtheadbb", RISCVCPU, cfg.ext_xtheadbb, false),
 DEFINE_PROP_BOOL("xtheadbs", RISCVCPU, cfg.ext_xtheadbs, false),
@@ -1978,6 +1981,10 @@ static void riscv_cpu_add_kvm_properties(Object *obj)
 riscv_cpu_add_kvm_unavail_prop(obj, prop->name);
 }
 
+for (prop = riscv_cpu_vendor_exts; prop && prop->name; prop++) {
+riscv_cpu_add_kvm_unavail_prop(obj, prop->name);
+}
+
 for (prop = riscv_cpu_experimental_exts; prop && prop->name; prop++) {
 riscv_cpu_add_kvm_unavail_prop(obj, prop->name);
 }
@@ -2022,6 +2029,10 @@ static void riscv_cpu_add_user_properties(Object *obj)
 qdev_property_add_static(dev, prop);
 }
 
+for (prop = riscv_cpu_vendor_exts; prop && prop->name; prop++) {
+qdev_property_add_static(dev, prop);
+}
+
 for (prop = riscv_cpu_experimental_exts; prop && prop->name; prop++) {
 qdev_property_add_static(dev, prop);
 }
-- 
2.41.0




[PATCH v9 08/20] target/riscv/cpu.c: add riscv_cpu_add_kvm_unavail_prop_array()

2023-09-01 Thread Daniel Henrique Barboza
Use a helper in riscv_cpu_add_kvm_properties() to eliminate some of its
code repetition.

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu.c | 24 +---
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index d484d63bcd..8cd19a9b9c 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1978,6 +1978,16 @@ static void riscv_cpu_add_kvm_unavail_prop(Object *obj, 
const char *prop_name)
 NULL, (void *)prop_name);
 }
 
+static void riscv_cpu_add_kvm_unavail_prop_array(Object *obj,
+ Property *array)
+{
+g_assert(array);
+
+for (Property *prop = array; prop && prop->name; prop++) {
+riscv_cpu_add_kvm_unavail_prop(obj, prop->name);
+}
+}
+
 static void riscv_cpu_add_kvm_properties(Object *obj)
 {
 Property *prop;
@@ -1986,17 +1996,9 @@ static void riscv_cpu_add_kvm_properties(Object *obj)
 kvm_riscv_init_user_properties(obj);
 riscv_cpu_add_misa_properties(obj);
 
-for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
-riscv_cpu_add_kvm_unavail_prop(obj, prop->name);
-}
-
-for (prop = riscv_cpu_vendor_exts; prop && prop->name; prop++) {
-riscv_cpu_add_kvm_unavail_prop(obj, prop->name);
-}
-
-for (prop = riscv_cpu_experimental_exts; prop && prop->name; prop++) {
-riscv_cpu_add_kvm_unavail_prop(obj, prop->name);
-}
+riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_extensions);
+riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_vendor_exts);
+riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_experimental_exts);
 
 for (prop = riscv_cpu_options; prop && prop->name; prop++) {
 /* Check if KVM created the property already */
-- 
2.41.0




[PATCH v9 14/20] target/riscv: make CPUCFG() macro public

2023-09-01 Thread Daniel Henrique Barboza
The RISC-V KVM driver uses a CPUCFG() macro that calculates the offset
of a certain field in the struct RISCVCPUConfig. We're going to use this
macro in target/riscv/cpu.c as well in the next patches. Make it public.

Rename it to CPU_CFG_OFFSET() for more clarity while we're at it.

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Alistair Francis 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu.c | 2 +-
 target/riscv/cpu.h | 2 ++
 target/riscv/kvm.c | 8 +++-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 03e936348a..43c68e1792 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -48,7 +48,7 @@ struct isa_ext_data {
 };
 
 #define ISA_EXT_DATA_ENTRY(_name, _min_ver, _prop) \
-{#_name, _min_ver, offsetof(struct RISCVCPUConfig, _prop)}
+{#_name, _min_ver, CPU_CFG_OFFSET(_prop)}
 
 /*
  * From vector_helper.c
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 6ea22e0eea..577abcd724 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -62,6 +62,8 @@
 const char *riscv_get_misa_ext_name(uint32_t bit);
 const char *riscv_get_misa_ext_description(uint32_t bit);
 
+#define CPU_CFG_OFFSET(_prop) offsetof(struct RISCVCPUConfig, _prop)
+
 /* Privileged specification version */
 enum {
 PRIV_VERSION_1_10_0 = 0,
diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
index c01cfb03f4..14763ec0cd 100644
--- a/target/riscv/kvm.c
+++ b/target/riscv/kvm.c
@@ -205,10 +205,8 @@ static void kvm_riscv_update_cpu_misa_ext(RISCVCPU *cpu, 
CPUState *cs)
 }
 }
 
-#define CPUCFG(_prop) offsetof(struct RISCVCPUConfig, _prop)
-
 #define KVM_EXT_CFG(_name, _prop, _reg_id) \
-{.name = _name, .offset = CPUCFG(_prop), \
+{.name = _name, .offset = CPU_CFG_OFFSET(_prop), \
  .kvm_reg_id = _reg_id}
 
 static KVMCPUConfig kvm_multi_ext_cfgs[] = {
@@ -285,13 +283,13 @@ static void kvm_cpu_set_multi_ext_cfg(Object *obj, 
Visitor *v,
 
 static KVMCPUConfig kvm_cbom_blocksize = {
 .name = "cbom_blocksize",
-.offset = CPUCFG(cbom_blocksize),
+.offset = CPU_CFG_OFFSET(cbom_blocksize),
 .kvm_reg_id = KVM_REG_RISCV_CONFIG_REG(zicbom_block_size)
 };
 
 static KVMCPUConfig kvm_cboz_blocksize = {
 .name = "cboz_blocksize",
-.offset = CPUCFG(cboz_blocksize),
+.offset = CPU_CFG_OFFSET(cboz_blocksize),
 .kvm_reg_id = KVM_REG_RISCV_CONFIG_REG(zicboz_block_size)
 };
 
-- 
2.41.0




[PATCH v9 00/20] riscv: 'max' CPU, detect user choice in TCG

2023-09-01 Thread Daniel Henrique Barboza
Hi,

This new version contains suggestions made by Andrew Jones in v8.

Most notable change is the removal of the opensbi.py test in patch 11,
which was replaced by a TuxBoot test. It's more suitable to test the
integrity of all the extensions enabled by the 'max' CPU.

The series is available in this branch:

https://gitlab.com/danielhb/qemu/-/tree/max_cpu_user_choice_v9

Patches missing acks: 11, 15

Changes from v8:
- patch 7:
  - add g_assert(array) at the start of riscv_cpu_add_qdev_prop_array()
- patch 8:
  - add g_assert(array) at the start of riscv_cpu_add_kvm_unavail_prop_array()
- patch 11:
  - removed both opensbi.py tests
  - added 2 'max' cpu tuxboot tests in tuxrun_baselines.py
- patch 12:
  - fixed typos in deprecated.rst
- patch 15:
  - use g_assert_not_reached() at the end of cpu_cfg_ext_get_min_version()
- patch 19:
  - added comment on top of riscv_cpu_add_misa_properties() explaining why
we're not implementing user choice support for MISA properties
- patch 20:
  - warn_report() is now called after the G error conditions
- v8 link: 
https://lore.kernel.org/qemu-riscv/20230824221440.484675-1-dbarb...@ventanamicro.com/



Daniel Henrique Barboza (20):
  target/riscv/cpu.c: split CPU options from riscv_cpu_extensions[]
  target/riscv/cpu.c: skip 'bool' check when filtering KVM props
  target/riscv/cpu.c: split kvm prop handling to its own helper
  target/riscv: add DEFINE_PROP_END_OF_LIST() to riscv_cpu_options[]
  target/riscv/cpu.c: split non-ratified exts from
riscv_cpu_extensions[]
  target/riscv/cpu.c: split vendor exts from riscv_cpu_extensions[]
  target/riscv/cpu.c: add riscv_cpu_add_qdev_prop_array()
  target/riscv/cpu.c: add riscv_cpu_add_kvm_unavail_prop_array()
  target/riscv/cpu.c: limit cfg->vext_spec log message
  target/riscv: add 'max' CPU type
  avocado, risc-v: add tuxboot tests for 'max' CPU
  target/riscv: deprecate the 'any' CPU type
  target/riscv/cpu.c: use offset in isa_ext_is_enabled/update_enabled
  target/riscv: make CPUCFG() macro public
  target/riscv/cpu.c: introduce cpu_cfg_ext_auto_update()
  target/riscv/cpu.c: use cpu_cfg_ext_auto_update() during realize()
  target/riscv/cpu.c: introduce RISCVCPUMultiExtConfig
  target/riscv: use isa_ext_update_enabled() in
init_max_cpu_extensions()
  target/riscv/cpu.c: honor user choice in cpu_cfg_ext_auto_update()
  target/riscv/cpu.c: consider user option with RVG

 docs/about/deprecated.rst |  12 +
 target/riscv/cpu-qom.h|   1 +
 target/riscv/cpu.c| 564 +-
 target/riscv/cpu.h|   2 +
 target/riscv/kvm.c|   8 +-
 tests/avocado/tuxrun_baselines.py |  32 ++
 6 files changed, 450 insertions(+), 169 deletions(-)

-- 
2.41.0




[PATCH v9 02/20] target/riscv/cpu.c: skip 'bool' check when filtering KVM props

2023-09-01 Thread Daniel Henrique Barboza
After the introduction of riscv_cpu_options[] all properties in
riscv_cpu_extensions[] are booleans. This check is now obsolete.

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Alistair Francis 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu.c | 14 --
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index fdbd8eb0b8..db640e7460 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1976,17 +1976,11 @@ static void riscv_cpu_add_user_properties(Object *obj)
  * Set the default to disabled for every extension
  * unknown to KVM and error out if the user attempts
  * to enable any of them.
- *
- * We're giving a pass for non-bool properties since they're
- * not related to the availability of extensions and can be
- * safely ignored as is.
  */
-if (prop->info == _prop_bool) {
-object_property_add(obj, prop->name, "bool",
-NULL, cpu_set_cfg_unavailable,
-NULL, (void *)prop->name);
-continue;
-}
+object_property_add(obj, prop->name, "bool",
+NULL, cpu_set_cfg_unavailable,
+NULL, (void *)prop->name);
+continue;
 }
 #endif
 qdev_property_add_static(dev, prop);
-- 
2.41.0




[PATCH v9 03/20] target/riscv/cpu.c: split kvm prop handling to its own helper

2023-09-01 Thread Daniel Henrique Barboza
Future patches will split the existing Property arrays even further, and
the existing code in riscv_cpu_add_user_properties() will start to scale
bad with it because it's dealing with KVM constraints mixed in with TCG
constraints. We're going to pay a high price to share a couple of common
lines of code between the two.

Create a new riscv_cpu_add_kvm_properties() that will be forked from
riscv_cpu_add_user_properties() if we're running KVM. The helper
includes all properties that a KVM CPU will add. The rest of
riscv_cpu_add_user_properties() body will then be relieved from having
to deal with KVM constraints.

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Weiwei Li 
Reviewed-by: Alistair Francis 
Reviewed-by: Andrew Jones 
---
 target/riscv/cpu.c | 65 ++
 1 file changed, 42 insertions(+), 23 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index db640e7460..8e6d316500 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1943,6 +1943,46 @@ static void cpu_set_cfg_unavailable(Object *obj, Visitor 
*v,
 }
 #endif
 
+#ifndef CONFIG_USER_ONLY
+static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name)
+{
+/* Check if KVM created the property already */
+if (object_property_find(obj, prop_name)) {
+return;
+}
+
+/*
+ * Set the default to disabled for every extension
+ * unknown to KVM and error out if the user attempts
+ * to enable any of them.
+ */
+object_property_add(obj, prop_name, "bool",
+NULL, cpu_set_cfg_unavailable,
+NULL, (void *)prop_name);
+}
+
+static void riscv_cpu_add_kvm_properties(Object *obj)
+{
+Property *prop;
+DeviceState *dev = DEVICE(obj);
+
+kvm_riscv_init_user_properties(obj);
+riscv_cpu_add_misa_properties(obj);
+
+for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
+riscv_cpu_add_kvm_unavail_prop(obj, prop->name);
+}
+
+for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) {
+/* Check if KVM created the property already */
+if (object_property_find(obj, riscv_cpu_options[i].name)) {
+continue;
+}
+qdev_property_add_static(dev, _cpu_options[i]);
+}
+}
+#endif
+
 /*
  * Add CPU properties with user-facing flags.
  *
@@ -1958,39 +1998,18 @@ static void riscv_cpu_add_user_properties(Object *obj)
 riscv_add_satp_mode_properties(obj);
 
 if (kvm_enabled()) {
-kvm_riscv_init_user_properties(obj);
+riscv_cpu_add_kvm_properties(obj);
+return;
 }
 #endif
 
 riscv_cpu_add_misa_properties(obj);
 
 for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
-#ifndef CONFIG_USER_ONLY
-if (kvm_enabled()) {
-/* Check if KVM created the property already */
-if (object_property_find(obj, prop->name)) {
-continue;
-}
-
-/*
- * Set the default to disabled for every extension
- * unknown to KVM and error out if the user attempts
- * to enable any of them.
- */
-object_property_add(obj, prop->name, "bool",
-NULL, cpu_set_cfg_unavailable,
-NULL, (void *)prop->name);
-continue;
-}
-#endif
 qdev_property_add_static(dev, prop);
 }
 
 for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) {
-/* Check if KVM created the property already */
-if (object_property_find(obj, riscv_cpu_options[i].name)) {
-continue;
-}
 qdev_property_add_static(dev, _cpu_options[i]);
 }
 }
-- 
2.41.0




Re: [PATCH] arm64: Restore trapless ptimer access

2023-09-01 Thread Colton Lewis
On Fri, Sep 01, 2023 at 09:35:47AM +0200, Andrew Jones wrote:
> On Thu, Aug 31, 2023 at 07:00:52PM +, Colton Lewis wrote:
> > Due to recent KVM changes, QEMU is setting a ptimer offset resulting
> > in unintended trap and emulate access and a consequent performance
> > hit. Filter out the PTIMER_CNT register to restore trapless ptimer
> > access.
> >
> > Quoting Andrew Jones:
> >
> > Simply reading the CNT register and writing back the same value is
> > enough to set an offset, since the timer will have certainly moved
> > past whatever value was read by the time it's written.  QEMU
> > frequently saves and restores all registers in the get-reg-list array,
> > unless they've been explicitly filtered out (with Linux commit
> > 680232a94c12, KVM_REG_ARM_PTIMER_CNT is now in the array). So, to
> > restore trapless ptimer accesses, we need a QEMU patch to filter out
> > the register.
> >
> > See
> > https://lore.kernel.org/kvmarm/gsntttsonus5@coltonlewis-kvm.c.googlers.com/T/#m0770023762a821db2a3f0dd0a7dc6aa54e0d0da9
>
> The link can be shorter with
>
> https://lore.kernel.org/all/20230823200408.1214332-1-coltonle...@google.com/

I will keep that in mind next time.

> > for additional context.
> >
> > Signed-off-by: Andrew Jones 
>
> Thanks for the testing and posting, Colton. Please add your s-o-b and a
> Tested-by tag as well.

Assuming it is sufficient to add here instead of reposting the whole patch:

Signed-off-by: Colton Lewis 
Tested-by: Colton Lewis 

> > ---
> >  target/arm/kvm64.c | 1 +
> >  1 file changed, 1 insertion(+)
> >
> > diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
> > index 4d904a1d11..2dd46e0a99 100644
> > --- a/target/arm/kvm64.c
> > +++ b/target/arm/kvm64.c
> > @@ -672,6 +672,7 @@ typedef struct CPRegStateLevel {
> >   */
> >  static const CPRegStateLevel non_runtime_cpregs[] = {
> >  { KVM_REG_ARM_TIMER_CNT, KVM_PUT_FULL_STATE },
> > +{ KVM_REG_ARM_PTIMER_CNT, KVM_PUT_FULL_STATE },
> >  };
> >
> >  int kvm_arm_cpreg_level(uint64_t regidx)
> > --
> > 2.42.0.283.g2d96d420d3-goog
> >



[PATCH RESEND 2/2] block: Remove unnecessary variable in bdrv_block_device_info

2023-09-01 Thread Fabiano Rosas
The commit 5d8813593f ("block/qapi: Let bdrv_query_image_info()
recurse") removed the loop where we set the 'bs0' variable, so now it
is just the same as 'bs'.

Signed-off-by: Fabiano Rosas 
Reviewed-by: Philippe Mathieu-Daudé 
---
 block/qapi.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/block/qapi.c b/block/qapi.c
index 79bf80c503..1cbb0935ff 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -48,7 +48,7 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
 {
 ImageInfo **p_image_info;
 ImageInfo *backing_info;
-BlockDriverState *bs0, *backing;
+BlockDriverState *backing;
 BlockDeviceInfo *info;
 ERRP_GUARD();
 
@@ -145,7 +145,6 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
 
 info->write_threshold = bdrv_write_threshold_get(bs);
 
-bs0 = bs;
 p_image_info = >image;
 info->backing_file_depth = 0;
 
@@ -153,7 +152,7 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
  * Skip automatically inserted nodes that the user isn't aware of for
  * query-block (blk != NULL), but not for query-named-block-nodes
  */
-bdrv_query_image_info(bs0, p_image_info, flat, blk != NULL, errp);
+bdrv_query_image_info(bs, p_image_info, flat, blk != NULL, errp);
 if (*errp) {
 qapi_free_BlockDeviceInfo(info);
 return NULL;
-- 
2.35.3




[PATCH RESEND 0/2] block/qapi: Dead code cleanup

2023-09-01 Thread Fabiano Rosas
Hi,

I'm resending a couple of already reviewed patches that were part of a
larger series[1].

Thanks

1- https://lore.kernel.org/r/20230609201910.12100-1-faro...@suse.de

Fabiano Rosas (2):
  block: Remove bdrv_query_block_node_info
  block: Remove unnecessary variable in bdrv_block_device_info

 block/qapi.c | 32 ++--
 include/block/qapi.h |  3 ---
 2 files changed, 2 insertions(+), 33 deletions(-)

-- 
2.35.3




[PATCH RESEND 1/2] block: Remove bdrv_query_block_node_info

2023-09-01 Thread Fabiano Rosas
The last call site of this function has been removed by commit
c04d0ab026 ("qemu-img: Let info print block graph").

Reviewed-by: Claudio Fontana 
Signed-off-by: Fabiano Rosas 
---
 block/qapi.c | 27 ---
 include/block/qapi.h |  3 ---
 2 files changed, 30 deletions(-)

diff --git a/block/qapi.c b/block/qapi.c
index f34f95e0ef..79bf80c503 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -309,33 +309,6 @@ out:
 aio_context_release(bdrv_get_aio_context(bs));
 }
 
-/**
- * bdrv_query_block_node_info:
- * @bs: block node to examine
- * @p_info: location to store node information
- * @errp: location to store error information
- *
- * Store image information about @bs in @p_info.
- *
- * @p_info will be set only on success. On error, store error in @errp.
- */
-void bdrv_query_block_node_info(BlockDriverState *bs,
-BlockNodeInfo **p_info,
-Error **errp)
-{
-BlockNodeInfo *info;
-ERRP_GUARD();
-
-info = g_new0(BlockNodeInfo, 1);
-bdrv_do_query_node_info(bs, info, errp);
-if (*errp) {
-qapi_free_BlockNodeInfo(info);
-return;
-}
-
-*p_info = info;
-}
-
 /**
  * bdrv_query_image_info:
  * @bs: block node to examine
diff --git a/include/block/qapi.h b/include/block/qapi.h
index 18d48ddb70..8663971c58 100644
--- a/include/block/qapi.h
+++ b/include/block/qapi.h
@@ -36,9 +36,6 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
 int bdrv_query_snapshot_info_list(BlockDriverState *bs,
   SnapshotInfoList **p_list,
   Error **errp);
-void bdrv_query_block_node_info(BlockDriverState *bs,
-BlockNodeInfo **p_info,
-Error **errp);
 void bdrv_query_image_info(BlockDriverState *bs,
ImageInfo **p_info,
bool flat,
-- 
2.35.3




Re: [PATCH for-8.2 v2 2/2] migration: Allow user to specify migration switchover bandwidth

2023-09-01 Thread Joao Martins



On 01/09/2023 18:59, Joao Martins wrote:
> On 03/08/2023 16:53, Peter Xu wrote:
>> @@ -2694,7 +2694,17 @@ static void migration_update_counters(MigrationState 
>> *s,
>>  transferred = current_bytes - s->iteration_initial_bytes;
>>  time_spent = current_time - s->iteration_start_time;
>>  bandwidth = (double)transferred / time_spent;
>> -s->threshold_size = bandwidth * migrate_downtime_limit();
>> +if (migrate_max_switchover_bandwidth()) {
>> +/*
>> + * If the user specified an available bandwidth, let's trust the
>> + * user so that can be more accurate than what we estimated.
>> + */
>> +avail_bw = migrate_max_switchover_bandwidth();
>> +} else {
>> +/* If the user doesn't specify bandwidth, we use the estimated */
>> +avail_bw = bandwidth;
>> +}
>> +s->threshold_size = avail_bw * migrate_downtime_limit();
>>  
> 
> [ sorry for giving review comments in piecemeal :/ ]
> 
> There might be something odd with the calculation. It would be right if
> downtime_limit was in seconds. But we are multipling a value that is in
> bytes/sec with a time unit that is in miliseconds. When avail_bw is set to
> switchover_bandwidth, it sounds to me this should be a:
> 
>   /* bytes/msec; @max-switchover-bandwidth is per-seconds */
>   avail_bw = migrate_max_switchover_bandwidth() / 1000.0;
> 
> Otherwise it looks like that we end up overestimating how much we can still 
> send
> during switchover? If this is correct and I am not missing some assumption, 

(...)

> then
> same is applicable to the threshold_size calculation in general without
> switchover-bandwidth but likely in a different way:
> 
>   /* bytes/msec; but @bandwidth is calculated in 100msec quantas */
>   avail_bw = bandwidth / 100.0;
> 

Nevermind this part. I was wrong in the @bandwidth adjustment as it is already
calculated in bytes/ms. It's max_switchover_bandwidth that needs an adjustment
it seems.

> There's a very good chance I'm missing details, so apologies beforehand on
> wasting your time if I didn't pick up on it through the code.
> 
>   Joao
> 



Re: [PATCH v5 8/8] migration: Add a wrapper to cleanup migration files

2023-09-01 Thread Fabiano Rosas
Peter Xu  writes:

> On Thu, Aug 31, 2023 at 03:39:16PM -0300, Fabiano Rosas wrote:
>> @@ -1166,16 +1183,9 @@ static void migrate_fd_cleanup(MigrationState *s)
>>  qemu_mutex_lock_iothread();
>>  
>>  multifd_save_cleanup();
>> -qemu_mutex_lock(>qemu_file_lock);
>> -tmp = s->to_dst_file;
>> -s->to_dst_file = NULL;
>> -qemu_mutex_unlock(>qemu_file_lock);
>> -/*
>> - * Close the file handle without the lock to make sure the
>> - * critical section won't block for long.
>> - */
>> -migration_ioc_unregister_yank_from_file(tmp);
>> -qemu_fclose(tmp);
>> +
>> +migration_ioc_unregister_yank_from_file(s->to_dst_file);
>
> I think you suggested that we should always take the file lock when
> operating on them, so this is slightly going backwards to not hold any lock
> when doing it. But doing so in migrate_fd_cleanup() is probably fine (as it
> serializes with bql on all the rest qmp commands, neither should migration
> thread exist at this point).  Your call; it's still much cleaner.

I think I was mistaken. We need the lock on the thread that clears the
pointer so that we can safely dereference it on another thread under the
lock.

Here we're accessing it from the same thread that later does the
clearing. So that's a slightly different problem.



Re: [PATCH v2 14/14] tcg/loongarch64: Lower rotli_vec to vrotri

2023-09-01 Thread Richard Henderson

On 9/1/23 02:31, Jiajie Chen wrote:

Signed-off-by: Jiajie Chen
---
  tcg/loongarch64/tcg-target.c.inc | 21 +
  tcg/loongarch64/tcg-target.h |  2 +-
  2 files changed, 22 insertions(+), 1 deletion(-)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH v2 13/14] tcg/loongarch64: Lower rotv_vec ops to LSX

2023-09-01 Thread Richard Henderson

On 9/1/23 02:31, Jiajie Chen wrote:

Lower the following ops:

- rotrv_vec
- rotlv_vec

Signed-off-by: Jiajie Chen
---
  tcg/loongarch64/tcg-target.c.inc | 14 ++
  tcg/loongarch64/tcg-target.h |  2 +-
  2 files changed, 15 insertions(+), 1 deletion(-)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH v2 12/14] tcg/loongarch64: Lower vector shift integer ops

2023-09-01 Thread Richard Henderson

On 9/1/23 02:31, Jiajie Chen wrote:

Lower the following ops:

- shli_vec
- shrv_vec
- sarv_vec

Signed-off-by: Jiajie Chen
---
  tcg/loongarch64/tcg-target.c.inc | 21 +
  tcg/loongarch64/tcg-target.h |  2 +-
  2 files changed, 22 insertions(+), 1 deletion(-)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH for-8.2 v2 2/2] migration: Allow user to specify migration switchover bandwidth

2023-09-01 Thread Joao Martins
On 03/08/2023 16:53, Peter Xu wrote:
> @@ -2694,7 +2694,17 @@ static void migration_update_counters(MigrationState 
> *s,
>  transferred = current_bytes - s->iteration_initial_bytes;
>  time_spent = current_time - s->iteration_start_time;
>  bandwidth = (double)transferred / time_spent;
> -s->threshold_size = bandwidth * migrate_downtime_limit();
> +if (migrate_max_switchover_bandwidth()) {
> +/*
> + * If the user specified an available bandwidth, let's trust the
> + * user so that can be more accurate than what we estimated.
> + */
> +avail_bw = migrate_max_switchover_bandwidth();
> +} else {
> +/* If the user doesn't specify bandwidth, we use the estimated */
> +avail_bw = bandwidth;
> +}
> +s->threshold_size = avail_bw * migrate_downtime_limit();
>  

[ sorry for giving review comments in piecemeal :/ ]

There might be something odd with the calculation. It would be right if
downtime_limit was in seconds. But we are multipling a value that is in
bytes/sec with a time unit that is in miliseconds. When avail_bw is set to
switchover_bandwidth, it sounds to me this should be a:

/* bytes/msec; @max-switchover-bandwidth is per-seconds */
avail_bw = migrate_max_switchover_bandwidth() / 1000.0;

Otherwise it looks like that we end up overestimating how much we can still send
during switchover? If this is correct and I am not missing some assumption, then
same is applicable to the threshold_size calculation in general without
switchover-bandwidth but likely in a different way:

/* bytes/msec; but @bandwidth is calculated in 100msec quantas */
avail_bw = bandwidth / 100.0;

There's a very good chance I'm missing details, so apologies beforehand on
wasting your time if I didn't pick up on it through the code.

Joao



Re: [PATCH v2 05/14] tcg/loongarch64: Lower vector bitwise operations

2023-09-01 Thread Richard Henderson

On 9/1/23 02:30, Jiajie Chen wrote:

Lower the following ops:

- and_vec
- andc_vec
- or_vec
- orc_vec
- xor_vec
- nor_vec
- not_vec

Signed-off-by: Jiajie Chen
---
  tcg/loongarch64/tcg-target-con-set.h |  2 ++
  tcg/loongarch64/tcg-target.c.inc | 44 
  tcg/loongarch64/tcg-target.h |  8 ++---
  3 files changed, 50 insertions(+), 4 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH v2 04/14] tcg/loongarch64: Lower add/sub_vec to vadd/vsub

2023-09-01 Thread Richard Henderson

On 9/1/23 02:30, Jiajie Chen wrote:

Lower the following ops:

- add_vec
- sub_vec

Signed-off-by: Jiajie Chen 
---
  tcg/loongarch64/tcg-target-con-set.h |  1 +
  tcg/loongarch64/tcg-target.c.inc | 58 
  2 files changed, 59 insertions(+)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index d04916db25..eaa015e813 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -31,5 +31,6 @@ C_O1_I2(r, 0, rZ)
  C_O1_I2(r, rZ, ri)
  C_O1_I2(r, rZ, rJ)
  C_O1_I2(r, rZ, rZ)
+C_O1_I2(w, w, wi)
  C_O1_I2(w, w, wJ)


Similar comment with respect to the constraint.  I think you may be right that we need to 
improve constant handling for vectors.  I'm willing to work with you to improve that as a 
follow-up.



Reviewed-by: Richard Henderson 


r~



Re: [PATCH v2 03/14] tcg/loongarch64: Lower cmp_vec to vseq/vsle/vslt

2023-09-01 Thread Richard Henderson

On 9/1/23 10:28, Jiajie Chen wrote:


On 2023/9/2 01:24, Richard Henderson wrote:

On 9/1/23 02:30, Jiajie Chen wrote:

Signed-off-by: Jiajie Chen 
---
  tcg/loongarch64/tcg-target-con-set.h |  1 +
  tcg/loongarch64/tcg-target.c.inc | 60 
  2 files changed, 61 insertions(+)


Reviewed-by: Richard Henderson 




diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index 37b3f80bf9..d04916db25 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -31,4 +31,5 @@ C_O1_I2(r, 0, rZ)
  C_O1_I2(r, rZ, ri)
  C_O1_I2(r, rZ, rJ)
  C_O1_I2(r, rZ, rZ)
+C_O1_I2(w, w, wJ)


Notes for improvement: 'J' is a signed 32-bit immediate.



I was wondering about the behavior of 'J' on i128 types: in tcg_target_const_match(), the 
argument type is int, so will the higher bits be truncated?


The argument is int64_t val.

The only constants that we allow for vectors are dupi, so all higher parts are the same as 
the lower part.



Besides, tcg_target_const_match() does not know the vector element width.


No, it hadn't been required so far -- there are very few vector instructions that allow 
immediates.



r~



Re: [PATCH v2 03/14] tcg/loongarch64: Lower cmp_vec to vseq/vsle/vslt

2023-09-01 Thread Jiajie Chen



On 2023/9/2 01:24, Richard Henderson wrote:

On 9/1/23 02:30, Jiajie Chen wrote:

Signed-off-by: Jiajie Chen 
---
  tcg/loongarch64/tcg-target-con-set.h |  1 +
  tcg/loongarch64/tcg-target.c.inc | 60 
  2 files changed, 61 insertions(+)


Reviewed-by: Richard Henderson 




diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h

index 37b3f80bf9..d04916db25 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -31,4 +31,5 @@ C_O1_I2(r, 0, rZ)
  C_O1_I2(r, rZ, ri)
  C_O1_I2(r, rZ, rJ)
  C_O1_I2(r, rZ, rZ)
+C_O1_I2(w, w, wJ)


Notes for improvement: 'J' is a signed 32-bit immediate.



I was wondering about the behavior of 'J' on i128 types: in 
tcg_target_const_match(), the argument type is int, so will the higher 
bits be truncated?


Besides, tcg_target_const_match() does not know the vector element width.





+    if (const_args[2]) {
+    /*
+ * cmp_vec dest, src, value
+ * Try vseqi/vslei/vslti
+ */
+    int64_t value = sextract64(a2, 0, 8 << vece);
+    if ((cond == TCG_COND_EQ || cond == TCG_COND_LE || \
+ cond == TCG_COND_LT) && (-0x10 <= value && value <= 
0x0f)) {
+    tcg_out32(s, 
encode_vdvjsk5_insn(cmp_vec_imm_insn[cond][vece], \

+ a0, a1, value));
+    break;
+    } else if ((cond == TCG_COND_LEU || cond == 
TCG_COND_LTU) &&

+    (0x00 <= value && value <= 0x1f)) {
+    tcg_out32(s, 
encode_vdvjuk5_insn(cmp_vec_imm_insn[cond][vece], \

+ a0, a1, value));


Better would be a new constraint that only matches

    -0x10 <= x <= 0x1f

If the sign is wrong for the comparison, it can *always* be loaded 
with just vldi.


Whereas at present, using J,


+    tcg_out_dupi_vec(s, type, vece, temp_vec, a2);
+    a2 = temp_vec;


this may require 3 instructions (lu12i.w + ori + vreplgr2vr).

By constraining the constants allowed, you allow the register 
allocator to see that a register is required, which may be reused for 
another instruction.



r~




Re: [PATCH 54/67] ui/vc: console-vc requires PIXMAN

2023-09-01 Thread Daniel P . Berrangé
On Wed, Aug 30, 2023 at 01:38:28PM +0400, marcandre.lur...@redhat.com wrote:
> From: Marc-André Lureau 
> 
> Add stubs for the fallback paths.
> 
> Signed-off-by: Marc-André Lureau 
> ---
>  ui/console-vc-stubs.c | 59 +++
>  ui/meson.build|  2 +-
>  2 files changed, 60 insertions(+), 1 deletion(-)
>  create mode 100644 ui/console-vc-stubs.c
> 
> diff --git a/ui/console-vc-stubs.c b/ui/console-vc-stubs.c
> new file mode 100644
> index 00..76ea880d27
> --- /dev/null
> +++ b/ui/console-vc-stubs.c
> @@ -0,0 +1,59 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * QEMU VC stubs
> + */
> +#include "qemu/osdep.h"
> +
> +#include "qapi/error.h"
> +#include "qemu/error-report.h"
> +#include "qemu/option.h"
> +#include "chardev/char.h"
> +#include "ui/console-priv.h"
> +
> +void qemu_text_console_select(QemuTextConsole *c)
> +{
> +}
> +
> +const char * qemu_text_console_get_label(QemuTextConsole *c)
> +{
> +return NULL;
> +}
> +
> +void qemu_text_console_update_cursor(void)
> +{
> +}
> +
> +void qemu_text_console_handle_keysym(QemuTextConsole *s, int keysym)
> +{
> +}
> +
> +#define TYPE_CHARDEV_VC "chardev-vc"
> +
> +static void vc_chr_parse(QemuOpts *opts, ChardevBackend *backend, Error 
> **errp)
> +{
> +const char *id = qemu_opts_id(opts);
> +
> +warn_report("%s: this is a dummy VC driver. "
> +"Use '-nographic' or a different chardev.", id);
> +}

Why should this be an error_setg() call given we have a errp
parameter, so make this unsupportable config into an error ?
Ignoring invalid user configs is not desirable in general.

> +
> +static void char_vc_class_init(ObjectClass *oc, void *data)
> +{
> +ChardevClass *cc = CHARDEV_CLASS(oc);
> +
> +cc->parse = vc_chr_parse;
> +}
> +
> +static const TypeInfo char_vc_type_info = {
> +.name = TYPE_CHARDEV_VC,
> +.parent = TYPE_CHARDEV,
> +.class_init = char_vc_class_init,
> +};
> +
> +void qemu_console_early_init(void)
> +{
> +/* set the default vc driver */
> +if (!object_class_by_name(TYPE_CHARDEV_VC)) {
> +type_register(_vc_type_info);
> +}
> +}
> diff --git a/ui/meson.build b/ui/meson.build
> index 0a1e8272a3..3085e10a72 100644
> --- a/ui/meson.build
> +++ b/ui/meson.build
> @@ -6,7 +6,6 @@ system_ss.add(png)
>  system_ss.add(files(
>'clipboard.c',
>'console.c',
> -  'console-vc.c',
>'cursor.c',
>'input-keymap.c',
>'input-legacy.c',
> @@ -19,6 +18,7 @@ system_ss.add(files(
>'ui-qmp-cmds.c',
>'util.c',
>  ))
> +system_ss.add(when: pixman, if_true: files('console-vc.c'), if_false: 
> files('console-vc-stubs.c'))
>  if dbus_display
>system_ss.add(files('dbus-module.c'))
>  endif
> -- 
> 2.41.0
> 
> 

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




Re: [PATCH 51/67] build-sys: add optional "pixman" feature

2023-09-01 Thread Daniel P . Berrangé
On Wed, Aug 30, 2023 at 05:55:26PM +0200, Philippe Mathieu-Daudé wrote:
> On 30/8/23 17:48, Philippe Mathieu-Daudé wrote:
> > On 30/8/23 11:38, marcandre.lur...@redhat.com wrote:
> > > From: Marc-André Lureau 
> > > 
> > > Set CONFIG_PIXMAN accordinly.
> > > 
> > > Signed-off-by: Marc-André Lureau 
> > > ---
> > >   meson.build   | 6 --
> > >   Kconfig.host  | 3 +++
> > >   meson_options.txt | 2 ++
> > >   3 files changed, 9 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/meson.build b/meson.build
> > > index 98e68ef0b1..3bd7046099 100644
> > > --- a/meson.build
> > > +++ b/meson.build
> > > @@ -836,8 +836,8 @@ if 'ust' in get_option('trace_backends')
> > >    method: 'pkg-config')
> > >   endif
> > >   pixman = not_found
> > > -if have_system or have_tools
> > > -  pixman = dependency('pixman-1', required: have_system,
> > > version:'>=0.21.8',
> > > +if not get_option('pixman').auto() or have_system or have_tools
> > > +  pixman = dependency('pixman-1', required: get_option('pixman'),
> > > version:'>=0.21.8',
> > >     method: 'pkg-config')
> 
> 
> > > diff --git a/meson_options.txt b/meson_options.txt
> > > index aaea5ddd77..89654fd77d 100644
> > > --- a/meson_options.txt
> > > +++ b/meson_options.txt
> > > @@ -216,6 +216,8 @@ option('l2tpv3', type : 'feature', value : 'auto',
> > >  description: 'l2tpv3 network backend support')
> > >   option('netmap', type : 'feature', value : 'auto',
> > >  description: 'netmap network backend support')
> > > +option('pixman', type : 'feature', value : 'auto',
> > > +   description: 'pixman support')
> > >   option('slirp', type: 'feature', value: 'auto',
> > >  description: 'libslirp user mode network backend support')
> > >   option('vde', type : 'feature', value : 'auto',
> > 
> > Apparently missing:
> > 
> > -- >8 --
> > diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
> > index 9da3fe299b..16957ea9f0 100644
> > --- a/scripts/meson-buildoptions.sh
> > +++ b/scripts/meson-buildoptions.sh
> > @@ -146,6 +146,7 @@ meson_options_help() {
> >     printf "%s\n" '  pa  PulseAudio sound support'
> >     printf "%s\n" '  parallels   parallels image format support'
> >     printf "%s\n" '  pipewire    PipeWire sound support'
> > +  printf "%s\n" '  pixman  pixman support'
> >     printf "%s\n" '  png PNG support with libpng'
> >     printf "%s\n" '  pvrdma  Enable PVRDMA support'
> >     printf "%s\n" '  qcow1   qcow1 image format support'
> > @@ -397,6 +398,8 @@ _meson_option_parse() {
> >   --disable-parallels) printf "%s" -Dparallels=disabled ;;
> >   --enable-pipewire) printf "%s" -Dpipewire=enabled ;;
> >   --disable-pipewire) printf "%s" -Dpipewire=disabled ;;
> > +    --enable-pixman) printf "%s" -Dpixman=enabled ;;
> > +    --disable-pixman) printf "%s" -Dpixman=disabled ;;
> >   --with-pkgversion=*) quote_sh "-Dpkgversion=$2" ;;
> >   --enable-png) printf "%s" -Dpng=enabled ;;
> >   --disable-png) printf "%s" -Dpng=disabled ;;
> > ---
> 
> Many files fail to build when using --disable-pixman here:

I guess meson.build ought to (temporarily) report an
eror if pixman is missing and/or explicitly disabled,
which is then removed in the next patch that actually
makes it work.


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




Re: [PATCH v2 03/14] tcg/loongarch64: Lower cmp_vec to vseq/vsle/vslt

2023-09-01 Thread Richard Henderson

On 9/1/23 02:30, Jiajie Chen wrote:

Signed-off-by: Jiajie Chen 
---
  tcg/loongarch64/tcg-target-con-set.h |  1 +
  tcg/loongarch64/tcg-target.c.inc | 60 
  2 files changed, 61 insertions(+)


Reviewed-by: Richard Henderson 




diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index 37b3f80bf9..d04916db25 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -31,4 +31,5 @@ C_O1_I2(r, 0, rZ)
  C_O1_I2(r, rZ, ri)
  C_O1_I2(r, rZ, rJ)
  C_O1_I2(r, rZ, rZ)
+C_O1_I2(w, w, wJ)


Notes for improvement: 'J' is a signed 32-bit immediate.


+if (const_args[2]) {
+/*
+ * cmp_vec dest, src, value
+ * Try vseqi/vslei/vslti
+ */
+int64_t value = sextract64(a2, 0, 8 << vece);
+if ((cond == TCG_COND_EQ || cond == TCG_COND_LE || \
+ cond == TCG_COND_LT) && (-0x10 <= value && value <= 0x0f)) {
+tcg_out32(s, encode_vdvjsk5_insn(cmp_vec_imm_insn[cond][vece], 
\
+ a0, a1, value));
+break;
+} else if ((cond == TCG_COND_LEU || cond == TCG_COND_LTU) &&
+(0x00 <= value && value <= 0x1f)) {
+tcg_out32(s, encode_vdvjuk5_insn(cmp_vec_imm_insn[cond][vece], 
\
+ a0, a1, value));


Better would be a new constraint that only matches

-0x10 <= x <= 0x1f

If the sign is wrong for the comparison, it can *always* be loaded with just 
vldi.

Whereas at present, using J,


+tcg_out_dupi_vec(s, type, vece, temp_vec, a2);
+a2 = temp_vec;


this may require 3 instructions (lu12i.w + ori + vreplgr2vr).

By constraining the constants allowed, you allow the register allocator to see that a 
register is required, which may be reused for another instruction.



r~



Re: [PATCH 50/67] ui/console: move DisplaySurface to its own header

2023-09-01 Thread Daniel P . Berrangé
On Wed, Aug 30, 2023 at 01:38:24PM +0400, marcandre.lur...@redhat.com wrote:
> From: Marc-André Lureau 
> 
> Mostly for readability reasons.
> 
> Signed-off-by: Marc-André Lureau 
> ---
>  include/ui/console.h | 84 +---
>  include/ui/surface.h | 91 
>  2 files changed, 92 insertions(+), 83 deletions(-)
>  create mode 100644 include/ui/surface.h
> 

> diff --git a/include/ui/surface.h b/include/ui/surface.h
> new file mode 100644
> index 00..37725a303e
> --- /dev/null
> +++ b/include/ui/surface.h
> @@ -0,0 +1,91 @@

When you moved the VC bits out of console.h you added a GPL-2.0-or-later
SPDX tag, so by implication this ought to gain the same.

> +#ifndef SURFACE_H
> +#define SURFACE_H
> +
> +#include "ui/qemu-pixman.h"
> +
> +#ifdef CONFIG_OPENGL
> +# include 
> +# include "ui/shader.h"
> +#endif
> +
> +#define QEMU_ALLOCATED_FLAG 0x01
> +#define QEMU_PLACEHOLDER_FLAG   0x02
> +
> +typedef struct DisplaySurface {
> +pixman_image_t *image;
> +uint8_t flags;
> +#ifdef CONFIG_OPENGL
> +GLenum glformat;
> +GLenum gltype;
> +GLuint texture;
> +#endif
> +#ifdef WIN32
> +HANDLE handle;
> +uint32_t handle_offset;
> +#endif
> +} DisplaySurface;
> +
> +PixelFormat qemu_default_pixelformat(int bpp);
> +
> +DisplaySurface *qemu_create_displaysurface_from(int width, int height,
> +pixman_format_code_t format,
> +int linesize, uint8_t *data);
> +DisplaySurface *qemu_create_displaysurface_pixman(pixman_image_t *image);
> +DisplaySurface *qemu_create_placeholder_surface(int w, int h,
> +const char *msg);
> +#ifdef WIN32
> +void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
> +  HANDLE h, uint32_t offset);
> +#endif
> +
> +DisplaySurface *qemu_create_displaysurface(int width, int height);
> +void qemu_free_displaysurface(DisplaySurface *surface);
> +
> +static inline int is_buffer_shared(DisplaySurface *surface)
> +{
> +return !(surface->flags & QEMU_ALLOCATED_FLAG);
> +}
> +
> +static inline int is_placeholder(DisplaySurface *surface)
> +{
> +return surface->flags & QEMU_PLACEHOLDER_FLAG;
> +}
> +
> +static inline int surface_stride(DisplaySurface *s)
> +{
> +return pixman_image_get_stride(s->image);
> +}
> +
> +static inline void *surface_data(DisplaySurface *s)
> +{
> +return pixman_image_get_data(s->image);
> +}
> +
> +static inline int surface_width(DisplaySurface *s)
> +{
> +return pixman_image_get_width(s->image);
> +}
> +
> +static inline int surface_height(DisplaySurface *s)
> +{
> +return pixman_image_get_height(s->image);
> +}
> +
> +static inline pixman_format_code_t surface_format(DisplaySurface *s)
> +{
> +return pixman_image_get_format(s->image);
> +}
> +
> +static inline int surface_bits_per_pixel(DisplaySurface *s)
> +{
> +int bits = PIXMAN_FORMAT_BPP(surface_format(s));
> +return bits;
> +}
> +
> +static inline int surface_bytes_per_pixel(DisplaySurface *s)
> +{
> +int bits = PIXMAN_FORMAT_BPP(surface_format(s));
> +return DIV_ROUND_UP(bits, 8);
> +}
> +
> +#endif
> -- 
> 2.41.0
> 
> 

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




Re: [PATCH 49/67] ui/vc: split off the VC part from console.c

2023-09-01 Thread Daniel P . Berrangé
On Wed, Aug 30, 2023 at 01:38:23PM +0400, marcandre.lur...@redhat.com wrote:
> From: Marc-André Lureau 
> 
> Move common declarations to console-priv.h, and add a new unit
> console-vc.c which will handle VC/chardev rendering, when pixman is
> available.
> 
> (if necessary, the move could be done chunk by chunks)
> 
> Signed-off-by: Marc-André Lureau 
> ---
>  ui/console-priv.h |   43 ++
>  ui/console-vc.c   | 1079 
>  ui/console.c  | 1096 +
>  ui/meson.build|1 +
>  4 files changed, 1126 insertions(+), 1093 deletions(-)
>  create mode 100644 ui/console-priv.h
>  create mode 100644 ui/console-vc.c
> 
> diff --git a/ui/console-vc.c b/ui/console-vc.c
> new file mode 100644
> index 00..656f099556
> --- /dev/null
> +++ b/ui/console-vc.c
> @@ -0,0 +1,1079 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * QEMU VC

This code is moved out of console.c, which (surprisingly) appears
to have an MIT license header.


The include/ui/console.h header meanwhile has no license, so is
valid to assume it is GPL-2.0-or-later I guess.

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




Re: [PATCH 48/67] ui/vc: preliminary QemuTextConsole changes before split

2023-09-01 Thread Daniel P . Berrangé
On Wed, Aug 30, 2023 at 01:38:22PM +0400, marcandre.lur...@redhat.com wrote:
> From: Marc-André Lureau 
> 
> Those changes will help to split console.c unit in the following commit.
> 
> Signed-off-by: Marc-André Lureau 
> ---
>  ui/console.c | 52 +++-
>  1 file changed, 35 insertions(+), 17 deletions(-)

Reviewed-by: Daniel P. Berrangé 


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




Re: [PATCH 12/20] target/riscv: move KVM only files to kvm subdir

2023-09-01 Thread Daniel Henrique Barboza




On 8/31/23 08:30, Andrew Jones wrote:

On Fri, Aug 25, 2023 at 10:08:45AM -0300, Daniel Henrique Barboza wrote:

Move the files to a 'kvm' dir to promote more code separation between
accelerators and making our lives easier supporting build options such
as --disable-tcg.

Rename kvm.c to kvm-cpu.c to keep it in line with its TCG counterpart.


Now that we have 'kvm' and 'tcg' subdirectories, it seems like we should
be removing prefixes from files, i.e. 'kvm/cpu.c' and 'tcg/cpu.c' would be
less verbose and just as easy to identify, but whatever people like...


I don't mind shortening the names. I chose these because x86 names it that
way.

It's also easier to identify in the editor which file I'm editing at that
moment via the filename alone, e.g. tcg-cpu.c is easier to identify than
seeing 'cpu.c' and having to check the rest of the path.

Yes, VSCode user here, too old for vim/emacs :D



Thanks,

Daniel






Signed-off-by: Daniel Henrique Barboza 
---
  hw/riscv/virt.c   | 2 +-
  target/riscv/cpu.c| 2 +-
  target/riscv/{kvm.c => kvm/kvm-cpu.c} | 0
  target/riscv/{ => kvm}/kvm-stub.c | 0
  target/riscv/{ => kvm}/kvm_riscv.h| 0
  target/riscv/kvm/meson.build  | 2 ++
  target/riscv/meson.build  | 2 +-
  7 files changed, 5 insertions(+), 3 deletions(-)
  rename target/riscv/{kvm.c => kvm/kvm-cpu.c} (100%)
  rename target/riscv/{ => kvm}/kvm-stub.c (100%)
  rename target/riscv/{ => kvm}/kvm_riscv.h (100%)
  create mode 100644 target/riscv/kvm/meson.build

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 388e52a294..77c384ddc3 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -35,7 +35,7 @@
  #include "hw/riscv/virt.h"
  #include "hw/riscv/boot.h"
  #include "hw/riscv/numa.h"
-#include "kvm_riscv.h"
+#include "kvm/kvm_riscv.h"
  #include "hw/intc/riscv_aclint.h"
  #include "hw/intc/riscv_aplic.h"
  #include "hw/intc/riscv_imsic.h"
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 04c6bfaeef..bf6c8519b1 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -33,7 +33,7 @@
  #include "fpu/softfloat-helpers.h"
  #include "sysemu/kvm.h"
  #include "sysemu/tcg.h"
-#include "kvm_riscv.h"
+#include "kvm/kvm_riscv.h"
  #include "tcg/tcg.h"
  
  /* RISC-V CPU definitions */

diff --git a/target/riscv/kvm.c b/target/riscv/kvm/kvm-cpu.c
similarity index 100%
rename from target/riscv/kvm.c
rename to target/riscv/kvm/kvm-cpu.c
diff --git a/target/riscv/kvm-stub.c b/target/riscv/kvm/kvm-stub.c
similarity index 100%
rename from target/riscv/kvm-stub.c
rename to target/riscv/kvm/kvm-stub.c
diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm/kvm_riscv.h
similarity index 100%
rename from target/riscv/kvm_riscv.h
rename to target/riscv/kvm/kvm_riscv.h
diff --git a/target/riscv/kvm/meson.build b/target/riscv/kvm/meson.build
new file mode 100644
index 00..1cd6783894
--- /dev/null
+++ b/target/riscv/kvm/meson.build
@@ -0,0 +1,2 @@
+riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm-cpu.c'),
+ if_false: files('kvm-stub.c'))
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
index f0486183fa..c53962215f 100644
--- a/target/riscv/meson.build
+++ b/target/riscv/meson.build
@@ -24,7 +24,6 @@ riscv_ss.add(files(
'zce_helper.c',
'vcrypto_helper.c'
  ))
-riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: 
files('kvm-stub.c'))
  
  riscv_system_ss = ss.source_set()

  riscv_system_ss.add(files(
@@ -39,6 +38,7 @@ riscv_system_ss.add(files(
  ))
  
  subdir('tcg')

+subdir('kvm')
  
  target_arch += {'riscv': riscv_ss}

  target_softmmu_arch += {'riscv': riscv_system_ss}
--
2.41.0




Reviewed-by: Andrew Jones 




Re: [PATCH 47/67] ui/console: remove redundant format field

2023-09-01 Thread Daniel P . Berrangé
On Wed, Aug 30, 2023 at 01:38:21PM +0400, marcandre.lur...@redhat.com wrote:
> From: Marc-André Lureau 
> 
> It's already part of PIXMAN image.
> 
> Signed-off-by: Marc-André Lureau 
> ---
>  include/ui/console.h | 15 +++
>  ui/console-gl.c  |  2 +-
>  ui/console.c |  4 +---
>  ui/gtk.c |  2 +-
>  ui/spice-display.c   |  2 +-
>  ui/vnc.c |  2 +-
>  6 files changed, 12 insertions(+), 15 deletions(-)

Reviewed-by: Daniel P. Berrangé 


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




Re: [PATCH 46/67] ui/vc: rename kbd_put → qemu_text_console functions

2023-09-01 Thread Daniel P . Berrangé
On Wed, Aug 30, 2023 at 05:41:51PM +0200, Philippe Mathieu-Daudé wrote:
> On 30/8/23 11:38, marcandre.lur...@redhat.com wrote:
> > From: Marc-André Lureau 
> > 
> > They are QemuTextConsole functions, let's make it clear.
> > 
> > Signed-off-by: Marc-André Lureau 
> > ---
> >   include/ui/console.h |  6 ++---
> >   ui/console.c | 10 
> >   ui/curses.c  |  2 +-
> >   ui/gtk.c |  6 ++---
> >   ui/sdl2-input.c  |  4 ++--
> >   ui/sdl2.c|  2 +-
> >   ui/vnc.c | 54 ++--
> >   ui/cocoa.m   |  2 +-
> >   8 files changed, 43 insertions(+), 43 deletions(-)
> > 
> > diff --git a/include/ui/console.h b/include/ui/console.h
> > index 9c362f0e87..26d63d17a2 100644
> > --- a/include/ui/console.h
> > +++ b/include/ui/console.h
> > @@ -112,9 +112,9 @@ bool qemu_mouse_set(int index, Error **errp);
> >   #define QEMU_KEY_CTRL_PAGEUP 0xe406
> >   #define QEMU_KEY_CTRL_PAGEDOWN   0xe407
> > -void kbd_put_keysym_console(QemuTextConsole *s, int keysym);
> > -bool kbd_put_qcode_console(QemuTextConsole *s, int qcode, bool ctrl);
> > -void kbd_put_string_console(QemuTextConsole *s, const char *str, int len);
> > +void qemu_text_console_put_keysym(QemuTextConsole *s, int keysym);
> > +bool qemu_text_console_put_qcode(QemuTextConsole *s, int qcode, bool ctrl);
> > +void qemu_text_console_put_string(QemuTextConsole *s, const char *str, int 
> > len);
> 
> 
> > diff --git a/ui/cocoa.m b/ui/cocoa.m
> > index 9eb4da7713..8b97319587 100644
> > --- a/ui/cocoa.m
> > +++ b/ui/cocoa.m
> > @@ -784,7 +784,7 @@ - (void) handleMonitorInput:(NSEvent *)event
> >   }
> >   if (keysym) {
> > -kbd_put_keysym_console(NULL, keysym);
> > +qemu_text_console_keysym(NULL, keysym);
> >   }
> >   }
> 
> ../../ui/cocoa.m:787:9: error: call to undeclared function
> 'qemu_text_console_keysym'; ISO C99 and later do not support implicit
> function declarations [-Wimplicit-function-declaration]
> qemu_text_console_keysym(NULL, keysym);
> ^
> 
> I can compile using:
> 
> -- >8 --
> diff --git a/ui/cocoa.m b/ui/cocoa.m
> index 8b97319587..b886db7510 100644
> --- a/ui/cocoa.m
> +++ b/ui/cocoa.m
> @@ -784,7 +784,7 @@ - (void) handleMonitorInput:(NSEvent *)event
>  }
> 
>  if (keysym) {
> -qemu_text_console_keysym(NULL, keysym);
> +qemu_text_console_put_keysym(NULL, keysym);
>  }
>  }

With that change added

Reviewed-by: Daniel P. Berrangé 


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




Re: [PATCH 44/67] ui/vc: change the argument for QemuTextConsole

2023-09-01 Thread Daniel P . Berrangé
On Wed, Aug 30, 2023 at 01:38:18PM +0400, marcandre.lur...@redhat.com wrote:
> From: Marc-André Lureau 
> 
> Those functions are specifc to text/vc console, make that explicit from
> the argument type.
> 
> Signed-off-by: Marc-André Lureau 
> ---
>  include/ui/console.h |  6 +++---
>  ui/console.c | 14 ++
>  ui/gtk.c |  2 +-
>  ui/sdl2-input.c  |  5 +++--
>  ui/sdl2.c|  5 ++---
>  5 files changed, 15 insertions(+), 17 deletions(-)
> 
> diff --git a/include/ui/console.h b/include/ui/console.h
> index 91d8bbc9dc..1ccd432b4d 100644
> --- a/include/ui/console.h
> +++ b/include/ui/console.h
> @@ -112,9 +112,9 @@ bool qemu_mouse_set(int index, Error **errp);
>  #define QEMU_KEY_CTRL_PAGEUP 0xe406
>  #define QEMU_KEY_CTRL_PAGEDOWN   0xe407
>  
> -void kbd_put_keysym_console(QemuConsole *s, int keysym);
> -bool kbd_put_qcode_console(QemuConsole *s, int qcode, bool ctrl);
> -void kbd_put_string_console(QemuConsole *s, const char *str, int len);
> +void kbd_put_keysym_console(QemuTextConsole *s, int keysym);
> +bool kbd_put_qcode_console(QemuTextConsole *s, int qcode, bool ctrl);
> +void kbd_put_string_console(QemuTextConsole *s, const char *str, int len);
>  void kbd_put_keysym(int keysym);
>  
>  /* Touch devices */
> diff --git a/ui/console.c b/ui/console.c
> index 9fccecafd7..a98adbb1b2 100644
> --- a/ui/console.c
> +++ b/ui/console.c
> @@ -1135,16 +1135,12 @@ static void kbd_send_chars(QemuTextConsole *s)
>  }
>  
>  /* called when an ascii key is pressed */
> -void kbd_put_keysym_console(QemuConsole *con, int keysym)
> +void kbd_put_keysym_console(QemuTextConsole *s, int keysym)
>  {
> -QemuTextConsole *s = (QemuTextConsole *)object_dynamic_cast(OBJECT(con), 
> TYPE_QEMU_TEXT_CONSOLE);
>  uint8_t buf[16], *q;
>  int c;
>  uint32_t num_free;
>  
> -if (!s)
> -return;
> -
>  switch(keysym) {
>  case QEMU_KEY_CTRL_UP:
>  console_scroll(s, -1);
> @@ -1214,7 +1210,7 @@ static const int ctrl_qcode_to_keysym[Q_KEY_CODE__MAX] 
> = {
>  [Q_KEY_CODE_PGDN]   = QEMU_KEY_CTRL_PAGEDOWN,
>  };
>  
> -bool kbd_put_qcode_console(QemuConsole *s, int qcode, bool ctrl)
> +bool kbd_put_qcode_console(QemuTextConsole *s, int qcode, bool ctrl)
>  {
>  int keysym;
>  
> @@ -1226,7 +1222,7 @@ bool kbd_put_qcode_console(QemuConsole *s, int qcode, 
> bool ctrl)
>  return true;
>  }
>  
> -void kbd_put_string_console(QemuConsole *s, const char *str, int len)
> +void kbd_put_string_console(QemuTextConsole *s, const char *str, int len)
>  {
>  int i;
>  
> @@ -1237,7 +1233,9 @@ void kbd_put_string_console(QemuConsole *s, const char 
> *str, int len)
>  
>  void kbd_put_keysym(int keysym)
>  {
> -kbd_put_keysym_console(active_console, keysym);
> +if (QEMU_IS_TEXT_CONSOLE(active_console)) {
> +kbd_put_keysym_console(QEMU_TEXT_CONSOLE(active_console), keysym);
> +}
>  }
>  
>  static void text_console_invalidate(void *opaque)
> diff --git a/ui/gtk.c b/ui/gtk.c
> index ef98bb0648..c34c133550 100644
> --- a/ui/gtk.c
> +++ b/ui/gtk.c
> @@ -1187,7 +1187,7 @@ static gboolean gd_text_key_down(GtkWidget *widget,
>   GdkEventKey *key, void *opaque)
>  {
>  VirtualConsole *vc = opaque;
> -QemuConsole *con = vc->gfx.dcl.con;
> +QemuTextConsole *con = QEMU_TEXT_CONSOLE(vc->gfx.dcl.con);
>  
>  if (key->keyval == GDK_KEY_Delete) {
>  kbd_put_qcode_console(con, Q_KEY_CODE_DELETE, false);
> diff --git a/ui/sdl2-input.c b/ui/sdl2-input.c
> index f068382209..efc0e76e8c 100644
> --- a/ui/sdl2-input.c
> +++ b/ui/sdl2-input.c
> @@ -44,14 +44,15 @@ void sdl2_process_key(struct sdl2_console *scon,
>  qkbd_state_key_event(scon->kbd, qcode, ev->type == SDL_KEYDOWN);
>  
>  if (!qemu_console_is_graphic(con)) {

If i'm nit-picking I'd say change to be

   "if  (QEMU_IS_TEXT_CONSOLE(con)) {"

as you did in the other places in this patch

> +QemuTextConsole *s = QEMU_TEXT_CONSOLE(con);
>  bool ctrl = qkbd_state_modifier_get(scon->kbd, QKBD_MOD_CTRL);
>  if (ev->type == SDL_KEYDOWN) {
>  switch (qcode) {
>  case Q_KEY_CODE_RET:
> -kbd_put_keysym_console(con, '\n');
> +kbd_put_keysym_console(s, '\n');
>  break;
>  default:
> -kbd_put_qcode_console(con, qcode, ctrl);
> +kbd_put_qcode_console(s, qcode, ctrl);
>  break;
>  }
>  }
> diff --git a/ui/sdl2.c b/ui/sdl2.c
> index 0d91b555e3..16b515fcf9 100644
> --- a/ui/sdl2.c
> +++ b/ui/sdl2.c
> @@ -483,10 +483,9 @@ static void handle_textinput(SDL_Event *ev)
>  return;
>  }
>  
> -if (qemu_console_is_graphic(con)) {
> -return;
> +if (QEMU_IS_TEXT_CONSOLE(con)) {
> +kbd_put_string_console(QEMU_TEXT_CONSOLE(con), ev->text.text, 
> strlen(ev->text.text));
>  }
> -kbd_put_string_console(con, ev->text.text, 

Re: [PATCH 43/67] ui/vc: do not parse VC-specific options in Spice and GTK

2023-09-01 Thread Daniel P . Berrangé
On Wed, Aug 30, 2023 at 01:38:17PM +0400, marcandre.lur...@redhat.com wrote:
> From: Marc-André Lureau 
> 
> In commit 6f974c843c ("gtk: overwrite the console.c char driver"), I
> shared the VC console parse handler with GTK. And later on in commit
> d8aec9d9 ("display: add -display spice-app launching a Spice client"),
> I also used it to handle spice-app VC.
> 
> This is not necessary, the VC console options (width/height/cols/rows)
> are specific, and unused by tty-level GTK/Spice VC.
> 
> This is not a breaking change, as those options are still being parsed
> by QAPI ChardevVC. Adjust the documentation about it.
> 
> Signed-off-by: Marc-André Lureau 
> ---
>  qapi/char.json | 4 
>  include/chardev/char.h | 3 ---
>  ui/console.c   | 4 ++--
>  ui/gtk.c   | 1 -
>  ui/spice-app.c | 7 ++-
>  5 files changed, 12 insertions(+), 7 deletions(-)
> 
> diff --git a/qapi/char.json b/qapi/char.json
> index 52aaff25eb..7e23fe3180 100644
> --- a/qapi/char.json
> +++ b/qapi/char.json
> @@ -390,6 +390,10 @@
>  #
>  # @rows: console height, in chars
>  #
> +# Note: the options are only effective when using the built-in QEMU 
> graphical VC
> +# (with the SDL display). When the VC is handled by the display backend (with
> +# GTK/VTE, Spice or D-Bus), they are simply ignored.

I don't find this explains the situation very well, I had to look at
the code to understand what's ultimately going on, as I didn't really
know what it meant by "built-in QEMU graphical VC". From the end user's
POV, they're just using '-chardev vc...'.

IIUC, the command line -chardev vc,. will end up instantiating
TYPE_CHARDEV_VC.

We actually then have 4 completely different implementations
of TYPE_CHARDEV_VC, and depending on which display backend
is enabled, a different TYPE_CHARDEV_VC will get registered.

So what your comment is saying is that the width/height/rows/cols
properties will only get honoured if the TYPE_CHARDEV_VC that is
registered, is the one that maps to the SDL display backend.

Wow, is this situation confusing and gross in the code :-(

So for the comment I think we can just cut out a few words to
make it simpler

 # Note: the options are only effective when the SDL graphical
 # display backend is active. They are ignored with the GTK,
 # Spice, VNC and D-Bus display backends.

As a future exercise for anyone motiviated, I would say that
TYPE_CHARDEV_VC ought to be abstract and we then have subclasses
for each of the impls we have that are registered unconditionally
with type_init(), then pick the subclass to instantiate based
on the display backend. That way we can ultimately make the
QAPI schema reflect that we have multiple ChardevVC impls and
only expose the cols/width/etc for the SDL impl.


Anyway, if the comment is simplied/clarified then

 Reviewed-by: Daniel P. Berrangé 
 

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




Re: [PATCH v2 01/14] tcg/loongarch64: Import LSX instructions

2023-09-01 Thread Richard Henderson

On 9/1/23 02:30, Jiajie Chen wrote:

Add opcodes and encoder functions for LSX.

Generated from
https://github.com/jiegec/loongarch-opcodes/tree/qemu-lsx.

Signed-off-by: Jiajie Chen
---
  tcg/loongarch64/tcg-insn-defs.c.inc | 6251 ++-
  1 file changed, 6134 insertions(+), 117 deletions(-)

diff --git a/tcg/loongarch64/tcg-insn-defs.c.inc 
b/tcg/loongarch64/tcg-insn-defs.c.inc
index b5bb0c5e73..ee3b483b02 100644
--- a/tcg/loongarch64/tcg-insn-defs.c.inc
+++ b/tcg/loongarch64/tcg-insn-defs.c.inc
@@ -4,7 +4,7 @@
   *
   * This file is auto-generated by genqemutcgdefs from
   *https://github.com/loongson-community/loongarch-opcodes,
- * from commit 25ca7effe9d88101c1cf96c4005423643386d81f.
+ * from commit 8027da9a8157a8b47fc48ff1def292e09c5668bd.
   * DO NOT EDIT.
   */
  


Acked-by: Richard Henderson 

r~



Re: [PATCH v2 02/14] tcg/loongarch64: Lower basic tcg vec ops to LSX

2023-09-01 Thread Richard Henderson

On 9/1/23 02:30, Jiajie Chen wrote:

LSX support on host cpu is detected via hwcap.

Lower the following ops to LSX:

- dup_vec
- dupi_vec
- dupm_vec
- ld_vec
- st_vec

Signed-off-by: Jiajie Chen
---
  tcg/loongarch64/tcg-target-con-set.h |   2 +
  tcg/loongarch64/tcg-target-con-str.h |   1 +
  tcg/loongarch64/tcg-target.c.inc | 219 ++-
  tcg/loongarch64/tcg-target.h |  38 -
  tcg/loongarch64/tcg-target.opc.h |  12 ++
  5 files changed, 270 insertions(+), 2 deletions(-)
  create mode 100644 tcg/loongarch64/tcg-target.opc.h


Reviewed-by: Richard Henderson 

r~



Re: [PATCH v2 05/19] host-utils: Add muldiv64_round_up

2023-09-01 Thread Richard Henderson

On 9/1/23 04:51, Cédric Le Goater wrote:

Adding more reviewers since this patch is modifying a common service.

Thanks,

C.


On 8/8/23 06:19, Nicholas Piggin wrote:

This will be used for converting time intervals in different base units
to host units, for the purpose of scheduling timers to emulate target
timers. Timers typically must not fire before their requested expiry
time but may fire some time afterward, so rounding up is the right way
to implement these.

Signed-off-by: Nicholas Piggin 
---
  include/qemu/host-utils.h | 21 -
  1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/include/qemu/host-utils.h b/include/qemu/host-utils.h
index 011618373e..e2a50a567f 100644
--- a/include/qemu/host-utils.h
+++ b/include/qemu/host-utils.h
@@ -56,6 +56,11 @@ static inline uint64_t muldiv64(uint64_t a, uint32_t b, 
uint32_t c)
  return (__int128_t)a * b / c;
  }
+static inline uint64_t muldiv64_round_up(uint64_t a, uint32_t b, uint32_t c)
+{
+    return ((__int128_t)a * b + c - 1) / c;
+}
+
  static inline uint64_t divu128(uint64_t *plow, uint64_t *phigh,
 uint64_t divisor)
  {
@@ -83,7 +88,8 @@ void mulu64(uint64_t *plow, uint64_t *phigh, uint64_t a, 
uint64_t b);
  uint64_t divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor);
  int64_t divs128(uint64_t *plow, int64_t *phigh, int64_t divisor);
-static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
+static inline uint64_t __muldiv64(uint64_t a, uint32_t b, uint32_t c,
+  bool round_up)


Perhaps better avoiding the reserved name: muldiv64_internal?

Otherwise,
Reviewed-by: Richard Henderson 


r~



  {
  union {
  uint64_t ll;
@@ -99,12 +105,25 @@ static inline uint64_t muldiv64(uint64_t a, uint32_t b, 
uint32_t c)
  u.ll = a;
  rl = (uint64_t)u.l.low * (uint64_t)b;
+    if (round_up) {
+    rl += c - 1;
+    }
  rh = (uint64_t)u.l.high * (uint64_t)b;
  rh += (rl >> 32);
  res.l.high = rh / c;
  res.l.low = (((rh % c) << 32) + (rl & 0x)) / c;
  return res.ll;
  }
+
+static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
+{
+    return __muldiv64(a, b, c, false);
+}
+
+static inline uint64_t muldiv64_round_up(uint64_t a, uint32_t b, uint32_t c)
+{
+    return __muldiv64(a, b, c, true);
+}
  #endif
  /**








Re: [PATCH v2 4/4] block-coroutine-wrapper: use qemu_get_current_aio_context()

2023-09-01 Thread Kevin Wolf
Am 24.08.2023 um 01:59 hat Stefan Hajnoczi geschrieben:
> Use qemu_get_current_aio_context() in mixed wrappers and coroutine
> wrappers so that code runs in the caller's AioContext instead of moving
> to the BlockDriverState's AioContext. This change is necessary for the
> multi-queue block layer where any thread can call into the block layer.
> 
> Most wrappers are IO_CODE where it's safe to use the current AioContext
> nowadays. BlockDrivers and the core block layer use their own locks and
> no longer depend on the AioContext lock for thread-safety.
> 
> The bdrv_create() wrapper invokes GLOBAL_STATE code. Using the current
> AioContext is safe because this code is only called with the BQL held
> from the main loop thread.
> 
> The output of qemu-iotests 051 is sensitive to event loop activity.
> Update the output because the monitor BH runs at a different time,
> causing prompts to be printed differently in the output.
> 
> Signed-off-by: Stefan Hajnoczi 

The update for 051 is actually missing from this patch, and so the test
fails.

I missed the dependency on your qio_channel series, so 281 ran into an
abort() for me (see below for the stack trace). I expect that the other
series actually fixes this, but this kind of interaction wasn't really
obvious. How did you make sure that there aren't other places that don't
like this change?

Kevin

(gdb) bt
#0  0x7f8ef0d2fe5c in __pthread_kill_implementation () at /lib64/libc.so.6
#1  0x7f8ef0cdfa76 in raise () at /lib64/libc.so.6
#2  0x7f8ef0cc97fc in abort () at /lib64/libc.so.6
#3  0x7f8ef0cc971b in _nl_load_domain.cold () at /lib64/libc.so.6
#4  0x7f8ef0cd8656 in  () at /lib64/libc.so.6
#5  0x55fd19da6af3 in qio_channel_yield (ioc=0x7f8eeb70, 
condition=G_IO_IN) at ../io/channel.c:583
#6  0x55fd19e0382f in nbd_read_eof (bs=0x55fd1b681350, ioc=0x7f8eeb70, 
buffer=0x55fd1b680da0, size=4, errp=0x0) at ../nbd/client.c:1454
#7  0x55fd19e03612 in nbd_receive_reply (bs=0x55fd1b681350, 
ioc=0x7f8eeb70, reply=0x55fd1b680da0, errp=0x0) at ../nbd/client.c:1491
#8  0x55fd19e40575 in nbd_receive_replies (s=0x55fd1b680b00, cookie=1) at 
../block/nbd.c:461
#9  0x55fd19e3fec4 in nbd_co_do_receive_one_chunk
(s=0x55fd1b680b00, cookie=1, only_structured=true, 
request_ret=0x7f8ee8bff91c, qiov=0x7f8ee8bfff10, payload=0x7f8ee8bff9d0, 
errp=0x7f8ee8bff910) at ../block/nbd.c:844
#10 0x55fd19e3fd55 in nbd_co_receive_one_chunk
(s=0x55fd1b680b00, cookie=1, only_structured=true, 
request_ret=0x7f8ee8bff91c, qiov=0x7f8ee8bfff10, reply=0x7f8ee8bff9f0, 
payload=0x7f8ee8bff9d0, errp=0x7f8ee8bff910)
at ../block/nbd.c:925
#11 0x55fd19e3f7b5 in nbd_reply_chunk_iter_receive (s=0x55fd1b680b00, 
iter=0x7f8ee8bff9d8, cookie=1, qiov=0x7f8ee8bfff10, reply=0x7f8ee8bff9f0, 
payload=0x7f8ee8bff9d0)
at ../block/nbd.c:1008
#12 0x55fd19e3ecf7 in nbd_co_receive_cmdread_reply (s=0x55fd1b680b00, 
cookie=1, offset=0, qiov=0x7f8ee8bfff10, request_ret=0x7f8ee8bffad4, 
errp=0x7f8ee8bffac8) at ../block/nbd.c:1074
#13 0x55fd19e3c804 in nbd_client_co_preadv (bs=0x55fd1b681350, offset=0, 
bytes=131072, qiov=0x7f8ee8bfff10, flags=0) at ../block/nbd.c:1258
#14 0x55fd19e33547 in bdrv_driver_preadv (bs=0x55fd1b681350, offset=0, 
bytes=131072, qiov=0x7f8ee8bfff10, qiov_offset=0, flags=0) at ../block/io.c:1005
#15 0x55fd19e2c8bb in bdrv_aligned_preadv (child=0x55fd1c282d90, 
req=0x7f8ee8bffd90, offset=0, bytes=131072, align=1, qiov=0x7f8ee8bfff10, 
qiov_offset=0, flags=0) at ../block/io.c:1398
#16 0x55fd19e2bf7d in bdrv_co_preadv_part (child=0x55fd1c282d90, offset=0, 
bytes=131072, qiov=0x7f8ee8bfff10, qiov_offset=0, flags=0) at ../block/io.c:1815
#17 0x55fd19e176bd in blk_co_do_preadv_part (blk=0x55fd1c269c00, offset=0, 
bytes=131072, qiov=0x7f8ee8bfff10, qiov_offset=0, flags=0) at 
../block/block-backend.c:1344
#18 0x55fd19e17588 in blk_co_preadv (blk=0x55fd1c269c00, offset=0, 
bytes=131072, qiov=0x7f8ee8bfff10, flags=0) at ../block/block-backend.c:1369
#19 0x55fd19e17514 in blk_co_pread (blk=0x55fd1c269c00, offset=0, 
bytes=131072, buf=0x55fd1c16d000, flags=0) at ../block/block-backend.c:1358
#20 0x55fd19ddcc91 in blk_co_pread_entry (opaque=0x7ffc4bbdd9a0) at 
block/block-gen.c:1519
#21 0x55fd19feb2a1 in coroutine_trampoline (i0=460835072, i1=22013) at 
../util/coroutine-ucontext.c:177
#22 0x7f8ef0cf5c20 in __start_context () at /lib64/libc.so.6

io/channel.c:583 is this:

577 void coroutine_fn qio_channel_yield(QIOChannel *ioc,
578 GIOCondition condition)
579 {
580 AioContext *ioc_ctx = ioc->ctx ?: qemu_get_aio_context();
581
582 assert(qemu_in_coroutine());
583 assert(in_aio_context_home_thread(ioc_ctx));
584




Re: [PATCH 42/67] ui/vc: move text console invalidate in helper

2023-09-01 Thread Daniel P . Berrangé
On Wed, Aug 30, 2023 at 01:38:16PM +0400, marcandre.lur...@redhat.com wrote:
> From: Marc-André Lureau 
> 
> This will allow to split the VC code in a separate unit more easily.
> 
> Signed-off-by: Marc-André Lureau 
> ---
>  include/ui/console.h |  1 +
>  ui/console.c | 13 +
>  2 files changed, 10 insertions(+), 4 deletions(-)

Reviewed-by: Daniel P. Berrangé 


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




Re: [PATCH 41/67] ui/console: minor stylistic changes

2023-09-01 Thread Daniel P . Berrangé
On Wed, Aug 30, 2023 at 01:38:15PM +0400, marcandre.lur...@redhat.com wrote:
> From: Marc-André Lureau 
> 
> Signed-off-by: Marc-André Lureau 
> ---
>  ui/console.c | 10 --
>  1 file changed, 4 insertions(+), 6 deletions(-)

Reviewed-by: Daniel P. Berrangé 


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




Re: [PATCH 40/67] ui/vc: skip text console resize when possible

2023-09-01 Thread Daniel P . Berrangé
On Wed, Aug 30, 2023 at 01:38:14PM +0400, marcandre.lur...@redhat.com wrote:
> From: Marc-André Lureau 
> 
> This function is called on invalidate, on each cursor blink.
> 
> Avoid the extra copy when the console size didn't change.
> 
> Signed-off-by: Marc-André Lureau 
> ---
>  ui/console.c | 12 +---
>  1 file changed, 9 insertions(+), 3 deletions(-)

Reviewed-by: Daniel P. Berrangé 


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




Re: [PATCH 39/67] ui/console: fold text_console_update_cursor_timer

2023-09-01 Thread Daniel P . Berrangé
On Wed, Aug 30, 2023 at 01:38:13PM +0400, marcandre.lur...@redhat.com wrote:
> From: Marc-André Lureau 
> 
> Signed-off-by: Marc-André Lureau 
> ---
>  ui/console.c | 10 ++
>  1 file changed, 2 insertions(+), 8 deletions(-)

Reviewed-by: Daniel P. Berrangé 


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




[PATCH v22 06/20] s390x/cpu topology: interception of PTF instruction

2023-09-01 Thread Nina Schoetterl-Glausch
From: Pierre Morel 

When the host supports the CPU topology facility, the PTF
instruction with function code 2 is interpreted by the SIE,
provided that the userland hypervisor activates the interpretation
by using the KVM_CAP_S390_CPU_TOPOLOGY KVM extension.

The PTF instructions with function code 0 and 1 are intercepted
and must be emulated by the userland hypervisor.

During RESET all CPU of the configuration are placed in
horizontal polarity.

Signed-off-by: Pierre Morel 
Reviewed-by: Nina Schoetterl-Glausch 
Reviewed-by: Thomas Huth 
Co-developed-by: Nina Schoetterl-Glausch 
Signed-off-by: Nina Schoetterl-Glausch 
---
 include/hw/s390x/s390-virtio-ccw.h |  6 
 hw/s390x/cpu-topology.c| 55 ++
 target/s390x/kvm/kvm.c | 11 ++
 3 files changed, 72 insertions(+)

diff --git a/include/hw/s390x/s390-virtio-ccw.h 
b/include/hw/s390x/s390-virtio-ccw.h
index 9bba21a916..c1d46e78af 100644
--- a/include/hw/s390x/s390-virtio-ccw.h
+++ b/include/hw/s390x/s390-virtio-ccw.h
@@ -30,6 +30,12 @@ struct S390CcwMachineState {
 uint8_t loadparm[8];
 };
 
+#define S390_PTF_REASON_NONE (0x00 << 8)
+#define S390_PTF_REASON_DONE (0x01 << 8)
+#define S390_PTF_REASON_BUSY (0x02 << 8)
+#define S390_TOPO_FC_MASK 0xffUL
+void s390_handle_ptf(S390CPU *cpu, uint8_t r1, uintptr_t ra);
+
 struct S390CcwMachineClass {
 /*< private >*/
 MachineClass parent_class;
diff --git a/hw/s390x/cpu-topology.c b/hw/s390x/cpu-topology.c
index 3a9fc14a90..b86d582653 100644
--- a/hw/s390x/cpu-topology.c
+++ b/hw/s390x/cpu-topology.c
@@ -90,6 +90,60 @@ static void s390_topology_init(MachineState *ms)
 smp->books * smp->drawers);
 }
 
+/*
+ * s390_handle_ptf:
+ *
+ * @register 1: contains the function code
+ *
+ * Function codes 0 (horizontal) and 1 (vertical) define the CPU
+ * polarization requested by the guest.
+ *
+ * Function code 2 is handling topology changes and is interpreted
+ * by the SIE.
+ */
+void s390_handle_ptf(S390CPU *cpu, uint8_t r1, uintptr_t ra)
+{
+CpuS390Polarization polarization;
+CPUS390XState *env = >env;
+uint64_t reg = env->regs[r1];
+int fc = reg & S390_TOPO_FC_MASK;
+
+if (!s390_has_feat(S390_FEAT_CONFIGURATION_TOPOLOGY)) {
+s390_program_interrupt(env, PGM_OPERATION, ra);
+return;
+}
+
+if (env->psw.mask & PSW_MASK_PSTATE) {
+s390_program_interrupt(env, PGM_PRIVILEGED, ra);
+return;
+}
+
+if (reg & ~S390_TOPO_FC_MASK) {
+s390_program_interrupt(env, PGM_SPECIFICATION, ra);
+return;
+}
+
+polarization = S390_CPU_POLARIZATION_VERTICAL;
+switch (fc) {
+case 0:
+polarization = S390_CPU_POLARIZATION_HORIZONTAL;
+/* fallthrough */
+case 1:
+if (s390_topology.polarization == polarization) {
+env->regs[r1] |= S390_PTF_REASON_DONE;
+setcc(cpu, 2);
+} else {
+s390_topology.polarization = polarization;
+s390_cpu_topology_set_changed(true);
+setcc(cpu, 0);
+}
+break;
+default:
+/* Note that fc == 2 is interpreted by the SIE */
+s390_program_interrupt(env, PGM_SPECIFICATION, ra);
+}
+}
+
 /**
  * s390_topology_reset:
  *
@@ -99,6 +153,7 @@ static void s390_topology_init(MachineState *ms)
 void s390_topology_reset(void)
 {
 s390_cpu_topology_set_changed(false);
+s390_topology.polarization = S390_CPU_POLARIZATION_HORIZONTAL;
 }
 
 /**
diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c
index ee6345ba27..10d66c2b65 100644
--- a/target/s390x/kvm/kvm.c
+++ b/target/s390x/kvm/kvm.c
@@ -86,6 +86,7 @@
 
 #define PRIV_B9_EQBS0x9c
 #define PRIV_B9_CLP 0xa0
+#define PRIV_B9_PTF 0xa2
 #define PRIV_B9_PCISTG  0xd0
 #define PRIV_B9_PCILG   0xd2
 #define PRIV_B9_RPCIT   0xd3
@@ -1457,6 +1458,13 @@ static int kvm_mpcifc_service_call(S390CPU *cpu, struct 
kvm_run *run)
 }
 }
 
+static void kvm_handle_ptf(S390CPU *cpu, struct kvm_run *run)
+{
+uint8_t r1 = (run->s390_sieic.ipb >> 20) & 0x0f;
+
+s390_handle_ptf(cpu, r1, RA_IGNORED);
+}
+
 static int handle_b9(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
 {
 int r = 0;
@@ -1474,6 +1482,9 @@ static int handle_b9(S390CPU *cpu, struct kvm_run *run, 
uint8_t ipa1)
 case PRIV_B9_RPCIT:
 r = kvm_rpcit_service_call(cpu, run);
 break;
+case PRIV_B9_PTF:
+kvm_handle_ptf(cpu, run);
+break;
 case PRIV_B9_EQBS:
 /* just inject exception */
 r = -1;
-- 
2.39.2




Re: [PATCH v5 8/8] migration: Add a wrapper to cleanup migration files

2023-09-01 Thread Peter Xu
On Thu, Aug 31, 2023 at 03:39:16PM -0300, Fabiano Rosas wrote:
> @@ -1166,16 +1183,9 @@ static void migrate_fd_cleanup(MigrationState *s)
>  qemu_mutex_lock_iothread();
>  
>  multifd_save_cleanup();
> -qemu_mutex_lock(>qemu_file_lock);
> -tmp = s->to_dst_file;
> -s->to_dst_file = NULL;
> -qemu_mutex_unlock(>qemu_file_lock);
> -/*
> - * Close the file handle without the lock to make sure the
> - * critical section won't block for long.
> - */
> -migration_ioc_unregister_yank_from_file(tmp);
> -qemu_fclose(tmp);
> +
> +migration_ioc_unregister_yank_from_file(s->to_dst_file);

I think you suggested that we should always take the file lock when
operating on them, so this is slightly going backwards to not hold any lock
when doing it. But doing so in migrate_fd_cleanup() is probably fine (as it
serializes with bql on all the rest qmp commands, neither should migration
thread exist at this point).  Your call; it's still much cleaner.

Reviewed-by: Peter Xu 

-- 
Peter Xu




[PATCH v22 00/20] s390x: CPU Topology

2023-09-01 Thread Nina Schoetterl-Glausch
Changes since v21 (range-diff below):

* fix ordering of entries in topology list
* don't leak topology list on error condition in insert_stsi_15_1_x
* make entitlement, dedication optional in query-cpu-info-fast
* rename query-cpu-polarization to query-s390x-cpu-polarization
* documentation changes
* add tests of guest view to avocado tests
* require KVM in avocado tests
* increase timeout in tests
* bump version in comments documenting availability to 8.2
* rename some symbols
* picked up R-b's (thanks Thomas)
* minor stuff, typos

Implementation discussions
==

CPU models
--

Since the facility 11, S390_FEAT_CONFIGURATION_TOPOLOGY is already
in the CPU model for old QEMU we could not activate it as usual from
KVM but needed a KVM capability: KVM_CAP_S390_CPU_TOPOLOGY.
Checking and enabling this capability enables facility 11,
S390_FEAT_CONFIGURATION_TOPOLOGY.

It is the responsibility of the admin to ensure the same CPU
model for source and target host in a migration.

Migration
-

When the target guest is started, the Multi-processor Topology Change
Report (MTCR) bit is set during the creation of the vCPU by KVM.
We do not need to migrate its state, in the worst case, the target
guest will see the MTCR and actualize its view of the topology
without necessity, but this will be done only one time.

Reset
-

Reseting the topology is done during subsystem reset, the
polarization is reset to horizontal polarization.

Topology attributes
---

The topology attributes are carried by the CPU object and defined
on object creation.
In the case the new attributes, socket, book, drawer, dedicated,
entitlement are not provided QEMU provides defaults values.

- Geometry defaults
  The geometry default are based on the core-id of the core to
  fill the geometry in a monotone way starting with drawer 0,
  book 0, and filling socket 0 with the number of cores per socket,
  then filling socket 1, socket 2 ... etc until the book is complete
  and all books until the first drawer is complete before starting with
  the next drawer.

  This allows to keep existing start scripts and Libvirt existing
  interface until it is extended.

- Modifiers defaults
  Default entitlement is medium
  Default dedication is not dedicated.

- Machine polarization default to horizontal

Dynamic topology modification
-

QAPI interface is extended with:
- a command: 'set-cpu-topology'
- a query: 'query-cpu-polarization'
- a query: extension of qmp 'query-cpus-fast'
- a query: extension of hmp 'hotpluggable-cpus'
- an event: 'CPU_POLARITY_CHANGE'

New command and interface are specified as unstable.

The admin may use query-cpus-fast to verify the topology provided
to the guest and set-cpu-topology to modify it.

The event CPU_POLARITY_CHANGE is sent when the guest successfuly
uses the PTF(2) instruction to request a polarization change.
In that case, the admin is supposed to modify the CPU provisioning
accordingly.

Testing
===

To use the QEMU patches, you will need Linux V6-rc1 or newer,
or use the following Linux mainline patches:

f5ecfee94493 2022-07-20 KVM: s390: resetting the Topology-Change-Report
24fe0195bc19 2022-07-20 KVM: s390: guest support for topology function
0130337ec45b 2022-07-20 KVM: s390: Cleanup ipte lock access and SIIF fac..

Currently this code is for KVM only, I have no idea if it is interesting
to provide a TCG patch. If ever it will be done in another series.

This series provide 12 avocado tests using Fedora-35 kernel and initrd
image.

Documentation
=

To have a better understanding of the S390x CPU Topology and its
implementation in QEMU you can have a look at the documentation in the
last patch of this series.

The admin will want to match the host and the guest topology, taking
into account that the guest does not recognize multithreading.
Consequently, two vCPU assigned to threads of the same real CPU should
preferably be assigned to the same socket of the guest machine.

Previous changes:
Since v20:

- changed name of target/s390/kvm/cpu_topology to
  target/s390/kvm/stsi-topology
  (Thomas, Cedric)

- moved the TLE list head from a global to a local in
  insert_stsi_15_1_x()
  (Nina)

- cleaning and merging some of the avocado tests
  (Nina)

- Several cleanings
  (Cedric, Thomas, Nina)

- moved setting of entitlement and dedicated from disapeared
  cpustate_to_cpuinfo_s390() to new s390_query_cpu_fast()

- small changes to documentation to reflect last changes using
  enum instead of int for polarization.
  0 -> horizontal and 1 -> vertical

Since v19:

- use enum to specify the entitlement
  (Nina)

- Change default entitlement to "auto"

- suppress skip_basis in avocado tests
  (after comment from Cedric)

- Correction of the documentation
  (Cedric)

- better code organization for s390_topology_add_core_to_socket
  and s390_socket_nb
  (Cedric)

- Changed Copyright to respect IBM policy
  (Nina)

- set 

[PATCH v22 03/20] target/s390x/cpu topology: handle STSI(15) and build the SYSIB

2023-09-01 Thread Nina Schoetterl-Glausch
From: Pierre Morel 

On interception of STSI(15.1.x) the System Information Block
(SYSIB) is built from the list of pre-ordered topology entries.

Signed-off-by: Pierre Morel 
Co-developed-by: Nina Schoetterl-Glausch 
Signed-off-by: Nina Schoetterl-Glausch 
---
 MAINTAINERS  |   1 +
 qapi/machine-target.json |  14 ++
 include/hw/s390x/cpu-topology.h  |  25 +++
 include/hw/s390x/sclp.h  |   1 +
 target/s390x/cpu.h   |  76 
 hw/s390x/cpu-topology.c  |   2 +
 target/s390x/kvm/kvm.c   |   5 +-
 target/s390x/kvm/stsi-topology.c | 296 +++
 target/s390x/kvm/meson.build |   3 +-
 9 files changed, 421 insertions(+), 2 deletions(-)
 create mode 100644 target/s390x/kvm/stsi-topology.c

diff --git a/MAINTAINERS b/MAINTAINERS
index b10b83583f..692ce9f121 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1700,6 +1700,7 @@ M: Nina Schoetterl-Glausch 
 S: Supported
 F: include/hw/s390x/cpu-topology.h
 F: hw/s390x/cpu-topology.c
+F: target/s390x/kvm/stsi-topology.c
 
 X86 Machines
 
diff --git a/qapi/machine-target.json b/qapi/machine-target.json
index f0a6b72414..275234a20f 100644
--- a/qapi/machine-target.json
+++ b/qapi/machine-target.json
@@ -361,3 +361,17 @@
'TARGET_MIPS',
'TARGET_LOONGARCH64',
'TARGET_RISCV' ] } }
+
+##
+# @CpuS390Polarization:
+#
+# An enumeration of cpu polarization that can be assumed by a virtual
+# S390 CPU
+#
+# Since: 8.2
+##
+{ 'enum': 'CpuS390Polarization',
+  'prefix': 'S390_CPU_POLARIZATION',
+  'data': [ 'horizontal', 'vertical' ],
+'if': { 'all': [ 'TARGET_S390X' , 'CONFIG_KVM' ] }
+}
diff --git a/include/hw/s390x/cpu-topology.h b/include/hw/s390x/cpu-topology.h
index 97b0af2795..fc15acf297 100644
--- a/include/hw/s390x/cpu-topology.h
+++ b/include/hw/s390x/cpu-topology.h
@@ -15,10 +15,35 @@
 #include "hw/boards.h"
 #include "qapi/qapi-types-machine-target.h"
 
+#define S390_TOPOLOGY_CPU_IFL   0x03
+
+typedef union s390_topology_id {
+uint64_t id;
+struct {
+uint8_t _reserved0;
+uint8_t drawer;
+uint8_t book;
+uint8_t socket;
+uint8_t type;
+uint8_t inv_polarization;
+uint8_t not_dedicated;
+uint8_t origin;
+};
+} s390_topology_id;
+
+typedef struct S390TopologyEntry {
+QTAILQ_ENTRY(S390TopologyEntry) next;
+s390_topology_id id;
+uint64_t mask;
+} S390TopologyEntry;
+
 typedef struct S390Topology {
 uint8_t *cores_per_socket;
+CpuS390Polarization polarization;
 } S390Topology;
 
+typedef QTAILQ_HEAD(, S390TopologyEntry) S390TopologyList;
+
 #ifdef CONFIG_KVM
 bool s390_has_topology(void);
 void s390_topology_setup_cpu(MachineState *ms, S390CPU *cpu, Error **errp);
diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h
index cf1f2efae2..c49051e17e 100644
--- a/include/hw/s390x/sclp.h
+++ b/include/hw/s390x/sclp.h
@@ -112,6 +112,7 @@ typedef struct CPUEntry {
 } QEMU_PACKED CPUEntry;
 
 #define SCLP_READ_SCP_INFO_FIXED_CPU_OFFSET 128
+#define SCLP_READ_SCP_INFO_MNEST2
 typedef struct ReadInfo {
 SCCBHeader h;
 uint16_t rnmax;
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index 7ebd5e05b6..b8a0c02714 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -569,6 +569,29 @@ typedef struct SysIB_322 {
 } SysIB_322;
 QEMU_BUILD_BUG_ON(sizeof(SysIB_322) != 4096);
 
+/*
+ * Topology Magnitude fields (MAG) indicates the maximum number of
+ * topology list entries (TLE) at the corresponding nesting level.
+ */
+#define S390_TOPOLOGY_MAG  6
+#define S390_TOPOLOGY_MAG6 0
+#define S390_TOPOLOGY_MAG5 1
+#define S390_TOPOLOGY_MAG4 2
+#define S390_TOPOLOGY_MAG3 3
+#define S390_TOPOLOGY_MAG2 4
+#define S390_TOPOLOGY_MAG1 5
+/* Configuration topology */
+typedef struct SysIB_151x {
+uint8_t  reserved0[2];
+uint16_t length;
+uint8_t  mag[S390_TOPOLOGY_MAG];
+uint8_t  reserved1;
+uint8_t  mnest;
+uint32_t reserved2;
+char tle[];
+} SysIB_151x;
+QEMU_BUILD_BUG_ON(sizeof(SysIB_151x) != 16);
+
 typedef union SysIB {
 SysIB_111 sysib_111;
 SysIB_121 sysib_121;
@@ -576,9 +599,62 @@ typedef union SysIB {
 SysIB_221 sysib_221;
 SysIB_222 sysib_222;
 SysIB_322 sysib_322;
+SysIB_151x sysib_151x;
 } SysIB;
 QEMU_BUILD_BUG_ON(sizeof(SysIB) != 4096);
 
+/*
+ * CPU Topology List provided by STSI with fc=15 provides a list
+ * of two different Topology List Entries (TLE) types to specify
+ * the topology hierarchy.
+ *
+ * - Container Topology List Entry
+ *   Defines a container to contain other Topology List Entries
+ *   of any type, nested containers or CPU.
+ * - CPU Topology List Entry
+ *   Specifies the CPUs position, type, entitlement and polarization
+ *   of the CPUs contained in the last Container TLE.
+ *
+ * There can be theoretically up to five levels of containers, QEMU
+ * uses only three levels, the drawer's, book's and socket's level.
+ 

[PATCH v22 14/20] tests/avocado: s390x cpu topology core

2023-09-01 Thread Nina Schoetterl-Glausch
From: Pierre Morel 

Introduction of the s390x cpu topology core functions and
basic tests.

We test the correlation between the command line and
the QMP results in query-cpus-fast for various CPU topology.

Signed-off-by: Pierre Morel 
---
 MAINTAINERS|   1 +
 tests/avocado/s390_topology.py | 200 +
 2 files changed, 201 insertions(+)
 create mode 100644 tests/avocado/s390_topology.py

diff --git a/MAINTAINERS b/MAINTAINERS
index 7f2937b0f2..d1b867 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1703,6 +1703,7 @@ F: hw/s390x/cpu-topology.c
 F: target/s390x/kvm/stsi-topology.c
 F: docs/devel/s390-cpu-topology.rst
 F: docs/system/s390x/cpu-topology.rst
+F: tests/avocado/s390_topology.py
 
 X86 Machines
 
diff --git a/tests/avocado/s390_topology.py b/tests/avocado/s390_topology.py
new file mode 100644
index 00..3a54fe2e00
--- /dev/null
+++ b/tests/avocado/s390_topology.py
@@ -0,0 +1,200 @@
+# Functional test that boots a Linux kernel and checks the console
+#
+# Copyright IBM Corp. 2023
+#
+# Author:
+#  Pierre Morel 
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# later.  See the COPYING file in the top-level directory.
+
+import os
+import shutil
+import time
+
+from avocado_qemu import QemuSystemTest
+from avocado_qemu import exec_command
+from avocado_qemu import exec_command_and_wait_for_pattern
+from avocado_qemu import interrupt_interactive_console_until_pattern
+from avocado_qemu import wait_for_console_pattern
+from avocado.utils import process
+from avocado.utils import archive
+
+
+class S390CPUTopology(QemuSystemTest):
+"""
+S390x CPU topology consists of 4 topology layers, from bottom to top,
+the cores, sockets, books and drawers and 2 modifiers attributes,
+the entitlement and the dedication.
+See: docs/system/s390x/cpu-topology.rst.
+
+S390x CPU topology is setup in different ways:
+- implicitly from the '-smp' argument by completing each topology
+  level one after the other beginning with drawer 0, book 0 and
+  socket 0.
+- explicitly from the '-device' argument on the QEMU command line
+- explicitly by hotplug of a new CPU using QMP or HMP
+- it is modified by using QMP 'set-cpu-topology'
+
+The S390x modifier attribute entitlement depends on the machine
+polarization, which can be horizontal or vertical.
+The polarization is changed on a request from the guest.
+"""
+timeout = 90
+
+KERNEL_COMMON_COMMAND_LINE = ('printk.time=0 '
+  'root=/dev/ram '
+  'selinux=0 '
+  'rdinit=/bin/sh')
+
+def wait_until_booted(self):
+wait_for_console_pattern(self, 'no job control',
+ failure_message='Kernel panic - not syncing',
+ vm=None)
+
+def check_topology(self, c, s, b, d, e, t):
+res = self.vm.qmp('query-cpus-fast')
+cpus =  res['return']
+for cpu in cpus:
+core = cpu['props']['core-id']
+socket = cpu['props']['socket-id']
+book = cpu['props']['book-id']
+drawer = cpu['props']['drawer-id']
+entitlement = cpu.get('entitlement')
+dedicated = cpu.get('dedicated')
+if core == c:
+self.assertEqual(drawer, d)
+self.assertEqual(book, b)
+self.assertEqual(socket, s)
+self.assertEqual(entitlement, e)
+self.assertEqual(dedicated, t)
+
+def kernel_init(self):
+"""
+We need a VM that supports CPU topology,
+currently this only the case when using KVM, not TCG.
+We need a kernel supporting the CPU topology.
+We need a minimal root filesystem with a shell.
+"""
+self.require_accelerator("kvm")
+kernel_url = ('https://archives.fedoraproject.org/pub/archive'
+  '/fedora-secondary/releases/35/Server/s390x/os'
+  '/images/kernel.img')
+kernel_hash = '0d1aaaf303f07cf0160c8c48e56fe638'
+kernel_path = self.fetch_asset(kernel_url, algorithm='md5',
+   asset_hash=kernel_hash)
+
+initrd_url = ('https://archives.fedoraproject.org/pub/archive'
+  '/fedora-secondary/releases/35/Server/s390x/os'
+  '/images/initrd.img')
+initrd_hash = 'a122057d95725ac030e2ec51df46e172'
+initrd_path_xz = self.fetch_asset(initrd_url, algorithm='md5',
+  asset_hash=initrd_hash)
+initrd_path = os.path.join(self.workdir, 'initrd-raw.img')
+archive.lzma_uncompress(initrd_path_xz, initrd_path)
+
+self.vm.set_console()
+kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE
+self.vm.add_args('-nographic',
+  

[PATCH v22 16/20] tests/avocado: s390x cpu topology entitlement tests

2023-09-01 Thread Nina Schoetterl-Glausch
From: Pierre Morel 

Test changes in the entitlement from both a guest and a host point of
view, depending on the polarization.

Signed-off-by: Pierre Morel 
Co-developed-by: Nina Schoetterl-Glausch 
Signed-off-by: Nina Schoetterl-Glausch 
---
 tests/avocado/s390_topology.py | 55 ++
 1 file changed, 55 insertions(+)

diff --git a/tests/avocado/s390_topology.py b/tests/avocado/s390_topology.py
index d7ee36cb89..733093723a 100644
--- a/tests/avocado/s390_topology.py
+++ b/tests/avocado/s390_topology.py
@@ -243,3 +243,58 @@ def test_polarization(self):
 res = self.vm.qmp('query-s390x-cpu-polarization')
 self.assertEqual(res['return']['polarization'], 'horizontal')
 self.check_topology(0, 0, 0, 0, 'medium', False)
+
+
+def check_polarization(self, polarization):
+"""
+We need the polarization change to get stabilized in kernel
+before we check it through the sysfs.
+"""
+exec_command_and_wait_for_pattern(self,
+""" sleep 1 ;
+/bin/cat /sys/devices/system/cpu/cpu0/polarization """,
+polarization)
+
+
+def test_entitlement(self):
+"""
+This test verifies that QEMU modifies the entitlement
+after a guest request and that the guest sees the change.
+
+:avocado: tags=arch:s390x
+:avocado: tags=machine:s390-ccw-virtio
+"""
+self.kernel_init()
+self.vm.launch()
+self.wait_until_booted()
+
+self.system_init()
+
+self.check_polarization('horizontal')
+self.check_topology(0, 0, 0, 0, 'medium', False)
+
+self.guest_set_dispatching('1')
+self.check_polarization('vertical:medium')
+self.check_topology(0, 0, 0, 0, 'medium', False)
+
+res = self.vm.qmp('set-cpu-topology',
+  {'core-id': 0, 'entitlement': 'low'})
+self.assertEqual(res['return'], {})
+self.check_polarization('vertical:low')
+self.check_topology(0, 0, 0, 0, 'low', False)
+
+res = self.vm.qmp('set-cpu-topology',
+  {'core-id': 0, 'entitlement': 'medium'})
+self.assertEqual(res['return'], {})
+self.check_polarization('vertical:medium')
+self.check_topology(0, 0, 0, 0, 'medium', False)
+
+res = self.vm.qmp('set-cpu-topology',
+  {'core-id': 0, 'entitlement': 'high'})
+self.assertEqual(res['return'], {})
+self.check_polarization('vertical:high')
+self.check_topology(0, 0, 0, 0, 'high', False)
+
+self.guest_set_dispatching('0');
+self.check_polarization("horizontal")
+self.check_topology(0, 0, 0, 0, 'high', False)
-- 
2.39.2




[PATCH v22 13/20] docs/s390x/cpu topology: document s390x cpu topology

2023-09-01 Thread Nina Schoetterl-Glausch
From: Pierre Morel 

Add some basic examples for the definition of cpu topology
in s390x.

Signed-off-by: Pierre Morel 
Co-developed-by: Nina Schoetterl-Glausch 
Signed-off-by: Nina Schoetterl-Glausch 
---
 MAINTAINERS|   2 +
 docs/devel/index-internals.rst |   1 +
 docs/devel/s390-cpu-topology.rst   | 171 
 docs/system/s390x/cpu-topology.rst | 242 +
 docs/system/target-s390x.rst   |   1 +
 5 files changed, 417 insertions(+)
 create mode 100644 docs/devel/s390-cpu-topology.rst
 create mode 100644 docs/system/s390x/cpu-topology.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 692ce9f121..7f2937b0f2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1701,6 +1701,8 @@ S: Supported
 F: include/hw/s390x/cpu-topology.h
 F: hw/s390x/cpu-topology.c
 F: target/s390x/kvm/stsi-topology.c
+F: docs/devel/s390-cpu-topology.rst
+F: docs/system/s390x/cpu-topology.rst
 
 X86 Machines
 
diff --git a/docs/devel/index-internals.rst b/docs/devel/index-internals.rst
index e1a93df263..6f81df92bc 100644
--- a/docs/devel/index-internals.rst
+++ b/docs/devel/index-internals.rst
@@ -14,6 +14,7 @@ Details about QEMU's various subsystems including how to add 
features to them.
migration
multi-process
reset
+   s390-cpu-topology
s390-dasd-ipl
tracing
vfio-migration
diff --git a/docs/devel/s390-cpu-topology.rst b/docs/devel/s390-cpu-topology.rst
new file mode 100644
index 00..70633f30cb
--- /dev/null
+++ b/docs/devel/s390-cpu-topology.rst
@@ -0,0 +1,171 @@
+QAPI interface for S390 CPU topology
+
+
+The following sections will explain the QAPI interface for S390 CPU topology
+with the help of exemplary output.
+For this, let's assume that QEMU has been started with the following
+command, defining 4 CPUs, where CPU[0] is defined by the -smp argument and will
+have default values:
+
+.. code-block:: bash
+
+ qemu-system-s390x \
+-enable-kvm \
+-cpu z14,ctop=on \
+-smp 1,drawers=3,books=3,sockets=2,cores=2,maxcpus=36 \
+\
+-device z14-s390x-cpu,core-id=19,entitlement=high \
+-device z14-s390x-cpu,core-id=11,entitlement=low \
+-device z14-s390x-cpu,core-id=112,entitlement=high \
+   ...
+
+Additions to query-cpus-fast
+
+
+The command query-cpus-fast allows querying the topology tree and
+modifiers for all configured vCPUs.
+
+.. code-block:: QMP
+
+ { "execute": "query-cpus-fast" }
+ {
+  "return": [
+{
+  "dedicated": false,
+  "thread-id": 536993,
+  "props": {
+"core-id": 0,
+"socket-id": 0,
+"drawer-id": 0,
+"book-id": 0
+  },
+  "cpu-state": "operating",
+  "entitlement": "medium",
+  "qom-path": "/machine/unattached/device[0]",
+  "cpu-index": 0,
+  "target": "s390x"
+},
+{
+  "dedicated": false,
+  "thread-id": 537003,
+  "props": {
+"core-id": 19,
+"socket-id": 1,
+"drawer-id": 0,
+"book-id": 2
+  },
+  "cpu-state": "operating",
+  "entitlement": "high",
+  "qom-path": "/machine/peripheral-anon/device[0]",
+  "cpu-index": 19,
+  "target": "s390x"
+},
+{
+  "dedicated": false,
+  "thread-id": 537004,
+  "props": {
+"core-id": 11,
+"socket-id": 1,
+"drawer-id": 0,
+"book-id": 1
+  },
+  "cpu-state": "operating",
+  "entitlement": "low",
+  "qom-path": "/machine/peripheral-anon/device[1]",
+  "cpu-index": 11,
+  "target": "s390x"
+},
+{
+  "dedicated": true,
+  "thread-id": 537005,
+  "props": {
+"core-id": 112,
+"socket-id": 0,
+"drawer-id": 3,
+"book-id": 2
+  },
+  "cpu-state": "operating",
+  "entitlement": "high",
+  "qom-path": "/machine/peripheral-anon/device[2]",
+  "cpu-index": 112,
+  "target": "s390x"
+}
+  ]
+ }
+
+
+QAPI command: set-cpu-topology
+--
+
+The command set-cpu-topology allows modifying the topology tree
+or the topology modifiers of a vCPU in the configuration.
+
+.. code-block:: QMP
+
+{ "execute": "set-cpu-topology",
+  "arguments": {
+ "core-id": 11,
+ "socket-id": 0,
+ "book-id": 0,
+ "drawer-id": 0,
+ "entitlement": "low",
+ "dedicated": false
+  }
+}
+{"return": {}}
+
+The core-id parameter is the only mandatory parameter and every
+unspecified parameter keeps its previous value.
+
+QAPI event CPU_POLARIZATION_CHANGE
+--
+
+When a guest requests a modification of the polarization,
+QEMU sends a CPU_POLARIZATION_CHANGE event.
+
+When requesting the change, the guest only specifies horizontal or
+vertical polarization.
+It is the job of the entity administrating QEMU to set the dedication and fine
+grained vertical entitlement in response to this event.
+
+Note that a 

[PATCH v22 11/20] qapi/s390x/cpu topology: CPU_POLARIZATION_CHANGE qapi event

2023-09-01 Thread Nina Schoetterl-Glausch
From: Pierre Morel 

When the guest asks to change the polarization this change
is forwarded to the upper layer using QAPI.
The upper layer is supposed to take according decisions concerning
CPU provisioning.

Signed-off-by: Pierre Morel 
Reviewed-by: Thomas Huth 
Reviewed-by: Nina Schoetterl-Glausch 
Co-developed-by: Nina Schoetterl-Glausch 
Signed-off-by: Nina Schoetterl-Glausch 
---
 qapi/machine-target.json | 33 +
 hw/s390x/cpu-topology.c  |  2 ++
 2 files changed, 35 insertions(+)

diff --git a/qapi/machine-target.json b/qapi/machine-target.json
index 1e7f512477..5c7a34c25f 100644
--- a/qapi/machine-target.json
+++ b/qapi/machine-target.json
@@ -412,3 +412,36 @@
   'features': [ 'unstable' ],
   'if': { 'all': [ 'TARGET_S390X' , 'CONFIG_KVM' ] }
 }
+
+##
+# @CPU_POLARIZATION_CHANGE:
+#
+# Emitted when the guest asks to change the polarization.
+#
+# @polarization: polarization specified by the guest
+#
+# Features:
+# @unstable: This command may still be modified.
+#
+# The guest can tell the host (via the PTF instruction) whether the
+# CPUs should be provisioned using horizontal or vertical polarization.
+#
+# On horizontal polarization the host is expected to provision all vCPUs
+# equally.
+# On vertical polarization the host can provision each vCPU differently.
+# The guest will get information on the details of the provisioning
+# the next time it uses the STSI(15) instruction.
+#
+# Since: 8.2
+#
+# Example:
+#
+# <- { "event": "CPU_POLARIZATION_CHANGE",
+#  "data": { "polarization": "horizontal" },
+#  "timestamp": { "seconds": 1401385907, "microseconds": 422329 } }
+##
+{ 'event': 'CPU_POLARIZATION_CHANGE',
+  'data': { 'polarization': 'CpuS390Polarization' },
+  'features': [ 'unstable' ],
+  'if': { 'all': [ 'TARGET_S390X', 'CONFIG_KVM' ] }
+}
diff --git a/hw/s390x/cpu-topology.c b/hw/s390x/cpu-topology.c
index c828538f2a..92513cb027 100644
--- a/hw/s390x/cpu-topology.c
+++ b/hw/s390x/cpu-topology.c
@@ -24,6 +24,7 @@
 #include "hw/s390x/s390-virtio-ccw.h"
 #include "hw/s390x/cpu-topology.h"
 #include "qapi/qapi-commands-machine-target.h"
+#include "qapi/qapi-events-machine-target.h"
 
 /*
  * s390_topology is used to keep the topology information.
@@ -136,6 +137,7 @@ void s390_handle_ptf(S390CPU *cpu, uint8_t r1, uintptr_t ra)
 } else {
 s390_topology.polarization = polarization;
 s390_cpu_topology_set_changed(true);
+qapi_event_send_cpu_polarization_change(polarization);
 setcc(cpu, 0);
 }
 break;
-- 
2.39.2




[PATCH v22 17/20] tests/avocado: s390x cpu topology test dedicated CPU

2023-09-01 Thread Nina Schoetterl-Glausch
From: Pierre Morel 

A dedicated CPU in vertical polarization can only have
a high entitlement.
Let's check this from both host and guest point of view.

Signed-off-by: Pierre Morel 
Co-developed-by: Nina Schoetterl-Glausch 
Signed-off-by: Nina Schoetterl-Glausch 
---
 tests/avocado/s390_topology.py | 33 +
 1 file changed, 33 insertions(+)

diff --git a/tests/avocado/s390_topology.py b/tests/avocado/s390_topology.py
index 733093723a..3b3902d646 100644
--- a/tests/avocado/s390_topology.py
+++ b/tests/avocado/s390_topology.py
@@ -298,3 +298,36 @@ def test_entitlement(self):
 self.guest_set_dispatching('0');
 self.check_polarization("horizontal")
 self.check_topology(0, 0, 0, 0, 'high', False)
+
+
+def test_dedicated(self):
+"""
+This test verifies that QEMU adjusts the entitlement correctly when a
+CPU is made dedicated.
+QEMU retains the entitlement value when horizontal polarization is in 
effect.
+For the guest, the field shows the effective value of the entitlement.
+
+:avocado: tags=arch:s390x
+:avocado: tags=machine:s390-ccw-virtio
+"""
+self.kernel_init()
+self.vm.launch()
+self.wait_until_booted()
+
+self.system_init()
+
+self.check_polarization("horizontal")
+
+res = self.vm.qmp('set-cpu-topology',
+  {'core-id': 0, 'dedicated': True})
+self.assertEqual(res['return'], {})
+self.check_topology(0, 0, 0, 0, 'high', True)
+self.check_polarization("horizontal")
+
+self.guest_set_dispatching('1');
+self.check_topology(0, 0, 0, 0, 'high', True)
+self.check_polarization("vertical:high")
+
+self.guest_set_dispatching('0');
+self.check_topology(0, 0, 0, 0, 'high', True)
+self.check_polarization("horizontal")
-- 
2.39.2




[PATCH v22 09/20] machine: adding s390 topology to query-cpu-fast

2023-09-01 Thread Nina Schoetterl-Glausch
From: Pierre Morel 

S390x provides two more topology attributes, entitlement and dedication.

Let's add these CPU attributes to the QAPI command query-cpu-fast.

Signed-off-by: Pierre Morel 
Reviewed-by: Nina Schoetterl-Glausch 
Co-developed-by: Nina Schoetterl-Glausch 
Signed-off-by: Nina Schoetterl-Glausch 
---
 qapi/machine.json  | 9 -
 target/s390x/cpu.c | 9 +
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/qapi/machine.json b/qapi/machine.json
index 54f99f4ac1..eba1f5c363 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -56,10 +56,17 @@
 # Additional information about a virtual S390 CPU
 #
 # @cpu-state: the virtual CPU's state
+# @dedicated: the virtual CPU's dedication (since 8.2)
+# @entitlement: the virtual CPU's entitlement (since 8.2)
 #
 # Since: 2.12
 ##
-{ 'struct': 'CpuInfoS390', 'data': { 'cpu-state': 'CpuS390State' } }
+{ 'struct': 'CpuInfoS390',
+  'data': { 'cpu-state': 'CpuS390State',
+'*dedicated': 'bool',
+'*entitlement': 'CpuS390Entitlement'
+  }
+}
 
 ##
 # @CpuInfoFast:
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index 74405beb51..5967e34a85 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -38,6 +38,7 @@
 #ifndef CONFIG_USER_ONLY
 #include "sysemu/reset.h"
 #endif
+#include "hw/s390x/cpu-topology.h"
 
 #define CR0_RESET   0xE0UL
 #define CR14_RESET  0xC200UL;
@@ -146,6 +147,14 @@ static void s390_query_cpu_fast(CPUState *cpu, CpuInfoFast 
*value)
 S390CPU *s390_cpu = S390_CPU(cpu);
 
 value->u.s390x.cpu_state = s390_cpu->env.cpu_state;
+#if !defined(CONFIG_USER_ONLY)
+if (s390_has_topology()) {
+value->u.s390x.has_dedicated = true;
+value->u.s390x.dedicated = s390_cpu->env.dedicated;
+value->u.s390x.has_entitlement = true;
+value->u.s390x.entitlement = s390_cpu->env.entitlement;
+}
+#endif
 }
 
 /* S390CPUClass::reset() */
-- 
2.39.2




  1   2   3   >