Commit 3adafef2 authored by Leon Alrae's avatar Leon Alrae
Browse files

target-mips: fix corner case in TLBWR causing QEMU to hang



cpu_mips_get_random() function is used to generate a random index from
CP0.Wired to TLBSize-1 range. Current implementation avoids generating
the same as before value, hence the while loop. If the guest sets
CP0.Wired to TLBSize-1 (which actually does not sound to be very
practical) QEMU will get stuck in the loop infinitely as we always
generate the same index.

Signed-off-by: default avatarLeon Alrae <leon.alrae@imgtec.com>
Reviewed-by: default avatarAurelien Jarno <aurelien@aurel32.net>
parent ceb0ee14
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -33,13 +33,18 @@ uint32_t cpu_mips_get_random (CPUMIPSState *env)
    static uint32_t seed = 1;
    static uint32_t prev_idx = 0;
    uint32_t idx;
    uint32_t nb_rand_tlb = env->tlb->nb_tlb - env->CP0_Wired;

    if (nb_rand_tlb == 1) {
        return env->tlb->nb_tlb - 1;
    }

    /* Don't return same value twice, so get another value */
    do {
        /* Use a simple algorithm of Linear Congruential Generator
         * from ISO/IEC 9899 standard. */
        seed = 1103515245 * seed + 12345;
        idx = (seed >> 16) % (env->tlb->nb_tlb - env->CP0_Wired) +
              env->CP0_Wired;
        idx = (seed >> 16) % nb_rand_tlb + env->CP0_Wired;
    } while (idx == prev_idx);
    prev_idx = idx;
    return idx;