Commit e3cffe6f authored by Nikunj A Dadhania's avatar Nikunj A Dadhania Committed by David Gibson
Browse files

target-ppc: add flag in check_tlb_flush()



We flush the qemu TLB lazily. check_tlb_flush is called whenever we hit
a context synchronizing event or instruction that requires a pending
flush to be performed.

However, we fail to handle broadcast TLB flush operations. In order to
fix that efficiently, we want to differentiate whether check_tlb_flush()
needs to only apply pending local flushes (isync instructions,
interrupts, ...) or also global pending flush operations. The latter is
only needed when executing instructions that are defined architecturally
as synchronizing global TLB flush operations. This in our case is
ptesync on BookS and tlbsync on BookE along with the paravirtualized
hypervisor calls.

Signed-off-by: default avatarNikunj A Dadhania <nikunj@linux.vnet.ibm.com>
[dwg: Changed gen_check_tlb_flush() to also take a bool, and fixed
 some spelling errors in commit message]
Signed-off-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
parent a8a6d53e
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -201,7 +201,7 @@ static target_ulong h_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,

    switch (ret) {
    case REMOVE_SUCCESS:
        check_tlb_flush(env);
        check_tlb_flush(env, true);
        return H_SUCCESS;

    case REMOVE_NOT_FOUND:
@@ -282,7 +282,7 @@ static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
        }
    }
 exit:
    check_tlb_flush(env);
    check_tlb_flush(env, true);

    return rc;
}
+2 −2
Original line number Diff line number Diff line
@@ -711,7 +711,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
    /* Any interrupt is context synchronizing, check if TCG TLB
     * needs a delayed flush on ppc64
     */
    check_tlb_flush(env);
    check_tlb_flush(env, false);
}

void ppc_cpu_do_interrupt(CPUState *cs)
@@ -973,7 +973,7 @@ static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;

    /* Context synchronizing: check if TCG TLB needs flush */
    check_tlb_flush(env);
    check_tlb_flush(env, false);
}

void helper_rfi(CPUPPCState *env)
+2 −1
Original line number Diff line number Diff line
@@ -18,7 +18,8 @@ DEF_HELPER_1(rfid, void, env)
DEF_HELPER_1(hrfid, void, env)
DEF_HELPER_2(store_lpcr, void, env, tl)
#endif
DEF_HELPER_1(check_tlb_flush, void, env)
DEF_HELPER_1(check_tlb_flush_local, void, env)
DEF_HELPER_1(check_tlb_flush_global, void, env)
#endif

DEF_HELPER_3(lmw, void, env, tl, i32)
+2 −2
Original line number Diff line number Diff line
@@ -154,7 +154,7 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
}

#if !defined(CONFIG_USER_ONLY)
static inline void check_tlb_flush(CPUPPCState *env)
static inline void check_tlb_flush(CPUPPCState *env, bool global)
{
    CPUState *cs = CPU(ppc_env_get_cpu(env));
    if (env->tlb_need_flush & TLB_NEED_LOCAL_FLUSH) {
@@ -163,7 +163,7 @@ static inline void check_tlb_flush(CPUPPCState *env)
    }
}
#else
static inline void check_tlb_flush(CPUPPCState *env) { }
static inline void check_tlb_flush(CPUPPCState *env, bool global) { }
#endif

#endif /* HELPER_REGS_H */
+7 −2
Original line number Diff line number Diff line
@@ -2867,9 +2867,14 @@ void helper_booke206_tlbflush(CPUPPCState *env, target_ulong type)
}


void helper_check_tlb_flush(CPUPPCState *env)
void helper_check_tlb_flush_local(CPUPPCState *env)
{
    check_tlb_flush(env);
    check_tlb_flush(env, false);
}

void helper_check_tlb_flush_global(CPUPPCState *env)
{
    check_tlb_flush(env, true);
}

/*****************************************************************************/
Loading