qemu-ppc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-ppc] [PATCH v3 20/24] target-ppc: Add more POWER8's branch con


From: Alexander Graf
Subject: Re: [Qemu-ppc] [PATCH v3 20/24] target-ppc: Add more POWER8's branch control SPRs
Date: Wed, 28 May 2014 02:30:50 +0200
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:24.0) Gecko/20100101 Thunderbird/24.5.0


On 27.05.14 12:37, Alexey Kardashevskiy wrote:
POWER8 supports Event-Based Branch Facility (EBB) and Target Address
Register (TAR). They are controlled via set of SPRs access to which
should generate an "Facility Unavailable" interrupt if the facilities
are not enabled in FSCR for problem state.

This adds EBB and TAR SPRs.

This adds check_spr_bit() helper to read and test SPR, it is used for FSCR.
This defines two bits in FSCR - per EEB and TAR facilities.

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

Signed-off-by: Alexey Kardashevskiy <address@hidden>
---
  target-ppc/cpu.h            | 12 +++++++
  target-ppc/excp_helper.c    |  5 +++
  target-ppc/translate_init.c | 87 +++++++++++++++++++++++++++++++++++++++++++++
  3 files changed, 104 insertions(+)

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 778b7d7..3e8b126 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,10 @@ 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 */
+
  /* Exception state register bits definition                                  
*/
  #define ESR_PIL   (1 << (63 - 36)) /* Illegal Instruction                    
*/
  #define ESR_PPR   (1 << (63 - 37)) /* Privileged Instruction                 
*/
@@ -1547,11 +1552,18 @@ static inline int cpu_mmu_index (CPUPPCState *env)
  #define SPR_UPERFF            (0x31F)
  #define SPR_RCPU_MI_RA0       (0x320)
  #define SPR_MPC_MI_DBCAM      (0x320)
+#define SPR_BESCRS            (0x320)
  #define SPR_RCPU_MI_RA1       (0x321)
  #define SPR_MPC_MI_DBRAM0     (0x321)
+#define SPR_BESCRSU           (0x321)
  #define SPR_RCPU_MI_RA2       (0x322)
  #define SPR_MPC_MI_DBRAM1     (0x322)
+#define SPR_BESCRR            (0x322)
  #define SPR_RCPU_MI_RA3       (0x323)
+#define SPR_BESCRRU           (0x323)
+#define SPR_EBBHR             (0x324)
+#define SPR_EBBRR             (0x325)
+#define SPR_BESCR             (0x326)
  #define SPR_RCPU_L2U_RA0      (0x328)
  #define SPR_MPC_MD_DBCAM      (0x328)
  #define SPR_RCPU_L2U_RA1      (0x329)
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/translate_init.c b/target-ppc/translate_init.c
index 9dda60e..f0be5b1 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -3104,6 +3104,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;
@@ -7614,12 +7615,98 @@ static void gen_spr_book3s_pcr(CPUPPCState *env)
                   0x00000000);
  }
+static bool check_spr_bit(void *ctx, int sprn, int bit)
+{
+    TCGv t = tcg_temp_new();
+    bool ret = true;
+
+    gen_load_spr(t, sprn);
+    if (!(GET_TCGV_I64(t) & (1 << bit))) {
+        gen_inval_exception(ctx, POWERPC_EXCP_FU);
+        ret = false;
+    }

That doesn't work. You have 2 phases:

  1) Translation
  2) Execution

The code above gets executed during the translation phase, when we generate host native code. But the check you're trying to do only happens during the execution phase.

So instead, you want to create a C helper in misc_helper.c (I think, not 100% sure where it fits best) and generate a call to that one here. Inside that C helper you could just use env.

Please always keep in mind that your code might have to run on a 32bit host, so constructs like (1 << bit) are scary :).


Alex

+
+    tcg_temp_free(t);
+
+    return ret;
+}
+
+static void spr_read_ebb_generic(void *opaque, int gprn, int sprn)
+{
+    if (check_spr_bit(opaque, SPR_FSCR, FSCR_EBB)) {
+        spr_read_generic(opaque, sprn, gprn);
+    }
+}
+
+static void spr_write_ebb_generic(void *opaque, int sprn, int gprn)
+{
+    if (check_spr_bit(opaque, SPR_FSCR, FSCR_EBB)) {
+        spr_write_generic(opaque, sprn, gprn);
+    }
+}
+
+static void spr_read_ebb_upper32(void *opaque, int gprn, int sprn)
+{
+    if (check_spr_bit(opaque, SPR_FSCR, FSCR_EBB)) {
+        spr_read_prev_upper32(opaque, sprn, gprn);
+    }
+}
+
+static void spr_write_ebb_upper32(void *opaque, int sprn, int gprn)
+{
+    if (check_spr_bit(opaque, SPR_FSCR, FSCR_EBB)) {
+        spr_write_prev_upper32(opaque, sprn, gprn);
+    }
+}
+
+static void spr_read_tar_generic(void *opaque, int gprn, int sprn)
+{
+    if (check_spr_bit(opaque, SPR_FSCR, FSCR_TAR)) {
+        spr_read_generic(opaque, sprn, gprn);
+    }
+}
+
+static void spr_write_tar_generic(void *opaque, int sprn, int gprn)
+{
+    if (check_spr_bit(opaque, SPR_FSCR, FSCR_TAR)) {
+        spr_write_generic(opaque, sprn, gprn);
+    }
+}
+
  static void gen_spr_power8_branch_control(CPUPPCState *env)
  {
      spr_register(env, SPR_TAR, "TAR",
+                 &spr_read_tar_generic, &spr_write_tar_generic,
                   &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BESCRS, "BESCRS",
+                 &spr_read_ebb_generic, &spr_write_ebb_generic,
                   &spr_read_generic, &spr_write_generic,
                   0x00000000);
+    spr_register(env, SPR_BESCRSU, "BESCRSU",
+                 &spr_read_ebb_upper32, &spr_write_ebb_upper32,
+                 &spr_read_ebb_upper32, &spr_write_ebb_upper32,
+                 0x00000000);
+    spr_register(env, SPR_BESCRR, "BESCRR",
+                 &spr_read_ebb_generic, &spr_write_ebb_generic,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BESCRRU, "BESCRRU",
+                 &spr_read_ebb_upper32, &spr_write_ebb_upper32,
+                 &spr_read_ebb_upper32, &spr_write_ebb_upper32,
+                 0x00000000);
+    spr_register_kvm(env, SPR_EBBHR, "EBBHR",
+                     &spr_read_ebb_generic, &spr_write_ebb_generic,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_EBBHR, 0x00000000);
+    spr_register_kvm(env, SPR_EBBRR, "EBBRR",
+                     &spr_read_ebb_generic, &spr_write_ebb_generic,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_EBBRR, 0x00000000);
+    spr_register_kvm(env, SPR_BESCR, "BESCR",
+                     &spr_read_ebb_generic, &spr_write_ebb_generic,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_BESCR, 0x00000000);
  }
static void gen_spr_power8_tm(CPUPPCState *env)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]