Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756973AbYFPIUz (ORCPT ); Mon, 16 Jun 2008 04:20:55 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754510AbYFPIUX (ORCPT ); Mon, 16 Jun 2008 04:20:23 -0400 Received: from lec.cs.unibo.it ([130.136.1.103]:33417 "EHLO lec.cs.unibo.it" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753010AbYFPIUT (ORCPT ); Mon, 16 Jun 2008 04:20:19 -0400 Date: Mon, 16 Jun 2008 09:58:28 +0200 To: LKML , Jeff Dike , Roland McGrath Subject: [PATCH 1/2] ptrace_multi: speedup for virtual machines (and debuggers) running on ptrace Message-ID: <20080616075828.GD6950@cs.unibo.it> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.13 (2006-08-11) From: renzo@cs.unibo.it (Renzo Davoli) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 11092 Lines: 351 This patch implements PTRACE_MULTI. Several ptrace requests can be packed up and sent together to the kernel. This speeds up Virtual Machines and, if you like, debuggers. Signed-off-by: Renzo Davoli --- diff -Naur linux-2.6.26-rc6/include/linux/mm.h linux-2.6.26-rc6-ptrace_multi/include/linux/mm.h --- linux-2.6.26-rc6/include/linux/mm.h 2008-06-13 13:33:30.000000000 +0200 +++ linux-2.6.26-rc6-ptrace_multi/include/linux/mm.h 2008-06-14 16:56:11.000000000 +0200 @@ -804,6 +804,7 @@ extern int make_pages_present(unsigned long addr, unsigned long end); extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write); +extern int access_process_vm_user(struct task_struct *tsk, unsigned long addr, char __user *ubuf, int len, int write, int string); int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start, int len, int write, int force, struct page **pages, struct vm_area_struct **vmas); diff -Naur linux-2.6.26-rc6/include/linux/ptrace.h linux-2.6.26-rc6-ptrace_multi/include/linux/ptrace.h --- linux-2.6.26-rc6/include/linux/ptrace.h 2008-06-13 13:33:30.000000000 +0200 +++ linux-2.6.26-rc6-ptrace_multi/include/linux/ptrace.h 2008-06-14 16:56:11.000000000 +0200 @@ -27,6 +27,18 @@ #define PTRACE_GETSIGINFO 0x4202 #define PTRACE_SETSIGINFO 0x4203 +#define PTRACE_MULTI 0x4300 +#define PTRACE_PEEKCHARDATA 0x4301 +#define PTRACE_POKECHARDATA 0x4302 +#define PTRACE_PEEKSTRINGDATA 0x4303 + +struct ptrace_multi { + long request; + long addr; + void *localaddr; + long length; +}; + /* options set using PTRACE_SETOPTIONS */ #define PTRACE_O_TRACESYSGOOD 0x00000001 #define PTRACE_O_TRACEFORK 0x00000002 @@ -84,6 +96,7 @@ extern struct task_struct *ptrace_get_task_struct(pid_t pid); extern int ptrace_traceme(void); extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); +extern int ptrace_readstringdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); extern int ptrace_attach(struct task_struct *tsk); extern int ptrace_detach(struct task_struct *, unsigned int); diff -Naur linux-2.6.26-rc6/kernel/ptrace.c linux-2.6.26-rc6-ptrace_multi/kernel/ptrace.c --- linux-2.6.26-rc6/kernel/ptrace.c 2008-06-13 13:33:31.000000000 +0200 +++ linux-2.6.26-rc6-ptrace_multi/kernel/ptrace.c 2008-06-14 19:00:13.000000000 +0200 @@ -2,6 +2,7 @@ * linux/kernel/ptrace.c * * (C) Copyright 1999 Linus Torvalds + * PTRACE_MULTI support 2008 Renzo Davoli * * Common interfaces for "ptrace()" which we do not want * to continually duplicate across every architecture. @@ -244,52 +245,23 @@ int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) { - int copied = 0; + if (!access_ok(VERIFY_WRITE, dst, len)) + return -EIO; + return access_process_vm_user(tsk, src, dst, len, 0, 0); +} - while (len > 0) { - char buf[128]; - int this_len, retval; - - this_len = (len > sizeof(buf)) ? sizeof(buf) : len; - retval = access_process_vm(tsk, src, buf, this_len, 0); - if (!retval) { - if (copied) - break; - return -EIO; - } - if (copy_to_user(dst, buf, retval)) - return -EFAULT; - copied += retval; - src += retval; - dst += retval; - len -= retval; - } - return copied; +int ptrace_readstringdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) +{ + if (!access_ok(VERIFY_WRITE, dst, len)) + return -EIO; + return access_process_vm_user(tsk, src, dst, len, 0, 1); } int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len) { - int copied = 0; - - while (len > 0) { - char buf[128]; - int this_len, retval; - - this_len = (len > sizeof(buf)) ? sizeof(buf) : len; - if (copy_from_user(buf, src, this_len)) - return -EFAULT; - retval = access_process_vm(tsk, dst, buf, this_len, 1); - if (!retval) { - if (copied) - break; - return -EIO; - } - copied += retval; - src += retval; - dst += retval; - len -= retval; - } - return copied; + if (!access_ok(VERIFY_READ, dst, len)) + return -EIO; + return access_process_vm_user(tsk, dst, src, len, 1, 0); } static int ptrace_setoptions(struct task_struct *child, long data) @@ -534,6 +506,50 @@ #define arch_ptrace_attach(child) do { } while (0) #endif +static int multi_ptrace(struct task_struct *child, long request, long addr, long size) +{ + int i, ret; + long j; + ret=0; + if (!access_ok(VERIFY_READ, addr,size*sizeof(struct ptrace_multi))) { + ret = -EIO; + goto out_multi_ptrace; + } + for (i=0; immap_sem); + /* ignore errors, just check how much was sucessfully transfered */ + while (len) { + int bytes, ret, offset; + void *maddr; + + ret = get_user_pages(tsk, mm, addr, 1, + write, 1, &page, &vma); + if (ret <= 0) + break; + + bytes = len; + offset = addr & (PAGE_SIZE-1); + if (bytes > PAGE_SIZE-offset) + bytes = PAGE_SIZE-offset; + + maddr = kmap(page); + if (write) { + __copy_from_user(buf,ubuf,bytes); + copy_to_user_page(vma, page, addr, + maddr + offset, buf, bytes); + if (!PageCompound(page)) + set_page_dirty_lock(page); + } else { + copy_from_user_page(vma, page, addr, + buf, maddr + offset, bytes); + if (string) { + for (offset=0;offsetmmap_sem); + mmput(mm); + + kfree(buf); + return addr - old_addr; +} + +/* * Print the name of a VMA. */ void print_vma_addr(char *prefix, unsigned long ip) diff -Naur linux-2.6.26-rc6/patch-linux-2.6.25.5-ptrace_vm linux-2.6.26-rc6-ptrace_multi/patch-linux-2.6.25.5-ptrace_vm --- linux-2.6.26-rc6/patch-linux-2.6.25.5-ptrace_vm 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-rc6-ptrace_multi/patch-linux-2.6.25.5-ptrace_vm 2008-06-14 16:56:11.000000000 +0200 @@ -0,0 +1 @@ +diff -Naur linux-2.6.25.5 linux-2.6.25.5.ptrace_vm -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/