1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 22a0a5b22SJan Willeke /* 32a0a5b22SJan Willeke * User-space Probes (UProbes) for s390 42a0a5b22SJan Willeke * 52a0a5b22SJan Willeke * Copyright IBM Corp. 2014 62a0a5b22SJan Willeke * Author(s): Jan Willeke, 72a0a5b22SJan Willeke */ 82a0a5b22SJan Willeke 92a0a5b22SJan Willeke #include <linux/uaccess.h> 102a0a5b22SJan Willeke #include <linux/uprobes.h> 112a0a5b22SJan Willeke #include <linux/compat.h> 122a0a5b22SJan Willeke #include <linux/kdebug.h> 1368db0cf1SIngo Molnar #include <linux/sched/task_stack.h> 1468db0cf1SIngo Molnar 152a0a5b22SJan Willeke #include <asm/switch_to.h> 162a0a5b22SJan Willeke #include <asm/facility.h> 17d6fe5be3SJan Willeke #include <asm/kprobes.h> 182a0a5b22SJan Willeke #include <asm/dis.h> 192a0a5b22SJan Willeke #include "entry.h" 202a0a5b22SJan Willeke 212a0a5b22SJan Willeke #define UPROBE_TRAP_NR UINT_MAX 222a0a5b22SJan Willeke 232a0a5b22SJan Willeke int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, 242a0a5b22SJan Willeke unsigned long addr) 252a0a5b22SJan Willeke { 262a0a5b22SJan Willeke return probe_is_prohibited_opcode(auprobe->insn); 272a0a5b22SJan Willeke } 282a0a5b22SJan Willeke 292a0a5b22SJan Willeke int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) 302a0a5b22SJan Willeke { 318bb3fdd6SHeiko Carstens if (psw_bits(regs->psw).eaba == PSW_BITS_AMODE_24BIT) 322a0a5b22SJan Willeke return -EINVAL; 338bb3fdd6SHeiko Carstens if (!is_compat_task() && psw_bits(regs->psw).eaba == PSW_BITS_AMODE_31BIT) 342a0a5b22SJan Willeke return -EINVAL; 352a0a5b22SJan Willeke clear_pt_regs_flag(regs, PIF_PER_TRAP); 36a7525982SHeiko Carstens auprobe->saved_per = psw_bits(regs->psw).per; 372a0a5b22SJan Willeke auprobe->saved_int_code = regs->int_code; 382a0a5b22SJan Willeke regs->int_code = UPROBE_TRAP_NR; 392a0a5b22SJan Willeke regs->psw.addr = current->utask->xol_vaddr; 402a0a5b22SJan Willeke set_tsk_thread_flag(current, TIF_UPROBE_SINGLESTEP); 412a0a5b22SJan Willeke update_cr_regs(current); 422a0a5b22SJan Willeke return 0; 432a0a5b22SJan Willeke } 442a0a5b22SJan Willeke 452a0a5b22SJan Willeke bool arch_uprobe_xol_was_trapped(struct task_struct *tsk) 462a0a5b22SJan Willeke { 472a0a5b22SJan Willeke struct pt_regs *regs = task_pt_regs(tsk); 482a0a5b22SJan Willeke 492a0a5b22SJan Willeke if (regs->int_code != UPROBE_TRAP_NR) 502a0a5b22SJan Willeke return true; 512a0a5b22SJan Willeke return false; 522a0a5b22SJan Willeke } 532a0a5b22SJan Willeke 548d1a2427SJan Willeke static int check_per_event(unsigned short cause, unsigned long control, 558d1a2427SJan Willeke struct pt_regs *regs) 568d1a2427SJan Willeke { 578d1a2427SJan Willeke if (!(regs->psw.mask & PSW_MASK_PER)) 588d1a2427SJan Willeke return 0; 598d1a2427SJan Willeke /* user space single step */ 608d1a2427SJan Willeke if (control == 0) 618d1a2427SJan Willeke return 1; 628d1a2427SJan Willeke /* over indication for storage alteration */ 638d1a2427SJan Willeke if ((control & 0x20200000) && (cause & 0x2000)) 648d1a2427SJan Willeke return 1; 658d1a2427SJan Willeke if (cause & 0x8000) { 668d1a2427SJan Willeke /* all branches */ 678d1a2427SJan Willeke if ((control & 0x80800000) == 0x80000000) 688d1a2427SJan Willeke return 1; 698d1a2427SJan Willeke /* branch into selected range */ 708d1a2427SJan Willeke if (((control & 0x80800000) == 0x80800000) && 718d1a2427SJan Willeke regs->psw.addr >= current->thread.per_user.start && 728d1a2427SJan Willeke regs->psw.addr <= current->thread.per_user.end) 738d1a2427SJan Willeke return 1; 748d1a2427SJan Willeke } 758d1a2427SJan Willeke return 0; 768d1a2427SJan Willeke } 778d1a2427SJan Willeke 782a0a5b22SJan Willeke int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) 792a0a5b22SJan Willeke { 802a0a5b22SJan Willeke int fixup = probe_get_fixup_type(auprobe->insn); 812a0a5b22SJan Willeke struct uprobe_task *utask = current->utask; 822a0a5b22SJan Willeke 832a0a5b22SJan Willeke clear_tsk_thread_flag(current, TIF_UPROBE_SINGLESTEP); 842a0a5b22SJan Willeke update_cr_regs(current); 85a7525982SHeiko Carstens psw_bits(regs->psw).per = auprobe->saved_per; 862a0a5b22SJan Willeke regs->int_code = auprobe->saved_int_code; 872a0a5b22SJan Willeke 882a0a5b22SJan Willeke if (fixup & FIXUP_PSW_NORMAL) 892a0a5b22SJan Willeke regs->psw.addr += utask->vaddr - utask->xol_vaddr; 902a0a5b22SJan Willeke if (fixup & FIXUP_RETURN_REGISTER) { 912a0a5b22SJan Willeke int reg = (auprobe->insn[0] & 0xf0) >> 4; 922a0a5b22SJan Willeke 932a0a5b22SJan Willeke regs->gprs[reg] += utask->vaddr - utask->xol_vaddr; 942a0a5b22SJan Willeke } 952a0a5b22SJan Willeke if (fixup & FIXUP_BRANCH_NOT_TAKEN) { 962a0a5b22SJan Willeke int ilen = insn_length(auprobe->insn[0] >> 8); 972a0a5b22SJan Willeke 982a0a5b22SJan Willeke if (regs->psw.addr - utask->xol_vaddr == ilen) 992a0a5b22SJan Willeke regs->psw.addr = utask->vaddr + ilen; 1002a0a5b22SJan Willeke } 1018d1a2427SJan Willeke if (check_per_event(current->thread.per_event.cause, 1028d1a2427SJan Willeke current->thread.per_user.control, regs)) { 1038d1a2427SJan Willeke /* fix per address */ 1048d1a2427SJan Willeke current->thread.per_event.address = utask->vaddr; 1058d1a2427SJan Willeke /* trigger per event */ 1068d1a2427SJan Willeke set_pt_regs_flag(regs, PIF_PER_TRAP); 1078d1a2427SJan Willeke } 1082a0a5b22SJan Willeke return 0; 1092a0a5b22SJan Willeke } 1102a0a5b22SJan Willeke 1112a0a5b22SJan Willeke int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, 1122a0a5b22SJan Willeke void *data) 1132a0a5b22SJan Willeke { 1142a0a5b22SJan Willeke struct die_args *args = data; 1152a0a5b22SJan Willeke struct pt_regs *regs = args->regs; 1162a0a5b22SJan Willeke 1172a0a5b22SJan Willeke if (!user_mode(regs)) 1182a0a5b22SJan Willeke return NOTIFY_DONE; 1192a0a5b22SJan Willeke if (regs->int_code & 0x200) /* Trap during transaction */ 1202a0a5b22SJan Willeke return NOTIFY_DONE; 1212a0a5b22SJan Willeke switch (val) { 1222a0a5b22SJan Willeke case DIE_BPT: 1232a0a5b22SJan Willeke if (uprobe_pre_sstep_notifier(regs)) 1242a0a5b22SJan Willeke return NOTIFY_STOP; 1252a0a5b22SJan Willeke break; 1262a0a5b22SJan Willeke case DIE_SSTEP: 1272a0a5b22SJan Willeke if (uprobe_post_sstep_notifier(regs)) 1282a0a5b22SJan Willeke return NOTIFY_STOP; 1292a0a5b22SJan Willeke default: 1302a0a5b22SJan Willeke break; 1312a0a5b22SJan Willeke } 1322a0a5b22SJan Willeke return NOTIFY_DONE; 1332a0a5b22SJan Willeke } 1342a0a5b22SJan Willeke 1352a0a5b22SJan Willeke void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) 1362a0a5b22SJan Willeke { 1372a0a5b22SJan Willeke clear_thread_flag(TIF_UPROBE_SINGLESTEP); 1382a0a5b22SJan Willeke regs->int_code = auprobe->saved_int_code; 1392a0a5b22SJan Willeke regs->psw.addr = current->utask->vaddr; 1408d1a2427SJan Willeke current->thread.per_event.address = current->utask->vaddr; 1412a0a5b22SJan Willeke } 1422a0a5b22SJan Willeke 1432a0a5b22SJan Willeke unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline, 1442a0a5b22SJan Willeke struct pt_regs *regs) 1452a0a5b22SJan Willeke { 1462a0a5b22SJan Willeke unsigned long orig; 1472a0a5b22SJan Willeke 1482a0a5b22SJan Willeke orig = regs->gprs[14]; 1492a0a5b22SJan Willeke regs->gprs[14] = trampoline; 1502a0a5b22SJan Willeke return orig; 1512a0a5b22SJan Willeke } 1522a0a5b22SJan Willeke 153783c3b53SHeiko Carstens bool arch_uretprobe_is_alive(struct return_instance *ret, enum rp_check ctx, 154783c3b53SHeiko Carstens struct pt_regs *regs) 155783c3b53SHeiko Carstens { 156783c3b53SHeiko Carstens if (ctx == RP_CHECK_CHAIN_CALL) 157783c3b53SHeiko Carstens return user_stack_pointer(regs) <= ret->stack; 158783c3b53SHeiko Carstens else 159783c3b53SHeiko Carstens return user_stack_pointer(regs) < ret->stack; 160783c3b53SHeiko Carstens } 161783c3b53SHeiko Carstens 1622a0a5b22SJan Willeke /* Instruction Emulation */ 1632a0a5b22SJan Willeke 1642a0a5b22SJan Willeke static void adjust_psw_addr(psw_t *psw, unsigned long len) 1652a0a5b22SJan Willeke { 1662a0a5b22SJan Willeke psw->addr = __rewind_psw(*psw, -len); 1672a0a5b22SJan Willeke } 1682a0a5b22SJan Willeke 1692a0a5b22SJan Willeke #define EMU_ILLEGAL_OP 1 1702a0a5b22SJan Willeke #define EMU_SPECIFICATION 2 1712a0a5b22SJan Willeke #define EMU_ADDRESSING 3 1722a0a5b22SJan Willeke 1732a0a5b22SJan Willeke #define emu_load_ril(ptr, output) \ 1742a0a5b22SJan Willeke ({ \ 1752a0a5b22SJan Willeke unsigned int mask = sizeof(*(ptr)) - 1; \ 1762a0a5b22SJan Willeke __typeof__(*(ptr)) input; \ 1772a0a5b22SJan Willeke int __rc = 0; \ 1782a0a5b22SJan Willeke \ 1792a0a5b22SJan Willeke if (!test_facility(34)) \ 1802a0a5b22SJan Willeke __rc = EMU_ILLEGAL_OP; \ 1812a0a5b22SJan Willeke else if ((u64 __force)ptr & mask) \ 1822a0a5b22SJan Willeke __rc = EMU_SPECIFICATION; \ 1832a0a5b22SJan Willeke else if (get_user(input, ptr)) \ 1842a0a5b22SJan Willeke __rc = EMU_ADDRESSING; \ 1852a0a5b22SJan Willeke else \ 1862a0a5b22SJan Willeke *(output) = input; \ 1872a0a5b22SJan Willeke __rc; \ 1882a0a5b22SJan Willeke }) 1892a0a5b22SJan Willeke 1908d1a2427SJan Willeke #define emu_store_ril(regs, ptr, input) \ 1912a0a5b22SJan Willeke ({ \ 1922a0a5b22SJan Willeke unsigned int mask = sizeof(*(ptr)) - 1; \ 1938d1a2427SJan Willeke __typeof__(ptr) __ptr = (ptr); \ 1942a0a5b22SJan Willeke int __rc = 0; \ 1952a0a5b22SJan Willeke \ 1962a0a5b22SJan Willeke if (!test_facility(34)) \ 1972a0a5b22SJan Willeke __rc = EMU_ILLEGAL_OP; \ 1988d1a2427SJan Willeke else if ((u64 __force)__ptr & mask) \ 1992a0a5b22SJan Willeke __rc = EMU_SPECIFICATION; \ 2008d1a2427SJan Willeke else if (put_user(*(input), __ptr)) \ 2012a0a5b22SJan Willeke __rc = EMU_ADDRESSING; \ 2028d1a2427SJan Willeke if (__rc == 0) \ 2039f9d86e1SHeiko Carstens sim_stor_event(regs, \ 2049f9d86e1SHeiko Carstens (void __force *)__ptr, \ 2059f9d86e1SHeiko Carstens mask + 1); \ 2062a0a5b22SJan Willeke __rc; \ 2072a0a5b22SJan Willeke }) 2082a0a5b22SJan Willeke 2092a0a5b22SJan Willeke #define emu_cmp_ril(regs, ptr, cmp) \ 2102a0a5b22SJan Willeke ({ \ 2112a0a5b22SJan Willeke unsigned int mask = sizeof(*(ptr)) - 1; \ 2122a0a5b22SJan Willeke __typeof__(*(ptr)) input; \ 2132a0a5b22SJan Willeke int __rc = 0; \ 2142a0a5b22SJan Willeke \ 2152a0a5b22SJan Willeke if (!test_facility(34)) \ 2162a0a5b22SJan Willeke __rc = EMU_ILLEGAL_OP; \ 2172a0a5b22SJan Willeke else if ((u64 __force)ptr & mask) \ 2182a0a5b22SJan Willeke __rc = EMU_SPECIFICATION; \ 2192a0a5b22SJan Willeke else if (get_user(input, ptr)) \ 2202a0a5b22SJan Willeke __rc = EMU_ADDRESSING; \ 2212a0a5b22SJan Willeke else if (input > *(cmp)) \ 2222a0a5b22SJan Willeke psw_bits((regs)->psw).cc = 1; \ 2232a0a5b22SJan Willeke else if (input < *(cmp)) \ 2242a0a5b22SJan Willeke psw_bits((regs)->psw).cc = 2; \ 2252a0a5b22SJan Willeke else \ 2262a0a5b22SJan Willeke psw_bits((regs)->psw).cc = 0; \ 2272a0a5b22SJan Willeke __rc; \ 2282a0a5b22SJan Willeke }) 2292a0a5b22SJan Willeke 2302a0a5b22SJan Willeke struct insn_ril { 2312a0a5b22SJan Willeke u8 opc0; 2322a0a5b22SJan Willeke u8 reg : 4; 2332a0a5b22SJan Willeke u8 opc1 : 4; 2342a0a5b22SJan Willeke s32 disp; 2352a0a5b22SJan Willeke } __packed; 2362a0a5b22SJan Willeke 2372a0a5b22SJan Willeke union split_register { 2382a0a5b22SJan Willeke u64 u64; 2392a0a5b22SJan Willeke u32 u32[2]; 2402a0a5b22SJan Willeke u16 u16[4]; 2412a0a5b22SJan Willeke s64 s64; 2422a0a5b22SJan Willeke s32 s32[2]; 2432a0a5b22SJan Willeke s16 s16[4]; 2442a0a5b22SJan Willeke }; 2452a0a5b22SJan Willeke 2462a0a5b22SJan Willeke /* 2478d1a2427SJan Willeke * If user per registers are setup to trace storage alterations and an 2488d1a2427SJan Willeke * emulated store took place on a fitting address a user trap is generated. 2498d1a2427SJan Willeke */ 2508d1a2427SJan Willeke static void sim_stor_event(struct pt_regs *regs, void *addr, int len) 2518d1a2427SJan Willeke { 2528d1a2427SJan Willeke if (!(regs->psw.mask & PSW_MASK_PER)) 2538d1a2427SJan Willeke return; 2548d1a2427SJan Willeke if (!(current->thread.per_user.control & PER_EVENT_STORE)) 2558d1a2427SJan Willeke return; 2568d1a2427SJan Willeke if ((void *)current->thread.per_user.start > (addr + len)) 2578d1a2427SJan Willeke return; 2588d1a2427SJan Willeke if ((void *)current->thread.per_user.end < addr) 2598d1a2427SJan Willeke return; 2608d1a2427SJan Willeke current->thread.per_event.address = regs->psw.addr; 2618d1a2427SJan Willeke current->thread.per_event.cause = PER_EVENT_STORE >> 16; 2628d1a2427SJan Willeke set_pt_regs_flag(regs, PIF_PER_TRAP); 2638d1a2427SJan Willeke } 2648d1a2427SJan Willeke 2658d1a2427SJan Willeke /* 2662a0a5b22SJan Willeke * pc relative instructions are emulated, since parameters may not be 2672a0a5b22SJan Willeke * accessible from the xol area due to range limitations. 2682a0a5b22SJan Willeke */ 2692a0a5b22SJan Willeke static void handle_insn_ril(struct arch_uprobe *auprobe, struct pt_regs *regs) 2702a0a5b22SJan Willeke { 2712a0a5b22SJan Willeke union split_register *rx; 2722a0a5b22SJan Willeke struct insn_ril *insn; 2732a0a5b22SJan Willeke unsigned int ilen; 2742a0a5b22SJan Willeke void *uptr; 2752a0a5b22SJan Willeke int rc = 0; 2762a0a5b22SJan Willeke 2772a0a5b22SJan Willeke insn = (struct insn_ril *) &auprobe->insn; 2782a0a5b22SJan Willeke rx = (union split_register *) ®s->gprs[insn->reg]; 2792a0a5b22SJan Willeke uptr = (void *)(regs->psw.addr + (insn->disp * 2)); 2802a0a5b22SJan Willeke ilen = insn_length(insn->opc0); 2812a0a5b22SJan Willeke 2822a0a5b22SJan Willeke switch (insn->opc0) { 2832a0a5b22SJan Willeke case 0xc0: 2842a0a5b22SJan Willeke switch (insn->opc1) { 2852a0a5b22SJan Willeke case 0x00: /* larl */ 2862a0a5b22SJan Willeke rx->u64 = (unsigned long)uptr; 2872a0a5b22SJan Willeke break; 2882a0a5b22SJan Willeke } 2892a0a5b22SJan Willeke break; 2902a0a5b22SJan Willeke case 0xc4: 2912a0a5b22SJan Willeke switch (insn->opc1) { 2922a0a5b22SJan Willeke case 0x02: /* llhrl */ 2932a0a5b22SJan Willeke rc = emu_load_ril((u16 __user *)uptr, &rx->u32[1]); 2942a0a5b22SJan Willeke break; 2952a0a5b22SJan Willeke case 0x04: /* lghrl */ 2962a0a5b22SJan Willeke rc = emu_load_ril((s16 __user *)uptr, &rx->u64); 2972a0a5b22SJan Willeke break; 2982a0a5b22SJan Willeke case 0x05: /* lhrl */ 2992a0a5b22SJan Willeke rc = emu_load_ril((s16 __user *)uptr, &rx->u32[1]); 3002a0a5b22SJan Willeke break; 3012a0a5b22SJan Willeke case 0x06: /* llghrl */ 3022a0a5b22SJan Willeke rc = emu_load_ril((u16 __user *)uptr, &rx->u64); 3032a0a5b22SJan Willeke break; 3042a0a5b22SJan Willeke case 0x08: /* lgrl */ 3052a0a5b22SJan Willeke rc = emu_load_ril((u64 __user *)uptr, &rx->u64); 3062a0a5b22SJan Willeke break; 3072a0a5b22SJan Willeke case 0x0c: /* lgfrl */ 3082a0a5b22SJan Willeke rc = emu_load_ril((s32 __user *)uptr, &rx->u64); 3092a0a5b22SJan Willeke break; 3102a0a5b22SJan Willeke case 0x0d: /* lrl */ 3112a0a5b22SJan Willeke rc = emu_load_ril((u32 __user *)uptr, &rx->u32[1]); 3122a0a5b22SJan Willeke break; 3132a0a5b22SJan Willeke case 0x0e: /* llgfrl */ 3142a0a5b22SJan Willeke rc = emu_load_ril((u32 __user *)uptr, &rx->u64); 3152a0a5b22SJan Willeke break; 3162a0a5b22SJan Willeke case 0x07: /* sthrl */ 3178d1a2427SJan Willeke rc = emu_store_ril(regs, (u16 __user *)uptr, &rx->u16[3]); 3182a0a5b22SJan Willeke break; 3192a0a5b22SJan Willeke case 0x0b: /* stgrl */ 3208d1a2427SJan Willeke rc = emu_store_ril(regs, (u64 __user *)uptr, &rx->u64); 3212a0a5b22SJan Willeke break; 3222a0a5b22SJan Willeke case 0x0f: /* strl */ 3238d1a2427SJan Willeke rc = emu_store_ril(regs, (u32 __user *)uptr, &rx->u32[1]); 3242a0a5b22SJan Willeke break; 3252a0a5b22SJan Willeke } 3262a0a5b22SJan Willeke break; 3272a0a5b22SJan Willeke case 0xc6: 3282a0a5b22SJan Willeke switch (insn->opc1) { 3292a0a5b22SJan Willeke case 0x02: /* pfdrl */ 3302a0a5b22SJan Willeke if (!test_facility(34)) 3312a0a5b22SJan Willeke rc = EMU_ILLEGAL_OP; 3322a0a5b22SJan Willeke break; 3332a0a5b22SJan Willeke case 0x04: /* cghrl */ 3342a0a5b22SJan Willeke rc = emu_cmp_ril(regs, (s16 __user *)uptr, &rx->s64); 3352a0a5b22SJan Willeke break; 3362a0a5b22SJan Willeke case 0x05: /* chrl */ 3372a0a5b22SJan Willeke rc = emu_cmp_ril(regs, (s16 __user *)uptr, &rx->s32[1]); 3382a0a5b22SJan Willeke break; 3392a0a5b22SJan Willeke case 0x06: /* clghrl */ 3402a0a5b22SJan Willeke rc = emu_cmp_ril(regs, (u16 __user *)uptr, &rx->u64); 3412a0a5b22SJan Willeke break; 3422a0a5b22SJan Willeke case 0x07: /* clhrl */ 3432a0a5b22SJan Willeke rc = emu_cmp_ril(regs, (u16 __user *)uptr, &rx->u32[1]); 3442a0a5b22SJan Willeke break; 3452a0a5b22SJan Willeke case 0x08: /* cgrl */ 3462a0a5b22SJan Willeke rc = emu_cmp_ril(regs, (s64 __user *)uptr, &rx->s64); 3472a0a5b22SJan Willeke break; 3482a0a5b22SJan Willeke case 0x0a: /* clgrl */ 3492a0a5b22SJan Willeke rc = emu_cmp_ril(regs, (u64 __user *)uptr, &rx->u64); 3502a0a5b22SJan Willeke break; 3512a0a5b22SJan Willeke case 0x0c: /* cgfrl */ 3522a0a5b22SJan Willeke rc = emu_cmp_ril(regs, (s32 __user *)uptr, &rx->s64); 3532a0a5b22SJan Willeke break; 3542a0a5b22SJan Willeke case 0x0d: /* crl */ 3552a0a5b22SJan Willeke rc = emu_cmp_ril(regs, (s32 __user *)uptr, &rx->s32[1]); 3562a0a5b22SJan Willeke break; 3572a0a5b22SJan Willeke case 0x0e: /* clgfrl */ 3582a0a5b22SJan Willeke rc = emu_cmp_ril(regs, (u32 __user *)uptr, &rx->u64); 3592a0a5b22SJan Willeke break; 3602a0a5b22SJan Willeke case 0x0f: /* clrl */ 3612a0a5b22SJan Willeke rc = emu_cmp_ril(regs, (u32 __user *)uptr, &rx->u32[1]); 3622a0a5b22SJan Willeke break; 3632a0a5b22SJan Willeke } 3642a0a5b22SJan Willeke break; 3652a0a5b22SJan Willeke } 3662a0a5b22SJan Willeke adjust_psw_addr(®s->psw, ilen); 3672a0a5b22SJan Willeke switch (rc) { 3682a0a5b22SJan Willeke case EMU_ILLEGAL_OP: 3692a0a5b22SJan Willeke regs->int_code = ilen << 16 | 0x0001; 3702a0a5b22SJan Willeke do_report_trap(regs, SIGILL, ILL_ILLOPC, NULL); 3712a0a5b22SJan Willeke break; 3722a0a5b22SJan Willeke case EMU_SPECIFICATION: 3732a0a5b22SJan Willeke regs->int_code = ilen << 16 | 0x0006; 3742a0a5b22SJan Willeke do_report_trap(regs, SIGILL, ILL_ILLOPC , NULL); 3752a0a5b22SJan Willeke break; 3762a0a5b22SJan Willeke case EMU_ADDRESSING: 3772a0a5b22SJan Willeke regs->int_code = ilen << 16 | 0x0005; 3782a0a5b22SJan Willeke do_report_trap(regs, SIGSEGV, SEGV_MAPERR, NULL); 3792a0a5b22SJan Willeke break; 3802a0a5b22SJan Willeke } 3812a0a5b22SJan Willeke } 3822a0a5b22SJan Willeke 3832a0a5b22SJan Willeke bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) 3842a0a5b22SJan Willeke { 3858bb3fdd6SHeiko Carstens if ((psw_bits(regs->psw).eaba == PSW_BITS_AMODE_24BIT) || 3868bb3fdd6SHeiko Carstens ((psw_bits(regs->psw).eaba == PSW_BITS_AMODE_31BIT) && 3872a0a5b22SJan Willeke !is_compat_task())) { 3882a0a5b22SJan Willeke regs->psw.addr = __rewind_psw(regs->psw, UPROBE_SWBP_INSN_SIZE); 3892a0a5b22SJan Willeke do_report_trap(regs, SIGILL, ILL_ILLADR, NULL); 3902a0a5b22SJan Willeke return true; 3912a0a5b22SJan Willeke } 3922a0a5b22SJan Willeke if (probe_is_insn_relative_long(auprobe->insn)) { 3932a0a5b22SJan Willeke handle_insn_ril(auprobe, regs); 3942a0a5b22SJan Willeke return true; 3952a0a5b22SJan Willeke } 3962a0a5b22SJan Willeke return false; 3972a0a5b22SJan Willeke } 398