1 /* 2 * Jump label s390 support 3 * 4 * Copyright IBM Corp. 2011 5 * Author(s): Jan Glauber <jang@linux.vnet.ibm.com> 6 */ 7 #include <linux/module.h> 8 #include <linux/uaccess.h> 9 #include <linux/stop_machine.h> 10 #include <linux/jump_label.h> 11 #include <asm/ipl.h> 12 13 #ifdef HAVE_JUMP_LABEL 14 15 struct insn { 16 u16 opcode; 17 s32 offset; 18 } __packed; 19 20 struct insn_args { 21 unsigned long *target; 22 struct insn *insn; 23 ssize_t size; 24 }; 25 26 static int __arch_jump_label_transform(void *data) 27 { 28 struct insn_args *args = data; 29 int rc; 30 31 rc = probe_kernel_write(args->target, args->insn, args->size); 32 WARN_ON_ONCE(rc < 0); 33 return 0; 34 } 35 36 void arch_jump_label_transform(struct jump_entry *entry, 37 enum jump_label_type type) 38 { 39 struct insn_args args; 40 struct insn insn; 41 42 if (type == JUMP_LABEL_ENABLE) { 43 /* brcl 15,offset */ 44 insn.opcode = 0xc0f4; 45 insn.offset = (entry->target - entry->code) >> 1; 46 } else { 47 /* brcl 0,0 */ 48 insn.opcode = 0xc004; 49 insn.offset = 0; 50 } 51 52 args.target = (void *) entry->code; 53 args.insn = &insn; 54 args.size = JUMP_LABEL_NOP_SIZE; 55 56 stop_machine(__arch_jump_label_transform, &args, NULL); 57 } 58 59 #endif 60