Commit f6b868fc5899899774eecc43fc21b3a6c6ecfa9a

Authored by blueswir1
1 parent c5e97233

Implement slbmte

In order to modify SLB entries on recent PPC64 machines, the slbmte
instruction is used.

This patch implements the slbmte instruction and makes the "bridge"
mode code use the slb set functions, so we can move the SLB into
the CPU struct later.

This is required for Linux to run on PPC64.

Signed-off-by: Alexander Graf <alex@csgraf.de>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6747 c046a42c-6fe2-441c-8c8c-71466251a162
target-ppc/cpu.h
@@ -716,7 +716,8 @@ void ppc_store_sdr1 (CPUPPCState *env, target_ulong value); @@ -716,7 +716,8 @@ void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
716 #if defined(TARGET_PPC64) 716 #if defined(TARGET_PPC64)
717 void ppc_store_asr (CPUPPCState *env, target_ulong value); 717 void ppc_store_asr (CPUPPCState *env, target_ulong value);
718 target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr); 718 target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr);
719 -void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs); 719 +target_ulong ppc_load_sr (CPUPPCState *env, int sr_nr);
  720 +void ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs);
720 #endif /* defined(TARGET_PPC64) */ 721 #endif /* defined(TARGET_PPC64) */
721 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value); 722 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value);
722 #endif /* !defined(CONFIG_USER_ONLY) */ 723 #endif /* !defined(CONFIG_USER_ONLY) */
target-ppc/helper.c
@@ -821,27 +821,34 @@ target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr) @@ -821,27 +821,34 @@ target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr)
821 return rt; 821 return rt;
822 } 822 }
823 823
824 -void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs) 824 +void ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
825 { 825 {
826 target_phys_addr_t sr_base; 826 target_phys_addr_t sr_base;
827 uint64_t tmp64; 827 uint64_t tmp64;
828 uint32_t tmp; 828 uint32_t tmp;
829 829
  830 + uint64_t vsid;
  831 + uint64_t esid;
  832 + int flags, valid, slb_nr;
  833 +
  834 + vsid = rs >> 12;
  835 + flags = ((rs >> 8) & 0xf);
  836 +
  837 + esid = rb >> 28;
  838 + valid = (rb & (1 << 27));
  839 + slb_nr = rb & 0xfff;
  840 +
  841 + tmp64 = (esid << 28) | valid | (vsid >> 24);
  842 + tmp = (vsid << 8) | (flags << 3);
  843 +
  844 + /* Write SLB entry to memory */
830 sr_base = env->spr[SPR_ASR]; 845 sr_base = env->spr[SPR_ASR];
831 sr_base += 12 * slb_nr; 846 sr_base += 12 * slb_nr;
832 - /* Copy Rs bits 37:63 to SLB 62:88 */  
833 - tmp = rs << 8;  
834 - tmp64 = (rs >> 24) & 0x7;  
835 - /* Copy Rs bits 33:36 to SLB 89:92 */  
836 - tmp |= ((rs >> 27) & 0xF) << 4;  
837 - /* Set the valid bit */  
838 - tmp64 |= 1 << 27;  
839 - /* Set ESID */  
840 - tmp64 |= (uint32_t)slb_nr << 28;  
841 - LOG_SLB("%s: %d " ADDRX " => " PADDRX " %016" PRIx64 847 +
  848 + LOG_SLB("%s: %d " ADDRX " - " ADDRX " => " PADDRX " %016" PRIx64
842 " %08" PRIx32 "\n", __func__, 849 " %08" PRIx32 "\n", __func__,
843 - slb_nr, rs, sr_base, tmp64, tmp);  
844 - /* Write SLB entry to memory */ 850 + slb_nr, rb, rs, sr_base, tmp64, tmp);
  851 +
845 stq_phys(sr_base, tmp64); 852 stq_phys(sr_base, tmp64);
846 stl_phys(sr_base + 8, tmp); 853 stl_phys(sr_base + 8, tmp);
847 } 854 }
@@ -1945,10 +1952,37 @@ void ppc_store_sdr1 (CPUPPCState *env, target_ulong value) @@ -1945,10 +1952,37 @@ void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
1945 } 1952 }
1946 } 1953 }
1947 1954
  1955 +#if defined(TARGET_PPC64)
  1956 +target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
  1957 +{
  1958 + // XXX
  1959 + return 0;
  1960 +}
  1961 +#endif
  1962 +
1948 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value) 1963 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
1949 { 1964 {
1950 LOG_MMU("%s: reg=%d " ADDRX " " ADDRX "\n", 1965 LOG_MMU("%s: reg=%d " ADDRX " " ADDRX "\n",
1951 __func__, srnum, value, env->sr[srnum]); 1966 __func__, srnum, value, env->sr[srnum]);
  1967 +#if defined(TARGET_PPC64)
  1968 + if (env->mmu_model & POWERPC_MMU_64) {
  1969 + uint64_t rb = 0, rs = 0;
  1970 +
  1971 + /* ESID = srnum */
  1972 + rb |= ((uint32_t)srnum & 0xf) << 28;
  1973 + /* Set the valid bit */
  1974 + rb |= 1 << 27;
  1975 + /* Index = ESID */
  1976 + rb |= (uint32_t)srnum;
  1977 +
  1978 + /* VSID = VSID */
  1979 + rs |= (value & 0xfffffff) << 12;
  1980 + /* flags = flags */
  1981 + rs |= ((value >> 27) & 0xf) << 9;
  1982 +
  1983 + ppc_store_slb(env, rb, rs);
  1984 + } else
  1985 +#endif
1952 if (env->sr[srnum] != value) { 1986 if (env->sr[srnum] != value) {
1953 env->sr[srnum] = value; 1987 env->sr[srnum] = value;
1954 #if !defined(FLUSH_ALL_TLBS) && 0 1988 #if !defined(FLUSH_ALL_TLBS) && 0
target-ppc/op_helper.c
@@ -3752,6 +3752,10 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) @@ -3752,6 +3752,10 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
3752 /* Segment registers load and store */ 3752 /* Segment registers load and store */
3753 target_ulong helper_load_sr (target_ulong sr_num) 3753 target_ulong helper_load_sr (target_ulong sr_num)
3754 { 3754 {
  3755 +#if defined(TARGET_PPC64)
  3756 + if (env->mmu_model & POWERPC_MMU_64)
  3757 + return ppc_load_sr(env, sr_num);
  3758 +#endif
3755 return env->sr[sr_num]; 3759 return env->sr[sr_num];
3756 } 3760 }
3757 3761
@@ -3767,9 +3771,9 @@ target_ulong helper_load_slb (target_ulong slb_nr) @@ -3767,9 +3771,9 @@ target_ulong helper_load_slb (target_ulong slb_nr)
3767 return ppc_load_slb(env, slb_nr); 3771 return ppc_load_slb(env, slb_nr);
3768 } 3772 }
3769 3773
3770 -void helper_store_slb (target_ulong slb_nr, target_ulong rs) 3774 +void helper_store_slb (target_ulong rb, target_ulong rs)
3771 { 3775 {
3772 - ppc_store_slb(env, slb_nr, rs); 3776 + ppc_store_slb(env, rb, rs);
3773 } 3777 }
3774 3778
3775 void helper_slbia (void) 3779 void helper_slbia (void)
target-ppc/translate.c
@@ -4300,7 +4300,7 @@ GEN_HANDLER2(mfsr_64b, &quot;mfsr&quot;, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B) @@ -4300,7 +4300,7 @@ GEN_HANDLER2(mfsr_64b, &quot;mfsr&quot;, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B)
4300 return; 4300 return;
4301 } 4301 }
4302 t0 = tcg_const_tl(SR(ctx->opcode)); 4302 t0 = tcg_const_tl(SR(ctx->opcode));
4303 - gen_helper_load_slb(cpu_gpr[rD(ctx->opcode)], t0); 4303 + gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4304 tcg_temp_free(t0); 4304 tcg_temp_free(t0);
4305 #endif 4305 #endif
4306 } 4306 }
@@ -4320,7 +4320,7 @@ GEN_HANDLER2(mfsrin_64b, &quot;mfsrin&quot;, 0x1F, 0x13, 0x14, 0x001F0001, @@ -4320,7 +4320,7 @@ GEN_HANDLER2(mfsrin_64b, &quot;mfsrin&quot;, 0x1F, 0x13, 0x14, 0x001F0001,
4320 t0 = tcg_temp_new(); 4320 t0 = tcg_temp_new();
4321 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28); 4321 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4322 tcg_gen_andi_tl(t0, t0, 0xF); 4322 tcg_gen_andi_tl(t0, t0, 0xF);
4323 - gen_helper_load_slb(cpu_gpr[rD(ctx->opcode)], t0); 4323 + gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4324 tcg_temp_free(t0); 4324 tcg_temp_free(t0);
4325 #endif 4325 #endif
4326 } 4326 }
@@ -4337,7 +4337,7 @@ GEN_HANDLER2(mtsr_64b, &quot;mtsr&quot;, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B) @@ -4337,7 +4337,7 @@ GEN_HANDLER2(mtsr_64b, &quot;mtsr&quot;, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B)
4337 return; 4337 return;
4338 } 4338 }
4339 t0 = tcg_const_tl(SR(ctx->opcode)); 4339 t0 = tcg_const_tl(SR(ctx->opcode));
4340 - gen_helper_store_slb(t0, cpu_gpr[rS(ctx->opcode)]); 4340 + gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4341 tcg_temp_free(t0); 4341 tcg_temp_free(t0);
4342 #endif 4342 #endif
4343 } 4343 }
@@ -4357,10 +4357,25 @@ GEN_HANDLER2(mtsrin_64b, &quot;mtsrin&quot;, 0x1F, 0x12, 0x07, 0x001F0001, @@ -4357,10 +4357,25 @@ GEN_HANDLER2(mtsrin_64b, &quot;mtsrin&quot;, 0x1F, 0x12, 0x07, 0x001F0001,
4357 t0 = tcg_temp_new(); 4357 t0 = tcg_temp_new();
4358 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28); 4358 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4359 tcg_gen_andi_tl(t0, t0, 0xF); 4359 tcg_gen_andi_tl(t0, t0, 0xF);
4360 - gen_helper_store_slb(t0, cpu_gpr[rS(ctx->opcode)]); 4360 + gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4361 tcg_temp_free(t0); 4361 tcg_temp_free(t0);
4362 #endif 4362 #endif
4363 } 4363 }
  4364 +
  4365 +/* slbmte */
  4366 +GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x00000000, PPC_SEGMENT_64B)
  4367 +{
  4368 +#if defined(CONFIG_USER_ONLY)
  4369 + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
  4370 +#else
  4371 + if (unlikely(!ctx->mem_idx)) {
  4372 + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
  4373 + return;
  4374 + }
  4375 + gen_helper_store_slb(cpu_gpr[rB(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
  4376 +#endif
  4377 +}
  4378 +
4364 #endif /* defined(TARGET_PPC64) */ 4379 #endif /* defined(TARGET_PPC64) */
4365 4380
4366 /*** Lookaside buffer management ***/ 4381 /*** Lookaside buffer management ***/