Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 75f115c0 authored by Jon Medhurst's avatar Jon Medhurst Committed by Tixy
Browse files

ARM: kprobes: Migrate ARM space_cccc_000x to decoding tables

parent 6c8a1929
Loading
Loading
Loading
Loading
+116 −136
Original line number Diff line number Diff line
@@ -997,7 +997,99 @@ static const union decode_item arm_1111_table[] = {
	DECODE_END
};

static const union decode_item arm_cccc_0001_0xx0____0xxx_table[] = {
	/* Miscellaneous instructions					*/

	/* MRS cpsr		cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */
	DECODE_SIMULATEX(0x0ff000f0, 0x01000000, simulate_mrs,
						 REGS(0, NOPC, 0, 0, 0)),

	/* BX			cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */
	DECODE_SIMULATE	(0x0ff000f0, 0x01200010, simulate_blx2bx),

	/* BLX (register)	cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */
	DECODE_SIMULATEX(0x0ff000f0, 0x01200030, simulate_blx2bx,
						 REGS(0, 0, 0, 0, NOPC)),

	/* CLZ			cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */
	DECODE_CUSTOM	(0x0ff000f0, 0x01600010, prep_emulate_rd12rm0),

	/* QADD			cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx */
	/* QSUB			cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx */
	/* QDADD		cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx */
	/* QDSUB		cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx */
	DECODE_CUSTOM	(0x0f9000f0, 0x01000050, prep_emulate_rd12rn16rm0_wflags),

	/* BXJ			cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
	/* MSR			cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
	/* MRS spsr		cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */
	/* BKPT			1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
	/* SMC			cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */
	/* And unallocated instructions...				*/
	DECODE_END
};

static const union decode_item arm_cccc_0001_0xx0____1xx0_table[] = {
	/* Halfword multiply and multiply-accumulate			*/

	/* SMLALxy		cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */
	DECODE_CUSTOM	(0x0ff00090, 0x01400080, prep_emulate_rdhi16rdlo12rs8rm0_wflags),

	/* SMULWy		cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */
	DECODE_OR	(0x0ff000b0, 0x012000a0),
	/* SMULxy		cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */
	DECODE_CUSTOM	(0x0ff00090, 0x01600080, prep_emulate_rd16rs8rm0_wflags),

	/* SMLAxy		cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx */
	DECODE_OR	(0x0ff00090, 0x01000080),
	/* SMLAWy		cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx */
	DECODE_CUSTOM	(0x0ff000b0, 0x01200080, prep_emulate_rd16rn12rs8rm0_wflags),

	DECODE_END
};

static const union decode_item arm_cccc_0000_____1001_table[] = {
	/* Multiply and multiply-accumulate				*/

	/* MUL			cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx */
	/* MULS			cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx */
	DECODE_CUSTOM	(0x0fe000f0, 0x00000090, prep_emulate_rd16rs8rm0_wflags),

	/* MLA			cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx */
	/* MLAS			cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx */
	DECODE_OR	(0x0fe000f0, 0x00200090),
	/* MLS			cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx */
	DECODE_CUSTOM	(0x0ff000f0, 0x00600090, prep_emulate_rd16rn12rs8rm0_wflags),

	/* UMAAL		cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx */
	DECODE_OR	(0x0ff000f0, 0x00400090),
	/* UMULL		cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx */
	/* UMULLS		cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx */
	/* UMLAL		cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx */
	/* UMLALS		cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx */
	/* SMULL		cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx */
	/* SMULLS		cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx */
	/* SMLAL		cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx */
	/* SMLALS		cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx */
	DECODE_CUSTOM	(0x0f8000f0, 0x00800090, prep_emulate_rdhi16rdlo12rs8rm0_wflags),

	DECODE_END
};

static const union decode_item arm_cccc_0001_____1001_table[] = {
	/* Synchronization primitives					*/

	/* SMP/SWPB		cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */
	DECODE_CUSTOM	(0x0fb000f0, 0x01000090, prep_emulate_rd12rn16rm0_wflags),

	/* LDREX/STREX{,D,B,H}	cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */
	/* And unallocated instructions...				*/
	DECODE_END
};

static const union decode_item arm_cccc_000x_____1xx1_table[] = {
	/* Extra load/store instructions				*/

	/* LDRD/STRD lr,pc,{...	cccc 000x x0x0 xxxx 111x xxxx 1101 xxxx */
	DECODE_REJECT	(0x0e10e0d0, 0x0000e0d0),

@@ -1011,6 +1103,20 @@ static const union decode_item arm_cccc_000x_____1xx1_table[] = {
	DECODE_EMULATEX	(0x0e5000d0, 0x004000d0, emulate_ldrdstrd,
						 REGS(NOPCWB, NOPCX, 0, 0, 0)),

	/* Reject Rd is PC */
	/* TODO: fold this into next entry when it is made a DECODE_EMULATE */
	DECODE_REJECT	(0x0000f000, 0x0000f000),

	/* STRH (register)	cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx */
	/* LDRH (register)	cccc 000x x0x1 xxxx xxxx xxxx 1011 xxxx */
	/* LDRSB (register)	cccc 000x x0x1 xxxx xxxx xxxx 1101 xxxx */
	/* LDRSH (register)	cccc 000x x0x1 xxxx xxxx xxxx 1111 xxxx */
	/* STRH (immediate)	cccc 000x x1x0 xxxx xxxx xxxx 1011 xxxx */
	/* LDRH (immediate)	cccc 000x x1x1 xxxx xxxx xxxx 1011 xxxx */
	/* LDRSB (immediate)	cccc 000x x1x1 xxxx xxxx xxxx 1101 xxxx */
	/* LDRSH (immediate)	cccc 000x x1x1 xxxx xxxx xxxx 1111 xxxx */
	DECODE_CUSTOM	(0x0e000090, 0x00000090, prep_emulate_ldr_str),

	DECODE_END
};

@@ -1079,146 +1185,20 @@ static const union decode_item arm_cccc_000x_table[] = {
static enum kprobe_insn __kprobes
space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
{
	/* cccc 0001 0xx0 xxxx xxxx xxxx xxxx xxx0 xxxx */
	if ((insn & 0x0f900010) == 0x01000000) {

		/* MRS cpsr : cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */
		if ((insn & 0x0ff000f0) == 0x01000000) {
			if (is_r15(insn, 12))
				return INSN_REJECTED;	/* Rd is PC */
			asi->insn_handler = simulate_mrs;
			return INSN_GOOD_NO_SLOT;
		}

		/* SMLALxy : cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */
		if ((insn & 0x0ff00090) == 0x01400080)
			return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn,
									asi);

		/* SMULWy : cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */
		/* SMULxy : cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */
		if ((insn & 0x0ff000b0) == 0x012000a0 ||
		    (insn & 0x0ff00090) == 0x01600080)
			return prep_emulate_rd16rs8rm0_wflags(insn, asi);

		/* SMLAxy : cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx : Q */
		/* SMLAWy : cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx : Q */
		if ((insn & 0x0ff00090) == 0x01000080 ||
		    (insn & 0x0ff000b0) == 0x01200080)
			return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);

		/* BXJ      : cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
		/* MSR      : cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
		/* MRS spsr : cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */

		/* Other instruction encodings aren't yet defined */
		return INSN_REJECTED;
	}

	/* cccc 0001 0xx0 xxxx xxxx xxxx xxxx 0xx1 xxxx */
	else if ((insn & 0x0f900090) == 0x01000010) {

		/* BLX(2) : cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */
		/* BX     : cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */
		if ((insn & 0x0ff000d0) == 0x01200010) {
			if ((insn & 0x0ff000ff) == 0x0120003f)
				return INSN_REJECTED; /* BLX pc */
			asi->insn_handler = simulate_blx2bx;
			return INSN_GOOD_NO_SLOT;
		}

		/* CLZ : cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */
		if ((insn & 0x0ff000f0) == 0x01600010)
			return prep_emulate_rd12rm0(insn, asi);
	if ((insn & 0x0f900080) == 0x01000000)
		return kprobe_decode_insn(insn, asi, arm_cccc_0001_0xx0____0xxx_table, false);

		/* QADD    : cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx :Q */
		/* QSUB    : cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx :Q */
		/* QDADD   : cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx :Q */
		/* QDSUB   : cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx :Q */
		if ((insn & 0x0f9000f0) == 0x01000050)
			return prep_emulate_rd12rn16rm0_wflags(insn, asi);
	if ((insn & 0x0f900090) == 0x01000080)
		return kprobe_decode_insn(insn, asi, arm_cccc_0001_0xx0____1xx0_table, false);

		/* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
		/* SMC  : cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */
	if ((insn & 0x0f0000f0) == 0x00000090)
		return kprobe_decode_insn(insn, asi, arm_cccc_0000_____1001_table, false);

		/* Other instruction encodings aren't yet defined */
		return INSN_REJECTED;
	}
	if ((insn & 0x0f0000f0) == 0x01000090)
		return kprobe_decode_insn(insn, asi, arm_cccc_0001_____1001_table, false);

	/* cccc 0000 xxxx xxxx xxxx xxxx xxxx 1001 xxxx */
	else if ((insn & 0x0f0000f0) == 0x00000090) {

		/* MUL    : cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx :   */
		/* MULS   : cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx :cc */
		/* MLA    : cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx :   */
		/* MLAS   : cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx :cc */
		/* UMAAL  : cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx :   */
		/* undef  : cccc 0000 0101 xxxx xxxx xxxx 1001 xxxx :   */
		/* MLS    : cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx :   */
		/* undef  : cccc 0000 0111 xxxx xxxx xxxx 1001 xxxx :   */
		/* UMULL  : cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx :   */
		/* UMULLS : cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx :cc */
		/* UMLAL  : cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx :   */
		/* UMLALS : cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx :cc */
		/* SMULL  : cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx :   */
		/* SMULLS : cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx :cc */
		/* SMLAL  : cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx :   */
		/* SMLALS : cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx :cc */
		if ((insn & 0x00d00000) == 0x00500000)
			return INSN_REJECTED;
		else if ((insn & 0x00e00000) == 0x00000000)
			return prep_emulate_rd16rs8rm0_wflags(insn, asi);
		else if ((insn & 0x00a00000) == 0x00200000)
			return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
		else
			return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn,
									asi);
	}

	/* cccc 000x xxxx xxxx xxxx xxxx xxxx 1xx1 xxxx */
	else if ((insn & 0x0e000090) == 0x00000090) {

		/* SWP   : cccc 0001 0000 xxxx xxxx xxxx 1001 xxxx */
		/* SWPB  : cccc 0001 0100 xxxx xxxx xxxx 1001 xxxx */
		/* ???   : cccc 0001 0x01 xxxx xxxx xxxx 1001 xxxx */
		/* ???   : cccc 0001 0x10 xxxx xxxx xxxx 1001 xxxx */
		/* ???   : cccc 0001 0x11 xxxx xxxx xxxx 1001 xxxx */
		/* STREX : cccc 0001 1000 xxxx xxxx xxxx 1001 xxxx */
		/* LDREX : cccc 0001 1001 xxxx xxxx xxxx 1001 xxxx */
		/* STREXD: cccc 0001 1010 xxxx xxxx xxxx 1001 xxxx */
		/* LDREXD: cccc 0001 1011 xxxx xxxx xxxx 1001 xxxx */
		/* STREXB: cccc 0001 1100 xxxx xxxx xxxx 1001 xxxx */
		/* LDREXB: cccc 0001 1101 xxxx xxxx xxxx 1001 xxxx */
		/* STREXH: cccc 0001 1110 xxxx xxxx xxxx 1001 xxxx */
		/* LDREXH: cccc 0001 1111 xxxx xxxx xxxx 1001 xxxx */

		/* LDRD  : cccc 000x xxx0 xxxx xxxx xxxx 1101 xxxx */
		/* STRD  : cccc 000x xxx0 xxxx xxxx xxxx 1111 xxxx */
		/* LDRH  : cccc 000x xxx1 xxxx xxxx xxxx 1011 xxxx */
		/* STRH  : cccc 000x xxx0 xxxx xxxx xxxx 1011 xxxx */
		/* LDRSB : cccc 000x xxx1 xxxx xxxx xxxx 1101 xxxx */
		/* LDRSH : cccc 000x xxx1 xxxx xxxx xxxx 1111 xxxx */
		if ((insn & 0x0f0000f0) == 0x01000090) {
			if ((insn & 0x0fb000f0) == 0x01000090) {
				/* SWP/SWPB */
				return prep_emulate_rd12rn16rm0_wflags(insn,
									asi);
			} else {
				/* STREX/LDREX variants and unallocaed space */
				return INSN_REJECTED;
			}

		} else if ((insn & 0x0e1000d0) == 0x00000d0) {

			return kprobe_decode_insn(insn, asi, arm_cccc_000x_____1xx1_table,
									false);
		}

		/* LDRH/STRH/LDRSB/LDRSH */
		if (is_r15(insn, 12))
			return INSN_REJECTED;	/* Rd is PC */
		return prep_emulate_ldr_str(insn, asi);
	}
	if ((insn & 0x0e000090) == 0x00000090)
		return kprobe_decode_insn(insn, asi, arm_cccc_000x_____1xx1_table, false);

	return kprobe_decode_insn(insn, asi, arm_cccc_000x_table, false);
}