Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * several functions that help interpret ARC instructions
0004  * used for unaligned accesses, kprobes and kgdb
0005  *
0006  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
0007  */
0008 
0009 #include <linux/types.h>
0010 #include <linux/kprobes.h>
0011 #include <linux/slab.h>
0012 #include <linux/uaccess.h>
0013 #include <asm/disasm.h>
0014 
0015 #if defined(CONFIG_KGDB) || defined(CONFIG_ARC_EMUL_UNALIGNED) || \
0016     defined(CONFIG_KPROBES)
0017 
0018 /* disasm_instr: Analyses instruction at addr, stores
0019  * findings in *state
0020  */
0021 void __kprobes disasm_instr(unsigned long addr, struct disasm_state *state,
0022     int userspace, struct pt_regs *regs, struct callee_regs *cregs)
0023 {
0024     int fieldA = 0;
0025     int fieldC = 0, fieldCisReg = 0;
0026     uint16_t word1 = 0, word0 = 0;
0027     int subopcode, is_linked, op_format;
0028     uint16_t *ins_ptr;
0029     uint16_t ins_buf[4];
0030     int bytes_not_copied = 0;
0031 
0032     memset(state, 0, sizeof(struct disasm_state));
0033 
0034     /* This fetches the upper part of the 32 bit instruction
0035      * in both the cases of Little Endian or Big Endian configurations. */
0036     if (userspace) {
0037         bytes_not_copied = copy_from_user(ins_buf,
0038                         (const void __user *) addr, 8);
0039         if (bytes_not_copied > 6)
0040             goto fault;
0041         ins_ptr = ins_buf;
0042     } else {
0043         ins_ptr = (uint16_t *) addr;
0044     }
0045 
0046     word1 = *((uint16_t *)addr);
0047 
0048     state->major_opcode = (word1 >> 11) & 0x1F;
0049 
0050     /* Check if the instruction is 32 bit or 16 bit instruction */
0051     if (state->major_opcode < 0x0B) {
0052         if (bytes_not_copied > 4)
0053             goto fault;
0054         state->instr_len = 4;
0055         word0 = *((uint16_t *)(addr+2));
0056         state->words[0] = (word1 << 16) | word0;
0057     } else {
0058         state->instr_len = 2;
0059         state->words[0] = word1;
0060     }
0061 
0062     /* Read the second word in case of limm */
0063     word1 = *((uint16_t *)(addr + state->instr_len));
0064     word0 = *((uint16_t *)(addr + state->instr_len + 2));
0065     state->words[1] = (word1 << 16) | word0;
0066 
0067     switch (state->major_opcode) {
0068     case op_Bcc:
0069         state->is_branch = 1;
0070 
0071         /* unconditional branch s25, conditional branch s21 */
0072         fieldA = (IS_BIT(state->words[0], 16)) ?
0073             FIELD_s25(state->words[0]) :
0074             FIELD_s21(state->words[0]);
0075 
0076         state->delay_slot = IS_BIT(state->words[0], 5);
0077         state->target = fieldA + (addr & ~0x3);
0078         state->flow = direct_jump;
0079         break;
0080 
0081     case op_BLcc:
0082         if (IS_BIT(state->words[0], 16)) {
0083             /* Branch and Link*/
0084             /* unconditional branch s25, conditional branch s21 */
0085             fieldA = (IS_BIT(state->words[0], 17)) ?
0086                 (FIELD_s25(state->words[0]) & ~0x3) :
0087                 FIELD_s21(state->words[0]);
0088 
0089             state->flow = direct_call;
0090         } else {
0091             /*Branch On Compare */
0092             fieldA = FIELD_s9(state->words[0]) & ~0x3;
0093             state->flow = direct_jump;
0094         }
0095 
0096         state->delay_slot = IS_BIT(state->words[0], 5);
0097         state->target = fieldA + (addr & ~0x3);
0098         state->is_branch = 1;
0099         break;
0100 
0101     case op_LD:  /* LD<zz> a,[b,s9] */
0102         state->write = 0;
0103         state->di = BITS(state->words[0], 11, 11);
0104         if (state->di)
0105             break;
0106         state->x = BITS(state->words[0], 6, 6);
0107         state->zz = BITS(state->words[0], 7, 8);
0108         state->aa = BITS(state->words[0], 9, 10);
0109         state->wb_reg = FIELD_B(state->words[0]);
0110         if (state->wb_reg == REG_LIMM) {
0111             state->instr_len += 4;
0112             state->aa = 0;
0113             state->src1 = state->words[1];
0114         } else {
0115             state->src1 = get_reg(state->wb_reg, regs, cregs);
0116         }
0117         state->src2 = FIELD_s9(state->words[0]);
0118         state->dest = FIELD_A(state->words[0]);
0119         state->pref = (state->dest == REG_LIMM);
0120         break;
0121 
0122     case op_ST:
0123         state->write = 1;
0124         state->di = BITS(state->words[0], 5, 5);
0125         if (state->di)
0126             break;
0127         state->aa = BITS(state->words[0], 3, 4);
0128         state->zz = BITS(state->words[0], 1, 2);
0129         state->src1 = FIELD_C(state->words[0]);
0130         if (state->src1 == REG_LIMM) {
0131             state->instr_len += 4;
0132             state->src1 = state->words[1];
0133         } else {
0134             state->src1 = get_reg(state->src1, regs, cregs);
0135         }
0136         state->wb_reg = FIELD_B(state->words[0]);
0137         if (state->wb_reg == REG_LIMM) {
0138             state->aa = 0;
0139             state->instr_len += 4;
0140             state->src2 = state->words[1];
0141         } else {
0142             state->src2 = get_reg(state->wb_reg, regs, cregs);
0143         }
0144         state->src3 = FIELD_s9(state->words[0]);
0145         break;
0146 
0147     case op_MAJOR_4:
0148         subopcode = MINOR_OPCODE(state->words[0]);
0149         switch (subopcode) {
0150         case 32:    /* Jcc */
0151         case 33:    /* Jcc.D */
0152         case 34:    /* JLcc */
0153         case 35:    /* JLcc.D */
0154             is_linked = 0;
0155 
0156             if (subopcode == 33 || subopcode == 35)
0157                 state->delay_slot = 1;
0158 
0159             if (subopcode == 34 || subopcode == 35)
0160                 is_linked = 1;
0161 
0162             fieldCisReg = 0;
0163             op_format = BITS(state->words[0], 22, 23);
0164             if (op_format == 0 || ((op_format == 3) &&
0165                 (!IS_BIT(state->words[0], 5)))) {
0166                 fieldC = FIELD_C(state->words[0]);
0167 
0168                 if (fieldC == REG_LIMM) {
0169                     fieldC = state->words[1];
0170                     state->instr_len += 4;
0171                 } else {
0172                     fieldCisReg = 1;
0173                 }
0174             } else if (op_format == 1 || ((op_format == 3)
0175                 && (IS_BIT(state->words[0], 5)))) {
0176                 fieldC = FIELD_C(state->words[0]);
0177             } else  {
0178                 /* op_format == 2 */
0179                 fieldC = FIELD_s12(state->words[0]);
0180             }
0181 
0182             if (!fieldCisReg) {
0183                 state->target = fieldC;
0184                 state->flow = is_linked ?
0185                     direct_call : direct_jump;
0186             } else {
0187                 state->target = get_reg(fieldC, regs, cregs);
0188                 state->flow = is_linked ?
0189                     indirect_call : indirect_jump;
0190             }
0191             state->is_branch = 1;
0192             break;
0193 
0194         case 40:    /* LPcc */
0195             if (BITS(state->words[0], 22, 23) == 3) {
0196                 /* Conditional LPcc u7 */
0197                 fieldC = FIELD_C(state->words[0]);
0198 
0199                 fieldC = fieldC << 1;
0200                 fieldC += (addr & ~0x03);
0201                 state->is_branch = 1;
0202                 state->flow = direct_jump;
0203                 state->target = fieldC;
0204             }
0205             /* For Unconditional lp, next pc is the fall through
0206              * which is updated */
0207             break;
0208 
0209         case 48 ... 55: /* LD a,[b,c] */
0210             state->di = BITS(state->words[0], 15, 15);
0211             if (state->di)
0212                 break;
0213             state->x = BITS(state->words[0], 16, 16);
0214             state->zz = BITS(state->words[0], 17, 18);
0215             state->aa = BITS(state->words[0], 22, 23);
0216             state->wb_reg = FIELD_B(state->words[0]);
0217             if (state->wb_reg == REG_LIMM) {
0218                 state->instr_len += 4;
0219                 state->src1 = state->words[1];
0220             } else {
0221                 state->src1 = get_reg(state->wb_reg, regs,
0222                         cregs);
0223             }
0224             state->src2 = FIELD_C(state->words[0]);
0225             if (state->src2 == REG_LIMM) {
0226                 state->instr_len += 4;
0227                 state->src2 = state->words[1];
0228             } else {
0229                 state->src2 = get_reg(state->src2, regs,
0230                     cregs);
0231             }
0232             state->dest = FIELD_A(state->words[0]);
0233             if (state->dest == REG_LIMM)
0234                 state->pref = 1;
0235             break;
0236 
0237         case 10:    /* MOV */
0238             /* still need to check for limm to extract instr len */
0239             /* MOV is special case because it only takes 2 args */
0240             switch (BITS(state->words[0], 22, 23)) {
0241             case 0: /* OP a,b,c */
0242                 if (FIELD_C(state->words[0]) == REG_LIMM)
0243                     state->instr_len += 4;
0244                 break;
0245             case 1: /* OP a,b,u6 */
0246                 break;
0247             case 2: /* OP b,b,s12 */
0248                 break;
0249             case 3: /* OP.cc b,b,c/u6 */
0250                 if ((!IS_BIT(state->words[0], 5)) &&
0251                     (FIELD_C(state->words[0]) == REG_LIMM))
0252                     state->instr_len += 4;
0253                 break;
0254             }
0255             break;
0256 
0257 
0258         default:
0259             /* Not a Load, Jump or Loop instruction */
0260             /* still need to check for limm to extract instr len */
0261             switch (BITS(state->words[0], 22, 23)) {
0262             case 0: /* OP a,b,c */
0263                 if ((FIELD_B(state->words[0]) == REG_LIMM) ||
0264                     (FIELD_C(state->words[0]) == REG_LIMM))
0265                     state->instr_len += 4;
0266                 break;
0267             case 1: /* OP a,b,u6 */
0268                 break;
0269             case 2: /* OP b,b,s12 */
0270                 break;
0271             case 3: /* OP.cc b,b,c/u6 */
0272                 if ((!IS_BIT(state->words[0], 5)) &&
0273                    ((FIELD_B(state->words[0]) == REG_LIMM) ||
0274                     (FIELD_C(state->words[0]) == REG_LIMM)))
0275                     state->instr_len += 4;
0276                 break;
0277             }
0278             break;
0279         }
0280         break;
0281 
0282     /* 16 Bit Instructions */
0283     case op_LD_ADD: /* LD_S|LDB_S|LDW_S a,[b,c] */
0284         state->zz = BITS(state->words[0], 3, 4);
0285         state->src1 = get_reg(FIELD_S_B(state->words[0]), regs, cregs);
0286         state->src2 = get_reg(FIELD_S_C(state->words[0]), regs, cregs);
0287         state->dest = FIELD_S_A(state->words[0]);
0288         break;
0289 
0290     case op_ADD_MOV_CMP:
0291         /* check for limm, ignore mov_s h,b (== mov_s 0,b) */
0292         if ((BITS(state->words[0], 3, 4) < 3) &&
0293             (FIELD_S_H(state->words[0]) == REG_LIMM))
0294             state->instr_len += 4;
0295         break;
0296 
0297     case op_S:
0298         subopcode = BITS(state->words[0], 5, 7);
0299         switch (subopcode) {
0300         case 0: /* j_s */
0301         case 1: /* j_s.d */
0302         case 2: /* jl_s */
0303         case 3: /* jl_s.d */
0304             state->target = get_reg(FIELD_S_B(state->words[0]),
0305                         regs, cregs);
0306             state->delay_slot = subopcode & 1;
0307             state->flow = (subopcode >= 2) ?
0308                 direct_call : indirect_jump;
0309             break;
0310         case 7:
0311             switch (BITS(state->words[0], 8, 10)) {
0312             case 4: /* jeq_s [blink] */
0313             case 5: /* jne_s [blink] */
0314             case 6: /* j_s [blink] */
0315             case 7: /* j_s.d [blink] */
0316                 state->delay_slot = (subopcode == 7);
0317                 state->flow = indirect_jump;
0318                 state->target = get_reg(31, regs, cregs);
0319             default:
0320                 break;
0321             }
0322         default:
0323             break;
0324         }
0325         break;
0326 
0327     case op_LD_S:   /* LD_S c, [b, u7] */
0328         state->src1 = get_reg(FIELD_S_B(state->words[0]), regs, cregs);
0329         state->src2 = FIELD_S_u7(state->words[0]);
0330         state->dest = FIELD_S_C(state->words[0]);
0331         break;
0332 
0333     case op_LDB_S:
0334     case op_STB_S:
0335         /* no further handling required as byte accesses should not
0336          * cause an unaligned access exception */
0337         state->zz = 1;
0338         break;
0339 
0340     case op_LDWX_S: /* LDWX_S c, [b, u6] */
0341         state->x = 1;
0342         fallthrough;
0343 
0344     case op_LDW_S:  /* LDW_S c, [b, u6] */
0345         state->zz = 2;
0346         state->src1 = get_reg(FIELD_S_B(state->words[0]), regs, cregs);
0347         state->src2 = FIELD_S_u6(state->words[0]);
0348         state->dest = FIELD_S_C(state->words[0]);
0349         break;
0350 
0351     case op_ST_S:   /* ST_S c, [b, u7] */
0352         state->write = 1;
0353         state->src1 = get_reg(FIELD_S_C(state->words[0]), regs, cregs);
0354         state->src2 = get_reg(FIELD_S_B(state->words[0]), regs, cregs);
0355         state->src3 = FIELD_S_u7(state->words[0]);
0356         break;
0357 
0358     case op_STW_S:  /* STW_S c,[b,u6] */
0359         state->write = 1;
0360         state->zz = 2;
0361         state->src1 = get_reg(FIELD_S_C(state->words[0]), regs, cregs);
0362         state->src2 = get_reg(FIELD_S_B(state->words[0]), regs, cregs);
0363         state->src3 = FIELD_S_u6(state->words[0]);
0364         break;
0365 
0366     case op_SP: /* LD_S|LDB_S b,[sp,u7], ST_S|STB_S b,[sp,u7] */
0367         /* note: we are ignoring possibility of:
0368          * ADD_S, SUB_S, PUSH_S, POP_S as these should not
0369          * cause unaligned exception anyway */
0370         state->write = BITS(state->words[0], 6, 6);
0371         state->zz = BITS(state->words[0], 5, 5);
0372         if (state->zz)
0373             break;  /* byte accesses should not come here */
0374         if (!state->write) {
0375             state->src1 = get_reg(28, regs, cregs);
0376             state->src2 = FIELD_S_u7(state->words[0]);
0377             state->dest = FIELD_S_B(state->words[0]);
0378         } else {
0379             state->src1 = get_reg(FIELD_S_B(state->words[0]), regs,
0380                     cregs);
0381             state->src2 = get_reg(28, regs, cregs);
0382             state->src3 = FIELD_S_u7(state->words[0]);
0383         }
0384         break;
0385 
0386     case op_GP: /* LD_S|LDB_S|LDW_S r0,[gp,s11/s9/s10] */
0387         /* note: ADD_S r0, gp, s11 is ignored */
0388         state->zz = BITS(state->words[0], 9, 10);
0389         state->src1 = get_reg(26, regs, cregs);
0390         state->src2 = state->zz ? FIELD_S_s10(state->words[0]) :
0391             FIELD_S_s11(state->words[0]);
0392         state->dest = 0;
0393         break;
0394 
0395     case op_Pcl:    /* LD_S b,[pcl,u10] */
0396         state->src1 = regs->ret & ~3;
0397         state->src2 = FIELD_S_u10(state->words[0]);
0398         state->dest = FIELD_S_B(state->words[0]);
0399         break;
0400 
0401     case op_BR_S:
0402         state->target = FIELD_S_s8(state->words[0]) + (addr & ~0x03);
0403         state->flow = direct_jump;
0404         state->is_branch = 1;
0405         break;
0406 
0407     case op_B_S:
0408         fieldA = (BITS(state->words[0], 9, 10) == 3) ?
0409             FIELD_S_s7(state->words[0]) :
0410             FIELD_S_s10(state->words[0]);
0411         state->target = fieldA + (addr & ~0x03);
0412         state->flow = direct_jump;
0413         state->is_branch = 1;
0414         break;
0415 
0416     case op_BL_S:
0417         state->target = FIELD_S_s13(state->words[0]) + (addr & ~0x03);
0418         state->flow = direct_call;
0419         state->is_branch = 1;
0420         break;
0421 
0422     default:
0423         break;
0424     }
0425 
0426     if (bytes_not_copied <= (8 - state->instr_len))
0427         return;
0428 
0429 fault:  state->fault = 1;
0430 }
0431 
0432 long __kprobes get_reg(int reg, struct pt_regs *regs,
0433                struct callee_regs *cregs)
0434 {
0435     long *p;
0436 
0437 #if defined(CONFIG_ISA_ARCOMPACT)
0438     if (reg <= 12) {
0439         p = &regs->r0;
0440         return p[-reg];
0441     }
0442 #else /* CONFIG_ISA_ARCV2 */
0443     if (reg <= 11) {
0444         p = &regs->r0;
0445         return p[reg];
0446     }
0447 
0448     if (reg == 12)
0449         return regs->r12;
0450     if (reg == 30)
0451         return regs->r30;
0452 #ifdef CONFIG_ARC_HAS_ACCL_REGS
0453     if (reg == 58)
0454         return regs->r58;
0455     if (reg == 59)
0456         return regs->r59;
0457 #endif
0458 #endif
0459     if (cregs && (reg <= 25)) {
0460         p = &cregs->r13;
0461         return p[13 - reg];
0462     }
0463 
0464     if (reg == 26)
0465         return regs->r26;
0466     if (reg == 27)
0467         return regs->fp;
0468     if (reg == 28)
0469         return regs->sp;
0470     if (reg == 31)
0471         return regs->blink;
0472 
0473     return 0;
0474 }
0475 
0476 void __kprobes set_reg(int reg, long val, struct pt_regs *regs,
0477         struct callee_regs *cregs)
0478 {
0479     long *p;
0480 
0481 #if defined(CONFIG_ISA_ARCOMPACT)
0482     switch (reg) {
0483     case 0 ... 12:
0484         p = &regs->r0;
0485         p[-reg] = val;
0486         break;
0487     case 13 ... 25:
0488         if (cregs) {
0489             p = &cregs->r13;
0490             p[13 - reg] = val;
0491         }
0492         break;
0493     case 26:
0494         regs->r26 = val;
0495         break;
0496     case 27:
0497         regs->fp = val;
0498         break;
0499     case 28:
0500         regs->sp = val;
0501         break;
0502     case 31:
0503         regs->blink = val;
0504         break;
0505     default:
0506         break;
0507     }
0508 #else /* CONFIG_ISA_ARCV2 */
0509     switch (reg) {
0510     case 0 ... 11:
0511         p = &regs->r0;
0512         p[reg] = val;
0513         break;
0514     case 12:
0515         regs->r12 = val;
0516         break;
0517     case 13 ... 25:
0518         if (cregs) {
0519             p = &cregs->r13;
0520             p[13 - reg] = val;
0521         }
0522         break;
0523     case 26:
0524         regs->r26 = val;
0525         break;
0526     case 27:
0527         regs->fp = val;
0528         break;
0529     case 28:
0530         regs->sp = val;
0531         break;
0532     case 30:
0533         regs->r30 = val;
0534         break;
0535     case 31:
0536         regs->blink = val;
0537         break;
0538 #ifdef CONFIG_ARC_HAS_ACCL_REGS
0539     case 58:
0540         regs->r58 = val;
0541         break;
0542     case 59:
0543         regs->r59 = val;
0544         break;
0545 #endif
0546     default:
0547         break;
0548     }
0549 #endif
0550 }
0551 
0552 /*
0553  * Disassembles the insn at @pc and sets @next_pc to next PC (which could be
0554  * @pc +2/4/6 (ARCompact ISA allows free intermixing of 16/32 bit insns).
0555  *
0556  * If @pc is a branch
0557  *  -@tgt_if_br is set to branch target.
0558  *  -If branch has delay slot, @next_pc updated with actual next PC.
0559  */
0560 int __kprobes disasm_next_pc(unsigned long pc, struct pt_regs *regs,
0561                  struct callee_regs *cregs,
0562                  unsigned long *next_pc, unsigned long *tgt_if_br)
0563 {
0564     struct disasm_state instr;
0565 
0566     disasm_instr(pc, &instr, 0, regs, cregs);
0567 
0568     *next_pc = pc + instr.instr_len;
0569 
0570     /* Instruction with possible two targets branch, jump and loop */
0571     if (instr.is_branch)
0572         *tgt_if_br = instr.target;
0573 
0574     /* For the instructions with delay slots, the fall through is the
0575      * instruction following the instruction in delay slot.
0576      */
0577      if (instr.delay_slot) {
0578         struct disasm_state instr_d;
0579 
0580         disasm_instr(*next_pc, &instr_d, 0, regs, cregs);
0581 
0582         *next_pc += instr_d.instr_len;
0583      }
0584 
0585      /* Zero Overhead Loop - end of the loop */
0586     if (!(regs->status32 & STATUS32_L) && (*next_pc == regs->lp_end)
0587         && (regs->lp_count > 1)) {
0588         *next_pc = regs->lp_start;
0589     }
0590 
0591     return instr.is_branch;
0592 }
0593 
0594 #endif /* CONFIG_KGDB || CONFIG_ARC_EMUL_UNALIGNED || CONFIG_KPROBES */