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 716 #if defined(TARGET_PPC64)
717 717 void ppc_store_asr (CPUPPCState *env, target_ulong value);
718 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 721 #endif /* defined(TARGET_PPC64) */
721 722 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value);
722 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 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 826 target_phys_addr_t sr_base;
827 827 uint64_t tmp64;
828 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 845 sr_base = env->spr[SPR_ASR];
831 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 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 852 stq_phys(sr_base, tmp64);
846 853 stl_phys(sr_base + 8, tmp);
847 854 }
... ... @@ -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 1963 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
1949 1964 {
1950 1965 LOG_MMU("%s: reg=%d " ADDRX " " ADDRX "\n",
1951 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 1986 if (env->sr[srnum] != value) {
1953 1987 env->sr[srnum] = value;
1954 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 3752 /* Segment registers load and store */
3753 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 3759 return env->sr[sr_num];
3756 3760 }
3757 3761  
... ... @@ -3767,9 +3771,9 @@ target_ulong helper_load_slb (target_ulong slb_nr)
3767 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 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 4300 return;
4301 4301 }
4302 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 4304 tcg_temp_free(t0);
4305 4305 #endif
4306 4306 }
... ... @@ -4320,7 +4320,7 @@ GEN_HANDLER2(mfsrin_64b, &quot;mfsrin&quot;, 0x1F, 0x13, 0x14, 0x001F0001,
4320 4320 t0 = tcg_temp_new();
4321 4321 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4322 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 4324 tcg_temp_free(t0);
4325 4325 #endif
4326 4326 }
... ... @@ -4337,7 +4337,7 @@ GEN_HANDLER2(mtsr_64b, &quot;mtsr&quot;, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B)
4337 4337 return;
4338 4338 }
4339 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 4341 tcg_temp_free(t0);
4342 4342 #endif
4343 4343 }
... ... @@ -4357,10 +4357,25 @@ GEN_HANDLER2(mtsrin_64b, &quot;mtsrin&quot;, 0x1F, 0x12, 0x07, 0x001F0001,
4357 4357 t0 = tcg_temp_new();
4358 4358 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4359 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 4361 tcg_temp_free(t0);
4362 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 4379 #endif /* defined(TARGET_PPC64) */
4365 4380  
4366 4381 /*** Lookaside buffer management ***/
... ...