All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108
@ 2018-11-08 12:16 David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 01/22] target/ppc: add external PID support David Gibson
                   ` (22 more replies)
  0 siblings, 23 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell; +Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier, David Gibson

The following changes since commit 4de6bb0c02ad3f0ec48f0f84ba1a65ab06e81b86:

  Update version for v3.1.0-rc0 release (2018-11-06 18:27:35 +0000)

are available in the Git repository at:

  git://github.com/dgibson/qemu.git tags/ppc-for-3.1-20181108

for you to fetch changes up to b9a477b725788e47bf653eab36e64f232d259f2a:

  ppc/spapr_caps: Add SPAPR_CAP_NESTED_KVM_HV (2018-11-08 13:08:35 +1100)

----------------------------------------------------------------
ppc patch queue 2018-11-08

Here's another patch of accumulated ppc patches for qemu-3.1.
Highlights are:
  * Support for nested HV KVM on POWER9 hosts
  * Remove Alex Graf as ppc maintainer
  * Emulation of external PID instructions

----------------------------------------------------------------
Alexander Graf (1):
      MAINTAINERS: PPC: Remove myself

Cédric Le Goater (3):
      ppc440_pcix: convert SysBus init method to a realize method
      ppc4xx_pci: convert SysBus init method to a realize method
      PPC: e500: convert SysBus init method to a realize method

Dr. David Alan Gilbert (1):
      macio/pmu: Fix missing vmsd terminator

Greg Kurz (1):
      spapr_pci: convert g_malloc() to g_new()

Maria Klimushenkova (1):
      This patch fixes processing of rfi instructions in icount mode.

Pavel Dovgalyuk (1):
      target/ppc: fix mtmsr instruction for icount

Peter Maydell (2):
      hw/ppc/mac_newworld: Free openpic_irqs array after use
      hw/ppc/ppc440_uc: Remove dead code in sdram_size()

Prasad J Pandit (1):
      ppc/pnv: check size before data buffer access

Richard Henderson (7):
      target/ppc: Split up float_invalid_op_excp
      target/ppc: Remove float_check_status
      target/ppc: Introduce fp number classification
      target/ppc: Split out float_invalid_op_addsub
      target/ppc: Split out float_invalid_op_mul
      target/ppc: Split out float_invalid_op_div
      target/ppc: Split out float_invalid_cvt

Roman Kapl (1):
      target/ppc: add external PID support

Suraj Jitindar Singh (2):
      target/ppc: Add one reg id for ptcr
      ppc/spapr_caps: Add SPAPR_CAP_NESTED_KVM_HV

Thomas Huth (1):
      hw/ppc/spapr_rng: Introduce CONFIG_SPAPR_RNG switch for spapr_rng.c

 MAINTAINERS                        |  30 +-
 default-configs/ppc64-softmmu.mak  |   1 +
 hw/misc/macio/pmu.c                |   1 +
 hw/pci-host/ppce500.c              |  14 +-
 hw/ppc/Makefile.objs               |   3 +-
 hw/ppc/mac_newworld.c              |   1 +
 hw/ppc/pnv_lpc.c                   |   8 +-
 hw/ppc/ppc440_pcix.c               |  14 +-
 hw/ppc/ppc440_uc.c                 |   6 +-
 hw/ppc/ppc4xx_pci.c                |  14 +-
 hw/ppc/spapr.c                     |  25 ++
 hw/ppc/spapr_caps.c                |  32 ++
 hw/ppc/spapr_pci.c                 |   2 +-
 hw/ppc/spapr_rng.c                 |  23 --
 include/hw/ppc/spapr.h             |   7 +-
 target/ppc/cpu.h                   |  24 +-
 target/ppc/fpu_helper.c            | 661 ++++++++++++++++++-------------------
 target/ppc/helper.h                |   4 +
 target/ppc/kvm.c                   |  12 +
 target/ppc/kvm_ppc.h               |  12 +
 target/ppc/mem_helper.c            |  34 +-
 target/ppc/mmu_helper.c            | 172 +++++++---
 target/ppc/translate.c             | 165 +++++++++
 target/ppc/translate/fp-impl.inc.c |  34 ++
 target/ppc/translate/fp-ops.inc.c  |   2 +
 target/ppc/translate_init.inc.c    |  31 +-
 26 files changed, 874 insertions(+), 458 deletions(-)

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 01/22] target/ppc: add external PID support
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-15 10:22   ` Peter Maydell
  2018-11-08 12:16 ` [Qemu-devel] [PULL 02/22] ppc440_pcix: convert SysBus init method to a realize method David Gibson
                   ` (21 subsequent siblings)
  22 siblings, 1 reply; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier, Roman Kapl, David Gibson

From: Roman Kapl <rka@sysgo.com>

External PID is a mechanism present on BookE 2.06 that enables application to
store/load data from different address spaces. There are special version of some
instructions, which operate on alternate address space, which is specified in
the EPLC/EPSC regiser.

This implementation uses two additional MMU modes (mmu_idx) to provide the
address space for the load and store instructions. The QEMU TLB fill code was
modified to recognize these MMU modes and use the values in EPLC/EPSC to find
the proper entry in he PPC TLB. These two QEMU TLBs are also flushed on each
write to EPLC/EPSC.

Following instructions are implemented: dcbfep dcbstep dcbtep dcbtstep dcbzep
dcbzlep icbiep lbepx ldepx lfdepx lhepx lwepx stbepx stdepx stfdepx sthepx
stwepx.

Following vector instructions are not: evlddepx evstddepx lvepx lvepxl stvepx
stvepxl.

Signed-off-by: Roman Kapl <rka@sysgo.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 target/ppc/cpu.h                   |  24 +++-
 target/ppc/helper.h                |   4 +
 target/ppc/mem_helper.c            |  34 +++++-
 target/ppc/mmu_helper.c            | 172 ++++++++++++++++++++++-------
 target/ppc/translate.c             | 141 +++++++++++++++++++++++
 target/ppc/translate/fp-impl.inc.c |  34 ++++++
 target/ppc/translate/fp-ops.inc.c  |   2 +
 target/ppc/translate_init.inc.c    |  21 +++-
 8 files changed, 387 insertions(+), 45 deletions(-)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index b5b8f6f440..ab68abe8a2 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -918,6 +918,19 @@ enum {
 /* number of possible TLBs */
 #define BOOKE206_MAX_TLBN      4
 
+#define EPID_EPID_SHIFT 0x0
+#define EPID_EPID 0xFF
+#define EPID_ELPID_SHIFT 0x10
+#define EPID_ELPID 0x3F0000
+#define EPID_EGS 0x20000000
+#define EPID_EGS_SHIFT 29
+#define EPID_EAS 0x40000000
+#define EPID_EAS_SHIFT 30
+#define EPID_EPR 0x80000000
+#define EPID_EPR_SHIFT 31
+/* We don't support EGS and ELPID */
+#define EPID_MASK (EPID_EPID | EPID_EAS | EPID_EPR)
+
 /*****************************************************************************/
 /* Server and Embedded Processor Control */
 
@@ -947,7 +960,16 @@ struct ppc_radix_page_info {
 
 /*****************************************************************************/
 /* The whole PowerPC CPU context */
-#define NB_MMU_MODES    8
+
+/* PowerPC needs eight modes for different hypervisor/supervisor/guest +
+ * real/paged mode combinations. The other two modes are for external PID
+ * load/store.
+ */
+#define NB_MMU_MODES    10
+#define MMU_MODE8_SUFFIX _epl
+#define MMU_MODE9_SUFFIX _eps
+#define PPC_TLB_EPID_LOAD 8
+#define PPC_TLB_EPID_STORE 9
 
 #define PPC_CPU_OPCODES_LEN          0x40
 #define PPC_CPU_INDIRECT_OPCODES_LEN 0x20
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 7a1481fd0b..c7de04e068 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -29,7 +29,9 @@ DEF_HELPER_4(lsw, void, env, tl, i32, i32)
 DEF_HELPER_5(lswx, void, env, tl, i32, i32, i32)
 DEF_HELPER_FLAGS_4(stsw, TCG_CALL_NO_WG, void, env, tl, i32, i32)
 DEF_HELPER_FLAGS_3(dcbz, TCG_CALL_NO_WG, void, env, tl, i32)
+DEF_HELPER_FLAGS_3(dcbzep, TCG_CALL_NO_WG, void, env, tl, i32)
 DEF_HELPER_FLAGS_2(icbi, TCG_CALL_NO_WG, void, env, tl)
+DEF_HELPER_FLAGS_2(icbiep, TCG_CALL_NO_WG, void, env, tl)
 DEF_HELPER_5(lscbx, tl, env, tl, i32, i32, i32)
 
 #if defined(TARGET_PPC64)
@@ -658,6 +660,8 @@ DEF_HELPER_2(booke206_tlbilx1, void, env, tl)
 DEF_HELPER_2(booke206_tlbilx3, void, env, tl)
 DEF_HELPER_2(booke206_tlbflush, void, env, tl)
 DEF_HELPER_3(booke_setpid, void, env, i32, tl)
+DEF_HELPER_2(booke_set_eplc, void, env, tl)
+DEF_HELPER_2(booke_set_epsc, void, env, tl)
 DEF_HELPER_2(6xx_tlbd, void, env, tl)
 DEF_HELPER_2(6xx_tlbi, void, env, tl)
 DEF_HELPER_2(74xx_tlbd, void, env, tl)
diff --git a/target/ppc/mem_helper.c b/target/ppc/mem_helper.c
index a1485fad9b..9c5a68579e 100644
--- a/target/ppc/mem_helper.c
+++ b/target/ppc/mem_helper.c
@@ -142,11 +142,13 @@ void helper_stsw(CPUPPCState *env, target_ulong addr, uint32_t nb,
     }
 }
 
-void helper_dcbz(CPUPPCState *env, target_ulong addr, uint32_t opcode)
+static void dcbz_common(CPUPPCState *env, target_ulong addr,
+                        uint32_t opcode, bool epid, uintptr_t retaddr)
 {
     target_ulong mask, dcbz_size = env->dcache_line_size;
     uint32_t i;
     void *haddr;
+    int mmu_idx = epid ? PPC_TLB_EPID_STORE : env->dmmu_idx;
 
 #if defined(TARGET_PPC64)
     /* Check for dcbz vs dcbzl on 970 */
@@ -166,17 +168,34 @@ void helper_dcbz(CPUPPCState *env, target_ulong addr, uint32_t opcode)
     }
 
     /* Try fast path translate */
-    haddr = tlb_vaddr_to_host(env, addr, MMU_DATA_STORE, env->dmmu_idx);
+    haddr = tlb_vaddr_to_host(env, addr, MMU_DATA_STORE, mmu_idx);
     if (haddr) {
         memset(haddr, 0, dcbz_size);
     } else {
         /* Slow path */
         for (i = 0; i < dcbz_size; i += 8) {
-            cpu_stq_data_ra(env, addr + i, 0, GETPC());
+            if (epid) {
+#if !defined(CONFIG_USER_ONLY)
+                /* Does not make sense on USER_ONLY config */
+                cpu_stq_eps_ra(env, addr + i, 0, retaddr);
+#endif
+            } else {
+                cpu_stq_data_ra(env, addr + i, 0, retaddr);
+            }
         }
     }
 }
 
+void helper_dcbz(CPUPPCState *env, target_ulong addr, uint32_t opcode)
+{
+    dcbz_common(env, addr, opcode, false, GETPC());
+}
+
+void helper_dcbzep(CPUPPCState *env, target_ulong addr, uint32_t opcode)
+{
+    dcbz_common(env, addr, opcode, true, GETPC());
+}
+
 void helper_icbi(CPUPPCState *env, target_ulong addr)
 {
     addr &= ~(env->dcache_line_size - 1);
@@ -188,6 +207,15 @@ void helper_icbi(CPUPPCState *env, target_ulong addr)
     cpu_ldl_data_ra(env, addr, GETPC());
 }
 
+void helper_icbiep(CPUPPCState *env, target_ulong addr)
+{
+#if !defined(CONFIG_USER_ONLY)
+    /* See comments above */
+    addr &= ~(env->dcache_line_size - 1);
+    cpu_ldl_epl_ra(env, addr, GETPC());
+#endif
+}
+
 /* XXX: to be tested */
 target_ulong helper_lscbx(CPUPPCState *env, target_ulong addr, uint32_t reg,
                           uint32_t ra, uint32_t rb)
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index 04f8317ea1..cefed34da4 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -924,29 +924,84 @@ static int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
     return 0;
 }
 
+static bool is_epid_mmu(int mmu_idx)
+{
+    return mmu_idx == PPC_TLB_EPID_STORE || mmu_idx == PPC_TLB_EPID_LOAD;
+}
+
+static uint32_t mmubooke206_esr(int mmu_idx, bool rw)
+{
+    uint32_t esr = 0;
+    if (rw) {
+        esr |= ESR_ST;
+    }
+    if (is_epid_mmu(mmu_idx)) {
+        esr |= ESR_EPID;
+    }
+    return esr;
+}
+
+/* Get EPID register given the mmu_idx. If this is regular load,
+ * construct the EPID access bits from current processor state  */
+
+/* Get the effective AS and PR bits and the PID. The PID is returned only if
+ * EPID load is requested, otherwise the caller must detect the correct EPID.
+ * Return true if valid EPID is returned. */
+static bool mmubooke206_get_as(CPUPPCState *env,
+                               int mmu_idx, uint32_t *epid_out,
+                               bool *as_out, bool *pr_out)
+{
+    if (is_epid_mmu(mmu_idx)) {
+        uint32_t epidr;
+        if (mmu_idx == PPC_TLB_EPID_STORE) {
+            epidr = env->spr[SPR_BOOKE_EPSC];
+        } else {
+            epidr = env->spr[SPR_BOOKE_EPLC];
+        }
+        *epid_out = (epidr & EPID_EPID) >> EPID_EPID_SHIFT;
+        *as_out = !!(epidr & EPID_EAS);
+        *pr_out = !!(epidr & EPID_EPR);
+        return true;
+    } else {
+        *as_out = msr_ds;
+        *pr_out = msr_pr;
+        return false;
+    }
+}
+
+/* Check if the tlb found by hashing really matches */
 static int mmubooke206_check_tlb(CPUPPCState *env, ppcmas_tlb_t *tlb,
                                  hwaddr *raddr, int *prot,
                                  target_ulong address, int rw,
-                                 int access_type)
+                                 int access_type, int mmu_idx)
 {
     int ret;
     int prot2 = 0;
+    uint32_t epid;
+    bool as, pr;
+    bool use_epid = mmubooke206_get_as(env, mmu_idx, &epid, &as, &pr);
 
-    if (ppcmas_tlb_check(env, tlb, raddr, address,
-                         env->spr[SPR_BOOKE_PID]) >= 0) {
-        goto found_tlb;
-    }
+    if (!use_epid) {
+        if (ppcmas_tlb_check(env, tlb, raddr, address,
+                             env->spr[SPR_BOOKE_PID]) >= 0) {
+            goto found_tlb;
+        }
 
-    if (env->spr[SPR_BOOKE_PID1] &&
-        ppcmas_tlb_check(env, tlb, raddr, address,
-                         env->spr[SPR_BOOKE_PID1]) >= 0) {
-        goto found_tlb;
-    }
+        if (env->spr[SPR_BOOKE_PID1] &&
+            ppcmas_tlb_check(env, tlb, raddr, address,
+                             env->spr[SPR_BOOKE_PID1]) >= 0) {
+            goto found_tlb;
+        }
 
-    if (env->spr[SPR_BOOKE_PID2] &&
-        ppcmas_tlb_check(env, tlb, raddr, address,
-                         env->spr[SPR_BOOKE_PID2]) >= 0) {
-        goto found_tlb;
+        if (env->spr[SPR_BOOKE_PID2] &&
+            ppcmas_tlb_check(env, tlb, raddr, address,
+                             env->spr[SPR_BOOKE_PID2]) >= 0) {
+            goto found_tlb;
+        }
+    } else {
+        if (ppcmas_tlb_check(env, tlb, raddr, address, epid) >= 0) {
+            goto found_tlb;
+        }
     }
 
     LOG_SWTLB("%s: TLB entry not found\n", __func__);
@@ -954,7 +1009,7 @@ static int mmubooke206_check_tlb(CPUPPCState *env, ppcmas_tlb_t *tlb,
 
 found_tlb:
 
-    if (msr_pr != 0) {
+    if (pr) {
         if (tlb->mas7_3 & MAS3_UR) {
             prot2 |= PAGE_READ;
         }
@@ -978,6 +1033,8 @@ found_tlb:
 
     /* Check the address space and permissions */
     if (access_type == ACCESS_CODE) {
+        /* There is no way to fetch code using epid load */
+        assert(!use_epid);
         if (msr_ir != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
             LOG_SWTLB("%s: AS doesn't match\n", __func__);
             return -1;
@@ -992,7 +1049,7 @@ found_tlb:
         LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, prot2);
         ret = -3;
     } else {
-        if (msr_dr != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
+        if (as != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
             LOG_SWTLB("%s: AS doesn't match\n", __func__);
             return -1;
         }
@@ -1012,7 +1069,7 @@ found_tlb:
 
 static int mmubooke206_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
                                             target_ulong address, int rw,
-                                            int access_type)
+                                            int access_type, int mmu_idx)
 {
     ppcmas_tlb_t *tlb;
     hwaddr raddr;
@@ -1030,7 +1087,7 @@ static int mmubooke206_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
                 continue;
             }
             ret = mmubooke206_check_tlb(env, tlb, &raddr, &ctx->prot, address,
-                                        rw, access_type);
+                                        rw, access_type, mmu_idx);
             if (ret != -1) {
                 goto found_tlb;
             }
@@ -1348,8 +1405,10 @@ static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx,
     return ret;
 }
 
-static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
-                                target_ulong eaddr, int rw, int access_type)
+static int get_physical_address_wtlb(
+    CPUPPCState *env, mmu_ctx_t *ctx,
+    target_ulong eaddr, int rw, int access_type,
+    int mmu_idx)
 {
     PowerPCCPU *cpu = ppc_env_get_cpu(env);
     int ret = -1;
@@ -1392,7 +1451,7 @@ static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
         break;
     case POWERPC_MMU_BOOKE206:
         ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
-                                               access_type);
+                                               access_type, mmu_idx);
         break;
     case POWERPC_MMU_MPC8xx:
         /* XXX: TODO */
@@ -1417,6 +1476,13 @@ static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
     return ret;
 }
 
+static int get_physical_address(
+    CPUPPCState *env, mmu_ctx_t *ctx,
+    target_ulong eaddr, int rw, int access_type)
+{
+    return get_physical_address_wtlb(env, ctx, eaddr, rw, access_type, 0);
+}
+
 hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
     PowerPCCPU *cpu = POWERPC_CPU(cs);
@@ -1463,8 +1529,15 @@ hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 }
 
 static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
-                                     int rw)
+                                     int rw, int mmu_idx)
 {
+    uint32_t epid;
+    bool as, pr;
+    uint32_t missed_tid = 0;
+    bool use_epid = mmubooke206_get_as(env, mmu_idx, &epid, &as, &pr);
+    if (rw == 2) {
+        as = msr_ir;
+    }
     env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
     env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
     env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
@@ -1473,7 +1546,7 @@ static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
     env->spr[SPR_BOOKE_MAS7] = 0;
 
     /* AS */
-    if (((rw == 2) && msr_ir) || ((rw != 2) && msr_dr)) {
+    if (as) {
         env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
         env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
     }
@@ -1481,19 +1554,25 @@ static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
     env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
     env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
 
-    switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
-    case MAS4_TIDSELD_PID0:
-        env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID] << MAS1_TID_SHIFT;
-        break;
-    case MAS4_TIDSELD_PID1:
-        env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID1] << MAS1_TID_SHIFT;
-        break;
-    case MAS4_TIDSELD_PID2:
-        env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID2] << MAS1_TID_SHIFT;
-        break;
+    if (!use_epid) {
+        switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
+        case MAS4_TIDSELD_PID0:
+            missed_tid = env->spr[SPR_BOOKE_PID];
+            break;
+        case MAS4_TIDSELD_PID1:
+            missed_tid = env->spr[SPR_BOOKE_PID1];
+            break;
+        case MAS4_TIDSELD_PID2:
+            missed_tid = env->spr[SPR_BOOKE_PID2];
+            break;
+        }
+        env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
+    } else {
+        missed_tid = epid;
+        env->spr[SPR_BOOKE_MAS6] |= missed_tid << 16;
     }
+    env->spr[SPR_BOOKE_MAS1] |= (missed_tid << MAS1_TID_SHIFT);
 
-    env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
 
     /* next victim logic */
     env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
@@ -1520,7 +1599,8 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
         /* data access */
         access_type = env->access_type;
     }
-    ret = get_physical_address(env, &ctx, address, rw, access_type);
+    ret = get_physical_address_wtlb(env, &ctx, address, rw,
+                                    access_type, mmu_idx);
     if (ret == 0) {
         tlb_set_page(cs, address & TARGET_PAGE_MASK,
                      ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
@@ -1550,12 +1630,13 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
                     env->spr[SPR_40x_ESR] = 0x00000000;
                     break;
                 case POWERPC_MMU_BOOKE206:
-                    booke206_update_mas_tlb_miss(env, address, 2);
+                    booke206_update_mas_tlb_miss(env, address, 2, mmu_idx);
                     /* fall through */
                 case POWERPC_MMU_BOOKE:
                     cs->exception_index = POWERPC_EXCP_ITLB;
                     env->error_code = 0;
                     env->spr[SPR_BOOKE_DEAR] = address;
+                    env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 0);
                     return -1;
                 case POWERPC_MMU_MPC8xx:
                     /* XXX: TODO */
@@ -1642,13 +1723,13 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
                     cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
                     break;
                 case POWERPC_MMU_BOOKE206:
-                    booke206_update_mas_tlb_miss(env, address, rw);
+                    booke206_update_mas_tlb_miss(env, address, rw, mmu_idx);
                     /* fall through */
                 case POWERPC_MMU_BOOKE:
                     cs->exception_index = POWERPC_EXCP_DTLB;
                     env->error_code = 0;
                     env->spr[SPR_BOOKE_DEAR] = address;
-                    env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0;
+                    env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, rw);
                     return -1;
                 case POWERPC_MMU_REAL:
                     cpu_abort(cs, "PowerPC in real mode should never raise "
@@ -1672,7 +1753,7 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
                 } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
                            (env->mmu_model == POWERPC_MMU_BOOKE206)) {
                     env->spr[SPR_BOOKE_DEAR] = address;
-                    env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0;
+                    env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, rw);
                 } else {
                     env->spr[SPR_DAR] = address;
                     if (rw == 1) {
@@ -2598,6 +2679,19 @@ void helper_booke_setpid(CPUPPCState *env, uint32_t pidn, target_ulong pid)
     tlb_flush(CPU(cpu));
 }
 
+void helper_booke_set_eplc(CPUPPCState *env, target_ulong val)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+    env->spr[SPR_BOOKE_EPLC] = val & EPID_MASK;
+    tlb_flush_by_mmuidx(CPU(cpu), 1 << PPC_TLB_EPID_LOAD);
+}
+void helper_booke_set_epsc(CPUPPCState *env, target_ulong val)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+    env->spr[SPR_BOOKE_EPSC] = val & EPID_MASK;
+    tlb_flush_by_mmuidx(CPU(cpu), 1 << PPC_TLB_EPID_STORE);
+}
+
 static inline void flush_page(CPUPPCState *env, ppcmas_tlb_t *tlb)
 {
     PowerPCCPU *cpu = ppc_env_get_cpu(env);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 4e59dd5f42..c999832426 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -2579,6 +2579,26 @@ GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
 GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
 /* lwz lwzu lwzux lwzx */
 GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
+
+#define GEN_LDEPX(name, ldop, opc2, opc3)                                     \
+static void glue(gen_, name##epx)(DisasContext *ctx)                          \
+{                                                                             \
+    TCGv EA;                                                                  \
+    CHK_SV;                                                                   \
+    gen_set_access_type(ctx, ACCESS_INT);                                     \
+    EA = tcg_temp_new();                                                      \
+    gen_addr_reg_index(ctx, EA);                                              \
+    tcg_gen_qemu_ld_tl(cpu_gpr[rD(ctx->opcode)], EA, PPC_TLB_EPID_LOAD, ldop);\
+    tcg_temp_free(EA);                                                        \
+}
+
+GEN_LDEPX(lb, DEF_MEMOP(MO_UB), 0x1F, 0x02)
+GEN_LDEPX(lh, DEF_MEMOP(MO_UW), 0x1F, 0x08)
+GEN_LDEPX(lw, DEF_MEMOP(MO_UL), 0x1F, 0x00)
+#if defined(TARGET_PPC64)
+GEN_LDEPX(ld, DEF_MEMOP(MO_Q), 0x1D, 0x00)
+#endif
+
 #if defined(TARGET_PPC64)
 /* lwaux */
 GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
@@ -2760,6 +2780,27 @@ GEN_STS(stb, st8, 0x06, PPC_INTEGER);
 GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
 /* stw stwu stwux stwx */
 GEN_STS(stw, st32, 0x04, PPC_INTEGER);
+
+#define GEN_STEPX(name, stop, opc2, opc3)                                     \
+static void glue(gen_, name##epx)(DisasContext *ctx)                          \
+{                                                                             \
+    TCGv EA;                                                                  \
+    CHK_SV;                                                                   \
+    gen_set_access_type(ctx, ACCESS_INT);                                     \
+    EA = tcg_temp_new();                                                      \
+    gen_addr_reg_index(ctx, EA);                                              \
+    tcg_gen_qemu_st_tl(                                                       \
+        cpu_gpr[rD(ctx->opcode)], EA, PPC_TLB_EPID_STORE, stop);              \
+    tcg_temp_free(EA);                                                        \
+}
+
+GEN_STEPX(stb, DEF_MEMOP(MO_UB), 0x1F, 0x06)
+GEN_STEPX(sth, DEF_MEMOP(MO_UW), 0x1F, 0x0C)
+GEN_STEPX(stw, DEF_MEMOP(MO_UL), 0x1F, 0x04)
+#if defined(TARGET_PPC64)
+GEN_STEPX(std, DEF_MEMOP(MO_Q), 0x1d, 0x04)
+#endif
+
 #if defined(TARGET_PPC64)
 GEN_STUX(std, st64_i64, 0x15, 0x05, PPC_64B);
 GEN_STX(std, st64_i64, 0x15, 0x04, PPC_64B);
@@ -4392,6 +4433,19 @@ static void gen_dcbf(DisasContext *ctx)
     tcg_temp_free(t0);
 }
 
+/* dcbfep (external PID dcbf) */
+static void gen_dcbfep(DisasContext *ctx)
+{
+    /* XXX: specification says this is treated as a load by the MMU */
+    TCGv t0;
+    CHK_SV;
+    gen_set_access_type(ctx, ACCESS_CACHE);
+    t0 = tcg_temp_new();
+    gen_addr_reg_index(ctx, t0);
+    tcg_gen_qemu_ld_tl(t0, t0, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_UB));
+    tcg_temp_free(t0);
+}
+
 /* dcbi (Supervisor only) */
 static void gen_dcbi(DisasContext *ctx)
 {
@@ -4425,6 +4479,18 @@ static void gen_dcbst(DisasContext *ctx)
     tcg_temp_free(t0);
 }
 
+/* dcbstep (dcbstep External PID version) */
+static void gen_dcbstep(DisasContext *ctx)
+{
+    /* XXX: specification say this is treated as a load by the MMU */
+    TCGv t0;
+    gen_set_access_type(ctx, ACCESS_CACHE);
+    t0 = tcg_temp_new();
+    gen_addr_reg_index(ctx, t0);
+    tcg_gen_qemu_ld_tl(t0, t0, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_UB));
+    tcg_temp_free(t0);
+}
+
 /* dcbt */
 static void gen_dcbt(DisasContext *ctx)
 {
@@ -4434,6 +4500,15 @@ static void gen_dcbt(DisasContext *ctx)
      */
 }
 
+/* dcbtep */
+static void gen_dcbtep(DisasContext *ctx)
+{
+    /* interpreted as no-op */
+    /* XXX: specification say this is treated as a load by the MMU
+     *      but does not generate any exception
+     */
+}
+
 /* dcbtst */
 static void gen_dcbtst(DisasContext *ctx)
 {
@@ -4443,6 +4518,15 @@ static void gen_dcbtst(DisasContext *ctx)
      */
 }
 
+/* dcbtstep */
+static void gen_dcbtstep(DisasContext *ctx)
+{
+    /* interpreted as no-op */
+    /* XXX: specification say this is treated as a load by the MMU
+     *      but does not generate any exception
+     */
+}
+
 /* dcbtls */
 static void gen_dcbtls(DisasContext *ctx)
 {
@@ -4469,6 +4553,21 @@ static void gen_dcbz(DisasContext *ctx)
     tcg_temp_free_i32(tcgv_op);
 }
 
+/* dcbzep */
+static void gen_dcbzep(DisasContext *ctx)
+{
+    TCGv tcgv_addr;
+    TCGv_i32 tcgv_op;
+
+    gen_set_access_type(ctx, ACCESS_CACHE);
+    tcgv_addr = tcg_temp_new();
+    tcgv_op = tcg_const_i32(ctx->opcode & 0x03FF000);
+    gen_addr_reg_index(ctx, tcgv_addr);
+    gen_helper_dcbzep(cpu_env, tcgv_addr, tcgv_op);
+    tcg_temp_free(tcgv_addr);
+    tcg_temp_free_i32(tcgv_op);
+}
+
 /* dst / dstt */
 static void gen_dst(DisasContext *ctx)
 {
@@ -4507,6 +4606,17 @@ static void gen_icbi(DisasContext *ctx)
     tcg_temp_free(t0);
 }
 
+/* icbiep */
+static void gen_icbiep(DisasContext *ctx)
+{
+    TCGv t0;
+    gen_set_access_type(ctx, ACCESS_CACHE);
+    t0 = tcg_temp_new();
+    gen_addr_reg_index(ctx, t0);
+    gen_helper_icbiep(cpu_env, t0);
+    tcg_temp_free(t0);
+}
+
 /* Optional: */
 /* dcba */
 static void gen_dcba(DisasContext *ctx)
@@ -6774,16 +6884,22 @@ GEN_HANDLER_E(mcrxrx, 0x1F, 0x00, 0x12, 0x007FF801, PPC_NONE, PPC2_ISA300),
 GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001EF801, PPC_MISC),
 GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000000, PPC_MISC),
 GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE),
+GEN_HANDLER_E(dcbfep, 0x1F, 0x1F, 0x03, 0x03C00001, PPC_NONE, PPC2_BOOKE206),
 GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE),
 GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE),
+GEN_HANDLER_E(dcbstep, 0x1F, 0x1F, 0x01, 0x03E00001, PPC_NONE, PPC2_BOOKE206),
 GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x00000001, PPC_CACHE),
+GEN_HANDLER_E(dcbtep, 0x1F, 0x1F, 0x09, 0x00000001, PPC_NONE, PPC2_BOOKE206),
 GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x00000001, PPC_CACHE),
+GEN_HANDLER_E(dcbtstep, 0x1F, 0x1F, 0x07, 0x00000001, PPC_NONE, PPC2_BOOKE206),
 GEN_HANDLER_E(dcbtls, 0x1F, 0x06, 0x05, 0x02000001, PPC_BOOKE, PPC2_BOOKE206),
 GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZ),
+GEN_HANDLER_E(dcbzep, 0x1F, 0x1F, 0x1F, 0x03C00001, PPC_NONE, PPC2_BOOKE206),
 GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC),
 GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x01800001, PPC_ALTIVEC),
 GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC),
 GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI),
+GEN_HANDLER_E(icbiep, 0x1F, 0x1F, 0x1E, 0x03E00001, PPC_NONE, PPC2_BOOKE206),
 GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA),
 GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT),
 GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT),
@@ -7086,6 +7202,19 @@ GEN_LDX_HVRM(lbzcix, ld8u, 0x15, 0x1a, PPC_CILDST)
 GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER)
 GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER)
 
+/* External PID based load */
+#undef GEN_LDEPX
+#define GEN_LDEPX(name, ldop, opc2, opc3)                                     \
+GEN_HANDLER_E(name##epx, 0x1F, opc2, opc3,                                    \
+              0x00000001, PPC_NONE, PPC2_BOOKE206),
+
+GEN_LDEPX(lb, DEF_MEMOP(MO_UB), 0x1F, 0x02)
+GEN_LDEPX(lh, DEF_MEMOP(MO_UW), 0x1F, 0x08)
+GEN_LDEPX(lw, DEF_MEMOP(MO_UL), 0x1F, 0x00)
+#if defined(TARGET_PPC64)
+GEN_LDEPX(ld, DEF_MEMOP(MO_Q), 0x1D, 0x00)
+#endif
+
 #undef GEN_ST
 #undef GEN_STU
 #undef GEN_STUX
@@ -7120,6 +7249,18 @@ GEN_STX_HVRM(stbcix, st8, 0x15, 0x1e, PPC_CILDST)
 GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER)
 GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER)
 
+#undef GEN_STEPX
+#define GEN_STEPX(name, ldop, opc2, opc3)                                     \
+GEN_HANDLER_E(name##epx, 0x1F, opc2, opc3,                                    \
+              0x00000001, PPC_NONE, PPC2_BOOKE206),
+
+GEN_STEPX(stb, DEF_MEMOP(MO_UB), 0x1F, 0x06)
+GEN_STEPX(sth, DEF_MEMOP(MO_UW), 0x1F, 0x0C)
+GEN_STEPX(stw, DEF_MEMOP(MO_UL), 0x1F, 0x04)
+#if defined(TARGET_PPC64)
+GEN_STEPX(std, DEF_MEMOP(MO_Q), 0x1D, 0x04)
+#endif
+
 #undef GEN_CRLOGIC
 #define GEN_CRLOGIC(name, tcg_op, opc)                                        \
 GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)
diff --git a/target/ppc/translate/fp-impl.inc.c b/target/ppc/translate/fp-impl.inc.c
index a6f522b85c..08770ba9f5 100644
--- a/target/ppc/translate/fp-impl.inc.c
+++ b/target/ppc/translate/fp-impl.inc.c
@@ -673,6 +673,23 @@ GEN_LDFS(lfd, ld64_i64, 0x12, PPC_FLOAT);
  /* lfs lfsu lfsux lfsx */
 GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
 
+/* lfdepx (external PID lfdx) */
+static void gen_lfdepx(DisasContext *ctx)
+{
+    TCGv EA;
+    CHK_SV;
+    if (unlikely(!ctx->fpu_enabled)) {
+        gen_exception(ctx, POWERPC_EXCP_FPU);
+        return;
+    }
+    gen_set_access_type(ctx, ACCESS_FLOAT);
+    EA = tcg_temp_new();
+    gen_addr_reg_index(ctx, EA);
+    tcg_gen_qemu_ld_i64(cpu_fpr[rD(ctx->opcode)], EA, PPC_TLB_EPID_LOAD,
+        DEF_MEMOP(MO_Q));
+    tcg_temp_free(EA);
+}
+
 /* lfdp */
 static void gen_lfdp(DisasContext *ctx)
 {
@@ -846,6 +863,23 @@ GEN_STFS(stfd, st64_i64, 0x16, PPC_FLOAT);
 /* stfs stfsu stfsux stfsx */
 GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
 
+/* stfdepx (external PID lfdx) */
+static void gen_stfdepx(DisasContext *ctx)
+{
+    TCGv EA;
+    CHK_SV;
+    if (unlikely(!ctx->fpu_enabled)) {
+        gen_exception(ctx, POWERPC_EXCP_FPU);
+        return;
+    }
+    gen_set_access_type(ctx, ACCESS_FLOAT);
+    EA = tcg_temp_new();
+    gen_addr_reg_index(ctx, EA);
+    tcg_gen_qemu_st_i64(cpu_fpr[rD(ctx->opcode)], EA, PPC_TLB_EPID_STORE,
+                       DEF_MEMOP(MO_Q));
+    tcg_temp_free(EA);
+}
+
 /* stfdp */
 static void gen_stfdp(DisasContext *ctx)
 {
diff --git a/target/ppc/translate/fp-ops.inc.c b/target/ppc/translate/fp-ops.inc.c
index 3c6d05a074..621f6bfe0c 100644
--- a/target/ppc/translate/fp-ops.inc.c
+++ b/target/ppc/translate/fp-ops.inc.c
@@ -66,6 +66,7 @@ GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
 
 GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT)
 GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT)
+GEN_HANDLER_E(lfdepx, 0x1F, 0x1F, 0x12, 0x00000001, PPC_NONE, PPC2_BOOKE206),
 GEN_HANDLER_E(lfiwax, 0x1f, 0x17, 0x1a, 0x00000001, PPC_NONE, PPC2_ISA205),
 GEN_HANDLER_E(lfiwzx, 0x1f, 0x17, 0x1b, 0x1, PPC_NONE, PPC2_FP_CVT_ISA206),
 GEN_HANDLER_E(lfdpx, 0x1F, 0x17, 0x18, 0x00200001, PPC_NONE, PPC2_ISA205),
@@ -87,6 +88,7 @@ GEN_STXF(name, stop, 0x17, op | 0x00, type)
 GEN_STFS(stfd, st64_i64, 0x16, PPC_FLOAT)
 GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT)
 GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX)
+GEN_HANDLER_E(stfdepx, 0x1F, 0x1F, 0x16, 0x00000001, PPC_NONE, PPC2_BOOKE206),
 GEN_HANDLER_E(stfdpx, 0x1F, 0x17, 0x1C, 0x00200001, PPC_NONE, PPC2_ISA205),
 
 GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES),
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index ee9432eb15..9a2d4a9835 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -1653,6 +1653,15 @@ static void spr_write_booke_pid(DisasContext *ctx, int sprn, int gprn)
     gen_helper_booke_setpid(cpu_env, t0, cpu_gpr[gprn]);
     tcg_temp_free_i32(t0);
 }
+static void spr_write_eplc(DisasContext *ctx, int sprn, int gprn)
+{
+    gen_helper_booke_set_eplc(cpu_env, cpu_gpr[gprn]);
+}
+static void spr_write_epsc(DisasContext *ctx, int sprn, int gprn)
+{
+    gen_helper_booke_set_epsc(cpu_env, cpu_gpr[gprn]);
+}
+
 #endif
 
 static void gen_spr_usprg3(CPUPPCState *env)
@@ -1912,6 +1921,16 @@ static void gen_spr_BookE206(CPUPPCState *env, uint32_t mas_mask,
                      &spr_read_generic, &spr_write_booke_pid,
                      0x00000000);
     }
+
+    spr_register(env, SPR_BOOKE_EPLC, "EPLC",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_eplc,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_EPSC, "EPSC",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_epsc,
+                 0x00000000);
+
     /* XXX : not implemented */
     spr_register(env, SPR_MMUCFG, "MMUCFG",
                  SPR_NOACCESS, SPR_NOACCESS,
@@ -2797,8 +2816,6 @@ static void gen_spr_8xx(CPUPPCState *env)
  * perf    => 768-783 (Power 2.04)
  * perf    => 784-799 (Power 2.04)
  * PPR     => SPR 896 (Power 2.04)
- * EPLC    => SPR 947 (Power 2.04 emb)
- * EPSC    => SPR 948 (Power 2.04 emb)
  * DABRX   => 1015    (Power 2.04 hypv)
  * FPECR   => SPR 1022 (?)
  * ... and more (thermal management, performance counters, ...)
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 02/22] ppc440_pcix: convert SysBus init method to a realize method
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 01/22] target/ppc: add external PID support David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 03/22] ppc4xx_pci: " David Gibson
                   ` (20 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier,
	Cédric Le Goater, David Gibson

From: Cédric Le Goater <clg@kaod.org>

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/ppc440_pcix.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/hw/ppc/ppc440_pcix.c b/hw/ppc/ppc440_pcix.c
index 64ed07afa6..42ef76b6f5 100644
--- a/hw/ppc/ppc440_pcix.c
+++ b/hw/ppc/ppc440_pcix.c
@@ -466,17 +466,18 @@ const MemoryRegionOps ppc440_pcix_host_data_ops = {
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
-static int ppc440_pcix_initfn(SysBusDevice *dev)
+static void ppc440_pcix_realize(DeviceState *dev, Error **errp)
 {
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
     PPC440PCIXState *s;
     PCIHostState *h;
 
     h = PCI_HOST_BRIDGE(dev);
     s = PPC440_PCIX_HOST_BRIDGE(dev);
 
-    sysbus_init_irq(dev, &s->irq);
+    sysbus_init_irq(sbd, &s->irq);
     memory_region_init(&s->busmem, OBJECT(dev), "pci bus memory", UINT64_MAX);
-    h->bus = pci_register_root_bus(DEVICE(dev), NULL, ppc440_pcix_set_irq,
+    h->bus = pci_register_root_bus(dev, NULL, ppc440_pcix_set_irq,
                          ppc440_pcix_map_irq, &s->irq, &s->busmem,
                          get_system_io(), PCI_DEVFN(0, 0), 1, TYPE_PCI_BUS);
 
@@ -497,17 +498,14 @@ static int ppc440_pcix_initfn(SysBusDevice *dev)
     memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem);
     memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem);
     memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->iomem);
-    sysbus_init_mmio(dev, &s->container);
-
-    return 0;
+    sysbus_init_mmio(sbd, &s->container);
 }
 
 static void ppc440_pcix_class_init(ObjectClass *klass, void *data)
 {
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    k->init = ppc440_pcix_initfn;
+    dc->realize = ppc440_pcix_realize;
     dc->reset = ppc440_pcix_reset;
 }
 
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 03/22] ppc4xx_pci: convert SysBus init method to a realize method
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 01/22] target/ppc: add external PID support David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 02/22] ppc440_pcix: convert SysBus init method to a realize method David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 04/22] PPC: e500: " David Gibson
                   ` (19 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier,
	Cédric Le Goater, David Gibson

From: Cédric Le Goater <clg@kaod.org>

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/ppc4xx_pci.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c
index b7642bac01..86981be710 100644
--- a/hw/ppc/ppc4xx_pci.c
+++ b/hw/ppc/ppc4xx_pci.c
@@ -300,8 +300,9 @@ static const VMStateDescription vmstate_ppc4xx_pci = {
 };
 
 /* XXX Interrupt acknowledge cycles not supported. */
-static int ppc4xx_pcihost_initfn(SysBusDevice *dev)
+static void ppc4xx_pcihost_realize(DeviceState *dev, Error **errp)
 {
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
     PPC4xxPCIState *s;
     PCIHostState *h;
     PCIBus *b;
@@ -311,10 +312,10 @@ static int ppc4xx_pcihost_initfn(SysBusDevice *dev)
     s = PPC4xx_PCI_HOST_BRIDGE(dev);
 
     for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
-        sysbus_init_irq(dev, &s->irq[i]);
+        sysbus_init_irq(sbd, &s->irq[i]);
     }
 
-    b = pci_register_root_bus(DEVICE(dev), NULL, ppc4xx_pci_set_irq,
+    b = pci_register_root_bus(dev, NULL, ppc4xx_pci_set_irq,
                               ppc4xx_pci_map_irq, s->irq, get_system_memory(),
                               get_system_io(), 0, 4, TYPE_PCI_BUS);
     h->bus = b;
@@ -332,10 +333,8 @@ static int ppc4xx_pcihost_initfn(SysBusDevice *dev)
     memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem);
     memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem);
     memory_region_add_subregion(&s->container, PCI_REG_BASE, &s->iomem);
-    sysbus_init_mmio(dev, &s->container);
+    sysbus_init_mmio(sbd, &s->container);
     qemu_register_reset(ppc4xx_pci_reset, s);
-
-    return 0;
 }
 
 static void ppc4xx_host_bridge_class_init(ObjectClass *klass, void *data)
@@ -367,10 +366,9 @@ static const TypeInfo ppc4xx_host_bridge_info = {
 
 static void ppc4xx_pcihost_class_init(ObjectClass *klass, void *data)
 {
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    k->init = ppc4xx_pcihost_initfn;
+    dc->realize = ppc4xx_pcihost_realize;
     dc->vmsd = &vmstate_ppc4xx_pci;
 }
 
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 04/22] PPC: e500: convert SysBus init method to a realize method
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (2 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 03/22] ppc4xx_pci: " David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 05/22] hw/ppc/spapr_rng: Introduce CONFIG_SPAPR_RNG switch for spapr_rng.c David Gibson
                   ` (18 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier,
	Cédric Le Goater, David Gibson

From: Cédric Le Goater <clg@kaod.org>

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Greg Kurz <groug@kaod.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/pci-host/ppce500.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c
index eb75e080fc..b8f8c112e6 100644
--- a/hw/pci-host/ppce500.c
+++ b/hw/pci-host/ppce500.c
@@ -436,8 +436,9 @@ static AddressSpace *e500_pcihost_set_iommu(PCIBus *bus, void *opaque,
     return &s->bm_as;
 }
 
-static int e500_pcihost_initfn(SysBusDevice *dev)
+static void e500_pcihost_realize(DeviceState *dev, Error **errp)
 {
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
     PCIHostState *h;
     PPCE500PCIState *s;
     PCIBus *b;
@@ -447,7 +448,7 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
     s = PPC_E500_PCI_HOST_BRIDGE(dev);
 
     for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
-        sysbus_init_irq(dev, &s->irq[i]);
+        sysbus_init_irq(sbd, &s->irq[i]);
     }
 
     for (i = 0; i < PCI_NUM_PINS; i++) {
@@ -460,7 +461,7 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
     /* PIO lives at the bottom of our bus space */
     memory_region_add_subregion_overlap(&s->busmem, 0, &s->pio, -2);
 
-    b = pci_register_root_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq,
+    b = pci_register_root_bus(dev, NULL, mpc85xx_pci_set_irq,
                               mpc85xx_pci_map_irq, s, &s->busmem, &s->pio,
                               PCI_DEVFN(s->first_slot, 0), 4, TYPE_PCI_BUS);
     h->bus = b;
@@ -483,10 +484,8 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
     memory_region_add_subregion(&s->container, PCIE500_CFGADDR, &h->conf_mem);
     memory_region_add_subregion(&s->container, PCIE500_CFGDATA, &h->data_mem);
     memory_region_add_subregion(&s->container, PCIE500_REG_BASE, &s->iomem);
-    sysbus_init_mmio(dev, &s->container);
+    sysbus_init_mmio(sbd, &s->container);
     pci_bus_set_route_irq_fn(b, e500_route_intx_pin_to_irq);
-
-    return 0;
 }
 
 static void e500_host_bridge_class_init(ObjectClass *klass, void *data)
@@ -526,9 +525,8 @@ static Property pcihost_properties[] = {
 static void e500_pcihost_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = e500_pcihost_initfn;
+    dc->realize = e500_pcihost_realize;
     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
     dc->props = pcihost_properties;
     dc->vmsd = &vmstate_ppce500_pci;
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 05/22] hw/ppc/spapr_rng: Introduce CONFIG_SPAPR_RNG switch for spapr_rng.c
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (3 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 04/22] PPC: e500: " David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 06/22] target/ppc: Split up float_invalid_op_excp David Gibson
                   ` (17 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier, Thomas Huth, David Gibson

From: Thomas Huth <thuth@redhat.com>

The spapr-rng device is suboptimal when compared to virtio-rng, so
users might want to disable it in their builds. Thus let's introduce
a proper CONFIG switch to allow us to compile QEMU without this device.
The function spapr_rng_populate_dt is required for linking, so move it
to a different location.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 default-configs/ppc64-softmmu.mak |  1 +
 hw/ppc/Makefile.objs              |  3 ++-
 hw/ppc/spapr.c                    | 23 +++++++++++++++++++++++
 hw/ppc/spapr_rng.c                | 23 -----------------------
 include/hw/ppc/spapr.h            |  2 --
 5 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
index f550573782..aec2855750 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -18,3 +18,4 @@ CONFIG_XICS_SPAPR=$(CONFIG_PSERIES)
 CONFIG_XICS_KVM=$(call land,$(CONFIG_PSERIES),$(CONFIG_KVM))
 CONFIG_MEM_DEVICE=y
 CONFIG_DIMM=y
+CONFIG_SPAPR_RNG=y
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 4ab5564672..4e0c1c0941 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -3,8 +3,9 @@ obj-y += ppc.o ppc_booke.o fdt.o
 # IBM pSeries (sPAPR)
 obj-$(CONFIG_PSERIES) += spapr.o spapr_caps.o spapr_vio.o spapr_events.o
 obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
-obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o spapr_drc.o spapr_rng.o
+obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o spapr_drc.o
 obj-$(CONFIG_PSERIES) += spapr_cpu_core.o spapr_ovec.o spapr_irq.o
+obj-$(CONFIG_SPAPR_RNG) +=  spapr_rng.o
 # IBM PowerNV
 obj-$(CONFIG_POWERNV) += pnv.o pnv_xscom.o pnv_core.o pnv_lpc.o pnv_psi.o pnv_occ.o pnv_bmc.o
 ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index c08130facb..e47b004b61 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -610,6 +610,29 @@ static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr)
     g_free(rev);
 }
 
+static int spapr_rng_populate_dt(void *fdt)
+{
+    int node;
+    int ret;
+
+    node = qemu_fdt_add_subnode(fdt, "/ibm,platform-facilities");
+    if (node <= 0) {
+        return -1;
+    }
+    ret = fdt_setprop_string(fdt, node, "device_type",
+                             "ibm,platform-facilities");
+    ret |= fdt_setprop_cell(fdt, node, "#address-cells", 0x1);
+    ret |= fdt_setprop_cell(fdt, node, "#size-cells", 0x0);
+
+    node = fdt_add_subnode(fdt, node, "ibm,random-v1");
+    if (node <= 0) {
+        return -1;
+    }
+    ret |= fdt_setprop_string(fdt, node, "compatible", "ibm,random");
+
+    return ret ? -1 : 0;
+}
+
 static uint32_t spapr_pc_dimm_node(MemoryDeviceInfoList *list, ram_addr_t addr)
 {
     MemoryDeviceInfoList *info;
diff --git a/hw/ppc/spapr_rng.c b/hw/ppc/spapr_rng.c
index d2acd61a15..644bac96f8 100644
--- a/hw/ppc/spapr_rng.c
+++ b/hw/ppc/spapr_rng.c
@@ -132,29 +132,6 @@ static void spapr_rng_realize(DeviceState *dev, Error **errp)
     }
 }
 
-int spapr_rng_populate_dt(void *fdt)
-{
-    int node;
-    int ret;
-
-    node = qemu_fdt_add_subnode(fdt, "/ibm,platform-facilities");
-    if (node <= 0) {
-        return -1;
-    }
-    ret = fdt_setprop_string(fdt, node, "device_type",
-                             "ibm,platform-facilities");
-    ret |= fdt_setprop_cell(fdt, node, "#address-cells", 0x1);
-    ret |= fdt_setprop_cell(fdt, node, "#size-cells", 0x0);
-
-    node = fdt_add_subnode(fdt, node, "ibm,random-v1");
-    if (node <= 0) {
-        return -1;
-    }
-    ret |= fdt_setprop_string(fdt, node, "compatible", "ibm,random");
-
-    return ret ? -1 : 0;
-}
-
 static Property spapr_rng_properties[] = {
     DEFINE_PROP_BOOL("use-kvm", sPAPRRngState, use_kvm, false),
     DEFINE_PROP_LINK("rng", sPAPRRngState, backend, TYPE_RNG_BACKEND,
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index ad4d7cfd97..0805ad85a1 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -745,8 +745,6 @@ int spapr_rtc_import_offset(sPAPRRTCState *rtc, int64_t legacy_offset);
 
 #define TYPE_SPAPR_RNG "spapr-rng"
 
-int spapr_rng_populate_dt(void *fdt);
-
 #define SPAPR_MEMORY_BLOCK_SIZE (1 << 28) /* 256MB */
 
 /*
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 06/22] target/ppc: Split up float_invalid_op_excp
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (4 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 05/22] hw/ppc/spapr_rng: Introduce CONFIG_SPAPR_RNG switch for spapr_rng.c David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 07/22] target/ppc: Remove float_check_status David Gibson
                   ` (16 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier, Richard Henderson,
	David Gibson

From: Richard Henderson <richard.henderson@linaro.org>

The always_inline trick only works if the function is always
called from the outer-most helper.  But it isn't, so pass in
the outer-most return address.  There's no need for a switch
statement whose argument is always a constant.  Unravel the
switch and goto via more helpers.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 target/ppc/fpu_helper.c | 344 +++++++++++++++++++++-------------------
 1 file changed, 181 insertions(+), 163 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index b9bb1b856e..6ec5227dd5 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -170,96 +170,120 @@ COMPUTE_FPRF(float64)
 COMPUTE_FPRF(float128)
 
 /* Floating-point invalid operations exception */
-static inline __attribute__((__always_inline__))
-uint64_t float_invalid_op_excp(CPUPPCState *env, int op, int set_fpcc)
+static void finish_invalid_op_excp(CPUPPCState *env, int op, uintptr_t retaddr)
 {
-    CPUState *cs = CPU(ppc_env_get_cpu(env));
-    uint64_t ret = 0;
-    int ve;
+    /* Update the floating-point invalid operation summary */
+    env->fpscr |= 1 << FPSCR_VX;
+    /* Update the floating-point exception summary */
+    env->fpscr |= FP_FX;
+    if (fpscr_ve != 0) {
+        /* Update the floating-point enabled exception summary */
+        env->fpscr |= 1 << FPSCR_FEX;
+        if (fp_exceptions_enabled(env)) {
+            raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
+                                   POWERPC_EXCP_FP | op, retaddr);
+        }
+    }
+}
 
-    ve = fpscr_ve;
-    switch (op) {
-    case POWERPC_EXCP_FP_VXSNAN:
-        env->fpscr |= 1 << FPSCR_VXSNAN;
-        break;
-    case POWERPC_EXCP_FP_VXSOFT:
-        env->fpscr |= 1 << FPSCR_VXSOFT;
-        break;
-    case POWERPC_EXCP_FP_VXISI:
-        /* Magnitude subtraction of infinities */
-        env->fpscr |= 1 << FPSCR_VXISI;
-        goto update_arith;
-    case POWERPC_EXCP_FP_VXIDI:
-        /* Division of infinity by infinity */
-        env->fpscr |= 1 << FPSCR_VXIDI;
-        goto update_arith;
-    case POWERPC_EXCP_FP_VXZDZ:
-        /* Division of zero by zero */
-        env->fpscr |= 1 << FPSCR_VXZDZ;
-        goto update_arith;
-    case POWERPC_EXCP_FP_VXIMZ:
-        /* Multiplication of zero by infinity */
-        env->fpscr |= 1 << FPSCR_VXIMZ;
-        goto update_arith;
-    case POWERPC_EXCP_FP_VXVC:
-        /* Ordered comparison of NaN */
-        env->fpscr |= 1 << FPSCR_VXVC;
+static void finish_invalid_op_arith(CPUPPCState *env, int op,
+                                    bool set_fpcc, uintptr_t retaddr)
+{
+    env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
+    if (fpscr_ve == 0) {
         if (set_fpcc) {
             env->fpscr &= ~(0xF << FPSCR_FPCC);
             env->fpscr |= 0x11 << FPSCR_FPCC;
         }
-        /* We must update the target FPR before raising the exception */
-        if (ve != 0) {
-            cs->exception_index = POWERPC_EXCP_PROGRAM;
-            env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC;
-            /* Update the floating-point enabled exception summary */
-            env->fpscr |= 1 << FPSCR_FEX;
-            /* Exception is differed */
-            ve = 0;
-        }
-        break;
-    case POWERPC_EXCP_FP_VXSQRT:
-        /* Square root of a negative number */
-        env->fpscr |= 1 << FPSCR_VXSQRT;
-    update_arith:
-        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
-        if (ve == 0) {
-            /* Set the result to quiet NaN */
-            ret = 0x7FF8000000000000ULL;
-            if (set_fpcc) {
-                env->fpscr &= ~(0xF << FPSCR_FPCC);
-                env->fpscr |= 0x11 << FPSCR_FPCC;
-            }
-        }
-        break;
-    case POWERPC_EXCP_FP_VXCVI:
-        /* Invalid conversion */
-        env->fpscr |= 1 << FPSCR_VXCVI;
-        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
-        if (ve == 0) {
-            /* Set the result to quiet NaN */
-            ret = 0x7FF8000000000000ULL;
-            if (set_fpcc) {
-                env->fpscr &= ~(0xF << FPSCR_FPCC);
-                env->fpscr |= 0x11 << FPSCR_FPCC;
-            }
-        }
-        break;
+    }
+    finish_invalid_op_excp(env, op, retaddr);
+}
+
+/* Signalling NaN */
+static void float_invalid_op_vxsnan(CPUPPCState *env, uintptr_t retaddr)
+{
+    env->fpscr |= 1 << FPSCR_VXSNAN;
+    finish_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, retaddr);
+}
+
+/* Magnitude subtraction of infinities */
+static void float_invalid_op_vxisi(CPUPPCState *env, bool set_fpcc,
+                                   uintptr_t retaddr)
+{
+    env->fpscr |= 1 << FPSCR_VXISI;
+    finish_invalid_op_arith(env, POWERPC_EXCP_FP_VXISI, set_fpcc, retaddr);
+}
+
+/* Division of infinity by infinity */
+static void float_invalid_op_vxidi(CPUPPCState *env, bool set_fpcc,
+                                   uintptr_t retaddr)
+{
+    env->fpscr |= 1 << FPSCR_VXIDI;
+    finish_invalid_op_arith(env, POWERPC_EXCP_FP_VXIDI, set_fpcc, retaddr);
+}
+
+/* Division of zero by zero */
+static void float_invalid_op_vxzdz(CPUPPCState *env, bool set_fpcc,
+                                   uintptr_t retaddr)
+{
+    env->fpscr |= 1 << FPSCR_VXZDZ;
+    finish_invalid_op_arith(env, POWERPC_EXCP_FP_VXZDZ, set_fpcc, retaddr);
+}
+
+/* Multiplication of zero by infinity */
+static void float_invalid_op_vximz(CPUPPCState *env, bool set_fpcc,
+                                   uintptr_t retaddr)
+{
+    env->fpscr |= 1 << FPSCR_VXIMZ;
+    finish_invalid_op_arith(env, POWERPC_EXCP_FP_VXIMZ, set_fpcc, retaddr);
+}
+
+/* Square root of a negative number */
+static void float_invalid_op_vxsqrt(CPUPPCState *env, bool set_fpcc,
+                                    uintptr_t retaddr)
+{
+    env->fpscr |= 1 << FPSCR_VXSQRT;
+    finish_invalid_op_arith(env, POWERPC_EXCP_FP_VXSQRT, set_fpcc, retaddr);
+}
+
+/* Ordered comparison of NaN */
+static void float_invalid_op_vxvc(CPUPPCState *env, bool set_fpcc,
+                                  uintptr_t retaddr)
+{
+    env->fpscr |= 1 << FPSCR_VXVC;
+    if (set_fpcc) {
+        env->fpscr &= ~(0xF << FPSCR_FPCC);
+        env->fpscr |= 0x11 << FPSCR_FPCC;
     }
     /* Update the floating-point invalid operation summary */
     env->fpscr |= 1 << FPSCR_VX;
     /* Update the floating-point exception summary */
     env->fpscr |= FP_FX;
-    if (ve != 0) {
+    /* We must update the target FPR before raising the exception */
+    if (fpscr_ve != 0) {
+        CPUState *cs = CPU(ppc_env_get_cpu(env));
+
+        cs->exception_index = POWERPC_EXCP_PROGRAM;
+        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC;
         /* Update the floating-point enabled exception summary */
         env->fpscr |= 1 << FPSCR_FEX;
-        if (fp_exceptions_enabled(env)) {
-            /* GETPC() works here because this is inline */
-            raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
-                                   POWERPC_EXCP_FP | op, GETPC());
+        /* Exception is differed */
+    }
+}
+
+/* Invalid conversion */
+static void float_invalid_op_vxcvi(CPUPPCState *env, bool set_fpcc,
+                                   uintptr_t retaddr)
+{
+    env->fpscr |= 1 << FPSCR_VXCVI;
+    env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
+    if (fpscr_ve == 0) {
+        if (set_fpcc) {
+            env->fpscr &= ~(0xF << FPSCR_FPCC);
+            env->fpscr |= 0x11 << FPSCR_FPCC;
         }
     }
-    return ret;
+    finish_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, retaddr);
 }
 
 static inline void float_zero_divide_excp(CPUPPCState *env, uintptr_t raddr)
@@ -632,11 +656,11 @@ float64 helper_fadd(CPUPPCState *env, float64 arg1, float64 arg2)
     if (unlikely(status & float_flag_invalid)) {
         if (float64_is_infinity(arg1) && float64_is_infinity(arg2)) {
             /* Magnitude subtraction of infinities */
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
+            float_invalid_op_vxisi(env, 1, GETPC());
         } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
                    float64_is_signaling_nan(arg2, &env->fp_status)) {
             /* sNaN addition */
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+            float_invalid_op_vxsnan(env, GETPC());
         }
     }
 
@@ -652,11 +676,11 @@ float64 helper_fsub(CPUPPCState *env, float64 arg1, float64 arg2)
     if (unlikely(status & float_flag_invalid)) {
         if (float64_is_infinity(arg1) && float64_is_infinity(arg2)) {
             /* Magnitude subtraction of infinities */
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
+            float_invalid_op_vxisi(env, 1, GETPC());
         } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
                    float64_is_signaling_nan(arg2, &env->fp_status)) {
             /* sNaN addition */
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+            float_invalid_op_vxsnan(env, GETPC());
         }
     }
 
@@ -673,11 +697,11 @@ float64 helper_fmul(CPUPPCState *env, float64 arg1, float64 arg2)
         if ((float64_is_infinity(arg1) && float64_is_zero(arg2)) ||
             (float64_is_zero(arg1) && float64_is_infinity(arg2))) {
             /* Multiplication of zero by infinity */
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
+            float_invalid_op_vximz(env, 1, GETPC());
         } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
                    float64_is_signaling_nan(arg2, &env->fp_status)) {
             /* sNaN multiplication */
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+            float_invalid_op_vxsnan(env, GETPC());
         }
     }
 
@@ -695,14 +719,14 @@ float64 helper_fdiv(CPUPPCState *env, float64 arg1, float64 arg2)
             /* Determine what kind of invalid operation was seen.  */
             if (float64_is_infinity(arg1) && float64_is_infinity(arg2)) {
                 /* Division of infinity by infinity */
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, 1);
+                float_invalid_op_vxidi(env, 1, GETPC());
             } else if (float64_is_zero(arg1) && float64_is_zero(arg2)) {
                 /* Division of zero by zero */
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, 1);
+                float_invalid_op_vxzdz(env, 1, GETPC());
             } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
                        float64_is_signaling_nan(arg2, &env->fp_status)) {
                 /* sNaN division */
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+                float_invalid_op_vxsnan(env, GETPC());
             }
         }
         if (status & float_flag_divbyzero) {
@@ -724,14 +748,14 @@ uint64_t helper_##op(CPUPPCState *env, uint64_t arg)                   \
                                                                        \
     if (unlikely(env->fp_status.float_exception_flags)) {              \
         if (float64_is_any_nan(arg)) {                                 \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);      \
+            float_invalid_op_vxcvi(env, 1, GETPC());                   \
             if (float64_is_signaling_nan(arg, &env->fp_status)) {      \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); \
+                float_invalid_op_vxsnan(env, GETPC());                 \
             }                                                          \
             farg.ll = nanval;                                          \
         } else if (env->fp_status.float_exception_flags &              \
                    float_flag_invalid) {                               \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);      \
+            float_invalid_op_vxcvi(env, 1, GETPC());                   \
         }                                                              \
         float_check_status(env);                                       \
     }                                                                  \
@@ -776,7 +800,7 @@ static inline uint64_t do_fri(CPUPPCState *env, uint64_t arg,
 
     if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
         /* sNaN round */
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+        float_invalid_op_vxsnan(env, GETPC());
         farg.ll = arg | 0x0008000000000000ULL;
     } else {
         int inexact = get_float_exception_flags(&env->fp_status) &
@@ -817,18 +841,18 @@ uint64_t helper_frim(CPUPPCState *env, uint64_t arg)
 
 #define FPU_MADDSUB_UPDATE(NAME, TP)                                    \
 static void NAME(CPUPPCState *env, TP arg1, TP arg2, TP arg3,           \
-                 unsigned int madd_flags)                               \
+                 unsigned int madd_flags, uintptr_t retaddr)            \
 {                                                                       \
     if (TP##_is_signaling_nan(arg1, &env->fp_status) ||                 \
         TP##_is_signaling_nan(arg2, &env->fp_status) ||                 \
         TP##_is_signaling_nan(arg3, &env->fp_status)) {                 \
         /* sNaN operation */                                            \
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);          \
+        float_invalid_op_vxsnan(env, retaddr);                          \
     }                                                                   \
     if ((TP##_is_infinity(arg1) && TP##_is_zero(arg2)) ||               \
         (TP##_is_zero(arg1) && TP##_is_infinity(arg2))) {               \
         /* Multiplication of zero by infinity */                        \
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);           \
+        float_invalid_op_vximz(env, 1, retaddr);                        \
     }                                                                   \
     if ((TP##_is_infinity(arg1) || TP##_is_infinity(arg2)) &&           \
         TP##_is_infinity(arg3)) {                                       \
@@ -841,7 +865,7 @@ static void NAME(CPUPPCState *env, TP arg1, TP arg2, TP arg3,           \
             cSign ^= 1;                                                 \
         }                                                               \
         if (aSign ^ bSign ^ cSign) {                                    \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);       \
+            float_invalid_op_vxisi(env, 1, retaddr);                    \
         }                                                               \
     }                                                                   \
 }
@@ -859,7 +883,7 @@ uint64_t helper_##op(CPUPPCState *env, uint64_t arg1,                   \
     if (flags) {                                                        \
         if (flags & float_flag_invalid) {                               \
             float64_maddsub_update_excp(env, arg1, arg2, arg3,          \
-                                        madd_flags);                    \
+                                        madd_flags, GETPC());           \
         }                                                               \
         float_check_status(env);                                        \
     }                                                                   \
@@ -885,8 +909,7 @@ uint64_t helper_frsp(CPUPPCState *env, uint64_t arg)
     farg.ll = arg;
 
     if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
-        /* sNaN square root */
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+        float_invalid_op_vxsnan(env, GETPC());
     }
     f32 = float64_to_float32(farg.d, &env->fp_status);
     farg.d = float32_to_float64(f32, &env->fp_status);
@@ -904,11 +927,11 @@ float64 helper_fsqrt(CPUPPCState *env, float64 arg)
         if (unlikely(float64_is_any_nan(arg))) {
             if (unlikely(float64_is_signaling_nan(arg, &env->fp_status))) {
                 /* sNaN square root */
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+                float_invalid_op_vxsnan(env, GETPC());
             }
         } else {
             /* Square root of a negative nonzero number */
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
+            float_invalid_op_vxsqrt(env, 1, GETPC());
         }
     }
 
@@ -926,7 +949,7 @@ float64 helper_fre(CPUPPCState *env, float64 arg)
         if (status & float_flag_invalid) {
             if (float64_is_signaling_nan(arg, &env->fp_status)) {
                 /* sNaN reciprocal */
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+                float_invalid_op_vxsnan(env, GETPC());
             }
         }
         if (status & float_flag_divbyzero) {
@@ -949,7 +972,7 @@ uint64_t helper_fres(CPUPPCState *env, uint64_t arg)
 
     if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
         /* sNaN reciprocal */
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+        float_invalid_op_vxsnan(env, GETPC());
     }
     farg.d = float64_div(float64_one, farg.d, &env->fp_status);
     f32 = float64_to_float32(farg.d, &env->fp_status);
@@ -970,10 +993,10 @@ float64 helper_frsqrte(CPUPPCState *env, float64 arg)
         if (status & float_flag_invalid) {
             if (float64_is_signaling_nan(arg, &env->fp_status)) {
                 /* sNaN reciprocal */
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+                float_invalid_op_vxsnan(env, GETPC());
             } else {
                 /* Square root of a negative nonzero number */
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
+                float_invalid_op_vxsqrt(env, 1, GETPC());
             }
         }
         if (status & float_flag_divbyzero) {
@@ -1095,7 +1118,7 @@ void helper_fcmpu(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
                  && (float64_is_signaling_nan(farg1.d, &env->fp_status) ||
                      float64_is_signaling_nan(farg2.d, &env->fp_status)))) {
         /* sNaN comparison */
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+        float_invalid_op_vxsnan(env, GETPC());
     }
 }
 
@@ -1123,14 +1146,11 @@ void helper_fcmpo(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
     env->fpscr |= ret << FPSCR_FPRF;
     env->crf[crfD] = ret;
     if (unlikely(ret == 0x01UL)) {
+        float_invalid_op_vxvc(env, 1, GETPC());
         if (float64_is_signaling_nan(farg1.d, &env->fp_status) ||
             float64_is_signaling_nan(farg2.d, &env->fp_status)) {
             /* sNaN comparison */
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
-                                  POWERPC_EXCP_FP_VXVC, 1);
-        } else {
-            /* qNaN comparison */
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 1);
+            float_invalid_op_vxsnan(env, GETPC());
         }
     }
 }
@@ -1783,10 +1803,10 @@ void helper_##name(CPUPPCState *env, uint32_t opcode)                        \
                                                                              \
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
             if (tp##_is_infinity(xa.fld) && tp##_is_infinity(xb.fld)) {      \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, sfprf);    \
+                float_invalid_op_vxisi(env, sfprf, GETPC());                 \
             } else if (tp##_is_signaling_nan(xa.fld, &tstat) ||              \
                        tp##_is_signaling_nan(xb.fld, &tstat)) {              \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   \
+                float_invalid_op_vxsnan(env, GETPC());                       \
             }                                                                \
         }                                                                    \
                                                                              \
@@ -1832,10 +1852,10 @@ void helper_xsaddqp(CPUPPCState *env, uint32_t opcode)
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
         if (float128_is_infinity(xa.f128) && float128_is_infinity(xb.f128)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
+            float_invalid_op_vxisi(env, 1, GETPC());
         } else if (float128_is_signaling_nan(xa.f128, &tstat) ||
                    float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+            float_invalid_op_vxsnan(env, GETPC());
         }
     }
 
@@ -1872,10 +1892,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
             if ((tp##_is_infinity(xa.fld) && tp##_is_zero(xb.fld)) ||        \
                 (tp##_is_infinity(xb.fld) && tp##_is_zero(xa.fld))) {        \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, sfprf);    \
+                float_invalid_op_vximz(env, sfprf, GETPC());                 \
             } else if (tp##_is_signaling_nan(xa.fld, &tstat) ||              \
                        tp##_is_signaling_nan(xb.fld, &tstat)) {              \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   \
+                float_invalid_op_vxsnan(env, GETPC());                       \
             }                                                                \
         }                                                                    \
                                                                              \
@@ -1919,10 +1939,10 @@ void helper_xsmulqp(CPUPPCState *env, uint32_t opcode)
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
         if ((float128_is_infinity(xa.f128) && float128_is_zero(xb.f128)) ||
             (float128_is_infinity(xb.f128) && float128_is_zero(xa.f128))) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
+            float_invalid_op_vximz(env, 1, GETPC());
         } else if (float128_is_signaling_nan(xa.f128, &tstat) ||
                    float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+            float_invalid_op_vxsnan(env, GETPC());
         }
     }
     helper_compute_fprf_float128(env, xt.f128);
@@ -1957,13 +1977,12 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
                                                                               \
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {     \
             if (tp##_is_infinity(xa.fld) && tp##_is_infinity(xb.fld)) {       \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, sfprf);     \
-            } else if (tp##_is_zero(xa.fld) &&                                \
-                tp##_is_zero(xb.fld)) {                                       \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, sfprf);     \
+                float_invalid_op_vxidi(env, sfprf, GETPC());                  \
+            } else if (tp##_is_zero(xa.fld) && tp##_is_zero(xb.fld)) {        \
+                float_invalid_op_vxzdz(env, sfprf, GETPC());                  \
             } else if (tp##_is_signaling_nan(xa.fld, &tstat) ||               \
-                tp##_is_signaling_nan(xb.fld, &tstat)) {                      \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);    \
+                       tp##_is_signaling_nan(xb.fld, &tstat)) {               \
+                float_invalid_op_vxsnan(env, GETPC());                        \
             }                                                                 \
         }                                                                     \
         if (unlikely(tstat.float_exception_flags & float_flag_divbyzero)) {   \
@@ -2009,13 +2028,12 @@ void helper_xsdivqp(CPUPPCState *env, uint32_t opcode)
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
         if (float128_is_infinity(xa.f128) && float128_is_infinity(xb.f128)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, 1);
-        } else if (float128_is_zero(xa.f128) &&
-            float128_is_zero(xb.f128)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, 1);
+            float_invalid_op_vxidi(env, 1, GETPC());
+        } else if (float128_is_zero(xa.f128) && float128_is_zero(xb.f128)) {
+            float_invalid_op_vxzdz(env, 1, GETPC());
         } else if (float128_is_signaling_nan(xa.f128, &tstat) ||
-            float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+                   float128_is_signaling_nan(xb.f128, &tstat)) {
+            float_invalid_op_vxsnan(env, GETPC());
         }
     }
     if (unlikely(tstat.float_exception_flags & float_flag_divbyzero)) {
@@ -2046,7 +2064,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
                                                                               \
     for (i = 0; i < nels; i++) {                                              \
         if (unlikely(tp##_is_signaling_nan(xb.fld, &env->fp_status))) {       \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);    \
+            float_invalid_op_vxsnan(env, GETPC());                            \
         }                                                                     \
         xt.fld = tp##_div(tp##_one, xb.fld, &env->fp_status);                 \
                                                                               \
@@ -2093,9 +2111,9 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
                                                                              \
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
             if (tp##_is_neg(xb.fld) && !tp##_is_zero(xb.fld)) {              \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf);   \
+                float_invalid_op_vxsqrt(env, sfprf, GETPC());                \
             } else if (tp##_is_signaling_nan(xb.fld, &tstat)) {              \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   \
+                float_invalid_op_vxsnan(env, GETPC());                       \
             }                                                                \
         }                                                                    \
                                                                              \
@@ -2143,9 +2161,9 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
                                                                              \
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
             if (tp##_is_neg(xb.fld) && !tp##_is_zero(xb.fld)) {              \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf);   \
+                float_invalid_op_vxsqrt(env, sfprf, GETPC());                \
             } else if (tp##_is_signaling_nan(xb.fld, &tstat)) {              \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   \
+                float_invalid_op_vxsnan(env, GETPC());                       \
             }                                                                \
         }                                                                    \
                                                                              \
@@ -2329,7 +2347,8 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
         env->fp_status.float_exception_flags |= tstat.float_exception_flags;  \
                                                                               \
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {     \
-            tp##_maddsub_update_excp(env, xa.fld, b->fld, c->fld, maddflgs);  \
+            tp##_maddsub_update_excp(env, xa.fld, b->fld,                     \
+                                     c->fld, maddflgs, GETPC());              \
         }                                                                     \
                                                                               \
         if (r2sp) {                                                           \
@@ -2407,10 +2426,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
             float64_is_quiet_nan(xb.VsrD(0), &env->fp_status);                \
     }                                                                         \
     if (vxsnan_flag) {                                                        \
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);                \
+        float_invalid_op_vxsnan(env, GETPC());                                \
     }                                                                         \
     if (vxvc_flag) {                                                          \
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0);                  \
+        float_invalid_op_vxvc(env, 0, GETPC());                               \
     }                                                                         \
     vex_flag = fpscr_ve && (vxvc_flag || vxsnan_flag);                        \
                                                                               \
@@ -2522,10 +2541,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                      \
         }                                                                \
     }                                                                    \
     if (vxsnan_flag) {                                                   \
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);           \
+        float_invalid_op_vxsnan(env, GETPC());                           \
     }                                                                    \
     if (vxvc_flag) {                                                     \
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0);             \
+        float_invalid_op_vxvc(env, 0, GETPC());                          \
     }                                                                    \
                                                                          \
     if (float64_lt(xa.VsrD(0), xb.VsrD(0), &env->fp_status)) {           \
@@ -2572,10 +2591,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                     \
         }                                                               \
     }                                                                   \
     if (vxsnan_flag) {                                                  \
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);          \
+        float_invalid_op_vxsnan(env, GETPC());                          \
     }                                                                   \
     if (vxvc_flag) {                                                    \
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0);            \
+        float_invalid_op_vxvc(env, 0, GETPC());                         \
     }                                                                   \
                                                                         \
     if (float128_lt(xa.f128, xb.f128, &env->fp_status)) {               \
@@ -2617,7 +2636,7 @@ void helper_##name(CPUPPCState *env, uint32_t opcode)                         \
         xt.fld = tp##_##op(xa.fld, xb.fld, &env->fp_status);                  \
         if (unlikely(tp##_is_signaling_nan(xa.fld, &env->fp_status) ||        \
                      tp##_is_signaling_nan(xb.fld, &env->fp_status))) {       \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);            \
+            float_invalid_op_vxsnan(env, GETPC());                            \
         }                                                                     \
     }                                                                         \
                                                                               \
@@ -2660,7 +2679,7 @@ void helper_##name(CPUPPCState *env, uint32_t opcode)                         \
                                                                               \
     vex_flag = fpscr_ve & vxsnan_flag;                                        \
     if (vxsnan_flag) {                                                        \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);            \
+        float_invalid_op_vxsnan(env, GETPC());                                \
     }                                                                         \
     if (!vex_flag) {                                                          \
         putVSR(rD(opcode) + 32, &xt, env);                                    \
@@ -2715,7 +2734,7 @@ void helper_##name(CPUPPCState *env, uint32_t opcode)                         \
                                                                               \
     vex_flag = fpscr_ve & vxsnan_flag;                                        \
     if (vxsnan_flag) {                                                        \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);            \
+        float_invalid_op_vxsnan(env, GETPC());                                \
     }                                                                         \
     if (!vex_flag) {                                                          \
         putVSR(rD(opcode) + 32, &xt, env);                                    \
@@ -2751,10 +2770,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                       \
                      tp##_is_any_nan(xb.fld))) {                          \
             if (tp##_is_signaling_nan(xa.fld, &env->fp_status) ||         \
                 tp##_is_signaling_nan(xb.fld, &env->fp_status)) {         \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);    \
+                float_invalid_op_vxsnan(env, GETPC());                    \
             }                                                             \
             if (svxvc) {                                                  \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0);      \
+                float_invalid_op_vxvc(env, 0, GETPC());                   \
             }                                                             \
             xt.fld = 0;                                                   \
             all_true = 0;                                                 \
@@ -2807,7 +2826,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                \
         xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status);        \
         if (unlikely(stp##_is_signaling_nan(xb.sfld,               \
                                             &env->fp_status))) {   \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
+            float_invalid_op_vxsnan(env, GETPC());                 \
             xt.tfld = ttp##_snan_to_qnan(xt.tfld);                 \
         }                                                          \
         if (sfprf) {                                               \
@@ -2846,7 +2865,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                       \
         xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status);             \
         if (unlikely(stp##_is_signaling_nan(xb.sfld,                    \
                                             &env->fp_status))) {        \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);      \
+            float_invalid_op_vxsnan(env, GETPC());                      \
             xt.tfld = ttp##_snan_to_qnan(xt.tfld);                      \
         }                                                               \
         if (sfprf) {                                                    \
@@ -2883,7 +2902,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                \
         xt.tfld = stp##_to_##ttp(xb.sfld, 1, &env->fp_status);     \
         if (unlikely(stp##_is_signaling_nan(xb.sfld,               \
                                             &env->fp_status))) {   \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
+            float_invalid_op_vxsnan(env, GETPC());                 \
             xt.tfld = ttp##_snan_to_qnan(xt.tfld);                 \
         }                                                          \
         if (sfprf) {                                               \
@@ -2919,9 +2938,8 @@ void helper_xscvqpdp(CPUPPCState *env, uint32_t opcode)
 
     xt.VsrD(0) = float128_to_float64(xb.f128, &tstat);
     env->fp_status.float_exception_flags |= tstat.float_exception_flags;
-    if (unlikely(float128_is_signaling_nan(xb.f128,
-                                           &tstat))) {
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);
+    if (unlikely(float128_is_signaling_nan(xb.f128, &tstat))) {
+        float_invalid_op_vxsnan(env, GETPC());
         xt.VsrD(0) = float64_snan_to_qnan(xt.VsrD(0));
     }
     helper_compute_fprf_float64(env, xt.VsrD(0));
@@ -2967,15 +2985,15 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
     for (i = 0; i < nels; i++) {                                             \
         if (unlikely(stp##_is_any_nan(xb.sfld))) {                           \
             if (stp##_is_signaling_nan(xb.sfld, &env->fp_status)) {          \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);       \
+                float_invalid_op_vxsnan(env, GETPC());                       \
             }                                                                \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0);            \
+            float_invalid_op_vxcvi(env, 0, GETPC());                         \
             xt.tfld = rnan;                                                  \
         } else {                                                             \
             xt.tfld = stp##_to_##ttp##_round_to_zero(xb.sfld,                \
                           &env->fp_status);                                  \
             if (env->fp_status.float_exception_flags & float_flag_invalid) { \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0);        \
+                float_invalid_op_vxcvi(env, 0, GETPC());                     \
             }                                                                \
         }                                                                    \
     }                                                                        \
@@ -3020,15 +3038,15 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
                                                                              \
     if (unlikely(stp##_is_any_nan(xb.sfld))) {                               \
         if (stp##_is_signaling_nan(xb.sfld, &env->fp_status)) {              \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);           \
+            float_invalid_op_vxsnan(env, GETPC());                           \
         }                                                                    \
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0);                \
+        float_invalid_op_vxcvi(env, 0, GETPC());                             \
         xt.tfld = rnan;                                                      \
     } else {                                                                 \
         xt.tfld = stp##_to_##ttp##_round_to_zero(xb.sfld,                    \
                       &env->fp_status);                                      \
         if (env->fp_status.float_exception_flags & float_flag_invalid) {     \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0);            \
+            float_invalid_op_vxcvi(env, 0, GETPC());                         \
         }                                                                    \
     }                                                                        \
                                                                              \
@@ -3144,7 +3162,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                    \
     for (i = 0; i < nels; i++) {                                       \
         if (unlikely(tp##_is_signaling_nan(xb.fld,                     \
                                            &env->fp_status))) {        \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);     \
+            float_invalid_op_vxsnan(env, GETPC());                     \
             xt.fld = tp##_snan_to_qnan(xb.fld);                        \
         } else {                                                       \
             xt.fld = tp##_round_to_int(xb.fld, &env->fp_status);       \
@@ -3373,7 +3391,7 @@ void helper_xsrqpi(CPUPPCState *env, uint32_t opcode)
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
         if (float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);
+            float_invalid_op_vxsnan(env, GETPC());
             xt.f128 = float128_snan_to_qnan(xt.f128);
         }
     }
@@ -3433,7 +3451,7 @@ void helper_xsrqpxp(CPUPPCState *env, uint32_t opcode)
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
         if (float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);
+            float_invalid_op_vxsnan(env, GETPC());
             xt.f128 = float128_snan_to_qnan(xt.f128);
         }
     }
@@ -3464,12 +3482,12 @@ void helper_xssqrtqp(CPUPPCState *env, uint32_t opcode)
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
         if (float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+            float_invalid_op_vxsnan(env, GETPC());
             xt.f128 = float128_snan_to_qnan(xb.f128);
         } else if  (float128_is_quiet_nan(xb.f128, &tstat)) {
             xt.f128 = xb.f128;
         } else if (float128_is_neg(xb.f128) && !float128_is_zero(xb.f128)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
+            float_invalid_op_vxsqrt(env, 1, GETPC());
             xt.f128 = float128_default_nan(&env->fp_status);
         }
     }
@@ -3500,10 +3518,10 @@ void helper_xssubqp(CPUPPCState *env, uint32_t opcode)
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
         if (float128_is_infinity(xa.f128) && float128_is_infinity(xb.f128)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
+            float_invalid_op_vxisi(env, 1, GETPC());
         } else if (float128_is_signaling_nan(xa.f128, &tstat) ||
                    float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+            float_invalid_op_vxsnan(env, GETPC());
         }
     }
 
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 07/22] target/ppc: Remove float_check_status
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (5 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 06/22] target/ppc: Split up float_invalid_op_excp David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 08/22] target/ppc: Introduce fp number classification David Gibson
                   ` (15 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier, Richard Henderson,
	David Gibson

From: Richard Henderson <richard.henderson@linaro.org>

Use do_float_check_status directly, so that we don't get confused
about which return address we're using.  And definitely don't use
helper_float_check_status.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 target/ppc/fpu_helper.c | 77 +++++++++++++++++++----------------------
 1 file changed, 35 insertions(+), 42 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 6ec5227dd5..c9198f826d 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -630,13 +630,6 @@ static void do_float_check_status(CPUPPCState *env, uintptr_t raddr)
     }
 }
 
-static inline  __attribute__((__always_inline__))
-void float_check_status(CPUPPCState *env)
-{
-    /* GETPC() works here because this is inline */
-    do_float_check_status(env, GETPC());
-}
-
 void helper_float_check_status(CPUPPCState *env)
 {
     do_float_check_status(env, GETPC());
@@ -757,7 +750,7 @@ uint64_t helper_##op(CPUPPCState *env, uint64_t arg)                   \
                    float_flag_invalid) {                               \
             float_invalid_op_vxcvi(env, 1, GETPC());                   \
         }                                                              \
-        float_check_status(env);                                       \
+        do_float_check_status(env, GETPC());                           \
     }                                                                  \
     return farg.ll;                                                    \
  }
@@ -782,7 +775,7 @@ uint64_t helper_##op(CPUPPCState *env, uint64_t arg)       \
     } else {                                               \
         farg.d = cvtr(arg, &env->fp_status);               \
     }                                                      \
-    float_check_status(env);                               \
+    do_float_check_status(env, GETPC());                   \
     return farg.ll;                                        \
 }
 
@@ -815,7 +808,7 @@ static inline uint64_t do_fri(CPUPPCState *env, uint64_t arg,
             env->fp_status.float_exception_flags &= ~float_flag_inexact;
         }
     }
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
     return farg.ll;
 }
 
@@ -885,7 +878,7 @@ uint64_t helper_##op(CPUPPCState *env, uint64_t arg1,                   \
             float64_maddsub_update_excp(env, arg1, arg2, arg3,          \
                                         madd_flags, GETPC());           \
         }                                                               \
-        float_check_status(env);                                        \
+        do_float_check_status(env, GETPC());                            \
     }                                                                   \
     return ret;                                                         \
 }
@@ -1819,7 +1812,7 @@ void helper_##name(CPUPPCState *env, uint32_t opcode)                        \
         }                                                                    \
     }                                                                        \
     putVSR(xT(opcode), &xt, env);                                            \
-    float_check_status(env);                                                 \
+    do_float_check_status(env, GETPC());                                     \
 }
 
 VSX_ADD_SUB(xsadddp, add, 1, float64, VsrD(0), 1, 0)
@@ -1862,7 +1855,7 @@ void helper_xsaddqp(CPUPPCState *env, uint32_t opcode)
     helper_compute_fprf_float128(env, xt.f128);
 
     putVSR(rD(opcode) + 32, &xt, env);
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
 }
 
 /* VSX_MUL - VSX floating point multiply
@@ -1909,7 +1902,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
     }                                                                        \
                                                                              \
     putVSR(xT(opcode), &xt, env);                                            \
-    float_check_status(env);                                                 \
+    do_float_check_status(env, GETPC());                                     \
 }
 
 VSX_MUL(xsmuldp, 1, float64, VsrD(0), 1, 0)
@@ -1948,7 +1941,7 @@ void helper_xsmulqp(CPUPPCState *env, uint32_t opcode)
     helper_compute_fprf_float128(env, xt.f128);
 
     putVSR(rD(opcode) + 32, &xt, env);
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
 }
 
 /* VSX_DIV - VSX floating point divide
@@ -1999,7 +1992,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
     }                                                                         \
                                                                               \
     putVSR(xT(opcode), &xt, env);                                             \
-    float_check_status(env);                                                  \
+    do_float_check_status(env, GETPC());                                      \
 }
 
 VSX_DIV(xsdivdp, 1, float64, VsrD(0), 1, 0)
@@ -2042,7 +2035,7 @@ void helper_xsdivqp(CPUPPCState *env, uint32_t opcode)
 
     helper_compute_fprf_float128(env, xt.f128);
     putVSR(rD(opcode) + 32, &xt, env);
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
 }
 
 /* VSX_RE  - VSX floating point reciprocal estimate
@@ -2078,7 +2071,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
     }                                                                         \
                                                                               \
     putVSR(xT(opcode), &xt, env);                                             \
-    float_check_status(env);                                                  \
+    do_float_check_status(env, GETPC());                                      \
 }
 
 VSX_RE(xsredp, 1, float64, VsrD(0), 1, 0)
@@ -2127,7 +2120,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
     }                                                                        \
                                                                              \
     putVSR(xT(opcode), &xt, env);                                            \
-    float_check_status(env);                                                 \
+    do_float_check_status(env, GETPC());                                     \
 }
 
 VSX_SQRT(xssqrtdp, 1, float64, VsrD(0), 1, 0)
@@ -2177,7 +2170,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
     }                                                                        \
                                                                              \
     putVSR(xT(opcode), &xt, env);                                            \
-    float_check_status(env);                                                 \
+    do_float_check_status(env, GETPC());                                     \
 }
 
 VSX_RSQRTE(xsrsqrtedp, 1, float64, VsrD(0), 1, 0)
@@ -2360,7 +2353,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
         }                                                                     \
     }                                                                         \
     putVSR(xT(opcode), &xt_out, env);                                         \
-    float_check_status(env);                                                  \
+    do_float_check_status(env, GETPC());                                      \
 }
 
 VSX_MADD(xsmaddadp, 1, float64, VsrD(0), MADD_FLGS, 1, 1, 0)
@@ -2443,7 +2436,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
         }                                                                     \
     }                                                                         \
     putVSR(xT(opcode), &xt, env);                                             \
-    helper_float_check_status(env);                                           \
+    do_float_check_status(env, GETPC());                                      \
 }
 
 VSX_SCALAR_CMP_DP(xscmpeqdp, eq, 1, 0)
@@ -2480,7 +2473,7 @@ void helper_xscmpexpdp(CPUPPCState *env, uint32_t opcode)
     env->fpscr |= cc << FPSCR_FPRF;
     env->crf[BF(opcode)] = cc;
 
-    helper_float_check_status(env);
+    do_float_check_status(env, GETPC());
 }
 
 void helper_xscmpexpqp(CPUPPCState *env, uint32_t opcode)
@@ -2512,7 +2505,7 @@ void helper_xscmpexpqp(CPUPPCState *env, uint32_t opcode)
     env->fpscr |= cc << FPSCR_FPRF;
     env->crf[BF(opcode)] = cc;
 
-    helper_float_check_status(env);
+    do_float_check_status(env, GETPC());
 }
 
 #define VSX_SCALAR_CMP(op, ordered)                                      \
@@ -2559,7 +2552,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                      \
     env->fpscr |= cc << FPSCR_FPRF;                                      \
     env->crf[BF(opcode)] = cc;                                           \
                                                                          \
-    float_check_status(env);                                             \
+    do_float_check_status(env, GETPC());                                 \
 }
 
 VSX_SCALAR_CMP(xscmpodp, 1)
@@ -2609,7 +2602,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                     \
     env->fpscr |= cc << FPSCR_FPRF;                                     \
     env->crf[BF(opcode)] = cc;                                          \
                                                                         \
-    float_check_status(env);                                            \
+    do_float_check_status(env, GETPC());                                \
 }
 
 VSX_SCALAR_CMPQ(xscmpoqp, 1)
@@ -2641,7 +2634,7 @@ void helper_##name(CPUPPCState *env, uint32_t opcode)                         \
     }                                                                         \
                                                                               \
     putVSR(xT(opcode), &xt, env);                                             \
-    float_check_status(env);                                                  \
+    do_float_check_status(env, GETPC());                                      \
 }
 
 VSX_MAX_MIN(xsmaxdp, maxnum, 1, float64, VsrD(0))
@@ -2792,7 +2785,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                       \
     if ((opcode >> (31-21)) & 1) {                                        \
         env->crf[6] = (all_true ? 0x8 : 0) | (all_false ? 0x2 : 0);       \
     }                                                                     \
-    float_check_status(env);                                              \
+    do_float_check_status(env, GETPC());                                  \
  }
 
 VSX_CMP(xvcmpeqdp, 2, float64, VsrD(i), eq, 0, 1)
@@ -2835,7 +2828,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                \
     }                                                              \
                                                                    \
     putVSR(xT(opcode), &xt, env);                                  \
-    float_check_status(env);                                       \
+    do_float_check_status(env, GETPC());                           \
 }
 
 VSX_CVT_FP_TO_FP(xscvdpsp, 1, float64, float32, VsrD(0), VsrW(0), 1)
@@ -2874,7 +2867,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                       \
     }                                                                   \
                                                                         \
     putVSR(rD(opcode) + 32, &xt, env);                                  \
-    float_check_status(env);                                            \
+    do_float_check_status(env, GETPC());                                \
 }
 
 VSX_CVT_FP_TO_FP_VECTOR(xscvdpqp, 1, float64, float128, VsrD(0), f128, 1)
@@ -2911,7 +2904,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                \
     }                                                              \
                                                                    \
     putVSR(xT(opcode), &xt, env);                                  \
-    float_check_status(env);                                       \
+    do_float_check_status(env, GETPC());                           \
 }
 
 VSX_CVT_FP_TO_FP_HP(xscvdphp, 1, float64, float16, VsrD(0), VsrH(3), 1)
@@ -2945,7 +2938,7 @@ void helper_xscvqpdp(CPUPPCState *env, uint32_t opcode)
     helper_compute_fprf_float64(env, xt.VsrD(0));
 
     putVSR(rD(opcode) + 32, &xt, env);
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
 }
 
 uint64_t helper_xscvdpspn(CPUPPCState *env, uint64_t xb)
@@ -2999,7 +2992,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
     }                                                                        \
                                                                              \
     putVSR(xT(opcode), &xt, env);                                            \
-    float_check_status(env);                                                 \
+    do_float_check_status(env, GETPC());                                     \
 }
 
 VSX_CVT_FP_TO_INT(xscvdpsxds, 1, float64, int64, VsrD(0), VsrD(0), \
@@ -3051,7 +3044,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
     }                                                                        \
                                                                              \
     putVSR(rD(opcode) + 32, &xt, env);                                       \
-    float_check_status(env);                                                 \
+    do_float_check_status(env, GETPC());                                     \
 }
 
 VSX_CVT_FP_TO_INT_VECTOR(xscvqpsdz, float128, int64, f128, VsrD(0),          \
@@ -3092,7 +3085,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                     \
     }                                                                   \
                                                                         \
     putVSR(xT(opcode), &xt, env);                                       \
-    float_check_status(env);                                            \
+    do_float_check_status(env, GETPC());                                \
 }
 
 VSX_CVT_INT_TO_FP(xscvsxddp, 1, int64, float64, VsrD(0), VsrD(0), 1, 0)
@@ -3127,7 +3120,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                     \
     helper_compute_fprf_##ttp(env, xt.tfld);                            \
                                                                         \
     putVSR(xT(opcode) + 32, &xt, env);                                  \
-    float_check_status(env);                                            \
+    do_float_check_status(env, GETPC());                                \
 }
 
 VSX_CVT_INT_TO_FP_VECTOR(xscvsdqp, int64, float128, VsrD(0), f128)
@@ -3181,7 +3174,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                    \
     }                                                                  \
                                                                        \
     putVSR(xT(opcode), &xt, env);                                      \
-    float_check_status(env);                                           \
+    do_float_check_status(env, GETPC());                               \
 }
 
 VSX_ROUND(xsrdpi, 1, float64, VsrD(0), float_round_ties_away, 1)
@@ -3209,7 +3202,7 @@ uint64_t helper_xsrsp(CPUPPCState *env, uint64_t xb)
     uint64_t xt = helper_frsp(env, xb);
 
     helper_compute_fprf_float64(env, xt);
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
     return xt;
 }
 
@@ -3401,7 +3394,7 @@ void helper_xsrqpi(CPUPPCState *env, uint32_t opcode)
     }
 
     helper_compute_fprf_float128(env, xt.f128);
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
     putVSR(rD(opcode) + 32, &xt, env);
 }
 
@@ -3458,7 +3451,7 @@ void helper_xsrqpxp(CPUPPCState *env, uint32_t opcode)
 
     helper_compute_fprf_float128(env, xt.f128);
     putVSR(rD(opcode) + 32, &xt, env);
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
 }
 
 void helper_xssqrtqp(CPUPPCState *env, uint32_t opcode)
@@ -3494,7 +3487,7 @@ void helper_xssqrtqp(CPUPPCState *env, uint32_t opcode)
 
     helper_compute_fprf_float128(env, xt.f128);
     putVSR(rD(opcode) + 32, &xt, env);
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
 }
 
 void helper_xssubqp(CPUPPCState *env, uint32_t opcode)
@@ -3527,5 +3520,5 @@ void helper_xssubqp(CPUPPCState *env, uint32_t opcode)
 
     helper_compute_fprf_float128(env, xt.f128);
     putVSR(rD(opcode) + 32, &xt, env);
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
 }
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 08/22] target/ppc: Introduce fp number classification
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (6 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 07/22] target/ppc: Remove float_check_status David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 09/22] target/ppc: Split out float_invalid_op_addsub David Gibson
                   ` (14 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier, Richard Henderson,
	David Gibson

From: Richard Henderson <richard.henderson@linaro.org>

Having a separate, logical classifiation of numbers will
unify more error paths for different formats.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 target/ppc/fpu_helper.c | 94 ++++++++++++++++++++++-------------------
 1 file changed, 51 insertions(+), 43 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index c9198f826d..9ae55b1e93 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -114,54 +114,62 @@ static inline int ppc_float64_get_unbiased_exp(float64 f)
     return ((f >> 52) & 0x7FF) - 1023;
 }
 
-#define COMPUTE_FPRF(tp)                                       \
-void helper_compute_fprf_##tp(CPUPPCState *env, tp arg)        \
+/* Classify a floating-point number.  */
+enum {
+    is_normal   = 1,
+    is_zero     = 2,
+    is_denormal = 4,
+    is_inf      = 8,
+    is_qnan     = 16,
+    is_snan     = 32,
+    is_neg      = 64,
+};
+
+#define COMPUTE_CLASS(tp)                                      \
+static int tp##_classify(tp arg)                               \
 {                                                              \
-    int isneg;                                                 \
-    int fprf;                                                  \
-                                                               \
-    isneg = tp##_is_neg(arg);                                  \
+    int ret = tp##_is_neg(arg) * is_neg;                       \
     if (unlikely(tp##_is_any_nan(arg))) {                      \
-        if (tp##_is_signaling_nan(arg, &env->fp_status)) {     \
-            /* Signaling NaN: flags are undefined */           \
-            fprf = 0x00;                                       \
-        } else {                                               \
-            /* Quiet NaN */                                    \
-            fprf = 0x11;                                       \
-        }                                                      \
+        float_status dummy = { };  /* snan_bit_is_one = 0 */   \
+        ret |= (tp##_is_signaling_nan(arg, &dummy)             \
+                ? is_snan : is_qnan);                          \
     } else if (unlikely(tp##_is_infinity(arg))) {              \
-        /* +/- infinity */                                     \
-        if (isneg) {                                           \
-            fprf = 0x09;                                       \
-        } else {                                               \
-            fprf = 0x05;                                       \
-        }                                                      \
+        ret |= is_inf;                                         \
+    } else if (tp##_is_zero(arg)) {                            \
+        ret |= is_zero;                                        \
+    } else if (tp##_is_zero_or_denormal(arg)) {                \
+        ret |= is_denormal;                                    \
     } else {                                                   \
-        if (tp##_is_zero(arg)) {                               \
-            /* +/- zero */                                     \
-            if (isneg) {                                       \
-                fprf = 0x12;                                   \
-            } else {                                           \
-                fprf = 0x02;                                   \
-            }                                                  \
-        } else {                                               \
-            if (tp##_is_zero_or_denormal(arg)) {               \
-                /* Denormalized numbers */                     \
-                fprf = 0x10;                                   \
-            } else {                                           \
-                /* Normalized numbers */                       \
-                fprf = 0x00;                                   \
-            }                                                  \
-            if (isneg) {                                       \
-                fprf |= 0x08;                                  \
-            } else {                                           \
-                fprf |= 0x04;                                  \
-            }                                                  \
-        }                                                      \
+        ret |= is_normal;                                      \
     }                                                          \
-    /* We update FPSCR_FPRF */                                 \
-    env->fpscr &= ~(0x1F << FPSCR_FPRF);                       \
-    env->fpscr |= fprf << FPSCR_FPRF;                          \
+    return ret;                                                \
+}
+
+COMPUTE_CLASS(float16)
+COMPUTE_CLASS(float32)
+COMPUTE_CLASS(float64)
+COMPUTE_CLASS(float128)
+
+static void set_fprf_from_class(CPUPPCState *env, int class)
+{
+    static const uint8_t fprf[6][2] = {
+        { 0x04, 0x08 },  /* normalized */
+        { 0x02, 0x12 },  /* zero */
+        { 0x14, 0x18 },  /* denormalized */
+        { 0x05, 0x09 },  /* infinity */
+        { 0x11, 0x11 },  /* qnan */
+        { 0x00, 0x00 },  /* snan -- flags are undefined */
+    };
+    bool isneg = class & is_neg;
+
+    env->fpscr &= ~(0x1F << FPSCR_FPRF);
+    env->fpscr |= fprf[ctz32(class)][isneg] << FPSCR_FPRF;
+}
+
+#define COMPUTE_FPRF(tp)                                \
+void helper_compute_fprf_##tp(CPUPPCState *env, tp arg) \
+{                                                       \
+    set_fprf_from_class(env, tp##_classify(arg));       \
 }
 
 COMPUTE_FPRF(float16)
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 09/22] target/ppc: Split out float_invalid_op_addsub
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (7 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 08/22] target/ppc: Introduce fp number classification David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 10/22] target/ppc: Split out float_invalid_op_mul David Gibson
                   ` (13 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier, Richard Henderson,
	David Gibson

From: Richard Henderson <richard.henderson@linaro.org>

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 target/ppc/fpu_helper.c | 60 ++++++++++++++++++-----------------------
 1 file changed, 26 insertions(+), 34 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 9ae55b1e93..111ce12a37 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -648,6 +648,17 @@ void helper_reset_fpstatus(CPUPPCState *env)
     set_float_exception_flags(0, &env->fp_status);
 }
 
+static void float_invalid_op_addsub(CPUPPCState *env, bool set_fpcc,
+                                    uintptr_t retaddr, int classes)
+{
+    if ((classes & ~is_neg) == is_inf) {
+        /* Magnitude subtraction of infinities */
+        float_invalid_op_vxisi(env, set_fpcc, retaddr);
+    } else if (classes & is_snan) {
+        float_invalid_op_vxsnan(env, retaddr);
+    }
+}
+
 /* fadd - fadd. */
 float64 helper_fadd(CPUPPCState *env, float64 arg1, float64 arg2)
 {
@@ -655,14 +666,9 @@ float64 helper_fadd(CPUPPCState *env, float64 arg1, float64 arg2)
     int status = get_float_exception_flags(&env->fp_status);
 
     if (unlikely(status & float_flag_invalid)) {
-        if (float64_is_infinity(arg1) && float64_is_infinity(arg2)) {
-            /* Magnitude subtraction of infinities */
-            float_invalid_op_vxisi(env, 1, GETPC());
-        } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
-                   float64_is_signaling_nan(arg2, &env->fp_status)) {
-            /* sNaN addition */
-            float_invalid_op_vxsnan(env, GETPC());
-        }
+        float_invalid_op_addsub(env, 1, GETPC(),
+                                float64_classify(arg1) |
+                                float64_classify(arg2));
     }
 
     return ret;
@@ -675,14 +681,9 @@ float64 helper_fsub(CPUPPCState *env, float64 arg1, float64 arg2)
     int status = get_float_exception_flags(&env->fp_status);
 
     if (unlikely(status & float_flag_invalid)) {
-        if (float64_is_infinity(arg1) && float64_is_infinity(arg2)) {
-            /* Magnitude subtraction of infinities */
-            float_invalid_op_vxisi(env, 1, GETPC());
-        } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
-                   float64_is_signaling_nan(arg2, &env->fp_status)) {
-            /* sNaN addition */
-            float_invalid_op_vxsnan(env, GETPC());
-        }
+        float_invalid_op_addsub(env, 1, GETPC(),
+                                float64_classify(arg1) |
+                                float64_classify(arg2));
     }
 
     return ret;
@@ -1803,12 +1804,9 @@ void helper_##name(CPUPPCState *env, uint32_t opcode)                        \
         env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
                                                                              \
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
-            if (tp##_is_infinity(xa.fld) && tp##_is_infinity(xb.fld)) {      \
-                float_invalid_op_vxisi(env, sfprf, GETPC());                 \
-            } else if (tp##_is_signaling_nan(xa.fld, &tstat) ||              \
-                       tp##_is_signaling_nan(xb.fld, &tstat)) {              \
-                float_invalid_op_vxsnan(env, GETPC());                       \
-            }                                                                \
+            float_invalid_op_addsub(env, sfprf, GETPC(),                     \
+                                    tp##_classify(xa.fld) |                  \
+                                    tp##_classify(xb.fld));                  \
         }                                                                    \
                                                                              \
         if (r2sp) {                                                          \
@@ -1852,12 +1850,9 @@ void helper_xsaddqp(CPUPPCState *env, uint32_t opcode)
     env->fp_status.float_exception_flags |= tstat.float_exception_flags;
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
-        if (float128_is_infinity(xa.f128) && float128_is_infinity(xb.f128)) {
-            float_invalid_op_vxisi(env, 1, GETPC());
-        } else if (float128_is_signaling_nan(xa.f128, &tstat) ||
-                   float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_vxsnan(env, GETPC());
-        }
+        float_invalid_op_addsub(env, 1, GETPC(),
+                                float128_classify(xa.f128) |
+                                float128_classify(xb.f128));
     }
 
     helper_compute_fprf_float128(env, xt.f128);
@@ -3518,12 +3513,9 @@ void helper_xssubqp(CPUPPCState *env, uint32_t opcode)
     env->fp_status.float_exception_flags |= tstat.float_exception_flags;
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
-        if (float128_is_infinity(xa.f128) && float128_is_infinity(xb.f128)) {
-            float_invalid_op_vxisi(env, 1, GETPC());
-        } else if (float128_is_signaling_nan(xa.f128, &tstat) ||
-                   float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_vxsnan(env, GETPC());
-        }
+        float_invalid_op_addsub(env, 1, GETPC(),
+                                float128_classify(xa.f128) |
+                                float128_classify(xb.f128));
     }
 
     helper_compute_fprf_float128(env, xt.f128);
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 10/22] target/ppc: Split out float_invalid_op_mul
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (8 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 09/22] target/ppc: Split out float_invalid_op_addsub David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 11/22] target/ppc: Split out float_invalid_op_div David Gibson
                   ` (12 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier, Richard Henderson,
	David Gibson

From: Richard Henderson <richard.henderson@linaro.org>

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 target/ppc/fpu_helper.c | 43 +++++++++++++++++++----------------------
 1 file changed, 20 insertions(+), 23 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 111ce12a37..ef251d062f 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -689,6 +689,17 @@ float64 helper_fsub(CPUPPCState *env, float64 arg1, float64 arg2)
     return ret;
 }
 
+static void float_invalid_op_mul(CPUPPCState *env, bool set_fprc,
+                                 uintptr_t retaddr, int classes)
+{
+    if ((classes & (is_zero | is_inf)) == (is_zero | is_inf)) {
+        /* Multiplication of zero by infinity */
+        float_invalid_op_vximz(env, set_fprc, retaddr);
+    } else if (classes & is_snan) {
+        float_invalid_op_vxsnan(env, retaddr);
+    }
+}
+
 /* fmul - fmul. */
 float64 helper_fmul(CPUPPCState *env, float64 arg1, float64 arg2)
 {
@@ -696,15 +707,9 @@ float64 helper_fmul(CPUPPCState *env, float64 arg1, float64 arg2)
     int status = get_float_exception_flags(&env->fp_status);
 
     if (unlikely(status & float_flag_invalid)) {
-        if ((float64_is_infinity(arg1) && float64_is_zero(arg2)) ||
-            (float64_is_zero(arg1) && float64_is_infinity(arg2))) {
-            /* Multiplication of zero by infinity */
-            float_invalid_op_vximz(env, 1, GETPC());
-        } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
-                   float64_is_signaling_nan(arg2, &env->fp_status)) {
-            /* sNaN multiplication */
-            float_invalid_op_vxsnan(env, GETPC());
-        }
+        float_invalid_op_mul(env, 1, GETPC(),
+                             float64_classify(arg1) |
+                             float64_classify(arg2));
     }
 
     return ret;
@@ -1886,13 +1891,9 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
         env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
                                                                              \
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
-            if ((tp##_is_infinity(xa.fld) && tp##_is_zero(xb.fld)) ||        \
-                (tp##_is_infinity(xb.fld) && tp##_is_zero(xa.fld))) {        \
-                float_invalid_op_vximz(env, sfprf, GETPC());                 \
-            } else if (tp##_is_signaling_nan(xa.fld, &tstat) ||              \
-                       tp##_is_signaling_nan(xb.fld, &tstat)) {              \
-                float_invalid_op_vxsnan(env, GETPC());                       \
-            }                                                                \
+            float_invalid_op_mul(env, sfprf, GETPC(),                        \
+                                 tp##_classify(xa.fld) |                     \
+                                 tp##_classify(xb.fld));                     \
         }                                                                    \
                                                                              \
         if (r2sp) {                                                          \
@@ -1933,13 +1934,9 @@ void helper_xsmulqp(CPUPPCState *env, uint32_t opcode)
     env->fp_status.float_exception_flags |= tstat.float_exception_flags;
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
-        if ((float128_is_infinity(xa.f128) && float128_is_zero(xb.f128)) ||
-            (float128_is_infinity(xb.f128) && float128_is_zero(xa.f128))) {
-            float_invalid_op_vximz(env, 1, GETPC());
-        } else if (float128_is_signaling_nan(xa.f128, &tstat) ||
-                   float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_vxsnan(env, GETPC());
-        }
+        float_invalid_op_mul(env, 1, GETPC(),
+                             float128_classify(xa.f128) |
+                             float128_classify(xb.f128));
     }
     helper_compute_fprf_float128(env, xt.f128);
 
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 11/22] target/ppc: Split out float_invalid_op_div
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (9 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 10/22] target/ppc: Split out float_invalid_op_mul David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 12/22] target/ppc: Split out float_invalid_cvt David Gibson
                   ` (11 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier, Richard Henderson,
	David Gibson

From: Richard Henderson <richard.henderson@linaro.org>

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 target/ppc/fpu_helper.c | 52 +++++++++++++++++++----------------------
 1 file changed, 24 insertions(+), 28 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index ef251d062f..127c08bcec 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -715,6 +715,21 @@ float64 helper_fmul(CPUPPCState *env, float64 arg1, float64 arg2)
     return ret;
 }
 
+static void float_invalid_op_div(CPUPPCState *env, bool set_fprc,
+                                 uintptr_t retaddr, int classes)
+{
+    classes &= ~is_neg;
+    if (classes == is_inf) {
+        /* Division of infinity by infinity */
+        float_invalid_op_vxidi(env, set_fprc, retaddr);
+    } else if (classes == is_zero) {
+        /* Division of zero by zero */
+        float_invalid_op_vxzdz(env, set_fprc, retaddr);
+    } else if (classes & is_snan) {
+        float_invalid_op_vxsnan(env, retaddr);
+    }
+}
+
 /* fdiv - fdiv. */
 float64 helper_fdiv(CPUPPCState *env, float64 arg1, float64 arg2)
 {
@@ -723,18 +738,9 @@ float64 helper_fdiv(CPUPPCState *env, float64 arg1, float64 arg2)
 
     if (unlikely(status)) {
         if (status & float_flag_invalid) {
-            /* Determine what kind of invalid operation was seen.  */
-            if (float64_is_infinity(arg1) && float64_is_infinity(arg2)) {
-                /* Division of infinity by infinity */
-                float_invalid_op_vxidi(env, 1, GETPC());
-            } else if (float64_is_zero(arg1) && float64_is_zero(arg2)) {
-                /* Division of zero by zero */
-                float_invalid_op_vxzdz(env, 1, GETPC());
-            } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
-                       float64_is_signaling_nan(arg2, &env->fp_status)) {
-                /* sNaN division */
-                float_invalid_op_vxsnan(env, GETPC());
-            }
+            float_invalid_op_div(env, 1, GETPC(),
+                                 float64_classify(arg1) |
+                                 float64_classify(arg2));
         }
         if (status & float_flag_divbyzero) {
             float_zero_divide_excp(env, GETPC());
@@ -1969,14 +1975,9 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
         env->fp_status.float_exception_flags |= tstat.float_exception_flags;  \
                                                                               \
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {     \
-            if (tp##_is_infinity(xa.fld) && tp##_is_infinity(xb.fld)) {       \
-                float_invalid_op_vxidi(env, sfprf, GETPC());                  \
-            } else if (tp##_is_zero(xa.fld) && tp##_is_zero(xb.fld)) {        \
-                float_invalid_op_vxzdz(env, sfprf, GETPC());                  \
-            } else if (tp##_is_signaling_nan(xa.fld, &tstat) ||               \
-                       tp##_is_signaling_nan(xb.fld, &tstat)) {               \
-                float_invalid_op_vxsnan(env, GETPC());                        \
-            }                                                                 \
+            float_invalid_op_div(env, sfprf, GETPC(),                         \
+                                 tp##_classify(xa.fld) |                      \
+                                 tp##_classify(xb.fld));                      \
         }                                                                     \
         if (unlikely(tstat.float_exception_flags & float_flag_divbyzero)) {   \
             float_zero_divide_excp(env, GETPC());                             \
@@ -2020,14 +2021,9 @@ void helper_xsdivqp(CPUPPCState *env, uint32_t opcode)
     env->fp_status.float_exception_flags |= tstat.float_exception_flags;
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
-        if (float128_is_infinity(xa.f128) && float128_is_infinity(xb.f128)) {
-            float_invalid_op_vxidi(env, 1, GETPC());
-        } else if (float128_is_zero(xa.f128) && float128_is_zero(xb.f128)) {
-            float_invalid_op_vxzdz(env, 1, GETPC());
-        } else if (float128_is_signaling_nan(xa.f128, &tstat) ||
-                   float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_vxsnan(env, GETPC());
-        }
+        float_invalid_op_div(env, 1, GETPC(),
+                             float128_classify(xa.f128) |
+                             float128_classify(xb.f128));
     }
     if (unlikely(tstat.float_exception_flags & float_flag_divbyzero)) {
         float_zero_divide_excp(env, GETPC());
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 12/22] target/ppc: Split out float_invalid_cvt
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (10 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 11/22] target/ppc: Split out float_invalid_op_div David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 13/22] spapr_pci: convert g_malloc() to g_new() David Gibson
                   ` (10 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier, Richard Henderson,
	David Gibson

From: Richard Henderson <richard.henderson@linaro.org>

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 target/ppc/fpu_helper.c | 67 +++++++++++++++++------------------------
 1 file changed, 28 insertions(+), 39 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 127c08bcec..2ed4f42275 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -750,30 +750,30 @@ float64 helper_fdiv(CPUPPCState *env, float64 arg1, float64 arg2)
     return ret;
 }
 
+static void float_invalid_cvt(CPUPPCState *env, bool set_fprc,
+                              uintptr_t retaddr, int class1)
+{
+    float_invalid_op_vxcvi(env, set_fprc, retaddr);
+    if (class1 & is_snan) {
+        float_invalid_op_vxsnan(env, retaddr);
+    }
+}
 
 #define FPU_FCTI(op, cvt, nanval)                                      \
-uint64_t helper_##op(CPUPPCState *env, uint64_t arg)                   \
+uint64_t helper_##op(CPUPPCState *env, float64 arg)                    \
 {                                                                      \
-    CPU_DoubleU farg;                                                  \
-                                                                       \
-    farg.ll = arg;                                                     \
-    farg.ll = float64_to_##cvt(farg.d, &env->fp_status);               \
+    uint64_t ret = float64_to_##cvt(arg, &env->fp_status);             \
+    int status = get_float_exception_flags(&env->fp_status);           \
                                                                        \
-    if (unlikely(env->fp_status.float_exception_flags)) {              \
-        if (float64_is_any_nan(arg)) {                                 \
-            float_invalid_op_vxcvi(env, 1, GETPC());                   \
-            if (float64_is_signaling_nan(arg, &env->fp_status)) {      \
-                float_invalid_op_vxsnan(env, GETPC());                 \
-            }                                                          \
-            farg.ll = nanval;                                          \
-        } else if (env->fp_status.float_exception_flags &              \
-                   float_flag_invalid) {                               \
-            float_invalid_op_vxcvi(env, 1, GETPC());                   \
+    if (unlikely(status)) {                                            \
+        if (status & float_flag_invalid) {                             \
+            float_invalid_cvt(env, 1, GETPC(), float64_classify(arg)); \
+            ret = nanval;                                              \
         }                                                              \
         do_float_check_status(env, GETPC());                           \
     }                                                                  \
-    return farg.ll;                                                    \
- }
+    return ret;                                                        \
+}
 
 FPU_FCTI(fctiw, int32, 0x80000000U)
 FPU_FCTI(fctiwz, int32_round_to_zero, 0x80000000U)
@@ -2965,6 +2965,7 @@ uint64_t helper_xscvspdpn(CPUPPCState *env, uint64_t xb)
 #define VSX_CVT_FP_TO_INT(op, nels, stp, ttp, sfld, tfld, rnan)              \
 void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
 {                                                                            \
+    int all_flags = env->fp_status.float_exception_flags, flags;             \
     ppc_vsr_t xt, xb;                                                        \
     int i;                                                                   \
                                                                              \
@@ -2972,22 +2973,18 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
     getVSR(xT(opcode), &xt, env);                                            \
                                                                              \
     for (i = 0; i < nels; i++) {                                             \
-        if (unlikely(stp##_is_any_nan(xb.sfld))) {                           \
-            if (stp##_is_signaling_nan(xb.sfld, &env->fp_status)) {          \
-                float_invalid_op_vxsnan(env, GETPC());                       \
-            }                                                                \
-            float_invalid_op_vxcvi(env, 0, GETPC());                         \
+        env->fp_status.float_exception_flags = 0;                            \
+        xt.tfld = stp##_to_##ttp##_round_to_zero(xb.sfld, &env->fp_status);  \
+        flags = env->fp_status.float_exception_flags;                        \
+        if (unlikely(flags & float_flag_invalid)) {                          \
+            float_invalid_cvt(env, 0, GETPC(), stp##_classify(xb.sfld));     \
             xt.tfld = rnan;                                                  \
-        } else {                                                             \
-            xt.tfld = stp##_to_##ttp##_round_to_zero(xb.sfld,                \
-                          &env->fp_status);                                  \
-            if (env->fp_status.float_exception_flags & float_flag_invalid) { \
-                float_invalid_op_vxcvi(env, 0, GETPC());                     \
-            }                                                                \
         }                                                                    \
+        all_flags |= flags;                                                  \
     }                                                                        \
                                                                              \
     putVSR(xT(opcode), &xt, env);                                            \
+    env->fp_status.float_exception_flags = all_flags;                        \
     do_float_check_status(env, GETPC());                                     \
 }
 
@@ -3025,18 +3022,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
     getVSR(rB(opcode) + 32, &xb, env);                                       \
     memset(&xt, 0, sizeof(xt));                                              \
                                                                              \
-    if (unlikely(stp##_is_any_nan(xb.sfld))) {                               \
-        if (stp##_is_signaling_nan(xb.sfld, &env->fp_status)) {              \
-            float_invalid_op_vxsnan(env, GETPC());                           \
-        }                                                                    \
-        float_invalid_op_vxcvi(env, 0, GETPC());                             \
+    xt.tfld = stp##_to_##ttp##_round_to_zero(xb.sfld, &env->fp_status);      \
+    if (env->fp_status.float_exception_flags & float_flag_invalid) {         \
+        float_invalid_cvt(env, 0, GETPC(), stp##_classify(xb.sfld));         \
         xt.tfld = rnan;                                                      \
-    } else {                                                                 \
-        xt.tfld = stp##_to_##ttp##_round_to_zero(xb.sfld,                    \
-                      &env->fp_status);                                      \
-        if (env->fp_status.float_exception_flags & float_flag_invalid) {     \
-            float_invalid_op_vxcvi(env, 0, GETPC());                         \
-        }                                                                    \
     }                                                                        \
                                                                              \
     putVSR(rD(opcode) + 32, &xt, env);                                       \
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 13/22] spapr_pci: convert g_malloc() to g_new()
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (11 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 12/22] target/ppc: Split out float_invalid_cvt David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 14/22] macio/pmu: Fix missing vmsd terminator David Gibson
                   ` (9 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell; +Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier, David Gibson

From: Greg Kurz <groug@kaod.org>

When allocating an array, it is a recommended coding practice to call
g_new(FooType, n) instead of g_malloc(n * sizeof(FooType)) because
it takes care to avoid overflow when calculating the size of the
allocated block and it returns FooType *, which allows the compiler
to perform type checking.

Signed-off-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/spapr_pci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 58afa46204..2374d55fc1 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -1882,7 +1882,7 @@ static int spapr_pci_pre_save(void *opaque)
     if (!sphb->msi_devs_num) {
         return 0;
     }
-    sphb->msi_devs = g_malloc(sphb->msi_devs_num * sizeof(spapr_pci_msi_mig));
+    sphb->msi_devs = g_new(spapr_pci_msi_mig, sphb->msi_devs_num);
 
     g_hash_table_iter_init(&iter, sphb->msi);
     for (i = 0; g_hash_table_iter_next(&iter, &key, &value); ++i) {
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 14/22] macio/pmu: Fix missing vmsd terminator
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (12 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 13/22] spapr_pci: convert g_malloc() to g_new() David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 15/22] hw/ppc/mac_newworld: Free openpic_irqs array after use David Gibson
                   ` (8 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier,
	Dr. David Alan Gilbert, David Gibson

From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>

Fix missing terminator in VMStateDescription

Fixes: d811d61fbc6ca5f2be2185fd7cfa916e7ba613ce
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/misc/macio/pmu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/misc/macio/pmu.c b/hw/misc/macio/pmu.c
index d25344f888..6e6d96c8c5 100644
--- a/hw/misc/macio/pmu.c
+++ b/hw/misc/macio/pmu.c
@@ -686,6 +686,7 @@ static const VMStateDescription vmstate_pmu_adb = {
         VMSTATE_TIMER_PTR(adb_poll_timer, PMUState),
         VMSTATE_UINT8(adb_reply_size, PMUState),
         VMSTATE_BUFFER(adb_reply, PMUState),
+        VMSTATE_END_OF_LIST()
     }
 };
 
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 15/22] hw/ppc/mac_newworld: Free openpic_irqs array after use
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (13 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 14/22] macio/pmu: Fix missing vmsd terminator David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 16/22] target/ppc: fix mtmsr instruction for icount David Gibson
                   ` (7 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell; +Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier, David Gibson

From: Peter Maydell <peter.maydell@linaro.org>

In ppc_core99_init(), we allocate an openpic_irqs array, which
we then use to collect up the various qemu_irqs which we're
going to connect to the interrupt controller. Once we've
called sysbus_connect_irq() to connect them all up, the
array is no longer required, but we forgot to free it.

Since board init is only run once at startup, the memory
leak is not a significant one.

Spotted by Coverity: CID 1192916.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/mac_newworld.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index a630cb81cd..14273a123e 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -303,6 +303,7 @@ static void ppc_core99_init(MachineState *machine)
             sysbus_connect_irq(s, k++, openpic_irqs[i][j]);
         }
     }
+    g_free(openpic_irqs);
 
     if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) {
         /* 970 gets a U3 bus */
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 16/22] target/ppc: fix mtmsr instruction for icount
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (14 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 15/22] hw/ppc/mac_newworld: Free openpic_irqs array after use David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 17/22] ppc/pnv: check size before data buffer access David Gibson
                   ` (6 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier, Pavel Dovgalyuk,
	Maria Klimushenkova, Pavel Dovgalyuk, David Gibson

From: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>

This patch fixes processing of mtmsr instructions in icount mode.
In this mode writing to interrupt/peripheral state is controlled
by can_do_io flag. This flag must be set explicitly before helper
function invocation.

Signed-off-by: Maria Klimushenkova <maria.klimushenkova@ispras.ru>
Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 target/ppc/translate.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index c999832426..fb18cedcf0 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -4298,11 +4298,17 @@ static void gen_mtmsrd(DisasContext *ctx)
          *      if we enter power saving mode, we will exit the loop
          *      directly from ppc_store_msr
          */
+        if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+            gen_io_start();
+        }
         gen_update_nip(ctx, ctx->base.pc_next);
         gen_helper_store_msr(cpu_env, cpu_gpr[rS(ctx->opcode)]);
         /* Must stop the translation as machine state (may have) changed */
         /* Note that mtmsr is not always defined as context-synchronizing */
         gen_stop_exception(ctx);
+        if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+            gen_io_end();
+        }
     }
 #endif /* !defined(CONFIG_USER_ONLY) */
 }
@@ -4327,6 +4333,9 @@ static void gen_mtmsr(DisasContext *ctx)
          *      if we enter power saving mode, we will exit the loop
          *      directly from ppc_store_msr
          */
+        if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+            gen_io_start();
+        }
         gen_update_nip(ctx, ctx->base.pc_next);
 #if defined(TARGET_PPC64)
         tcg_gen_deposit_tl(msr, cpu_msr, cpu_gpr[rS(ctx->opcode)], 0, 32);
@@ -4334,6 +4343,9 @@ static void gen_mtmsr(DisasContext *ctx)
         tcg_gen_mov_tl(msr, cpu_gpr[rS(ctx->opcode)]);
 #endif
         gen_helper_store_msr(cpu_env, msr);
+        if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+            gen_io_end();
+        }
         tcg_temp_free(msr);
         /* Must stop the translation as machine state (may have) changed */
         /* Note that mtmsr is not always defined as context-synchronizing */
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 17/22] ppc/pnv: check size before data buffer access
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (15 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 16/22] target/ppc: fix mtmsr instruction for icount David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 18/22] MAINTAINERS: PPC: Remove myself David Gibson
                   ` (5 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier, Prasad J Pandit,
	David Gibson

From: Prasad J Pandit <pjp@fedoraproject.org>

While performing PowerNV memory r/w operations, the access length
'sz' could exceed the data[4] buffer size. Add check to avoid OOB
access.

Reported-by: Moguofang <moguofang@huawei.com>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/pnv_lpc.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c
index d7721320a2..172a915cfc 100644
--- a/hw/ppc/pnv_lpc.c
+++ b/hw/ppc/pnv_lpc.c
@@ -155,9 +155,15 @@ static void pnv_lpc_do_eccb(PnvLpcController *lpc, uint64_t cmd)
     /* XXX Check for magic bits at the top, addr size etc... */
     unsigned int sz = (cmd & ECCB_CTL_SZ_MASK) >> ECCB_CTL_SZ_LSH;
     uint32_t opb_addr = cmd & ECCB_CTL_ADDR_MASK;
-    uint8_t data[4];
+    uint8_t data[8];
     bool success;
 
+    if (sz > sizeof(data)) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+            "ECCB: invalid operation at @0x%08x size %d\n", opb_addr, sz);
+        return;
+    }
+
     if (cmd & ECCB_CTL_READ) {
         success = opb_read(lpc, opb_addr, data, sz);
         if (success) {
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 18/22] MAINTAINERS: PPC: Remove myself
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (16 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 17/22] ppc/pnv: check size before data buffer access David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 19/22] hw/ppc/ppc440_uc: Remove dead code in sdram_size() David Gibson
                   ` (4 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell; +Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier, David Gibson

From: Alexander Graf <agraf@suse.de>

I haven't really been maintaining any PowerPC code for quite a while now,
so let's reflect reality: David does all the work and embedded PPC is in
"Odd Fixes" state rather than supported now.

Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 MAINTAINERS | 30 ++++++++++++++----------------
 1 file changed, 14 insertions(+), 16 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 0499e11593..46772bc0b0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -230,7 +230,6 @@ F: tests/tcg/openrisc/
 
 PowerPC
 M: David Gibson <david@gibson.dropbear.id.au>
-M: Alexander Graf <agraf@suse.de>
 L: qemu-ppc@nongnu.org
 S: Maintained
 F: target/ppc/
@@ -341,7 +340,7 @@ S: Maintained
 F: target/mips/kvm.c
 
 PPC
-M: Alexander Graf <agraf@suse.de>
+M: David Gibson <david@gibson.dropbear.id.au>
 S: Maintained
 F: target/ppc/kvm.c
 
@@ -779,21 +778,21 @@ F: hw/openrisc/openrisc_sim.c
 PowerPC Machines
 ----------------
 405
-M: Alexander Graf <agraf@suse.de>
+M: David Gibson <david@gibson.dropbear.id.au>
 L: qemu-ppc@nongnu.org
 S: Odd Fixes
 F: hw/ppc/ppc405_boards.c
 
 Bamboo
-M: Alexander Graf <agraf@suse.de>
+M: David Gibson <david@gibson.dropbear.id.au>
 L: qemu-ppc@nongnu.org
 S: Odd Fixes
 F: hw/ppc/ppc440_bamboo.c
 
 e500
-M: Alexander Graf <agraf@suse.de>
+M: David Gibson <david@gibson.dropbear.id.au>
 L: qemu-ppc@nongnu.org
-S: Supported
+S: Odd Fixes
 F: hw/ppc/e500.[hc]
 F: hw/ppc/e500plat.c
 F: include/hw/ppc/ppc_e500.h
@@ -801,16 +800,16 @@ F: include/hw/pci-host/ppce500.h
 F: pc-bios/u-boot.e500
 
 mpc8544ds
-M: Alexander Graf <agraf@suse.de>
+M: David Gibson <david@gibson.dropbear.id.au>
 L: qemu-ppc@nongnu.org
-S: Supported
+S: Odd Fixes
 F: hw/ppc/mpc8544ds.c
 F: hw/ppc/mpc8544_guts.c
 
 New World
-M: Alexander Graf <agraf@suse.de>
+M: David Gibson <david@gibson.dropbear.id.au>
 L: qemu-ppc@nongnu.org
-S: Maintained
+S: Odd Fixes
 F: hw/ppc/mac_newworld.c
 F: hw/pci-host/uninorth.c
 F: hw/pci-bridge/dec.[hc]
@@ -822,9 +821,9 @@ F: include/hw/misc/mos6522.h
 F: include/hw/ppc/mac_dbdma.h
 
 Old World
-M: Alexander Graf <agraf@suse.de>
+M: David Gibson <david@gibson.dropbear.id.au>
 L: qemu-ppc@nongnu.org
-S: Maintained
+S: Odd Fixes
 F: hw/ppc/mac_oldworld.c
 F: hw/pci-host/grackle.c
 F: hw/misc/macio/
@@ -849,7 +848,6 @@ F: pc-bios/ppc_rom.bin
 
 sPAPR
 M: David Gibson <david@gibson.dropbear.id.au>
-M: Alexander Graf <agraf@suse.de>
 L: qemu-ppc@nongnu.org
 S: Supported
 F: hw/*/spapr*
@@ -1124,7 +1122,7 @@ F: tests/acpi-test-data/*
 F: tests/acpi-test-data/*/*
 
 ppc4xx
-M: Alexander Graf <agraf@suse.de>
+M: David Gibson <david@gibson.dropbear.id.au>
 L: qemu-ppc@nongnu.org
 S: Odd Fixes
 F: hw/ppc/ppc4*.c
@@ -1133,9 +1131,9 @@ F: include/hw/ppc/ppc4xx.h
 F: include/hw/i2c/ppc4xx_i2c.h
 
 ppce500
-M: Alexander Graf <agraf@suse.de>
+M: David Gibson <david@gibson.dropbear.id.au>
 L: qemu-ppc@nongnu.org
-S: Supported
+S: Odd Fixes
 F: hw/ppc/e500*
 F: hw/pci-host/ppce500.c
 F: hw/net/fsl_etsec/
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 19/22] hw/ppc/ppc440_uc: Remove dead code in sdram_size()
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (17 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 18/22] MAINTAINERS: PPC: Remove myself David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 20/22] This patch fixes processing of rfi instructions in icount mode David Gibson
                   ` (3 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell; +Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier, David Gibson

From: Peter Maydell <peter.maydell@linaro.org>

Coverity points out in CID 1390588 that the test for sh == 0
in sdram_size() can never fire, because we calculate sh with
    sh = 1024 - ((bcr >> 6) & 0x3ff);
which must result in a value between 1 and 1024 inclusive.

Without the relevant manual for the SoC, we're not completely
sure of the correct behaviour here, but we can remove the
dead code without changing how QEMU currently behaves.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/ppc440_uc.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 09ccda548f..9360f781ce 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -559,11 +559,7 @@ static target_ulong sdram_size(uint32_t bcr)
     int sh;
 
     sh = 1024 - ((bcr >> 6) & 0x3ff);
-    if (sh == 0) {
-        size = -1;
-    } else {
-        size = 8 * MiB * sh;
-    }
+    size = 8 * MiB * sh;
 
     return size;
 }
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 20/22] This patch fixes processing of rfi instructions in icount mode.
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (18 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 19/22] hw/ppc/ppc440_uc: Remove dead code in sdram_size() David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 13:17   ` Greg Kurz
  2018-11-08 12:16 ` [Qemu-devel] [PULL 21/22] target/ppc: Add one reg id for ptcr David Gibson
                   ` (2 subsequent siblings)
  22 siblings, 1 reply; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier, Maria Klimushenkova,
	Pavel Dovgalyuk, David Gibson

From: Maria Klimushenkova <maria.klimushenkova@ispras.ru>

In this mode writing to interrupt/peripheral state is controlled
by can_do_io flag. This flag must be set explicitly before helper
function invocation.

Signed-off-by: Maria Klimushenkova <maria.klimushenkova@ispras.ru>
Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 target/ppc/translate.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index fb18cedcf0..2b37910248 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -3919,9 +3919,15 @@ static void gen_rfi(DisasContext *ctx)
     }
     /* Restore CPU state */
     CHK_SV;
+    if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+        gen_io_start();
+    }
     gen_update_cfar(ctx, ctx->base.pc_next - 4);
     gen_helper_rfi(cpu_env);
     gen_sync_exception(ctx);
+    if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+        gen_io_end();
+    }
 #endif
 }
 
@@ -3933,9 +3939,15 @@ static void gen_rfid(DisasContext *ctx)
 #else
     /* Restore CPU state */
     CHK_SV;
+    if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+        gen_io_start();
+    }
     gen_update_cfar(ctx, ctx->base.pc_next - 4);
     gen_helper_rfid(cpu_env);
     gen_sync_exception(ctx);
+    if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+        gen_io_end();
+    }
 #endif
 }
 
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 21/22] target/ppc: Add one reg id for ptcr
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (19 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 20/22] This patch fixes processing of rfi instructions in icount mode David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 12:16 ` [Qemu-devel] [PULL 22/22] ppc/spapr_caps: Add SPAPR_CAP_NESTED_KVM_HV David Gibson
  2018-11-08 14:45 ` [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 Eric Blake
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier,
	Suraj Jitindar Singh, David Gibson

From: Suraj Jitindar Singh <sjitindarsingh@gmail.com>

The ptcr (partition table control register) is used to store the address
and size of the partition table. For nested kvm-hv we have a level 1
guest register the location of it's partition table with the hypervisor.
Thus to support migration we need to be able to read this out of kvm
and restore it post migration.

Add the one reg id for the ptcr.

Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 target/ppc/translate_init.inc.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index 9a2d4a9835..168d0cec28 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -8214,11 +8214,11 @@ static void gen_spr_power9_mmu(CPUPPCState *env)
 {
 #if !defined(CONFIG_USER_ONLY)
     /* Partition Table Control */
-    spr_register_hv(env, SPR_PTCR, "PTCR",
-                    SPR_NOACCESS, SPR_NOACCESS,
-                    SPR_NOACCESS, SPR_NOACCESS,
-                    &spr_read_generic, &spr_write_ptcr,
-                    0x00000000);
+    spr_register_kvm_hv(env, SPR_PTCR, "PTCR",
+                        SPR_NOACCESS, SPR_NOACCESS,
+                        SPR_NOACCESS, SPR_NOACCESS,
+                        &spr_read_generic, &spr_write_ptcr,
+                        KVM_REG_PPC_PTCR, 0x00000000);
 #endif
 }
 
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PULL 22/22] ppc/spapr_caps: Add SPAPR_CAP_NESTED_KVM_HV
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (20 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 21/22] target/ppc: Add one reg id for ptcr David Gibson
@ 2018-11-08 12:16 ` David Gibson
  2018-11-08 14:45 ` [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 Eric Blake
  22 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-08 12:16 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-ppc, qemu-devel, groug, agraf, lvivier,
	Suraj Jitindar Singh, David Gibson

From: Suraj Jitindar Singh <sjitindarsingh@gmail.com>

Add the spapr cap SPAPR_CAP_NESTED_KVM_HV to be used to control the
availability of nested kvm-hv to the level 1 (L1) guest.

Assuming a hypervisor with support enabled an L1 guest can be allowed to
use the kvm-hv module (and thus run it's own kvm-hv guests) by setting:
-machine pseries,cap-nested-hv=true
or disabled with:
-machine pseries,cap-nested-hv=false

Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/spapr.c         |  2 ++
 hw/ppc/spapr_caps.c    | 32 ++++++++++++++++++++++++++++++++
 include/hw/ppc/spapr.h |  5 ++++-
 target/ppc/kvm.c       | 12 ++++++++++++
 target/ppc/kvm_ppc.h   | 12 ++++++++++++
 5 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index e47b004b61..7afd1a175b 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1938,6 +1938,7 @@ static const VMStateDescription vmstate_spapr = {
         &vmstate_spapr_cap_sbbc,
         &vmstate_spapr_cap_ibs,
         &vmstate_spapr_irq_map,
+        &vmstate_spapr_cap_nested_kvm_hv,
         NULL
     }
 };
@@ -3902,6 +3903,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
     smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
     smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
     smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
+    smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
     spapr_caps_add_properties(smc, &error_abort);
     smc->irq = &spapr_irq_xics;
 }
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index aa605cea91..64f98ae68d 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -368,6 +368,28 @@ static void cap_hpt_maxpagesize_cpu_apply(sPAPRMachineState *spapr,
     ppc_hash64_filter_pagesizes(cpu, spapr_pagesize_cb, &maxshift);
 }
 
+static void cap_nested_kvm_hv_apply(sPAPRMachineState *spapr,
+                                    uint8_t val, Error **errp)
+{
+    if (!val) {
+        /* capability disabled by default */
+        return;
+    }
+
+    if (tcg_enabled()) {
+        error_setg(errp,
+                   "No Nested KVM-HV support in tcg, try cap-nested-hv=off");
+    } else if (kvm_enabled()) {
+        if (!kvmppc_has_cap_nested_kvm_hv()) {
+            error_setg(errp,
+"KVM implementation does not support Nested KVM-HV, try cap-nested-hv=off");
+        } else if (kvmppc_set_cap_nested_kvm_hv(val) < 0) {
+                error_setg(errp,
+"Error enabling cap-nested-hv with KVM, try cap-nested-hv=off");
+        }
+    }
+}
+
 sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
     [SPAPR_CAP_HTM] = {
         .name = "htm",
@@ -437,6 +459,15 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
         .apply = cap_hpt_maxpagesize_apply,
         .cpu_apply = cap_hpt_maxpagesize_cpu_apply,
     },
+    [SPAPR_CAP_NESTED_KVM_HV] = {
+        .name = "nested-hv",
+        .description = "Allow Nested KVM-HV",
+        .index = SPAPR_CAP_NESTED_KVM_HV,
+        .get = spapr_cap_get_bool,
+        .set = spapr_cap_set_bool,
+        .type = "bool",
+        .apply = cap_nested_kvm_hv_apply,
+    },
 };
 
 static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr,
@@ -564,6 +595,7 @@ SPAPR_CAP_MIG_STATE(dfp, SPAPR_CAP_DFP);
 SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC);
 SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC);
 SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS);
+SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
 
 void spapr_caps_init(sPAPRMachineState *spapr)
 {
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 0805ad85a1..6279711fe8 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -70,8 +70,10 @@ typedef enum {
 #define SPAPR_CAP_IBS                   0x05
 /* HPT Maximum Page Size (encoded as a shift) */
 #define SPAPR_CAP_HPT_MAXPAGESIZE       0x06
+/* Nested KVM-HV */
+#define SPAPR_CAP_NESTED_KVM_HV         0x07
 /* Num Caps */
-#define SPAPR_CAP_NUM                   (SPAPR_CAP_HPT_MAXPAGESIZE + 1)
+#define SPAPR_CAP_NUM                   (SPAPR_CAP_NESTED_KVM_HV + 1)
 
 /*
  * Capability Values
@@ -791,6 +793,7 @@ extern const VMStateDescription vmstate_spapr_cap_dfp;
 extern const VMStateDescription vmstate_spapr_cap_cfpc;
 extern const VMStateDescription vmstate_spapr_cap_sbbc;
 extern const VMStateDescription vmstate_spapr_cap_ibs;
+extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv;
 
 static inline uint8_t spapr_get_cap(sPAPRMachineState *spapr, int cap)
 {
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 30aeafa7de..f81327d6cd 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -91,6 +91,7 @@ static int cap_ppc_pvr_compat;
 static int cap_ppc_safe_cache;
 static int cap_ppc_safe_bounds_check;
 static int cap_ppc_safe_indirect_branch;
+static int cap_ppc_nested_kvm_hv;
 
 static uint32_t debug_inst_opcode;
 
@@ -150,6 +151,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
     cap_mmu_hash_v3 = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_HASH_V3);
     cap_resize_hpt = kvm_vm_check_extension(s, KVM_CAP_SPAPR_RESIZE_HPT);
     kvmppc_get_cpu_characteristics(s);
+    cap_ppc_nested_kvm_hv = kvm_vm_check_extension(s, KVM_CAP_PPC_NESTED_HV);
     /*
      * Note: setting it to false because there is not such capability
      * in KVM at this moment.
@@ -2422,6 +2424,16 @@ int kvmppc_get_cap_safe_indirect_branch(void)
     return cap_ppc_safe_indirect_branch;
 }
 
+bool kvmppc_has_cap_nested_kvm_hv(void)
+{
+    return !!cap_ppc_nested_kvm_hv;
+}
+
+int kvmppc_set_cap_nested_kvm_hv(int enable)
+{
+    return kvm_vm_enable_cap(kvm_state, KVM_CAP_PPC_NESTED_HV, 0, enable);
+}
+
 bool kvmppc_has_cap_spapr_vfio(void)
 {
     return cap_spapr_vfio;
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
index f696c6e498..bdfaa4e70a 100644
--- a/target/ppc/kvm_ppc.h
+++ b/target/ppc/kvm_ppc.h
@@ -62,6 +62,8 @@ bool kvmppc_has_cap_mmu_hash_v3(void);
 int kvmppc_get_cap_safe_cache(void);
 int kvmppc_get_cap_safe_bounds_check(void);
 int kvmppc_get_cap_safe_indirect_branch(void);
+bool kvmppc_has_cap_nested_kvm_hv(void);
+int kvmppc_set_cap_nested_kvm_hv(int enable);
 int kvmppc_enable_hwrng(void);
 int kvmppc_put_books_sregs(PowerPCCPU *cpu);
 PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void);
@@ -320,6 +322,16 @@ static inline int kvmppc_get_cap_safe_indirect_branch(void)
     return 0;
 }
 
+static inline bool kvmppc_has_cap_nested_kvm_hv(void)
+{
+    return false;
+}
+
+static inline int kvmppc_set_cap_nested_kvm_hv(int enable)
+{
+    return -1;
+}
+
 static inline int kvmppc_enable_hwrng(void)
 {
     return -1;
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PULL 20/22] This patch fixes processing of rfi instructions in icount mode.
  2018-11-08 12:16 ` [Qemu-devel] [PULL 20/22] This patch fixes processing of rfi instructions in icount mode David Gibson
@ 2018-11-08 13:17   ` Greg Kurz
  0 siblings, 0 replies; 29+ messages in thread
From: Greg Kurz @ 2018-11-08 13:17 UTC (permalink / raw)
  To: David Gibson
  Cc: peter.maydell, lvivier, agraf, qemu-devel, Maria Klimushenkova,
	qemu-ppc, Pavel Dovgalyuk

On Thu,  8 Nov 2018 23:16:44 +1100
David Gibson <david@gibson.dropbear.id.au> wrote:

> From: Maria Klimushenkova <maria.klimushenkova@ispras.ru>
> 
> In this mode writing to interrupt/peripheral state is controlled
> by can_do_io flag. This flag must be set explicitly before helper
> function invocation.
> 
> Signed-off-by: Maria Klimushenkova <maria.klimushenkova@ispras.ru>
> Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
> Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---

The 'This patch fixes ...' wording in the commit title looks weird, and
it doesn't even mention the target/ppc subsystem...

What about this ?

target/ppc: fix processing of rfi instructions in icount mode

>  target/ppc/translate.c | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index fb18cedcf0..2b37910248 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -3919,9 +3919,15 @@ static void gen_rfi(DisasContext *ctx)
>      }
>      /* Restore CPU state */
>      CHK_SV;
> +    if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
> +        gen_io_start();
> +    }
>      gen_update_cfar(ctx, ctx->base.pc_next - 4);
>      gen_helper_rfi(cpu_env);
>      gen_sync_exception(ctx);
> +    if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
> +        gen_io_end();
> +    }
>  #endif
>  }
>  
> @@ -3933,9 +3939,15 @@ static void gen_rfid(DisasContext *ctx)
>  #else
>      /* Restore CPU state */
>      CHK_SV;
> +    if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
> +        gen_io_start();
> +    }
>      gen_update_cfar(ctx, ctx->base.pc_next - 4);
>      gen_helper_rfid(cpu_env);
>      gen_sync_exception(ctx);
> +    if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
> +        gen_io_end();
> +    }
>  #endif
>  }
>  

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108
  2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
                   ` (21 preceding siblings ...)
  2018-11-08 12:16 ` [Qemu-devel] [PULL 22/22] ppc/spapr_caps: Add SPAPR_CAP_NESTED_KVM_HV David Gibson
@ 2018-11-08 14:45 ` Eric Blake
  2018-11-08 15:14   ` Peter Maydell
  22 siblings, 1 reply; 29+ messages in thread
From: Eric Blake @ 2018-11-08 14:45 UTC (permalink / raw)
  To: David Gibson, peter.maydell; +Cc: lvivier, agraf, qemu-devel, groug, qemu-ppc

On 11/8/18 6:16 AM, David Gibson wrote:
> The following changes since commit 4de6bb0c02ad3f0ec48f0f84ba1a65ab06e81b86:
> 
>    Update version for v3.1.0-rc0 release (2018-11-06 18:27:35 +0000)
> 

> 
> Maria Klimushenkova (1):
>        This patch fixes processing of rfi instructions in icount mode.

Repeating the comment on 20/22 here, in case David wants to send a v2 
respin of the PR before Peter applies this subject line as-is.

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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108
  2018-11-08 14:45 ` [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 Eric Blake
@ 2018-11-08 15:14   ` Peter Maydell
  0 siblings, 0 replies; 29+ messages in thread
From: Peter Maydell @ 2018-11-08 15:14 UTC (permalink / raw)
  To: Eric Blake
  Cc: David Gibson, Laurent Vivier, Alexander Graf, QEMU Developers,
	Greg Kurz, qemu-ppc

On 8 November 2018 at 14:45, Eric Blake <eblake@redhat.com> wrote:
> On 11/8/18 6:16 AM, David Gibson wrote:
>>
>> The following changes since commit
>> 4de6bb0c02ad3f0ec48f0f84ba1a65ab06e81b86:
>>
>>    Update version for v3.1.0-rc0 release (2018-11-06 18:27:35 +0000)
>>
>
>>
>> Maria Klimushenkova (1):
>>        This patch fixes processing of rfi instructions in icount mode.
>
>
> Repeating the comment on 20/22 here, in case David wants to send a v2 respin
> of the PR before Peter applies this subject line as-is.

...sorry, already pushed to master before I saw this.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PULL 01/22] target/ppc: add external PID support
  2018-11-08 12:16 ` [Qemu-devel] [PULL 01/22] target/ppc: add external PID support David Gibson
@ 2018-11-15 10:22   ` Peter Maydell
  2018-11-19 16:39     ` Peter Maydell
  0 siblings, 1 reply; 29+ messages in thread
From: Peter Maydell @ 2018-11-15 10:22 UTC (permalink / raw)
  To: David Gibson
  Cc: qemu-ppc, QEMU Developers, Greg Kurz, Alexander Graf,
	Laurent Vivier, Roman Kapl

On 8 November 2018 at 12:16, David Gibson <david@gibson.dropbear.id.au> wrote:
> From: Roman Kapl <rka@sysgo.com>
>
> External PID is a mechanism present on BookE 2.06 that enables application to
> store/load data from different address spaces. There are special version of some
> instructions, which operate on alternate address space, which is specified in
> the EPLC/EPSC regiser.
>
> This implementation uses two additional MMU modes (mmu_idx) to provide the
> address space for the load and store instructions. The QEMU TLB fill code was
> modified to recognize these MMU modes and use the values in EPLC/EPSC to find
> the proper entry in he PPC TLB. These two QEMU TLBs are also flushed on each
> write to EPLC/EPSC.
>
> Following instructions are implemented: dcbfep dcbstep dcbtep dcbtstep dcbzep
> dcbzlep icbiep lbepx ldepx lfdepx lhepx lwepx stbepx stdepx stfdepx sthepx
> stwepx.
>
> Following vector instructions are not: evlddepx evstddepx lvepx lvepxl stvepx
> stvepxl.

Hi; Coverity reports an issue (CID1396864) with this function:

> +/* dcbfep (external PID dcbf) */
> +static void gen_dcbfep(DisasContext *ctx)
> +{
> +    /* XXX: specification says this is treated as a load by the MMU */
> +    TCGv t0;
> +    CHK_SV;
> +    gen_set_access_type(ctx, ACCESS_CACHE);
> +    t0 = tcg_temp_new();
> +    gen_addr_reg_index(ctx, t0);
> +    tcg_gen_qemu_ld_tl(t0, t0, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_UB));
> +    tcg_temp_free(t0);
> +}

It says that the gen_set_access_type() call is unreachable. I think
this is a false positive (the code is unreachable, but only if
CONFIG_USER_ONLY is defined). On the other hand, all the other
similar gen_* functions in this file that use CHK_SV seem to have
a pattern of

#if defined(CONFIG_USER_ONLY)
    GEN_PRIV;
#else
    TCGv t0;
    CHK_SV;
    [etc]
#endif

so maybe we should do that here too for consistency?

thanks
-- PMM

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PULL 01/22] target/ppc: add external PID support
  2018-11-15 10:22   ` Peter Maydell
@ 2018-11-19 16:39     ` Peter Maydell
  2018-11-25  8:22       ` David Gibson
  0 siblings, 1 reply; 29+ messages in thread
From: Peter Maydell @ 2018-11-19 16:39 UTC (permalink / raw)
  To: David Gibson
  Cc: qemu-ppc, QEMU Developers, Greg Kurz, Alexander Graf,
	Laurent Vivier, Roman Kapl

On 15 November 2018 at 10:22, Peter Maydell <peter.maydell@linaro.org> wrote:
> Hi; Coverity reports an issue (CID1396864) with this function:
>
>> +/* dcbfep (external PID dcbf) */
>> +static void gen_dcbfep(DisasContext *ctx)
>> +{
>> +    /* XXX: specification says this is treated as a load by the MMU */
>> +    TCGv t0;
>> +    CHK_SV;
>> +    gen_set_access_type(ctx, ACCESS_CACHE);
>> +    t0 = tcg_temp_new();
>> +    gen_addr_reg_index(ctx, t0);
>> +    tcg_gen_qemu_ld_tl(t0, t0, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_UB));
>> +    tcg_temp_free(t0);
>> +}
>
> It says that the gen_set_access_type() call is unreachable. I think
> this is a false positive (the code is unreachable, but only if
> CONFIG_USER_ONLY is defined). On the other hand, all the other
> similar gen_* functions in this file that use CHK_SV seem to have
> a pattern of
>
> #if defined(CONFIG_USER_ONLY)
>     GEN_PRIV;
> #else
>     TCGv t0;
>     CHK_SV;
>     [etc]
> #endif
>
> so maybe we should do that here too for consistency?

I've marked the issue as a false-positive in Coverity (since it is,
and that's what we've done with some equivalent target/ppc Coverity
issues with other functions previously). I'll let you decide whether
you want to prefer "with ifdefs" or "without". (TBH I think the
"without" style is better here.)

thanks
-- PMM

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PULL 01/22] target/ppc: add external PID support
  2018-11-19 16:39     ` Peter Maydell
@ 2018-11-25  8:22       ` David Gibson
  0 siblings, 0 replies; 29+ messages in thread
From: David Gibson @ 2018-11-25  8:22 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-ppc, QEMU Developers, Greg Kurz, Alexander Graf,
	Laurent Vivier, Roman Kapl

[-- Attachment #1: Type: text/plain, Size: 1879 bytes --]

On Mon, Nov 19, 2018 at 04:39:29PM +0000, Peter Maydell wrote:
> On 15 November 2018 at 10:22, Peter Maydell <peter.maydell@linaro.org> wrote:
> > Hi; Coverity reports an issue (CID1396864) with this function:
> >
> >> +/* dcbfep (external PID dcbf) */
> >> +static void gen_dcbfep(DisasContext *ctx)
> >> +{
> >> +    /* XXX: specification says this is treated as a load by the MMU */
> >> +    TCGv t0;
> >> +    CHK_SV;
> >> +    gen_set_access_type(ctx, ACCESS_CACHE);
> >> +    t0 = tcg_temp_new();
> >> +    gen_addr_reg_index(ctx, t0);
> >> +    tcg_gen_qemu_ld_tl(t0, t0, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_UB));
> >> +    tcg_temp_free(t0);
> >> +}
> >
> > It says that the gen_set_access_type() call is unreachable. I think
> > this is a false positive (the code is unreachable, but only if
> > CONFIG_USER_ONLY is defined). On the other hand, all the other
> > similar gen_* functions in this file that use CHK_SV seem to have
> > a pattern of
> >
> > #if defined(CONFIG_USER_ONLY)
> >     GEN_PRIV;
> > #else
> >     TCGv t0;
> >     CHK_SV;
> >     [etc]
> > #endif
> >
> > so maybe we should do that here too for consistency?
> 
> I've marked the issue as a false-positive in Coverity (since it is,
> and that's what we've done with some equivalent target/ppc Coverity
> issues with other functions previously). I'll let you decide whether
> you want to prefer "with ifdefs" or "without". (TBH I think the
> "without" style is better here.)

I tend to agree, but are you ok dealing with the whole slew of
Coverity false positives it will create if we move to that style?
AFAIK, I don't have the power to deal with it from my end.

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

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2018-11-25  8:22 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-08 12:16 [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 01/22] target/ppc: add external PID support David Gibson
2018-11-15 10:22   ` Peter Maydell
2018-11-19 16:39     ` Peter Maydell
2018-11-25  8:22       ` David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 02/22] ppc440_pcix: convert SysBus init method to a realize method David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 03/22] ppc4xx_pci: " David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 04/22] PPC: e500: " David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 05/22] hw/ppc/spapr_rng: Introduce CONFIG_SPAPR_RNG switch for spapr_rng.c David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 06/22] target/ppc: Split up float_invalid_op_excp David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 07/22] target/ppc: Remove float_check_status David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 08/22] target/ppc: Introduce fp number classification David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 09/22] target/ppc: Split out float_invalid_op_addsub David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 10/22] target/ppc: Split out float_invalid_op_mul David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 11/22] target/ppc: Split out float_invalid_op_div David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 12/22] target/ppc: Split out float_invalid_cvt David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 13/22] spapr_pci: convert g_malloc() to g_new() David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 14/22] macio/pmu: Fix missing vmsd terminator David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 15/22] hw/ppc/mac_newworld: Free openpic_irqs array after use David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 16/22] target/ppc: fix mtmsr instruction for icount David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 17/22] ppc/pnv: check size before data buffer access David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 18/22] MAINTAINERS: PPC: Remove myself David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 19/22] hw/ppc/ppc440_uc: Remove dead code in sdram_size() David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 20/22] This patch fixes processing of rfi instructions in icount mode David Gibson
2018-11-08 13:17   ` Greg Kurz
2018-11-08 12:16 ` [Qemu-devel] [PULL 21/22] target/ppc: Add one reg id for ptcr David Gibson
2018-11-08 12:16 ` [Qemu-devel] [PULL 22/22] ppc/spapr_caps: Add SPAPR_CAP_NESTED_KVM_HV David Gibson
2018-11-08 14:45 ` [Qemu-devel] [PULL 00/22] ppc-for-3.1 queue 20181108 Eric Blake
2018-11-08 15:14   ` Peter Maydell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.