From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24966 invoked by alias); 17 Dec 2007 21:27:31 -0000 Received: (qmail 24620 invoked by uid 22791); 17 Dec 2007 21:27:29 -0000 X-Spam-Status: No, hits=-2.6 required=5.0 tests=AWL,BAYES_00,DK_POLICY_SIGNSOME,DK_SIGNED,SPF_PASS X-Spam-Check-By: sourceware.org Received: from rv-out-0910.google.com (HELO rv-out-0910.google.com) (209.85.198.191) by sourceware.org (qpsmtpd/0.31) with ESMTP; Mon, 17 Dec 2007 21:26:59 +0000 Received: by rv-out-0910.google.com with SMTP id l15so2076614rvb.50 for ; Mon, 17 Dec 2007 13:26:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:subject:from:to:cc:content-type:date:message-id:mime-version:x-mailer:content-transfer-encoding; bh=3V7bIyL5Taz37p10MEVkUB40IiZvEBav8R1mZLW5os8=; b=fYCW+zFt/uofXg/fqMV1zHB+Z30ZPDolQ18WgIcwV8jxjbny2kdLggurG7NQ0MreuiX2YDFZ2oWJAcxI8QQ+kAkq/V8A8numD0903D39szWNaXWxrJis9K+FcE1TxWxxFTJuTdjIUKLNpysGV3I1DO0saEPB/j+AZZDqxi39cVM= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=subject:from:to:cc:content-type:date:message-id:mime-version:x-mailer:content-transfer-encoding; b=ixdk0k5qOERH1gq3pQbnmHf8eOTHBjdiuHfKkVapA5tYIfCTvQN2e/Bvb38v7DycD5dUrtCJlj67UXi9VZOGVUhMRwMQow8ftsFFWGufDAPPUuubFxZKKu5cwMVGz3+Qpsvh+sgoTQ6lBLi+AdbNlS9oQ32tjW1bk4pygWNVsqY= Received: by 10.140.82.38 with SMTP id f38mr4329524rvb.30.1197926816093; Mon, 17 Dec 2007 13:26:56 -0800 (PST) Received: from ?192.168.1.100? ( [216.19.190.48]) by mx.google.com with ESMTPS id b39sm8065652rvf.2007.12.17.13.26.55 (version=TLSv1/SSLv3 cipher=RC4-MD5); Mon, 17 Dec 2007 13:26:55 -0800 (PST) Subject: [PATCH 3/4] x86: add kprobe-booster to X86_64 From: Harvey Harrison To: Ingo Molnar Cc: Ananth N Mavinakayanahalli , Jim Keniston , Roland McGrath , Arjan van de Ven , prasanna@in.ibm.com, anil.s.keshavamurthy@intel.com, davem@davemloft.net, systemtap-ml , LKML , Andrew Morton Content-Type: text/plain Date: Mon, 17 Dec 2007 21:27:00 -0000 Message-Id: <1197926823.23402.30.camel@brick> Mime-Version: 1.0 X-Mailer: Evolution 2.12.1 Content-Transfer-Encoding: 7bit Mailing-List: contact systemtap-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: systemtap-owner@sourceware.org X-SW-Source: 2007-q4/txt/msg00526.txt.bz2 Based on X86_32, mostly by un-ifdeffing code. Based on patch from Masami Hiramatsu Signed-off-by: Harvey Harrison --- arch/x86/kernel/kprobes.c | 57 +++++++++++++++++++++++---------------------- include/asm-x86/kprobes.h | 12 +++++---- 2 files changed, 36 insertions(+), 33 deletions(-) diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c index 64c702c..47bae2c 100644 --- a/arch/x86/kernel/kprobes.c +++ b/arch/x86/kernel/kprobes.c @@ -151,15 +151,17 @@ twobyte_has_modrm[256 / (sizeof(unsigned long) * 8)] = { #undef R4 #undef RF -/* insert a jmp code */ +/* + * Insert a jump instruction at address 'from' which jumps to address 'to' */ static inline void set_jmp_op(void *from, void *to) { struct __arch_jmp_op { char op; - long raddr; - } __attribute__((packed)) *jop; + s32 raddr; + } __attribute__((packed)) * jop; jop = (struct __arch_jmp_op *)from; - jop->raddr = (long)(to) - ((long)(from) + 5); + + jop->raddr = (s32)((long)(to) - ((long)(from) + 5)); jop->op = RELATIVEJUMP_INSTRUCTION; } @@ -183,6 +185,9 @@ retry: } switch (opcode & 0xf0) { +#ifdef X86_64 + case 0x40: + goto retry; /* REX prefix is boostable */ case 0x60: if (0x63 < opcode && opcode < 0x67) goto retry; /* prefixes */ @@ -202,7 +207,7 @@ retry: case 0xf0: if ((opcode & 0x0c) == 0 && opcode != 0xf1) goto retry; /* lock/rep(ne) prefix */ - /* clear and set flags can be boost */ + /* clear and set flags are boostable */ return (opcode == 0xf5 || (0xf7 < opcode && opcode < 0xfe)); default: if (opcode == 0x26 || opcode == 0x36 || opcode == 0x3e) @@ -221,6 +226,10 @@ static s32 __kprobes *is_riprel(u8 *insn) { int need_modrm; +#ifdef CONFIG_X86_32 + return NULL; +#endif + /* Skip legacy instruction prefixes. */ while (1) { switch (*insn) { @@ -266,18 +275,10 @@ static s32 __kprobes *is_riprel(u8 *insn) static void __kprobes arch_copy_kprobe(struct kprobe *p) { -#ifdef CONFIG_X86_32 - memcpy(p->ainsn.insn, p->addr, - (MAX_INSN_SIZE + 1) * sizeof(kprobe_opcode_t)); - p->opcode = *p->addr; - if (can_boost(p->addr)) { - p->ainsn.boostable = 0; - } else { - p->ainsn.boostable = -1; - } -#else s32 *ripdisp; - memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE); + memcpy(p->ainsn.insn, p->addr, + MAX_INSN_SIZE + sizeof(kprobe_opcode_t)); + ripdisp = is_riprel(p->ainsn.insn); if (ripdisp) { /* @@ -297,8 +298,13 @@ static void __kprobes arch_copy_kprobe(struct kprobe *p) BUG_ON((s64) (s32) disp != disp); /* Sanity check. */ *ripdisp = disp; } + p->opcode = *p->addr; -#endif + if (can_boost(p->addr)) { + p->ainsn.boostable = 0; + } else { + p->ainsn.boostable = -1; + } } /* @@ -343,11 +349,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) void __kprobes arch_remove_kprobe(struct kprobe *p) { mutex_lock(&kprobe_mutex); -#ifdef CONFIG_X86_32 free_insn_slot(p->ainsn.insn, (p->ainsn.boostable == 1)); -#else - free_insn_slot(p->ainsn.insn, 0); -#endif mutex_unlock(&kprobe_mutex); } @@ -544,7 +546,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) return 1; ss_probe: -#if defined(CONFIG_X86_32) && (!defined(CONFIG_PREEMPT) || defined(CONFIG_PM)) +#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PM) if (p->ainsn.boostable == 1 && !p->post_handler){ /* Boost up -- we can execute copied instructions directly */ reset_current_kprobe(); @@ -722,6 +724,11 @@ void *__kprobes trampoline_handler(struct pt_regs *regs) * that is atop the stack is the address following the copied instruction. * We need to make it the address following the original instruction. * + * If this is the first time we've single-stepped the instruction at + * this probepoint, and the instruction is boostable, boost it: add a + * jump instruction after the copied instruction, that jumps to the next + * instruction after the probepoint. + * * This function also checks instruction size for preparing direct execution. */ static void __kprobes resume_execution(struct kprobe *p, @@ -754,10 +761,8 @@ static void __kprobes resume_execution(struct kprobe *p, case 0xcb: case 0xcf: case 0xea: /* jmp absolute -- ip is correct */ -#ifdef CONFIG_X86_32 /* ip is already adjusted, no more changes required */ p->ainsn.boostable = 1; -#endif goto no_change; case 0xe8: /* call relative - Fix return addr */ *tos = orig_ip + (*tos - copy_ip); @@ -777,10 +782,8 @@ static void __kprobes resume_execution(struct kprobe *p, } else if (((insn[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */ ((insn[1] & 0x31) == 0x21)) { /* jmp far, absolute indirect */ /* ip is correct. */ -#ifdef CONFIG_X86_32 /* And this is boostable */ p->ainsn.boostable = 1; -#endif goto no_change; } break; @@ -788,7 +791,6 @@ static void __kprobes resume_execution(struct kprobe *p, break; } -#ifdef CONFIG_X86_32 if (p->ainsn.boostable == 0) { if ((regs->ip > copy_ip) && (regs->ip - copy_ip) + 5 < (MAX_INSN_SIZE + 1)) { @@ -803,7 +805,6 @@ static void __kprobes resume_execution(struct kprobe *p, p->ainsn.boostable = -1; } } -#endif regs->ip = orig_ip + (regs->ip - copy_ip); no_change: diff --git a/include/asm-x86/kprobes.h b/include/asm-x86/kprobes.h index 7319c62..f9a4fd2 100644 --- a/include/asm-x86/kprobes.h +++ b/include/asm-x86/kprobes.h @@ -58,13 +58,15 @@ void kretprobe_trampoline(void); struct arch_specific_insn { /* copy of the original instruction */ kprobe_opcode_t *insn; -#ifdef CONFIG_X86_32 /* - * If this flag is not 0, this kprobe can be boost when its - * post_handler and break_handler is not set. + * boostable = -1: This instruction type is not boostable. + * boostable = 0: This instruction type is boostable. + * boostable = 1: This instruction has been boosted: we have + * added a relative jump after the instruction copy in insn, + * so no single-step and fixup are needed (unless there's + * a post_handler or break_handler). */ - int boostable; -#endif + int boostable; }; struct prev_kprobe { -- 1.5.4.rc0.1083.gf568