RE: [PATCH v2 3/3] hw: Set virtio-iommu aw-bits default value on pc_q35_9.0 and arm virt

2024-02-01 Thread Duan, Zhenzhong
Hi Eric,

>-Original Message-
>From: Eric Auger 
>pc_q35_9.0 and arm virt
>
>Currently the default input range can extend to 64 bits. On x86,
>when the virtio-iommu protects vfio devices, the physical iommu
>may support only 39 bits. Let's set the default to 39, as done
>for the intel-iommu. On ARM we set 48b as a default (matching
>SMMUv3 SMMU_IDR5.VAX == 0).
>
>We use hw_compat_8_2 to handle the compatibility for machines
>before 9.0 which used to have a virtio-iommu default input range
>of 64 bits.
>
>Of course if aw-bits is set from the command line, the default
>is overriden.
>
>Signed-off-by: Eric Auger 
>
>---
>
>v1 -> v2:
>- set aw-bits to 48b on ARM
>- use hw_compat_8_2 to handle the compat for older machines
>  which used 64b as a default
>---
> hw/arm/virt.c| 6 ++
> hw/core/machine.c| 5 -
> hw/i386/pc.c | 6 ++
> hw/virtio/virtio-iommu.c | 2 +-
> 4 files changed, 17 insertions(+), 2 deletions(-)
>
>diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>index e6ead2c5c8..56539f2fc5 100644
>--- a/hw/arm/virt.c
>+++ b/hw/arm/virt.c
>@@ -2718,10 +2718,16 @@ static void
>virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
> } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) {
> virtio_md_pci_pre_plug(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev),
>errp);
> } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) {
>+uint8_t aw_bits = object_property_get_uint(OBJECT(dev),
>+   "aw-bits", NULL);
> hwaddr db_start = 0, db_end = 0;
> QList *reserved_regions;
> char *resv_prop_str;
>
>+if (!aw_bits) {
>+qdev_prop_set_uint8(dev, "aw-bits", 48);
>+}
>+
> if (vms->iommu != VIRT_IOMMU_NONE) {
> error_setg(errp, "virt machine does not support multiple IOMMUs");
> return;
>diff --git a/hw/core/machine.c b/hw/core/machine.c
>index fb5afdcae4..70ac96954c 100644
>--- a/hw/core/machine.c
>+++ b/hw/core/machine.c
>@@ -30,9 +30,12 @@
> #include "exec/confidential-guest-support.h"
> #include "hw/virtio/virtio-pci.h"
> #include "hw/virtio/virtio-net.h"
>+#include "hw/virtio/virtio-iommu.h"
> #include "audio/audio.h"
>
>-GlobalProperty hw_compat_8_2[] = {};
>+GlobalProperty hw_compat_8_2[] = {
>+{ TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "64" },
>+};
> const size_t hw_compat_8_2_len = G_N_ELEMENTS(hw_compat_8_2);
>
> GlobalProperty hw_compat_8_1[] = {
>diff --git a/hw/i386/pc.c b/hw/i386/pc.c
>index 803244e5cc..0e2bcb4840 100644
>--- a/hw/i386/pc.c
>+++ b/hw/i386/pc.c
>@@ -1458,6 +1458,8 @@ static void
>pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
> } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) {
> virtio_md_pci_pre_plug(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev),
>errp);
> } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) {
>+uint8_t aw_bits = object_property_get_uint(OBJECT(dev),
>+   "aw-bits", NULL);
> /* Declare the APIC range as the reserved MSI region */
> char *resv_prop_str = g_strdup_printf("0xfee0:0xfeef:%d",
>   VIRTIO_IOMMU_RESV_MEM_T_MSI);
>@@ -1466,6 +1468,10 @@ static void
>pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
> qlist_append_str(reserved_regions, resv_prop_str);
> qdev_prop_set_array(dev, "reserved-regions", reserved_regions);
>
>+if (!aw_bits) {
>+qdev_prop_set_uint8(dev, "aw-bits", 39);
>+}
>+
> g_free(resv_prop_str);
> }
>
>diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
>index 7870bdbeee..c468e9b13b 100644
>--- a/hw/virtio/virtio-iommu.c
>+++ b/hw/virtio/virtio-iommu.c
>@@ -1529,7 +1529,7 @@ static Property virtio_iommu_properties[] = {
> DEFINE_PROP_LINK("primary-bus", VirtIOIOMMU, primary_bus,
>  TYPE_PCI_BUS, PCIBus *),
> DEFINE_PROP_BOOL("boot-bypass", VirtIOIOMMU, boot_bypass, true),
>-DEFINE_PROP_UINT8("aw-bits", VirtIOIOMMU, aw_bits, 64),
>+DEFINE_PROP_UINT8("aw-bits", VirtIOIOMMU, aw_bits, 0),

Not clear if virtio-iommu support other archs besides x86 and arm.
It looks on those archs, aw_bits is default 0 on machine 9.0 above
and will fails the check in realize?

Thanks
Zhenzhong

> DEFINE_PROP_END_OF_LIST(),
> };
>
>--
>2.41.0




RE: [PATCH v2 2/3] virtio-iommu: Trace domain range limits as unsigned int

2024-02-01 Thread Duan, Zhenzhong



>-Original Message-
>From: Eric Auger 
>Subject: [PATCH v2 2/3] virtio-iommu: Trace domain range limits as
>unsigned int
>
>Use %u format to trace domain_range limits.
>
>Signed-off-by: Eric Auger 

Reviewed-by: Zhenzhong Duan 

Thanks
Zhenzhong

>---
> hw/virtio/trace-events | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
>diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
>index 77905d1994..2350849fbd 100644
>--- a/hw/virtio/trace-events
>+++ b/hw/virtio/trace-events
>@@ -111,7 +111,7 @@ virtio_iommu_device_reset(void) "reset!"
> virtio_iommu_system_reset(void) "system reset!"
> virtio_iommu_get_features(uint64_t features) "device supports
>features=0x%"PRIx64
> virtio_iommu_device_status(uint8_t status) "driver status = %d"
>-virtio_iommu_get_config(uint64_t page_size_mask, uint64_t start,
>uint64_t end, uint32_t domain_start, uint32_t domain_end, uint32_t
>probe_size, uint8_t bypass) "page_size_mask=0x%"PRIx64" input range
>start=0x%"PRIx64" input range end=0x%"PRIx64" domain range start=%d
>domain range end=%d probe_size=0x%x bypass=0x%x"
>+virtio_iommu_get_config(uint64_t page_size_mask, uint64_t start,
>uint64_t end, uint32_t domain_start, uint32_t domain_end, uint32_t
>probe_size, uint8_t bypass) "page_size_mask=0x%"PRIx64" input range
>start=0x%"PRIx64" input range end=0x%"PRIx64" domain range start=%u
>domain range end=%u probe_size=0x%x bypass=0x%x"
> virtio_iommu_set_config(uint8_t bypass) "bypass=0x%x"
> virtio_iommu_attach(uint32_t domain_id, uint32_t ep_id) "domain=%d
>endpoint=%d"
> virtio_iommu_detach(uint32_t domain_id, uint32_t ep_id) "domain=%d
>endpoint=%d"
>--
>2.41.0




RE: [PATCH v2 1/3] virtio-iommu: Add an option to define the input range width

2024-02-01 Thread Duan, Zhenzhong



>-Original Message-
>From: Eric Auger 
>Subject: [PATCH v2 1/3] virtio-iommu: Add an option to define the input
>range width
>
>aw-bits is a new option that allows to set the bit width of
>the input address range. This value will be used as a default for
>the device config input_range.end. By default it is set to 64 bits
>which is the current value.
>
>Signed-off-by: Eric Auger 

Reviewed-by: Zhenzhong Duan 

Thanks
Zhenzhong

>
>---
>
>v1 -> v2:
>- Check the aw-bits value is within [32,64]
>---
> include/hw/virtio/virtio-iommu.h | 1 +
> hw/virtio/virtio-iommu.c | 7 ++-
> 2 files changed, 7 insertions(+), 1 deletion(-)
>
>diff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-
>iommu.h
>index 781ebaea8f..5fbe4677c2 100644
>--- a/include/hw/virtio/virtio-iommu.h
>+++ b/include/hw/virtio/virtio-iommu.h
>@@ -66,6 +66,7 @@ struct VirtIOIOMMU {
> bool boot_bypass;
> Notifier machine_done;
> bool granule_frozen;
>+uint8_t aw_bits;
> };
>
> #endif
>diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
>index ec2ba11d1d..7870bdbeee 100644
>--- a/hw/virtio/virtio-iommu.c
>+++ b/hw/virtio/virtio-iommu.c
>@@ -1314,7 +1314,11 @@ static void
>virtio_iommu_device_realize(DeviceState *dev, Error **errp)
>  */
> s->config.bypass = s->boot_bypass;
> s->config.page_size_mask = qemu_real_host_page_mask();
>-s->config.input_range.end = UINT64_MAX;
>+if (s->aw_bits < 32 || s->aw_bits > 64) {
>+error_setg(errp, "aw-bits must be within [32,64]");
>+}
>+s->config.input_range.end =
>+s->aw_bits == 64 ? UINT64_MAX : BIT_ULL(s->aw_bits) - 1;
> s->config.domain_range.end = UINT32_MAX;
> s->config.probe_size = VIOMMU_PROBE_SIZE;
>
>@@ -1525,6 +1529,7 @@ static Property virtio_iommu_properties[] = {
> DEFINE_PROP_LINK("primary-bus", VirtIOIOMMU, primary_bus,
>  TYPE_PCI_BUS, PCIBus *),
> DEFINE_PROP_BOOL("boot-bypass", VirtIOIOMMU, boot_bypass, true),
>+DEFINE_PROP_UINT8("aw-bits", VirtIOIOMMU, aw_bits, 64),
> DEFINE_PROP_END_OF_LIST(),
> };
>
>--
>2.41.0




[PULL 08/57] target/cris: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/cris/cpu.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/target/cris/cpu.c b/target/cris/cpu.c
index 6349148b65..163fb05d58 100644
--- a/target/cris/cpu.c
+++ b/target/cris/cpu.c
@@ -56,6 +56,11 @@ static bool cris_cpu_has_work(CPUState *cs)
 return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
 }
 
+static int cris_cpu_mmu_index(CPUState *cs, bool ifetch)
+{
+return !!(cpu_env(cs)->pregs[PR_CCS] & U_FLAG);
+}
+
 static void cris_cpu_reset_hold(Object *obj)
 {
 CPUState *s = CPU(obj);
@@ -274,6 +279,7 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
 
 cc->class_by_name = cris_cpu_class_by_name;
 cc->has_work = cris_cpu_has_work;
+cc->mmu_index = cris_cpu_mmu_index;
 cc->dump_state = cris_cpu_dump_state;
 cc->set_pc = cris_cpu_set_pc;
 cc->get_pc = cris_cpu_get_pc;
-- 
2.34.1




[PULL 43/57] target/sparc: Use i128 for FqTOs, FqTOi

2024-02-01 Thread Richard Henderson
Signed-off-by: Richard Henderson 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-9-richard.hender...@linaro.org>
---
 target/sparc/helper.h | 4 ++--
 target/sparc/fop_helper.c | 8 
 target/sparc/translate.c  | 7 ---
 3 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index 0a030fc908..e770107eb0 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -98,13 +98,13 @@ DEF_HELPER_FLAGS_2(fxtoq, TCG_CALL_NO_RWG, void, env, s64)
 #endif
 DEF_HELPER_FLAGS_2(fdtos, TCG_CALL_NO_RWG, f32, env, f64)
 DEF_HELPER_FLAGS_2(fstod, TCG_CALL_NO_RWG, f64, env, f32)
-DEF_HELPER_FLAGS_1(fqtos, TCG_CALL_NO_RWG, f32, env)
+DEF_HELPER_FLAGS_2(fqtos, TCG_CALL_NO_RWG, f32, env, i128)
 DEF_HELPER_FLAGS_2(fstoq, TCG_CALL_NO_RWG, void, env, f32)
 DEF_HELPER_FLAGS_1(fqtod, TCG_CALL_NO_RWG, f64, env)
 DEF_HELPER_FLAGS_2(fdtoq, TCG_CALL_NO_RWG, void, env, f64)
 DEF_HELPER_FLAGS_2(fstoi, TCG_CALL_NO_RWG, s32, env, f32)
 DEF_HELPER_FLAGS_2(fdtoi, TCG_CALL_NO_RWG, s32, env, f64)
-DEF_HELPER_FLAGS_1(fqtoi, TCG_CALL_NO_RWG, s32, env)
+DEF_HELPER_FLAGS_2(fqtoi, TCG_CALL_NO_RWG, s32, env, i128)
 #ifdef TARGET_SPARC64
 DEF_HELPER_FLAGS_2(fstox, TCG_CALL_NO_RWG, s64, env, f32)
 DEF_HELPER_FLAGS_2(fdtox, TCG_CALL_NO_RWG, s64, env, f64)
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
index ceb64d802f..657a14575d 100644
--- a/target/sparc/fop_helper.c
+++ b/target/sparc/fop_helper.c
@@ -180,9 +180,9 @@ float64 helper_fstod(CPUSPARCState *env, float32 src)
 return float32_to_float64(src, >fp_status);
 }
 
-float32 helper_fqtos(CPUSPARCState *env)
+float32 helper_fqtos(CPUSPARCState *env, Int128 src)
 {
-return float128_to_float32(QT1, >fp_status);
+return float128_to_float32(f128_in(src), >fp_status);
 }
 
 void helper_fstoq(CPUSPARCState *env, float32 src)
@@ -211,9 +211,9 @@ int32_t helper_fdtoi(CPUSPARCState *env, float64 src)
 return float64_to_int32_round_to_zero(src, >fp_status);
 }
 
-int32_t helper_fqtoi(CPUSPARCState *env)
+int32_t helper_fqtoi(CPUSPARCState *env, Int128 src)
 {
-return float128_to_int32_round_to_zero(QT1, >fp_status);
+return float128_to_int32_round_to_zero(f128_in(src), >fp_status);
 }
 
 #ifdef TARGET_SPARC64
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index 96aa7ed235..f70efb29a1 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -4692,8 +4692,9 @@ static bool do_env_qq(DisasContext *dc, arg_r_r *a,
 TRANS(FSQRTq, ALL, do_env_qq, a, gen_helper_fsqrtq)
 
 static bool do_env_fq(DisasContext *dc, arg_r_r *a,
-  void (*func)(TCGv_i32, TCGv_env))
+  void (*func)(TCGv_i32, TCGv_env, TCGv_i128))
 {
+TCGv_i128 src;
 TCGv_i32 dst;
 
 if (gen_trap_ifnofpu(dc)) {
@@ -4704,9 +4705,9 @@ static bool do_env_fq(DisasContext *dc, arg_r_r *a,
 }
 
 gen_op_clear_ieee_excp_and_FTT();
-gen_op_load_fpr_QT1(QFPREG(a->rs));
+src = gen_load_fpr_Q(dc, a->rs);
 dst = tcg_temp_new_i32();
-func(dst, tcg_env);
+func(dst, tcg_env, src);
 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
 gen_store_fpr_F(dc, a->rd, dst);
 return advance_pc(dc);
-- 
2.34.1




[PULL 48/57] target/sparc: Use i128 for Fdmulq

2024-02-01 Thread Richard Henderson
Signed-off-by: Richard Henderson 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-14-richard.hender...@linaro.org>
---
 target/sparc/helper.h |  2 +-
 target/sparc/fop_helper.c |  8 
 target/sparc/translate.c  | 15 ---
 3 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index 20f67f89b0..f7aeb31169 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -84,7 +84,7 @@ DEF_HELPER_FLAGS_3(fmuls, TCG_CALL_NO_RWG, f32, env, f32, f32)
 DEF_HELPER_FLAGS_3(fdivs, TCG_CALL_NO_RWG, f32, env, f32, f32)
 
 DEF_HELPER_FLAGS_3(fsmuld, TCG_CALL_NO_RWG, f64, env, f32, f32)
-DEF_HELPER_FLAGS_3(fdmulq, TCG_CALL_NO_RWG, void, env, f64, f64)
+DEF_HELPER_FLAGS_3(fdmulq, TCG_CALL_NO_RWG, i128, env, f64, f64)
 
 DEF_HELPER_FLAGS_2(fitod, TCG_CALL_NO_RWG_SE, f64, env, s32)
 DEF_HELPER_FLAGS_2(fitoq, TCG_CALL_NO_RWG, i128, env, s32)
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
index 9a0110e201..cd9b212597 100644
--- a/target/sparc/fop_helper.c
+++ b/target/sparc/fop_helper.c
@@ -129,11 +129,11 @@ float64 helper_fsmuld(CPUSPARCState *env, float32 src1, 
float32 src2)
>fp_status);
 }
 
-void helper_fdmulq(CPUSPARCState *env, float64 src1, float64 src2)
+Int128 helper_fdmulq(CPUSPARCState *env, float64 src1, float64 src2)
 {
-QT0 = float128_mul(float64_to_float128(src1, >fp_status),
-   float64_to_float128(src2, >fp_status),
-   >fp_status);
+return f128_ret(float128_mul(float64_to_float128(src1, >fp_status),
+ float64_to_float128(src2, >fp_status),
+ >fp_status));
 }
 
 /* Integer to float conversion.  */
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index d478a2fcd0..d12de5ae5c 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -276,14 +276,6 @@ static void gen_store_fpr_Q(DisasContext *dc, unsigned int 
dst, TCGv_i128 v)
 gen_update_fprs_dirty(dc, dst);
 }
 
-static void gen_op_store_QT0_fpr(unsigned int dst)
-{
-tcg_gen_ld_i64(cpu_fpr[dst / 2], tcg_env, offsetof(CPUSPARCState, qt0) +
-   offsetof(CPU_QuadU, ll.upper));
-tcg_gen_ld_i64(cpu_fpr[dst/2 + 1], tcg_env, offsetof(CPUSPARCState, qt0) +
-   offsetof(CPU_QuadU, ll.lower));
-}
-
 /* moves */
 #ifdef CONFIG_USER_ONLY
 #define supervisor(dc) 0
@@ -4992,6 +4984,7 @@ TRANS(FDIVq, ALL, do_env_qqq, a, gen_helper_fdivq)
 static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a)
 {
 TCGv_i64 src1, src2;
+TCGv_i128 dst;
 
 if (gen_trap_ifnofpu(dc)) {
 return true;
@@ -5003,10 +4996,10 @@ static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a)
 gen_op_clear_ieee_excp_and_FTT();
 src1 = gen_load_fpr_D(dc, a->rs1);
 src2 = gen_load_fpr_D(dc, a->rs2);
-gen_helper_fdmulq(tcg_env, src1, src2);
+dst = tcg_temp_new_i128();
+gen_helper_fdmulq(dst, tcg_env, src1, src2);
 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
-gen_op_store_QT0_fpr(QFPREG(a->rd));
-gen_update_fprs_dirty(dc, QFPREG(a->rd));
+gen_store_fpr_Q(dc, a->rd, dst);
 return advance_pc(dc);
 }
 
-- 
2.34.1




[PULL 49/57] target/sparc: Remove qt0, qt1 temporaries

2024-02-01 Thread Richard Henderson
These are no longer used for passing data to/from helpers.

Signed-off-by: Richard Henderson 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-15-richard.hender...@linaro.org>
---
 target/sparc/cpu.h | 2 --
 target/sparc/fop_helper.c  | 3 ---
 target/sparc/ldst_helper.c | 3 ---
 3 files changed, 8 deletions(-)

diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index 1e076f6355..75c46e2736 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -509,8 +509,6 @@ struct CPUArchState {
 uint64_t mmubpregs[4];
 uint64_t prom_addr;
 #endif
-/* temporary float registers */
-float128 qt0, qt1;
 float_status fp_status;
 #if defined(TARGET_SPARC64)
 #define MAXTL_MAX 8
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
index cd9b212597..7353a61237 100644
--- a/target/sparc/fop_helper.c
+++ b/target/sparc/fop_helper.c
@@ -23,9 +23,6 @@
 #include "exec/helper-proto.h"
 #include "fpu/softfloat.h"
 
-#define QT0 (env->qt0)
-#define QT1 (env->qt1)
-
 static inline float128 f128_in(Int128 i)
 {
 union {
diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c
index 52aa6c631b..1ecd58e8ff 100644
--- a/target/sparc/ldst_helper.c
+++ b/target/sparc/ldst_helper.c
@@ -66,9 +66,6 @@
 #endif
 #endif
 
-#define QT0 (env->qt0)
-#define QT1 (env->qt1)
-
 #if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
 /* Calculates TSB pointer value for fault page size
  * UltraSPARC IIi has fixed sizes (8k or 64k) for the page pointers
-- 
2.34.1




[PATCH] linux-user/aarch64: Add padding before __kernel_rt_sigreturn

2024-02-01 Thread Richard Henderson
Without this padding, an unwind through the signal handler
will pick up the unwind info for the preceding syscall.

This fixes gcc's 30_threads/thread/native_handle/cancel.cc.

Cc: qemu-sta...@nongnu.org
Fixes: ee95fae075c6 ("linux-user/aarch64: Add vdso")
Resolves: https://linaro.atlassian.net/browse/GNU-974
Signed-off-by: Richard Henderson 
---
 linux-user/aarch64/vdso-be.so | Bin 3216 -> 3224 bytes
 linux-user/aarch64/vdso-le.so | Bin 3216 -> 3224 bytes
 linux-user/aarch64/vdso.S |   4 
 3 files changed, 4 insertions(+)

diff --git a/linux-user/aarch64/vdso-be.so b/linux-user/aarch64/vdso-be.so
index 
6084f3d1a701316004894fcdd739c4e1e0463b68..808206ade824b09d786f6cc34f7cddf80b63130e
 100755
GIT binary patch
delta 121
zcmbOrIYV-SKI4pu2Kk&{7{Gw#%fuBAMC1c?^>~k}v|avdxNjSSLfftVb3bgJ!|2S&
z_-6A1CJrVZc?IUH8G;R$7#SF@Om<{a*v!K!^~TWO|cva$K*Om;sOMw`hy
ZxXl@VO#Z-a#EKC)of1

delta 116
zcmbOsIYDxQKI4Rm2Kk{Gw#!^9O2L>8U?-5V_M@!kH(Sx4vJn|*ujLPgija~Pc&
z8DDIEz{J5c`3;N8W)W6tCdL<&4cM*OEF8_CVnO!c?IUH8G;R$7#SF@Om<{a*v!K!!o>JyvLd?^n`3BUW_royOm=q`Mw`hS
dxy>1WOn%92lgFM@hy!9z%j7~Xc>tTxDQW-!

delta 108
zcmbOsIYDxQ2IGW@n)#d`SQx

[PULL 37/57] target/sparc: Use tcg_gen_qemu_{ld, st}_i128 for ASI_M_BFILL

2024-02-01 Thread Richard Henderson
Align the operation to the 32-byte cacheline.
Use 2 i128 instead of 4 i64.

Signed-off-by: Richard Henderson 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-3-richard.hender...@linaro.org>
---
 target/sparc/translate.c | 29 ++---
 1 file changed, 14 insertions(+), 15 deletions(-)

diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index 1082aabc14..3a59262c9a 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -2172,23 +2172,22 @@ static void gen_stda_asi(DisasContext *dc, DisasASI 
*da, TCGv addr, int rd)
 
 case GET_ASI_BFILL:
 assert(TARGET_LONG_BITS == 32);
-/* Store 32 bytes of T64 to ADDR.  */
-/* ??? The original qemu code suggests 8-byte alignment, dropping
-   the low bits, but the only place I can see this used is in the
-   Linux kernel with 32 byte alignment, which would make more sense
-   as a cacheline-style operation.  */
+/*
+ * Store 32 bytes of [rd:rd+1] to ADDR.
+ * See comments for GET_ASI_COPY above.
+ */
 {
-TCGv_i64 t64 = tcg_temp_new_i64();
-TCGv d_addr = tcg_temp_new();
-TCGv eight = tcg_constant_tl(8);
-int i;
+MemOp mop = MO_TE | MO_128 | MO_ATOM_IFALIGN_PAIR;
+TCGv_i64 t8 = tcg_temp_new_i64();
+TCGv_i128 t16 = tcg_temp_new_i128();
+TCGv daddr = tcg_temp_new();
 
-tcg_gen_concat_tl_i64(t64, lo, hi);
-tcg_gen_andi_tl(d_addr, addr, -8);
-for (i = 0; i < 32; i += 8) {
-tcg_gen_qemu_st_i64(t64, d_addr, da->mem_idx, da->memop);
-tcg_gen_add_tl(d_addr, d_addr, eight);
-}
+tcg_gen_concat_tl_i64(t8, lo, hi);
+tcg_gen_concat_i64_i128(t16, t8, t8);
+tcg_gen_andi_tl(daddr, addr, -32);
+tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop);
+tcg_gen_addi_tl(daddr, daddr, 16);
+tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop);
 }
 break;
 
-- 
2.34.1




[PULL 21/57] target/ppc: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/ppc/cpu_init.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 86c8031765..9931372a08 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -7105,6 +7105,11 @@ static bool ppc_cpu_has_work(CPUState *cs)
 return cs->interrupt_request & CPU_INTERRUPT_HARD;
 }
 
+static int ppc_cpu_mmu_index(CPUState *cs, bool ifetch)
+{
+return ppc_env_mmu_index(cpu_env(cs), ifetch);
+}
+
 static void ppc_cpu_reset_hold(Object *obj)
 {
 CPUState *s = CPU(obj);
@@ -7372,6 +7377,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void 
*data)
 
 cc->class_by_name = ppc_cpu_class_by_name;
 cc->has_work = ppc_cpu_has_work;
+cc->mmu_index = ppc_cpu_mmu_index;
 cc->dump_state = ppc_cpu_dump_state;
 cc->set_pc = ppc_cpu_set_pc;
 cc->get_pc = ppc_cpu_get_pc;
-- 
2.34.1




[PULL 05/57] target/arm: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 6a96b245f2..1f9ea622bd 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -133,6 +133,11 @@ static bool arm_cpu_has_work(CPUState *cs)
  | CPU_INTERRUPT_EXITTB);
 }
 
+static int arm_cpu_mmu_index(CPUState *cs, bool ifetch)
+{
+return arm_env_mmu_index(cpu_env(cs));
+}
+
 void arm_register_pre_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
  void *opaque)
 {
@@ -2497,6 +2502,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void 
*data)
 
 cc->class_by_name = arm_cpu_class_by_name;
 cc->has_work = arm_cpu_has_work;
+cc->mmu_index = arm_cpu_mmu_index;
 cc->dump_state = arm_cpu_dump_state;
 cc->set_pc = arm_cpu_set_pc;
 cc->get_pc = arm_cpu_get_pc;
-- 
2.34.1




[PULL 28/57] target/sh4: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/sh4/cpu.h | 16 ++--
 target/sh4/cpu.c | 16 
 2 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h
index 0e6fa65bae..9c5e2b349e 100644
--- a/target/sh4/cpu.h
+++ b/target/sh4/cpu.h
@@ -273,16 +273,6 @@ void cpu_load_tlb(CPUSH4State * env);
 
 /* MMU modes definitions */
 #define MMU_USER_IDX 1
-static inline int cpu_mmu_index (CPUSH4State *env, bool ifetch)
-{
-/* The instruction in a RTE delay slot is fetched in privileged
-   mode, but executed in user mode.  */
-if (ifetch && (env->flags & TB_FLAG_DELAY_SLOT_RTE)) {
-return 0;
-} else {
-return (env->sr & (1u << SR_MD)) == 0 ? 1 : 0;
-}
-}
 
 #include "exec/cpu-all.h"
 
@@ -380,6 +370,12 @@ static inline void cpu_write_sr(CPUSH4State *env, 
target_ulong sr)
 env->sr = sr & ~((1u << SR_M) | (1u << SR_Q) | (1u << SR_T));
 }
 
+int sh4_cpu_mmu_index(CPUState *cs, bool ifetch);
+static inline int cpu_mmu_index(CPUSH4State *env, bool ifetch)
+{
+return sh4_cpu_mmu_index(env_cpu(env), ifetch);
+}
+
 static inline void cpu_get_tb_cpu_state(CPUSH4State *env, vaddr *pc,
 uint64_t *cs_base, uint32_t *flags)
 {
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
index 39772955b5..6fead5655f 100644
--- a/target/sh4/cpu.c
+++ b/target/sh4/cpu.c
@@ -89,6 +89,21 @@ static bool superh_cpu_has_work(CPUState *cs)
 return cs->interrupt_request & CPU_INTERRUPT_HARD;
 }
 
+int sh4_cpu_mmu_index(CPUState *cs, bool ifetch)
+{
+CPUSH4State *env = cpu_env(cs);
+
+/*
+ * The instruction in a RTE delay slot is fetched in privileged mode,
+ * but executed in user mode.
+ */
+if (ifetch && (env->flags & TB_FLAG_DELAY_SLOT_RTE)) {
+return 0;
+} else {
+return (env->sr & (1u << SR_MD)) == 0 ? 1 : 0;
+}
+}
+
 static void superh_cpu_reset_hold(Object *obj)
 {
 CPUState *s = CPU(obj);
@@ -266,6 +281,7 @@ static void superh_cpu_class_init(ObjectClass *oc, void 
*data)
 
 cc->class_by_name = superh_cpu_class_by_name;
 cc->has_work = superh_cpu_has_work;
+cc->mmu_index = sh4_cpu_mmu_index;
 cc->dump_state = superh_cpu_dump_state;
 cc->set_pc = superh_cpu_set_pc;
 cc->get_pc = superh_cpu_get_pc;
-- 
2.34.1




[PULL 54/57] target/sparc: Split cexc and ftt from env->fsr

2024-02-01 Thread Richard Henderson
These two fields are adjusted by all FPop insns.
Having them separate makes it easier to set without masking.

Signed-off-by: Richard Henderson 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-20-richard.hender...@linaro.org>
---
 target/sparc/cpu.h|  7 +-
 target/sparc/helper.h |  2 +-
 target/sparc/fop_helper.c | 46 ++-
 target/sparc/translate.c  | 31 --
 4 files changed, 48 insertions(+), 38 deletions(-)

diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index 216155d231..c5be9e37de 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -176,6 +176,7 @@ enum {
 #define FSR_DZM   (1ULL << 24)
 #define FSR_NXM   (1ULL << 23)
 #define FSR_TEM_MASK (FSR_NVM | FSR_OFM | FSR_UFM | FSR_DZM | FSR_NXM)
+#define FSR_TEM_SHIFT  23
 
 #define FSR_NVA   (1ULL << 9)
 #define FSR_OFA   (1ULL << 8)
@@ -183,6 +184,7 @@ enum {
 #define FSR_DZA   (1ULL << 6)
 #define FSR_NXA   (1ULL << 5)
 #define FSR_AEXC_MASK (FSR_NVA | FSR_OFA | FSR_UFA | FSR_DZA | FSR_NXA)
+#define FSR_AEXC_SHIFT 5
 
 #define FSR_NVC   (1ULL << 4)
 #define FSR_OFC   (1ULL << 3)
@@ -464,7 +466,10 @@ struct CPUArchState {
 target_ulong cond; /* conditional branch result (XXX: save it in a
   temporary register when possible) */
 
-target_ulong fsr;  /* FPU state register */
+/* FPU State Register, in parts */
+target_ulong fsr;   /* rm, tem, aexc, fcc* */
+uint32_t fsr_cexc_ftt;  /* cexc, ftt */
+
 CPU_DoubleU fpr[TARGET_DPREGS];  /* floating point registers */
 uint32_t cwp;  /* index of current register window (extracted
   from PSR) */
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index 7c688edd62..7466164468 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -36,7 +36,7 @@ DEF_HELPER_FLAGS_4(ld_asi, TCG_CALL_NO_WG, i64, env, tl, int, 
i32)
 DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32)
 #endif
 DEF_HELPER_FLAGS_1(get_fsr, TCG_CALL_NO_WG_SE, tl, env)
-DEF_HELPER_FLAGS_2(set_fsr, TCG_CALL_NO_RWG, void, env, tl)
+DEF_HELPER_FLAGS_2(set_fsr_noftt, 0, void, env, tl)
 DEF_HELPER_FLAGS_2(fsqrts, 0, f32, env, f32)
 DEF_HELPER_FLAGS_2(fsqrtd, 0, f64, env, f64)
 DEF_HELPER_FLAGS_2(fsqrtq, 0, i128, env, i128)
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
index 755117ea08..ac30f88810 100644
--- a/target/sparc/fop_helper.c
+++ b/target/sparc/fop_helper.c
@@ -48,9 +48,7 @@ static inline Int128 f128_ret(float128 f)
 static void check_ieee_exceptions(CPUSPARCState *env, uintptr_t ra)
 {
 target_ulong status = get_float_exception_flags(>fp_status);
-target_ulong fsr = env->fsr;
-
-fsr &= FSR_FTT_CEXC_NMASK;
+uint32_t cexc = 0;
 
 if (unlikely(status)) {
 /* Keep exception flags clear for next time.  */
@@ -58,38 +56,33 @@ static void check_ieee_exceptions(CPUSPARCState *env, 
uintptr_t ra)
 
 /* Copy IEEE 754 flags into FSR */
 if (status & float_flag_invalid) {
-fsr |= FSR_NVC;
+cexc |= FSR_NVC;
 }
 if (status & float_flag_overflow) {
-fsr |= FSR_OFC;
+cexc |= FSR_OFC;
 }
 if (status & float_flag_underflow) {
-fsr |= FSR_UFC;
+cexc |= FSR_UFC;
 }
 if (status & float_flag_divbyzero) {
-fsr |= FSR_DZC;
+cexc |= FSR_DZC;
 }
 if (status & float_flag_inexact) {
-fsr |= FSR_NXC;
+cexc |= FSR_NXC;
 }
 
-if ((fsr & FSR_CEXC_MASK) & ((fsr & FSR_TEM_MASK) >> 23)) {
-CPUState *cs = env_cpu(env);
-
-/* Unmasked exception, generate a trap.  Note that while
-   the helper is marked as NO_WG, we can get away with
-   writing to cpu state along the exception path, since
-   TCG generated code will never see the write.  */
-env->fsr = fsr | FSR_FTT_IEEE_EXCP;
-cs->exception_index = TT_FP_EXCP;
-cpu_loop_exit_restore(cs, ra);
-} else {
-/* Accumulate exceptions */
-fsr |= (fsr & FSR_CEXC_MASK) << 5;
+if (cexc & (env->fsr >> FSR_TEM_SHIFT)) {
+/* Unmasked exception, generate an IEEE trap. */
+env->fsr_cexc_ftt = cexc | FSR_FTT_IEEE_EXCP;
+cpu_raise_exception_ra(env, TT_FP_EXCP, ra);
 }
+
+/* Accumulate exceptions */
+env->fsr |= cexc << FSR_AEXC_SHIFT;
 }
 
-env->fsr = fsr;
+/* No trap, so FTT is cleared. */
+env->fsr_cexc_ftt = cexc;
 }
 
 float32 helper_fadds(CPUSPARCState *env, float32 src1, float32 src2)
@@ -456,7 +449,7 @@ GEN_FCMP(fcmpeq_fcc3, float128, 26, 1);
 
 target_ulong cpu_get_fsr(CPUSPARCState *env)
 {
-target_ulong fsr = env->fsr;
+target_ulong fsr = env->fsr | env->fsr_cexc_ftt;
 
 /* VER is kept completely separate until 

[PULL 46/57] target/sparc: Use i128 for FsTOq, FiTOq

2024-02-01 Thread Richard Henderson
Signed-off-by: Richard Henderson 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-12-richard.hender...@linaro.org>
---
 target/sparc/helper.h | 4 ++--
 target/sparc/fop_helper.c | 8 
 target/sparc/translate.c  | 9 +
 3 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index 7caae9a441..5e93342583 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -87,7 +87,7 @@ DEF_HELPER_FLAGS_3(fsmuld, TCG_CALL_NO_RWG, f64, env, f32, 
f32)
 DEF_HELPER_FLAGS_3(fdmulq, TCG_CALL_NO_RWG, void, env, f64, f64)
 
 DEF_HELPER_FLAGS_2(fitod, TCG_CALL_NO_RWG_SE, f64, env, s32)
-DEF_HELPER_FLAGS_2(fitoq, TCG_CALL_NO_RWG, void, env, s32)
+DEF_HELPER_FLAGS_2(fitoq, TCG_CALL_NO_RWG, i128, env, s32)
 
 DEF_HELPER_FLAGS_2(fitos, TCG_CALL_NO_RWG, f32, env, s32)
 
@@ -99,7 +99,7 @@ DEF_HELPER_FLAGS_2(fxtoq, TCG_CALL_NO_RWG, void, env, s64)
 DEF_HELPER_FLAGS_2(fdtos, TCG_CALL_NO_RWG, f32, env, f64)
 DEF_HELPER_FLAGS_2(fstod, TCG_CALL_NO_RWG, f64, env, f32)
 DEF_HELPER_FLAGS_2(fqtos, TCG_CALL_NO_RWG, f32, env, i128)
-DEF_HELPER_FLAGS_2(fstoq, TCG_CALL_NO_RWG, void, env, f32)
+DEF_HELPER_FLAGS_2(fstoq, TCG_CALL_NO_RWG, i128, env, f32)
 DEF_HELPER_FLAGS_2(fqtod, TCG_CALL_NO_RWG, f64, env, i128)
 DEF_HELPER_FLAGS_2(fdtoq, TCG_CALL_NO_RWG, void, env, f64)
 DEF_HELPER_FLAGS_2(fstoi, TCG_CALL_NO_RWG, s32, env, f32)
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
index faf75e651f..c7dc835d28 100644
--- a/target/sparc/fop_helper.c
+++ b/target/sparc/fop_helper.c
@@ -147,9 +147,9 @@ float64 helper_fitod(CPUSPARCState *env, int32_t src)
 return int32_to_float64(src, >fp_status);
 }
 
-void helper_fitoq(CPUSPARCState *env, int32_t src)
+Int128 helper_fitoq(CPUSPARCState *env, int32_t src)
 {
-QT0 = int32_to_float128(src, >fp_status);
+return f128_ret(int32_to_float128(src, >fp_status));
 }
 
 #ifdef TARGET_SPARC64
@@ -185,9 +185,9 @@ float32 helper_fqtos(CPUSPARCState *env, Int128 src)
 return float128_to_float32(f128_in(src), >fp_status);
 }
 
-void helper_fstoq(CPUSPARCState *env, float32 src)
+Int128 helper_fstoq(CPUSPARCState *env, float32 src)
 {
-QT0 = float32_to_float128(src, >fp_status);
+return f128_ret(float32_to_float128(src, >fp_status));
 }
 
 float64 helper_fqtod(CPUSPARCState *env, Int128 src)
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index 6c003eed7c..6522a9b0c8 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -4726,9 +4726,10 @@ TRANS(FqTOd, ALL, do_env_dq, a, gen_helper_fqtod)
 TRANS(FqTOx, 64, do_env_dq, a, gen_helper_fqtox)
 
 static bool do_env_qf(DisasContext *dc, arg_r_r *a,
-  void (*func)(TCGv_env, TCGv_i32))
+  void (*func)(TCGv_i128, TCGv_env, TCGv_i32))
 {
 TCGv_i32 src;
+TCGv_i128 dst;
 
 if (gen_trap_ifnofpu(dc)) {
 return true;
@@ -4739,9 +4740,9 @@ static bool do_env_qf(DisasContext *dc, arg_r_r *a,
 
 gen_op_clear_ieee_excp_and_FTT();
 src = gen_load_fpr_F(dc, a->rs);
-func(tcg_env, src);
-gen_op_store_QT0_fpr(QFPREG(a->rd));
-gen_update_fprs_dirty(dc, QFPREG(a->rd));
+dst = tcg_temp_new_i128();
+func(dst, tcg_env, src);
+gen_store_fpr_Q(dc, a->rd, dst);
 return advance_pc(dc);
 }
 
-- 
2.34.1




[PULL 56/57] target/sparc: Split fcc out of env->fsr

2024-02-01 Thread Richard Henderson
Represent each fcc field separately from the rest of fsr.
This vastly simplifies floating-point comparisons.

Signed-off-by: Richard Henderson 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-22-richard.hender...@linaro.org>
---
 target/sparc/cpu.h|  20 +-
 target/sparc/helper.h |  34 +--
 target/sparc/fop_helper.c | 169 ++---
 target/sparc/translate.c  | 503 +-
 4 files changed, 201 insertions(+), 525 deletions(-)

diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index c5be9e37de..986c7217ed 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -31,8 +31,10 @@
 
 #if !defined(TARGET_SPARC64)
 #define TARGET_DPREGS 16
+#define TARGET_FCCREGS 1
 #else
 #define TARGET_DPREGS 32
+#define TARGET_FCCREGS 4
 #endif
 
 /*#define EXCP_INTERRUPT 0x100*/
@@ -203,24 +205,19 @@ enum {
 #ifdef TARGET_SPARC64
 #define FSR_FTT_NMASK  0xfffe3fffULL
 #define FSR_FTT_CEXC_NMASK 0xfffe3fe0ULL
-#define FSR_LDFSR_OLDMASK  0x003f000fc000ULL
-#define FSR_LDXFSR_MASK0x003fcfc00fffULL
-#define FSR_LDXFSR_OLDMASK 0x000fc000ULL
 #else
 #define FSR_FTT_NMASK  0xfffe3fffULL
 #define FSR_FTT_CEXC_NMASK 0xfffe3fe0ULL
-#define FSR_LDFSR_OLDMASK  0x000fc000ULL
 #endif
-#define FSR_LDFSR_MASK 0xcfc00fffULL
 #define FSR_FTT_IEEE_EXCP (1ULL << 14)
 #define FSR_FTT_UNIMPFPOP (3ULL << 14)
 #define FSR_FTT_SEQ_ERROR (4ULL << 14)
 #define FSR_FTT_INVAL_FPR (6ULL << 14)
 
-#define FSR_FCC1_SHIFT 11
-#define FSR_FCC1  (1ULL << FSR_FCC1_SHIFT)
-#define FSR_FCC0_SHIFT 10
-#define FSR_FCC0  (1ULL << FSR_FCC0_SHIFT)
+#define FSR_FCC0_SHIFT10
+#define FSR_FCC1_SHIFT32
+#define FSR_FCC2_SHIFT34
+#define FSR_FCC3_SHIFT36
 
 /* MMU */
 #define MMU_E (1<<0)
@@ -467,8 +464,9 @@ struct CPUArchState {
   temporary register when possible) */
 
 /* FPU State Register, in parts */
-target_ulong fsr;   /* rm, tem, aexc, fcc* */
-uint32_t fsr_cexc_ftt;  /* cexc, ftt */
+uint32_t fsr;/* rm, tem, aexc */
+uint32_t fsr_cexc_ftt;   /* cexc, ftt */
+uint32_t fcc[TARGET_FCCREGS];/* fcc* */
 
 CPU_DoubleU fpr[TARGET_DPREGS];  /* floating point registers */
 uint32_t cwp;  /* index of current register window (extracted
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index c8e14fe371..6a42ba4e9e 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -36,36 +36,16 @@ DEF_HELPER_FLAGS_4(ld_asi, TCG_CALL_NO_WG, i64, env, tl, 
int, i32)
 DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32)
 #endif
 DEF_HELPER_FLAGS_1(get_fsr, TCG_CALL_NO_WG_SE, tl, env)
-DEF_HELPER_FLAGS_2(set_fsr_noftt, TCG_CALL_NO_RWG, void, env, tl)
+DEF_HELPER_FLAGS_2(set_fsr_nofcc_noftt, TCG_CALL_NO_RWG, void, env, i32)
 DEF_HELPER_FLAGS_2(fsqrts, TCG_CALL_NO_WG, f32, env, f32)
 DEF_HELPER_FLAGS_2(fsqrtd, TCG_CALL_NO_WG, f64, env, f64)
 DEF_HELPER_FLAGS_2(fsqrtq, TCG_CALL_NO_WG, i128, env, i128)
-DEF_HELPER_FLAGS_3(fcmps, TCG_CALL_NO_WG, void, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, void, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmpes, TCG_CALL_NO_WG, void, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, void, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, void, env, i128, i128)
-DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, void, env, i128, i128)
-#ifdef TARGET_SPARC64
-DEF_HELPER_FLAGS_3(fcmps_fcc1, TCG_CALL_NO_WG, void, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmps_fcc2, TCG_CALL_NO_WG, void, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmps_fcc3, TCG_CALL_NO_WG, void, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmpd_fcc1, TCG_CALL_NO_WG, void, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmpd_fcc2, TCG_CALL_NO_WG, void, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmpd_fcc3, TCG_CALL_NO_WG, void, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmpes_fcc1, TCG_CALL_NO_WG, void, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmpes_fcc2, TCG_CALL_NO_WG, void, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmpes_fcc3, TCG_CALL_NO_WG, void, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmped_fcc1, TCG_CALL_NO_WG, void, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmped_fcc2, TCG_CALL_NO_WG, void, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmped_fcc3, TCG_CALL_NO_WG, void, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmpq_fcc1, TCG_CALL_NO_WG, void, env, i128, i128)
-DEF_HELPER_FLAGS_3(fcmpq_fcc2, TCG_CALL_NO_WG, void, env, i128, i128)
-DEF_HELPER_FLAGS_3(fcmpq_fcc3, TCG_CALL_NO_WG, void, env, i128, i128)
-DEF_HELPER_FLAGS_3(fcmpeq_fcc1, TCG_CALL_NO_WG, void, env, i128, i128)
-DEF_HELPER_FLAGS_3(fcmpeq_fcc2, TCG_CALL_NO_WG, void, env, i128, i128)
-DEF_HELPER_FLAGS_3(fcmpeq_fcc3, TCG_CALL_NO_WG, void, env, i128, i128)
-#endif
+DEF_HELPER_FLAGS_3(fcmps, TCG_CALL_NO_WG, i32, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmpes, TCG_CALL_NO_WG, i32, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, i32, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, i32, env, f64, 

[PULL 51/57] target/sparc: Split ver from env->fsr

2024-02-01 Thread Richard Henderson
This field is read-only.  It is easier to store it separately
and merge it only upon read.

While we're at it, use FSR_VER_SHIFT to initialize fpu_version.

Signed-off-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-17-richard.hender...@linaro.org>
---
 target/sparc/cpu.h|  3 +++
 target/sparc/cpu.c| 27 +--
 target/sparc/fop_helper.c |  9 +++--
 3 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index 3cf8cc2d0b..216155d231 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -191,6 +191,9 @@ enum {
 #define FSR_NXC   (1ULL << 0)
 #define FSR_CEXC_MASK (FSR_NVC | FSR_OFC | FSR_UFC | FSR_DZC | FSR_NXC)
 
+#define FSR_VER_SHIFT  17
+#define FSR_VER_MASK   (7 << FSR_VER_SHIFT)
+
 #define FSR_FTT2   (1ULL << 16)
 #define FSR_FTT1   (1ULL << 15)
 #define FSR_FTT0   (1ULL << 14)
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
index 1897ab230d..313ebc4c11 100644
--- a/target/sparc/cpu.c
+++ b/target/sparc/cpu.c
@@ -368,7 +368,7 @@ static const sparc_def_t sparc_defs[] = {
 {
 .name = "Fujitsu MB86904",
 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
-.fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+.fpu_version = 4 << FSR_VER_SHIFT, /* FPU version 4 (Meiko) */
 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
 .mmu_bm = 0x4000,
 .mmu_ctpr_mask = 0x00c0,
@@ -381,7 +381,7 @@ static const sparc_def_t sparc_defs[] = {
 {
 .name = "Fujitsu MB86907",
 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
-.fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+.fpu_version = 4 << FSR_VER_SHIFT, /* FPU version 4 (Meiko) */
 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
 .mmu_bm = 0x4000,
 .mmu_ctpr_mask = 0xffc0,
@@ -394,7 +394,7 @@ static const sparc_def_t sparc_defs[] = {
 {
 .name = "TI MicroSparc I",
 .iu_version = 0x4100,
-.fpu_version = 4 << 17,
+.fpu_version = 4 << FSR_VER_SHIFT,
 .mmu_version = 0x4100,
 .mmu_bm = 0x4000,
 .mmu_ctpr_mask = 0x0070,
@@ -407,7 +407,7 @@ static const sparc_def_t sparc_defs[] = {
 {
 .name = "TI MicroSparc II",
 .iu_version = 0x4200,
-.fpu_version = 4 << 17,
+.fpu_version = 4 << FSR_VER_SHIFT,
 .mmu_version = 0x0200,
 .mmu_bm = 0x4000,
 .mmu_ctpr_mask = 0x00c0,
@@ -420,7 +420,7 @@ static const sparc_def_t sparc_defs[] = {
 {
 .name = "TI MicroSparc IIep",
 .iu_version = 0x4200,
-.fpu_version = 4 << 17,
+.fpu_version = 4 << FSR_VER_SHIFT,
 .mmu_version = 0x0400,
 .mmu_bm = 0x4000,
 .mmu_ctpr_mask = 0x00c0,
@@ -433,7 +433,7 @@ static const sparc_def_t sparc_defs[] = {
 {
 .name = "TI SuperSparc 40", /* STP1020NPGA */
 .iu_version = 0x4100, /* SuperSPARC 2.x */
-.fpu_version = 0 << 17,
+.fpu_version = 0 << FSR_VER_SHIFT,
 .mmu_version = 0x0800, /* SuperSPARC 2.x, no MXCC */
 .mmu_bm = 0x2000,
 .mmu_ctpr_mask = 0xffc0,
@@ -446,7 +446,7 @@ static const sparc_def_t sparc_defs[] = {
 {
 .name = "TI SuperSparc 50", /* STP1020PGA */
 .iu_version = 0x4000, /* SuperSPARC 3.x */
-.fpu_version = 0 << 17,
+.fpu_version = 0 << FSR_VER_SHIFT,
 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
 .mmu_bm = 0x2000,
 .mmu_ctpr_mask = 0xffc0,
@@ -459,7 +459,7 @@ static const sparc_def_t sparc_defs[] = {
 {
 .name = "TI SuperSparc 51",
 .iu_version = 0x4000, /* SuperSPARC 3.x */
-.fpu_version = 0 << 17,
+.fpu_version = 0 << FSR_VER_SHIFT,
 .mmu_version = 0x0100, /* SuperSPARC 3.x, MXCC */
 .mmu_bm = 0x2000,
 .mmu_ctpr_mask = 0xffc0,
@@ -473,7 +473,7 @@ static const sparc_def_t sparc_defs[] = {
 {
 .name = "TI SuperSparc 60", /* STP1020APGA */
 .iu_version = 0x4000, /* SuperSPARC 3.x */
-.fpu_version = 0 << 17,
+.fpu_version = 0 << FSR_VER_SHIFT,
 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
 .mmu_bm = 0x2000,
 .mmu_ctpr_mask = 0xffc0,
@@ -486,7 +486,7 @@ static const sparc_def_t sparc_defs[] = {
 {
 .name = "TI SuperSparc 61",
 .iu_version = 0x4400, /* SuperSPARC 3.x */
-.fpu_version = 0 << 17,
+.fpu_version = 0 << FSR_VER_SHIFT,
 .mmu_version = 0x0100, /* SuperSPARC 3.x, MXCC */
 .mmu_bm = 0x2000,
 .mmu_ctpr_mask = 0xffc0,
@@ -500,7 +500,7 @@ static const sparc_def_t sparc_defs[] = {
 {
 .name = "TI SuperSparc II",
 .iu_version = 0x4000, /* 

[PULL 41/57] target/sparc: Use i128 for FSQRTq

2024-02-01 Thread Richard Henderson
Signed-off-by: Richard Henderson 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-7-richard.hender...@linaro.org>
---
 target/sparc/helper.h |  2 +-
 target/sparc/fop_helper.c | 26 --
 target/sparc/translate.c  | 12 +++-
 3 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index 74a1575d21..eea2fa570c 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -43,7 +43,7 @@ DEF_HELPER_FLAGS_3(fcmps, TCG_CALL_NO_WG, tl, env, f32, f32)
 DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, tl, env, f64, f64)
 DEF_HELPER_FLAGS_3(fcmpes, TCG_CALL_NO_WG, tl, env, f32, f32)
 DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, tl, env, f64, f64)
-DEF_HELPER_FLAGS_1(fsqrtq, TCG_CALL_NO_RWG, void, env)
+DEF_HELPER_FLAGS_2(fsqrtq, TCG_CALL_NO_RWG, i128, env, i128)
 DEF_HELPER_FLAGS_1(fcmpq, TCG_CALL_NO_WG, tl, env)
 DEF_HELPER_FLAGS_1(fcmpeq, TCG_CALL_NO_WG, tl, env)
 #ifdef TARGET_SPARC64
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
index d6fb769769..d639e50965 100644
--- a/target/sparc/fop_helper.c
+++ b/target/sparc/fop_helper.c
@@ -26,6 +26,28 @@
 #define QT0 (env->qt0)
 #define QT1 (env->qt1)
 
+static inline float128 f128_in(Int128 i)
+{
+union {
+Int128 i;
+float128 f;
+} u;
+
+u.i = i;
+return u.f;
+}
+
+static inline Int128 f128_ret(float128 f)
+{
+union {
+Int128 i;
+float128 f;
+} u;
+
+u.f = f;
+return u.i;
+}
+
 static target_ulong do_check_ieee_exceptions(CPUSPARCState *env, uintptr_t ra)
 {
 target_ulong status = get_float_exception_flags(>fp_status);
@@ -222,9 +244,9 @@ float64 helper_fsqrtd(CPUSPARCState *env, float64 src)
 return float64_sqrt(src, >fp_status);
 }
 
-void helper_fsqrtq(CPUSPARCState *env)
+Int128 helper_fsqrtq(CPUSPARCState *env, Int128 src)
 {
-QT0 = float128_sqrt(QT1, >fp_status);
+return f128_ret(float128_sqrt(f128_in(src), >fp_status));
 }
 
 #define GEN_FCMP(name, size, reg1, reg2, FS, E) \
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index 41952281dc..ca98565c16 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -4669,8 +4669,10 @@ TRANS(FNEGq, 64, do_qq, a, gen_op_fnegq)
 TRANS(FABSq, 64, do_qq, a, gen_op_fabsq)
 
 static bool do_env_qq(DisasContext *dc, arg_r_r *a,
-   void (*func)(TCGv_env))
+  void (*func)(TCGv_i128, TCGv_env, TCGv_i128))
 {
+TCGv_i128 t;
+
 if (gen_trap_ifnofpu(dc)) {
 return true;
 }
@@ -4679,11 +4681,11 @@ static bool do_env_qq(DisasContext *dc, arg_r_r *a,
 }
 
 gen_op_clear_ieee_excp_and_FTT();
-gen_op_load_fpr_QT1(QFPREG(a->rs));
-func(tcg_env);
+
+t = gen_load_fpr_Q(dc, a->rs);
+func(t, tcg_env, t);
 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
-gen_op_store_QT0_fpr(QFPREG(a->rd));
-gen_update_fprs_dirty(dc, QFPREG(a->rd));
+gen_store_fpr_Q(dc, a->rd, t);
 return advance_pc(dc);
 }
 
-- 
2.34.1




[PULL 45/57] target/sparc: Use i128 for FCMPq, FCMPEq

2024-02-01 Thread Richard Henderson
Signed-off-by: Richard Henderson 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-11-richard.hender...@linaro.org>
---
 target/sparc/helper.h | 16 ++--
 target/sparc/fop_helper.c | 23 +
 target/sparc/translate.c  | 54 +++
 3 files changed, 41 insertions(+), 52 deletions(-)

diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index 4cb3451878..7caae9a441 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -44,8 +44,8 @@ DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, tl, env, f64, f64)
 DEF_HELPER_FLAGS_3(fcmpes, TCG_CALL_NO_WG, tl, env, f32, f32)
 DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, tl, env, f64, f64)
 DEF_HELPER_FLAGS_2(fsqrtq, TCG_CALL_NO_RWG, i128, env, i128)
-DEF_HELPER_FLAGS_1(fcmpq, TCG_CALL_NO_WG, tl, env)
-DEF_HELPER_FLAGS_1(fcmpeq, TCG_CALL_NO_WG, tl, env)
+DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, tl, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, tl, env, i128, i128)
 #ifdef TARGET_SPARC64
 DEF_HELPER_FLAGS_3(fcmps_fcc1, TCG_CALL_NO_WG, tl, env, f32, f32)
 DEF_HELPER_FLAGS_3(fcmps_fcc2, TCG_CALL_NO_WG, tl, env, f32, f32)
@@ -59,12 +59,12 @@ DEF_HELPER_FLAGS_3(fcmpes_fcc3, TCG_CALL_NO_WG, tl, env, 
f32, f32)
 DEF_HELPER_FLAGS_3(fcmped_fcc1, TCG_CALL_NO_WG, tl, env, f64, f64)
 DEF_HELPER_FLAGS_3(fcmped_fcc2, TCG_CALL_NO_WG, tl, env, f64, f64)
 DEF_HELPER_FLAGS_3(fcmped_fcc3, TCG_CALL_NO_WG, tl, env, f64, f64)
-DEF_HELPER_FLAGS_1(fcmpq_fcc1, TCG_CALL_NO_WG, tl, env)
-DEF_HELPER_FLAGS_1(fcmpq_fcc2, TCG_CALL_NO_WG, tl, env)
-DEF_HELPER_FLAGS_1(fcmpq_fcc3, TCG_CALL_NO_WG, tl, env)
-DEF_HELPER_FLAGS_1(fcmpeq_fcc1, TCG_CALL_NO_WG, tl, env)
-DEF_HELPER_FLAGS_1(fcmpeq_fcc2, TCG_CALL_NO_WG, tl, env)
-DEF_HELPER_FLAGS_1(fcmpeq_fcc3, TCG_CALL_NO_WG, tl, env)
+DEF_HELPER_FLAGS_3(fcmpq_fcc1, TCG_CALL_NO_WG, tl, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmpq_fcc2, TCG_CALL_NO_WG, tl, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmpq_fcc3, TCG_CALL_NO_WG, tl, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmpeq_fcc1, TCG_CALL_NO_WG, tl, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmpeq_fcc2, TCG_CALL_NO_WG, tl, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmpeq_fcc3, TCG_CALL_NO_WG, tl, env, i128, i128)
 #endif
 DEF_HELPER_2(raise_exception, noreturn, env, int)
 
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
index 9f39b933e8..faf75e651f 100644
--- a/target/sparc/fop_helper.c
+++ b/target/sparc/fop_helper.c
@@ -248,9 +248,12 @@ Int128 helper_fsqrtq(CPUSPARCState *env, Int128 src)
 return f128_ret(float128_sqrt(f128_in(src), >fp_status));
 }
 
-#define GEN_FCMP(name, size, reg1, reg2, FS, E) \
-target_ulong glue(helper_, name) (CPUSPARCState *env)   \
+#define GEN_FCMP(name, size, FS, E) \
+target_ulong glue(helper_, name) (CPUSPARCState *env,   \
+  Int128 src1, Int128 src2) \
 {   \
+float128 reg1 = f128_in(src1);  \
+float128 reg2 = f128_in(src2);  \
 FloatRelation ret;  \
 target_ulong fsr;   \
 if (E) {\
@@ -316,33 +319,33 @@ GEN_FCMP_T(fcmpd, float64, 0, 0);
 GEN_FCMP_T(fcmpes, float32, 0, 1);
 GEN_FCMP_T(fcmped, float64, 0, 1);
 
-GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
-GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
+GEN_FCMP(fcmpq, float128, 0, 0);
+GEN_FCMP(fcmpeq, float128, 0, 1);
 
 #ifdef TARGET_SPARC64
 GEN_FCMP_T(fcmps_fcc1, float32, 22, 0);
 GEN_FCMP_T(fcmpd_fcc1, float64, 22, 0);
-GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
+GEN_FCMP(fcmpq_fcc1, float128, 22, 0);
 
 GEN_FCMP_T(fcmps_fcc2, float32, 24, 0);
 GEN_FCMP_T(fcmpd_fcc2, float64, 24, 0);
-GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
+GEN_FCMP(fcmpq_fcc2, float128, 24, 0);
 
 GEN_FCMP_T(fcmps_fcc3, float32, 26, 0);
 GEN_FCMP_T(fcmpd_fcc3, float64, 26, 0);
-GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
+GEN_FCMP(fcmpq_fcc3, float128, 26, 0);
 
 GEN_FCMP_T(fcmpes_fcc1, float32, 22, 1);
 GEN_FCMP_T(fcmped_fcc1, float64, 22, 1);
-GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
+GEN_FCMP(fcmpeq_fcc1, float128, 22, 1);
 
 GEN_FCMP_T(fcmpes_fcc2, float32, 24, 1);
 GEN_FCMP_T(fcmped_fcc2, float64, 24, 1);
-GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
+GEN_FCMP(fcmpeq_fcc2, float128, 24, 1);
 
 GEN_FCMP_T(fcmpes_fcc3, float32, 26, 1);
 GEN_FCMP_T(fcmped_fcc3, float64, 26, 1);
-GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
+GEN_FCMP(fcmpeq_fcc3, float128, 26, 1);
 #endif
 #undef GEN_FCMP_T
 #undef GEN_FCMP
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index 6f75f4d5d6..6c003eed7c 100644
--- a/target/sparc/translate.c
+++ 

[PULL 42/57] target/sparc: Use i128 for FADDq, FSUBq, FMULq, FDIVq

2024-02-01 Thread Richard Henderson
Signed-off-by: Richard Henderson 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-8-richard.hender...@linaro.org>
---
 target/sparc/helper.h | 12 +---
 target/sparc/fop_helper.c | 29 ++---
 target/sparc/translate.c  | 13 +++--
 3 files changed, 26 insertions(+), 28 deletions(-)

diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index eea2fa570c..0a030fc908 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -67,17 +67,16 @@ DEF_HELPER_FLAGS_1(fcmpeq_fcc2, TCG_CALL_NO_WG, tl, env)
 DEF_HELPER_FLAGS_1(fcmpeq_fcc3, TCG_CALL_NO_WG, tl, env)
 #endif
 DEF_HELPER_2(raise_exception, noreturn, env, int)
-#define F_HELPER_0_1(name) \
-  DEF_HELPER_FLAGS_1(f ## name, TCG_CALL_NO_RWG, void, env)
 
 DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_RWG, f64, env, f64, f64)
 DEF_HELPER_FLAGS_3(fsubd, TCG_CALL_NO_RWG, f64, env, f64, f64)
 DEF_HELPER_FLAGS_3(fmuld, TCG_CALL_NO_RWG, f64, env, f64, f64)
 DEF_HELPER_FLAGS_3(fdivd, TCG_CALL_NO_RWG, f64, env, f64, f64)
-F_HELPER_0_1(addq)
-F_HELPER_0_1(subq)
-F_HELPER_0_1(mulq)
-F_HELPER_0_1(divq)
+
+DEF_HELPER_FLAGS_3(faddq, TCG_CALL_NO_RWG, i128, env, i128, i128)
+DEF_HELPER_FLAGS_3(fsubq, TCG_CALL_NO_RWG, i128, env, i128, i128)
+DEF_HELPER_FLAGS_3(fmulq, TCG_CALL_NO_RWG, i128, env, i128, i128)
+DEF_HELPER_FLAGS_3(fdivq, TCG_CALL_NO_RWG, i128, env, i128, i128)
 
 DEF_HELPER_FLAGS_3(fadds, TCG_CALL_NO_RWG, f32, env, f32, f32)
 DEF_HELPER_FLAGS_3(fsubs, TCG_CALL_NO_RWG, f32, env, f32, f32)
@@ -135,6 +134,5 @@ VIS_CMPHELPER(cmpeq)
 VIS_CMPHELPER(cmple)
 VIS_CMPHELPER(cmpne)
 #endif
-#undef F_HELPER_0_1
 #undef VIS_HELPER
 #undef VIS_CMPHELPER
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
index d639e50965..ceb64d802f 100644
--- a/target/sparc/fop_helper.c
+++ b/target/sparc/fop_helper.c
@@ -98,22 +98,22 @@ target_ulong helper_check_ieee_exceptions(CPUSPARCState 
*env)
 return do_check_ieee_exceptions(env, GETPC());
 }
 
-#define F_HELPER(name, p) void helper_f##name##p(CPUSPARCState *env)
-
-#define F_BINOP(name)   \
+#define F_BINOP(name)\
 float32 helper_f ## name ## s (CPUSPARCState *env, float32 src1, \
-   float32 src2)\
-{   \
-return float32_ ## name (src1, src2, >fp_status);  \
-}   \
+   float32 src2) \
+{\
+return float32_ ## name (src1, src2, >fp_status);   \
+}\
 float64 helper_f ## name ## d (CPUSPARCState * env, float64 src1,\
-   float64 src2)\
-{   \
-return float64_ ## name (src1, src2, >fp_status);  \
-}   \
-F_HELPER(name, q)   \
-{   \
-QT0 = float128_ ## name (QT0, QT1, >fp_status);\
+   float64 src2) \
+{\
+return float64_ ## name (src1, src2, >fp_status);   \
+}\
+Int128 helper_f ## name ## q(CPUSPARCState * env, Int128 src1,   \
+ Int128 src2)\
+{\
+return f128_ret(float128_ ## name (f128_in(src1), f128_in(src2), \
+   >fp_status));\
 }
 
 F_BINOP(add);
@@ -168,7 +168,6 @@ void helper_fxtoq(CPUSPARCState *env, int64_t src)
 QT0 = int64_to_float128(src, >fp_status);
 }
 #endif
-#undef F_HELPER
 
 /* floating point conversion */
 float32 helper_fdtos(CPUSPARCState *env, float64 src)
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index ca98565c16..96aa7ed235 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -4976,8 +4976,10 @@ static bool do_(DisasContext *dc, arg_r_r_r *a,
 TRANS(PDIST, VIS1, do_, a, gen_helper_pdist)
 
 static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a,
-   void (*func)(TCGv_env))
+   void (*func)(TCGv_i128, TCGv_env, TCGv_i128, TCGv_i128))
 {
+TCGv_i128 src1, src2;
+
 if (gen_trap_ifnofpu(dc)) {
 return true;
 }
@@ -4986,12 +4988,11 @@ static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a,
 }
 
 gen_op_clear_ieee_excp_and_FTT();
-

[PULL 57/57] target/sparc: Remove FSR_FTT_NMASK, FSR_FTT_CEXC_NMASK

2024-02-01 Thread Richard Henderson
These macros are no longer used.

Signed-off-by: Richard Henderson 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-23-richard.hender...@linaro.org>
---
 target/sparc/cpu.h | 7 ---
 1 file changed, 7 deletions(-)

diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index 986c7217ed..edf46b387e 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -202,13 +202,6 @@ enum {
 #define FSR_FTT1   (1ULL << 15)
 #define FSR_FTT0   (1ULL << 14)
 #define FSR_FTT_MASK (FSR_FTT2 | FSR_FTT1 | FSR_FTT0)
-#ifdef TARGET_SPARC64
-#define FSR_FTT_NMASK  0xfffe3fffULL
-#define FSR_FTT_CEXC_NMASK 0xfffe3fe0ULL
-#else
-#define FSR_FTT_NMASK  0xfffe3fffULL
-#define FSR_FTT_CEXC_NMASK 0xfffe3fe0ULL
-#endif
 #define FSR_FTT_IEEE_EXCP (1ULL << 14)
 #define FSR_FTT_UNIMPFPOP (3ULL << 14)
 #define FSR_FTT_SEQ_ERROR (4ULL << 14)
-- 
2.34.1




[PULL 53/57] target/sparc: Merge check_ieee_exceptions with FPop helpers

2024-02-01 Thread Richard Henderson
If an exception is to be raised, the destination fp register
should be unmodified.  The current implementation is incorrect,
in that double results will be written back before calling
gen_helper_check_ieee_exceptions, despite the placement of
gen_store_fpr_D, since gen_dest_fpr_D returns cpu_fpr[].

We can simplify the entire implementation by having each
FPOp helper call check_ieee_exceptions.  For the moment this
requires that all FPop helpers write to the TCG global cpu_fsr,
so remove TCG_CALL_NO_WG from the DEF_HELPER_FLAGS_*.

Signed-off-by: Richard Henderson 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-19-richard.hender...@linaro.org>
---
 target/sparc/helper.h | 119 +++--
 target/sparc/fop_helper.c | 215 --
 target/sparc/translate.c  |  14 ---
 3 files changed, 219 insertions(+), 129 deletions(-)

diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index cc8db50d75..7c688edd62 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -35,81 +35,80 @@ DEF_HELPER_3(tsubcctv, tl, env, tl, tl)
 DEF_HELPER_FLAGS_4(ld_asi, TCG_CALL_NO_WG, i64, env, tl, int, i32)
 DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32)
 #endif
-DEF_HELPER_FLAGS_1(check_ieee_exceptions, TCG_CALL_NO_WG, tl, env)
 DEF_HELPER_FLAGS_1(get_fsr, TCG_CALL_NO_WG_SE, tl, env)
 DEF_HELPER_FLAGS_2(set_fsr, TCG_CALL_NO_RWG, void, env, tl)
-DEF_HELPER_FLAGS_2(fsqrts, TCG_CALL_NO_RWG, f32, env, f32)
-DEF_HELPER_FLAGS_2(fsqrtd, TCG_CALL_NO_RWG, f64, env, f64)
-DEF_HELPER_FLAGS_3(fcmps, TCG_CALL_NO_WG, tl, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, tl, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmpes, TCG_CALL_NO_WG, tl, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, tl, env, f64, f64)
-DEF_HELPER_FLAGS_2(fsqrtq, TCG_CALL_NO_RWG, i128, env, i128)
-DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, tl, env, i128, i128)
-DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, tl, env, i128, i128)
+DEF_HELPER_FLAGS_2(fsqrts, 0, f32, env, f32)
+DEF_HELPER_FLAGS_2(fsqrtd, 0, f64, env, f64)
+DEF_HELPER_FLAGS_2(fsqrtq, 0, i128, env, i128)
+DEF_HELPER_FLAGS_3(fcmps, 0, tl, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmpd, 0, tl, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmpes, 0, tl, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmped, 0, tl, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmpq, 0, tl, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmpeq, 0, tl, env, i128, i128)
 #ifdef TARGET_SPARC64
-DEF_HELPER_FLAGS_3(fcmps_fcc1, TCG_CALL_NO_WG, tl, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmps_fcc2, TCG_CALL_NO_WG, tl, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmps_fcc3, TCG_CALL_NO_WG, tl, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmpd_fcc1, TCG_CALL_NO_WG, tl, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmpd_fcc2, TCG_CALL_NO_WG, tl, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmpd_fcc3, TCG_CALL_NO_WG, tl, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmpes_fcc1, TCG_CALL_NO_WG, tl, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmpes_fcc2, TCG_CALL_NO_WG, tl, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmpes_fcc3, TCG_CALL_NO_WG, tl, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmped_fcc1, TCG_CALL_NO_WG, tl, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmped_fcc2, TCG_CALL_NO_WG, tl, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmped_fcc3, TCG_CALL_NO_WG, tl, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmpq_fcc1, TCG_CALL_NO_WG, tl, env, i128, i128)
-DEF_HELPER_FLAGS_3(fcmpq_fcc2, TCG_CALL_NO_WG, tl, env, i128, i128)
-DEF_HELPER_FLAGS_3(fcmpq_fcc3, TCG_CALL_NO_WG, tl, env, i128, i128)
-DEF_HELPER_FLAGS_3(fcmpeq_fcc1, TCG_CALL_NO_WG, tl, env, i128, i128)
-DEF_HELPER_FLAGS_3(fcmpeq_fcc2, TCG_CALL_NO_WG, tl, env, i128, i128)
-DEF_HELPER_FLAGS_3(fcmpeq_fcc3, TCG_CALL_NO_WG, tl, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmps_fcc1, 0, tl, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmps_fcc2, 0, tl, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmps_fcc3, 0, tl, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmpd_fcc1, 0, tl, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmpd_fcc2, 0, tl, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmpd_fcc3, 0, tl, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmpes_fcc1, 0, tl, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmpes_fcc2, 0, tl, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmpes_fcc3, 0, tl, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmped_fcc1, 0, tl, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmped_fcc2, 0, tl, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmped_fcc3, 0, tl, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmpq_fcc1, 0, tl, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmpq_fcc2, 0, tl, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmpq_fcc3, 0, tl, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmpeq_fcc1, 0, tl, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmpeq_fcc2, 0, tl, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmpeq_fcc3, 0, tl, env, i128, i128)
 #endif
 DEF_HELPER_2(raise_exception, noreturn, env, int)
 
-DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_RWG, f64, env, f64, f64)
-DEF_HELPER_FLAGS_3(fsubd, TCG_CALL_NO_RWG, f64, env, f64, f64)
-DEF_HELPER_FLAGS_3(fmuld, TCG_CALL_NO_RWG, f64, env, f64, f64)
-DEF_HELPER_FLAGS_3(fdivd, 

[PULL 44/57] target/sparc: Use i128 for FqTOd, FqTOx

2024-02-01 Thread Richard Henderson
Signed-off-by: Richard Henderson 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-10-richard.hender...@linaro.org>
---
 target/sparc/helper.h | 4 ++--
 target/sparc/fop_helper.c | 8 
 target/sparc/translate.c  | 7 ---
 3 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index e770107eb0..4cb3451878 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -100,7 +100,7 @@ DEF_HELPER_FLAGS_2(fdtos, TCG_CALL_NO_RWG, f32, env, f64)
 DEF_HELPER_FLAGS_2(fstod, TCG_CALL_NO_RWG, f64, env, f32)
 DEF_HELPER_FLAGS_2(fqtos, TCG_CALL_NO_RWG, f32, env, i128)
 DEF_HELPER_FLAGS_2(fstoq, TCG_CALL_NO_RWG, void, env, f32)
-DEF_HELPER_FLAGS_1(fqtod, TCG_CALL_NO_RWG, f64, env)
+DEF_HELPER_FLAGS_2(fqtod, TCG_CALL_NO_RWG, f64, env, i128)
 DEF_HELPER_FLAGS_2(fdtoq, TCG_CALL_NO_RWG, void, env, f64)
 DEF_HELPER_FLAGS_2(fstoi, TCG_CALL_NO_RWG, s32, env, f32)
 DEF_HELPER_FLAGS_2(fdtoi, TCG_CALL_NO_RWG, s32, env, f64)
@@ -108,7 +108,7 @@ DEF_HELPER_FLAGS_2(fqtoi, TCG_CALL_NO_RWG, s32, env, i128)
 #ifdef TARGET_SPARC64
 DEF_HELPER_FLAGS_2(fstox, TCG_CALL_NO_RWG, s64, env, f32)
 DEF_HELPER_FLAGS_2(fdtox, TCG_CALL_NO_RWG, s64, env, f64)
-DEF_HELPER_FLAGS_1(fqtox, TCG_CALL_NO_RWG, s64, env)
+DEF_HELPER_FLAGS_2(fqtox, TCG_CALL_NO_RWG, s64, env, i128)
 
 DEF_HELPER_FLAGS_2(fpmerge, TCG_CALL_NO_RWG_SE, i64, i64, i64)
 DEF_HELPER_FLAGS_2(fmul8x16, TCG_CALL_NO_RWG_SE, i64, i64, i64)
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
index 657a14575d..9f39b933e8 100644
--- a/target/sparc/fop_helper.c
+++ b/target/sparc/fop_helper.c
@@ -190,9 +190,9 @@ void helper_fstoq(CPUSPARCState *env, float32 src)
 QT0 = float32_to_float128(src, >fp_status);
 }
 
-float64 helper_fqtod(CPUSPARCState *env)
+float64 helper_fqtod(CPUSPARCState *env, Int128 src)
 {
-return float128_to_float64(QT1, >fp_status);
+return float128_to_float64(f128_in(src), >fp_status);
 }
 
 void helper_fdtoq(CPUSPARCState *env, float64 src)
@@ -227,9 +227,9 @@ int64_t helper_fdtox(CPUSPARCState *env, float64 src)
 return float64_to_int64_round_to_zero(src, >fp_status);
 }
 
-int64_t helper_fqtox(CPUSPARCState *env)
+int64_t helper_fqtox(CPUSPARCState *env, Int128 src)
 {
-return float128_to_int64_round_to_zero(QT1, >fp_status);
+return float128_to_int64_round_to_zero(f128_in(src), >fp_status);
 }
 #endif
 
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index f70efb29a1..6f75f4d5d6 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -4717,8 +4717,9 @@ TRANS(FqTOs, ALL, do_env_fq, a, gen_helper_fqtos)
 TRANS(FqTOi, ALL, do_env_fq, a, gen_helper_fqtoi)
 
 static bool do_env_dq(DisasContext *dc, arg_r_r *a,
-  void (*func)(TCGv_i64, TCGv_env))
+  void (*func)(TCGv_i64, TCGv_env, TCGv_i128))
 {
+TCGv_i128 src;
 TCGv_i64 dst;
 
 if (gen_trap_ifnofpu(dc)) {
@@ -4729,9 +4730,9 @@ static bool do_env_dq(DisasContext *dc, arg_r_r *a,
 }
 
 gen_op_clear_ieee_excp_and_FTT();
-gen_op_load_fpr_QT1(QFPREG(a->rs));
+src = gen_load_fpr_Q(dc, a->rs);
 dst = gen_dest_fpr_D(dc, a->rd);
-func(dst, tcg_env);
+func(dst, tcg_env, src);
 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
 gen_store_fpr_D(dc, a->rd, dst);
 return advance_pc(dc);
-- 
2.34.1




[PULL 33/57] include/exec: Change cpu_mmu_index argument to CPUState

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/exec/cpu-all.h|  2 +-
 include/exec/cpu-common.h |  3 +--
 target/sparc/cpu.h|  2 +-
 accel/tcg/cputlb.c| 22 +---
 semihosting/uaccess.c |  2 +-
 target/cris/translate.c   |  2 +-
 target/hppa/mem_helper.c  |  2 +-
 target/hppa/op_helper.c   |  8 +++---
 target/i386/tcg/translate.c   |  2 +-
 target/loongarch/tcg/tlb_helper.c |  4 +--
 target/m68k/op_helper.c   |  2 +-
 target/microblaze/helper.c|  3 +--
 target/microblaze/mmu.c   |  2 +-
 target/microblaze/translate.c |  2 +-
 target/nios2/translate.c  |  2 +-
 target/openrisc/translate.c   |  2 +-
 target/sparc/ldst_helper.c|  2 +-
 target/sparc/mmu_helper.c |  2 +-
 target/tricore/helper.c   |  2 +-
 target/tricore/translate.c|  2 +-
 target/xtensa/mmu_helper.c|  2 +-
 accel/tcg/ldst_common.c.inc   | 42 ---
 22 files changed, 65 insertions(+), 49 deletions(-)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 80c0d0699b..bc05dce7ab 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -311,7 +311,7 @@ CPUArchState *cpu_copy(CPUArchState *env);
 #define TLB_MMIO(1 << (TARGET_PAGE_BITS_MIN - 2))
 #define TLB_WATCHPOINT  0
 
-static inline int cpu_mmu_index(CPUArchState *env, bool ifetch)
+static inline int cpu_mmu_index(CPUState *cs, bool ifetch)
 {
 return MMU_USER_IDX;
 }
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index cdfbe994fd..9ead1be100 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -275,9 +275,8 @@ static inline CPUState *env_cpu(CPUArchState *env)
  * The user-only version of this function is inline in cpu-all.h,
  * where it always returns MMU_USER_IDX.
  */
-static inline int cpu_mmu_index(CPUArchState *env, bool ifetch)
+static inline int cpu_mmu_index(CPUState *cs, bool ifetch)
 {
-CPUState *cs = env_cpu(env);
 int ret = cs->cc->mmu_index(cs, ifetch);
 tcg_debug_assert(ret >= 0 && ret < NB_MMU_MODES);
 return ret;
diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index 51856152fa..1e076f6355 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -755,7 +755,7 @@ static inline void cpu_get_tb_cpu_state(CPUSPARCState *env, 
vaddr *pc,
 uint32_t flags;
 *pc = env->pc;
 *cs_base = env->npc;
-flags = cpu_mmu_index(env, false);
+flags = cpu_mmu_index(env_cpu(env), false);
 #ifndef CONFIG_USER_ONLY
 if (cpu_supervisor_mode(env)) {
 flags |= TB_FLAG_SUPER;
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 3facfcbb24..047cd2cc0a 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1601,7 +1601,7 @@ tb_page_addr_t get_page_addr_code_hostp(CPUArchState 
*env, vaddr addr,
 void *p;
 
 (void)probe_access_internal(env_cpu(env), addr, 1, MMU_INST_FETCH,
-cpu_mmu_index(env, true), false,
+cpu_mmu_index(env_cpu(env), true), false,
 , , 0, false);
 if (p == NULL) {
 return -1;
@@ -2959,26 +2959,30 @@ static void do_st16_mmu(CPUState *cpu, vaddr addr, 
Int128 val,
 
 uint32_t cpu_ldub_code(CPUArchState *env, abi_ptr addr)
 {
-MemOpIdx oi = make_memop_idx(MO_UB, cpu_mmu_index(env, true));
-return do_ld1_mmu(env_cpu(env), addr, oi, 0, MMU_INST_FETCH);
+CPUState *cs = env_cpu(env);
+MemOpIdx oi = make_memop_idx(MO_UB, cpu_mmu_index(cs, true));
+return do_ld1_mmu(cs, addr, oi, 0, MMU_INST_FETCH);
 }
 
 uint32_t cpu_lduw_code(CPUArchState *env, abi_ptr addr)
 {
-MemOpIdx oi = make_memop_idx(MO_TEUW, cpu_mmu_index(env, true));
-return do_ld2_mmu(env_cpu(env), addr, oi, 0, MMU_INST_FETCH);
+CPUState *cs = env_cpu(env);
+MemOpIdx oi = make_memop_idx(MO_TEUW, cpu_mmu_index(cs, true));
+return do_ld2_mmu(cs, addr, oi, 0, MMU_INST_FETCH);
 }
 
 uint32_t cpu_ldl_code(CPUArchState *env, abi_ptr addr)
 {
-MemOpIdx oi = make_memop_idx(MO_TEUL, cpu_mmu_index(env, true));
-return do_ld4_mmu(env_cpu(env), addr, oi, 0, MMU_INST_FETCH);
+CPUState *cs = env_cpu(env);
+MemOpIdx oi = make_memop_idx(MO_TEUL, cpu_mmu_index(cs, true));
+return do_ld4_mmu(cs, addr, oi, 0, MMU_INST_FETCH);
 }
 
 uint64_t cpu_ldq_code(CPUArchState *env, abi_ptr addr)
 {
-MemOpIdx oi = make_memop_idx(MO_TEUQ, cpu_mmu_index(env, true));
-return do_ld8_mmu(env_cpu(env), addr, oi, 0, MMU_INST_FETCH);
+CPUState *cs = env_cpu(env);
+MemOpIdx oi = make_memop_idx(MO_TEUQ, cpu_mmu_index(cs, true));
+return do_ld8_mmu(cs, addr, oi, 0, MMU_INST_FETCH);
 }
 
 uint8_t cpu_ldb_code_mmu(CPUArchState *env, abi_ptr addr,
diff --git a/semihosting/uaccess.c b/semihosting/uaccess.c
index 5d889f9263..dc587d73bc 100644
--- a/semihosting/uaccess.c
+++ 

[PULL 34/57] tests/tcg: Fix the /proc/self/mem probing in the PROT_NONE gdbstub test

2024-02-01 Thread Richard Henderson
From: Ilya Leoshkevich 

The `if not probe_proc_self_mem` check never passes, because
probe_proc_self_mem is a function object, which is a truthy value.
Add parentheses in order to perform a function call.

Fixes: dc84d50a7f9b ("tests/tcg: Add the PROT_NONE gdbstub test")
Signed-off-by: Ilya Leoshkevich 
Message-Id: <20240131220245.235993-1-...@linux.ibm.com>
Signed-off-by: Richard Henderson 
---
 tests/tcg/multiarch/gdbstub/prot-none.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/tcg/multiarch/gdbstub/prot-none.py 
b/tests/tcg/multiarch/gdbstub/prot-none.py
index e829d3ebc5..7e264589cb 100644
--- a/tests/tcg/multiarch/gdbstub/prot-none.py
+++ b/tests/tcg/multiarch/gdbstub/prot-none.py
@@ -20,7 +20,7 @@ def probe_proc_self_mem():
 
 def run_test():
 """Run through the tests one by one"""
-if not probe_proc_self_mem:
+if not probe_proc_self_mem():
 print("SKIP: /proc/self/mem is not usable")
 exit(0)
 gdb.Breakpoint("break_here")
-- 
2.34.1




[PULL 47/57] target/sparc: Use i128 for FdTOq, FxTOq

2024-02-01 Thread Richard Henderson
Signed-off-by: Richard Henderson 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-13-richard.hender...@linaro.org>
---
 target/sparc/helper.h | 4 ++--
 target/sparc/fop_helper.c | 8 
 target/sparc/translate.c  | 9 +
 3 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index 5e93342583..20f67f89b0 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -94,14 +94,14 @@ DEF_HELPER_FLAGS_2(fitos, TCG_CALL_NO_RWG, f32, env, s32)
 #ifdef TARGET_SPARC64
 DEF_HELPER_FLAGS_2(fxtos, TCG_CALL_NO_RWG, f32, env, s64)
 DEF_HELPER_FLAGS_2(fxtod, TCG_CALL_NO_RWG, f64, env, s64)
-DEF_HELPER_FLAGS_2(fxtoq, TCG_CALL_NO_RWG, void, env, s64)
+DEF_HELPER_FLAGS_2(fxtoq, TCG_CALL_NO_RWG, i128, env, s64)
 #endif
 DEF_HELPER_FLAGS_2(fdtos, TCG_CALL_NO_RWG, f32, env, f64)
 DEF_HELPER_FLAGS_2(fstod, TCG_CALL_NO_RWG, f64, env, f32)
 DEF_HELPER_FLAGS_2(fqtos, TCG_CALL_NO_RWG, f32, env, i128)
 DEF_HELPER_FLAGS_2(fstoq, TCG_CALL_NO_RWG, i128, env, f32)
 DEF_HELPER_FLAGS_2(fqtod, TCG_CALL_NO_RWG, f64, env, i128)
-DEF_HELPER_FLAGS_2(fdtoq, TCG_CALL_NO_RWG, void, env, f64)
+DEF_HELPER_FLAGS_2(fdtoq, TCG_CALL_NO_RWG, i128, env, f64)
 DEF_HELPER_FLAGS_2(fstoi, TCG_CALL_NO_RWG, s32, env, f32)
 DEF_HELPER_FLAGS_2(fdtoi, TCG_CALL_NO_RWG, s32, env, f64)
 DEF_HELPER_FLAGS_2(fqtoi, TCG_CALL_NO_RWG, s32, env, i128)
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
index c7dc835d28..9a0110e201 100644
--- a/target/sparc/fop_helper.c
+++ b/target/sparc/fop_helper.c
@@ -163,9 +163,9 @@ float64 helper_fxtod(CPUSPARCState *env, int64_t src)
 return int64_to_float64(src, >fp_status);
 }
 
-void helper_fxtoq(CPUSPARCState *env, int64_t src)
+Int128 helper_fxtoq(CPUSPARCState *env, int64_t src)
 {
-QT0 = int64_to_float128(src, >fp_status);
+return f128_ret(int64_to_float128(src, >fp_status));
 }
 #endif
 
@@ -195,9 +195,9 @@ float64 helper_fqtod(CPUSPARCState *env, Int128 src)
 return float128_to_float64(f128_in(src), >fp_status);
 }
 
-void helper_fdtoq(CPUSPARCState *env, float64 src)
+Int128 helper_fdtoq(CPUSPARCState *env, float64 src)
 {
-QT0 = float64_to_float128(src, >fp_status);
+return f128_ret(float64_to_float128(src, >fp_status));
 }
 
 /* Float to integer conversion.  */
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index 6522a9b0c8..d478a2fcd0 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -4750,9 +4750,10 @@ TRANS(FiTOq, ALL, do_env_qf, a, gen_helper_fitoq)
 TRANS(FsTOq, ALL, do_env_qf, a, gen_helper_fstoq)
 
 static bool do_env_qd(DisasContext *dc, arg_r_r *a,
-  void (*func)(TCGv_env, TCGv_i64))
+  void (*func)(TCGv_i128, TCGv_env, TCGv_i64))
 {
 TCGv_i64 src;
+TCGv_i128 dst;
 
 if (gen_trap_ifnofpu(dc)) {
 return true;
@@ -4763,9 +4764,9 @@ static bool do_env_qd(DisasContext *dc, arg_r_r *a,
 
 gen_op_clear_ieee_excp_and_FTT();
 src = gen_load_fpr_D(dc, a->rs);
-func(tcg_env, src);
-gen_op_store_QT0_fpr(QFPREG(a->rd));
-gen_update_fprs_dirty(dc, QFPREG(a->rd));
+dst = tcg_temp_new_i128();
+func(dst, tcg_env, src);
+gen_store_fpr_Q(dc, a->rd, dst);
 return advance_pc(dc);
 }
 
-- 
2.34.1




[PULL 52/57] target/sparc: Clear cexc and ftt in do_check_ieee_exceptions

2024-02-01 Thread Richard Henderson
Don't do the clearing explicitly before each FPop,
rather do it as part of the rest of exception handling.

Signed-off-by: Richard Henderson 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-18-richard.hender...@linaro.org>
---
 target/sparc/fop_helper.c |  2 ++
 target/sparc/translate.c  | 16 
 2 files changed, 2 insertions(+), 16 deletions(-)

diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
index 22b412adb5..64f20e78f1 100644
--- a/target/sparc/fop_helper.c
+++ b/target/sparc/fop_helper.c
@@ -50,6 +50,8 @@ static target_ulong do_check_ieee_exceptions(CPUSPARCState 
*env, uintptr_t ra)
 target_ulong status = get_float_exception_flags(>fp_status);
 target_ulong fsr = env->fsr;
 
+fsr &= FSR_FTT_CEXC_NMASK;
+
 if (unlikely(status)) {
 /* Keep exception flags clear for next time.  */
 set_float_exception_flags(0, >fp_status);
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index da4f167fa6..67bac6f65f 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -4524,7 +4524,6 @@ static bool do_env_ff(DisasContext *dc, arg_r_r *a,
 return true;
 }
 
-gen_op_clear_ieee_excp_and_FTT();
 tmp = gen_load_fpr_F(dc, a->rs);
 func(tmp, tcg_env, tmp);
 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
@@ -4546,7 +4545,6 @@ static bool do_env_fd(DisasContext *dc, arg_r_r *a,
 return true;
 }
 
-gen_op_clear_ieee_excp_and_FTT();
 dst = tcg_temp_new_i32();
 src = gen_load_fpr_D(dc, a->rs);
 func(dst, tcg_env, src);
@@ -4590,7 +4588,6 @@ static bool do_env_dd(DisasContext *dc, arg_r_r *a,
 return true;
 }
 
-gen_op_clear_ieee_excp_and_FTT();
 dst = gen_dest_fpr_D(dc, a->rd);
 src = gen_load_fpr_D(dc, a->rs);
 func(dst, tcg_env, src);
@@ -4613,7 +4610,6 @@ static bool do_env_df(DisasContext *dc, arg_r_r *a,
 return true;
 }
 
-gen_op_clear_ieee_excp_and_FTT();
 dst = gen_dest_fpr_D(dc, a->rd);
 src = gen_load_fpr_F(dc, a->rs);
 func(dst, tcg_env, src);
@@ -4661,8 +4657,6 @@ static bool do_env_qq(DisasContext *dc, arg_r_r *a,
 return true;
 }
 
-gen_op_clear_ieee_excp_and_FTT();
-
 t = gen_load_fpr_Q(dc, a->rs);
 func(t, tcg_env, t);
 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
@@ -4685,7 +4679,6 @@ static bool do_env_fq(DisasContext *dc, arg_r_r *a,
 return true;
 }
 
-gen_op_clear_ieee_excp_and_FTT();
 src = gen_load_fpr_Q(dc, a->rs);
 dst = tcg_temp_new_i32();
 func(dst, tcg_env, src);
@@ -4710,7 +4703,6 @@ static bool do_env_dq(DisasContext *dc, arg_r_r *a,
 return true;
 }
 
-gen_op_clear_ieee_excp_and_FTT();
 src = gen_load_fpr_Q(dc, a->rs);
 dst = gen_dest_fpr_D(dc, a->rd);
 func(dst, tcg_env, src);
@@ -4808,7 +4800,6 @@ static bool do_env_fff(DisasContext *dc, arg_r_r_r *a,
 return true;
 }
 
-gen_op_clear_ieee_excp_and_FTT();
 src1 = gen_load_fpr_F(dc, a->rs1);
 src2 = gen_load_fpr_F(dc, a->rs2);
 func(src1, tcg_env, src1, src2);
@@ -4903,7 +4894,6 @@ static bool do_env_ddd(DisasContext *dc, arg_r_r_r *a,
 return true;
 }
 
-gen_op_clear_ieee_excp_and_FTT();
 dst = gen_dest_fpr_D(dc, a->rd);
 src1 = gen_load_fpr_D(dc, a->rs1);
 src2 = gen_load_fpr_D(dc, a->rs2);
@@ -4930,7 +4920,6 @@ static bool trans_FsMULd(DisasContext *dc, arg_r_r_r *a)
 return raise_unimpfpop(dc);
 }
 
-gen_op_clear_ieee_excp_and_FTT();
 dst = gen_dest_fpr_D(dc, a->rd);
 src1 = gen_load_fpr_F(dc, a->rs1);
 src2 = gen_load_fpr_F(dc, a->rs2);
@@ -4972,7 +4961,6 @@ static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a,
 return true;
 }
 
-gen_op_clear_ieee_excp_and_FTT();
 src1 = gen_load_fpr_Q(dc, a->rs1);
 src2 = gen_load_fpr_Q(dc, a->rs2);
 func(src1, tcg_env, src1, src2);
@@ -4998,7 +4986,6 @@ static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a)
 return true;
 }
 
-gen_op_clear_ieee_excp_and_FTT();
 src1 = gen_load_fpr_D(dc, a->rs1);
 src2 = gen_load_fpr_D(dc, a->rs2);
 dst = tcg_temp_new_i128();
@@ -5087,7 +5074,6 @@ static bool do_fcmps(DisasContext *dc, arg_FCMPs *a, bool 
e)
 return true;
 }
 
-gen_op_clear_ieee_excp_and_FTT();
 src1 = gen_load_fpr_F(dc, a->rs1);
 src2 = gen_load_fpr_F(dc, a->rs2);
 if (e) {
@@ -5112,7 +5098,6 @@ static bool do_fcmpd(DisasContext *dc, arg_FCMPd *a, bool 
e)
 return true;
 }
 
-gen_op_clear_ieee_excp_and_FTT();
 src1 = gen_load_fpr_D(dc, a->rs1);
 src2 = gen_load_fpr_D(dc, a->rs2);
 if (e) {
@@ -5140,7 +5125,6 @@ static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool 
e)
 return true;
 }
 
-gen_op_clear_ieee_excp_and_FTT();
 src1 = gen_load_fpr_Q(dc, a->rs1);
 src2 = gen_load_fpr_Q(dc, a->rs2);
 if (e) {
-- 
2.34.1




[PULL 36/57] target/sparc: Use tcg_gen_qemu_{ld, st}_i128 for ASI_M_BCOPY

2024-02-01 Thread Richard Henderson
Align the operation to the 32-byte cacheline.
Use 2 pair of i128 instead of 8 pair of i32.

Signed-off-by: Richard Henderson 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-2-richard.hender...@linaro.org>
---
 target/sparc/translate.c | 43 +++-
 1 file changed, 25 insertions(+), 18 deletions(-)

diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index 97184fa403..1082aabc14 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -1727,28 +1727,35 @@ static void gen_st_asi(DisasContext *dc, DisasASI *da, 
TCGv src, TCGv addr)
 
 case GET_ASI_BCOPY:
 assert(TARGET_LONG_BITS == 32);
-/* Copy 32 bytes from the address in SRC to ADDR.  */
-/* ??? The original qemu code suggests 4-byte alignment, dropping
-   the low bits, but the only place I can see this used is in the
-   Linux kernel with 32 byte alignment, which would make more sense
-   as a cacheline-style operation.  */
+/*
+ * Copy 32 bytes from the address in SRC to ADDR.
+ *
+ * From Ross RT625 hyperSPARC manual, section 4.6:
+ * "Block Copy and Block Fill will work only on cache line boundaries."
+ *
+ * It does not specify if an unaliged address is truncated or trapped.
+ * Previous qemu behaviour was to truncate to 4 byte alignment, which
+ * is obviously wrong.  The only place I can see this used is in the
+ * Linux kernel which begins with page alignment, advancing by 32,
+ * so is always aligned.  Assume truncation as the simpler option.
+ *
+ * Since the loads and stores are paired, allow the copy to happen
+ * in the host endianness.  The copy need not be atomic.
+ */
 {
+MemOp mop = MO_128 | MO_ATOM_IFALIGN_PAIR;
 TCGv saddr = tcg_temp_new();
 TCGv daddr = tcg_temp_new();
-TCGv four = tcg_constant_tl(4);
-TCGv_i32 tmp = tcg_temp_new_i32();
-int i;
+TCGv_i128 tmp = tcg_temp_new_i128();
 
-tcg_gen_andi_tl(saddr, src, -4);
-tcg_gen_andi_tl(daddr, addr, -4);
-for (i = 0; i < 32; i += 4) {
-/* Since the loads and stores are paired, allow the
-   copy to happen in the host endianness.  */
-tcg_gen_qemu_ld_i32(tmp, saddr, da->mem_idx, MO_UL);
-tcg_gen_qemu_st_i32(tmp, daddr, da->mem_idx, MO_UL);
-tcg_gen_add_tl(saddr, saddr, four);
-tcg_gen_add_tl(daddr, daddr, four);
-}
+tcg_gen_andi_tl(saddr, src, -32);
+tcg_gen_andi_tl(daddr, addr, -32);
+tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop);
+tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop);
+tcg_gen_addi_tl(saddr, saddr, 16);
+tcg_gen_addi_tl(daddr, daddr, 16);
+tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop);
+tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop);
 }
 break;
 
-- 
2.34.1




[PULL 55/57] target/sparc: Remove cpu_fsr

2024-02-01 Thread Richard Henderson
Drop this field as a tcg global, loading it explicitly in the
few places required.  This means that all FPop helpers may
once again be TCG_CALL_NO_WG.

Signed-off-by: Richard Henderson 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-21-richard.hender...@linaro.org>
---
 target/sparc/helper.h | 120 +++---
 target/sparc/fop_helper.c |   9 ++-
 target/sparc/translate.c  |  98 ---
 3 files changed, 114 insertions(+), 113 deletions(-)

diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index 7466164468..c8e14fe371 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -36,79 +36,79 @@ DEF_HELPER_FLAGS_4(ld_asi, TCG_CALL_NO_WG, i64, env, tl, 
int, i32)
 DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32)
 #endif
 DEF_HELPER_FLAGS_1(get_fsr, TCG_CALL_NO_WG_SE, tl, env)
-DEF_HELPER_FLAGS_2(set_fsr_noftt, 0, void, env, tl)
-DEF_HELPER_FLAGS_2(fsqrts, 0, f32, env, f32)
-DEF_HELPER_FLAGS_2(fsqrtd, 0, f64, env, f64)
-DEF_HELPER_FLAGS_2(fsqrtq, 0, i128, env, i128)
-DEF_HELPER_FLAGS_3(fcmps, 0, tl, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmpd, 0, tl, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmpes, 0, tl, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmped, 0, tl, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmpq, 0, tl, env, i128, i128)
-DEF_HELPER_FLAGS_3(fcmpeq, 0, tl, env, i128, i128)
+DEF_HELPER_FLAGS_2(set_fsr_noftt, TCG_CALL_NO_RWG, void, env, tl)
+DEF_HELPER_FLAGS_2(fsqrts, TCG_CALL_NO_WG, f32, env, f32)
+DEF_HELPER_FLAGS_2(fsqrtd, TCG_CALL_NO_WG, f64, env, f64)
+DEF_HELPER_FLAGS_2(fsqrtq, TCG_CALL_NO_WG, i128, env, i128)
+DEF_HELPER_FLAGS_3(fcmps, TCG_CALL_NO_WG, void, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, void, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmpes, TCG_CALL_NO_WG, void, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, void, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, void, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, void, env, i128, i128)
 #ifdef TARGET_SPARC64
-DEF_HELPER_FLAGS_3(fcmps_fcc1, 0, tl, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmps_fcc2, 0, tl, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmps_fcc3, 0, tl, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmpd_fcc1, 0, tl, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmpd_fcc2, 0, tl, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmpd_fcc3, 0, tl, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmpes_fcc1, 0, tl, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmpes_fcc2, 0, tl, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmpes_fcc3, 0, tl, env, f32, f32)
-DEF_HELPER_FLAGS_3(fcmped_fcc1, 0, tl, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmped_fcc2, 0, tl, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmped_fcc3, 0, tl, env, f64, f64)
-DEF_HELPER_FLAGS_3(fcmpq_fcc1, 0, tl, env, i128, i128)
-DEF_HELPER_FLAGS_3(fcmpq_fcc2, 0, tl, env, i128, i128)
-DEF_HELPER_FLAGS_3(fcmpq_fcc3, 0, tl, env, i128, i128)
-DEF_HELPER_FLAGS_3(fcmpeq_fcc1, 0, tl, env, i128, i128)
-DEF_HELPER_FLAGS_3(fcmpeq_fcc2, 0, tl, env, i128, i128)
-DEF_HELPER_FLAGS_3(fcmpeq_fcc3, 0, tl, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmps_fcc1, TCG_CALL_NO_WG, void, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmps_fcc2, TCG_CALL_NO_WG, void, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmps_fcc3, TCG_CALL_NO_WG, void, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmpd_fcc1, TCG_CALL_NO_WG, void, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmpd_fcc2, TCG_CALL_NO_WG, void, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmpd_fcc3, TCG_CALL_NO_WG, void, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmpes_fcc1, TCG_CALL_NO_WG, void, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmpes_fcc2, TCG_CALL_NO_WG, void, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmpes_fcc3, TCG_CALL_NO_WG, void, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmped_fcc1, TCG_CALL_NO_WG, void, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmped_fcc2, TCG_CALL_NO_WG, void, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmped_fcc3, TCG_CALL_NO_WG, void, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmpq_fcc1, TCG_CALL_NO_WG, void, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmpq_fcc2, TCG_CALL_NO_WG, void, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmpq_fcc3, TCG_CALL_NO_WG, void, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmpeq_fcc1, TCG_CALL_NO_WG, void, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmpeq_fcc2, TCG_CALL_NO_WG, void, env, i128, i128)
+DEF_HELPER_FLAGS_3(fcmpeq_fcc3, TCG_CALL_NO_WG, void, env, i128, i128)
 #endif
 DEF_HELPER_2(raise_exception, noreturn, env, int)
 
-DEF_HELPER_FLAGS_3(faddd, 0, f64, env, f64, f64)
-DEF_HELPER_FLAGS_3(fsubd, 0, f64, env, f64, f64)
-DEF_HELPER_FLAGS_3(fmuld, 0, f64, env, f64, f64)
-DEF_HELPER_FLAGS_3(fdivd, 0, f64, env, f64, f64)
+DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_WG, f64, env, f64, f64)
+DEF_HELPER_FLAGS_3(fsubd, TCG_CALL_NO_WG, f64, env, f64, f64)
+DEF_HELPER_FLAGS_3(fmuld, TCG_CALL_NO_WG, f64, env, f64, f64)
+DEF_HELPER_FLAGS_3(fdivd, TCG_CALL_NO_WG, f64, env, f64, f64)
 
-DEF_HELPER_FLAGS_3(faddq, 0, i128, env, i128, i128)
-DEF_HELPER_FLAGS_3(fsubq, 0, i128, env, i128, i128)
-DEF_HELPER_FLAGS_3(fmulq, 0, i128, env, i128, 

[PULL 15/57] target/mips: Pass ptw_mmu_idx down from mips_cpu_tlb_fill

2024-02-01 Thread Richard Henderson
Rather than adjust env->hflags so that the value computed
by cpu_mmu_index() changes, compute the mmu_idx that we
want directly and pass it down.

Introduce symbolic constants for MMU_{KERNEL,ERL}_IDX.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/mips/cpu.h   |  4 +++-
 target/mips/tcg/sysemu/tlb_helper.c | 32 -
 2 files changed, 16 insertions(+), 20 deletions(-)

diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 1163a71f3c..3ba8dccd2d 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -1242,12 +1242,14 @@ uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState 
*env);
  * MMU modes definitions. We carefully match the indices with our
  * hflags layout.
  */
+#define MMU_KERNEL_IDX 0
 #define MMU_USER_IDX 2
+#define MMU_ERL_IDX 3
 
 static inline int hflags_mmu_index(uint32_t hflags)
 {
 if (hflags & MIPS_HFLAG_ERL) {
-return 3; /* ERL */
+return MMU_ERL_IDX;
 } else {
 return hflags & MIPS_HFLAG_KSU;
 }
diff --git a/target/mips/tcg/sysemu/tlb_helper.c 
b/target/mips/tcg/sysemu/tlb_helper.c
index 4ede904800..b715449114 100644
--- a/target/mips/tcg/sysemu/tlb_helper.c
+++ b/target/mips/tcg/sysemu/tlb_helper.c
@@ -623,7 +623,7 @@ static uint64_t get_tlb_entry_layout(CPUMIPSState *env, 
uint64_t entry,
 static int walk_directory(CPUMIPSState *env, uint64_t *vaddr,
 int directory_index, bool *huge_page, bool *hgpg_directory_hit,
 uint64_t *pw_entrylo0, uint64_t *pw_entrylo1,
-unsigned directory_shift, unsigned leaf_shift)
+unsigned directory_shift, unsigned leaf_shift, int ptw_mmu_idx)
 {
 int dph = (env->CP0_PWCtl >> CP0PC_DPH) & 0x1;
 int psn = (env->CP0_PWCtl >> CP0PC_PSN) & 0x3F;
@@ -638,8 +638,7 @@ static int walk_directory(CPUMIPSState *env, uint64_t 
*vaddr,
 uint64_t w = 0;
 
 if (get_physical_address(env, , , *vaddr, MMU_DATA_LOAD,
- cpu_mmu_index(env, false)) !=
- TLBRET_MATCH) {
+ ptw_mmu_idx) != TLBRET_MATCH) {
 /* wrong base address */
 return 0;
 }
@@ -666,8 +665,7 @@ static int walk_directory(CPUMIPSState *env, uint64_t 
*vaddr,
 *pw_entrylo0 = entry;
 }
 if (get_physical_address(env, , , vaddr2, MMU_DATA_LOAD,
- cpu_mmu_index(env, false)) !=
- TLBRET_MATCH) {
+ ptw_mmu_idx) != TLBRET_MATCH) {
 return 0;
 }
 if (!get_pte(env, vaddr2, leafentry_size, )) {
@@ -690,7 +688,7 @@ static int walk_directory(CPUMIPSState *env, uint64_t 
*vaddr,
 }
 
 static bool page_table_walk_refill(CPUMIPSState *env, vaddr address,
-   int mmu_idx)
+   int ptw_mmu_idx)
 {
 int gdw = (env->CP0_PWSize >> CP0PS_GDW) & 0x3F;
 int udw = (env->CP0_PWSize >> CP0PS_UDW) & 0x3F;
@@ -776,7 +774,7 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr 
address,
 vaddr |= goffset;
 switch (walk_directory(env, , pf_gdw, _page, _gdhit,
_entrylo0, _entrylo1,
-   directory_shift, leaf_shift))
+   directory_shift, leaf_shift, ptw_mmu_idx))
 {
 case 0:
 return false;
@@ -793,7 +791,7 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr 
address,
 vaddr |= uoffset;
 switch (walk_directory(env, , pf_udw, _page, _udhit,
_entrylo0, _entrylo1,
-   directory_shift, leaf_shift))
+   directory_shift, leaf_shift, ptw_mmu_idx))
 {
 case 0:
 return false;
@@ -810,7 +808,7 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr 
address,
 vaddr |= moffset;
 switch (walk_directory(env, , pf_mdw, _page, _mdhit,
_entrylo0, _entrylo1,
-   directory_shift, leaf_shift))
+   directory_shift, leaf_shift, ptw_mmu_idx))
 {
 case 0:
 return false;
@@ -825,8 +823,7 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr 
address,
 /* Leaf Level Page Table - First half of PTE pair */
 vaddr |= ptoffset0;
 if (get_physical_address(env, , , vaddr, MMU_DATA_LOAD,
- cpu_mmu_index(env, false)) !=
- TLBRET_MATCH) {
+ ptw_mmu_idx) != TLBRET_MATCH) {
 return false;
 }
 if (!get_pte(env, vaddr, leafentry_size, _entry)) {
@@ -838,8 +835,7 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr 
address,
 /* Leaf Level Page Table - Second half of PTE pair */
 vaddr |= ptoffset1;
 if 

[PULL 25/57] target/rx: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/rx/cpu.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/target/rx/cpu.c b/target/rx/cpu.c
index 353132dac2..5205167da1 100644
--- a/target/rx/cpu.c
+++ b/target/rx/cpu.c
@@ -64,6 +64,11 @@ static bool rx_cpu_has_work(CPUState *cs)
 (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIR);
 }
 
+static int riscv_cpu_mmu_index(CPUState *cs, bool ifunc)
+{
+return 0;
+}
+
 static void rx_cpu_reset_hold(Object *obj)
 {
 RXCPU *cpu = RX_CPU(obj);
@@ -204,6 +209,7 @@ static void rx_cpu_class_init(ObjectClass *klass, void 
*data)
 
 cc->class_by_name = rx_cpu_class_by_name;
 cc->has_work = rx_cpu_has_work;
+cc->mmu_index = riscv_cpu_mmu_index;
 cc->dump_state = rx_cpu_dump_state;
 cc->set_pc = rx_cpu_set_pc;
 cc->get_pc = rx_cpu_get_pc;
-- 
2.34.1




[PULL 20/57] target/ppc: Split out ppc_env_mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/ppc/cpu.h|  7 ++-
 target/ppc/cpu_init.c   |  2 +-
 target/ppc/mem_helper.c | 10 +-
 target/ppc/mmu_common.c |  4 ++--
 4 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index f8101ffa29..5f4f52aec5 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1624,7 +1624,7 @@ int ppc_dcr_write(ppc_dcr_t *dcr_env, int dcrn, uint32_t 
val);
 
 /* MMU modes definitions */
 #define MMU_USER_IDX 0
-static inline int cpu_mmu_index(CPUPPCState *env, bool ifetch)
+static inline int ppc_env_mmu_index(CPUPPCState *env, bool ifetch)
 {
 #ifdef CONFIG_USER_ONLY
 return MMU_USER_IDX;
@@ -1633,6 +1633,11 @@ static inline int cpu_mmu_index(CPUPPCState *env, bool 
ifetch)
 #endif
 }
 
+static inline int cpu_mmu_index(CPUPPCState *env, bool ifetch)
+{
+return ppc_env_mmu_index(env, ifetch);
+}
+
 /* Compatibility modes */
 #if defined(TARGET_PPC64)
 bool ppc_check_compat(PowerPCCPU *cpu, uint32_t compat_pvr,
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 23eb5522b6..86c8031765 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -7457,7 +7457,7 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
 qemu_fprintf(f, "MSR " TARGET_FMT_lx " HID0 " TARGET_FMT_lx "  HF "
  "%08x iidx %d didx %d\n",
  env->msr, env->spr[SPR_HID0], env->hflags,
- cpu_mmu_index(env, true), cpu_mmu_index(env, false));
+ ppc_env_mmu_index(env, true), ppc_env_mmu_index(env, false));
 #if !defined(CONFIG_USER_ONLY)
 if (env->tb_env) {
 qemu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64
diff --git a/target/ppc/mem_helper.c b/target/ppc/mem_helper.c
index c7535481d6..ea7e8443a8 100644
--- a/target/ppc/mem_helper.c
+++ b/target/ppc/mem_helper.c
@@ -83,7 +83,7 @@ static void *probe_contiguous(CPUPPCState *env, target_ulong 
addr, uint32_t nb,
 void helper_lmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
 {
 uintptr_t raddr = GETPC();
-int mmu_idx = cpu_mmu_index(env, false);
+int mmu_idx = ppc_env_mmu_index(env, false);
 void *host = probe_contiguous(env, addr, (32 - reg) * 4,
   MMU_DATA_LOAD, mmu_idx, raddr);
 
@@ -105,7 +105,7 @@ void helper_lmw(CPUPPCState *env, target_ulong addr, 
uint32_t reg)
 void helper_stmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
 {
 uintptr_t raddr = GETPC();
-int mmu_idx = cpu_mmu_index(env, false);
+int mmu_idx = ppc_env_mmu_index(env, false);
 void *host = probe_contiguous(env, addr, (32 - reg) * 4,
   MMU_DATA_STORE, mmu_idx, raddr);
 
@@ -135,7 +135,7 @@ static void do_lsw(CPUPPCState *env, target_ulong addr, 
uint32_t nb,
 return;
 }
 
-mmu_idx = cpu_mmu_index(env, false);
+mmu_idx = ppc_env_mmu_index(env, false);
 host = probe_contiguous(env, addr, nb, MMU_DATA_LOAD, mmu_idx, raddr);
 
 if (likely(host)) {
@@ -224,7 +224,7 @@ void helper_stsw(CPUPPCState *env, target_ulong addr, 
uint32_t nb,
 return;
 }
 
-mmu_idx = cpu_mmu_index(env, false);
+mmu_idx = ppc_env_mmu_index(env, false);
 host = probe_contiguous(env, addr, nb, MMU_DATA_STORE, mmu_idx, raddr);
 
 if (likely(host)) {
@@ -276,7 +276,7 @@ static void dcbz_common(CPUPPCState *env, target_ulong addr,
 target_ulong mask, dcbz_size = env->dcache_line_size;
 uint32_t i;
 void *haddr;
-int mmu_idx = epid ? PPC_TLB_EPID_STORE : cpu_mmu_index(env, false);
+int mmu_idx = epid ? PPC_TLB_EPID_STORE : ppc_env_mmu_index(env, false);
 
 #if defined(TARGET_PPC64)
 /* Check for dcbz vs dcbzl on 970 */
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 6ca5d12207..751403f1c8 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1561,9 +1561,9 @@ hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr 
addr)
  * mapped by code TLBs, so we also try a MMU_INST_FETCH.
  */
 if (ppc_xlate(cpu, addr, MMU_DATA_LOAD, , , ,
-  cpu_mmu_index(>env, false), false) ||
+  ppc_env_mmu_index(>env, false), false) ||
 ppc_xlate(cpu, addr, MMU_INST_FETCH, , , ,
-  cpu_mmu_index(>env, true), false)) {
+  ppc_env_mmu_index(>env, true), false)) {
 return raddr & TARGET_PAGE_MASK;
 }
 return -1;
-- 
2.34.1




[PULL 40/57] target/sparc: Inline FNEG, FABS

2024-02-01 Thread Richard Henderson
These are simple bit manipulation insns.
Begin using i128 for float128.
Implement FMOVq with do_qq.

Signed-off-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-6-richard.hender...@linaro.org>
---
 target/sparc/helper.h |  6 
 target/sparc/fop_helper.c | 34 -
 target/sparc/translate.c  | 62 +++
 3 files changed, 30 insertions(+), 72 deletions(-)

diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index 55eff66283..74a1575d21 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -37,7 +37,6 @@ DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, 
i64, int, i32)
 #endif
 DEF_HELPER_FLAGS_1(check_ieee_exceptions, TCG_CALL_NO_WG, tl, env)
 DEF_HELPER_FLAGS_2(set_fsr, TCG_CALL_NO_RWG, void, env, tl)
-DEF_HELPER_FLAGS_1(fabss, TCG_CALL_NO_RWG_SE, f32, f32)
 DEF_HELPER_FLAGS_2(fsqrts, TCG_CALL_NO_RWG, f32, env, f32)
 DEF_HELPER_FLAGS_2(fsqrtd, TCG_CALL_NO_RWG, f64, env, f64)
 DEF_HELPER_FLAGS_3(fcmps, TCG_CALL_NO_WG, tl, env, f32, f32)
@@ -48,7 +47,6 @@ DEF_HELPER_FLAGS_1(fsqrtq, TCG_CALL_NO_RWG, void, env)
 DEF_HELPER_FLAGS_1(fcmpq, TCG_CALL_NO_WG, tl, env)
 DEF_HELPER_FLAGS_1(fcmpeq, TCG_CALL_NO_WG, tl, env)
 #ifdef TARGET_SPARC64
-DEF_HELPER_FLAGS_1(fabsd, TCG_CALL_NO_RWG_SE, f64, f64)
 DEF_HELPER_FLAGS_3(fcmps_fcc1, TCG_CALL_NO_WG, tl, env, f32, f32)
 DEF_HELPER_FLAGS_3(fcmps_fcc2, TCG_CALL_NO_WG, tl, env, f32, f32)
 DEF_HELPER_FLAGS_3(fcmps_fcc3, TCG_CALL_NO_WG, tl, env, f32, f32)
@@ -61,7 +59,6 @@ DEF_HELPER_FLAGS_3(fcmpes_fcc3, TCG_CALL_NO_WG, tl, env, f32, 
f32)
 DEF_HELPER_FLAGS_3(fcmped_fcc1, TCG_CALL_NO_WG, tl, env, f64, f64)
 DEF_HELPER_FLAGS_3(fcmped_fcc2, TCG_CALL_NO_WG, tl, env, f64, f64)
 DEF_HELPER_FLAGS_3(fcmped_fcc3, TCG_CALL_NO_WG, tl, env, f64, f64)
-DEF_HELPER_FLAGS_1(fabsq, TCG_CALL_NO_RWG, void, env)
 DEF_HELPER_FLAGS_1(fcmpq_fcc1, TCG_CALL_NO_WG, tl, env)
 DEF_HELPER_FLAGS_1(fcmpq_fcc2, TCG_CALL_NO_WG, tl, env)
 DEF_HELPER_FLAGS_1(fcmpq_fcc3, TCG_CALL_NO_WG, tl, env)
@@ -90,15 +87,12 @@ DEF_HELPER_FLAGS_3(fdivs, TCG_CALL_NO_RWG, f32, env, f32, 
f32)
 DEF_HELPER_FLAGS_3(fsmuld, TCG_CALL_NO_RWG, f64, env, f32, f32)
 DEF_HELPER_FLAGS_3(fdmulq, TCG_CALL_NO_RWG, void, env, f64, f64)
 
-DEF_HELPER_FLAGS_1(fnegs, TCG_CALL_NO_RWG_SE, f32, f32)
 DEF_HELPER_FLAGS_2(fitod, TCG_CALL_NO_RWG_SE, f64, env, s32)
 DEF_HELPER_FLAGS_2(fitoq, TCG_CALL_NO_RWG, void, env, s32)
 
 DEF_HELPER_FLAGS_2(fitos, TCG_CALL_NO_RWG, f32, env, s32)
 
 #ifdef TARGET_SPARC64
-DEF_HELPER_FLAGS_1(fnegd, TCG_CALL_NO_RWG_SE, f64, f64)
-DEF_HELPER_FLAGS_1(fnegq, TCG_CALL_NO_RWG, void, env)
 DEF_HELPER_FLAGS_2(fxtos, TCG_CALL_NO_RWG, f32, env, s64)
 DEF_HELPER_FLAGS_2(fxtod, TCG_CALL_NO_RWG, f64, env, s64)
 DEF_HELPER_FLAGS_2(fxtoq, TCG_CALL_NO_RWG, void, env, s64)
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
index 0f8aa3abcd..d6fb769769 100644
--- a/target/sparc/fop_helper.c
+++ b/target/sparc/fop_helper.c
@@ -114,23 +114,6 @@ void helper_fdmulq(CPUSPARCState *env, float64 src1, 
float64 src2)
>fp_status);
 }
 
-float32 helper_fnegs(float32 src)
-{
-return float32_chs(src);
-}
-
-#ifdef TARGET_SPARC64
-float64 helper_fnegd(float64 src)
-{
-return float64_chs(src);
-}
-
-F_HELPER(neg, q)
-{
-QT0 = float128_chs(QT1);
-}
-#endif
-
 /* Integer to float conversion.  */
 float32 helper_fitos(CPUSPARCState *env, int32_t src)
 {
@@ -229,23 +212,6 @@ int64_t helper_fqtox(CPUSPARCState *env)
 }
 #endif
 
-float32 helper_fabss(float32 src)
-{
-return float32_abs(src);
-}
-
-#ifdef TARGET_SPARC64
-float64 helper_fabsd(float64 src)
-{
-return float64_abs(src);
-}
-
-void helper_fabsq(CPUSPARCState *env)
-{
-QT0 = float128_abs(QT1);
-}
-#endif
-
 float32 helper_fsqrts(CPUSPARCState *env, float32 src)
 {
 return float32_sqrt(src, >fp_status);
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index c68f6ca94e..41952281dc 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -43,9 +43,7 @@
 #else
 # define gen_helper_clear_softint(E, S) qemu_build_not_reached()
 # define gen_helper_done(E) qemu_build_not_reached()
-# define gen_helper_fabsd(D, S) qemu_build_not_reached()
 # define gen_helper_flushw(E)   qemu_build_not_reached()
-# define gen_helper_fnegd(D, S) qemu_build_not_reached()
 # define gen_helper_rdccr(D, E) qemu_build_not_reached()
 # define gen_helper_rdcwp(D, E) qemu_build_not_reached()
 # define gen_helper_restored(E) qemu_build_not_reached()
@@ -61,7 +59,6 @@
 # define gen_helper_write_softint(E, S) qemu_build_not_reached()
 # define gen_helper_wrpil(E, S) qemu_build_not_reached()
 # define gen_helper_wrpstate(E, S)  qemu_build_not_reached()
-# define gen_helper_fabsq   

[PULL 27/57] target/s390x: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/s390x/cpu.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index 7f123863dc..49a2341acc 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -142,6 +142,11 @@ static bool s390_cpu_has_work(CPUState *cs)
 return s390_cpu_has_int(cpu);
 }
 
+static int s390x_cpu_mmu_index(CPUState *cs, bool ifetch)
+{
+return s390x_env_mmu_index(cpu_env(cs), ifetch);
+}
+
 static void s390_query_cpu_fast(CPUState *cpu, CpuInfoFast *value)
 {
 S390CPU *s390_cpu = S390_CPU(cpu);
@@ -352,6 +357,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
 scc->reset = s390_cpu_reset;
 cc->class_by_name = s390_cpu_class_by_name,
 cc->has_work = s390_cpu_has_work;
+cc->mmu_index = s390x_cpu_mmu_index;
 cc->dump_state = s390_cpu_dump_state;
 cc->query_cpu_fast = s390_query_cpu_fast;
 cc->set_pc = s390_cpu_set_pc;
-- 
2.34.1




[PULL 39/57] target/sparc: Introduce gen_{load,store}_fpr_Q

2024-02-01 Thread Richard Henderson
Use them for trans_FMOVq.

Signed-off-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-5-richard.hender...@linaro.org>
---
 target/sparc/translate.c | 25 +++--
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index 6824b5d835..c68f6ca94e 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -264,6 +264,22 @@ static TCGv_i64 gen_dest_fpr_D(DisasContext *dc, unsigned 
int dst)
 return cpu_fpr[DFPREG(dst) / 2];
 }
 
+static TCGv_i128 gen_load_fpr_Q(DisasContext *dc, unsigned int src)
+{
+TCGv_i128 ret = tcg_temp_new_i128();
+
+src = QFPREG(src);
+tcg_gen_concat_i64_i128(ret, cpu_fpr[src / 2 + 1], cpu_fpr[src / 2]);
+return ret;
+}
+
+static void gen_store_fpr_Q(DisasContext *dc, unsigned int dst, TCGv_i128 v)
+{
+dst = DFPREG(dst);
+tcg_gen_extr_i128_i64(cpu_fpr[dst / 2 + 1], cpu_fpr[dst / 2], v);
+gen_update_fprs_dirty(dc, dst);
+}
+
 static void gen_op_load_fpr_QT0(unsigned int src)
 {
 tcg_gen_st_i64(cpu_fpr[src / 2], tcg_env, offsetof(CPUSPARCState, qt0) +
@@ -4615,7 +4631,7 @@ TRANS(FsTOx, 64, do_env_df, a, gen_helper_fstox)
 
 static bool trans_FMOVq(DisasContext *dc, arg_FMOVq *a)
 {
-int rd, rs;
+TCGv_i128 t;
 
 if (!avail_64(dc)) {
 return false;
@@ -4628,11 +4644,8 @@ static bool trans_FMOVq(DisasContext *dc, arg_FMOVq *a)
 }
 
 gen_op_clear_ieee_excp_and_FTT();
-rd = QFPREG(a->rd);
-rs = QFPREG(a->rs);
-tcg_gen_mov_i64(cpu_fpr[rd / 2], cpu_fpr[rs / 2]);
-tcg_gen_mov_i64(cpu_fpr[rd / 2 + 1], cpu_fpr[rs / 2 + 1]);
-gen_update_fprs_dirty(dc, rd);
+t = gen_load_fpr_Q(dc, a->rs);
+gen_store_fpr_Q(dc, a->rd, t);
 return advance_pc(dc);
 }
 
-- 
2.34.1




[PULL 06/57] target/avr: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/avr/cpu.h | 4 +---
 target/avr/cpu.c | 6 ++
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/target/avr/cpu.h b/target/avr/cpu.h
index 7d5dd42575..4595c6bb18 100644
--- a/target/avr/cpu.h
+++ b/target/avr/cpu.h
@@ -184,9 +184,7 @@ static inline void set_avr_feature(CPUAVRState *env, int 
feature)
 env->features |= (1U << feature);
 }
 
-#define cpu_mmu_index avr_cpu_mmu_index
-
-static inline int avr_cpu_mmu_index(CPUAVRState *env, bool ifetch)
+static inline int cpu_mmu_index(CPUAVRState *env, bool ifetch)
 {
 return ifetch ? MMU_CODE_IDX : MMU_DATA_IDX;
 }
diff --git a/target/avr/cpu.c b/target/avr/cpu.c
index 1c68748b24..a40f445af2 100644
--- a/target/avr/cpu.c
+++ b/target/avr/cpu.c
@@ -50,6 +50,11 @@ static bool avr_cpu_has_work(CPUState *cs)
 && cpu_interrupts_enabled(env);
 }
 
+static int avr_cpu_mmu_index(CPUState *cs, bool ifetch)
+{
+return ifetch ? MMU_CODE_IDX : MMU_DATA_IDX;
+}
+
 static void avr_cpu_synchronize_from_tb(CPUState *cs,
 const TranslationBlock *tb)
 {
@@ -236,6 +241,7 @@ static void avr_cpu_class_init(ObjectClass *oc, void *data)
 cc->class_by_name = avr_cpu_class_by_name;
 
 cc->has_work = avr_cpu_has_work;
+cc->mmu_index = avr_cpu_mmu_index;
 cc->dump_state = avr_cpu_dump_state;
 cc->set_pc = avr_cpu_set_pc;
 cc->get_pc = avr_cpu_get_pc;
-- 
2.34.1




[PULL 10/57] target/i386: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/i386/cpu.h | 13 ++---
 target/i386/cpu.c | 10 ++
 2 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 7f0786e8b9..62bdb02378 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -2296,13 +2296,6 @@ uint64_t cpu_get_tsc(CPUX86State *env);
 #define MMU_NESTED_IDX  3
 #define MMU_PHYS_IDX4
 
-static inline int cpu_mmu_index(CPUX86State *env, bool ifetch)
-{
-return (env->hflags & HF_CPL_MASK) == 3 ? MMU_USER_IDX :
-(!(env->hflags & HF_SMAP_MASK) || (env->eflags & AC_MASK))
-? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX;
-}
-
 static inline int cpu_mmu_index_kernel(CPUX86State *env)
 {
 return !(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP_IDX :
@@ -2322,6 +2315,12 @@ static inline int cpu_mmu_index_kernel(CPUX86State *env)
 #include "hw/i386/apic.h"
 #endif
 
+int x86_cpu_mmu_index(CPUState *cs, bool ifetch);
+static inline int cpu_mmu_index(CPUX86State *env, bool ifetch)
+{
+return x86_cpu_mmu_index(env_cpu(env), ifetch);
+}
+
 static inline void cpu_get_tb_cpu_state(CPUX86State *env, vaddr *pc,
 uint64_t *cs_base, uint32_t *flags)
 {
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 03822d9ba8..280bcb7d00 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -7720,6 +7720,15 @@ static bool x86_cpu_has_work(CPUState *cs)
 return x86_cpu_pending_interrupt(cs, cs->interrupt_request) != 0;
 }
 
+int x86_cpu_mmu_index(CPUState *cs, bool ifetch)
+{
+CPUX86State *env = cpu_env(cs);
+
+return (env->hflags & HF_CPL_MASK) == 3 ? MMU_USER_IDX :
+(!(env->hflags & HF_SMAP_MASK) || (env->eflags & AC_MASK))
+? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX;
+}
+
 static void x86_disas_set_info(CPUState *cs, disassemble_info *info)
 {
 X86CPU *cpu = X86_CPU(cs);
@@ -7954,6 +7963,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, 
void *data)
 cc->class_by_name = x86_cpu_class_by_name;
 cc->parse_features = x86_cpu_parse_featurestr;
 cc->has_work = x86_cpu_has_work;
+cc->mmu_index = x86_cpu_mmu_index;
 cc->dump_state = x86_cpu_dump_state;
 cc->set_pc = x86_cpu_set_pc;
 cc->get_pc = x86_cpu_get_pc;
-- 
2.34.1




[PULL 50/57] target/sparc: Introduce cpu_get_fsr, cpu_put_fsr

2024-02-01 Thread Richard Henderson
Signed-off-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-16-richard.hender...@linaro.org>
---
 target/sparc/cpu.h  |  4 +++-
 target/sparc/helper.h   |  1 +
 linux-user/sparc/cpu_loop.c |  2 +-
 linux-user/sparc/signal.c   | 14 +-
 target/sparc/cpu.c  |  5 +++--
 target/sparc/fop_helper.c   | 21 +++--
 target/sparc/gdbstub.c  |  8 
 target/sparc/machine.c  | 36 ++--
 target/sparc/translate.c|  7 ++-
 9 files changed, 80 insertions(+), 18 deletions(-)

diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index 75c46e2736..3cf8cc2d0b 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -617,7 +617,9 @@ void sparc_restore_state_to_opc(CPUState *cs,
 const TranslationBlock *tb,
 const uint64_t *data);
 
-/* cpu-exec.c */
+/* fop_helper.c */
+target_ulong cpu_get_fsr(CPUSPARCState *);
+void cpu_put_fsr(CPUSPARCState *, target_ulong);
 
 /* win_helper.c */
 target_ulong cpu_get_psr(CPUSPARCState *env1);
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index f7aeb31169..cc8db50d75 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -36,6 +36,7 @@ DEF_HELPER_FLAGS_4(ld_asi, TCG_CALL_NO_WG, i64, env, tl, int, 
i32)
 DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32)
 #endif
 DEF_HELPER_FLAGS_1(check_ieee_exceptions, TCG_CALL_NO_WG, tl, env)
+DEF_HELPER_FLAGS_1(get_fsr, TCG_CALL_NO_WG_SE, tl, env)
 DEF_HELPER_FLAGS_2(set_fsr, TCG_CALL_NO_RWG, void, env, tl)
 DEF_HELPER_FLAGS_2(fsqrts, TCG_CALL_NO_RWG, f32, env, f32)
 DEF_HELPER_FLAGS_2(fsqrtd, TCG_CALL_NO_RWG, f64, env, f64)
diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c
index 3c1bde00dd..50424a54df 100644
--- a/linux-user/sparc/cpu_loop.c
+++ b/linux-user/sparc/cpu_loop.c
@@ -293,7 +293,7 @@ void cpu_loop (CPUSPARCState *env)
 case TT_FP_EXCP:
 {
 int code = TARGET_FPE_FLTUNK;
-target_ulong fsr = env->fsr;
+target_ulong fsr = cpu_get_fsr(env);
 
 if ((fsr & FSR_FTT_MASK) == FSR_FTT_IEEE_EXCP) {
 if (fsr & FSR_NVC) {
diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c
index dfcae707e0..c2dc1000e2 100644
--- a/linux-user/sparc/signal.c
+++ b/linux-user/sparc/signal.c
@@ -199,20 +199,21 @@ static void save_fpu(struct target_siginfo_fpu *fpu, 
CPUSPARCState *env)
 for (i = 0; i < 32; ++i) {
 __put_user(env->fpr[i].ll, >si_double_regs[i]);
 }
-__put_user(env->fsr, >si_fsr);
+__put_user(cpu_get_fsr(env), >si_fsr);
 __put_user(env->gsr, >si_gsr);
 __put_user(env->fprs, >si_fprs);
 #else
 for (i = 0; i < 16; ++i) {
 __put_user(env->fpr[i].ll, >si_double_regs[i]);
 }
-__put_user(env->fsr, >si_fsr);
+__put_user(cpu_get_fsr(env), >si_fsr);
 __put_user(0, >si_fpqdepth);
 #endif
 }
 
 static void restore_fpu(struct target_siginfo_fpu *fpu, CPUSPARCState *env)
 {
+target_ulong fsr;
 int i;
 
 #ifdef TARGET_SPARC64
@@ -230,15 +231,16 @@ static void restore_fpu(struct target_siginfo_fpu *fpu, 
CPUSPARCState *env)
 __get_user(env->fpr[i].ll, >si_double_regs[i]);
 }
 }
-__get_user(env->fsr, >si_fsr);
 __get_user(env->gsr, >si_gsr);
 env->fprs |= fprs;
 #else
 for (i = 0; i < 16; ++i) {
 __get_user(env->fpr[i].ll, >si_double_regs[i]);
 }
-__get_user(env->fsr, >si_fsr);
 #endif
+
+__get_user(fsr, >si_fsr);
+cpu_put_fsr(env, fsr);
 }
 
 #ifdef TARGET_ARCH_HAS_SETUP_FRAME
@@ -662,6 +664,7 @@ void sparc64_set_context(CPUSPARCState *env)
 __get_user(fenab, &(fpup->mcfpu_enab));
 if (fenab) {
 abi_ulong fprs;
+abi_ulong fsr;
 
 /*
  * We use the FPRS from the guest only in deciding whether
@@ -690,7 +693,8 @@ void sparc64_set_context(CPUSPARCState *env)
 __get_user(env->fpr[i].ll, &(fpup->mcfpu_fregs.dregs[i]));
 }
 }
-__get_user(env->fsr, &(fpup->mcfpu_fsr));
+__get_user(fsr, &(fpup->mcfpu_fsr));
+cpu_put_fsr(env, fsr);
 __get_user(env->gsr, &(fpup->mcfpu_gsr));
 }
 unlock_user_struct(ucp, ucp_addr, 0);
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
index afa62723fe..1897ab230d 100644
--- a/target/sparc/cpu.c
+++ b/target/sparc/cpu.c
@@ -670,7 +670,7 @@ static void sparc_cpu_dump_state(CPUState *cs, FILE *f, int 
flags)
  env->cansave, env->canrestore, env->otherwin, env->wstate,
  env->cleanwin, env->nwindows - 1 - env->cwp);
 qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: 
%016x\n",
- env->fsr, env->y, env->fprs);
+ cpu_get_fsr(env), env->y, env->fprs);
 
 #else
 qemu_fprintf(f, "psr: 

[PULL 30/57] target/tricore: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/tricore/cpu.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c
index e6d91c74b5..74e8a22b86 100644
--- a/target/tricore/cpu.c
+++ b/target/tricore/cpu.c
@@ -89,6 +89,11 @@ static bool tricore_cpu_has_work(CPUState *cs)
 return true;
 }
 
+static int tricore_cpu_mmu_index(CPUState *cs, bool ifetch)
+{
+return 0;
+}
+
 static void tricore_cpu_realizefn(DeviceState *dev, Error **errp)
 {
 CPUState *cs = CPU(dev);
@@ -194,6 +199,7 @@ static void tricore_cpu_class_init(ObjectClass *c, void 
*data)
>parent_phases);
 cc->class_by_name = tricore_cpu_class_by_name;
 cc->has_work = tricore_cpu_has_work;
+cc->mmu_index = tricore_cpu_mmu_index;
 
 cc->gdb_read_register = tricore_cpu_gdb_read_register;
 cc->gdb_write_register = tricore_cpu_gdb_write_register;
-- 
2.34.1




[PULL 31/57] target/xtensa: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/xtensa/cpu.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
index 62020b1f33..79f91819df 100644
--- a/target/xtensa/cpu.c
+++ b/target/xtensa/cpu.c
@@ -74,6 +74,11 @@ static bool xtensa_cpu_has_work(CPUState *cs)
 #endif
 }
 
+static int xtensa_cpu_mmu_index(CPUState *cs, bool ifetch)
+{
+return xtensa_get_cring(cpu_env(cs));
+}
+
 #ifdef CONFIG_USER_ONLY
 static bool abi_call0;
 
@@ -252,6 +257,7 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void 
*data)
 
 cc->class_by_name = xtensa_cpu_class_by_name;
 cc->has_work = xtensa_cpu_has_work;
+cc->mmu_index = xtensa_cpu_mmu_index;
 cc->dump_state = xtensa_cpu_dump_state;
 cc->set_pc = xtensa_cpu_set_pc;
 cc->get_pc = xtensa_cpu_get_pc;
-- 
2.34.1




[PULL 38/57] target/sparc: Remove gen_dest_fpr_F

2024-02-01 Thread Richard Henderson
Replace with tcg_temp_new_i32.

Signed-off-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Mark Cave-Ayland 
Acked-by: Mark Cave-Ayland 
Message-Id: <20231103173841.33651-4-richard.hender...@linaro.org>
---
 target/sparc/translate.c | 17 ++---
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index 3a59262c9a..6824b5d835 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -246,11 +246,6 @@ static void gen_store_fpr_F(DisasContext *dc, unsigned int 
dst, TCGv_i32 v)
 gen_update_fprs_dirty(dc, dst);
 }
 
-static TCGv_i32 gen_dest_fpr_F(DisasContext *dc)
-{
-return tcg_temp_new_i32();
-}
-
 static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src)
 {
 src = DFPREG(src);
@@ -1873,7 +1868,7 @@ static void gen_ldf_asi(DisasContext *dc, DisasASI *da, 
MemOp orig_size,
 memop |= MO_ALIGN_4;
 switch (size) {
 case MO_32:
-d32 = gen_dest_fpr_F(dc);
+d32 = tcg_temp_new_i32();
 tcg_gen_qemu_ld_i32(d32, addr, da->mem_idx, memop);
 gen_store_fpr_F(dc, rd, d32);
 break;
@@ -1938,7 +1933,7 @@ static void gen_ldf_asi(DisasContext *dc, DisasASI *da, 
MemOp orig_size,
 case MO_32:
 d64 = tcg_temp_new_i64();
 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
-d32 = gen_dest_fpr_F(dc);
+d32 = tcg_temp_new_i32();
 tcg_gen_extrl_i64_i32(d32, d64);
 gen_store_fpr_F(dc, rd, d32);
 break;
@@ -2228,7 +2223,7 @@ static void gen_fmovs(DisasContext *dc, DisasCompare 
*cmp, int rd, int rs)
 
 s1 = gen_load_fpr_F(dc, rs);
 s2 = gen_load_fpr_F(dc, rd);
-dst = gen_dest_fpr_F(dc);
+dst = tcg_temp_new_i32();
 zero = tcg_constant_i32(0);
 
 tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2);
@@ -4497,7 +4492,7 @@ static bool do_fd(DisasContext *dc, arg_r_r *a,
 return true;
 }
 
-dst = gen_dest_fpr_F(dc);
+dst = tcg_temp_new_i32();
 src = gen_load_fpr_D(dc, a->rs);
 func(dst, src);
 gen_store_fpr_F(dc, a->rd, dst);
@@ -4539,7 +4534,7 @@ static bool do_env_fd(DisasContext *dc, arg_r_r *a,
 }
 
 gen_op_clear_ieee_excp_and_FTT();
-dst = gen_dest_fpr_F(dc);
+dst = tcg_temp_new_i32();
 src = gen_load_fpr_D(dc, a->rs);
 func(dst, tcg_env, src);
 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
@@ -4697,7 +4692,7 @@ static bool do_env_fq(DisasContext *dc, arg_r_r *a,
 
 gen_op_clear_ieee_excp_and_FTT();
 gen_op_load_fpr_QT1(QFPREG(a->rs));
-dst = gen_dest_fpr_F(dc);
+dst = tcg_temp_new_i32();
 func(dst, tcg_env);
 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
 gen_store_fpr_F(dc, a->rd, dst);
-- 
2.34.1




[PULL 26/57] target/s390x: Split out s390x_env_mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/s390x/cpu.h|  4 +++-
 target/s390x/tcg/mem_helper.c | 34 ++
 2 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index fa3aac4f97..f0fed5d6ad 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -381,7 +381,7 @@ extern const VMStateDescription vmstate_s390_cpu;
 #define MMU_HOME_IDX2
 #define MMU_REAL_IDX3
 
-static inline int cpu_mmu_index(CPUS390XState *env, bool ifetch)
+static inline int s390x_env_mmu_index(CPUS390XState *env, bool ifetch)
 {
 #ifdef CONFIG_USER_ONLY
 return MMU_USER_IDX;
@@ -412,6 +412,8 @@ static inline int cpu_mmu_index(CPUS390XState *env, bool 
ifetch)
 #endif
 }
 
+#define cpu_mmu_index s390x_env_mmu_index
+
 #ifdef CONFIG_TCG
 
 #include "tcg/tcg_s390x.h"
diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
index 84103251b9..557831def4 100644
--- a/target/s390x/tcg/mem_helper.c
+++ b/target/s390x/tcg/mem_helper.c
@@ -358,7 +358,7 @@ static int mmu_idx_from_as(uint8_t as)
 static uint32_t do_helper_nc(CPUS390XState *env, uint32_t l, uint64_t dest,
  uint64_t src, uintptr_t ra)
 {
-const int mmu_idx = cpu_mmu_index(env, false);
+const int mmu_idx = s390x_env_mmu_index(env, false);
 S390Access srca1, srca2, desta;
 uint32_t i;
 uint8_t c = 0;
@@ -392,7 +392,7 @@ uint32_t HELPER(nc)(CPUS390XState *env, uint32_t l, 
uint64_t dest,
 static uint32_t do_helper_xc(CPUS390XState *env, uint32_t l, uint64_t dest,
  uint64_t src, uintptr_t ra)
 {
-const int mmu_idx = cpu_mmu_index(env, false);
+const int mmu_idx = s390x_env_mmu_index(env, false);
 S390Access srca1, srca2, desta;
 uint32_t i;
 uint8_t c = 0;
@@ -433,7 +433,7 @@ uint32_t HELPER(xc)(CPUS390XState *env, uint32_t l, 
uint64_t dest,
 static uint32_t do_helper_oc(CPUS390XState *env, uint32_t l, uint64_t dest,
  uint64_t src, uintptr_t ra)
 {
-const int mmu_idx = cpu_mmu_index(env, false);
+const int mmu_idx = s390x_env_mmu_index(env, false);
 S390Access srca1, srca2, desta;
 uint32_t i;
 uint8_t c = 0;
@@ -467,7 +467,7 @@ uint32_t HELPER(oc)(CPUS390XState *env, uint32_t l, 
uint64_t dest,
 static uint32_t do_helper_mvc(CPUS390XState *env, uint32_t l, uint64_t dest,
   uint64_t src, uintptr_t ra)
 {
-const int mmu_idx = cpu_mmu_index(env, false);
+const int mmu_idx = s390x_env_mmu_index(env, false);
 S390Access srca, desta;
 uint32_t i;
 
@@ -508,7 +508,7 @@ void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t 
dest, uint64_t src)
 /* move right to left */
 void HELPER(mvcrl)(CPUS390XState *env, uint64_t l, uint64_t dest, uint64_t src)
 {
-const int mmu_idx = cpu_mmu_index(env, false);
+const int mmu_idx = s390x_env_mmu_index(env, false);
 const uint64_t ra = GETPC();
 S390Access srca, desta;
 int32_t i;
@@ -529,7 +529,7 @@ void HELPER(mvcrl)(CPUS390XState *env, uint64_t l, uint64_t 
dest, uint64_t src)
 /* move inverse  */
 void HELPER(mvcin)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
 {
-const int mmu_idx = cpu_mmu_index(env, false);
+const int mmu_idx = s390x_env_mmu_index(env, false);
 S390Access srca, desta;
 uintptr_t ra = GETPC();
 int i;
@@ -550,7 +550,7 @@ void HELPER(mvcin)(CPUS390XState *env, uint32_t l, uint64_t 
dest, uint64_t src)
 /* move numerics  */
 void HELPER(mvn)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
 {
-const int mmu_idx = cpu_mmu_index(env, false);
+const int mmu_idx = s390x_env_mmu_index(env, false);
 S390Access srca1, srca2, desta;
 uintptr_t ra = GETPC();
 int i;
@@ -572,7 +572,7 @@ void HELPER(mvn)(CPUS390XState *env, uint32_t l, uint64_t 
dest, uint64_t src)
 /* move with offset  */
 void HELPER(mvo)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
 {
-const int mmu_idx = cpu_mmu_index(env, false);
+const int mmu_idx = s390x_env_mmu_index(env, false);
 /* MVO always processes one more byte than specified - maximum is 16 */
 const int len_dest = (l >> 4) + 1;
 const int len_src = (l & 0xf) + 1;
@@ -606,7 +606,7 @@ void HELPER(mvo)(CPUS390XState *env, uint32_t l, uint64_t 
dest, uint64_t src)
 /* move zones  */
 void HELPER(mvz)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
 {
-const int mmu_idx = cpu_mmu_index(env, false);
+const int mmu_idx = s390x_env_mmu_index(env, false);
 S390Access srca1, srca2, desta;
 uintptr_t ra = GETPC();
 int i;
@@ -669,7 +669,7 @@ uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, 
uint32_t mask,
 
 if (!mask) {
 /* Recognize access exceptions for the first byte */
-probe_read(env, addr, 1, cpu_mmu_index(env, false), ra);
+probe_read(env, addr, 1, 

[PULL 16/57] target/mips: Split out mips_env_mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/mips/cpu.h   |  7 ++-
 target/mips/sysemu/physaddr.c   |  2 +-
 target/mips/tcg/msa_helper.c| 10 +-
 target/mips/tcg/sysemu/cp0_helper.c |  2 +-
 target/mips/tcg/sysemu/special_helper.c |  2 +-
 target/mips/tcg/sysemu/tlb_helper.c |  2 +-
 6 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 3ba8dccd2d..4c15e76781 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -1255,11 +1255,16 @@ static inline int hflags_mmu_index(uint32_t hflags)
 }
 }
 
-static inline int cpu_mmu_index(CPUMIPSState *env, bool ifetch)
+static inline int mips_env_mmu_index(CPUMIPSState *env)
 {
 return hflags_mmu_index(env->hflags);
 }
 
+static inline int cpu_mmu_index(CPUMIPSState *env, bool ifetch)
+{
+return mips_env_mmu_index(env);
+}
+
 #include "exec/cpu-all.h"
 
 /* Exceptions */
diff --git a/target/mips/sysemu/physaddr.c b/target/mips/sysemu/physaddr.c
index 05990aa5bb..13c8bc8f47 100644
--- a/target/mips/sysemu/physaddr.c
+++ b/target/mips/sysemu/physaddr.c
@@ -236,7 +236,7 @@ hwaddr mips_cpu_get_phys_page_debug(CPUState *cs, vaddr 
addr)
 int prot;
 
 if (get_physical_address(env, _addr, , addr, MMU_DATA_LOAD,
- cpu_mmu_index(env, false)) != 0) {
+ mips_env_mmu_index(env)) != 0) {
 return -1;
 }
 return phys_addr;
diff --git a/target/mips/tcg/msa_helper.c b/target/mips/tcg/msa_helper.c
index 7a8dbada5d..d2181763e7 100644
--- a/target/mips/tcg/msa_helper.c
+++ b/target/mips/tcg/msa_helper.c
@@ -8214,7 +8214,7 @@ void helper_msa_ffint_u_df(CPUMIPSState *env, uint32_t 
df, uint32_t wd,
 #if !defined(CONFIG_USER_ONLY)
 #define MEMOP_IDX(DF)   \
 MemOpIdx oi = make_memop_idx(MO_TE | DF | MO_UNALN, \
- cpu_mmu_index(env, false));
+ mips_env_mmu_index(env));
 #else
 #define MEMOP_IDX(DF)
 #endif
@@ -8323,7 +8323,7 @@ void helper_msa_st_b(CPUMIPSState *env, uint32_t wd,
  target_ulong addr)
 {
 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
-int mmu_idx = cpu_mmu_index(env, false);
+int mmu_idx = mips_env_mmu_index(env);
 uintptr_t ra = GETPC();
 
 ensure_writable_pages(env, addr, mmu_idx, ra);
@@ -8337,7 +8337,7 @@ void helper_msa_st_h(CPUMIPSState *env, uint32_t wd,
  target_ulong addr)
 {
 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
-int mmu_idx = cpu_mmu_index(env, false);
+int mmu_idx = mips_env_mmu_index(env);
 uintptr_t ra = GETPC();
 uint64_t d0, d1;
 
@@ -8358,7 +8358,7 @@ void helper_msa_st_w(CPUMIPSState *env, uint32_t wd,
  target_ulong addr)
 {
 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
-int mmu_idx = cpu_mmu_index(env, false);
+int mmu_idx = mips_env_mmu_index(env);
 uintptr_t ra = GETPC();
 uint64_t d0, d1;
 
@@ -8379,7 +8379,7 @@ void helper_msa_st_d(CPUMIPSState *env, uint32_t wd,
  target_ulong addr)
 {
 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
-int mmu_idx = cpu_mmu_index(env, false);
+int mmu_idx = mips_env_mmu_index(env);
 uintptr_t ra = GETPC();
 
 ensure_writable_pages(env, addr, mmu_idx, GETPC());
diff --git a/target/mips/tcg/sysemu/cp0_helper.c 
b/target/mips/tcg/sysemu/cp0_helper.c
index cc545aed9c..62f6fb4bf6 100644
--- a/target/mips/tcg/sysemu/cp0_helper.c
+++ b/target/mips/tcg/sysemu/cp0_helper.c
@@ -1202,7 +1202,7 @@ void helper_mtc0_status(CPUMIPSState *env, target_ulong 
arg1)
 old, old & env->CP0_Cause & CP0Ca_IP_mask,
 val, val & env->CP0_Cause & CP0Ca_IP_mask,
 env->CP0_Cause);
-switch (cpu_mmu_index(env, false)) {
+switch (mips_env_mmu_index(env)) {
 case 3:
 qemu_log(", ERL\n");
 break;
diff --git a/target/mips/tcg/sysemu/special_helper.c 
b/target/mips/tcg/sysemu/special_helper.c
index 93276f789d..518d3fbc34 100644
--- a/target/mips/tcg/sysemu/special_helper.c
+++ b/target/mips/tcg/sysemu/special_helper.c
@@ -68,7 +68,7 @@ static void debug_post_eret(CPUMIPSState *env)
 if (env->hflags & MIPS_HFLAG_DM) {
 qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
 }
-switch (cpu_mmu_index(env, false)) {
+switch (mips_env_mmu_index(env)) {
 case 3:
 qemu_log(", ERL\n");
 break;
diff --git a/target/mips/tcg/sysemu/tlb_helper.c 
b/target/mips/tcg/sysemu/tlb_helper.c
index b715449114..cdae42ffdd 100644
--- a/target/mips/tcg/sysemu/tlb_helper.c
+++ b/target/mips/tcg/sysemu/tlb_helper.c
@@ -973,7 +973,7 @@ hwaddr cpu_mips_translate_address(CPUMIPSState *env, 
target_ulong address,
 
 /* data access */
 ret = get_physical_address(env, , , address, 

[PULL 24/57] target/riscv: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Alistair Francis 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/riscv/cpu.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 8cbfc7e781..be21fa09c6 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -867,6 +867,11 @@ static bool riscv_cpu_has_work(CPUState *cs)
 #endif
 }
 
+static int riscv_cpu_mmu_index(CPUState *cs, bool ifetch)
+{
+return riscv_env_mmu_index(cpu_env(cs), ifetch);
+}
+
 static void riscv_cpu_reset_hold(Object *obj)
 {
 #ifndef CONFIG_USER_ONLY
@@ -1810,6 +1815,7 @@ static void riscv_cpu_class_init(ObjectClass *c, void 
*data)
 
 cc->class_by_name = riscv_cpu_class_by_name;
 cc->has_work = riscv_cpu_has_work;
+cc->mmu_index = riscv_cpu_mmu_index;
 cc->dump_state = riscv_cpu_dump_state;
 cc->set_pc = riscv_cpu_set_pc;
 cc->get_pc = riscv_cpu_get_pc;
-- 
2.34.1




[PULL 23/57] target/riscv: Replace cpu_mmu_index with riscv_env_mmu_index

2024-02-01 Thread Richard Henderson
Use the target-specific function name in preference
to the generic name.

Reviewed-by: Alistair Francis 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/riscv/cpu_helper.c| 4 ++--
 target/riscv/op_helper.c | 4 ++--
 target/riscv/vector_helper.c | 9 +
 3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 15f87ecdb0..b6b23b7d03 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -106,7 +106,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
 #else
 flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv);
 
-flags |= cpu_mmu_index(env, 0);
+flags |= riscv_env_mmu_index(env, 0);
 fs = get_field(env->mstatus, MSTATUS_FS);
 vs = get_field(env->mstatus, MSTATUS_VS);
 
@@ -1200,7 +1200,7 @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr 
addr)
 CPURISCVState *env = >env;
 hwaddr phys_addr;
 int prot;
-int mmu_idx = cpu_mmu_index(>env, false);
+int mmu_idx = riscv_env_mmu_index(>env, false);
 
 if (get_physical_address(env, _addr, , addr, NULL, 0, mmu_idx,
  true, env->virt_enabled, true)) {
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 5355225d56..f414aaebdb 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -157,7 +157,7 @@ void helper_cbo_zero(CPURISCVState *env, target_ulong 
address)
 {
 RISCVCPU *cpu = env_archcpu(env);
 uint16_t cbozlen = cpu->cfg.cboz_blocksize;
-int mmu_idx = cpu_mmu_index(env, false);
+int mmu_idx = riscv_env_mmu_index(env, false);
 uintptr_t ra = GETPC();
 void *mem;
 
@@ -205,7 +205,7 @@ static void check_zicbom_access(CPURISCVState *env,
 uintptr_t ra)
 {
 RISCVCPU *cpu = env_archcpu(env);
-int mmu_idx = cpu_mmu_index(env, false);
+int mmu_idx = riscv_env_mmu_index(env, false);
 uint16_t cbomlen = cpu->cfg.cbom_blocksize;
 void *phost;
 int ret;
diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index c1c3a4d1ea..fe0d5d053c 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -113,14 +113,15 @@ static void probe_pages(CPURISCVState *env, target_ulong 
addr,
 {
 target_ulong pagelen = -(addr | TARGET_PAGE_MASK);
 target_ulong curlen = MIN(pagelen, len);
+int mmu_index = riscv_env_mmu_index(env, false);
 
 probe_access(env, adjust_addr(env, addr), curlen, access_type,
- cpu_mmu_index(env, false), ra);
+ mmu_index, ra);
 if (len > curlen) {
 addr += curlen;
 curlen = len - curlen;
 probe_access(env, adjust_addr(env, addr), curlen, access_type,
- cpu_mmu_index(env, false), ra);
+ mmu_index, ra);
 }
 }
 
@@ -464,6 +465,7 @@ vext_ldff(void *vd, void *v0, target_ulong base,
 uint32_t esz = 1 << log2_esz;
 uint32_t vma = vext_vma(desc);
 target_ulong addr, offset, remain;
+int mmu_index = riscv_env_mmu_index(env, false);
 
 /* probe every access */
 for (i = env->vstart; i < env->vl; i++) {
@@ -478,8 +480,7 @@ vext_ldff(void *vd, void *v0, target_ulong base,
 remain = nf << log2_esz;
 while (remain > 0) {
 offset = -(addr | TARGET_PAGE_MASK);
-host = tlb_vaddr_to_host(env, addr, MMU_DATA_LOAD,
- cpu_mmu_index(env, false));
+host = tlb_vaddr_to_host(env, addr, MMU_DATA_LOAD, mmu_index);
 if (host) {
 #ifdef CONFIG_USER_ONLY
 if (!page_check_range(addr, offset, PAGE_READ)) {
-- 
2.34.1




[PULL 00/57] tcg patch queue

2024-02-01 Thread Richard Henderson
The following changes since commit 14639717bf379480e937716fcaf1e72b47fd4c5f:

  Merge tag 'pull-trivial-patches' of https://gitlab.com/mjt0k/qemu into 
staging (2024-01-31 19:53:45 +)

are available in the Git repository at:

  https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20240202

for you to fetch changes up to 73e095fc71dfeb8f5f767d9ac71078e562d935b0:

  target/sparc: Remove FSR_FTT_NMASK, FSR_FTT_CEXC_NMASK (2024-02-02 14:40:06 
+1000)


tests/tcg: Fix multiarch/gdbstub/prot-none.py
hw/core: Convert cpu_mmu_index to a CPUClass hook
tcg/loongarch64: Set vector registers call clobbered
target/sparc: floating-point cleanup


Ilya Leoshkevich (1):
  tests/tcg: Fix the /proc/self/mem probing in the PROT_NONE gdbstub test

Richard Henderson (56):
  include/hw/core: Add mmu_index to CPUClass
  target/alpha: Split out alpha_env_mmu_index
  target/alpha: Populate CPUClass.mmu_index
  target/arm: Split out arm_env_mmu_index
  target/arm: Populate CPUClass.mmu_index
  target/avr: Populate CPUClass.mmu_index
  target/cris: Cache mem_index in DisasContext
  target/cris: Populate CPUClass.mmu_index
  target/hppa: Populate CPUClass.mmu_index
  target/i386: Populate CPUClass.mmu_index
  target/loongarch: Populate CPUClass.mmu_index
  target/loongarch: Rename MMU_IDX_*
  target/m68k: Populate CPUClass.mmu_index
  target/microblaze: Populate CPUClass.mmu_index
  target/mips: Pass ptw_mmu_idx down from mips_cpu_tlb_fill
  target/mips: Split out mips_env_mmu_index
  target/mips: Populate CPUClass.mmu_index
  target/nios2: Populate CPUClass.mmu_index
  target/openrisc: Populate CPUClass.mmu_index
  target/ppc: Split out ppc_env_mmu_index
  target/ppc: Populate CPUClass.mmu_index
  target/riscv: Rename riscv_cpu_mmu_index to riscv_env_mmu_index
  target/riscv: Replace cpu_mmu_index with riscv_env_mmu_index
  target/riscv: Populate CPUClass.mmu_index
  target/rx: Populate CPUClass.mmu_index
  target/s390x: Split out s390x_env_mmu_index
  target/s390x: Populate CPUClass.mmu_index
  target/sh4: Populate CPUClass.mmu_index
  target/sparc: Populate CPUClass.mmu_index
  target/tricore: Populate CPUClass.mmu_index
  target/xtensa: Populate CPUClass.mmu_index
  include/exec: Implement cpu_mmu_index generically
  include/exec: Change cpu_mmu_index argument to CPUState
  tcg/loongarch64: Set vector registers call clobbered
  target/sparc: Use tcg_gen_qemu_{ld, st}_i128 for ASI_M_BCOPY
  target/sparc: Use tcg_gen_qemu_{ld, st}_i128 for ASI_M_BFILL
  target/sparc: Remove gen_dest_fpr_F
  target/sparc: Introduce gen_{load,store}_fpr_Q
  target/sparc: Inline FNEG, FABS
  target/sparc: Use i128 for FSQRTq
  target/sparc: Use i128 for FADDq, FSUBq, FMULq, FDIVq
  target/sparc: Use i128 for FqTOs, FqTOi
  target/sparc: Use i128 for FqTOd, FqTOx
  target/sparc: Use i128 for FCMPq, FCMPEq
  target/sparc: Use i128 for FsTOq, FiTOq
  target/sparc: Use i128 for FdTOq, FxTOq
  target/sparc: Use i128 for Fdmulq
  target/sparc: Remove qt0, qt1 temporaries
  target/sparc: Introduce cpu_get_fsr, cpu_put_fsr
  target/sparc: Split ver from env->fsr
  target/sparc: Clear cexc and ftt in do_check_ieee_exceptions
  target/sparc: Merge check_ieee_exceptions with FPop helpers
  target/sparc: Split cexc and ftt from env->fsr
  target/sparc: Remove cpu_fsr
  target/sparc: Split fcc out of env->fsr
  target/sparc: Remove FSR_FTT_NMASK, FSR_FTT_CEXC_NMASK

 include/exec/cpu-all.h |   4 +
 include/exec/cpu-common.h  |  21 +
 include/hw/core/cpu.h  |   3 +
 target/alpha/cpu.h |   2 +-
 target/arm/cpu.h   |  13 -
 target/arm/internals.h |   5 +
 target/avr/cpu.h   |   7 -
 target/cris/cpu.h  |   4 -
 target/hexagon/cpu.h   |   9 -
 target/hppa/cpu.h  |  13 -
 target/i386/cpu.h  |   7 -
 target/loongarch/cpu.h |  18 +-
 target/m68k/cpu.h  |   4 -
 target/microblaze/cpu.h|  15 -
 target/mips/cpu.h  |   6 +-
 target/nios2/cpu.h |   6 -
 target/openrisc/cpu.h  |  12 -
 target/ppc/cpu.h   |   2 +-
 target/riscv/cpu.h |   4 +-
 target/rx/cpu.h|   5 -
 target/s390x/cpu.h |   2 +-
 

[PULL 13/57] target/m68k: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/m68k/cpu.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index 44000f5869..8a8392e694 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -56,6 +56,11 @@ static bool m68k_cpu_has_work(CPUState *cs)
 return cs->interrupt_request & CPU_INTERRUPT_HARD;
 }
 
+static int m68k_cpu_mmu_index(CPUState *cs, bool ifetch)
+{
+return cpu_env(cs)->sr & SR_S ? MMU_KERNEL_IDX : MMU_USER_IDX;
+}
+
 static void m68k_set_feature(CPUM68KState *env, int feature)
 {
 env->features |= BIT_ULL(feature);
@@ -551,6 +556,7 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
 
 cc->class_by_name = m68k_cpu_class_by_name;
 cc->has_work = m68k_cpu_has_work;
+cc->mmu_index = m68k_cpu_mmu_index;
 cc->dump_state = m68k_cpu_dump_state;
 cc->set_pc = m68k_cpu_set_pc;
 cc->get_pc = m68k_cpu_get_pc;
-- 
2.34.1




[PULL 29/57] target/sparc: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/sparc/cpu.h | 34 ++
 target/sparc/cpu.c | 29 +
 2 files changed, 35 insertions(+), 28 deletions(-)

diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index 12a11ecb26..92c58c92c1 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -708,34 +708,6 @@ static inline int cpu_supervisor_mode(CPUSPARCState *env1)
 }
 #endif
 
-static inline int cpu_mmu_index(CPUSPARCState *env, bool ifetch)
-{
-#if defined(CONFIG_USER_ONLY)
-return MMU_USER_IDX;
-#elif !defined(TARGET_SPARC64)
-if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
-return MMU_PHYS_IDX;
-} else {
-return env->psrs;
-}
-#else
-/* IMMU or DMMU disabled.  */
-if (ifetch
-? (env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0
-: (env->lsu & DMMU_E) == 0) {
-return MMU_PHYS_IDX;
-} else if (cpu_hypervisor_mode(env)) {
-return MMU_PHYS_IDX;
-} else if (env->tl > 0) {
-return MMU_NUCLEUS_IDX;
-} else if (cpu_supervisor_mode(env)) {
-return MMU_KERNEL_IDX;
-} else {
-return MMU_USER_IDX;
-}
-#endif
-}
-
 static inline int cpu_interrupts_enabled(CPUSPARCState *env1)
 {
 #if !defined (TARGET_SPARC64)
@@ -777,6 +749,12 @@ trap_state* cpu_tsptr(CPUSPARCState* env);
 #define TB_FLAG_HYPER(1 << 7)
 #define TB_FLAG_ASI_SHIFT24
 
+int sparc_cpu_mmu_index(CPUState *cs, bool ifetch);
+static inline int cpu_mmu_index(CPUSPARCState *env, bool ifetch)
+{
+return sparc_cpu_mmu_index(env_cpu(env), ifetch);
+}
+
 static inline void cpu_get_tb_cpu_state(CPUSPARCState *env, vaddr *pc,
 uint64_t *cs_base, uint32_t *pflags)
 {
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
index 7d0d629a3d..7a3b815737 100644
--- a/target/sparc/cpu.c
+++ b/target/sparc/cpu.c
@@ -718,6 +718,34 @@ static bool sparc_cpu_has_work(CPUState *cs)
cpu_interrupts_enabled(env);
 }
 
+int sparc_cpu_mmu_index(CPUState *cs, bool ifetch)
+{
+CPUSPARCState *env = cpu_env(cs);
+
+#ifndef TARGET_SPARC64
+if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
+return MMU_PHYS_IDX;
+} else {
+return env->psrs;
+}
+#else
+/* IMMU or DMMU disabled.  */
+if (ifetch
+? (env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0
+: (env->lsu & DMMU_E) == 0) {
+return MMU_PHYS_IDX;
+} else if (cpu_hypervisor_mode(env)) {
+return MMU_PHYS_IDX;
+} else if (env->tl > 0) {
+return MMU_NUCLEUS_IDX;
+} else if (cpu_supervisor_mode(env)) {
+return MMU_KERNEL_IDX;
+} else {
+return MMU_USER_IDX;
+}
+#endif
+}
+
 static char *sparc_cpu_type_name(const char *cpu_model)
 {
 char *name = g_strdup_printf(SPARC_CPU_TYPE_NAME("%s"), cpu_model);
@@ -906,6 +934,7 @@ static void sparc_cpu_class_init(ObjectClass *oc, void 
*data)
 cc->class_by_name = sparc_cpu_class_by_name;
 cc->parse_features = sparc_cpu_parse_features;
 cc->has_work = sparc_cpu_has_work;
+cc->mmu_index = sparc_cpu_mmu_index;
 cc->dump_state = sparc_cpu_dump_state;
 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
-- 
2.34.1




[PULL 18/57] target/nios2: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/nios2/cpu.h | 12 ++--
 target/nios2/cpu.c |  7 +++
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h
index 2d79b5b298..9965ff74c1 100644
--- a/target/nios2/cpu.h
+++ b/target/nios2/cpu.h
@@ -270,12 +270,6 @@ void do_nios2_semihosting(CPUNios2State *env);
 #define MMU_SUPERVISOR_IDX  0
 #define MMU_USER_IDX1
 
-static inline int cpu_mmu_index(CPUNios2State *env, bool ifetch)
-{
-return (env->ctrl[CR_STATUS] & CR_STATUS_U) ? MMU_USER_IDX :
-  MMU_SUPERVISOR_IDX;
-}
-
 #ifndef CONFIG_USER_ONLY
 hwaddr nios2_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
@@ -292,6 +286,12 @@ FIELD(TBFLAGS, CRS0, 0, 1)  /* Set if CRS == 0. */
 FIELD(TBFLAGS, U, 1, 1) /* Overlaps CR_STATUS_U */
 FIELD(TBFLAGS, R0_0, 2, 1)  /* Set if R0 == 0. */
 
+int nios2_cpu_mmu_index(CPUState *cs, bool ifetch);
+static inline int cpu_mmu_index(CPUNios2State *env, bool ifetch)
+{
+return nios2_cpu_mmu_index(env_cpu(env), ifetch);
+}
+
 static inline void cpu_get_tb_cpu_state(CPUNios2State *env, vaddr *pc,
 uint64_t *cs_base, uint32_t *flags)
 {
diff --git a/target/nios2/cpu.c b/target/nios2/cpu.c
index 596c0c5617..e42885997e 100644
--- a/target/nios2/cpu.c
+++ b/target/nios2/cpu.c
@@ -57,6 +57,12 @@ static bool nios2_cpu_has_work(CPUState *cs)
 return cs->interrupt_request & CPU_INTERRUPT_HARD;
 }
 
+int nios2_cpu_mmu_index(CPUState *cs, bool ifetch)
+{
+return (cpu_env(cs)->ctrl[CR_STATUS] & CR_STATUS_U
+? MMU_USER_IDX : MMU_SUPERVISOR_IDX);
+}
+
 static void nios2_cpu_reset_hold(Object *obj)
 {
 CPUState *cs = CPU(obj);
@@ -381,6 +387,7 @@ static void nios2_cpu_class_init(ObjectClass *oc, void 
*data)
 
 cc->class_by_name = nios2_cpu_class_by_name;
 cc->has_work = nios2_cpu_has_work;
+cc->mmu_index = nios2_cpu_mmu_index;
 cc->dump_state = nios2_cpu_dump_state;
 cc->set_pc = nios2_cpu_set_pc;
 cc->get_pc = nios2_cpu_get_pc;
-- 
2.34.1




[PULL 19/57] target/openrisc: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/openrisc/cpu.h | 10 ++
 target/openrisc/cpu.c | 13 +
 2 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index b454014ddd..7dbed8d8be 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -361,16 +361,10 @@ static inline void cpu_get_tb_cpu_state(CPUOpenRISCState 
*env, vaddr *pc,
| (env->sr & (SR_SM | SR_DME | SR_IME | SR_OVE));
 }
 
+int openrisc_cpu_mmu_index(CPUState *cs, bool ifetch);
 static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch)
 {
-int ret = MMU_NOMMU_IDX;  /* mmu is disabled */
-
-if (env->sr & (ifetch ? SR_IME : SR_DME)) {
-/* The mmu is enabled; test supervisor state.  */
-ret = env->sr & SR_SM ? MMU_SUPERVISOR_IDX : MMU_USER_IDX;
-}
-
-return ret;
+return openrisc_cpu_mmu_index(env_cpu(env), ifetch);
 }
 
 static inline uint32_t cpu_get_sr(const CPUOpenRISCState *env)
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index 477d49d4bc..8670152c84 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -68,6 +68,18 @@ static bool openrisc_cpu_has_work(CPUState *cs)
 CPU_INTERRUPT_TIMER);
 }
 
+int openrisc_cpu_mmu_index(CPUState *cs, bool ifetch)
+{
+CPUOpenRISCState *env = cpu_env(cs);
+
+if (env->sr & (ifetch ? SR_IME : SR_DME)) {
+/* The mmu is enabled; test supervisor state.  */
+return env->sr & SR_SM ? MMU_SUPERVISOR_IDX : MMU_USER_IDX;
+}
+
+return MMU_NOMMU_IDX;  /* mmu is disabled */
+}
+
 static void openrisc_disas_set_info(CPUState *cpu, disassemble_info *info)
 {
 info->print_insn = print_insn_or1k;
@@ -239,6 +251,7 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void 
*data)
 
 cc->class_by_name = openrisc_cpu_class_by_name;
 cc->has_work = openrisc_cpu_has_work;
+cc->mmu_index = openrisc_cpu_mmu_index;
 cc->dump_state = openrisc_cpu_dump_state;
 cc->set_pc = openrisc_cpu_set_pc;
 cc->get_pc = openrisc_cpu_get_pc;
-- 
2.34.1




[PULL 17/57] target/mips: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/mips/cpu.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index df544ab39b..d644adbc77 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -182,6 +182,11 @@ static bool mips_cpu_has_work(CPUState *cs)
 return has_work;
 }
 
+static int mips_cpu_mmu_index(CPUState *cs, bool ifunc)
+{
+return mips_env_mmu_index(cpu_env(cs));
+}
+
 #include "cpu-defs.c.inc"
 
 static void mips_cpu_reset_hold(Object *obj)
@@ -579,6 +584,7 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
 
 cc->class_by_name = mips_cpu_class_by_name;
 cc->has_work = mips_cpu_has_work;
+cc->mmu_index = mips_cpu_mmu_index;
 cc->dump_state = mips_cpu_dump_state;
 cc->set_pc = mips_cpu_set_pc;
 cc->get_pc = mips_cpu_get_pc;
-- 
2.34.1




[PULL 35/57] tcg/loongarch64: Set vector registers call clobbered

2024-02-01 Thread Richard Henderson
Because there are more call clobbered registers than
call saved registers, we begin with all registers as
call clobbered and then reset those that are saved.

This was missed when we introduced the LSX support.

Cc: qemu-sta...@nongnu.org
Fixes: 16288ded944 ("tcg/loongarch64: Lower basic tcg vec ops to LSX")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2136
Signed-off-by: Richard Henderson 
Reviewed-by: Song Gao 
Message-Id: <20240201233414.500588-1-richard.hender...@linaro.org>
---
 tcg/loongarch64/tcg-target.c.inc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index bab0a173a3..dcf0205458 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -2327,7 +2327,7 @@ static void tcg_target_init(TCGContext *s)
 tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS;
 tcg_target_available_regs[TCG_TYPE_I64] = ALL_GENERAL_REGS;
 
-tcg_target_call_clobber_regs = ALL_GENERAL_REGS;
+tcg_target_call_clobber_regs = ALL_GENERAL_REGS | ALL_VECTOR_REGS;
 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0);
 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1);
 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2);
-- 
2.34.1




[PULL 02/57] target/alpha: Split out alpha_env_mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/alpha/cpu.h   | 7 ++-
 target/alpha/translate.c | 2 +-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h
index ce806587ca..3beff2738a 100644
--- a/target/alpha/cpu.h
+++ b/target/alpha/cpu.h
@@ -389,7 +389,7 @@ enum {
 
 #define TB_FLAG_UNALIGN   (1u << 1)
 
-static inline int cpu_mmu_index(CPUAlphaState *env, bool ifetch)
+static inline int alpha_env_mmu_index(CPUAlphaState *env)
 {
 int ret = env->flags & ENV_FLAG_PS_USER ? MMU_USER_IDX : MMU_KERNEL_IDX;
 if (env->flags & ENV_FLAG_PAL_MODE) {
@@ -398,6 +398,11 @@ static inline int cpu_mmu_index(CPUAlphaState *env, bool 
ifetch)
 return ret;
 }
 
+static inline int cpu_mmu_index(CPUAlphaState *env, bool ifetch)
+{
+return alpha_env_mmu_index(env);
+}
+
 enum {
 IR_V0   = 0,
 IR_T0   = 1,
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index 134eb7225b..4b464f8651 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -2875,7 +2875,7 @@ static void alpha_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cpu)
 int64_t bound;
 
 ctx->tbflags = ctx->base.tb->flags;
-ctx->mem_idx = cpu_mmu_index(env, false);
+ctx->mem_idx = alpha_env_mmu_index(env);
 ctx->implver = env->implver;
 ctx->amask = env->amask;
 
-- 
2.34.1




[PULL 11/57] target/loongarch: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/loongarch/cpu.h |  6 ++
 target/loongarch/cpu.c | 11 +++
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 0fa5e0ca93..5dfcfeb3a4 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -408,15 +408,13 @@ struct LoongArchCPUClass {
 #define MMU_IDX_USER MMU_PLV_USER
 #define MMU_IDX_DA   4
 
+int loongarch_cpu_mmu_index(CPUState *cs, bool ifetch);
 static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch)
 {
 #ifdef CONFIG_USER_ONLY
 return MMU_IDX_USER;
 #else
-if (FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG)) {
-return FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV);
-}
-return MMU_IDX_DA;
+return loongarch_cpu_mmu_index(env_cpu(env), ifetch);
 #endif
 }
 
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index fb8dde7def..cbecc63213 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -375,6 +375,16 @@ static bool loongarch_cpu_has_work(CPUState *cs)
 #endif
 }
 
+int loongarch_cpu_mmu_index(CPUState *cs, bool ifetch)
+{
+CPULoongArchState *env = cpu_env(cs);
+
+if (FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG)) {
+return FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV);
+}
+return MMU_IDX_DA;
+}
+
 static void loongarch_la464_initfn(Object *obj)
 {
 LoongArchCPU *cpu = LOONGARCH_CPU(obj);
@@ -779,6 +789,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void 
*data)
 
 cc->class_by_name = loongarch_cpu_class_by_name;
 cc->has_work = loongarch_cpu_has_work;
+cc->mmu_index = loongarch_cpu_mmu_index;
 cc->dump_state = loongarch_cpu_dump_state;
 cc->set_pc = loongarch_cpu_set_pc;
 cc->get_pc = loongarch_cpu_get_pc;
-- 
2.34.1




[PULL 07/57] target/cris: Cache mem_index in DisasContext

2024-02-01 Thread Richard Henderson
Compute this value once for each translation.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/cris/translate.c | 14 +-
 target/cris/translate_v10.c.inc |  6 ++
 2 files changed, 7 insertions(+), 13 deletions(-)

diff --git a/target/cris/translate.c b/target/cris/translate.c
index ee1402a9a3..7acea29a01 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -94,6 +94,7 @@ typedef struct DisasContext {
 
 CRISCPU *cpu;
 target_ulong pc, ppc;
+int mem_index;
 
 /* Decoder.  */
 unsigned int (*decoder)(CPUCRISState *env, struct DisasContext *dc);
@@ -1008,37 +1009,31 @@ static inline void cris_prepare_jmp (DisasContext *dc, 
unsigned int type)
 
 static void gen_load64(DisasContext *dc, TCGv_i64 dst, TCGv addr)
 {
-int mem_index = cpu_mmu_index(>cpu->env, false);
-
 /* If we get a fault on a delayslot we must keep the jmp state in
the cpu-state to be able to re-execute the jmp.  */
 if (dc->delayed_branch == 1) {
 cris_store_direct_jmp(dc);
 }
 
-tcg_gen_qemu_ld_i64(dst, addr, mem_index, MO_TEUQ);
+tcg_gen_qemu_ld_i64(dst, addr, dc->mem_index, MO_TEUQ);
 }
 
 static void gen_load(DisasContext *dc, TCGv dst, TCGv addr, 
  unsigned int size, int sign)
 {
-int mem_index = cpu_mmu_index(>cpu->env, false);
-
 /* If we get a fault on a delayslot we must keep the jmp state in
the cpu-state to be able to re-execute the jmp.  */
 if (dc->delayed_branch == 1) {
 cris_store_direct_jmp(dc);
 }
 
-tcg_gen_qemu_ld_tl(dst, addr, mem_index,
+tcg_gen_qemu_ld_tl(dst, addr, dc->mem_index,
MO_TE + ctz32(size) + (sign ? MO_SIGN : 0));
 }
 
 static void gen_store (DisasContext *dc, TCGv addr, TCGv val,
unsigned int size)
 {
-int mem_index = cpu_mmu_index(>cpu->env, false);
-
 /* If we get a fault on a delayslot we must keep the jmp state in
the cpu-state to be able to re-execute the jmp.  */
 if (dc->delayed_branch == 1) {
@@ -1055,7 +1050,7 @@ static void gen_store (DisasContext *dc, TCGv addr, TCGv 
val,
 return;
 }
 
-tcg_gen_qemu_st_tl(val, addr, mem_index, MO_TE + ctz32(size));
+tcg_gen_qemu_st_tl(val, addr, dc->mem_index, MO_TE + ctz32(size));
 
 if (dc->flags_x) {
 cris_evaluate_flags(dc);
@@ -2971,6 +2966,7 @@ static void cris_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 dc->cpu = env_archcpu(env);
 dc->ppc = pc_start;
 dc->pc = pc_start;
+dc->mem_index = cpu_mmu_index(env, false);
 dc->flags_uptodate = 1;
 dc->flags_x = tb_flags & X_FLAG;
 dc->cc_x_uptodate = 0;
diff --git a/target/cris/translate_v10.c.inc b/target/cris/translate_v10.c.inc
index 6df599fdce..73fc27c15d 100644
--- a/target/cris/translate_v10.c.inc
+++ b/target/cris/translate_v10.c.inc
@@ -91,8 +91,6 @@ static void gen_store_v10_conditional(DisasContext *dc, TCGv 
addr, TCGv val,
 static void gen_store_v10(DisasContext *dc, TCGv addr, TCGv val,
unsigned int size)
 {
-int mem_index = cpu_mmu_index(>cpu->env, false);
-
 /* If we get a fault on a delayslot we must keep the jmp state in
the cpu-state to be able to re-execute the jmp.  */
 if (dc->delayed_branch == 1) {
@@ -101,11 +99,11 @@ static void gen_store_v10(DisasContext *dc, TCGv addr, 
TCGv val,
 
 /* Conditional writes. */
 if (dc->flags_x) {
-gen_store_v10_conditional(dc, addr, val, size, mem_index);
+gen_store_v10_conditional(dc, addr, val, size, dc->mem_index);
 return;
 }
 
-tcg_gen_qemu_st_tl(val, addr, mem_index, ctz32(size) | MO_TE);
+tcg_gen_qemu_st_tl(val, addr, dc->mem_index, ctz32(size) | MO_TE);
 }
 
 
-- 
2.34.1




[PULL 22/57] target/riscv: Rename riscv_cpu_mmu_index to riscv_env_mmu_index

2024-02-01 Thread Richard Henderson
Free up the riscv_cpu_mmu_index name for other usage;
emphasize that the argument is 'env'.

Reviewed-by: Alistair Francis 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/riscv/cpu.h| 4 ++--
 target/riscv/cpu_helper.c | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 5f3955c38d..9c825c7b51 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -498,7 +498,7 @@ target_ulong riscv_cpu_get_geilen(CPURISCVState *env);
 void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong geilen);
 bool riscv_cpu_vector_enabled(CPURISCVState *env);
 void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
-int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch);
+int riscv_env_mmu_index(CPURISCVState *env, bool ifetch);
 G_NORETURN void  riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
MMUAccessType access_type,
int mmu_idx, uintptr_t retaddr);
@@ -507,7 +507,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
 bool probe, uintptr_t retaddr);
 char *riscv_isa_string(RISCVCPU *cpu);
 
-#define cpu_mmu_index riscv_cpu_mmu_index
+#define cpu_mmu_index riscv_env_mmu_index
 
 #ifndef CONFIG_USER_ONLY
 void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index c7cc7eb423..15f87ecdb0 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -33,7 +33,7 @@
 #include "debug.h"
 #include "tcg/oversized-guest.h"
 
-int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
+int riscv_env_mmu_index(CPURISCVState *env, bool ifetch)
 {
 #ifdef CONFIG_USER_ONLY
 return 0;
-- 
2.34.1




[PULL 12/57] target/loongarch: Rename MMU_IDX_*

2024-02-01 Thread Richard Henderson
The expected form is MMU_FOO_IDX, not MMU_IDX_FOO.
Rename to match generic code.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/loongarch/cpu.h | 8 
 target/loongarch/cpu.c | 2 +-
 target/loongarch/tcg/tlb_helper.c  | 4 ++--
 target/loongarch/tcg/translate.c   | 2 +-
 target/loongarch/tcg/insn_trans/trans_privileged.c.inc | 2 +-
 5 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 5dfcfeb3a4..47fd110e81 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -404,15 +404,15 @@ struct LoongArchCPUClass {
  */
 #define MMU_PLV_KERNEL   0
 #define MMU_PLV_USER 3
-#define MMU_IDX_KERNEL   MMU_PLV_KERNEL
-#define MMU_IDX_USER MMU_PLV_USER
-#define MMU_IDX_DA   4
+#define MMU_KERNEL_IDX   MMU_PLV_KERNEL
+#define MMU_USER_IDX MMU_PLV_USER
+#define MMU_DA_IDX   4
 
 int loongarch_cpu_mmu_index(CPUState *cs, bool ifetch);
 static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch)
 {
 #ifdef CONFIG_USER_ONLY
-return MMU_IDX_USER;
+return MMU_USER_IDX;
 #else
 return loongarch_cpu_mmu_index(env_cpu(env), ifetch);
 #endif
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index cbecc63213..139acfe373 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -382,7 +382,7 @@ int loongarch_cpu_mmu_index(CPUState *cs, bool ifetch)
 if (FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG)) {
 return FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV);
 }
-return MMU_IDX_DA;
+return MMU_DA_IDX;
 }
 
 static void loongarch_la464_initfn(Object *obj)
diff --git a/target/loongarch/tcg/tlb_helper.c 
b/target/loongarch/tcg/tlb_helper.c
index 449043c68b..65ffbef08e 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -188,8 +188,8 @@ static int get_physical_address(CPULoongArchState *env, 
hwaddr *physical,
 int *prot, target_ulong address,
 MMUAccessType access_type, int mmu_idx)
 {
-int user_mode = mmu_idx == MMU_IDX_USER;
-int kernel_mode = mmu_idx == MMU_IDX_KERNEL;
+int user_mode = mmu_idx == MMU_USER_IDX;
+int kernel_mode = mmu_idx == MMU_KERNEL_IDX;
 uint32_t plv, base_c, base_v;
 int64_t addr_high;
 uint8_t da = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, DA);
diff --git a/target/loongarch/tcg/translate.c b/target/loongarch/tcg/translate.c
index 235515c629..58674cb268 100644
--- a/target/loongarch/tcg/translate.c
+++ b/target/loongarch/tcg/translate.c
@@ -125,7 +125,7 @@ static void 
loongarch_tr_init_disas_context(DisasContextBase *dcbase,
 if (ctx->base.tb->flags & HW_FLAGS_CRMD_PG) {
 ctx->mem_idx = ctx->plv;
 } else {
-ctx->mem_idx = MMU_IDX_DA;
+ctx->mem_idx = MMU_DA_IDX;
 }
 
 /* Bound the number of insns to execute to those left on the page.  */
diff --git a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc 
b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
index 01d457212b..7e4ec93edb 100644
--- a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
+++ b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
@@ -323,7 +323,7 @@ TRANS(iocsrwr_d, IOCSR, gen_iocsrwr, gen_helper_iocsrwr_d)
 
 static void check_mmu_idx(DisasContext *ctx)
 {
-if (ctx->mem_idx != MMU_IDX_DA) {
+if (ctx->mem_idx != MMU_DA_IDX) {
 tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next + 4);
 ctx->base.is_jmp = DISAS_EXIT;
 }
-- 
2.34.1




[PULL 03/57] target/alpha: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/alpha/cpu.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
index de705c3703..bf70173a25 100644
--- a/target/alpha/cpu.c
+++ b/target/alpha/cpu.c
@@ -64,6 +64,11 @@ static bool alpha_cpu_has_work(CPUState *cs)
 | CPU_INTERRUPT_MCHK);
 }
 
+static int alpha_cpu_mmu_index(CPUState *cs, bool ifetch)
+{
+return alpha_env_mmu_index(cpu_env(cs));
+}
+
 static void alpha_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
 {
 info->mach = bfd_mach_alpha_ev6;
@@ -230,6 +235,7 @@ static void alpha_cpu_class_init(ObjectClass *oc, void 
*data)
 
 cc->class_by_name = alpha_cpu_class_by_name;
 cc->has_work = alpha_cpu_has_work;
+cc->mmu_index = alpha_cpu_mmu_index;
 cc->dump_state = alpha_cpu_dump_state;
 cc->set_pc = alpha_cpu_set_pc;
 cc->get_pc = alpha_cpu_get_pc;
-- 
2.34.1




[PULL 32/57] include/exec: Implement cpu_mmu_index generically

2024-02-01 Thread Richard Henderson
For user-only mode, use MMU_USER_IDX.
For system mode, use CPUClass.mmu_index.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/exec/cpu-all.h|  4 
 include/exec/cpu-common.h | 22 ++
 target/alpha/cpu.h|  5 -
 target/arm/cpu.h  | 13 -
 target/avr/cpu.h  |  5 -
 target/cris/cpu.h |  4 
 target/hexagon/cpu.h  |  9 -
 target/hppa/cpu.h | 10 --
 target/i386/cpu.h |  6 --
 target/loongarch/cpu.h| 10 --
 target/m68k/cpu.h |  4 
 target/microblaze/cpu.h   |  6 --
 target/mips/cpu.h |  5 -
 target/nios2/cpu.h|  6 --
 target/openrisc/cpu.h |  6 --
 target/ppc/cpu.h  |  5 -
 target/riscv/cpu.h|  2 --
 target/rx/cpu.h   |  5 -
 target/s390x/cpu.h|  2 --
 target/sh4/cpu.h  |  6 --
 target/sparc/cpu.h|  6 --
 target/tricore/cpu.h  |  5 -
 target/xtensa/cpu.h   |  5 -
 target/hppa/cpu.c |  2 +-
 target/i386/cpu.c |  2 +-
 target/loongarch/cpu.c|  2 +-
 target/microblaze/cpu.c   |  2 +-
 target/nios2/cpu.c|  2 +-
 target/openrisc/cpu.c |  2 +-
 target/sh4/cpu.c  |  2 +-
 target/sparc/cpu.c|  2 +-
 31 files changed, 34 insertions(+), 133 deletions(-)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 8501a33dbf..80c0d0699b 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -311,6 +311,10 @@ CPUArchState *cpu_copy(CPUArchState *env);
 #define TLB_MMIO(1 << (TARGET_PAGE_BITS_MIN - 2))
 #define TLB_WATCHPOINT  0
 
+static inline int cpu_mmu_index(CPUArchState *env, bool ifetch)
+{
+return MMU_USER_IDX;
+}
 #else
 
 /*
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index dcbd5f5783..cdfbe994fd 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -8,6 +8,7 @@
 #include "exec/hwaddr.h"
 #endif
 #include "hw/core/cpu.h"
+#include "tcg/debug-assert.h"
 
 #define EXCP_INTERRUPT  0x1 /* async interruption */
 #define EXCP_HLT0x10001 /* hlt instruction reached */
@@ -262,4 +263,25 @@ static inline CPUState *env_cpu(CPUArchState *env)
 return (void *)env - sizeof(CPUState);
 }
 
+#ifndef CONFIG_USER_ONLY
+/**
+ * cpu_mmu_index:
+ * @env: The cpu environment
+ * @ifetch: True for code access, false for data access.
+ *
+ * Return the core mmu index for the current translation regime.
+ * This function is used by generic TCG code paths.
+ *
+ * The user-only version of this function is inline in cpu-all.h,
+ * where it always returns MMU_USER_IDX.
+ */
+static inline int cpu_mmu_index(CPUArchState *env, bool ifetch)
+{
+CPUState *cs = env_cpu(env);
+int ret = cs->cc->mmu_index(cs, ifetch);
+tcg_debug_assert(ret >= 0 && ret < NB_MMU_MODES);
+return ret;
+}
+#endif /* !CONFIG_USER_ONLY */
+
 #endif /* CPU_COMMON_H */
diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h
index 3beff2738a..7188a409a0 100644
--- a/target/alpha/cpu.h
+++ b/target/alpha/cpu.h
@@ -398,11 +398,6 @@ static inline int alpha_env_mmu_index(CPUAlphaState *env)
 return ret;
 }
 
-static inline int cpu_mmu_index(CPUAlphaState *env, bool ifetch)
-{
-return alpha_env_mmu_index(env);
-}
-
 enum {
 IR_V0   = 0,
 IR_T0   = 1,
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index d3477b1601..63f31e0d98 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3240,19 +3240,6 @@ FIELD(TBFLAG_A64, NV2_MEM_BE, 36, 1)
 #define EX_TBFLAG_M32(IN, WHICH)   FIELD_EX32(IN.flags2, TBFLAG_M32, WHICH)
 #define EX_TBFLAG_AM32(IN, WHICH)  FIELD_EX32(IN.flags2, TBFLAG_AM32, WHICH)
 
-/**
- * cpu_mmu_index:
- * @env: The cpu environment
- * @ifetch: True for code access, false for data access.
- *
- * Return the core mmu index for the current translation regime.
- * This function is used by generic TCG code paths.
- */
-static inline int cpu_mmu_index(CPUARMState *env, bool ifetch)
-{
-return EX_TBFLAG_ANY(env->hflags, MMUIDX);
-}
-
 /**
  * sve_vq
  * @env: the cpu context
diff --git a/target/avr/cpu.h b/target/avr/cpu.h
index 4595c6bb18..d185d20dcb 100644
--- a/target/avr/cpu.h
+++ b/target/avr/cpu.h
@@ -184,11 +184,6 @@ static inline void set_avr_feature(CPUAVRState *env, int 
feature)
 env->features |= (1U << feature);
 }
 
-static inline int cpu_mmu_index(CPUAVRState *env, bool ifetch)
-{
-return ifetch ? MMU_CODE_IDX : MMU_DATA_IDX;
-}
-
 void avr_cpu_tcg_init(void);
 
 int cpu_avr_exec(CPUState *cpu);
diff --git a/target/cris/cpu.h b/target/cris/cpu.h
index d830dcac5b..3904e5448c 100644
--- a/target/cris/cpu.h
+++ b/target/cris/cpu.h
@@ -260,10 +260,6 @@ enum {
 
 /* MMU modes definitions */
 #define MMU_USER_IDX 1
-static inline int cpu_mmu_index (CPUCRISState *env, bool ifetch)
-{
-   return !!(env->pregs[PR_CCS] & U_FLAG);
-}
 
 /* Support function regs.  */
 #define SFR_RW_GC_CFG   

[PULL 14/57] target/microblaze: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/microblaze/cpu.h | 13 ++---
 target/microblaze/cpu.c | 18 +-
 2 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h
index b5374365f5..90ab796de9 100644
--- a/target/microblaze/cpu.h
+++ b/target/microblaze/cpu.h
@@ -434,19 +434,10 @@ void mb_cpu_transaction_failed(CPUState *cs, hwaddr 
physaddr, vaddr addr,
MemTxResult response, uintptr_t retaddr);
 #endif
 
+int mb_cpu_mmu_index(CPUState *cs, bool ifetch);
 static inline int cpu_mmu_index(CPUMBState *env, bool ifetch)
 {
-MicroBlazeCPU *cpu = env_archcpu(env);
-
-/* Are we in nommu mode?.  */
-if (!(env->msr & MSR_VM) || !cpu->cfg.use_mmu) {
-return MMU_NOMMU_IDX;
-}
-
-if (env->msr & MSR_UM) {
-return MMU_USER_IDX;
-}
-return MMU_KERNEL_IDX;
+return mb_cpu_mmu_index(env_cpu(env), ifetch);
 }
 
 #ifndef CONFIG_USER_ONLY
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
index 2318ad7013..6dad11905b 100644
--- a/target/microblaze/cpu.c
+++ b/target/microblaze/cpu.c
@@ -118,6 +118,22 @@ static bool mb_cpu_has_work(CPUState *cs)
 return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
 }
 
+int mb_cpu_mmu_index(CPUState *cs, bool ifetch)
+{
+CPUMBState *env = cpu_env(cs);
+MicroBlazeCPU *cpu = env_archcpu(env);
+
+/* Are we in nommu mode?.  */
+if (!(env->msr & MSR_VM) || !cpu->cfg.use_mmu) {
+return MMU_NOMMU_IDX;
+}
+
+if (env->msr & MSR_UM) {
+return MMU_USER_IDX;
+}
+return MMU_KERNEL_IDX;
+}
+
 #ifndef CONFIG_USER_ONLY
 static void mb_cpu_ns_axi_dp(void *opaque, int irq, int level)
 {
@@ -415,7 +431,7 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
 
 cc->class_by_name = mb_cpu_class_by_name;
 cc->has_work = mb_cpu_has_work;
-
+cc->mmu_index = mb_cpu_mmu_index;
 cc->dump_state = mb_cpu_dump_state;
 cc->set_pc = mb_cpu_set_pc;
 cc->get_pc = mb_cpu_get_pc;
-- 
2.34.1




[PULL 01/57] include/hw/core: Add mmu_index to CPUClass

2024-02-01 Thread Richard Henderson
To be used after all targets have populated the hook.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/hw/core/cpu.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 2c284d6397..4385ce54c9 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -103,6 +103,8 @@ struct SysemuCPUOps;
  * @parse_features: Callback to parse command line arguments.
  * @reset_dump_flags: #CPUDumpFlags to use for reset logging.
  * @has_work: Callback for checking if there is work to do.
+ * @mmu_index: Callback for choosing softmmu mmu index;
+ *   may be used internally by memory_rw_debug without TCG.
  * @memory_rw_debug: Callback for GDB memory access.
  * @dump_state: Callback for dumping state.
  * @query_cpu_fast:
@@ -150,6 +152,7 @@ struct CPUClass {
 void (*parse_features)(const char *typename, char *str, Error **errp);
 
 bool (*has_work)(CPUState *cpu);
+int (*mmu_index)(CPUState *cpu, bool ifetch);
 int (*memory_rw_debug)(CPUState *cpu, vaddr addr,
uint8_t *buf, int len, bool is_write);
 void (*dump_state)(CPUState *cpu, FILE *, int flags);
-- 
2.34.1




[PULL 04/57] target/arm: Split out arm_env_mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/arm/internals.h  |  5 +
 target/arm/helper.c |  2 +-
 target/arm/tcg/helper-a64.c |  4 ++--
 target/arm/tcg/mte_helper.c | 18 +-
 target/arm/tcg/sve_helper.c |  8 
 target/arm/tcg/tlb_helper.c |  2 +-
 6 files changed, 22 insertions(+), 17 deletions(-)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index 71d6c70bf3..fc337fe40e 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -40,6 +40,11 @@
 #define BANK_HYP6
 #define BANK_MON7
 
+static inline int arm_env_mmu_index(CPUARMState *env)
+{
+return EX_TBFLAG_ANY(env->hflags, MMUIDX);
+}
+
 static inline bool excp_is_internal(int excp)
 {
 /* Return true if this exception number represents a QEMU-internal
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 945d8571a6..b0488caf40 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -7841,7 +7841,7 @@ static void dccvap_writefn(CPUARMState *env, const 
ARMCPRegInfo *opaque,
 uint64_t vaddr_in = (uint64_t) value;
 uint64_t vaddr = vaddr_in & ~(dline_size - 1);
 void *haddr;
-int mem_idx = cpu_mmu_index(env, false);
+int mem_idx = arm_env_mmu_index(env);
 
 /* This won't be crossing page boundaries */
 haddr = probe_read(env, vaddr, dline_size, mem_idx, GETPC());
diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c
index 198b975f20..ebaa7f00df 100644
--- a/target/arm/tcg/helper-a64.c
+++ b/target/arm/tcg/helper-a64.c
@@ -856,7 +856,7 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t 
new_pc)
 tbii = EX_TBFLAG_A64(env->hflags, TBII);
 if ((tbii >> extract64(new_pc, 55, 1)) & 1) {
 /* TBI is enabled. */
-int core_mmu_idx = cpu_mmu_index(env, false);
+int core_mmu_idx = arm_env_mmu_index(env);
 if (regime_has_2_ranges(core_to_aa64_mmu_idx(core_mmu_idx))) {
 new_pc = sextract64(new_pc, 0, 56);
 } else {
@@ -925,7 +925,7 @@ void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in)
  */
 int blocklen = 4 << env_archcpu(env)->dcz_blocksize;
 uint64_t vaddr = vaddr_in & ~(blocklen - 1);
-int mmu_idx = cpu_mmu_index(env, false);
+int mmu_idx = arm_env_mmu_index(env);
 void *mem;
 
 /*
diff --git a/target/arm/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c
index ffb8ea1c34..d971b81370 100644
--- a/target/arm/tcg/mte_helper.c
+++ b/target/arm/tcg/mte_helper.c
@@ -291,7 +291,7 @@ static int load_tag1(uint64_t ptr, uint8_t *mem)
 
 uint64_t HELPER(ldg)(CPUARMState *env, uint64_t ptr, uint64_t xt)
 {
-int mmu_idx = cpu_mmu_index(env, false);
+int mmu_idx = arm_env_mmu_index(env);
 uint8_t *mem;
 int rtag = 0;
 
@@ -311,7 +311,7 @@ static void check_tag_aligned(CPUARMState *env, uint64_t 
ptr, uintptr_t ra)
 {
 if (unlikely(!QEMU_IS_ALIGNED(ptr, TAG_GRANULE))) {
 arm_cpu_do_unaligned_access(env_cpu(env), ptr, MMU_DATA_STORE,
-cpu_mmu_index(env, false), ra);
+arm_env_mmu_index(env), ra);
 g_assert_not_reached();
 }
 }
@@ -344,7 +344,7 @@ typedef void stg_store1(uint64_t, uint8_t *, int);
 static inline void do_stg(CPUARMState *env, uint64_t ptr, uint64_t xt,
   uintptr_t ra, stg_store1 store1)
 {
-int mmu_idx = cpu_mmu_index(env, false);
+int mmu_idx = arm_env_mmu_index(env);
 uint8_t *mem;
 
 check_tag_aligned(env, ptr, ra);
@@ -371,7 +371,7 @@ void HELPER(stg_parallel)(CPUARMState *env, uint64_t ptr, 
uint64_t xt)
 
 void HELPER(stg_stub)(CPUARMState *env, uint64_t ptr)
 {
-int mmu_idx = cpu_mmu_index(env, false);
+int mmu_idx = arm_env_mmu_index(env);
 uintptr_t ra = GETPC();
 
 check_tag_aligned(env, ptr, ra);
@@ -381,7 +381,7 @@ void HELPER(stg_stub)(CPUARMState *env, uint64_t ptr)
 static inline void do_st2g(CPUARMState *env, uint64_t ptr, uint64_t xt,
uintptr_t ra, stg_store1 store1)
 {
-int mmu_idx = cpu_mmu_index(env, false);
+int mmu_idx = arm_env_mmu_index(env);
 int tag = allocation_tag_from_addr(xt);
 uint8_t *mem1, *mem2;
 
@@ -429,7 +429,7 @@ void HELPER(st2g_parallel)(CPUARMState *env, uint64_t ptr, 
uint64_t xt)
 
 void HELPER(st2g_stub)(CPUARMState *env, uint64_t ptr)
 {
-int mmu_idx = cpu_mmu_index(env, false);
+int mmu_idx = arm_env_mmu_index(env);
 uintptr_t ra = GETPC();
 int in_page = -(ptr | TARGET_PAGE_MASK);
 
@@ -445,7 +445,7 @@ void HELPER(st2g_stub)(CPUARMState *env, uint64_t ptr)
 
 uint64_t HELPER(ldgm)(CPUARMState *env, uint64_t ptr)
 {
-int mmu_idx = cpu_mmu_index(env, false);
+int mmu_idx = arm_env_mmu_index(env);
 uintptr_t ra = GETPC();
 int gm_bs = env_archcpu(env)->gm_blocksize;
 int gm_bs_bytes = 4 << gm_bs;
@@ -505,7 +505,7 @@ uint64_t HELPER(ldgm)(CPUARMState *env, uint64_t ptr)
 
 void 

[PULL 09/57] target/hppa: Populate CPUClass.mmu_index

2024-02-01 Thread Richard Henderson
Reviewed-by: Helge Deller 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.h |  7 ++-
 target/hppa/cpu.c | 12 
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 6a153405d2..04439f247d 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -281,16 +281,13 @@ static inline int HPPA_BTLB_ENTRIES(CPUHPPAState *env)
 return hppa_is_pa20(env) ? 0 : PA10_BTLB_FIXED + PA10_BTLB_VARIABLE;
 }
 
+int hppa_cpu_mmu_index(CPUState *cs, bool ifetch);
 static inline int cpu_mmu_index(CPUHPPAState *env, bool ifetch)
 {
 #ifdef CONFIG_USER_ONLY
 return MMU_USER_IDX;
 #else
-if (env->psw & (ifetch ? PSW_C : PSW_D)) {
-return PRIV_P_TO_MMU_IDX(env->iaoq_f & 3, env->psw & PSW_P);
-}
-/* mmu disabled */
-return env->psw & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX;
+return hppa_cpu_mmu_index(env_cpu(env), ifetch);
 #endif
 }
 
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index 3c019855b4..fbb37e541e 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -94,6 +94,17 @@ static bool hppa_cpu_has_work(CPUState *cs)
 return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
 }
 
+int hppa_cpu_mmu_index(CPUState *cs, bool ifetch)
+{
+CPUHPPAState *env = cpu_env(cs);
+
+if (env->psw & (ifetch ? PSW_C : PSW_D)) {
+return PRIV_P_TO_MMU_IDX(env->iaoq_f & 3, env->psw & PSW_P);
+}
+/* mmu disabled */
+return env->psw & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX;
+}
+
 static void hppa_cpu_disas_set_info(CPUState *cs, disassemble_info *info)
 {
 info->mach = bfd_mach_hppa20;
@@ -194,6 +205,7 @@ static void hppa_cpu_class_init(ObjectClass *oc, void *data)
 
 cc->class_by_name = hppa_cpu_class_by_name;
 cc->has_work = hppa_cpu_has_work;
+cc->mmu_index = hppa_cpu_mmu_index;
 cc->dump_state = hppa_cpu_dump_state;
 cc->set_pc = hppa_cpu_set_pc;
 cc->get_pc = hppa_cpu_get_pc;
-- 
2.34.1




Re: [PATCH 00/22] target/sparc: floating-point cleanup

2024-02-01 Thread Richard Henderson

On 2/1/24 07:49, Mark Cave-Ayland wrote:

I'm happy for you to take this via tcg-next if that's easiest for you.


Yes, I can do that.


r~



Re: [PATCH 05/22] target/sparc: Inline FNEG, FABS

2024-02-01 Thread Richard Henderson

On 1/30/24 18:40, Philippe Mathieu-Daudé wrote:

Hi Richard,

On 3/11/23 18:38, Richard Henderson wrote:

These are simple bit manipulation insns.
Begin using i128 for float128.
Implement FMOVq with do_qq.

Signed-off-by: Richard Henderson 
---
  target/sparc/helper.h |  6 
  target/sparc/fop_helper.c | 34 -
  target/sparc/translate.c  | 62 +++
  3 files changed, 30 insertions(+), 72 deletions(-)




@@ -1239,13 +1235,13 @@ static void gen_op_fmovs(TCGv_i32 dst, TCGv_i32 src)
  static void gen_op_fnegs(TCGv_i32 dst, TCGv_i32 src)
  {
  gen_op_clear_ieee_excp_and_FTT();
-    gen_helper_fnegs(dst, src);
+    tcg_gen_xori_i32(dst, src, 1u << 31);
  }
  static void gen_op_fabss(TCGv_i32 dst, TCGv_i32 src)
  {
  gen_op_clear_ieee_excp_and_FTT();
-    gen_helper_fabss(dst, src);
+    tcg_gen_andi_i32(dst, src, ~(1u << 31));
  }
  static void gen_op_fmovd(TCGv_i64 dst, TCGv_i64 src)
@@ -1257,13 +1253,33 @@ static void gen_op_fmovd(TCGv_i64 dst, TCGv_i64 src)
  static void gen_op_fnegd(TCGv_i64 dst, TCGv_i64 src)
  {
  gen_op_clear_ieee_excp_and_FTT();
-    gen_helper_fnegd(dst, src);
+    tcg_gen_xori_i64(dst, src, 1ull << 63);
  }
  static void gen_op_fabsd(TCGv_i64 dst, TCGv_i64 src)
  {
  gen_op_clear_ieee_excp_and_FTT();
-    gen_helper_fabsd(dst, src);
+    tcg_gen_andi_i64(dst, src, ~(1ull << 63));
+}
+
+static void gen_op_fnegq(TCGv_i128 dst, TCGv_i128 src)
+{
+    TCGv_i64 l = tcg_temp_new_i64();
+    TCGv_i64 h = tcg_temp_new_i64();
+
+    tcg_gen_extr_i128_i64(l, h, src);
+    tcg_gen_xori_i64(h, h, 1ull << 63);
+    tcg_gen_concat_i64_i128(dst, l, h);
+}
+
+static void gen_op_fabsq(TCGv_i128 dst, TCGv_i128 src)
+{
+    TCGv_i64 l = tcg_temp_new_i64();
+    TCGv_i64 h = tcg_temp_new_i64();
+
+    tcg_gen_extr_i128_i64(l, h, src);
+    tcg_gen_andi_i64(h, h, ~(1ull << 63));
+    tcg_gen_concat_i64_i128(dst, l, h);
  }


Why not extract these as generic TCG FPU helpers?


The representation of floating-point registers varies wildly between targets.  Sparc would 
be the only one to (a) have float128 and (b) represent them in TCGv_i128.


Even considering float32, is the representation TCGv_i32 or TCGv_i64?
Should the result be nan-boxed (riscv and loongarch)?

We already provide tcg_gen_xori_i{32,64}, so, really that's enough for any 
target.


$ git grep -wE 'float...?_(chs|abs)' target/
target/arm/tcg/helper-a64.c:214:    a = float16_chs(a);
target/arm/tcg/helper-a64.c:229:    a = float32_chs(a);
target/arm/tcg/helper-a64.c:244:    a = float64_chs(a);
target/arm/tcg/helper-a64.c:259:    a = float16_chs(a);
target/arm/tcg/helper-a64.c:274:    a = float32_chs(a);
target/arm/tcg/helper-a64.c:289:    a = float64_chs(a);
target/arm/tcg/helper-a64.c:632:    float16 f0 = float16_abs(a);
target/arm/tcg/helper-a64.c:633:    float16 f1 = float16_abs(b);
target/arm/tcg/helper-a64.c:642:    float16 f0 = float16_abs(a);
target/arm/tcg/helper-a64.c:643:    float16 f1 = float16_abs(b);
target/arm/tcg/mve_helper.c:2840:    return float16_abs(float16_sub(a, b, s));
target/arm/tcg/mve_helper.c:2845:    return float32_abs(float32_sub(a, b, s));
target/arm/tcg/mve_helper.c:2854:    return float16_maxnum(float16_abs(a), float16_abs(b), 
s);
target/arm/tcg/mve_helper.c:2859:    return float32_maxnum(float32_abs(a), float32_abs(b), 
s);
target/arm/tcg/mve_helper.c:2864:    return float16_minnum(float16_abs(a), float16_abs(b), 
s);
target/arm/tcg/mve_helper.c:2869:    return float32_minnum(float32_abs(a), float32_abs(b), 
s);

target/arm/tcg/neon_helper.c:1513:    float32 f0 = float32_abs(make_float32(a));
target/arm/tcg/neon_helper.c:1514:    float32 f1 = float32_abs(make_float32(b));
target/arm/tcg/neon_helper.c:1521:    float32 f0 = float32_abs(make_float32(a));
target/arm/tcg/neon_helper.c:1522:    float32 f1 = float32_abs(make_float32(b));
target/arm/tcg/neon_helper.c:1529:    float64 f0 = float64_abs(make_float64(a));
target/arm/tcg/neon_helper.c:1530:    float64 f1 = float64_abs(make_float64(b));
target/arm/tcg/neon_helper.c:1537:    float64 f0 = float64_abs(make_float64(a));
target/arm/tcg/neon_helper.c:1538:    float64 f1 = float64_abs(make_float64(b));
target/arm/tcg/sve_helper.c:4227:DO_REDUCE(sve_fmaxv_h, float16, H1_2, max, 
float16_chs(float16_infinity))
target/arm/tcg/sve_helper.c:4228:DO_REDUCE(sve_fmaxv_s, float32, H1_4, max, 
float32_chs(float32_infinity))
target/arm/tcg/sve_helper.c:4229:DO_REDUCE(sve_fmaxv_d, float64, H1_8, max, 
float64_chs(float64_infinity))

target/arm/tcg/sve_helper.c:4345:    return float16_abs(float16_sub(a, b, s));
target/arm/tcg/sve_helper.c:4350:    return float32_abs(float32_sub(a, b, s));
target/arm/tcg/sve_helper.c:4355:    return float64_abs(float64_sub(a, b, s));
target/arm/tcg/sve_helper.c:4997:    mm = float16_abs(mm);
target/arm/tcg/sve_helper.c:5019:    mm = float32_abs(mm);
target/arm/tcg/sve_helper.c:5045:    mm = float64_abs(mm);
target/arm/tcg/sve_helper.c:5062:    

Re: [PULL 02/10] hw/hppa/machine: Disable default devices with --nodefaults option

2024-02-01 Thread Guenter Roeck
Hi,

On Sat, Jan 13, 2024 at 06:57:20AM +0100, del...@kernel.org wrote:
> From: Helge Deller 
> 
> Recognize the qemu --nodefaults option, which will disable the
> following default devices on hppa:
> - lsi53c895a SCSI controller,
> - artist graphics card,
> - LASI 82596 NIC,
> - tulip PCI NIC,
> - second serial PCI card,
> - USB OHCI controller.
> 
> Adding this option is very useful to allow manual testing and
> debugging of the other possible devices on the command line.
> 

With this patch in the tree, I get some interesting crashes in Seabios
if I provide a somewhat unusual command line option. For example,
something like

-usb -device usb-ehci,id=ehci \
-device usb-uas,bus=ehci.0,id=uas \
-device scsi-hd,bus=uas.0,scsi-id=0,lun=0,drive=d0 \
-drive file= ...

is accepted as command line option but results in

SeaBIOS PA-RISC 32-bit Firmware Version 15 (QEMU 8.2.1)
Duplex Console IO Dependent Code (IODC) revision 1
--
  (c) Copyright 2017-2024 Helge Deller  and SeaBIOS developers.
--
  Processor   SpeedState   Coprocessor State  Cache Size
  -     -  -  --
  0  250 MHzActive Functional0 KB
  1  250 MHzIdle   Functional0 KB
  2  250 MHzIdle   Functional0 KB
  3  250 MHzIdle   Functional0 KB
  Emulated machine: HP C3700 (64-bit PA2.0) with 32-bit PDC
  Available memory: 1024 MB
  Good memory required: 16 MB
  Primary boot path:FWSCSI.0.0
  Alternate boot path:  FWSCSI.0.0
  Console path: SERIAL_2.9600.8.none
  Keyboard path:SERIAL_2.9600.8.none
*ERROR* in SeaBIOS-hppa-v15:
prepare_boot_path:2898
SeaBIOS wants SYSTEM HALT.

This is without --nodefaults, and it used to work. Is that intentional ?

If I do use the --nodefaults parameter, I was unable to figure out how
to configure the serial console. What command line parameter(s) do I need to
get it ?

Thanks,
Guenter



Re: [PATCH] tests/tcg: Fix the /proc/self/mem probing in the PROT_NONE gdbstub test

2024-02-01 Thread Richard Henderson

On 2/1/24 08:02, Ilya Leoshkevich wrote:

The `if not probe_proc_self_mem` check never passes, because
probe_proc_self_mem is a function object, which is a truthy value.
Add parentheses in order to perform a function call.

Fixes: dc84d50a7f9b ("tests/tcg: Add the PROT_NONE gdbstub test")
Signed-off-by: Ilya Leoshkevich 
---
  tests/tcg/multiarch/gdbstub/prot-none.py | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/tcg/multiarch/gdbstub/prot-none.py 
b/tests/tcg/multiarch/gdbstub/prot-none.py
index e829d3ebc5f..7e264589cb8 100644
--- a/tests/tcg/multiarch/gdbstub/prot-none.py
+++ b/tests/tcg/multiarch/gdbstub/prot-none.py
@@ -20,7 +20,7 @@ def probe_proc_self_mem():
  
  def run_test():

  """Run through the tests one by one"""
-if not probe_proc_self_mem:
+if not probe_proc_self_mem():
  print("SKIP: /proc/self/mem is not usable")
  exit(0)
  gdb.Breakpoint("break_here")


Ack.  Queued to tcg-next.

r~



Re: [PATCH 13/14] migration/multifd: Move header prepare/fill into send_prepare()

2024-02-01 Thread Peter Xu
On Wed, Jan 31, 2024 at 06:31:10PM +0800, pet...@redhat.com wrote:
> From: Peter Xu 
> 
> This patch redefines the interfacing of ->send_prepare().  It further
> simplifies multifd_send_thread() especially on zero copy.
> 
> Now with the new interface, we require the hook to do all the work for
> preparing the IOVs to send.  After it's completed, the IOVs should be ready
> to be dumped into the specific multifd QIOChannel later.
> 
> So now the API looks like:
> 
>   p->pages --->  send_prepare() -> IOVs
> 
> This also prepares for the case where the input can be extended to even not
> any p->pages.  But that's for later.
> 
> This patch will achieve similar goal of what Fabiano used to propose here:
> 
> https://lore.kernel.org/r/20240126221943.26628-1-faro...@suse.de
> 
> However the send() interface may not be necessary.  I'm boldly attaching a
> "Co-developed-by" for Fabiano.
> 
> Co-developed-by: Fabiano Rosas 
> Signed-off-by: Peter Xu 

Just a heads-up: I plan to squash something like below also into it.
That's mostly Fabiano's:

https://lore.kernel.org/r/20240126221943.26628-6-faro...@suse.de

But instead of overwritting write_flags in the hook, I made it a
conditional "OR" just in case we'll extend write_flags later in common
paths and get it overlooked.

In short, I'll keep all zerocopy changes together in this single patch,
hopefully clearer.

=
diff --git a/migration/multifd.c b/migration/multifd.c
index cd4467aff4..6aa44340de 100644
--- a/migration/multifd.c
+++ b/migration/multifd.c
@@ -50,15 +50,15 @@ typedef struct {
 /**
  * nocomp_send_setup: setup send side
  *
- * For no compression this function does nothing.
- *
- * Returns 0 for success or -1 for error
- *
  * @p: Params for the channel that we are using
  * @errp: pointer to an error
  */
 static int nocomp_send_setup(MultiFDSendParams *p, Error **errp)
 {
+if (migrate_zero_copy_send()) {
+p->write_flags |= QIO_CHANNEL_WRITE_FLAG_ZERO_COPY;
+}
+
 return 0;
 }

-- 
Peter Xu




[PATCH] linux-user/aarch64: Add padding before __kernel_rt_sigreturn

2024-02-01 Thread Richard Henderson
Without this padding, an unwind through the signal handler
will pick up the unwind info for the preceding syscall.

This fixes gcc's 30_threads/thread/native_handle/cancel.cc.

Cc: qemu-sta...@nongnu.org
Fixes: ee95fae075c6 ("linux-user/aarch64: Add vdso")
Resolves: https://linaro.atlassian.net/browse/GNU-974
Signed-off-by: Richard Henderson 
---
 linux-user/aarch64/vdso-be.so | Bin 3216 -> 3224 bytes
 linux-user/aarch64/vdso-le.so | Bin 3216 -> 3224 bytes
 linux-user/aarch64/vdso.S |   4 
 3 files changed, 4 insertions(+)

diff --git a/linux-user/aarch64/vdso-be.so b/linux-user/aarch64/vdso-be.so
index 
6084f3d1a701316004894fcdd739c4e1e0463b68..808206ade824b09d786f6cc34f7cddf80b63130e
 100755
GIT binary patch
delta 121
zcmbOrIYV-SKI4pu2Kk&{7{Gw#%fuBAMC1c?^>~k}v|avdxNjSSLfftVb3bgJ!|2S&
z_-6A1CJrVZc?IUH8G;R$7#SF@Om<{a*v!K!^~TWO|cva$K*Om;sOMw`hy
ZxXl@VO#Z-a#EKC)of1

delta 116
zcmbOsIYDxQKI4Rm2Kk{Gw#!^9O2L>8U?-5V_M@!kH(Sx4vJn|*ujLPgija~Pc&
z8DDIEz{J5c`3;N8W)W6tCdL<&4cM*OEF8_CVnO!c?IUH8G;R$7#SF@Om<{a*v!K!!o>JyvLd?^n`3BUW_royOm=q`Mw`hS
dxy>1WOn%92lgFM@hy!9z%j7~Xc>tTxDQW-!

delta 108
zcmbOsIYDxQ2IGW@n)#d`SQx

Re: [PATCH v3] target/riscv: mcountinhibit, mcounteren, scounteren, hcounteren is 32-bit

2024-02-01 Thread Alistair Francis
On Wed, Jan 31, 2024 at 10:37 PM Vadim Shakirov
 wrote:
>
> mcountinhibit, mcounteren, scounteren and hcounteren must always be 32-bit
> by privileged spec
>
> Signed-off-by: Vadim Shakirov 

Do you mind rebasing this on
https://github.com/alistair23/qemu/tree/riscv-to-apply.next ?

Alistair

> ---
>  target/riscv/cpu.h |  8 
>  target/riscv/machine.c | 16 
>  2 files changed, 12 insertions(+), 12 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 5b0824ef8f..88efd8a6f9 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -254,7 +254,7 @@ struct CPUArchState {
>  target_ulong hstatus;
>  target_ulong hedeleg;
>  uint64_t hideleg;
> -target_ulong hcounteren;
> +uint32_t hcounteren;
>  target_ulong htval;
>  target_ulong htinst;
>  target_ulong hgatp;
> @@ -317,10 +317,10 @@ struct CPUArchState {
>   */
>  bool two_stage_indirect_lookup;
>
> -target_ulong scounteren;
> -target_ulong mcounteren;
> +uint32_t scounteren;
> +uint32_t mcounteren;
>
> -target_ulong mcountinhibit;
> +uint32_t mcountinhibit;
>
>  /* PMU counter state */
>  PMUCTRState pmu_ctrs[RV_MAX_MHPMCOUNTERS];
> diff --git a/target/riscv/machine.c b/target/riscv/machine.c
> index fdde243e04..f129032b0d 100644
> --- a/target/riscv/machine.c
> +++ b/target/riscv/machine.c
> @@ -79,14 +79,14 @@ static bool hyper_needed(void *opaque)
>
>  static const VMStateDescription vmstate_hyper = {
>  .name = "cpu/hyper",
> -.version_id = 3,
> -.minimum_version_id = 3,
> +.version_id = 4,
> +.minimum_version_id = 4,
>  .needed = hyper_needed,
>  .fields = (VMStateField[]) {
>  VMSTATE_UINTTL(env.hstatus, RISCVCPU),
>  VMSTATE_UINTTL(env.hedeleg, RISCVCPU),
>  VMSTATE_UINT64(env.hideleg, RISCVCPU),
> -VMSTATE_UINTTL(env.hcounteren, RISCVCPU),
> +VMSTATE_UINT32(env.hcounteren, RISCVCPU),
>  VMSTATE_UINTTL(env.htval, RISCVCPU),
>  VMSTATE_UINTTL(env.htinst, RISCVCPU),
>  VMSTATE_UINTTL(env.hgatp, RISCVCPU),
> @@ -354,8 +354,8 @@ static const VMStateDescription vmstate_jvt = {
>
>  const VMStateDescription vmstate_riscv_cpu = {
>  .name = "cpu",
> -.version_id = 9,
> -.minimum_version_id = 9,
> +.version_id = 10,
> +.minimum_version_id = 10,
>  .post_load = riscv_cpu_post_load,
>  .fields = (VMStateField[]) {
>  VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32),
> @@ -398,9 +398,9 @@ const VMStateDescription vmstate_riscv_cpu = {
>  VMSTATE_UINTTL(env.mtval, RISCVCPU),
>  VMSTATE_UINTTL(env.miselect, RISCVCPU),
>  VMSTATE_UINTTL(env.siselect, RISCVCPU),
> -VMSTATE_UINTTL(env.scounteren, RISCVCPU),
> -VMSTATE_UINTTL(env.mcounteren, RISCVCPU),
> -VMSTATE_UINTTL(env.mcountinhibit, RISCVCPU),
> +VMSTATE_UINT32(env.scounteren, RISCVCPU),
> +VMSTATE_UINT32(env.mcounteren, RISCVCPU),
> +VMSTATE_UINT32(env.mcountinhibit, RISCVCPU),
>  VMSTATE_STRUCT_ARRAY(env.pmu_ctrs, RISCVCPU, RV_MAX_MHPMCOUNTERS, 0,
>   vmstate_pmu_ctr_state, PMUCTRState),
>  VMSTATE_UINTTL_ARRAY(env.mhpmevent_val, RISCVCPU, RV_MAX_MHPMEVENTS),
> --
> 2.34.1
>
>



Re: [PATCH v3] target/riscv: mcountinhibit, mcounteren, scounteren, hcounteren is 32-bit

2024-02-01 Thread Alistair Francis
On Wed, Jan 31, 2024 at 10:37 PM Vadim Shakirov
 wrote:
>
> mcountinhibit, mcounteren, scounteren and hcounteren must always be 32-bit
> by privileged spec
>
> Signed-off-by: Vadim Shakirov 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu.h |  8 
>  target/riscv/machine.c | 16 
>  2 files changed, 12 insertions(+), 12 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 5b0824ef8f..88efd8a6f9 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -254,7 +254,7 @@ struct CPUArchState {
>  target_ulong hstatus;
>  target_ulong hedeleg;
>  uint64_t hideleg;
> -target_ulong hcounteren;
> +uint32_t hcounteren;
>  target_ulong htval;
>  target_ulong htinst;
>  target_ulong hgatp;
> @@ -317,10 +317,10 @@ struct CPUArchState {
>   */
>  bool two_stage_indirect_lookup;
>
> -target_ulong scounteren;
> -target_ulong mcounteren;
> +uint32_t scounteren;
> +uint32_t mcounteren;
>
> -target_ulong mcountinhibit;
> +uint32_t mcountinhibit;
>
>  /* PMU counter state */
>  PMUCTRState pmu_ctrs[RV_MAX_MHPMCOUNTERS];
> diff --git a/target/riscv/machine.c b/target/riscv/machine.c
> index fdde243e04..f129032b0d 100644
> --- a/target/riscv/machine.c
> +++ b/target/riscv/machine.c
> @@ -79,14 +79,14 @@ static bool hyper_needed(void *opaque)
>
>  static const VMStateDescription vmstate_hyper = {
>  .name = "cpu/hyper",
> -.version_id = 3,
> -.minimum_version_id = 3,
> +.version_id = 4,
> +.minimum_version_id = 4,
>  .needed = hyper_needed,
>  .fields = (VMStateField[]) {
>  VMSTATE_UINTTL(env.hstatus, RISCVCPU),
>  VMSTATE_UINTTL(env.hedeleg, RISCVCPU),
>  VMSTATE_UINT64(env.hideleg, RISCVCPU),
> -VMSTATE_UINTTL(env.hcounteren, RISCVCPU),
> +VMSTATE_UINT32(env.hcounteren, RISCVCPU),
>  VMSTATE_UINTTL(env.htval, RISCVCPU),
>  VMSTATE_UINTTL(env.htinst, RISCVCPU),
>  VMSTATE_UINTTL(env.hgatp, RISCVCPU),
> @@ -354,8 +354,8 @@ static const VMStateDescription vmstate_jvt = {
>
>  const VMStateDescription vmstate_riscv_cpu = {
>  .name = "cpu",
> -.version_id = 9,
> -.minimum_version_id = 9,
> +.version_id = 10,
> +.minimum_version_id = 10,
>  .post_load = riscv_cpu_post_load,
>  .fields = (VMStateField[]) {
>  VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32),
> @@ -398,9 +398,9 @@ const VMStateDescription vmstate_riscv_cpu = {
>  VMSTATE_UINTTL(env.mtval, RISCVCPU),
>  VMSTATE_UINTTL(env.miselect, RISCVCPU),
>  VMSTATE_UINTTL(env.siselect, RISCVCPU),
> -VMSTATE_UINTTL(env.scounteren, RISCVCPU),
> -VMSTATE_UINTTL(env.mcounteren, RISCVCPU),
> -VMSTATE_UINTTL(env.mcountinhibit, RISCVCPU),
> +VMSTATE_UINT32(env.scounteren, RISCVCPU),
> +VMSTATE_UINT32(env.mcounteren, RISCVCPU),
> +VMSTATE_UINT32(env.mcountinhibit, RISCVCPU),
>  VMSTATE_STRUCT_ARRAY(env.pmu_ctrs, RISCVCPU, RV_MAX_MHPMCOUNTERS, 0,
>   vmstate_pmu_ctr_state, PMUCTRState),
>  VMSTATE_UINTTL_ARRAY(env.mhpmevent_val, RISCVCPU, RV_MAX_MHPMEVENTS),
> --
> 2.34.1
>
>



Re: [PATCH 3/6] target/riscv: add remaining named features

2024-02-01 Thread Alistair Francis
On Thu, Feb 1, 2024 at 5:15 AM Daniel Henrique Barboza
 wrote:
>
>
>
> On 1/29/24 22:10, Alistair Francis wrote:
> > On Fri, Jan 26, 2024 at 5:54 AM Daniel Henrique Barboza
> >  wrote:
> >>
> >> The RVA22U64 and RVA22S64 profiles mandates certain extensions that,
> >> until now, we were implying that they were available.
> >>
> >> We can't do this anymore since named features also has a riscv,isa
> >> entry.  Let's add them to riscv_cpu_named_features[].
> >>
> >> They will also need to be explicitly enabled in both profile
> >> descriptions. TCG will enable the named features it already implements,
> >> other accelerators are free to handle it as they like.
> >>
> >> After this patch, here's the riscv,isa from a buildroot using the
> >> 'rva22s64' CPU:
> >>
> >>   # cat /proc/device-tree/cpus/cpu@0/riscv,isa
> >> rv64imafdc_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_
> >> zicntr_zicsr_zifencei_zihintpause_zihpm_za64rs_zfhmin_zca_zcd_zba_zbb_
> >> zbs_zkt_sscounterenw_sstvala_sstvecd_svade_svinval_svpbmt#
> >>
> >> Signed-off-by: Daniel Henrique Barboza 
> >> ---
> >>   target/riscv/cpu.c | 41 +-
> >>   target/riscv/cpu_cfg.h |  9 +
> >>   target/riscv/tcg/tcg-cpu.c | 19 +-
> >>   3 files changed, 59 insertions(+), 10 deletions(-)
> >>
> >> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> >> index 28d3cfa8ce..1ecd8a57ed 100644
> >> --- a/target/riscv/cpu.c
> >> +++ b/target/riscv/cpu.c
> >> @@ -101,6 +101,10 @@ const RISCVIsaExtData isa_edata_arr[] = {
> >>   ISA_EXT_DATA_ENTRY(zicbom, PRIV_VERSION_1_12_0, ext_zicbom),
> >>   ISA_EXT_DATA_ENTRY(zicbop, PRIV_VERSION_1_12_0, ext_zicbop),
> >>   ISA_EXT_DATA_ENTRY(zicboz, PRIV_VERSION_1_12_0, ext_zicboz),
> >> +ISA_EXT_DATA_ENTRY(ziccamoa, PRIV_VERSION_1_11_0, ext_ziccamoa),
> >> +ISA_EXT_DATA_ENTRY(ziccif, PRIV_VERSION_1_11_0, ext_ziccif),
> >> +ISA_EXT_DATA_ENTRY(zicclsm, PRIV_VERSION_1_11_0, ext_zicclsm),
> >> +ISA_EXT_DATA_ENTRY(ziccrse, PRIV_VERSION_1_11_0, ext_ziccrse),
> >>   ISA_EXT_DATA_ENTRY(zicond, PRIV_VERSION_1_12_0, ext_zicond),
> >>   ISA_EXT_DATA_ENTRY(zicntr, PRIV_VERSION_1_12_0, ext_zicntr),
> >>   ISA_EXT_DATA_ENTRY(zicsr, PRIV_VERSION_1_10_0, ext_zicsr),
> >> @@ -109,6 +113,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
> >>   ISA_EXT_DATA_ENTRY(zihintpause, PRIV_VERSION_1_10_0, 
> >> ext_zihintpause),
> >>   ISA_EXT_DATA_ENTRY(zihpm, PRIV_VERSION_1_12_0, ext_zihpm),
> >>   ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),
> >> +ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, ext_za64rs),
> >>   ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas),
> >>   ISA_EXT_DATA_ENTRY(zawrs, PRIV_VERSION_1_12_0, ext_zawrs),
> >>   ISA_EXT_DATA_ENTRY(zfa, PRIV_VERSION_1_12_0, ext_zfa),
> >> @@ -170,8 +175,12 @@ const RISCVIsaExtData isa_edata_arr[] = {
> >>   ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, ext_smepmp),
> >>   ISA_EXT_DATA_ENTRY(smstateen, PRIV_VERSION_1_12_0, ext_smstateen),
> >>   ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia),
> >> +ISA_EXT_DATA_ENTRY(ssccptr, PRIV_VERSION_1_11_0, ext_ssccptr),
> >>   ISA_EXT_DATA_ENTRY(sscofpmf, PRIV_VERSION_1_12_0, ext_sscofpmf),
> >> +ISA_EXT_DATA_ENTRY(sscounterenw, PRIV_VERSION_1_12_0, 
> >> ext_sscounterenw),
> >>   ISA_EXT_DATA_ENTRY(sstc, PRIV_VERSION_1_12_0, ext_sstc),
> >> +ISA_EXT_DATA_ENTRY(sstvala, PRIV_VERSION_1_12_0, ext_sstvala),
> >> +ISA_EXT_DATA_ENTRY(sstvecd, PRIV_VERSION_1_12_0, ext_sstvecd),
> >>   ISA_EXT_DATA_ENTRY(svade, PRIV_VERSION_1_11_0, ext_svade),
> >>   ISA_EXT_DATA_ENTRY(svadu, PRIV_VERSION_1_12_0, ext_svadu),
> >>   ISA_EXT_DATA_ENTRY(svinval, PRIV_VERSION_1_12_0, ext_svinval),
> >> @@ -1523,6 +1532,22 @@ const RISCVCPUMultiExtConfig 
> >> riscv_cpu_named_features[] = {
> >>   MULTI_EXT_CFG_BOOL("svade", ext_svade, true),
> >>   MULTI_EXT_CFG_BOOL("zic64b", ext_zic64b, true),
> >>
> >> +/*
> >> + * cache-related extensions that are always enabled
> >> + * since QEMU RISC-V does not have a cache model.
> >> + */
> >> +MULTI_EXT_CFG_BOOL("za64rs", ext_za64rs, true),
> >> +MULTI_EXT_CFG_BOOL("ziccif", ext_ziccif, true),
> >> +MULTI_EXT_CFG_BOOL("ziccrse", ext_ziccrse, true),
> >> +MULTI_EXT_CFG_BOOL("ziccamoa", ext_ziccamoa, true),
> >> +MULTI_EXT_CFG_BOOL("zicclsm", ext_zicclsm, true),
> >> +MULTI_EXT_CFG_BOOL("ssccptr", ext_ssccptr, true),
> >> +
> >> +/* Other named features that QEMU TCG always implements */
> >> +MULTI_EXT_CFG_BOOL("sstvecd", ext_sstvecd, true),
> >> +MULTI_EXT_CFG_BOOL("sstvala", ext_sstvala, true),
> >> +MULTI_EXT_CFG_BOOL("sscounterenw", ext_sscounterenw, true),
> >> +
> >>   DEFINE_PROP_END_OF_LIST(),
> >>   };
> >>
> >> @@ -2116,13 +2141,8 @@ static const PropertyInfo prop_marchid = {
> >>   };
> >>
> >>   /*
> >> - * RVA22U64 defines some 

Re: [PATCH 00/14] migration/multifd: Refactor ->send_prepare() and cleanups

2024-02-01 Thread Peter Xu
On Thu, Feb 01, 2024 at 06:46:35PM -0300, Fabiano Rosas wrote:
> Avihai Horon  writes:
> 
> > On 01/02/2024 7:47, Peter Xu wrote:
> >> External email: Use caution opening links or attachments
> >>
> >>
> >> On Wed, Jan 31, 2024 at 07:49:51PM -0300, Fabiano Rosas wrote:
> >>> pet...@redhat.com writes:
> >>>
>  From: Peter Xu 
> 
>  This patchset contains quite a few refactorings to current multifd:
> 
> - It picked up some patches from an old series of mine [0] (the last
>   patches were dropped, though; I did the cleanup slightly 
>  differently):
> 
>   I still managed to include one patch to split pending_job, but I
>   rewrote the patch here.
> 
> - It tries to cleanup multiple multifd paths here and there, the 
>  ultimate
>   goal is to redefine send_prepare() to be something like:
> 
> p->pages --->  send_prepare() -> IOVs
> 
>   So that there's no obvious change yet on multifd_ops besides 
>  redefined
>   interface for send_prepare().  We may want a separate OPs for file
>   later.
> 
>  For 2), one benefit is already presented by Fabiano in his other series 
>  [1]
>  on cleaning up zero copy, but this patchset addressed it quite 
>  differently,
>  and hopefully also more gradually.  The other benefit is for sure if we
>  have a more concrete API for send_prepare() and if we can reach an 
>  initial
>  consensus, then we can have the recent compression accelerators rebased 
>  on
>  top of this one.
> 
>  This also prepares for the case where the input can be extended to even 
>  not
>  any p->pages, but arbitrary data (like VFIO's potential use case in the
>  future?).  But that will also for later even if reasonable.
> 
>  Please have a look.  Thanks,
> 
>  [0] https://lore.kernel.org/r/20231022201211.452861-1-pet...@redhat.com
>  [1] 
>  https://lore.kernel.org/qemu-devel/20240126221943.26628-1-faro...@suse.de
> 
>  Peter Xu (14):
> migration/multifd: Drop stale comment for multifd zero copy
> migration/multifd: multifd_send_kick_main()
> migration/multifd: Drop MultiFDSendParams.quit, cleanup error paths
> migration/multifd: Postpone reset of MultiFDPages_t
> migration/multifd: Drop MultiFDSendParams.normal[] array
> migration/multifd: Separate SYNC request with normal jobs
> migration/multifd: Simplify locking in sender thread
> migration/multifd: Drop pages->num check in sender thread
> migration/multifd: Rename p->num_packets and clean it up
> migration/multifd: Move total_normal_pages accounting
> migration/multifd: Move trace_multifd_send|recv()
> migration/multifd: multifd_send_prepare_header()
> migration/multifd: Move header prepare/fill into send_prepare()
> migration/multifd: Forbid spurious wakeups
> 
>    migration/multifd.h  |  34 +++--
>    migration/multifd-zlib.c |  11 +-
>    migration/multifd-zstd.c |  11 +-
>    migration/multifd.c  | 291 +++
>    4 files changed, 182 insertions(+), 165 deletions(-)
> >>> This series didn't survive my  iterations test on the opensuse
> >>> machine.
> >>>
> >>> # Running /x86_64/migration/multifd/tcp/tls/x509/reject-anon-client
> >>> ...
> >>> kill_qemu() detected QEMU death from signal 11 (Segmentation fault) (core 
> >>> dumped)
> >>>
> >>>
> >>> #0  0x5575dda06399 in qemu_mutex_lock_impl (mutex=0x18, 
> >>> file=0x5575ddce9cc3 "../util/qemu-thread-posix.c", line=275) at 
> >>> ../util/qemu-thread-posix.c:92
> >>> #1  0x5575dda06a94 in qemu_sem_post (sem=0x18) at 
> >>> ../util/qemu-thread-posix.c:275
> >>> #2  0x5575dd56a512 in multifd_send_thread (opaque=0x5575df054ef8) at 
> >>> ../migration/multifd.c:720
> >>> #3  0x5575dda0709b in qemu_thread_start (args=0x7fd404001d50) at 
> >>> ../util/qemu-thread-posix.c:541
> >>> #4  0x7fd45e8a26ea in start_thread (arg=0x7fd3faffd700) at 
> >>> pthread_create.c:477
> >>> #5  0x7fd45cd2150f in clone () at 
> >>> ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
> >>>
> >>> The multifd thread is posting channels_ready with an already freed
> >>> multifd_send_state.
> >>>
> >>> This is the bug Avihai has hit. We're going into multifd_save_cleanup()
> >>> so early that multifd_new_send_channel_async() hasn't even had the
> >>> chance to set p->running. So it misses the join and frees everything up
> >>> while a second multifd thread is just starting.
> >> Thanks for doing that.
> >>
> >> Would this series makes that bug easier to happen?
> >
> > I think so.
> > Patch #3 added an extra multifd_send_should_exit() check in 
> > multifd_send_sync_main(), so now it can exit early if the first channel 
> > fails.
> > Plus, now migration state is set to FAILED early 

Re: [PATCH] RISC-V: Report the QEMU vendor/arch IDs on virtual CPUs

2024-02-01 Thread Alistair Francis
On Thu, Feb 1, 2024 at 5:33 AM Palmer Dabbelt  wrote:
>
> Right now we just report 0 for marchid/mvendorid in QEMU.  That's legal,
> but it's tricky for users that want to check if they're running on QEMU
> to do so.  This sets marchid to 42, which I've proposed as the QEMU
> architecture ID (mvendorid remains 0, just explicitly set, as that's how
> the ISA handles open source implementations).
>
> Link: https://github.com/riscv/riscv-isa-manual/pull/1213

This has been accepted now :)

> Signed-off-by: Palmer Dabbelt 
> ---
>  target/riscv/cpu.c  | 16 
>  target/riscv/cpu_vendorid.h |  3 +++
>  2 files changed, 19 insertions(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 8cbfc7e781..1aef186f87 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -415,6 +415,9 @@ static void riscv_any_cpu_init(Object *obj)
>  cpu->cfg.ext_zicsr = true;
>  cpu->cfg.mmu = true;
>  cpu->cfg.pmp = true;
> +
> +cpu->cfg.mvendorid = QEMU_MVENDORID;
> +cpu->cfg.marchid = QEMU_MARCHID;
>  }
>
>  static void riscv_max_cpu_init(Object *obj)
> @@ -432,6 +435,8 @@ static void riscv_max_cpu_init(Object *obj)
>  set_satp_mode_max_supported(RISCV_CPU(obj), mlx == MXL_RV32 ?
>  VM_1_10_SV32 : VM_1_10_SV57);
>  #endif
> +cpu->cfg.mvendorid = QEMU_MVENDORID;
> +cpu->cfg.marchid = QEMU_MARCHID;
>  }
>
>  #if defined(TARGET_RISCV64)
> @@ -445,6 +450,8 @@ static void rv64_base_cpu_init(Object *obj)
>  #ifndef CONFIG_USER_ONLY
>  set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
>  #endif
> +cpu->cfg.mvendorid = QEMU_MVENDORID;
> +cpu->cfg.marchid = QEMU_MARCHID;
>  }
>
>  static void rv64_sifive_u_cpu_init(Object *obj)
> @@ -569,6 +576,8 @@ static void rv128_base_cpu_init(Object *obj)
>  #ifndef CONFIG_USER_ONLY
>  set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
>  #endif
> +cpu->cfg.mvendorid = QEMU_MVENDORID;
> +cpu->cfg.marchid = QEMU_MARCHID;
>  }
>
>  static void rv64i_bare_cpu_init(Object *obj)
> @@ -591,6 +600,8 @@ static void rv64i_bare_cpu_init(Object *obj)
>  #ifndef CONFIG_USER_ONLY
>  set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV64);
>  #endif
> +cpu->cfg.mvendorid = QEMU_MVENDORID;
> +cpu->cfg.marchid = QEMU_MARCHID;
>  }
>  #else
>  static void rv32_base_cpu_init(Object *obj)
> @@ -603,6 +614,8 @@ static void rv32_base_cpu_init(Object *obj)
>  #ifndef CONFIG_USER_ONLY
>  set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV32);
>  #endif
> +cpu->cfg.mvendorid = QEMU_MVENDORID;
> +cpu->cfg.marchid = QEMU_MARCHID;
>  }
>
>  static void rv32_sifive_u_cpu_init(Object *obj)
> @@ -672,6 +685,9 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj)
>  cpu->cfg.ext_zifencei = true;
>  cpu->cfg.ext_zicsr = true;
>  cpu->cfg.pmp = true;
> +
> +cpu->cfg.mvendorid = QEMU_MVENDORID;
> +cpu->cfg.marchid = QEMU_MARCHID;
>  }
>  #endif
>
> diff --git a/target/riscv/cpu_vendorid.h b/target/riscv/cpu_vendorid.h
> index 96b6b9c2cb..486832cd53 100644
> --- a/target/riscv/cpu_vendorid.h
> +++ b/target/riscv/cpu_vendorid.h
> @@ -7,4 +7,7 @@
>  #define VEYRON_V1_MIMPID0x111
>  #define VEYRON_V1_MVENDORID 0x61f
>
> +#define QEMU_VIRT_MVENDORID 0
> +#define QEMU_VIRT_MARCHID   42

These aren't used. I think you meant to reference this from the CPU
init functions

Alistair

> +
>  #endif /*  TARGET_RISCV_CPU_VENDORID_H */
> --
> 2.43.0
>
>



Re: [PATCH v6 0/6] Pointer Masking update for Zjpm v0.8

2024-02-01 Thread Alistair Francis
On Fri, Feb 2, 2024 at 1:11 AM Alexey Baturo  wrote:
>
> From: Alexey Baturo 
>
> Hi,
>
> This patch series is rebased on 
> https://github.com/alistair23/qemu/tree/riscv-to-apply.next

Thanks!

Applied to riscv-to-apply.next

Alistair

>
> Thanks
>
> [v5]:
> This patch series targets Zjpm v0.8 extension.
> The spec itself could be found here: 
> https://github.com/riscv/riscv-j-extension/blob/8088461d8d66a7676872b61c908cbeb7cf5c5d1d/zjpm-spec.pdf
> This patch series is updated after the suggested comments:
> - add "x-" to the extension names to indicate experimental
>
> [v4]:
> Patch series updated after the suggested comments:
> - removed J-letter extension as it's unused
> - renamed and fixed function to detect if address should be sign-extended
> - zeroed unused context variables and moved computation logic to another patch
> - bumped pointer masking version_id and minimum_version_id by 1
>
> [v3]:
> There patches are updated after Richard's comments:
> - moved new tb flags to the end
> - used tcg_gen_(s)extract to get the final address
> - properly handle CONFIG_USER_ONLY
>
> [v2]:
> As per Richard's suggestion I made pmm field part of tb_flags.
> It allowed to get rid of global variable to store pmlen.
> Also it allowed to simplify all the machinery around it.
>
> [v1]:
> It looks like Zjpm v0.8 is almost frozen and we don't expect it change 
> drastically anymore.
> Compared to the original implementation with explicit base and mask CSRs, we 
> now only have
> several fixed options for number of masked bits which are set using existing 
> CSRs.
> The changes have been tested with handwritten assembly tests and LLVM HWASAN
> test suite.
>
> Alexey Baturo (6):
>   target/riscv: Remove obsolete pointer masking extension code.
>   target/riscv: Add new CSR fields for S{sn,mn,m}pm extensions as part
> of Zjpm v0.8
>   target/riscv: Add helper functions to calculate current number of
> masked bits for pointer masking
>   target/riscv: Add pointer masking tb flags
>   target/riscv: Update address modify functions to take into account
> pointer masking
>   target/riscv: Enable updates for pointer masking variables and thus
> enable pointer masking extension
>
>  target/riscv/cpu.c   | 22 
>  target/riscv/cpu.h   | 47 -
>  target/riscv/cpu_bits.h  | 90 ++---
>  target/riscv/cpu_cfg.h   |  3 ++
>  target/riscv/cpu_helper.c| 97 
>  target/riscv/csr.c   | 41 ---
>  target/riscv/machine.c   | 22 +++-
>  target/riscv/pmp.c   | 13 +++--
>  target/riscv/pmp.h   | 11 ++--
>  target/riscv/tcg/tcg-cpu.c   |  5 +-
>  target/riscv/translate.c | 46 +++--
>  target/riscv/vector_helper.c | 15 +-
>  12 files changed, 160 insertions(+), 252 deletions(-)
>
> --
> 2.34.1
>
>



Re: [PATCH] tcg/loongarch64: Set vector registers call clobbered

2024-02-01 Thread gaosong

在 2024/2/2 上午7:34, Richard Henderson 写道:

Because there are more call clobbered registers than
call saved registers, we begin with all registers as
call clobbered and then reset those that are saved.

This was missed when we introduced the LSX support.

Cc: qemu-sta...@nongnu.org
Fixes: 16288ded944 ("tcg/loongarch64: Lower basic tcg vec ops to LSX")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2136
Signed-off-by: Richard Henderson 
---
  tcg/loongarch64/tcg-target.c.inc | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

Thank you !

Reviewed-by: Song Gao 

Thanks.
Song Gao

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index bab0a173a3..dcf0205458 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -2327,7 +2327,7 @@ static void tcg_target_init(TCGContext *s)
  tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS;
  tcg_target_available_regs[TCG_TYPE_I64] = ALL_GENERAL_REGS;
  
-tcg_target_call_clobber_regs = ALL_GENERAL_REGS;

+tcg_target_call_clobber_regs = ALL_GENERAL_REGS | ALL_VECTOR_REGS;
  tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0);
  tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1);
  tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2);





Re: [PATCH 04/14] migration/multifd: Postpone reset of MultiFDPages_t

2024-02-01 Thread Peter Xu
On Fri, Feb 02, 2024 at 08:28:47AM +0800, Peter Xu wrote:
> > Pages allocated is nonsense. See if you agree with its removal:
> > https://gitlab.com/farosas/qemu/-/commit/7cfff1a3e31b271e901a6c08d8b5d8c01b680e4d
> > 
> > ---
> > From 7cfff1a3e31b271e901a6c08d8b5d8c01b680e4d Mon Sep 17 00:00:00 2001
> > From: Fabiano Rosas 
> > Date: Tue, 24 Oct 2023 19:03:41 -0300
> > Subject: [PATCH] multifd: Remove MultiFDPage_t:allocated
> > 
> > When dealing with RAM, having a field called 'allocated' is
> > confusing. This field simply holds number of pages that fit in a
> > multifd packet.
> > 
> > Since it is a constant dependent on the size of the multifd packet,
> > remove it and instead use the page size and MULTIFD_PACKET_SIZE
> > directly.
> > 
> > This is another step in the direction of having no mentions of 'page'
> > in the multifd send thread.
> > 
> > Signed-off-by: Fabiano Rosas 
> > ---
> >  migration/multifd.c | 6 ++
> >  migration/multifd.h | 2 --
> >  2 files changed, 2 insertions(+), 6 deletions(-)
> > 
> > diff --git a/migration/multifd.c b/migration/multifd.c
> > index bdefce27706..83fb2caab04 100644
> > --- a/migration/multifd.c
> > +++ b/migration/multifd.c
> > @@ -241,7 +241,6 @@ static MultiFDPages_t *multifd_pages_init(uint32_t n)
> >  {
> >  MultiFDPages_t *pages = g_new0(MultiFDPages_t, 1);
> >  
> > -pages->allocated = n;
> >  pages->offset = g_new0(ram_addr_t, n);
> >  pages->page_size = qemu_target_page_size();
> >  
> > @@ -251,7 +250,6 @@ static MultiFDPages_t *multifd_pages_init(uint32_t n)
> >  static void multifd_pages_clear(MultiFDPages_t *pages)
> >  {
> >  pages->num = 0;
> > -pages->allocated = 0;
> >  pages->block = NULL;
> >  g_free(pages->offset);
> >  pages->offset = NULL;
> > @@ -264,7 +262,7 @@ static void multifd_send_fill_packet(MultiFDSendParams 
> > *p)
> >  int i;
> >  
> >  packet->flags = cpu_to_be32(p->flags);
> > -packet->pages_alloc = cpu_to_be32(p->pages->allocated);
> > +packet->pages_alloc = cpu_to_be32(MULTIFD_PACKET_SIZE / 
> > p->pages->page_size);
> >  packet->normal_pages = cpu_to_be32(p->pages->num);
> >  packet->next_packet_size = cpu_to_be32(p->next_packet_size);
> >  packet->packet_num = cpu_to_be64(p->packet_num);
> > @@ -451,7 +449,7 @@ int multifd_queue_page(RAMBlock *block, ram_addr_t 
> > offset)
> >  pages->offset[pages->num] = offset;
> >  pages->num++;
> >  
> > -if (pages->num < pages->allocated) {
> > +if (pages->num * pages->page_size < MULTIFD_PACKET_SIZE) {
> >  return 1;
> >  }
> >  } else {
> > diff --git a/migration/multifd.h b/migration/multifd.h
> > index 655f8d5eeb4..d1342296d63 100644
> > --- a/migration/multifd.h
> > +++ b/migration/multifd.h
> > @@ -56,8 +56,6 @@ typedef struct {
> >  typedef struct {
> >  /* number of used pages */
> >  uint32_t num;
> > -/* number of allocated pages */
> > -uint32_t allocated;
> >  /* guest page size */
> >  uint32_t page_size;
> >  /* offset of each page */
> > -- 
> 
> I agree.
> 
> Even if we would like to add a parameter to setup the allcated size (I
> remember one of the accelerator series has it), it'll still be a global
> variable rather than per-pages thing.
> 
> I can cherry pick this and post together; will need a rebase but I can do
> that.

I see a slight step back here when rebase, since we'll calculate n_pages
every time to enqueue the page:

static inline bool multifd_queue_full(MultiFDPages_t *pages)
{
return pages->num == (MULTIFD_PACKET_SIZE / pages->page_size);
}

The "allocated" is still good to cache the value.  Fabiano, would it make
sense we still use a global var (perhaps in multifd_save_state?) to cache
this?

I'll leave this alone as of now I think, but again I agree we should have
something similar.

-- 
Peter Xu




Re: [PATCH 04/14] migration/multifd: Postpone reset of MultiFDPages_t

2024-02-01 Thread Peter Xu
On Thu, Feb 01, 2024 at 12:21:27PM -0300, Fabiano Rosas wrote:
> Peter Xu  writes:
> 
> > On Wed, Jan 31, 2024 at 12:27:51PM -0300, Fabiano Rosas wrote:
> >> > +/* Reset a MultiFDPages_t* object for the next use */
> >> > +static void multifd_pages_reset(MultiFDPages_t *pages)
> >> > +{
> >> > +/*
> >> > + * We don't need to touch offset[] array, because it will be
> >> > + * overwritten later when reused.
> >> > + */
> >> > +pages->num = 0;
> >> > +pages->block = NULL;
> >> 
> >> Having to do this at all is a huge overloading of this field. This not
> >> only resets it, but it also communicates to multifd_queue_page() that
> >> the previous payload has been sent. Otherwise, multifd_queue_page()
> >> wouldn't know whether the previous call to multifd_queue_page() has
> >> called multifd_send_pages() or if it has exited early. So this basically
> >> means "the block that was previously here has been sent".
> >> 
> >> That's why we need the changed=true logic. A
> >> multifd_send_state->pages->block still has a few pages left to send, but
> >> because it's less than pages->allocated, it skips
> >> multifd_send_pages(). The next call to multifd_queue_page() already has
> >> the next ramblock. So we set changed=true, call multifd_send_pages() to
> >> send the remaining pages of that block and recurse into
> >> multifd_queue_page() once more to send the new block.
> >
> > I agree, the queue page routines are not easy to follow as well.
> >
> > How do you like a rewrite of the queue logic, like this?
> >
> > =
> > bool multifd_queue_page(RAMBlock *block, ram_addr_t offset)
> > {
> > MultiFDPages_t *pages;
> >
> > retry:
> > pages = multifd_send_state->pages;
> >
> > /* If the queue is empty, we can already enqueue now */
> > if (multifd_queue_empty(pages)) {
> > pages->block = block;
> > multifd_enqueue(pages, offset);
> > return true;
> > }
> >
> > /*
> >  * Not empty, meanwhile we need a flush.  It can because of either:
> >  *
> >  * (1) The page is not on the same ramblock of previous ones, or,
> >  * (2) The queue is full.
> >  *
> >  * After flush, always retry.
> >  */
> > if (pages->block != block || multifd_queue_full(pages)) {
> > if (!multifd_send_pages()) {
> > return false;
> > }
> > goto retry;
> > }
> >
> > /* Not empty, and we still have space, do it! */
> > multifd_enqueue(pages, offset);
> > return true;
> > }
> > =
> >
> > Would this be clearer?  With above, we can drop the ->ramblock reset,
> > afaict.
> >
> > I attached three patches if you agree it's better, then I'll include them
> > in v2.
> 
> Yes, let's do it.
> 
> >
> > -- 
> > Peter Xu
> > From c5dc2052794efd6da6a1e6f4b49f25d5b32879f7 Mon Sep 17 00:00:00 2001
> > From: Peter Xu 
> > Date: Thu, 1 Feb 2024 17:50:21 +0800
> > Subject: [PATCH 1/3] migration/multifd: Change retval of 
> > multifd_queue_page()
> >
> > Using int is an overkill when there're only two options.  Change it to a
> > boolean.
> >
> > Signed-off-by: Peter Xu 
> > ---
> >  migration/multifd.h | 2 +-
> >  migration/multifd.c | 9 +
> >  migration/ram.c | 2 +-
> >  3 files changed, 7 insertions(+), 6 deletions(-)
> >
> > diff --git a/migration/multifd.h b/migration/multifd.h
> > index 34a2ecb9f4..a320c53a6f 100644
> > --- a/migration/multifd.h
> > +++ b/migration/multifd.h
> > @@ -22,7 +22,7 @@ bool multifd_recv_all_channels_created(void);
> >  void multifd_recv_new_channel(QIOChannel *ioc, Error **errp);
> >  void multifd_recv_sync_main(void);
> >  int multifd_send_sync_main(void);
> > -int multifd_queue_page(RAMBlock *block, ram_addr_t offset);
> > +bool multifd_queue_page(RAMBlock *block, ram_addr_t offset);
> >  
> >  /* Multifd Compression flags */
> >  #define MULTIFD_FLAG_SYNC (1 << 0)
> > diff --git a/migration/multifd.c b/migration/multifd.c
> > index 91be6d2fc4..d0a3b4e062 100644
> > --- a/migration/multifd.c
> > +++ b/migration/multifd.c
> > @@ -505,7 +505,8 @@ static int multifd_send_pages(void)
> >  return 1;
> >  }
> >  
> > -int multifd_queue_page(RAMBlock *block, ram_addr_t offset)
> > +/* Returns true if enqueue successful, false otherwise */
> > +bool multifd_queue_page(RAMBlock *block, ram_addr_t offset)
> >  {
> >  MultiFDPages_t *pages = multifd_send_state->pages;
> >  bool changed = false;
> > @@ -519,21 +520,21 @@ int multifd_queue_page(RAMBlock *block, ram_addr_t 
> > offset)
> >  pages->num++;
> >  
> >  if (pages->num < pages->allocated) {
> > -return 1;
> > +return true;
> >  }
> >  } else {
> >  changed = true;
> >  }
> >  
> >  if (multifd_send_pages() < 0) {
> > -return -1;
> > +return false;
> >  }
> >  
> >  if (changed) {
> >  return multifd_queue_page(block, offset);
> >  }
> >  
> > -return 1;
> > +return true;
> >  }
> >  
> >  /* Multifd 

Re: [PATCH 03/14] migration/multifd: Drop MultiFDSendParams.quit, cleanup error paths

2024-02-01 Thread Peter Xu
On Thu, Feb 01, 2024 at 10:30:19AM -0300, Fabiano Rosas wrote:
> > @@ -586,7 +595,7 @@ void multifd_save_cleanup(void)
> >  if (!migrate_multifd()) {
> >  return;
> >  }
> > -multifd_send_terminate_threads(NULL);
> > +multifd_send_terminate_threads();
> >  for (i = 0; i < migrate_multifd_channels(); i++) {
> >  MultiFDSendParams *p = _send_state->params[i];
> 
> We could then move the qemu_thread_join loop into
> multifd_send_terminate_threads().

Sure, I can do that.

When at it, I found that maybe I should cleanup more things in this
function to provide small helpers.

I think I'll keep this one alone, while I'll append one more patch to do
it.

> 
> (and fix all the bugs we have so that we only progress past
> multifd_send_terminate_threads() once all threads have exited and no
> more thread is going to spawn)

I guess this will still take some effort.  I hope that we can avoid some
threads from being created at all for either async/tls purpose.

For now when I'm doing the cleanup I'll add a TODO too for this.

I'll repost a new version for the whole set today.

-- 
Peter Xu




Re: [PATCH] hw/pci: migration: Skip config space check for vendor specific capability during restore/load

2024-02-01 Thread Alex Williamson
On Thu, 1 Feb 2024 13:10:48 -0500
"Michael S. Tsirkin"  wrote:

> On Thu, Feb 01, 2024 at 11:08:58PM +0530, Vinayak Kale wrote:
> > 
> > On 31/01/24 11:08 pm, Alex Williamson wrote:  
> > > 
> > > On Wed, 31 Jan 2024 15:22:59 +0530
> > > Vinayak Kale  wrote:
> > >   
> > > > On 31/01/24 12:28 am, Alex Williamson wrote:  
> > > > > 
> > > > > On Tue, 30 Jan 2024 23:32:26 +0530
> > > > > Vinayak Kale  wrote:
> > > > >   
> > > > > > Missed adding Michael, Marcel, Alex and Avihai earlier, apologies.
> > > > > > 
> > > > > > Regards,
> > > > > > Vinayak
> > > > > > 
> > > > > > On 30/01/24 3:26 pm, Vinayak Kale wrote:  
> > > > > > > In case of migration, during restore operation, qemu checks the 
> > > > > > > config space of the pci device with the config space
> > > > > > > in the migration stream captured during save operation. In case 
> > > > > > > of config space data mismatch, restore operation is failed.
> > > > > > > 
> > > > > > > config space check is done in function get_pci_config_device(). 
> > > > > > > By default VSC (vendor-specific-capability) in config space is 
> > > > > > > checked.
> > > > > > > 
> > > > > > > Ideally qemu should not check VSC during restore/load. This patch 
> > > > > > > skips the check by not setting pdev->cmask[] for VSC offsets in 
> > > > > > > pci_add_capability().
> > > > > > > If cmask[] is not set for an offset, then qemu skips config space 
> > > > > > > check for that offset.
> > > > > > > 
> > > > > > > Signed-off-by: Vinayak Kale 
> > > > > > > ---
> > > > > > > hw/pci/pci.c | 7 +--
> > > > > > > 1 file changed, 5 insertions(+), 2 deletions(-)
> > > > > > > 
> > > > > > > diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> > > > > > > index 76080af580..32429109df 100644
> > > > > > > --- a/hw/pci/pci.c
> > > > > > > +++ b/hw/pci/pci.c
> > > > > > > @@ -2485,8 +2485,11 @@ int pci_add_capability(PCIDevice *pdev, 
> > > > > > > uint8_t cap_id,
> > > > > > > memset(pdev->used + offset, 0xFF, QEMU_ALIGN_UP(size, 4));
> > > > > > > /* Make capability read-only by default */
> > > > > > > memset(pdev->wmask + offset, 0, size);
> > > > > > > -/* Check capability by default */
> > > > > > > -memset(pdev->cmask + offset, 0xFF, size);
> > > > > > > +
> > > > > > > +if (cap_id != PCI_CAP_ID_VNDR) {
> > > > > > > +/* Check non-vendor specific capability by default */
> > > > > > > +memset(pdev->cmask + offset, 0xFF, size);
> > > > > > > +}
> > > > > > > return offset;
> > > > > > > }
> > > > > > >   
> > > > > >   
> > > > > 
> > > > > If there is a possibility that the data within the vendor specific cap
> > > > > can be consumed by the driver or diagnostic tools, then it's part of
> > > > > the device ABI and should be consistent across migration.  A mismatch
> > > > > can certainly cause a migration failure, but why shouldn't it?  
> > > > 
> > > > Sure, the device ABI should be consistent across migration. In case of
> > > > VSC, it should represent same format on source and destination. But
> > > > shouldn't VSC content check or its interpretation be left to vendor
> > > > driver instead of qemu?  
> > > 
> > > By "vendor driver" here, are you suggesting that QEMU device models (ex.
> > > hw/net/{e1000*,igb*,rtl8139*}) should perform that validation?  If so,
> > > where's the patch that introduces any sort of validation hooks for
> > > vendors to provide?  Where is this validation going to happen in the
> > > case of a migratable vfio-pci variant devices?  Nothing about this
> > > patch suggests that it's deferring responsibility to some other code
> > > entity, it only indicates "checking this breaks, let's not do it".
> > > 
> > > It's possible that the device you care about only reports volatile
> > > diagnostic information through the vendor specific capability, but
> > > another device might use it to report information relative to the
> > > internal hardware configuration.  Without knowing what the vendor
> > > specific capability contains, QEMU needs to take the most conservative
> > > approach by default.  Thanks,  
> > 
> > PCI/PCIe spec doesn’t define ABI for VSC/VSEC contents. Any other code
> > entity except vendor driver should ignore VSC contents. QEMU’s expectation
> > of VSC contents to be equal on source and destination seems incorrect given
> > that QEMU has no control over ABI for VSC contents.
> >   
> > > 
> > > Alex
> > >   
> 
> I don't get why this matters though. This is no different from any other
> device specific register. If a register is visible to guest it generally
> should not change across migration. If you are migrating a VFIO device and
> you are making a vsc visible to guest then your migration routine must
> make sure to migrate the contents of vsc.
> 
> Maybe there's a good reason to have a register which actually does
> change. Then, please document the actual reason. When you say:
> 
>Ideally qemu should not check VSC during restore/load.
> 
> 

Re: [PULL 06/15] tests/qtest/migration: Don't use -cpu max for aarch64

2024-02-01 Thread Peter Xu
Fabiano, I think you forgot to reply-to-all.. adding back the list and
people in the loop.

On Thu, Feb 01, 2024 at 10:12:44AM -0300, Fabiano Rosas wrote:
> Peter Xu  writes:
> 
> > On Wed, Jan 31, 2024 at 10:09:16AM -0300, Fabiano Rosas wrote:
> >> If we ask for KVM and it falls back to TCG, we need a cpu that supports
> >> both. We don't have that. I've put some command-line combinations at the
> >> end of the email[1], take a look.
> >
> > Thanks a lot, Fabiano.  I think I have a better picture now.
> >
> > Now the question is whether it'll be worthwhile we (migration) explicitly
> > provide code to workaround such issue in qtest, or we wait for ARM side
> > until we have a processor that can be both stable and support KVM+TCG.
> >
> > I actually personally prefer to wait - it's not too bad after all, because
> > it only affects the new "n-1" migration test.  Most of the migration
> > functionality will still be covered there in CI for ARM.
> 
> That's fine with me. We just need to do something about the arm CI job
> which is currently disabled waiting for a fix. We could remove it or add
> some words somewhere explaining the situation. I can do that once we
> reach an agreement here.

Yes.  IMHO we can keep the test (with SKIPPED=1) but amend the message,
which will start to state inaccurately:

# This job is disabled until we release 9.0. The existing
# migration-test in 8.2 is broken on aarch64. The fix was already
# commited, but it will only take effect once 9.0 is out.

IMHO then it won't mean 9.0 will have it fixed, but we'll simply wait for a
cpu model that is ready for both kvm+tcg, then we replace "max".

For gic_version, I knew 3 was there for quite some time so maybe we can
start from that?  Or we need suggestions from ARM people.

-- 
Peter Xu




[PATCH] tcg/loongarch64: Set vector registers call clobbered

2024-02-01 Thread Richard Henderson
Because there are more call clobbered registers than
call saved registers, we begin with all registers as
call clobbered and then reset those that are saved.

This was missed when we introduced the LSX support.

Cc: qemu-sta...@nongnu.org
Fixes: 16288ded944 ("tcg/loongarch64: Lower basic tcg vec ops to LSX")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2136
Signed-off-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index bab0a173a3..dcf0205458 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -2327,7 +2327,7 @@ static void tcg_target_init(TCGContext *s)
 tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS;
 tcg_target_available_regs[TCG_TYPE_I64] = ALL_GENERAL_REGS;
 
-tcg_target_call_clobber_regs = ALL_GENERAL_REGS;
+tcg_target_call_clobber_regs = ALL_GENERAL_REGS | ALL_VECTOR_REGS;
 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0);
 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1);
 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2);
-- 
2.34.1




Re: [External] Re: [PATCH v3 03/20] multifd: Zero pages transmission

2024-02-01 Thread Hao Xiang
On Wed, Jan 31, 2024 at 9:22 PM Peter Xu  wrote:
>
> On Thu, Jan 04, 2024 at 12:44:35AM +, Hao Xiang wrote:
> > From: Juan Quintela 
> >
> > This implements the zero page dection and handling.
> >
> > Signed-off-by: Juan Quintela 
> > ---
> >  migration/multifd.c | 41 +++--
> >  migration/multifd.h |  5 +
> >  2 files changed, 44 insertions(+), 2 deletions(-)
> >
> > diff --git a/migration/multifd.c b/migration/multifd.c
> > index 5a1f50c7e8..756673029d 100644
> > --- a/migration/multifd.c
> > +++ b/migration/multifd.c
> > @@ -11,6 +11,7 @@
> >   */
> >
> >  #include "qemu/osdep.h"
> > +#include "qemu/cutils.h"
> >  #include "qemu/rcu.h"
> >  #include "exec/target_page.h"
> >  #include "sysemu/sysemu.h"
> > @@ -279,6 +280,12 @@ static void multifd_send_fill_packet(MultiFDSendParams 
> > *p)
> >
> >  packet->offset[i] = cpu_to_be64(temp);
> >  }
> > +for (i = 0; i < p->zero_num; i++) {
> > +/* there are architectures where ram_addr_t is 32 bit */
> > +uint64_t temp = p->zero[i];
> > +
> > +packet->offset[p->normal_num + i] = cpu_to_be64(temp);
> > +}
> >  }
>
> I think changes like this needs to be moved into the previous patch.  I got
> quite confused when reading previous one and only understood what happens
> until now.  Fabiano, if you're going to pick these ones out and post
> separately, please also consider.  Perhaps squashing them together?
>

Discussed with Fabiano on a separate thread here
https://lore.kernel.org/all/CAAYibXi=WB5wfvLFM0b=d9ojf66lb7ftgonzzz-tvk4rbbx...@mail.gmail.com/

I am moving the original multifd zero page checking changes into a
seperate patchset. There is some necessary refactoring work on the top
of the original series. I will send that out this week.
> --
> Peter Xu
>



Re: [External] Re: [PATCH v3 15/20] migration/multifd: Add test hook to set normal page ratio.

2024-02-01 Thread Hao Xiang
On Wed, Jan 31, 2024 at 9:24 PM Peter Xu  wrote:
>
> On Thu, Jan 04, 2024 at 12:44:47AM +, Hao Xiang wrote:
> > +# @multifd-normal-page-ratio: Test hook setting the normal page ratio.
> > +# (Since 8.2)
>
> Please remember to touch all of them to 9.0 when repost, thanks.
>

Will do.

> --
> Peter Xu
>



[PATCH v3 07/20] qapi/schema: adjust type narrowing for mypy's benefit

2024-02-01 Thread John Snow
We already take care to perform some type narrowing for arg_type and
ret_type, but not in a way where mypy can utilize the result once we add
type hints, e.g.:

qapi/schema.py:833: error: Incompatible types in assignment (expression
has type "QAPISchemaType", variable has type
"Optional[QAPISchemaObjectType]") [assignment]

qapi/schema.py:893: error: Incompatible types in assignment (expression
has type "QAPISchemaType", variable has type
"Optional[QAPISchemaObjectType]") [assignment]

A simple change to use a temporary variable helps the medicine go down.

Signed-off-by: John Snow 
---
 scripts/qapi/schema.py | 16 +---
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index 8abcd4a86cb..043ee7556e6 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -851,13 +851,14 @@ def __init__(self, name, info, doc, ifcond, features,
 def check(self, schema):
 super().check(schema)
 if self._arg_type_name:
-self.arg_type = schema.resolve_type(
+arg_type = schema.resolve_type(
 self._arg_type_name, self.info, "command's 'data'")
-if not isinstance(self.arg_type, QAPISchemaObjectType):
+if not isinstance(arg_type, QAPISchemaObjectType):
 raise QAPISemError(
 self.info,
 "command's 'data' cannot take %s"
-% self.arg_type.describe())
+% arg_type.describe())
+self.arg_type = arg_type
 if self.arg_type.variants and not self.boxed:
 raise QAPISemError(
 self.info,
@@ -874,8 +875,8 @@ def check(self, schema):
 if self.name not in self.info.pragma.command_returns_exceptions:
 typ = self.ret_type
 if isinstance(typ, QAPISchemaArrayType):
-typ = self.ret_type.element_type
 assert typ
+typ = typ.element_type
 if not isinstance(typ, QAPISchemaObjectType):
 raise QAPISemError(
 self.info,
@@ -911,13 +912,14 @@ def __init__(self, name, info, doc, ifcond, features, 
arg_type, boxed):
 def check(self, schema):
 super().check(schema)
 if self._arg_type_name:
-self.arg_type = schema.resolve_type(
+typ = schema.resolve_type(
 self._arg_type_name, self.info, "event's 'data'")
-if not isinstance(self.arg_type, QAPISchemaObjectType):
+if not isinstance(typ, QAPISchemaObjectType):
 raise QAPISemError(
 self.info,
 "event's 'data' cannot take %s"
-% self.arg_type.describe())
+% typ.describe())
+self.arg_type = typ
 if self.arg_type.variants and not self.boxed:
 raise QAPISemError(
 self.info,
-- 
2.43.0




[PATCH v3 14/20] qapi/schema: Don't initialize "members" with `None`

2024-02-01 Thread John Snow
Declare, but don't initialize the "members" field with type
List[QAPISchemaObjectTypeMember].

This simplifies the typing from what would otherwise be
Optional[List[T]] to merely List[T]. This removes the need to add
assertions to several callsites that this value is not None - which it
never will be after the delayed initialization in check() anyway.

The type declaration without initialization trick will cause accidental
uses of this field prior to full initialization to raise an
AttributeError.

(Note that it is valid to have an empty members list, see the internal
q_empty object as an example. For this reason, we cannot use the empty
list as a replacement test for full initialization and instead rely on
the _checked/_checking fields.)

Signed-off-by: John Snow 
---
 scripts/qapi/schema.py | 13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index a459016e148..947e7efb1a8 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -20,7 +20,7 @@
 from collections import OrderedDict
 import os
 import re
-from typing import List, Optional
+from typing import List, Optional, cast
 
 from .common import (
 POINTER_SUFFIX,
@@ -457,7 +457,7 @@ def __init__(self, name, info, doc, ifcond, features,
 self.base = None
 self.local_members = local_members
 self.variants = variants
-self.members = None
+self.members: List[QAPISchemaObjectTypeMember]
 self._checking = False
 
 def check(self, schema):
@@ -474,7 +474,7 @@ def check(self, schema):
 
 self._checking = True
 super().check(schema)
-assert self._checked and self.members is None
+assert self._checked
 
 seen = OrderedDict()
 if self._base_name:
@@ -491,7 +491,10 @@ def check(self, schema):
 for m in self.local_members:
 m.check(schema)
 m.check_clash(self.info, seen)
-members = seen.values()
+
+# check_clash is abstract, but local_members is asserted to be
+# List[QAPISchemaObjectTypeMember]. Cast to the narrower type.
+members = cast(List[QAPISchemaObjectTypeMember], list(seen.values()))
 
 if self.variants:
 self.variants.check(schema, seen)
@@ -524,11 +527,9 @@ def is_implicit(self):
 return self.name.startswith('q_')
 
 def is_empty(self):
-assert self.members is not None
 return not self.members and not self.variants
 
 def has_conditional_members(self):
-assert self.members is not None
 return any(m.ifcond.is_present() for m in self.members)
 
 def c_name(self):
-- 
2.43.0




[PATCH v3 06/20] qapi/schema: make c_type() and json_type() abstract methods

2024-02-01 Thread John Snow
These methods should always return a str, it's only the default abstract
implementation that doesn't. They can be marked "abstract", which
requires subclasses to override the method with the proper return type.

Signed-off-by: John Snow 
---
 scripts/qapi/schema.py | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index ac34e2781de..8abcd4a86cb 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -16,6 +16,7 @@
 
 # TODO catching name collisions in generated code would be nice
 
+from abc import ABC, abstractmethod
 from collections import OrderedDict
 import os
 import re
@@ -253,9 +254,10 @@ def visit(self, visitor):
 visitor.visit_include(self._sub_module.name, self.info)
 
 
-class QAPISchemaType(QAPISchemaDefinition):
+class QAPISchemaType(QAPISchemaDefinition, ABC):
 # Return the C type for common use.
 # For the types we commonly box, this is a pointer type.
+@abstractmethod
 def c_type(self):
 pass
 
@@ -267,6 +269,7 @@ def c_param_type(self):
 def c_unboxed_type(self):
 return self.c_type()
 
+@abstractmethod
 def json_type(self):
 pass
 
-- 
2.43.0




[PATCH v3 12/20] qapi/schema: assert info is present when necessary

2024-02-01 Thread John Snow
QAPISchemaInfo arguments can often be None because built-in definitions
don't have such information.  The type hint can only be
Optional[QAPISchemaInfo] then.  But, mypy gets upset about all the
places where we exploit that it can't actually be None there.  Add
assertions that will help mypy over the hump, to enable adding type
hints in a forthcoming commit.

Signed-off-by: John Snow 
---
 scripts/qapi/schema.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index ae350f64a8f..d4d3c3bbcee 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -758,6 +758,7 @@ def describe(self, info):
 else:
 assert False
 
+assert info is not None
 if defined_in != info.defn_name:
 return "%s '%s' of %s '%s'" % (role, self.name, meta, defined_in)
 return "%s '%s'" % (role, self.name)
@@ -848,6 +849,7 @@ def __init__(self, name, info, doc, ifcond, features,
 self.coroutine = coroutine
 
 def check(self, schema):
+assert self.info is not None
 super().check(schema)
 if self._arg_type_name:
 arg_type = schema.resolve_type(
-- 
2.43.0




[PATCH v3 02/20] qapi/schema: add pylint suppressions

2024-02-01 Thread John Snow
With this patch, pylint is happy with the file, so enable it in the
configuration.

Signed-off-by: John Snow 
Reviewed-by: Markus Armbruster 
---
 scripts/qapi/pylintrc  | 5 -
 scripts/qapi/schema.py | 5 +
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/scripts/qapi/pylintrc b/scripts/qapi/pylintrc
index 1342412c3cf..c028a1f9f51 100644
--- a/scripts/qapi/pylintrc
+++ b/scripts/qapi/pylintrc
@@ -1,10 +1,5 @@
 [MASTER]
 
-# Add files or directories matching the regex patterns to the ignore list.
-# The regex matches against base names, not paths.
-ignore-patterns=schema.py,
-
-
 [MESSAGES CONTROL]
 
 # Disable the message, report, category or checker with the given id(s). You
diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index 6a836950a9a..b7830672e57 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -12,6 +12,8 @@
 # This work is licensed under the terms of the GNU GPL, version 2.
 # See the COPYING file in the top-level directory.
 
+# pylint: disable=too-many-lines
+
 # TODO catching name collisions in generated code would be nice
 
 from collections import OrderedDict
@@ -83,6 +85,7 @@ def c_name(self):
 return c_name(self.name)
 
 def check(self, schema):
+# pylint: disable=unused-argument
 assert not self._checked
 seen = {}
 for f in self.features:
@@ -117,6 +120,7 @@ def is_implicit(self):
 return not self.info
 
 def visit(self, visitor):
+# pylint: disable=unused-argument
 assert self._checked
 
 def describe(self):
@@ -135,6 +139,7 @@ def visit_module(self, name):
 pass
 
 def visit_needed(self, entity):
+# pylint: disable=unused-argument
 # Default to visiting everything
 return True
 
-- 
2.43.0




[PATCH v3 09/20] qapi/schema: assert resolve_type has 'info' and 'what' args on error

2024-02-01 Thread John Snow
resolve_type() is generally used to resolve configuration-provided type
names into type objects, and generally requires valid 'info' and 'what'
parameters.

In some cases, such as with QAPISchemaArrayType.check(), resolve_type
may be used to resolve built-in types and as such will not have an
'info' argument, but also must not fail in this scenario.

Use an assertion to sate mypy that we will indeed have 'info' and 'what'
parameters for the error pathway in resolve_type.

Note: there are only three callsites to resolve_type at present where
"info" is perceived to be possibly None:

1) QAPISchemaArrayType.check()
2) QAPISchemaObjectTypeMember.check()
3) QAPISchemaEvent.check()

Of those three, only the first actually ever passes None; the other two
are limited by their base class initializers which accept info=None, but
neither subclass actually use a None value in practice, currently.

Signed-off-by: John Snow 
---
 scripts/qapi/schema.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index e617abb03af..573be7275a6 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -1004,6 +1004,7 @@ def lookup_type(self, name):
 def resolve_type(self, name, info, what):
 typ = self.lookup_type(name)
 if not typ:
+assert info and what  # built-in types must not fail lookup
 if callable(what):
 what = what(info)
 raise QAPISemError(
-- 
2.43.0




[PATCH v3 19/20] qapi/schema: turn on mypy strictness

2024-02-01 Thread John Snow
This patch can be rolled in with the previous one once the series is
ready for merge, but for work-in-progress' sake, it's separate here.

Signed-off-by: John Snow 
---
 scripts/qapi/mypy.ini | 5 -
 1 file changed, 5 deletions(-)

diff --git a/scripts/qapi/mypy.ini b/scripts/qapi/mypy.ini
index 56e0dfb1327..8109470a031 100644
--- a/scripts/qapi/mypy.ini
+++ b/scripts/qapi/mypy.ini
@@ -2,8 +2,3 @@
 strict = True
 disallow_untyped_calls = False
 python_version = 3.8
-
-[mypy-qapi.schema]
-disallow_untyped_defs = False
-disallow_incomplete_defs = False
-check_untyped_defs = False
-- 
2.43.0




[PATCH v3 04/20] qapi/schema: declare type for QAPISchemaObjectTypeMember.type

2024-02-01 Thread John Snow
A QAPISchemaObjectTypeMember's type gets resolved only during .check().
We have QAPISchemaObjectTypeMember.__init__() initialize self.type =
None, and .check() assign the actual type.  Using .type before .check()
is wrong, and hopefully crashes due to the value being None.  Works.

However, it makes for awkward typing.  With .type:
Optional[QAPISchemaType], mypy is of course unable to see that it's None
before .check(), and a QAPISchemaType after.  To help it over the hump,
we'd have to assert self.type is not None before all the (valid) uses.
The assertion catches invalid uses, but only at run time; mypy can't
flag them.

Instead, declare .type in .__init__() as QAPISchemaType *without*
initializing it.  Using .type before .check() now certainly crashes,
which is an improvement.  Mypy still can't flag invalid uses, but that's
okay.

Addresses typing errors such as these:

qapi/schema.py:657: error: "None" has no attribute "alternate_qtype"  
[attr-defined]
qapi/schema.py:662: error: "None" has no attribute "describe"  [attr-defined]

Signed-off-by: John Snow 
---
 scripts/qapi/schema.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index 7f790d44742..74a32656249 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -794,7 +794,7 @@ def __init__(self, name, info, typ, optional, ifcond=None, 
features=None):
 assert isinstance(f, QAPISchemaFeature)
 f.set_defined_in(name)
 self._type_name = typ
-self.type = None
+self.type: QAPISchemaType  # set during check()
 self.optional = optional
 self.features = features or []
 
-- 
2.43.0




[PATCH v3 15/20] qapi/schema: fix typing for QAPISchemaVariants.tag_member

2024-02-01 Thread John Snow
There are two related changes here:

(1) We need to perform type narrowing for resolving the type of
tag_member during check(), and

(2) tag_member is a delayed initialization field, but we can hide it
behind a property that raises an Exception if it's called too
early. This simplifies the typing in quite a few places and avoids
needing to assert that the "tag_member is not None" at a dozen
callsites, which can be confusing and suggest the wrong thing to a
drive-by contributor.

Signed-off-by: John Snow 
---
 scripts/qapi/schema.py | 22 +++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index 947e7efb1a8..7508e3a4fa6 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -635,25 +635,39 @@ def __init__(self, tag_name, info, tag_member, variants):
 assert isinstance(v, QAPISchemaVariant)
 self._tag_name = tag_name
 self.info = info
-self.tag_member = tag_member
+self._tag_member: Optional[QAPISchemaObjectTypeMember] = tag_member
 self.variants = variants
 
+@property
+def tag_member(self) -> 'QAPISchemaObjectTypeMember':
+if self._tag_member is None:
+raise RuntimeError(
+"QAPISchemaVariants has no tag_member property until "
+"after check() has been run."
+)
+return self._tag_member
+
 def set_defined_in(self, name):
 for v in self.variants:
 v.set_defined_in(name)
 
 def check(self, schema, seen):
 if self._tag_name:  # union
-self.tag_member = seen.get(c_name(self._tag_name))
+# We need to narrow the member type:
+tmp = seen.get(c_name(self._tag_name))
+assert tmp is None or isinstance(tmp, QAPISchemaObjectTypeMember)
+self._tag_member = tmp
+
 base = "'base'"
 # Pointing to the base type when not implicit would be
 # nice, but we don't know it here
-if not self.tag_member or self._tag_name != self.tag_member.name:
+if not self._tag_member or self._tag_name != self._tag_member.name:
 raise QAPISemError(
 self.info,
 "discriminator '%s' is not a member of %s"
 % (self._tag_name, base))
 # Here we do:
+assert self.tag_member.defined_in
 base_type = schema.resolve_type(self.tag_member.defined_in)
 if not base_type.is_implicit():
 base = "base type '%s'" % self.tag_member.defined_in
@@ -673,11 +687,13 @@ def check(self, schema, seen):
 "discriminator member '%s' of %s must not be conditional"
 % (self._tag_name, base))
 else:   # alternate
+assert self._tag_member
 assert isinstance(self.tag_member.type, QAPISchemaEnumType)
 assert not self.tag_member.optional
 assert not self.tag_member.ifcond.is_present()
 if self._tag_name:  # union
 # branches that are not explicitly covered get an empty type
+assert self.tag_member.defined_in
 cases = {v.name for v in self.variants}
 for m in self.tag_member.type.members:
 if m.name not in cases:
-- 
2.43.0




[PATCH v3 13/20] qapi/schema: split "checked" field into "checking" and "checked"

2024-02-01 Thread John Snow
Instead of using the None value for the members field, use a dedicated
"checking" value to detect recursive misconfigurations.

This is intended to assist with subsequent patches which will seek to
remove the "None" value from the members field (which can never be set
legally after the final call to check()) in order to simplify static
typing of that field, by avoiding needing assertions littered at many
callsites.

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

diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index d4d3c3bbcee..a459016e148 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -458,19 +458,21 @@ def __init__(self, name, info, doc, ifcond, features,
 self.local_members = local_members
 self.variants = variants
 self.members = None
+self._checking = False
 
 def check(self, schema):
 # This calls another type T's .check() exactly when the C
 # struct emitted by gen_object() contains that T's C struct
 # (pointers don't count).
-if self.members is not None:
-# A previous .check() completed: nothing to do
-return
-if self._checked:
+if self._checking:
 # Recursed: C struct contains itself
 raise QAPISemError(self.info,
"object %s contains itself" % self.name)
+if self._checked:
+# A previous .check() completed: nothing to do
+return
 
+self._checking = True
 super().check(schema)
 assert self._checked and self.members is None
 
@@ -495,7 +497,8 @@ def check(self, schema):
 self.variants.check(schema, seen)
 self.variants.check_clash(self.info, seen)
 
-self.members = members  # mark completed
+self.members = members
+self._checking = False  # mark completed
 
 # Check that the members of this type do not cause duplicate JSON members,
 # and update seen to track the members seen so far. Report any errors
-- 
2.43.0




[PATCH v3 01/20] qapi: sort pylint suppressions

2024-02-01 Thread John Snow
Suggested-by: Markus Armbruster 
Signed-off-by: John Snow 
---
 scripts/qapi/pylintrc | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/scripts/qapi/pylintrc b/scripts/qapi/pylintrc
index 90546df5345..1342412c3cf 100644
--- a/scripts/qapi/pylintrc
+++ b/scripts/qapi/pylintrc
@@ -16,13 +16,13 @@ ignore-patterns=schema.py,
 # --enable=similarities". If you want to run only the classes checker, but have
 # no Warning level messages displayed, use "--disable=all --enable=classes
 # --disable=W".
-disable=fixme,
+disable=consider-using-f-string,
+fixme,
 missing-docstring,
 too-many-arguments,
 too-many-branches,
-too-many-statements,
 too-many-instance-attributes,
-consider-using-f-string,
+too-many-statements,
 useless-option-value,
 
 [REPORTS]
-- 
2.43.0




[PATCH v3 18/20] qapi/schema: add type hints

2024-02-01 Thread John Snow
This patch only adds type hints, which aren't utilized at runtime and
don't change the behavior of this module in any way.

In a scant few locations, type hints are removed where no longer
necessary due to inference power from typing all of the rest of
creation; and any type hints that no longer need string quotes are
changed.

Signed-off-by: John Snow 
---
 scripts/qapi/schema.py | 572 -
 1 file changed, 398 insertions(+), 174 deletions(-)

diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index 4d153b216c0..319c8475d21 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -16,11 +16,21 @@
 
 # TODO catching name collisions in generated code would be nice
 
+from __future__ import annotations
+
 from abc import ABC, abstractmethod
 from collections import OrderedDict
 import os
 import re
-from typing import List, Optional, cast
+from typing import (
+Any,
+Callable,
+Dict,
+List,
+Optional,
+Union,
+cast,
+)
 
 from .common import (
 POINTER_SUFFIX,
@@ -32,26 +42,30 @@
 )
 from .error import QAPIError, QAPISemError, QAPISourceError
 from .expr import check_exprs
-from .parser import QAPIExpression, QAPISchemaParser
+from .parser import QAPIDoc, QAPIExpression, QAPISchemaParser
+from .source import QAPISourceInfo
 
 
 class QAPISchemaIfCond:
-def __init__(self, ifcond=None):
+def __init__(
+self,
+ifcond: Optional[Union[str, Dict[str, object]]] = None,
+) -> None:
 self.ifcond = ifcond
 
-def _cgen(self):
+def _cgen(self) -> str:
 return cgen_ifcond(self.ifcond)
 
-def gen_if(self):
+def gen_if(self) -> str:
 return gen_if(self._cgen())
 
-def gen_endif(self):
+def gen_endif(self) -> str:
 return gen_endif(self._cgen())
 
-def docgen(self):
+def docgen(self) -> str:
 return docgen_ifcond(self.ifcond)
 
-def is_present(self):
+def is_present(self) -> bool:
 return bool(self.ifcond)
 
 
@@ -62,8 +76,8 @@ class QAPISchemaEntity:
 This is either a directive, such as include, or a definition.
 The latter uses sub-class `QAPISchemaDefinition`.
 """
-def __init__(self, info):
-self._module = None
+def __init__(self, info: Optional[QAPISourceInfo]):
+self._module: Optional[QAPISchemaModule] = None
 # For explicitly defined entities, info points to the (explicit)
 # definition.  For builtins (and their arrays), info is None.
 # For implicitly defined entities, info points to a place that
@@ -72,37 +86,46 @@ def __init__(self, info):
 self.info = info
 self._checked = False
 
-def __repr__(self):
+def __repr__(self) -> str:
 return "<%s at 0x%x>" % (type(self).__name__, id(self))
 
-def check(self, schema):
+def check(self, schema: QAPISchema) -> None:
 # pylint: disable=unused-argument
 self._checked = True
 
-def connect_doc(self, doc=None):
+def connect_doc(self, doc: Optional[QAPIDoc] = None) -> None:
 pass
 
-def check_doc(self):
+def check_doc(self) -> None:
 pass
 
-def _set_module(self, schema, info):
+def _set_module(
+self, schema: QAPISchema, info: Optional[QAPISourceInfo]
+) -> None:
 assert self._checked
 fname = info.fname if info else QAPISchemaModule.BUILTIN_MODULE_NAME
 self._module = schema.module_by_fname(fname)
 self._module.add_entity(self)
 
-def set_module(self, schema):
+def set_module(self, schema: QAPISchema) -> None:
 self._set_module(schema, self.info)
 
-def visit(self, visitor):
+def visit(self, visitor: QAPISchemaVisitor) -> None:
 # pylint: disable=unused-argument
 assert self._checked
 
 
 class QAPISchemaDefinition(QAPISchemaEntity):
-meta: Optional[str] = None
+meta: str
 
-def __init__(self, name: str, info, doc, ifcond=None, features=None):
+def __init__(
+self,
+name: str,
+info: Optional[QAPISourceInfo],
+doc: Optional[QAPIDoc],
+ifcond: Optional[QAPISchemaIfCond] = None,
+features: Optional[List[QAPISchemaFeature]] = None,
+):
 assert isinstance(name, str)
 super().__init__(info)
 for f in features or []:
@@ -113,89 +136,147 @@ def __init__(self, name: str, info, doc, ifcond=None, 
features=None):
 self._ifcond = ifcond or QAPISchemaIfCond()
 self.features = features or []
 
-def __repr__(self):
+def __repr__(self) -> str:
 return "<%s:%s at 0x%x>" % (type(self).__name__, self.name,
 id(self))
 
-def c_name(self):
+def c_name(self) -> str:
 return c_name(self.name)
 
-def check(self, schema):
+def check(self, schema: QAPISchema) -> None:
 assert not self._checked
 super().check(schema)
-seen = {}
+seen: Dict[str, 

[PATCH v3 05/20] qapi/schema: declare type for QAPISchemaArrayType.element_type

2024-02-01 Thread John Snow
A QAPISchemaArrayType's element type gets resolved only during .check().
We have QAPISchemaArrayType.__init__() initialize self.element_type =
None, and .check() assign the actual type.  Using .element_type before
.check() is wrong, and hopefully crashes due to the value being None.
Works.

However, it makes for awkward typing.  With .element_type:
Optional[QAPISchemaType], mypy is of course unable to see that it's None
before .check(), and a QAPISchemaType after.  To help it over the hump,
we'd have to assert self.element_type is not None before all the (valid)
uses.  The assertion catches invalid uses, but only at run time; mypy
can't flag them.

Instead, declare .element_type in .__init__() as QAPISchemaType
*without* initializing it.  Using .element_type before .check() now
certainly crashes, which is an improvement.  Mypy still can't flag
invalid uses, but that's okay.

Signed-off-by: John Snow 
---
 scripts/qapi/schema.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index 74a32656249..ac34e2781de 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -389,7 +389,7 @@ def __init__(self, name, info, element_type):
 super().__init__(name, info, None)
 assert isinstance(element_type, str)
 self._element_type_name = element_type
-self.element_type = None
+self.element_type: QAPISchemaType
 
 def need_has_if_optional(self):
 # When FOO is an array, we still need has_FOO to distinguish
-- 
2.43.0




[PATCH v3 20/20] qapi/schema: remove unnecessary asserts

2024-02-01 Thread John Snow
With strict typing enabled, these runtime statements aren't necessary
anymore; we can prove them statically.

Signed-off-by: John Snow 
---
 scripts/qapi/schema.py | 25 -
 1 file changed, 25 deletions(-)

diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index 319c8475d21..fb0c5d6e2c6 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -126,10 +126,8 @@ def __init__(
 ifcond: Optional[QAPISchemaIfCond] = None,
 features: Optional[List[QAPISchemaFeature]] = None,
 ):
-assert isinstance(name, str)
 super().__init__(info)
 for f in features or []:
-assert isinstance(f, QAPISchemaFeature)
 f.set_defined_in(name)
 self.name = name
 self.doc = doc
@@ -171,7 +169,6 @@ def is_implicit(self) -> bool:
 return not self.info
 
 def describe(self) -> str:
-assert self.meta
 return "%s '%s'" % (self.meta, self.name)
 
 
@@ -385,7 +382,6 @@ def check(self, schema: QAPISchema) -> None:
 f"feature '{feat.name}' is not supported for types")
 
 def describe(self) -> str:
-assert self.meta
 return "%s type '%s'" % (self.meta, self.name)
 
 
@@ -394,7 +390,6 @@ class QAPISchemaBuiltinType(QAPISchemaType):
 
 def __init__(self, name: str, json_type: str, c_type: str):
 super().__init__(name, None, None)
-assert not c_type or isinstance(c_type, str)
 assert json_type in ('string', 'number', 'int', 'boolean', 'null',
  'value')
 self._json_type_name = json_type
@@ -437,9 +432,7 @@ def __init__(
 ):
 super().__init__(name, info, doc, ifcond, features)
 for m in members:
-assert isinstance(m, QAPISchemaEnumMember)
 m.set_defined_in(name)
-assert prefix is None or isinstance(prefix, str)
 self.members = members
 self.prefix = prefix
 
@@ -482,7 +475,6 @@ def __init__(
 self, name: str, info: Optional[QAPISourceInfo], element_type: str
 ):
 super().__init__(name, info, None)
-assert isinstance(element_type, str)
 self._element_type_name = element_type
 self.element_type: QAPISchemaType
 
@@ -527,7 +519,6 @@ def visit(self, visitor: QAPISchemaVisitor) -> None:
  self.element_type)
 
 def describe(self) -> str:
-assert self.meta
 return "%s type ['%s']" % (self.meta, self._element_type_name)
 
 
@@ -547,12 +538,9 @@ def __init__(
 # union has base, variants, and no local_members
 super().__init__(name, info, doc, ifcond, features)
 self.meta = 'union' if variants else 'struct'
-assert base is None or isinstance(base, str)
 for m in local_members:
-assert isinstance(m, QAPISchemaObjectTypeMember)
 m.set_defined_in(name)
 if variants is not None:
-assert isinstance(variants, QAPISchemaVariants)
 variants.set_defined_in(name)
 self._base_name = base
 self.base = None
@@ -674,7 +662,6 @@ def __init__(
 variants: QAPISchemaVariants,
 ):
 super().__init__(name, info, doc, ifcond, features)
-assert isinstance(variants, QAPISchemaVariants)
 assert variants.tag_member
 variants.set_defined_in(name)
 variants.tag_member.set_defined_in(self.name)
@@ -750,8 +737,6 @@ def __init__(
 assert bool(tag_member) != bool(tag_name)
 assert (isinstance(tag_name, str) or
 isinstance(tag_member, QAPISchemaObjectTypeMember))
-for v in variants:
-assert isinstance(v, QAPISchemaVariant)
 self._tag_name = tag_name
 self.info = info
 self._tag_member = tag_member
@@ -865,7 +850,6 @@ def __init__(
 info: Optional[QAPISourceInfo],
 ifcond: Optional[QAPISchemaIfCond] = None,
 ):
-assert isinstance(name, str)
 self.name = name
 self.info = info
 self.ifcond = ifcond or QAPISchemaIfCond()
@@ -933,7 +917,6 @@ def __init__(
 ):
 super().__init__(name, info, ifcond)
 for f in features or []:
-assert isinstance(f, QAPISchemaFeature)
 f.set_defined_in(name)
 self.features = features or []
 
@@ -962,10 +945,7 @@ def __init__(
 features: Optional[List[QAPISchemaFeature]] = None,
 ):
 super().__init__(name, info, ifcond)
-assert isinstance(typ, str)
-assert isinstance(optional, bool)
 for f in features or []:
-assert isinstance(f, QAPISchemaFeature)
 f.set_defined_in(name)
 self._type_name = typ
 self.type: QAPISchemaType  # set during check()
@@ -973,7 +953,6 @@ def __init__(
 self.features = features or []
 
 def need_has(self) -> bool:
-assert self.type
 return self.optional and 

[PATCH v3 03/20] qapi: create QAPISchemaDefinition

2024-02-01 Thread John Snow
Include entities don't have names, but we generally expect "entities" to
have names. Reclassify all entities with names as *definitions*, leaving
the nameless include entities as QAPISchemaEntity instances.

This is primarily to help simplify typing around expectations of what
callers expect for properties of an "entity".

Suggested-by: Markus Armbruster 
Signed-off-by: John Snow 
---
 scripts/qapi/schema.py | 152 -
 1 file changed, 88 insertions(+), 64 deletions(-)

diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index b7830672e57..7f790d44742 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -55,14 +55,13 @@ def is_present(self):
 
 
 class QAPISchemaEntity:
-meta: Optional[str] = None
+"""
+A schema entity.
 
-def __init__(self, name: str, info, doc, ifcond=None, features=None):
-assert name is None or isinstance(name, str)
-for f in features or []:
-assert isinstance(f, QAPISchemaFeature)
-f.set_defined_in(name)
-self.name = name
+This is either a directive, such as include, or a definition.
+The latter uses sub-class `QAPISchemaDefinition`.
+"""
+def __init__(self, info):
 self._module = None
 # For explicitly defined entities, info points to the (explicit)
 # definition.  For builtins (and their arrays), info is None.
@@ -70,37 +69,20 @@ def __init__(self, name: str, info, doc, ifcond=None, 
features=None):
 # triggered the implicit definition (there may be more than one
 # such place).
 self.info = info
-self.doc = doc
-self._ifcond = ifcond or QAPISchemaIfCond()
-self.features = features or []
 self._checked = False
 
 def __repr__(self):
-if self.name is None:
-return "<%s at 0x%x>" % (type(self).__name__, id(self))
-return "<%s:%s at 0x%x>" % (type(self).__name__, self.name,
-id(self))
-
-def c_name(self):
-return c_name(self.name)
+return "<%s at 0x%x>" % (type(self).__name__, id(self))
 
 def check(self, schema):
 # pylint: disable=unused-argument
-assert not self._checked
-seen = {}
-for f in self.features:
-f.check_clash(self.info, seen)
 self._checked = True
 
 def connect_doc(self, doc=None):
-doc = doc or self.doc
-if doc:
-for f in self.features:
-doc.connect_feature(f)
+pass
 
 def check_doc(self):
-if self.doc:
-self.doc.check()
+pass
 
 def _set_module(self, schema, info):
 assert self._checked
@@ -111,6 +93,51 @@ def _set_module(self, schema, info):
 def set_module(self, schema):
 self._set_module(schema, self.info)
 
+def visit(self, visitor):
+# pylint: disable=unused-argument
+assert self._checked
+
+
+class QAPISchemaDefinition(QAPISchemaEntity):
+meta: Optional[str] = None
+
+def __init__(self, name: str, info, doc, ifcond=None, features=None):
+assert isinstance(name, str)
+super().__init__(info)
+for f in features or []:
+assert isinstance(f, QAPISchemaFeature)
+f.set_defined_in(name)
+self.name = name
+self.doc = doc
+self._ifcond = ifcond or QAPISchemaIfCond()
+self.features = features or []
+
+def __repr__(self):
+return "<%s:%s at 0x%x>" % (type(self).__name__, self.name,
+id(self))
+
+def c_name(self):
+return c_name(self.name)
+
+def check(self, schema):
+assert not self._checked
+super().check(schema)
+seen = {}
+for f in self.features:
+f.check_clash(self.info, seen)
+
+def connect_doc(self, doc=None):
+super().connect_doc(doc)
+doc = doc or self.doc
+if doc:
+for f in self.features:
+doc.connect_feature(f)
+
+def check_doc(self):
+super().check_doc()
+if self.doc:
+self.doc.check()
+
 @property
 def ifcond(self):
 assert self._checked
@@ -119,10 +146,6 @@ def ifcond(self):
 def is_implicit(self):
 return not self.info
 
-def visit(self, visitor):
-# pylint: disable=unused-argument
-assert self._checked
-
 def describe(self):
 assert self.meta
 return "%s '%s'" % (self.meta, self.name)
@@ -222,7 +245,7 @@ def visit(self, visitor):
 
 class QAPISchemaInclude(QAPISchemaEntity):
 def __init__(self, sub_module, info):
-super().__init__(None, info, None)
+super().__init__(info)
 self._sub_module = sub_module
 
 def visit(self, visitor):
@@ -230,7 +253,7 @@ def visit(self, visitor):
 visitor.visit_include(self._sub_module.name, self.info)
 
 
-class QAPISchemaType(QAPISchemaEntity):
+class 

[PATCH v3 11/20] qapi/schema: fix QAPISchemaArrayType.check's call to resolve_type

2024-02-01 Thread John Snow
Adjust the expression at the callsite to work around mypy's weak type
introspection that believes this expression can resolve to
QAPISourceInfo; it cannot.

(Fundamentally: self.info only resolves to false in a boolean expression
when it is None; therefore this expression may only ever produce
Optional[str]. mypy does not know that 'info', when it is a
QAPISourceInfo object, cannot ever be false.)

Signed-off-by: John Snow 
---
 scripts/qapi/schema.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index 074897ee4fb..ae350f64a8f 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -403,7 +403,7 @@ def check(self, schema):
 super().check(schema)
 self.element_type = schema.resolve_type(
 self._element_type_name, self.info,
-self.info and self.info.defn_meta)
+self.info.defn_meta if self.info else None)
 assert not isinstance(self.element_type, QAPISchemaArrayType)
 
 def set_module(self, schema):
-- 
2.43.0




[PATCH v3 10/20] qapi: use schema.resolve_type instead of schema.lookup_type

2024-02-01 Thread John Snow
the function lookup_type() is capable of returning None, but some
callers aren't prepared for that and assume it will always succeed. For
static type analysis purposes, this creates problems at those callsites.

Modify resolve_type() - which already cannot ever return None - to allow
'info' and 'what' parameters to be elided, which infers that the type
lookup is a built-in type lookup.

Change several callsites to use the new form of resolve_type to avoid
the more laborious strictly-typed error-checking scaffolding:

  ret = lookup_type("foo")
  assert ret is not None
  typ: QAPISchemaType = ret

which can be replaced with the simpler:

  typ = resolve_type("foo")

Signed-off-by: John Snow 
---
 scripts/qapi/introspect.py | 4 ++--
 scripts/qapi/schema.py | 5 ++---
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
index 67c7d89aae0..c38df61a6d5 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -227,10 +227,10 @@ def _use_type(self, typ: QAPISchemaType) -> str:
 
 # Map the various integer types to plain int
 if typ.json_type() == 'int':
-typ = self._schema.lookup_type('int')
+typ = self._schema.resolve_type('int')
 elif (isinstance(typ, QAPISchemaArrayType) and
   typ.element_type.json_type() == 'int'):
-typ = self._schema.lookup_type('intList')
+typ = self._schema.resolve_type('intList')
 # Add type to work queue if new
 if typ not in self._used_types:
 self._used_types.append(typ)
diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index 573be7275a6..074897ee4fb 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -650,8 +650,7 @@ def check(self, schema, seen):
 "discriminator '%s' is not a member of %s"
 % (self._tag_name, base))
 # Here we do:
-base_type = schema.lookup_type(self.tag_member.defined_in)
-assert base_type
+base_type = schema.resolve_type(self.tag_member.defined_in)
 if not base_type.is_implicit():
 base = "base type '%s'" % self.tag_member.defined_in
 if not isinstance(self.tag_member.type, QAPISchemaEnumType):
@@ -1001,7 +1000,7 @@ def lookup_type(self, name):
 assert typ is None or isinstance(typ, QAPISchemaType)
 return typ
 
-def resolve_type(self, name, info, what):
+def resolve_type(self, name, info=None, what=None):
 typ = self.lookup_type(name)
 if not typ:
 assert info and what  # built-in types must not fail lookup
-- 
2.43.0




  1   2   3   4   >