cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

probes.c (3452B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 *    Common helper functions for kprobes and uprobes
      4 *
      5 *    Copyright IBM Corp. 2014
      6 */
      7
      8#include <linux/errno.h>
      9#include <asm/kprobes.h>
     10#include <asm/dis.h>
     11
     12int probe_is_prohibited_opcode(u16 *insn)
     13{
     14	if (!is_known_insn((unsigned char *)insn))
     15		return -EINVAL;
     16	switch (insn[0] >> 8) {
     17	case 0x0c:	/* bassm */
     18	case 0x0b:	/* bsm	 */
     19	case 0x83:	/* diag  */
     20	case 0x44:	/* ex	 */
     21	case 0xac:	/* stnsm */
     22	case 0xad:	/* stosm */
     23		return -EINVAL;
     24	case 0xc6:
     25		switch (insn[0] & 0x0f) {
     26		case 0x00: /* exrl   */
     27			return -EINVAL;
     28		}
     29	}
     30	switch (insn[0]) {
     31	case 0x0101:	/* pr	 */
     32	case 0xb25a:	/* bsa	 */
     33	case 0xb240:	/* bakr  */
     34	case 0xb258:	/* bsg	 */
     35	case 0xb218:	/* pc	 */
     36	case 0xb228:	/* pt	 */
     37	case 0xb98d:	/* epsw	 */
     38	case 0xe560:	/* tbegin */
     39	case 0xe561:	/* tbeginc */
     40	case 0xb2f8:	/* tend	 */
     41		return -EINVAL;
     42	}
     43	return 0;
     44}
     45
     46int probe_get_fixup_type(u16 *insn)
     47{
     48	/* default fixup method */
     49	int fixup = FIXUP_PSW_NORMAL;
     50
     51	switch (insn[0] >> 8) {
     52	case 0x05:	/* balr	*/
     53	case 0x0d:	/* basr */
     54		fixup = FIXUP_RETURN_REGISTER;
     55		/* if r2 = 0, no branch will be taken */
     56		if ((insn[0] & 0x0f) == 0)
     57			fixup |= FIXUP_BRANCH_NOT_TAKEN;
     58		break;
     59	case 0x06:	/* bctr	*/
     60	case 0x07:	/* bcr	*/
     61		fixup = FIXUP_BRANCH_NOT_TAKEN;
     62		break;
     63	case 0x45:	/* bal	*/
     64	case 0x4d:	/* bas	*/
     65		fixup = FIXUP_RETURN_REGISTER;
     66		break;
     67	case 0x47:	/* bc	*/
     68	case 0x46:	/* bct	*/
     69	case 0x86:	/* bxh	*/
     70	case 0x87:	/* bxle	*/
     71		fixup = FIXUP_BRANCH_NOT_TAKEN;
     72		break;
     73	case 0x82:	/* lpsw	*/
     74		fixup = FIXUP_NOT_REQUIRED;
     75		break;
     76	case 0xb2:	/* lpswe */
     77		if ((insn[0] & 0xff) == 0xb2)
     78			fixup = FIXUP_NOT_REQUIRED;
     79		break;
     80	case 0xa7:	/* bras	*/
     81		if ((insn[0] & 0x0f) == 0x05)
     82			fixup |= FIXUP_RETURN_REGISTER;
     83		break;
     84	case 0xc0:
     85		if ((insn[0] & 0x0f) == 0x05)	/* brasl */
     86			fixup |= FIXUP_RETURN_REGISTER;
     87		break;
     88	case 0xeb:
     89		switch (insn[2] & 0xff) {
     90		case 0x44: /* bxhg  */
     91		case 0x45: /* bxleg */
     92			fixup = FIXUP_BRANCH_NOT_TAKEN;
     93			break;
     94		}
     95		break;
     96	case 0xe3:	/* bctg	*/
     97		if ((insn[2] & 0xff) == 0x46)
     98			fixup = FIXUP_BRANCH_NOT_TAKEN;
     99		break;
    100	case 0xec:
    101		switch (insn[2] & 0xff) {
    102		case 0xe5: /* clgrb */
    103		case 0xe6: /* cgrb  */
    104		case 0xf6: /* crb   */
    105		case 0xf7: /* clrb  */
    106		case 0xfc: /* cgib  */
    107		case 0xfd: /* cglib */
    108		case 0xfe: /* cib   */
    109		case 0xff: /* clib  */
    110			fixup = FIXUP_BRANCH_NOT_TAKEN;
    111			break;
    112		}
    113		break;
    114	}
    115	return fixup;
    116}
    117
    118int probe_is_insn_relative_long(u16 *insn)
    119{
    120	/* Check if we have a RIL-b or RIL-c format instruction which
    121	 * we need to modify in order to avoid instruction emulation. */
    122	switch (insn[0] >> 8) {
    123	case 0xc0:
    124		if ((insn[0] & 0x0f) == 0x00) /* larl */
    125			return true;
    126		break;
    127	case 0xc4:
    128		switch (insn[0] & 0x0f) {
    129		case 0x02: /* llhrl  */
    130		case 0x04: /* lghrl  */
    131		case 0x05: /* lhrl   */
    132		case 0x06: /* llghrl */
    133		case 0x07: /* sthrl  */
    134		case 0x08: /* lgrl   */
    135		case 0x0b: /* stgrl  */
    136		case 0x0c: /* lgfrl  */
    137		case 0x0d: /* lrl    */
    138		case 0x0e: /* llgfrl */
    139		case 0x0f: /* strl   */
    140			return true;
    141		}
    142		break;
    143	case 0xc6:
    144		switch (insn[0] & 0x0f) {
    145		case 0x02: /* pfdrl  */
    146		case 0x04: /* cghrl  */
    147		case 0x05: /* chrl   */
    148		case 0x06: /* clghrl */
    149		case 0x07: /* clhrl  */
    150		case 0x08: /* cgrl   */
    151		case 0x0a: /* clgrl  */
    152		case 0x0c: /* cgfrl  */
    153		case 0x0d: /* crl    */
    154		case 0x0e: /* clgfrl */
    155		case 0x0f: /* clrl   */
    156			return true;
    157		}
    158		break;
    159	}
    160	return false;
    161}