18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Common helper functions for kprobes and uprobes 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright IBM Corp. 2014 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/errno.h> 98c2ecf20Sopenharmony_ci#include <asm/kprobes.h> 108c2ecf20Sopenharmony_ci#include <asm/dis.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ciint probe_is_prohibited_opcode(u16 *insn) 138c2ecf20Sopenharmony_ci{ 148c2ecf20Sopenharmony_ci if (!is_known_insn((unsigned char *)insn)) 158c2ecf20Sopenharmony_ci return -EINVAL; 168c2ecf20Sopenharmony_ci switch (insn[0] >> 8) { 178c2ecf20Sopenharmony_ci case 0x0c: /* bassm */ 188c2ecf20Sopenharmony_ci case 0x0b: /* bsm */ 198c2ecf20Sopenharmony_ci case 0x83: /* diag */ 208c2ecf20Sopenharmony_ci case 0x44: /* ex */ 218c2ecf20Sopenharmony_ci case 0xac: /* stnsm */ 228c2ecf20Sopenharmony_ci case 0xad: /* stosm */ 238c2ecf20Sopenharmony_ci return -EINVAL; 248c2ecf20Sopenharmony_ci case 0xc6: 258c2ecf20Sopenharmony_ci switch (insn[0] & 0x0f) { 268c2ecf20Sopenharmony_ci case 0x00: /* exrl */ 278c2ecf20Sopenharmony_ci return -EINVAL; 288c2ecf20Sopenharmony_ci } 298c2ecf20Sopenharmony_ci } 308c2ecf20Sopenharmony_ci switch (insn[0]) { 318c2ecf20Sopenharmony_ci case 0x0101: /* pr */ 328c2ecf20Sopenharmony_ci case 0xb25a: /* bsa */ 338c2ecf20Sopenharmony_ci case 0xb240: /* bakr */ 348c2ecf20Sopenharmony_ci case 0xb258: /* bsg */ 358c2ecf20Sopenharmony_ci case 0xb218: /* pc */ 368c2ecf20Sopenharmony_ci case 0xb228: /* pt */ 378c2ecf20Sopenharmony_ci case 0xb98d: /* epsw */ 388c2ecf20Sopenharmony_ci case 0xe560: /* tbegin */ 398c2ecf20Sopenharmony_ci case 0xe561: /* tbeginc */ 408c2ecf20Sopenharmony_ci case 0xb2f8: /* tend */ 418c2ecf20Sopenharmony_ci return -EINVAL; 428c2ecf20Sopenharmony_ci } 438c2ecf20Sopenharmony_ci return 0; 448c2ecf20Sopenharmony_ci} 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ciint probe_get_fixup_type(u16 *insn) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci /* default fixup method */ 498c2ecf20Sopenharmony_ci int fixup = FIXUP_PSW_NORMAL; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci switch (insn[0] >> 8) { 528c2ecf20Sopenharmony_ci case 0x05: /* balr */ 538c2ecf20Sopenharmony_ci case 0x0d: /* basr */ 548c2ecf20Sopenharmony_ci fixup = FIXUP_RETURN_REGISTER; 558c2ecf20Sopenharmony_ci /* if r2 = 0, no branch will be taken */ 568c2ecf20Sopenharmony_ci if ((insn[0] & 0x0f) == 0) 578c2ecf20Sopenharmony_ci fixup |= FIXUP_BRANCH_NOT_TAKEN; 588c2ecf20Sopenharmony_ci break; 598c2ecf20Sopenharmony_ci case 0x06: /* bctr */ 608c2ecf20Sopenharmony_ci case 0x07: /* bcr */ 618c2ecf20Sopenharmony_ci fixup = FIXUP_BRANCH_NOT_TAKEN; 628c2ecf20Sopenharmony_ci break; 638c2ecf20Sopenharmony_ci case 0x45: /* bal */ 648c2ecf20Sopenharmony_ci case 0x4d: /* bas */ 658c2ecf20Sopenharmony_ci fixup = FIXUP_RETURN_REGISTER; 668c2ecf20Sopenharmony_ci break; 678c2ecf20Sopenharmony_ci case 0x47: /* bc */ 688c2ecf20Sopenharmony_ci case 0x46: /* bct */ 698c2ecf20Sopenharmony_ci case 0x86: /* bxh */ 708c2ecf20Sopenharmony_ci case 0x87: /* bxle */ 718c2ecf20Sopenharmony_ci fixup = FIXUP_BRANCH_NOT_TAKEN; 728c2ecf20Sopenharmony_ci break; 738c2ecf20Sopenharmony_ci case 0x82: /* lpsw */ 748c2ecf20Sopenharmony_ci fixup = FIXUP_NOT_REQUIRED; 758c2ecf20Sopenharmony_ci break; 768c2ecf20Sopenharmony_ci case 0xb2: /* lpswe */ 778c2ecf20Sopenharmony_ci if ((insn[0] & 0xff) == 0xb2) 788c2ecf20Sopenharmony_ci fixup = FIXUP_NOT_REQUIRED; 798c2ecf20Sopenharmony_ci break; 808c2ecf20Sopenharmony_ci case 0xa7: /* bras */ 818c2ecf20Sopenharmony_ci if ((insn[0] & 0x0f) == 0x05) 828c2ecf20Sopenharmony_ci fixup |= FIXUP_RETURN_REGISTER; 838c2ecf20Sopenharmony_ci break; 848c2ecf20Sopenharmony_ci case 0xc0: 858c2ecf20Sopenharmony_ci if ((insn[0] & 0x0f) == 0x05) /* brasl */ 868c2ecf20Sopenharmony_ci fixup |= FIXUP_RETURN_REGISTER; 878c2ecf20Sopenharmony_ci break; 888c2ecf20Sopenharmony_ci case 0xeb: 898c2ecf20Sopenharmony_ci switch (insn[2] & 0xff) { 908c2ecf20Sopenharmony_ci case 0x44: /* bxhg */ 918c2ecf20Sopenharmony_ci case 0x45: /* bxleg */ 928c2ecf20Sopenharmony_ci fixup = FIXUP_BRANCH_NOT_TAKEN; 938c2ecf20Sopenharmony_ci break; 948c2ecf20Sopenharmony_ci } 958c2ecf20Sopenharmony_ci break; 968c2ecf20Sopenharmony_ci case 0xe3: /* bctg */ 978c2ecf20Sopenharmony_ci if ((insn[2] & 0xff) == 0x46) 988c2ecf20Sopenharmony_ci fixup = FIXUP_BRANCH_NOT_TAKEN; 998c2ecf20Sopenharmony_ci break; 1008c2ecf20Sopenharmony_ci case 0xec: 1018c2ecf20Sopenharmony_ci switch (insn[2] & 0xff) { 1028c2ecf20Sopenharmony_ci case 0xe5: /* clgrb */ 1038c2ecf20Sopenharmony_ci case 0xe6: /* cgrb */ 1048c2ecf20Sopenharmony_ci case 0xf6: /* crb */ 1058c2ecf20Sopenharmony_ci case 0xf7: /* clrb */ 1068c2ecf20Sopenharmony_ci case 0xfc: /* cgib */ 1078c2ecf20Sopenharmony_ci case 0xfd: /* cglib */ 1088c2ecf20Sopenharmony_ci case 0xfe: /* cib */ 1098c2ecf20Sopenharmony_ci case 0xff: /* clib */ 1108c2ecf20Sopenharmony_ci fixup = FIXUP_BRANCH_NOT_TAKEN; 1118c2ecf20Sopenharmony_ci break; 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci break; 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci return fixup; 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ciint probe_is_insn_relative_long(u16 *insn) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci /* Check if we have a RIL-b or RIL-c format instruction which 1218c2ecf20Sopenharmony_ci * we need to modify in order to avoid instruction emulation. */ 1228c2ecf20Sopenharmony_ci switch (insn[0] >> 8) { 1238c2ecf20Sopenharmony_ci case 0xc0: 1248c2ecf20Sopenharmony_ci if ((insn[0] & 0x0f) == 0x00) /* larl */ 1258c2ecf20Sopenharmony_ci return true; 1268c2ecf20Sopenharmony_ci break; 1278c2ecf20Sopenharmony_ci case 0xc4: 1288c2ecf20Sopenharmony_ci switch (insn[0] & 0x0f) { 1298c2ecf20Sopenharmony_ci case 0x02: /* llhrl */ 1308c2ecf20Sopenharmony_ci case 0x04: /* lghrl */ 1318c2ecf20Sopenharmony_ci case 0x05: /* lhrl */ 1328c2ecf20Sopenharmony_ci case 0x06: /* llghrl */ 1338c2ecf20Sopenharmony_ci case 0x07: /* sthrl */ 1348c2ecf20Sopenharmony_ci case 0x08: /* lgrl */ 1358c2ecf20Sopenharmony_ci case 0x0b: /* stgrl */ 1368c2ecf20Sopenharmony_ci case 0x0c: /* lgfrl */ 1378c2ecf20Sopenharmony_ci case 0x0d: /* lrl */ 1388c2ecf20Sopenharmony_ci case 0x0e: /* llgfrl */ 1398c2ecf20Sopenharmony_ci case 0x0f: /* strl */ 1408c2ecf20Sopenharmony_ci return true; 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci break; 1438c2ecf20Sopenharmony_ci case 0xc6: 1448c2ecf20Sopenharmony_ci switch (insn[0] & 0x0f) { 1458c2ecf20Sopenharmony_ci case 0x02: /* pfdrl */ 1468c2ecf20Sopenharmony_ci case 0x04: /* cghrl */ 1478c2ecf20Sopenharmony_ci case 0x05: /* chrl */ 1488c2ecf20Sopenharmony_ci case 0x06: /* clghrl */ 1498c2ecf20Sopenharmony_ci case 0x07: /* clhrl */ 1508c2ecf20Sopenharmony_ci case 0x08: /* cgrl */ 1518c2ecf20Sopenharmony_ci case 0x0a: /* clgrl */ 1528c2ecf20Sopenharmony_ci case 0x0c: /* cgfrl */ 1538c2ecf20Sopenharmony_ci case 0x0d: /* crl */ 1548c2ecf20Sopenharmony_ci case 0x0e: /* clgfrl */ 1558c2ecf20Sopenharmony_ci case 0x0f: /* clrl */ 1568c2ecf20Sopenharmony_ci return true; 1578c2ecf20Sopenharmony_ci } 1588c2ecf20Sopenharmony_ci break; 1598c2ecf20Sopenharmony_ci } 1608c2ecf20Sopenharmony_ci return false; 1618c2ecf20Sopenharmony_ci} 162