x86-64-specific-addition Adds the x86-64 specific code part, while reworking the rest a whole lot. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Index: linux-2.6.14/mm/proc_mm.c =================================================================== --- linux-2.6.14.orig/mm/proc_mm.c 2005-10-29 05:50:19.000000000 +0200 +++ linux-2.6.14/mm/proc_mm.c 2005-10-29 05:50:31.000000000 +0200 @@ -3,43 +3,66 @@ * Licensed under the GPL */ -#include "linux/mm.h" -#include "linux/init.h" -#include "linux/proc_fs.h" -#include "linux/proc_mm.h" -#include "linux/file.h" -#include "linux/mman.h" -#include "asm/uaccess.h" -#include "asm/mmu_context.h" - -static struct file_operations proc_mm_fops; +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Naming conventions are a mess, so I note them down. + * + * Things ending in _mm can be for everything. It's only for + * {open,release}_proc_mm. + * + * For the rest: + * + * _mm means /proc/mm, _mm64 means /proc/mm64. This is for the infrastructure + * only (for instance proc_mm_get_mm checks whether the file is /proc/mm or + * /proc/mm64; for instance the /proc handling). + * + * While for what is conversion dependant, we use the suffix _native and _emul. + * In some cases, there is a mapping between these ones (defined by + * ). + */ -struct mm_struct *proc_mm_get_mm(int fd) +/*These two are common to everything.*/ +static int open_proc_mm(struct inode *inode, struct file *file) { - struct mm_struct *ret = ERR_PTR(-EBADF); - struct file *file; + struct mm_struct *mm = mm_alloc(); + int ret; - file = fget(fd); - if (!file) - goto out; + ret = -ENOMEM; + if(mm == NULL) + goto out_mem; - ret = ERR_PTR(-EINVAL); - if(file->f_op != &proc_mm_fops) - goto out_fput; + init_new_empty_context(mm); + arch_pick_mmap_layout(mm); - ret = file->private_data; - out_fput: - fput(file); - out: - return(ret); + file->private_data = mm; + + return 0; + +out_mem: + return ret; +} + +static int release_proc_mm(struct inode *inode, struct file *file) +{ + struct mm_struct *mm = file->private_data; + + mmput(mm); + return 0; } -extern long do_mmap2(struct mm_struct *mm, unsigned long addr, - unsigned long len, unsigned long prot, - unsigned long flags, unsigned long fd, - unsigned long pgoff); +static struct file_operations proc_mm_fops; + +struct mm_struct *proc_mm_get_mm_native(int fd); -static ssize_t write_proc_mm(struct file *file, const char *buffer, +static ssize_t write_proc_mm_native(struct file *file, const char *buffer, size_t count, loff_t *ppos) { struct mm_struct *mm = file->private_data; @@ -66,8 +89,8 @@ if (! (map->flags & MAP_FIXED)) return(-EINVAL); - ret = do_mmap2(mm, map->addr, map->len, map->prot, - map->flags, map->fd, map->offset >> PAGE_SHIFT); + ret = __do_mmap(mm, map->addr, map->len, map->prot, + map->flags, map->fd, map->offset); if((ret & ~PAGE_MASK) == 0) ret = count; @@ -95,7 +118,7 @@ } case MM_COPY_SEGMENTS: { - struct mm_struct *from = proc_mm_get_mm(req.u.copy_segments); + struct mm_struct *from = proc_mm_get_mm_native(req.u.copy_segments); if(IS_ERR(from)){ ret = PTR_ERR(from); @@ -112,43 +135,37 @@ break; } - return(ret); + return ret; } -static int open_proc_mm(struct inode *inode, struct file *file) +/*These three are all for /proc/mm.*/ +struct mm_struct *proc_mm_get_mm(int fd) { - struct mm_struct *mm = mm_alloc(); - int ret; - - ret = -ENOMEM; - if(mm == NULL) - goto out_mem; - - init_new_empty_context(mm); - arch_pick_mmap_layout(mm); + struct mm_struct *ret = ERR_PTR(-EBADF); + struct file *file; - file->private_data = mm; + file = fget(fd); + if (!file) + goto out; - return(0); + ret = ERR_PTR(-EINVAL); + if(file->f_op != &proc_mm_fops) + goto out_fput; - out_mem: + ret = file->private_data; +out_fput: + fput(file); +out: return(ret); } -static int release_proc_mm(struct inode *inode, struct file *file) -{ - struct mm_struct *mm = file->private_data; - - mmput(mm); - return(0); -} - static struct file_operations proc_mm_fops = { .open = open_proc_mm, .release = release_proc_mm, .write = write_proc_mm, }; +/*Macro-ify it to avoid the duplication.*/ static int make_proc_mm(void) { struct proc_dir_entry *ent; @@ -160,11 +177,56 @@ } ent->proc_fops = &proc_mm_fops; - return(0); + return 0; } __initcall(make_proc_mm); +/*XXX: change the option.*/ +#ifdef CONFIG_64BIT +static struct file_operations proc_mm64_fops = { + .open = open_proc_mm, + .release = release_proc_mm, + .write = write_proc_mm64, +}; + +static int make_proc_mm64(void) +{ + struct proc_dir_entry *ent; + + ent = create_proc_entry("mm64", 0222, &proc_root); + if(ent == NULL){ + printk("make_proc_mm : Failed to register /proc/mm64\n"); + return(0); + } + ent->proc_fops = &proc_mm64_fops; + + return 0; +} + +__initcall(make_proc_mm64); + +struct mm_struct *proc_mm_get_mm64(int fd) +{ + struct mm_struct *ret = ERR_PTR(-EBADF); + struct file *file; + + file = fget(fd); + if (!file) + goto out; + + ret = ERR_PTR(-EINVAL); + /*This is the only change.*/ + if(file->f_op != &proc_mm64_fops) + goto out_fput; + + ret = file->private_data; +out_fput: + fput(file); +out: + return(ret); +} +#endif /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically Index: linux-2.6.14/include/linux/proc_mm.h =================================================================== --- linux-2.6.14.orig/include/linux/proc_mm.h 2005-10-29 05:50:00.000000000 +0200 +++ linux-2.6.14/include/linux/proc_mm.h 2005-10-29 05:50:31.000000000 +0200 @@ -6,7 +6,52 @@ #ifndef __PROC_MM_H #define __PROC_MM_H -#include "linux/sched.h" +#include +#include + +/* The differences between this one and do_mmap are that: + * - we must perform controls for userspace-supplied params (which are + * arch-specific currently). And also fget(fd) if needed and so on... + * - we must accept the struct mm_struct on which to act as first param, and the + * offset in byte rather than page units as last param. + */ +static inline long __do_mmap(struct mm_struct *mm, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flags, unsigned long fd, + unsigned long off); + +/* This header can be used only on archs defining CONFIG_PROC_MM in their + * configs, so asm/proc_mm.h can still exist only for the needed archs. + * Including it only in the x86-64 case does not make sense.*/ +#include + +/*XXX: this is defined on x86_64, but not on every 64-bit arch (not on sh64).*/ +#ifdef CONFIG_64BIT + +#define write_proc_mm write_proc_mm_emul +#define write_proc_mm64 write_proc_mm_native + +/* It would make more sense to do this mapping the reverse direction, to map the + * called name to the defined one and not the reverse. Like the 2nd example + */ +/*#define proc_mm_get_mm proc_mm_get_mm_emul +#define proc_mm_get_mm64 proc_mm_get_mm_native*/ + +#define proc_mm_get_mm_emul proc_mm_get_mm +#define proc_mm_get_mm_native proc_mm_get_mm64 + +#else + +#define write_proc_mm write_proc_mm_native +#undef write_proc_mm64 + +/*#define proc_mm_get_mm proc_mm_get_mm_native +#undef proc_mm_get_mm64*/ + +#define proc_mm_get_mm_native proc_mm_get_mm +#undef proc_mm_get_mm_emul + +#endif #define MM_MMAP 54 #define MM_MUNMAP 55 Index: linux-2.6.14/arch/x86_64/mm/proc_mm.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.14/arch/x86_64/mm/proc_mm.c 2005-10-29 05:50:31.000000000 +0200 @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +ssize_t write_proc_mm_emul(struct file *file, const char *buffer, + size_t count, loff_t *ppos) +{ + struct mm_struct *mm = file->private_data; + struct proc_mm_op32 req; + int n, ret; + + if(count > sizeof(req)) + return(-EINVAL); + + n = copy_from_user(&req, buffer, count); + if(n != 0) + return(-EFAULT); + + ret = count; + switch(req.op){ + case MM_MMAP: { + struct mm_mmap32 *map = &req.u.mmap; + + /* Nobody ever noticed it, but do_mmap_pgoff() calls + * get_unmapped_area() which checks current->mm, if + * MAP_FIXED is not set, so mmap() could replace + * an old mapping. + */ + if (! (map->flags & MAP_FIXED)) + return(-EINVAL); + + ret = __do_mmap(mm, map->addr, map->len, map->prot, + map->flags, map->fd, map->offset >> PAGE_SHIFT); + if((ret & ~PAGE_MASK) == 0) + ret = count; + + break; + } + case MM_MUNMAP: { + struct mm_munmap32 *unmap = &req.u.munmap; + + down_write(&mm->mmap_sem); + ret = do_munmap(mm, unmap->addr, unmap->len); + up_write(&mm->mmap_sem); + + if(ret == 0) + ret = count; + break; + } + case MM_MPROTECT: { + struct mm_mprotect32 *protect = &req.u.mprotect; + + ret = do_mprotect(mm, protect->addr, protect->len, + protect->prot); + if(ret == 0) + ret = count; + break; + } + + case MM_COPY_SEGMENTS: { + struct mm_struct *from = proc_mm_get_mm_emul(req.u.copy_segments); + + if(IS_ERR(from)){ + ret = PTR_ERR(from); + break; + } + + ret = copy_context(mm, from); + if(ret == 0) + ret = count; + break; + } + default: + ret = -EINVAL; + break; + } + + return ret; +} + Index: linux-2.6.14/include/asm-x86_64/proc_mm.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.14/include/asm-x86_64/proc_mm.h 2005-10-29 05:50:31.000000000 +0200 @@ -0,0 +1,56 @@ +#ifndef __ASM_PROC_MM +#define __ASM_PROC_MM +#include + +#include + +struct mm_mmap32 { + compat_ulong_t addr; + compat_ulong_t len; + compat_ulong_t prot; + compat_ulong_t flags; + compat_ulong_t fd; + compat_ulong_t offset; +}; + +struct mm_munmap32 { + compat_ulong_t addr; + compat_ulong_t len; +}; + +struct mm_mprotect32 { + compat_ulong_t addr; + compat_ulong_t len; + compat_uint_t prot; +}; + +struct proc_mm_op32 { + compat_int_t op; + union { + struct mm_mmap32 mmap; + struct mm_munmap32 munmap; + struct mm_mprotect32 mprotect; + compat_int_t copy_segments; + } u; +}; + +extern ssize_t write_proc_mm_emul(struct file *file, const char *buffer, + size_t count, loff_t *ppos); + +extern long do64_mmap(struct mm_struct *mm, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long off); + +static inline long __do_mmap(struct mm_struct *mm, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flags, unsigned long fd, + unsigned long off) +{ + /* The latter one is stricter, since will actually check that off is page + * aligned. The first one skipped the check. */ + + /* return do32_mmap2(mm, addr, len, prot, flags, fd, off >> + * PAGE_SHIFT);*/ + return do64_mmap(mm, addr, len, prot, flags, fd, off); +} + +#endif /* __ASM_PROC_MM */ Index: linux-2.6.14/arch/x86_64/Kconfig =================================================================== --- linux-2.6.14.orig/arch/x86_64/Kconfig 2005-10-29 05:49:27.000000000 +0200 +++ linux-2.6.14/arch/x86_64/Kconfig 2005-10-29 05:50:31.000000000 +0200 @@ -357,6 +357,10 @@ of memory and any 32-bit devices. Don't turn on unless you know what you are doing. +config PROC_MM + bool "/proc/mm support" + default y + config X86_MCE bool "Machine check support" if EMBEDDED default y Index: linux-2.6.14/arch/x86_64/ia32/ptrace32.c =================================================================== --- linux-2.6.14.orig/arch/x86_64/ia32/ptrace32.c 2005-10-29 05:49:27.000000000 +0200 +++ linux-2.6.14/arch/x86_64/ia32/ptrace32.c 2005-10-29 05:50:31.000000000 +0200 @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -27,6 +29,7 @@ #include #include #include +#include /* determines which flags the user has access to. */ /* 1 = access 0 = no access */ @@ -251,6 +254,12 @@ case PTRACE_SETFPXREGS: case PTRACE_GETFPXREGS: case PTRACE_GETEVENTMSG: +#ifdef CONFIG_PROC_MM + case PTRACE_FAULTINFO: + case PTRACE_SIGPENDING: + case PTRACE_LDT: + case PTRACE_SWITCH_MM: +#endif break; } @@ -363,6 +372,52 @@ ret = 0; break; } +#ifdef CONFIG_PROC_MM + case PTRACE_FAULTINFO: { + struct ptrace_faultinfo32 fault; + + fault = ((struct ptrace_faultinfo32) + { .is_write = (compat_int_t) child->thread.error_code, + .addr = (compat_uptr_t) child->thread.cr2 }); + ret = copy_to_user((unsigned long *) datap, &fault, + sizeof(fault)); + break; + } + case PTRACE_SIGPENDING: + ret = copy_to_user((unsigned long *) datap, + &child->pending.signal, + sizeof(child->pending.signal)); + break; + + case PTRACE_LDT: { + struct ptrace_ldt32 ldt; + + if(copy_from_user(&ldt, (unsigned long *) datap, + sizeof(ldt))){ + ret = -EIO; + break; + } + ret = __modify_ldt(child->mm, ldt.func, compat_ptr(ldt.ptr), ldt.bytecount); + break; + } + + case PTRACE_SWITCH_MM: { + struct mm_struct *old = child->mm; + struct mm_struct *new = proc_mm_get_mm(data); + + if(IS_ERR(new)){ + ret = PTR_ERR(new); + break; + } + + atomic_inc(&new->mm_users); + child->mm = new; + child->active_mm = new; + mmput(old); + ret = 0; + break; + } +#endif case PTRACE_GETEVENTMSG: ret = put_user(child->ptrace_message,(unsigned int __user *)compat_ptr(data)); Index: linux-2.6.14/include/asm-x86_64/mmu_context.h =================================================================== --- linux-2.6.14.orig/include/asm-x86_64/mmu_context.h 2005-10-29 05:49:27.000000000 +0200 +++ linux-2.6.14/include/asm-x86_64/mmu_context.h 2005-10-29 05:50:31.000000000 +0200 @@ -8,13 +8,28 @@ #include #include #include +#include /* * possibly do the LDT unload here? + * Used for LDT initialization/destruction. You cannot copy an LDT with + * init_new_context, since it thinks you are passing it a new LDT and won't + * deallocate its old content. */ + int init_new_context(struct task_struct *tsk, struct mm_struct *mm); void destroy_context(struct mm_struct *mm); +/* LDT initialization for a clean environment - needed for SKAS.*/ +static inline void init_new_empty_context(struct mm_struct *mm) +{ + init_MUTEX(&mm->context.sem); + mm->context.size = 0; +} + +/* LDT copy for SKAS - for the above problem.*/ +int copy_context(struct mm_struct *mm, struct mm_struct *old_mm); + #ifdef CONFIG_SMP static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) @@ -37,6 +52,9 @@ struct task_struct *tsk) { unsigned cpu = smp_processor_id(); +#ifdef CONFIG_SMP + prev = read_pda(active_mm); +#endif if (likely(prev != next)) { /* stop flush ipis for the previous mm */ clear_bit(cpu, &prev->cpu_vm_mask); @@ -53,8 +71,6 @@ #ifdef CONFIG_SMP else { write_pda(mmu_state, TLBSTATE_OK); - if (read_pda(active_mm) != next) - out_of_line_bug(); if(!test_and_set_bit(cpu, &next->cpu_vm_mask)) { /* We were in lazy tlb mode and leave_mm disabled * tlb flush IPI delivery. We must reload CR3 Index: linux-2.6.14/arch/x86_64/ia32/sys_ia32.c =================================================================== --- linux-2.6.14.orig/arch/x86_64/ia32/sys_ia32.c 2005-10-29 05:49:27.000000000 +0200 +++ linux-2.6.14/arch/x86_64/ia32/sys_ia32.c 2005-10-29 05:50:31.000000000 +0200 @@ -833,11 +833,10 @@ return ret; } -asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, +long do32_mmap2(struct mm_struct *mm, unsigned long addr, + unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { - struct mm_struct *mm = current->mm; unsigned long error; struct file * file = NULL; @@ -849,7 +848,7 @@ } down_write(&mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); + error = __do_mmap_pgoff(mm, file, addr, len, prot, flags, pgoff); up_write(&mm->mmap_sem); if (file) @@ -857,6 +856,15 @@ return error; } +/* XXX: this wrapper can be probably removed, we can simply use the 64-bit + * version.*/ +asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff) +{ + return do32_mmap2(current->mm, addr, len, prot, flags, fd, pgoff); +} + asmlinkage long sys32_olduname(struct oldold_utsname __user * name) { int error; Index: linux-2.6.14/arch/x86_64/kernel/ldt.c =================================================================== --- linux-2.6.14.orig/arch/x86_64/kernel/ldt.c 2005-10-29 05:49:27.000000000 +0200 +++ linux-2.6.14/arch/x86_64/kernel/ldt.c 2005-10-29 05:50:31.000000000 +0200 @@ -22,6 +22,7 @@ #include #include #include +#include #ifdef CONFIG_SMP /* avoids "defined but not used" warnig */ static void flush_ldt(void *null) @@ -58,7 +59,7 @@ wmb(); pc->size = mincount; wmb(); - if (reload) { + if (reload && (¤t->active_mm->context == pc)) { #ifdef CONFIG_SMP cpumask_t mask; @@ -94,14 +95,10 @@ * we do not have to muck with descriptors here, that is * done in switch_mm() as needed. */ -int init_new_context(struct task_struct *tsk, struct mm_struct *mm) +int copy_context(struct mm_struct *mm, struct mm_struct *old_mm) { - struct mm_struct * old_mm; int retval = 0; - init_MUTEX(&mm->context.sem); - mm->context.size = 0; - old_mm = current->mm; if (old_mm && old_mm->context.size > 0) { down(&old_mm->context.sem); retval = copy_ldt(&mm->context, &old_mm->context); @@ -110,6 +107,12 @@ return retval; } +int init_new_context(struct task_struct *tsk, struct mm_struct *mm) +{ + init_new_empty_context(mm); + return copy_context(mm, current->mm); +} + /* * * Don't touch the LDT register - we're already in the next thread. @@ -125,11 +128,10 @@ } } -static int read_ldt(void __user * ptr, unsigned long bytecount) +static int read_ldt(struct mm_struct * mm, void __user * ptr, unsigned long bytecount) { int err; unsigned long size; - struct mm_struct * mm = current->mm; if (!mm->context.size) return 0; @@ -170,10 +172,8 @@ return bytecount; } -static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode) +static int write_ldt(struct mm_struct * mm, void __user * ptr, unsigned long bytecount, int oldmode) { - struct task_struct *me = current; - struct mm_struct * mm = me->mm; __u32 entry_1, entry_2, *lp; int error; struct user_desc ldt_info; @@ -198,7 +198,7 @@ down(&mm->context.sem); if (ldt_info.entry_number >= (unsigned)mm->context.size) { - error = alloc_ldt(¤t->mm->context, ldt_info.entry_number+1, 1); + error = alloc_ldt(&mm->context, ldt_info.entry_number+1, 1); if (error < 0) goto out_unlock; } @@ -231,23 +231,29 @@ return error; } -asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) +int __modify_ldt(struct mm_struct * mm, int func, void __user *ptr, + unsigned long bytecount) { int ret = -ENOSYS; switch (func) { case 0: - ret = read_ldt(ptr, bytecount); + ret = read_ldt(mm, ptr, bytecount); break; case 1: - ret = write_ldt(ptr, bytecount, 1); + ret = write_ldt(mm, ptr, bytecount, 1); break; case 2: ret = read_default_ldt(ptr, bytecount); break; case 0x11: - ret = write_ldt(ptr, bytecount, 0); + ret = write_ldt(mm, ptr, bytecount, 0); break; } return ret; } + +asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) +{ + return __modify_ldt(current->mm, func, ptr, bytecount); +} Index: linux-2.6.14/include/asm-x86_64/desc.h =================================================================== --- linux-2.6.14.orig/include/asm-x86_64/desc.h 2005-10-29 05:49:27.000000000 +0200 +++ linux-2.6.14/include/asm-x86_64/desc.h 2005-10-29 05:50:31.000000000 +0200 @@ -215,6 +215,9 @@ extern struct desc_ptr idt_descr; +extern int __modify_ldt(struct mm_struct * mm, int func, void __user *ptr, + unsigned long bytecount); + #endif /* !__ASSEMBLY__ */ #endif Index: linux-2.6.14/include/asm-x86_64/ptrace.h =================================================================== --- linux-2.6.14.orig/include/asm-x86_64/ptrace.h 2005-10-29 05:49:27.000000000 +0200 +++ linux-2.6.14/include/asm-x86_64/ptrace.h 2005-10-29 05:50:31.000000000 +0200 @@ -64,6 +64,45 @@ /* top of stack page */ }; +/* Stolen from +#include ; we can't include it because +there is a nasty ciclic include chain. +*/ + +#define compat_int_t s32 +#define compat_long_t s32 +#define compat_uint_t u32 +#define compat_ulong_t u32 +#define compat_uptr_t u32 + +struct ptrace_faultinfo32 { + compat_int_t is_write; + compat_ulong_t addr; +}; + +struct ptrace_ldt32 { + compat_int_t func; + compat_uptr_t ptr; /*Actually a void pointer on i386, but must be converted.*/ + compat_ulong_t bytecount; +}; + +struct ptrace_faultinfo { + int is_write; + unsigned long addr; +}; + +struct ptrace_ldt { + int func; + void *ptr; + unsigned long bytecount; +}; + +#undef compat_int_t +#undef compat_long_t +#undef compat_uint_t +#undef compat_ulong_t +#undef compat_uptr_t + #endif /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ @@ -74,6 +113,11 @@ #define PTRACE_GETFPXREGS 18 #define PTRACE_SETFPXREGS 19 +#define PTRACE_FAULTINFO 52 +#define PTRACE_SIGPENDING 53 +#define PTRACE_LDT 54 +#define PTRACE_SWITCH_MM 55 + /* only useful for access 32bit programs */ #define PTRACE_GET_THREAD_AREA 25 #define PTRACE_SET_THREAD_AREA 26 Index: linux-2.6.14/arch/x86_64/mm/Makefile =================================================================== --- linux-2.6.14.orig/arch/x86_64/mm/Makefile 2005-10-29 05:49:27.000000000 +0200 +++ linux-2.6.14/arch/x86_64/mm/Makefile 2005-10-29 05:50:31.000000000 +0200 @@ -7,5 +7,6 @@ obj-$(CONFIG_NUMA) += numa.o obj-$(CONFIG_K8_NUMA) += k8topology.o obj-$(CONFIG_ACPI_NUMA) += srat.o +obj-$(CONFIG_PROC_MM) += proc_mm.o hugetlbpage-y = ../../i386/mm/hugetlbpage.o Index: linux-2.6.14/arch/x86_64/kernel/ptrace.c =================================================================== --- linux-2.6.14.orig/arch/x86_64/kernel/ptrace.c 2005-10-29 05:49:27.000000000 +0200 +++ linux-2.6.14/arch/x86_64/kernel/ptrace.c 2005-10-29 05:50:31.000000000 +0200 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -604,6 +605,59 @@ break; } +#ifdef CONFIG_PROC_MM + case PTRACE_FAULTINFO: { + struct ptrace_faultinfo fault; + + /* I checked in thread_struct comments that error_code and cr2 + * are still part of the "fault info" section, so I guess that + * things are unchanged for now. Still to check manuals. BB*/ + fault = ((struct ptrace_faultinfo) + { .is_write = child->thread.error_code, + .addr = child->thread.cr2 }); + ret = copy_to_user((unsigned long *) data, &fault, + sizeof(fault)); + if(ret) + break; + break; + } + + case PTRACE_SIGPENDING: + ret = copy_to_user((unsigned long *) data, + &child->pending.signal, + sizeof(child->pending.signal)); + break; + + case PTRACE_LDT: { + struct ptrace_ldt ldt; + + if(copy_from_user(&ldt, (unsigned long *) data, + sizeof(ldt))){ + ret = -EIO; + break; + } + ret = __modify_ldt(child->mm, ldt.func, ldt.ptr, ldt.bytecount); + break; + } + + case PTRACE_SWITCH_MM: { + struct mm_struct *old = child->mm; + struct mm_struct *new = proc_mm_get_mm(data); + + if(IS_ERR(new)){ + ret = PTR_ERR(new); + break; + } + + atomic_inc(&new->mm_users); + child->mm = new; + child->active_mm = new; + mmput(old); + ret = 0; + break; + } +#endif + default: ret = ptrace_request(child, request, addr, data); break; Index: linux-2.6.14/arch/x86_64/kernel/sys_x86_64.c =================================================================== --- linux-2.6.14.orig/arch/x86_64/kernel/sys_x86_64.c 2005-10-29 05:49:27.000000000 +0200 +++ linux-2.6.14/arch/x86_64/kernel/sys_x86_64.c 2005-10-29 05:50:31.000000000 +0200 @@ -19,6 +19,7 @@ #include #include +#include /* * sys_pipe() is the normal C calling standard for creating @@ -37,7 +38,7 @@ return error; } -asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, +long do64_mmap(struct mm_struct *mm, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off) { long error; @@ -55,9 +56,9 @@ if (!file) goto out; } - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, off >> PAGE_SHIFT); - up_write(¤t->mm->mmap_sem); + down_write(&mm->mmap_sem); + error = __do_mmap_pgoff(mm, file, addr, len, prot, flags, off >> PAGE_SHIFT); + up_write(&mm->mmap_sem); if (file) fput(file); @@ -65,6 +66,12 @@ return error; } +asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long off) +{ + return do64_mmap(current->mm, addr, len, prot, flags, fd, off); +} + static void find_start_end(unsigned long flags, unsigned long *begin, unsigned long *end) { Index: linux-2.6.14/include/asm-i386/proc_mm.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.14/include/asm-i386/proc_mm.h 2005-10-29 05:50:31.000000000 +0200 @@ -0,0 +1,18 @@ +#ifndef __ASM_PROC_MM +#define __ASM_PROC_MM + +#include + +extern long do_mmap2(struct mm_struct *mm, unsigned long addr, + unsigned long len, unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff); + +static inline long __do_mmap(struct mm_struct *mm, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flags, unsigned long fd, + unsigned long off) +{ + return do_mmap2(mm, addr, len, prot, flags, fd, off >> PAGE_SHIFT); +} + +#endif /* __ASM_PROC_MM */