From 0f2a1484487407390196ca5b3c3a07bee6df15ad Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Wed, 3 Feb 2016 03:15:23 +0000 Subject: [PATCH] MIPS: pm-cps: Avoid offset overflow on MIPSr6 This is similar to commit 934c79231c1b ("MIPS: asm: r4kcache: Add MIPS R6 cache unroll functions"). The CACHE instruction has been redefined for MIPSr6 and it reduced its offset field to 8 bits. This leads to micro-assembler field overflow warnings when booting SMP MIPSr6 cores like the following one: Call Trace: [] show_stack+0x68/0x88 [] dump_stack+0x68/0x88 [] warn_slowpath_common+0x8c/0xc8 [] warn_slowpath_fmt+0x38/0x48 [] build_insn+0x514/0x5c0 [] cps_gen_cache_routine.isra.3+0xe0/0x1b8 [] cps_pm_init+0x364/0x9ec [] do_one_initcall+0x90/0x1a8 [] kernel_init_freeable+0x160/0x21c [] kernel_init+0x10/0xf8 [] ret_from_kernel_thread+0x14/0x1c We fix this by incrementing the base register on every loop. Signed-off-by: Markos Chandras Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12329/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/pm-cps.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c index fa3f9ebad8f4..adda3ffb9b78 100644 --- a/arch/mips/kernel/pm-cps.c +++ b/arch/mips/kernel/pm-cps.c @@ -224,11 +224,18 @@ static void __init cps_gen_cache_routine(u32 **pp, struct uasm_label **pl, uasm_build_label(pl, *pp, lbl); /* Generate the cache ops */ - for (i = 0; i < unroll_lines; i++) - uasm_i_cache(pp, op, i * cache->linesz, t0); + for (i = 0; i < unroll_lines; i++) { + if (cpu_has_mips_r6) { + uasm_i_cache(pp, op, 0, t0); + uasm_i_addiu(pp, t0, t0, cache->linesz); + } else { + uasm_i_cache(pp, op, i * cache->linesz, t0); + } + } - /* Update the base address */ - uasm_i_addiu(pp, t0, t0, unroll_lines * cache->linesz); + if (!cpu_has_mips_r6) + /* Update the base address */ + uasm_i_addiu(pp, t0, t0, unroll_lines * cache->linesz); /* Loop if we haven't reached the end address yet */ uasm_il_bne(pp, pr, t0, t1, lbl);