aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
authorPaul Burton <paul.burton@imgtec.com>2016-11-07 10:07:04 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-03-12 00:41:40 -0500
commitb0b4eb58c5efe31c5dbd8fc771b43bb13bf84430 (patch)
tree5ad727b8d64b0e4ba4acc1fd6549a8a5f15e21d6 /arch/mips/kernel
parentce449cbdcff78a383741bc79d66f2779a556735b (diff)
MIPS: Fix get_frame_info() handling of microMIPS function size
commit b6c7a324df37bf05ef7a2c1580683cf10d082d97 upstream. get_frame_info() is meant to iterate over up to the first 128 instructions within a function, but for microMIPS kernels it will not reach that many instructions unless the function is 512 bytes long since we calculate the maximum number of instructions to check by dividing the function length by the 4 byte size of a union mips_instruction. In microMIPS kernels this won't do since instructions are variable length. Fix this by instead checking whether the pointer to the current instruction has reached the end of the function, and use max_insns as a simple constant to check the number of iterations against. Signed-off-by: Paul Burton <paul.burton@imgtec.com> Fixes: 34c2f668d0f6 ("MIPS: microMIPS: Add unaligned access support.") Cc: Leonid Yegoshin <leonid.yegoshin@imgtec.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14530/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/process.c12
1 files changed, 5 insertions, 7 deletions
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 941a88191f0e..d56ef4ba0a84 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -293,9 +293,9 @@ static inline int is_sp_move_ins(union mips_instruction *ip)
293static int get_frame_info(struct mips_frame_info *info) 293static int get_frame_info(struct mips_frame_info *info)
294{ 294{
295 bool is_mmips = IS_ENABLED(CONFIG_CPU_MICROMIPS); 295 bool is_mmips = IS_ENABLED(CONFIG_CPU_MICROMIPS);
296 union mips_instruction insn, *ip; 296 union mips_instruction insn, *ip, *ip_end;
297 unsigned max_insns = info->func_size / sizeof(union mips_instruction); 297 const unsigned int max_insns = 128;
298 unsigned i; 298 unsigned int i;
299 299
300 info->pc_offset = -1; 300 info->pc_offset = -1;
301 info->frame_size = 0; 301 info->frame_size = 0;
@@ -304,11 +304,9 @@ static int get_frame_info(struct mips_frame_info *info)
304 if (!ip) 304 if (!ip)
305 goto err; 305 goto err;
306 306
307 if (max_insns == 0) 307 ip_end = (void *)ip + info->func_size;
308 max_insns = 128U; /* unknown function size */
309 max_insns = min(128U, max_insns);
310 308
311 for (i = 0; i < max_insns; i++, ip++) { 309 for (i = 0; i < max_insns && ip < ip_end; i++, ip++) {
312 if (is_mmips && mm_insn_16bit(ip->halfword[0])) { 310 if (is_mmips && mm_insn_16bit(ip->halfword[0])) {
313 insn.halfword[0] = 0; 311 insn.halfword[0] = 0;
314 insn.halfword[1] = ip->halfword[0]; 312 insn.halfword[1] = ip->halfword[0];