aboutsummaryrefslogtreecommitdiff
path: root/target-ppc/helper.c
diff options
context:
space:
mode:
authorblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>2009-03-07 20:50:01 +0000
committerblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>2009-03-07 20:50:01 +0000
commitf6b868fc5899899774eecc43fc21b3a6c6ecfa9a (patch)
tree00cf84e46ee8213d417d41e5cc61506d7d5f4ff8 /target-ppc/helper.c
parentc5e97233e8c8e53aab1b80b5e9891a71c4edea3e (diff)
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
Diffstat (limited to 'target-ppc/helper.c')
-rw-r--r--target-ppc/helper.c60
1 files changed, 47 insertions, 13 deletions
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index e02dcb03d9..cc471969a2 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -821,27 +821,34 @@ target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr)
return rt;
}
-void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs)
+void ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
{
target_phys_addr_t sr_base;
uint64_t tmp64;
uint32_t tmp;
+ uint64_t vsid;
+ uint64_t esid;
+ int flags, valid, slb_nr;
+
+ vsid = rs >> 12;
+ flags = ((rs >> 8) & 0xf);
+
+ esid = rb >> 28;
+ valid = (rb & (1 << 27));
+ slb_nr = rb & 0xfff;
+
+ tmp64 = (esid << 28) | valid | (vsid >> 24);
+ tmp = (vsid << 8) | (flags << 3);
+
+ /* Write SLB entry to memory */
sr_base = env->spr[SPR_ASR];
sr_base += 12 * slb_nr;
- /* Copy Rs bits 37:63 to SLB 62:88 */
- tmp = rs << 8;
- tmp64 = (rs >> 24) & 0x7;
- /* Copy Rs bits 33:36 to SLB 89:92 */
- tmp |= ((rs >> 27) & 0xF) << 4;
- /* Set the valid bit */
- tmp64 |= 1 << 27;
- /* Set ESID */
- tmp64 |= (uint32_t)slb_nr << 28;
- LOG_SLB("%s: %d " ADDRX " => " PADDRX " %016" PRIx64
+
+ LOG_SLB("%s: %d " ADDRX " - " ADDRX " => " PADDRX " %016" PRIx64
" %08" PRIx32 "\n", __func__,
- slb_nr, rs, sr_base, tmp64, tmp);
- /* Write SLB entry to memory */
+ slb_nr, rb, rs, sr_base, tmp64, tmp);
+
stq_phys(sr_base, tmp64);
stl_phys(sr_base + 8, tmp);
}
@@ -1945,10 +1952,37 @@ void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
}
}
+#if defined(TARGET_PPC64)
+target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
+{
+ // XXX
+ return 0;
+}
+#endif
+
void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
{
LOG_MMU("%s: reg=%d " ADDRX " " ADDRX "\n",
__func__, srnum, value, env->sr[srnum]);
+#if defined(TARGET_PPC64)
+ if (env->mmu_model & POWERPC_MMU_64) {
+ uint64_t rb = 0, rs = 0;
+
+ /* ESID = srnum */
+ rb |= ((uint32_t)srnum & 0xf) << 28;
+ /* Set the valid bit */
+ rb |= 1 << 27;
+ /* Index = ESID */
+ rb |= (uint32_t)srnum;
+
+ /* VSID = VSID */
+ rs |= (value & 0xfffffff) << 12;
+ /* flags = flags */
+ rs |= ((value >> 27) & 0xf) << 9;
+
+ ppc_store_slb(env, rb, rs);
+ } else
+#endif
if (env->sr[srnum] != value) {
env->sr[srnum] = value;
#if !defined(FLUSH_ALL_TLBS) && 0