On 01/23/2012 07:19 PM, Scott Wood wrote:
On 01/23/2012 11:33 AM, Alexander Graf wrote:
On 01/23/2012 06:32 PM, Scott Wood wrote:
On 01/20/2012 10:15 PM, Alexander Graf wrote:
@@ -4273,6 +4274,16 @@ void helper_booke206_tlbwe(void)
           tlb->mas1&= ~MAS1_IPROT;
       }

+    /* check that we support the targeted size */
+    size_tlb = (tlb->mas1&   MAS1_TSIZE_MASK)>>   MAS1_TSIZE_SHIFT;
+    size_ps = booke206_tlbnps(env, tlbn);
+    if ((tlb->mas1&   MAS1_VALID)&&   (tlbncfg&   TLBnCFG_AVAIL)&&
+        !(size_ps&   (1<<   size_tlb))) {
+        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
+                                   POWERPC_EXCP_INVAL |
+                                   POWERPC_EXCP_INVAL_INVAL);
+    }
+
       if (booke206_tlb_to_page_size(env, tlb) == TARGET_PAGE_SIZE) {
           tlb_flush_page(env, tlb->mas2&   MAS2_EPN_MASK);
       } else {
For tlb0 on e500 and derivatives, tsize is explicitly documented as
ignored.  Software may rely on this.
Yup, that's why there's the check for TLBnCG_AVAIL, which indicates that
a TLB has dynamic page size capabilities, which TLB0 does not have.
Silly me, thinking "avail" meant "this TLB is available" instead of
looking up the actual meaning. :-P

Where do we check whether the TLB exists at all?

We don't. Eventually TLB access goes through:

static inline ppcmas_tlb_t *booke206_get_tlbm(CPUState *env, const int tlbn,
                                              target_ulong ea, int way)
{
    int r;
    uint32_t ways = booke206_tlb_ways(env, tlbn);
    int ways_bits = ffs(ways) - 1;
    int tlb_bits = ffs(booke206_tlb_size(env, tlbn)) - 1;
    int i;

    way &= ways - 1;
    ea >>= MAS2_EPN_SHIFT;
    ea &= (1 << (tlb_bits - ways_bits)) - 1;
    r = (ea << ways_bits) | way;

    /* bump up to tlbn index */
    for (i = 0; i < tlbn; i++) {
        r += booke206_tlb_size(env, i);
    }

    return &env->tlb.tlbm[r];
}

Since unavailable TLBs have ways set to 0 and tlb_size is 0, we always end up with the last TLB entry that's available.

So if you do a tlbwe on tlbn=5 on TLB2, you write to the last entry of TLB1. Which actually is fine according to the spec:

If an invalid value is specified for MAS0TLBSEL
MAS0ESEL or MAS2EPN, either no TLB entry is written
by the tlbwe, or the tlbwe is performed as if some
implementation-dependent, valid value were substi-
tuted for the invalid value, or an Illegal Instruction
exception occurs.

We substitute it with a valid value :)


Alex


Reply via email to