LoongArch: Add guard for the larch_insn_gen_xxx functions

Add guard for the larch_insn_gen_xxx functions to verify whether the
immediate operand is within the acceptable range.

Signed-off-by: WANG Rui <wangrui@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
This commit is contained in:
WANG Rui 2023-06-29 20:58:42 +08:00 committed by Huacai Chen
parent d7c2496097
commit 0d03e9dce5
3 changed files with 34 additions and 5 deletions

View File

@ -5,6 +5,7 @@
#ifndef _ASM_INST_H #ifndef _ASM_INST_H
#define _ASM_INST_H #define _ASM_INST_H
#include <linux/bitops.h>
#include <linux/types.h> #include <linux/types.h>
#include <asm/asm.h> #include <asm/asm.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
@ -15,14 +16,22 @@
#define ADDR_IMMMASK_LU52ID 0xFFF0000000000000 #define ADDR_IMMMASK_LU52ID 0xFFF0000000000000
#define ADDR_IMMMASK_LU32ID 0x000FFFFF00000000 #define ADDR_IMMMASK_LU32ID 0x000FFFFF00000000
#define ADDR_IMMMASK_LU12IW 0x00000000FFFFF000 #define ADDR_IMMMASK_LU12IW 0x00000000FFFFF000
#define ADDR_IMMMASK_ORI 0x0000000000000FFF
#define ADDR_IMMMASK_ADDU16ID 0x00000000FFFF0000 #define ADDR_IMMMASK_ADDU16ID 0x00000000FFFF0000
#define ADDR_IMMSHIFT_LU52ID 52 #define ADDR_IMMSHIFT_LU52ID 52
#define ADDR_IMMSBIDX_LU52ID 11
#define ADDR_IMMSHIFT_LU32ID 32 #define ADDR_IMMSHIFT_LU32ID 32
#define ADDR_IMMSBIDX_LU32ID 19
#define ADDR_IMMSHIFT_LU12IW 12 #define ADDR_IMMSHIFT_LU12IW 12
#define ADDR_IMMSBIDX_LU12IW 19
#define ADDR_IMMSHIFT_ORI 0
#define ADDR_IMMSBIDX_ORI 63
#define ADDR_IMMSHIFT_ADDU16ID 16 #define ADDR_IMMSHIFT_ADDU16ID 16
#define ADDR_IMMSBIDX_ADDU16ID 15
#define ADDR_IMM(addr, INSN) ((addr & ADDR_IMMMASK_##INSN) >> ADDR_IMMSHIFT_##INSN) #define ADDR_IMM(addr, INSN) \
(sign_extend64(((addr & ADDR_IMMMASK_##INSN) >> ADDR_IMMSHIFT_##INSN), ADDR_IMMSBIDX_##INSN))
enum reg0i15_op { enum reg0i15_op {
break_op = 0x54, break_op = 0x54,
@ -449,7 +458,7 @@ u32 larch_insn_gen_move(enum loongarch_gpr rd, enum loongarch_gpr rj);
u32 larch_insn_gen_lu12iw(enum loongarch_gpr rd, int imm); u32 larch_insn_gen_lu12iw(enum loongarch_gpr rd, int imm);
u32 larch_insn_gen_lu32id(enum loongarch_gpr rd, int imm); u32 larch_insn_gen_lu32id(enum loongarch_gpr rd, int imm);
u32 larch_insn_gen_lu52id(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm); u32 larch_insn_gen_lu52id(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm);
u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, unsigned long pc, unsigned long dest); u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm);
static inline bool signed_imm_check(long val, unsigned int bit) static inline bool signed_imm_check(long val, unsigned int bit)
{ {

View File

@ -55,7 +55,7 @@ static inline struct plt_entry emit_plt_entry(unsigned long val)
lu12iw = larch_insn_gen_lu12iw(LOONGARCH_GPR_T1, ADDR_IMM(val, LU12IW)); lu12iw = larch_insn_gen_lu12iw(LOONGARCH_GPR_T1, ADDR_IMM(val, LU12IW));
lu32id = larch_insn_gen_lu32id(LOONGARCH_GPR_T1, ADDR_IMM(val, LU32ID)); lu32id = larch_insn_gen_lu32id(LOONGARCH_GPR_T1, ADDR_IMM(val, LU32ID));
lu52id = larch_insn_gen_lu52id(LOONGARCH_GPR_T1, LOONGARCH_GPR_T1, ADDR_IMM(val, LU52ID)); lu52id = larch_insn_gen_lu52id(LOONGARCH_GPR_T1, LOONGARCH_GPR_T1, ADDR_IMM(val, LU52ID));
jirl = larch_insn_gen_jirl(0, LOONGARCH_GPR_T1, 0, (val & 0xfff)); jirl = larch_insn_gen_jirl(0, LOONGARCH_GPR_T1, ADDR_IMM(val, ORI));
return (struct plt_entry) { lu12iw, lu32id, lu52id, jirl }; return (struct plt_entry) { lu12iw, lu32id, lu52id, jirl };
} }

View File

@ -226,6 +226,11 @@ u32 larch_insn_gen_lu12iw(enum loongarch_gpr rd, int imm)
{ {
union loongarch_instruction insn; union loongarch_instruction insn;
if (imm < -SZ_512K || imm >= SZ_512K) {
pr_warn("The generated lu12i.w instruction is out of range.\n");
return INSN_BREAK;
}
emit_lu12iw(&insn, rd, imm); emit_lu12iw(&insn, rd, imm);
return insn.word; return insn.word;
@ -235,6 +240,11 @@ u32 larch_insn_gen_lu32id(enum loongarch_gpr rd, int imm)
{ {
union loongarch_instruction insn; union loongarch_instruction insn;
if (imm < -SZ_512K || imm >= SZ_512K) {
pr_warn("The generated lu32i.d instruction is out of range.\n");
return INSN_BREAK;
}
emit_lu32id(&insn, rd, imm); emit_lu32id(&insn, rd, imm);
return insn.word; return insn.word;
@ -244,16 +254,26 @@ u32 larch_insn_gen_lu52id(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm)
{ {
union loongarch_instruction insn; union loongarch_instruction insn;
if (imm < -SZ_2K || imm >= SZ_2K) {
pr_warn("The generated lu52i.d instruction is out of range.\n");
return INSN_BREAK;
}
emit_lu52id(&insn, rd, rj, imm); emit_lu52id(&insn, rd, rj, imm);
return insn.word; return insn.word;
} }
u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, unsigned long pc, unsigned long dest) u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm)
{ {
union loongarch_instruction insn; union loongarch_instruction insn;
emit_jirl(&insn, rj, rd, (dest - pc) >> 2); if ((imm & 3) || imm < -SZ_128K || imm >= SZ_128K) {
pr_warn("The generated jirl instruction is out of range.\n");
return INSN_BREAK;
}
emit_jirl(&insn, rj, rd, imm >> 2);
return insn.word; return insn.word;
} }