mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-06 09:13:55 -06:00
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>
This commit is contained in:
parent
4de6bb0c02
commit
50728199c5
8 changed files with 387 additions and 45 deletions
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue