summary refs log tree commit diff stats
path: root/target/ppc
diff options
context:
space:
mode:
Diffstat (limited to 'target/ppc')
-rw-r--r--target/ppc/cpu-qom.h1
-rw-r--r--target/ppc/cpu.h105
-rw-r--r--target/ppc/translate.c23
-rw-r--r--target/ppc/translate_init.c26
4 files changed, 79 insertions, 76 deletions
diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h
index 429b47f959..deaa46a14b 100644
--- a/target/ppc/cpu-qom.h
+++ b/target/ppc/cpu-qom.h
@@ -191,6 +191,7 @@ typedef struct PowerPCCPUClass {
     uint64_t insns_flags;
     uint64_t insns_flags2;
     uint64_t msr_mask;
+    uint64_t lpcr_pm;           /* Power-saving mode Exit Cause Enable bits */
     powerpc_mmu_t   mmu_model;
     powerpc_excp_t  excp_model;
     powerpc_input_t bus_model;
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 989761b795..370b05e76e 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -87,6 +87,13 @@
 #define PPC_ELF_MACHINE     EM_PPC
 #endif
 
+#define PPC_BIT(bit)            (0x8000000000000000UL >> (bit))
+#define PPC_BIT32(bit)          (0x80000000UL >> (bit))
+#define PPC_BIT8(bit)           (0x80UL >> (bit))
+#define PPC_BITMASK(bs, be)     ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs))
+#define PPC_BITMASK32(bs, be)   ((PPC_BIT32(bs) - PPC_BIT32(be)) | \
+                                 PPC_BIT32(bs))
+
 /*****************************************************************************/
 /* Exception vectors definitions                                             */
 enum {
@@ -371,10 +378,10 @@ struct ppc_slb_t {
 #define MSR_LE   0  /* Little-endian mode                           1 hflags */
 
 /* LPCR bits */
-#define LPCR_VPM0         (1ull << (63 - 0))
-#define LPCR_VPM1         (1ull << (63 - 1))
-#define LPCR_ISL          (1ull << (63 - 2))
-#define LPCR_KBV          (1ull << (63 - 3))
+#define LPCR_VPM0         PPC_BIT(0)
+#define LPCR_VPM1         PPC_BIT(1)
+#define LPCR_ISL          PPC_BIT(2)
+#define LPCR_KBV          PPC_BIT(3)
 #define LPCR_DPFD_SHIFT   (63 - 11)
 #define LPCR_DPFD         (0x7ull << LPCR_DPFD_SHIFT)
 #define LPCR_VRMASD_SHIFT (63 - 16)
@@ -382,41 +389,41 @@ struct ppc_slb_t {
 /* P9: Power-saving mode Exit Cause Enable (Upper Section) Mask */
 #define LPCR_PECE_U_SHIFT (63 - 19)
 #define LPCR_PECE_U_MASK  (0x7ull << LPCR_PECE_U_SHIFT)
-#define LPCR_HVEE         (1ull << (63 - 17)) /* Hypervisor Virt Exit Enable */
+#define LPCR_HVEE         PPC_BIT(17) /* Hypervisor Virt Exit Enable */
 #define LPCR_RMLS_SHIFT   (63 - 37)
 #define LPCR_RMLS         (0xfull << LPCR_RMLS_SHIFT)
-#define LPCR_ILE          (1ull << (63 - 38))
+#define LPCR_ILE          PPC_BIT(38)
 #define LPCR_AIL_SHIFT    (63 - 40)      /* Alternate interrupt location */
 #define LPCR_AIL          (3ull << LPCR_AIL_SHIFT)
-#define LPCR_UPRT         (1ull << (63 - 41)) /* Use Process Table */
-#define LPCR_EVIRT        (1ull << (63 - 42)) /* Enhanced Virtualisation */
-#define LPCR_ONL          (1ull << (63 - 45))
-#define LPCR_LD           (1ull << (63 - 46)) /* Large Decrementer */
-#define LPCR_P7_PECE0     (1ull << (63 - 49))
-#define LPCR_P7_PECE1     (1ull << (63 - 50))
-#define LPCR_P7_PECE2     (1ull << (63 - 51))
-#define LPCR_P8_PECE0     (1ull << (63 - 47))
-#define LPCR_P8_PECE1     (1ull << (63 - 48))
-#define LPCR_P8_PECE2     (1ull << (63 - 49))
-#define LPCR_P8_PECE3     (1ull << (63 - 50))
-#define LPCR_P8_PECE4     (1ull << (63 - 51))
+#define LPCR_UPRT         PPC_BIT(41) /* Use Process Table */
+#define LPCR_EVIRT        PPC_BIT(42) /* Enhanced Virtualisation */
+#define LPCR_ONL          PPC_BIT(45)
+#define LPCR_LD           PPC_BIT(46) /* Large Decrementer */
+#define LPCR_P7_PECE0     PPC_BIT(49)
+#define LPCR_P7_PECE1     PPC_BIT(50)
+#define LPCR_P7_PECE2     PPC_BIT(51)
+#define LPCR_P8_PECE0     PPC_BIT(47)
+#define LPCR_P8_PECE1     PPC_BIT(48)
+#define LPCR_P8_PECE2     PPC_BIT(49)
+#define LPCR_P8_PECE3     PPC_BIT(50)
+#define LPCR_P8_PECE4     PPC_BIT(51)
 /* P9: Power-saving mode Exit Cause Enable (Lower Section) Mask */
 #define LPCR_PECE_L_SHIFT (63 - 51)
 #define LPCR_PECE_L_MASK  (0x1full << LPCR_PECE_L_SHIFT)
-#define LPCR_PDEE         (1ull << (63 - 47)) /* Privileged Doorbell Exit EN */
-#define LPCR_HDEE         (1ull << (63 - 48)) /* Hyperv Doorbell Exit Enable */
-#define LPCR_EEE          (1ull << (63 - 49)) /* External Exit Enable        */
-#define LPCR_DEE          (1ull << (63 - 50)) /* Decrementer Exit Enable     */
-#define LPCR_OEE          (1ull << (63 - 51)) /* Other Exit Enable           */
-#define LPCR_MER          (1ull << (63 - 52))
-#define LPCR_GTSE         (1ull << (63 - 53)) /* Guest Translation Shootdown */
-#define LPCR_TC           (1ull << (63 - 54))
-#define LPCR_HEIC         (1ull << (63 - 59)) /* HV Extern Interrupt Control */
-#define LPCR_LPES0        (1ull << (63 - 60))
-#define LPCR_LPES1        (1ull << (63 - 61))
-#define LPCR_RMI          (1ull << (63 - 62))
-#define LPCR_HVICE        (1ull << (63 - 62)) /* HV Virtualisation Int Enable */
-#define LPCR_HDICE        (1ull << (63 - 63))
+#define LPCR_PDEE         PPC_BIT(47) /* Privileged Doorbell Exit EN */
+#define LPCR_HDEE         PPC_BIT(48) /* Hyperv Doorbell Exit Enable */
+#define LPCR_EEE          PPC_BIT(49) /* External Exit Enable        */
+#define LPCR_DEE          PPC_BIT(50) /* Decrementer Exit Enable     */
+#define LPCR_OEE          PPC_BIT(51) /* Other Exit Enable           */
+#define LPCR_MER          PPC_BIT(52)
+#define LPCR_GTSE         PPC_BIT(53) /* Guest Translation Shootdown */
+#define LPCR_TC           PPC_BIT(54)
+#define LPCR_HEIC         PPC_BIT(59) /* HV Extern Interrupt Control */
+#define LPCR_LPES0        PPC_BIT(60)
+#define LPCR_LPES1        PPC_BIT(61)
+#define LPCR_RMI          PPC_BIT(62)
+#define LPCR_HVICE        PPC_BIT(62) /* HV Virtualisation Int Enable */
+#define LPCR_HDICE        PPC_BIT(63)
 
 #define msr_sf   ((env->msr >> MSR_SF)   & 1)
 #define msr_isf  ((env->msr >> MSR_ISF)  & 1)
@@ -507,22 +514,22 @@ struct ppc_slb_t {
 #define FSCR_IC_TAR         8
 
 /* Exception state register bits definition                                  */
-#define ESR_PIL   (1 << (63 - 36)) /* Illegal Instruction                    */
-#define ESR_PPR   (1 << (63 - 37)) /* Privileged Instruction                 */
-#define ESR_PTR   (1 << (63 - 38)) /* Trap                                   */
-#define ESR_FP    (1 << (63 - 39)) /* Floating-Point Operation               */
-#define ESR_ST    (1 << (63 - 40)) /* Store Operation                        */
-#define ESR_AP    (1 << (63 - 44)) /* Auxiliary Processor Operation          */
-#define ESR_PUO   (1 << (63 - 45)) /* Unimplemented Operation                */
-#define ESR_BO    (1 << (63 - 46)) /* Byte Ordering                          */
-#define ESR_PIE   (1 << (63 - 47)) /* Imprecise exception                    */
-#define ESR_DATA  (1 << (63 - 53)) /* Data Access (Embedded page table)      */
-#define ESR_TLBI  (1 << (63 - 54)) /* TLB Ineligible (Embedded page table)   */
-#define ESR_PT    (1 << (63 - 55)) /* Page Table (Embedded page table)       */
-#define ESR_SPV   (1 << (63 - 56)) /* SPE/VMX operation                      */
-#define ESR_EPID  (1 << (63 - 57)) /* External Process ID operation          */
-#define ESR_VLEMI (1 << (63 - 58)) /* VLE operation                          */
-#define ESR_MIF   (1 << (63 - 62)) /* Misaligned instruction (VLE)           */
+#define ESR_PIL   PPC_BIT(36) /* Illegal Instruction                    */
+#define ESR_PPR   PPC_BIT(37) /* Privileged Instruction                 */
+#define ESR_PTR   PPC_BIT(38) /* Trap                                   */
+#define ESR_FP    PPC_BIT(39) /* Floating-Point Operation               */
+#define ESR_ST    PPC_BIT(40) /* Store Operation                        */
+#define ESR_AP    PPC_BIT(44) /* Auxiliary Processor Operation          */
+#define ESR_PUO   PPC_BIT(45) /* Unimplemented Operation                */
+#define ESR_BO    PPC_BIT(46) /* Byte Ordering                          */
+#define ESR_PIE   PPC_BIT(47) /* Imprecise exception                    */
+#define ESR_DATA  PPC_BIT(53) /* Data Access (Embedded page table)      */
+#define ESR_TLBI  PPC_BIT(54) /* TLB Ineligible (Embedded page table)   */
+#define ESR_PT    PPC_BIT(55) /* Page Table (Embedded page table)       */
+#define ESR_SPV   PPC_BIT(56) /* SPE/VMX operation                      */
+#define ESR_EPID  PPC_BIT(57) /* External Process ID operation          */
+#define ESR_VLEMI PPC_BIT(58) /* VLE operation                          */
+#define ESR_MIF   PPC_BIT(62) /* Misaligned instruction (VLE)           */
 
 /* Transaction EXception And Summary Register bits                           */
 #define TEXASR_FAILURE_PERSISTENT                (63 - 7)
@@ -1991,7 +1998,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
 #define HID0_DEEPNAP        (1 << 24)           /* pre-2.06 */
 #define HID0_DOZE           (1 << 23)           /* pre-2.06 */
 #define HID0_NAP            (1 << 22)           /* pre-2.06 */
-#define HID0_HILE           (1ull << (63 - 19)) /* POWER8 */
+#define HID0_HILE           PPC_BIT(19) /* POWER8 */
 
 /*****************************************************************************/
 /* PowerPC Instructions types definitions                                    */
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 998fbed848..4075fc8589 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -3419,7 +3419,7 @@ static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
 }
 
 /***                                Branch                                 ***/
-static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
+static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
 {
     if (NARROW_MODE(ctx)) {
         dest = (uint32_t) dest;
@@ -3441,7 +3441,7 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
                 gen_debug_exception(ctx);
             }
         }
-        tcg_gen_exit_tb(0);
+        tcg_gen_lookup_and_goto_ptr();
     }
 }
 
@@ -3479,7 +3479,7 @@ static void gen_b(DisasContext *ctx)
 #define BCOND_CTR 2
 #define BCOND_TAR 3
 
-static inline void gen_bcond(DisasContext *ctx, int type)
+static void gen_bcond(DisasContext *ctx, int type)
 {
     uint32_t bo = BO(ctx->opcode);
     TCGLabel *l1;
@@ -3543,26 +3543,19 @@ static inline void gen_bcond(DisasContext *ctx, int type)
         } else {
             gen_goto_tb(ctx, 0, li);
         }
-        if ((bo & 0x14) != 0x14) {
-            gen_set_label(l1);
-            gen_goto_tb(ctx, 1, ctx->nip);
-        }
     } else {
         if (NARROW_MODE(ctx)) {
             tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
         } else {
             tcg_gen_andi_tl(cpu_nip, target, ~3);
         }
-        tcg_gen_exit_tb(0);
-        if ((bo & 0x14) != 0x14) {
-            gen_set_label(l1);
-            gen_update_nip(ctx, ctx->nip);
-            tcg_gen_exit_tb(0);
-        }
-    }
-    if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) {
+        tcg_gen_lookup_and_goto_ptr();
         tcg_temp_free(target);
     }
+    if ((bo & 0x14) != 0x14) {
+        gen_set_label(l1);
+        gen_goto_tb(ctx, 1, ctx->nip);
+    }
 }
 
 static void gen_bc(DisasContext *ctx)
diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c
index 4e11e6f489..70ff15a51a 100644
--- a/target/ppc/translate_init.c
+++ b/target/ppc/translate_init.c
@@ -8535,6 +8535,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
     pcc->l1_dcache_size = 0x8000;
     pcc->l1_icache_size = 0x8000;
     pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
+    pcc->lpcr_pm = LPCR_P7_PECE0 | LPCR_P7_PECE1 | LPCR_P7_PECE2;
 }
 
 static void init_proc_POWER8(CPUPPCState *env)
@@ -8704,6 +8705,8 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
     pcc->l1_dcache_size = 0x8000;
     pcc->l1_icache_size = 0x8000;
     pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
+    pcc->lpcr_pm = LPCR_P8_PECE0 | LPCR_P8_PECE1 | LPCR_P8_PECE2 |
+                   LPCR_P8_PECE3 | LPCR_P8_PECE4;
 }
 
 #ifdef CONFIG_SOFTMMU
@@ -8898,14 +8901,17 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
     pcc->l1_dcache_size = 0x8000;
     pcc->l1_icache_size = 0x8000;
     pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
+    pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE;
 }
 
 #if !defined(CONFIG_USER_ONLY)
 void cpu_ppc_set_papr(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp)
 {
+    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
     CPUPPCState *env = &cpu->env;
     ppc_spr_t *lpcr = &env->spr_cb[SPR_LPCR];
     ppc_spr_t *amor = &env->spr_cb[SPR_AMOR];
+    CPUState *cs = CPU(cpu);
 
     cpu->vhyp = vhyp;
 
@@ -8932,8 +8938,7 @@ void cpu_ppc_set_papr(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp)
     lpcr->default_value &= ~LPCR_RMLS;
     lpcr->default_value |= 1ull << LPCR_RMLS_SHIFT;
 
-    switch (env->mmu_model) {
-    case POWERPC_MMU_3_00:
+    if (env->mmu_model == POWERPC_MMU_3_00) {
         /* By default we choose legacy mode and switch to new hash or radix
          * when a register process table hcall is made. So disable process
          * tables and guest translation shootdown by default
@@ -8947,16 +8952,13 @@ void cpu_ppc_set_papr(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp)
         } else {
             lpcr->default_value &= ~(LPCR_UPRT | LPCR_GTSE);
         }
-        lpcr->default_value |= LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE |
-                               LPCR_OEE;
-        break;
-    default:
-        /* P7 and P8 has slightly different PECE bits, mostly because P8 adds
-         * bit 47 and 48 which are reserved on P7. Here we set them all, which
-         * will work as expected for both implementations
-         */
-        lpcr->default_value |= LPCR_P8_PECE0 | LPCR_P8_PECE1 | LPCR_P8_PECE2 |
-                               LPCR_P8_PECE3 | LPCR_P8_PECE4;
+    }
+
+    /* Only enable Power-saving mode Exit Cause exceptions on the boot
+     * CPU. The RTAS command start-cpu will enable them on secondaries.
+     */
+    if (cs == first_cpu) {
+        lpcr->default_value |= pcc->lpcr_pm;
     }
 
     /* We should be followed by a CPU reset but update the active value