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

target-ppc: tlbie/tlbivax should have global effect



tlbie (BookS) and tlbivax (BookE) plus the H_CALLs(pseries) should have
a global effect.

Introduces TLB_NEED_GLOBAL_FLUSH flag. During lazy tlb flush, after
taking care of pending local flushes, check broadcast flush(at context
synchronizing event ptesync/tlbsync, etc) is needed. Depending on the
bitmask state of the tlb_need_flush, tlb is flushed from other cpus if
needed and the flags are cleared.

Suggested-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarNikunj A Dadhania <nikunj@linux.vnet.ibm.com>
Reviewed-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
[dwg: Use 'true' instead of '1' for call to check_tlb_flush()]
Signed-off-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
parent e3cffe6f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -319,6 +319,8 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPRMachineState *spapr,
    ppc_hash64_store_hpte(cpu, pte_index,
                          (v & ~HPTE64_V_VALID) | HPTE64_V_HPTE_DIRTY, 0);
    ppc_hash64_tlb_flush_hpte(cpu, pte_index, v, r);
    /* Flush the tlb */
    check_tlb_flush(env, true);
    /* Don't need a memory barrier, due to qemu's global lock */
    ppc_hash64_store_hpte(cpu, pte_index, v | HPTE64_V_HPTE_DIRTY, r);
    return H_SUCCESS;
+1 −0
Original line number Diff line number Diff line
@@ -1010,6 +1010,7 @@ struct CPUPPCState {
    bool kvm_sw_tlb;  /* non-zero if KVM SW TLB API is active                */
    uint32_t tlb_need_flush; /* Delayed flush needed */
#define TLB_NEED_LOCAL_FLUSH   0x1
#define TLB_NEED_GLOBAL_FLUSH  0x2
#endif

    /* Other registers */
+17 −0
Original line number Diff line number Diff line
@@ -161,6 +161,23 @@ static inline void check_tlb_flush(CPUPPCState *env, bool global)
        tlb_flush(cs, 1);
        env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
    }

    /* Propagate TLB invalidations to other CPUs when the guest uses broadcast
     * TLB invalidation instructions.
     */
    if (global && (env->tlb_need_flush & TLB_NEED_GLOBAL_FLUSH)) {
        CPUState *other_cs;
        CPU_FOREACH(other_cs) {
            if (other_cs != cs) {
                PowerPCCPU *cpu = POWERPC_CPU(other_cs);
                CPUPPCState *other_env = &cpu->env;

                other_env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
                tlb_flush(other_cs, 1);
            }
        }
        env->tlb_need_flush &= ~TLB_NEED_GLOBAL_FLUSH;
    }
}
#else
static inline void check_tlb_flush(CPUPPCState *env, bool global) { }
+1 −1
Original line number Diff line number Diff line
@@ -912,7 +912,7 @@ void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu,
     * invalidate, and we still don't have a tlb_flush_mask(env, n,
     * mask) in QEMU, we just invalidate all TLBs
     */
    tlb_flush(CPU(cpu), 1);
    cpu->env.tlb_need_flush = TLB_NEED_GLOBAL_FLUSH | TLB_NEED_LOCAL_FLUSH;
}

void ppc_hash64_update_rmls(CPUPPCState *env)
+7 −3
Original line number Diff line number Diff line
@@ -2757,7 +2757,7 @@ static inline void booke206_invalidate_ea_tlb(CPUPPCState *env, int tlbn,

void helper_booke206_tlbivax(CPUPPCState *env, target_ulong address)
{
    PowerPCCPU *cpu = ppc_env_get_cpu(env);
    CPUState *cs;

    if (address & 0x4) {
        /* flush all entries */
@@ -2774,11 +2774,15 @@ void helper_booke206_tlbivax(CPUPPCState *env, target_ulong address)
    if (address & 0x8) {
        /* flush TLB1 entries */
        booke206_invalidate_ea_tlb(env, 1, address);
        tlb_flush(CPU(cpu), 1);
        CPU_FOREACH(cs) {
            tlb_flush(cs, 1);
        }
    } else {
        /* flush TLB0 entries */
        booke206_invalidate_ea_tlb(env, 0, address);
        tlb_flush_page(CPU(cpu), address & MAS2_EPN_MASK);
        CPU_FOREACH(cs) {
            tlb_flush_page(cs, address & MAS2_EPN_MASK);
        }
    }
}

Loading