diff mbox

[v4,20/29] target-ppc: Add POWER8's FSCR SPR

Message ID 1401787684-31895-21-git-send-email-aik@ozlabs.ru
State New
Headers show

Commit Message

Alexey Kardashevskiy June 3, 2014, 9:27 a.m. UTC
This adds an FSCR (Facility Status and Control Register) SPR. This defines
names for FSCR bits.

This defines new exception type - POWERPC_EXCP_FU - "facility unavailable" (FU).
This registers an interrupt vector for it at 0xF60 as PowerISA defines.

This adds a TCG helper_fscr_facility_check() helper to raise an exception
if the facility is not enabled. It updates the interrupt cause field
in FSCR. This adds a TCG translation block generation code. The helper
may be used for HFSCR too as it has the same format.

The helper raising FU exceptions is not used by this patch but will be
in the next ones.

This adds gen_update_current_nip() to update NIP in DisasContext.
This helper is not used now and will be called before checking for
a condition for throwing an FU exception.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
Changes:
v4:
* added gen_update_current_nip()
* it is gen_spr_power8_fscr() now instead of gen_spr_power8_common()
* added "facility unavailable" exception vector at 0xF60
---
 target-ppc/cpu.h            | 16 ++++++++++++++++
 target-ppc/excp_helper.c    |  5 +++++
 target-ppc/helper.h         |  1 +
 target-ppc/misc_helper.c    | 27 +++++++++++++++++++++++++++
 target-ppc/translate.c      |  7 +++++++
 target-ppc/translate_init.c | 10 ++++++++++
 6 files changed, 66 insertions(+)
diff mbox

Patch

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 8f43b37..32fadcd 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -238,6 +238,7 @@  enum {
     POWERPC_EXCP_DTLBE    = 93, /* Data TLB error                            */
     /* VSX Unavailable (Power ISA 2.06 and later)                            */
     POWERPC_EXCP_VSXU     = 94, /* VSX Unavailable                           */
+    POWERPC_EXCP_FU       = 95, /* Facility Unavailable                      */
     /* EOL                                                                   */
     POWERPC_EXCP_NB       = 96,
     /* QEMU exceptions: used internally during code translation              */
@@ -516,6 +517,19 @@  struct ppc_slb_t {
 #endif
 #endif
 
+/* Facility Status and Control (FSCR) bits */
+#define FSCR_EBB        (63 - 56) /* Event-Based Branch Facility */
+#define FSCR_TAR        (63 - 55) /* Target Address Register */
+/* Interrupt cause mask and position in FSCR. HFSCR has the same format */
+#define FSCR_IC_MASK    (0xFFULL)
+#define FSCR_IC_POS     (63 - 7)
+#define FSCR_IC_DSCR_SPR3   2
+#define FSCR_IC_PMU         3
+#define FSCR_IC_BHRB        4
+#define FSCR_IC_TM          5
+#define FSCR_IC_EBB         7
+#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                 */
@@ -1104,6 +1118,7 @@  do {                                            \
 /*****************************************************************************/
 PowerPCCPU *cpu_ppc_init(const char *cpu_model);
 void ppc_translate_init(void);
+void gen_update_current_nip(void *opaque);
 int cpu_ppc_exec (CPUPPCState *s);
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
@@ -1272,6 +1287,7 @@  static inline int cpu_mmu_index (CPUPPCState *env)
 #define SPR_CTRL              (0x098)
 #define SPR_MPC_CMPE          (0x098)
 #define SPR_MPC_CMPF          (0x099)
+#define SPR_FSCR              (0x099)
 #define SPR_MPC_CMPG          (0x09A)
 #define SPR_MPC_CMPH          (0x09B)
 #define SPR_MPC_LCTRL1        (0x09C)
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index 4fa297d..fd89d99 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -398,6 +398,11 @@  static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
             new_msr |= (target_ulong)MSR_HVB;
         }
         goto store_current;
+    case POWERPC_EXCP_FU:         /* Facility unavailable exception          */
+        if (lpes1 == 0) {
+            new_msr |= (target_ulong)MSR_HVB;
+        }
+        goto store_current;
     case POWERPC_EXCP_PIT:       /* Programmable interval timer interrupt    */
         LOG_EXCP("PIT exception\n");
         goto store_next;
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 4c795f2..9041ba0 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -579,6 +579,7 @@  DEF_HELPER_3(store_dcr, void, env, tl, tl)
 
 DEF_HELPER_2(load_dump_spr, void, env, i32)
 DEF_HELPER_2(store_dump_spr, void, env, i32)
+DEF_HELPER_4(fscr_facility_check, void, env, i32, i32, i32)
 DEF_HELPER_1(load_tbl, tl, env)
 DEF_HELPER_1(load_tbu, tl, env)
 DEF_HELPER_1(load_atbl, tl, env)
diff --git a/target-ppc/misc_helper.c b/target-ppc/misc_helper.c
index 2eb2fa6..9ef18c4 100644
--- a/target-ppc/misc_helper.c
+++ b/target-ppc/misc_helper.c
@@ -34,6 +34,33 @@  void helper_store_dump_spr(CPUPPCState *env, uint32_t sprn)
     qemu_log("Write SPR %d %03x <= " TARGET_FMT_lx "\n", sprn, sprn,
              env->spr[sprn]);
 }
+
+#ifdef TARGET_PPC64
+static void raise_fu_exception(CPUPPCState *env, uint32_t bit,
+                               uint32_t sprn, uint32_t cause)
+{
+    qemu_log("Facility SPR %d is unavailable (SPR FSCR:%d)\n", sprn, bit);
+
+    env->spr[SPR_FSCR] &= ~((target_ulong)FSCR_IC_MASK << FSCR_IC_POS);
+    cause &= FSCR_IC_MASK;
+    env->spr[SPR_FSCR] |= (target_ulong)cause << FSCR_IC_POS;
+
+    helper_raise_exception_err(env, POWERPC_EXCP_FU, 0);
+}
+#endif
+
+void helper_fscr_facility_check(CPUPPCState *env, uint32_t bit,
+                                uint32_t sprn, uint32_t cause)
+{
+#ifdef TARGET_PPC64
+    if (env->spr[SPR_FSCR] & (1ULL << bit)) {
+        /* Facility is enabled, continue */
+        return;
+    }
+    raise_fu_exception(env, bit, sprn, cause);
+#endif
+}
+
 #if !defined(CONFIG_USER_ONLY)
 
 void helper_store_sdr1(CPUPPCState *env, target_ulong val)
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index fb2b18b..f330a13 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -290,6 +290,13 @@  static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
     tcg_gen_movi_tl(cpu_nip, nip);
 }
 
+void gen_update_current_nip(void *opaque)
+{
+    DisasContext *ctx = opaque;
+
+    tcg_gen_movi_tl(cpu_nip, ctx->nip);
+}
+
 static inline void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
 {
     TCGv_i32 t0, t1;
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index c41d289..6f0c36b 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -3073,6 +3073,7 @@  static void init_excp_POWER7 (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_PERFM]    = 0x00000F00;
     env->excp_vectors[POWERPC_EXCP_VPU]      = 0x00000F20;
     env->excp_vectors[POWERPC_EXCP_VSXU]     = 0x00000F40;
+    env->excp_vectors[POWERPC_EXCP_FU]       = 0x00000F60;
     env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
     env->excp_vectors[POWERPC_EXCP_MAINT]    = 0x00001600;
     env->excp_vectors[POWERPC_EXCP_VPUA]     = 0x00001700;
@@ -7575,6 +7576,14 @@  static void gen_spr_power8_tce_address_control(CPUPPCState *env)
                  0x00000000);
 }
 
+static void gen_spr_power8_fscr(CPUPPCState *env)
+{
+    spr_register_kvm(env, SPR_FSCR, "FSCR",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_FSCR, 0x00000000);
+}
+
 static void init_proc_book3s_64(CPUPPCState *env, int version)
 {
     gen_spr_ne_601(env);
@@ -7619,6 +7628,7 @@  static void init_proc_book3s_64(CPUPPCState *env, int version)
     }
     if (version >= BOOK3S_CPU_POWER8) {
         gen_spr_power8_tce_address_control(env);
+        gen_spr_power8_fscr(env);
     }
 #if !defined(CONFIG_USER_ONLY)
     switch (version) {