Octeon firmware programs contiguous PageMask values that do not follow the generic R4K even maskbits rule.
Keep the generic validation rule for other MIPS CPUs, while allowing Octeon CPUs to use the contiguous masks accepted by hardware. Signed-off-by: Kirill A. Korinsky <[email protected]> Suggested-by: Philippe Mathieu-Daudé <[email protected]> --- target/mips/tcg/system/cp0_helper.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/target/mips/tcg/system/cp0_helper.c b/target/mips/tcg/system/cp0_helper.c index 3fc55314a8..9f7270d558 100644 --- a/target/mips/tcg/system/cp0_helper.c +++ b/target/mips/tcg/system/cp0_helper.c @@ -885,11 +885,17 @@ void HELPER(mtc0_memorymapid)(CPUMIPSState *env, target_ulong arg1) uint32_t compute_pagemask(CPUMIPSState *env, uint32_t val) { /* Don't care MASKX as we don't support 1KB page */ - uint32_t mask = extract32(val, CP0PM_MASK, 16); + uint32_t mask = (env->insn_flags & INSN_OCTEON) ? + val >> CP0PM_MASK : extract32(val, CP0PM_MASK, 16); int maskbits = cto32(mask); - /* Ensure no more set bit after first zero, and maskbits even. */ - if ((mask >> maskbits) == 0 && maskbits % 2 == 0) { + /* + * Generic R4K PageMask values use two mask bits per size step. + * Octeon accepts contiguous byte masks such as 0x003fffff for + * two 2 MiB pages. + */ + if ((mask & (mask + 1)) == 0 && + ((env->insn_flags & INSN_OCTEON) || maskbits % 2 == 0)) { return mask << CP0PM_MASK; } else { /* When invalid, set to default target page size. */ -- 2.56.0
