target-ppc: Add POWER8's TM SPRs
authorAlexey Kardashevskiy <aik@ozlabs.ru>
Wed, 4 Jun 2014 12:50:59 +0000 (22:50 +1000)
committerAlexander Graf <agraf@suse.de>
Mon, 16 Jun 2014 11:24:45 +0000 (13:24 +0200)
This adds TM (Transactional Memory) SPRs.

This adds generic spr_read_prev_upper32()/spr_write_prev_upper32() to
handle upper half SPRs such as TEXASRU which is upper half of TEXASR.
Since this is not the only register like that and their numbers go
consequently, it makes sense to generalize the helpers.

This adds a gen_msr_facility_check() helper which purpose is to generate
the Facility Unavailable exception if the facility is disabled.
It is a copy of gen_fscr_facility_check() but it checks for enabled
facility in MSR rather than FSCR/HFSCR. It still sets the interrupt cause
in FSCR/HFSCR (whichever is passed to the helper).

This adds spr_read_tm/spr_write_tm/spr_read_tm_upper32/spr_write_tm_upper32
which are used for TM SPRs.

This adds TM-relates MSR bits definitions. This enables TM in POWER8 CPU class'
msr_mask.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
target-ppc/cpu.h
target-ppc/helper.h
target-ppc/misc_helper.c
target-ppc/translate_init.c

index d19e284061353a18f9b635fe6457aa436fa0d7b4..a85916ef4702bc44109ca8ba7c0bd7e0cc3eb81b 100644 (file)
@@ -427,6 +427,9 @@ struct ppc_slb_t {
 #define MSR_TAG  62 /* Tag-active mode (POWERx ?)                            */
 #define MSR_ISF  61 /* Sixty-four-bit interrupt mode on 630                  */
 #define MSR_SHV  60 /* hypervisor state                               hflags */
+#define MSR_TS0  34 /* Transactional state, 2 bits (Book3s)                  */
+#define MSR_TS1  33
+#define MSR_TM   32 /* Transactional Memory Available (Book3s)               */
 #define MSR_CM   31 /* Computation mode for BookE                     hflags */
 #define MSR_ICM  30 /* Interrupt computation mode for BookE                  */
 #define MSR_THV  29 /* hypervisor state for 32 bits PowerPC           hflags */
@@ -503,6 +506,9 @@ struct ppc_slb_t {
 #define msr_pmm  ((env->msr >> MSR_PMM)  & 1)
 #define msr_ri   ((env->msr >> MSR_RI)   & 1)
 #define msr_le   ((env->msr >> MSR_LE)   & 1)
+#define msr_ts   ((env->msr >> MSR_TS1)  & 3)
+#define msr_tm   ((env->msr >> MSR_TM)   & 1)
+
 /* Hypervisor bit is more specific */
 #if defined(TARGET_PPC64)
 #define MSR_HVB (1ULL << MSR_SHV)
@@ -1271,6 +1277,10 @@ static inline int cpu_mmu_index (CPUPPCState *env)
 #define SPR_MPC_EIE           (0x050)
 #define SPR_MPC_EID           (0x051)
 #define SPR_MPC_NRI           (0x052)
+#define SPR_TFHAR             (0x080)
+#define SPR_TFIAR             (0x081)
+#define SPR_TEXASR            (0x082)
+#define SPR_TEXASRU           (0x083)
 #define SPR_UCTRL             (0x088)
 #define SPR_MPC_CMPA          (0x090)
 #define SPR_MPC_CMPB          (0x091)
index c1417ea75d7ef216a36a63a8b915a4d432ffcaa4..509eae52ff26d01015fb646e59fb022935e82d01 100644 (file)
@@ -578,6 +578,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_4(msr_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)
index 554831facab9974df1b5b43b3ac4dd4156e7a824..a577b3afd1dae91dcacea851267acc3e59321da2 100644 (file)
@@ -61,6 +61,18 @@ void helper_fscr_facility_check(CPUPPCState *env, uint32_t bit,
 #endif
 }
 
+void helper_msr_facility_check(CPUPPCState *env, uint32_t bit,
+                               uint32_t sprn, uint32_t cause)
+{
+#ifdef TARGET_PPC64
+    if (env->msr & (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)
index 548b5825425707a60c81d8e75668fff98d1989ef..d31ecc64867c69b6a4dd8930fa33c575106d9de5 100644 (file)
@@ -7297,6 +7297,45 @@ static void gen_fscr_facility_check(void *opaque, int facility_sprn, int bit,
     tcg_temp_free_i32(t1);
 }
 
+static void gen_msr_facility_check(void *opaque, int facility_sprn, int bit,
+                                   int sprn, int cause)
+{
+    TCGv_i32 t1 = tcg_const_i32(bit);
+    TCGv_i32 t2 = tcg_const_i32(sprn);
+    TCGv_i32 t3 = tcg_const_i32(cause);
+
+    gen_update_current_nip(opaque);
+    gen_helper_msr_facility_check(cpu_env, t1, t2, t3);
+
+    tcg_temp_free_i32(t3);
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
+static void spr_read_prev_upper32(void *opaque, int gprn, int sprn)
+{
+    TCGv spr_up = tcg_temp_new();
+    TCGv spr = tcg_temp_new();
+
+    gen_load_spr(spr, sprn - 1);
+    tcg_gen_shri_tl(spr_up, spr, 32);
+    tcg_gen_ext32u_tl(cpu_gpr[gprn], spr_up);
+
+    tcg_temp_free(spr);
+    tcg_temp_free(spr_up);
+}
+
+static void spr_write_prev_upper32(void *opaque, int sprn, int gprn)
+{
+    TCGv spr = tcg_temp_new();
+
+    gen_load_spr(spr, sprn - 1);
+    tcg_gen_deposit_tl(spr, spr, cpu_gpr[gprn], 32, 32);
+    gen_store_spr(sprn - 1, spr);
+
+    tcg_temp_free(spr);
+}
+
 static int check_pow_970 (CPUPPCState *env)
 {
     if (env->spr[SPR_HID0] & (HID0_DEEPNAP | HID0_DOZE | HID0_NAP)) {
@@ -7634,6 +7673,50 @@ static void gen_spr_power8_tce_address_control(CPUPPCState *env)
                  0x00000000);
 }
 
+static void spr_read_tm(void *opaque, int gprn, int sprn)
+{
+    gen_msr_facility_check(opaque, SPR_FSCR, MSR_TM, sprn, FSCR_IC_TM);
+    spr_read_generic(opaque, gprn, sprn);
+}
+
+static void spr_write_tm(void *opaque, int sprn, int gprn)
+{
+    gen_msr_facility_check(opaque, SPR_FSCR, MSR_TM, sprn, FSCR_IC_TM);
+    spr_write_generic(opaque, sprn, gprn);
+}
+
+static void spr_read_tm_upper32(void *opaque, int gprn, int sprn)
+{
+    gen_msr_facility_check(opaque, SPR_FSCR, MSR_TM, sprn, FSCR_IC_TM);
+    spr_read_prev_upper32(opaque, gprn, sprn);
+}
+
+static void spr_write_tm_upper32(void *opaque, int sprn, int gprn)
+{
+    gen_msr_facility_check(opaque, SPR_FSCR, MSR_TM, sprn, FSCR_IC_TM);
+    spr_write_prev_upper32(opaque, sprn, gprn);
+}
+
+static void gen_spr_power8_tm(CPUPPCState *env)
+{
+    spr_register_kvm(env, SPR_TFHAR, "TFHAR",
+                     &spr_read_tm, &spr_write_tm,
+                     &spr_read_tm, &spr_write_tm,
+                     KVM_REG_PPC_TFHAR, 0x00000000);
+    spr_register_kvm(env, SPR_TFIAR, "TFIAR",
+                     &spr_read_tm, &spr_write_tm,
+                     &spr_read_tm, &spr_write_tm,
+                     KVM_REG_PPC_TFIAR, 0x00000000);
+    spr_register_kvm(env, SPR_TEXASR, "TEXASR",
+                     &spr_read_tm, &spr_write_tm,
+                     &spr_read_tm, &spr_write_tm,
+                     KVM_REG_PPC_TEXASR, 0x00000000);
+    spr_register(env, SPR_TEXASRU, "TEXASRU",
+                 &spr_read_tm_upper32, &spr_write_tm_upper32,
+                 &spr_read_tm_upper32, &spr_write_tm_upper32,
+                 0x00000000);
+}
+
 static void gen_spr_power8_fscr(CPUPPCState *env)
 {
 #if defined(CONFIG_USER_ONLY)
@@ -7695,6 +7778,7 @@ static void init_proc_book3s_64(CPUPPCState *env, int version)
         gen_spr_power8_fscr(env);
         gen_spr_power8_pmu_sup(env);
         gen_spr_power8_pmu_user(env);
+        gen_spr_power8_tm(env);
     }
 #if !defined(CONFIG_USER_ONLY)
     switch (version) {
@@ -8066,6 +8150,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
                         PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 |
                         PPC2_ISA205 | PPC2_ISA207S;
     pcc->msr_mask = (1ull << MSR_SF) |
+                    (1ull << MSR_TM) |
                     (1ull << MSR_VR) |
                     (1ull << MSR_VSX) |
                     (1ull << MSR_EE) |
@@ -9378,6 +9463,9 @@ static void ppc_cpu_reset(CPUState *s)
     msr |= (target_ulong)1 << MSR_VSX; /* Allow VSX usage */
     msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
     msr |= (target_ulong)1 << MSR_PR;
+#if defined(TARGET_PPC64)
+    msr |= (target_ulong)1 << MSR_TM; /* Transactional memory */
+#endif
 #if !defined(TARGET_WORDS_BIGENDIAN)
     msr |= (target_ulong)1 << MSR_LE; /* Little-endian user mode */
 #endif