summaryrefslogtreecommitdiffstats
path: root/target/ppc/mem_helper.c
diff options
context:
space:
mode:
authorRoman Kapl2018-09-21 08:59:07 +0200
committerDavid Gibson2018-11-08 02:04:40 +0100
commit50728199c549467b01609ddbb831237f72c8f3f6 (patch)
treeb34cccca349829897bdc60c7251e801e3bb38962 /target/ppc/mem_helper.c
parentUpdate version for v3.1.0-rc0 release (diff)
downloadqemu-50728199c549467b01609ddbb831237f72c8f3f6.tar.gz
qemu-50728199c549467b01609ddbb831237f72c8f3f6.tar.xz
qemu-50728199c549467b01609ddbb831237f72c8f3f6.zip
target/ppc: add external PID support
External PID is a mechanism present on BookE 2.06 that enables application to store/load data from different address spaces. There are special version of some instructions, which operate on alternate address space, which is specified in the EPLC/EPSC regiser. This implementation uses two additional MMU modes (mmu_idx) to provide the address space for the load and store instructions. The QEMU TLB fill code was modified to recognize these MMU modes and use the values in EPLC/EPSC to find the proper entry in he PPC TLB. These two QEMU TLBs are also flushed on each write to EPLC/EPSC. Following instructions are implemented: dcbfep dcbstep dcbtep dcbtstep dcbzep dcbzlep icbiep lbepx ldepx lfdepx lhepx lwepx stbepx stdepx stfdepx sthepx stwepx. Following vector instructions are not: evlddepx evstddepx lvepx lvepxl stvepx stvepxl. Signed-off-by: Roman Kapl <rka@sysgo.com> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'target/ppc/mem_helper.c')
-rw-r--r--target/ppc/mem_helper.c34
1 files changed, 31 insertions, 3 deletions
diff --git a/target/ppc/mem_helper.c b/target/ppc/mem_helper.c
index a1485fad9b..9c5a68579e 100644
--- a/target/ppc/mem_helper.c
+++ b/target/ppc/mem_helper.c
@@ -142,11 +142,13 @@ void helper_stsw(CPUPPCState *env, target_ulong addr, uint32_t nb,
}
}
-void helper_dcbz(CPUPPCState *env, target_ulong addr, uint32_t opcode)
+static void dcbz_common(CPUPPCState *env, target_ulong addr,
+ uint32_t opcode, bool epid, uintptr_t retaddr)
{
target_ulong mask, dcbz_size = env->dcache_line_size;
uint32_t i;
void *haddr;
+ int mmu_idx = epid ? PPC_TLB_EPID_STORE : env->dmmu_idx;
#if defined(TARGET_PPC64)
/* Check for dcbz vs dcbzl on 970 */
@@ -166,17 +168,34 @@ void helper_dcbz(CPUPPCState *env, target_ulong addr, uint32_t opcode)
}
/* Try fast path translate */
- haddr = tlb_vaddr_to_host(env, addr, MMU_DATA_STORE, env->dmmu_idx);
+ haddr = tlb_vaddr_to_host(env, addr, MMU_DATA_STORE, mmu_idx);
if (haddr) {
memset(haddr, 0, dcbz_size);
} else {
/* Slow path */
for (i = 0; i < dcbz_size; i += 8) {
- cpu_stq_data_ra(env, addr + i, 0, GETPC());
+ if (epid) {
+#if !defined(CONFIG_USER_ONLY)
+ /* Does not make sense on USER_ONLY config */
+ cpu_stq_eps_ra(env, addr + i, 0, retaddr);
+#endif
+ } else {
+ cpu_stq_data_ra(env, addr + i, 0, retaddr);
+ }
}
}
}
+void helper_dcbz(CPUPPCState *env, target_ulong addr, uint32_t opcode)
+{
+ dcbz_common(env, addr, opcode, false, GETPC());
+}
+
+void helper_dcbzep(CPUPPCState *env, target_ulong addr, uint32_t opcode)
+{
+ dcbz_common(env, addr, opcode, true, GETPC());
+}
+
void helper_icbi(CPUPPCState *env, target_ulong addr)
{
addr &= ~(env->dcache_line_size - 1);
@@ -188,6 +207,15 @@ void helper_icbi(CPUPPCState *env, target_ulong addr)
cpu_ldl_data_ra(env, addr, GETPC());
}
+void helper_icbiep(CPUPPCState *env, target_ulong addr)
+{
+#if !defined(CONFIG_USER_ONLY)
+ /* See comments above */
+ addr &= ~(env->dcache_line_size - 1);
+ cpu_ldl_epl_ra(env, addr, GETPC());
+#endif
+}
+
/* XXX: to be tested */
target_ulong helper_lscbx(CPUPPCState *env, target_ulong addr, uint32_t reg,
uint32_t ra, uint32_t rb)