1d9f5ab7bSJason Baron /* 2d9f5ab7bSJason Baron * jump label x86 support 3d9f5ab7bSJason Baron * 4d9f5ab7bSJason Baron * Copyright (C) 2009 Jason Baron <jbaron@redhat.com> 5d9f5ab7bSJason Baron * 6d9f5ab7bSJason Baron */ 7d9f5ab7bSJason Baron #include <linux/jump_label.h> 8d9f5ab7bSJason Baron #include <linux/memory.h> 9d9f5ab7bSJason Baron #include <linux/uaccess.h> 10d9f5ab7bSJason Baron #include <linux/module.h> 11d9f5ab7bSJason Baron #include <linux/list.h> 12d9f5ab7bSJason Baron #include <linux/jhash.h> 13d9f5ab7bSJason Baron #include <linux/cpu.h> 14d9f5ab7bSJason Baron #include <asm/kprobes.h> 15d9f5ab7bSJason Baron #include <asm/alternative.h> 16d9f5ab7bSJason Baron 17d9f5ab7bSJason Baron #ifdef HAVE_JUMP_LABEL 18d9f5ab7bSJason Baron 19d9f5ab7bSJason Baron union jump_code_union { 20d9f5ab7bSJason Baron char code[JUMP_LABEL_NOP_SIZE]; 21d9f5ab7bSJason Baron struct { 22d9f5ab7bSJason Baron char jump; 23d9f5ab7bSJason Baron int offset; 24d9f5ab7bSJason Baron } __attribute__((packed)); 25d9f5ab7bSJason Baron }; 26d9f5ab7bSJason Baron 27*e71a5be1SJeremy Fitzhardinge static void __jump_label_transform(struct jump_entry *entry, 28*e71a5be1SJeremy Fitzhardinge enum jump_label_type type, 29*e71a5be1SJeremy Fitzhardinge void *(*poker)(void *, const void *, size_t)) 30d9f5ab7bSJason Baron { 31d9f5ab7bSJason Baron union jump_code_union code; 32d9f5ab7bSJason Baron 33d9f5ab7bSJason Baron if (type == JUMP_LABEL_ENABLE) { 34d9f5ab7bSJason Baron code.jump = 0xe9; 35d9f5ab7bSJason Baron code.offset = entry->target - 36d9f5ab7bSJason Baron (entry->code + JUMP_LABEL_NOP_SIZE); 37d9f5ab7bSJason Baron } else 38dc326fcaSH. Peter Anvin memcpy(&code, ideal_nops[NOP_ATOMIC5], JUMP_LABEL_NOP_SIZE); 39*e71a5be1SJeremy Fitzhardinge 40*e71a5be1SJeremy Fitzhardinge (*poker)((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE); 41*e71a5be1SJeremy Fitzhardinge } 42*e71a5be1SJeremy Fitzhardinge 43*e71a5be1SJeremy Fitzhardinge void arch_jump_label_transform(struct jump_entry *entry, 44*e71a5be1SJeremy Fitzhardinge enum jump_label_type type) 45*e71a5be1SJeremy Fitzhardinge { 46d9f5ab7bSJason Baron get_online_cpus(); 47d9f5ab7bSJason Baron mutex_lock(&text_mutex); 48*e71a5be1SJeremy Fitzhardinge __jump_label_transform(entry, type, text_poke_smp); 49d9f5ab7bSJason Baron mutex_unlock(&text_mutex); 50d9f5ab7bSJason Baron put_online_cpus(); 51d9f5ab7bSJason Baron } 52d9f5ab7bSJason Baron 53*e71a5be1SJeremy Fitzhardinge void arch_jump_label_transform_static(struct jump_entry *entry, 54*e71a5be1SJeremy Fitzhardinge enum jump_label_type type) 55*e71a5be1SJeremy Fitzhardinge { 56*e71a5be1SJeremy Fitzhardinge __jump_label_transform(entry, type, text_poke_early); 57*e71a5be1SJeremy Fitzhardinge } 58*e71a5be1SJeremy Fitzhardinge 59d9f5ab7bSJason Baron #endif 60