This is the new_mm, switch_mm, and /proc/<pid>/mm implementation for 32- and 64-bit x86 and UML, plus 32-bit support on 64-bit x86.
diff --git a/arch/um/include/skas_ptrace.h b/arch/um/include/skas_ptrace.h index cd2327d..6b55c52 100644 --- a/arch/um/include/skas_ptrace.h +++ b/arch/um/include/skas_ptrace.h @@ -7,7 +7,9 @@ #define __SKAS_PTRACE_H #define PTRACE_FAULTINFO 52 -#define PTRACE_SWITCH_MM 55 +#ifndef OLD_PTRACE_SWITCH_MM +#define OLD_PTRACE_SWITCH_MM 55 +#endif #include "sysdep/skas_ptrace.h" diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 47b57b4..913037e 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -192,7 +192,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) } #endif #ifdef CONFIG_PROC_MM - case PTRACE_SWITCH_MM: { + case OLD_PTRACE_SWITCH_MM: { struct mm_struct *old = child->mm; struct mm_struct *new = proc_mm_get_mm(data); @@ -292,3 +292,19 @@ void syscall_trace(struct uml_pt_regs *regs, int entryexit) current->exit_code = 0; } } + +int copyin_user_regs(struct user_regs *to, unsigned long __user *from) +{ + return copy_from_user(&to->regs, from, sizeof(to->regs)); +} + +int ptrace_to_pt_regs(struct pt_regs *to, struct user_regs *from) +{ + memcpy(to, &from->regs, sizeof(from->regs)); + return 0; +} + +int pt_regs_to_ptrace(unsigned long __user *to, struct pt_regs *from) +{ + return copy_to_user(to, &from->regs.gp, sizeof(from->regs.gp)); +} diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 82a0780..522d0f1 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -627,7 +627,7 @@ void __switch_mm(struct mm_id *mm_idp) /* FIXME: need cpu pid in __switch_mm */ if (proc_mm) { - err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, + err = ptrace(OLD_PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_idp->u.mm_fd); if (err) panic("__switch_mm - PTRACE_SWITCH_MM failed, " diff --git a/arch/um/sys-i386/syscalls.c b/arch/um/sys-i386/syscalls.c index e2d1426..85621a2 100644 --- a/arch/um/sys-i386/syscalls.c +++ b/arch/um/sys-i386/syscalls.c @@ -200,3 +200,11 @@ long sys_sigaction(int sig, const struct old_sigaction __user *act, return ret; } + +extern long do_switch_mm(int fd, int flags, long __user *new, + long __user *save, struct pt_regs *regs); + +long sys_switch_mm(int fd, int flags, long __user *new, long __user *save) +{ + return do_switch_mm(fd, flags, new, save, ¤t->thread.regs); +} diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c index 86f6b18..ff012ba 100644 --- a/arch/um/sys-x86_64/syscalls.c +++ b/arch/um/sys-x86_64/syscalls.c @@ -112,3 +112,11 @@ void arch_switch_to(struct task_struct *from, struct task_struct *to) arch_prctl(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs); } + +extern long do_switch_mm(int fd, int flags, long __user *new, + long __user *save, struct pt_regs *regs); + +long stub_switch_mm(int fd, int flags, long __user *new, long __user *save) +{ + return do_switch_mm(fd, flags, new, save, ¤t->thread.regs); +} diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index df588f0..1992458 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -374,6 +374,7 @@ quiet_ni_syscall: PTREGSCALL stub32_vfork, sys_vfork, %rdi PTREGSCALL stub32_iopl, sys_iopl, %rsi PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend, %rdx + PTREGSCALL stub32_switch_mm, sys_switch_mm, %r8 ENTRY(ia32_ptregs_common) popq %r11 @@ -726,4 +727,6 @@ ia32_sys_call_table: .quad compat_sys_timerfd .quad sys_eventfd .quad sys32_fallocate + .quad sys_new_mm /* 325 */ + .quad stub32_switch_mm ia32_syscall_end: diff --git a/arch/x86/ia32/ptrace32.c b/arch/x86/ia32/ptrace32.c index 4a233ad..5c0caa4 100644 --- a/arch/x86/ia32/ptrace32.c +++ b/arch/x86/ia32/ptrace32.c @@ -38,7 +38,7 @@ #define R32(l,q) \ case offsetof(struct user32, regs.l): stack[offsetof(struct pt_regs, q)/8] = val; break -static int putreg32(struct task_struct *child, unsigned regno, u32 val) +int putreg32(struct task_struct *child, unsigned regno, u32 val) { int i; __u64 *stack = (__u64 *)task_pt_regs(child); @@ -139,7 +139,7 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val) #define R32(l,q) \ case offsetof(struct user32, regs.l): *val = stack[offsetof(struct pt_regs, q)/8]; break -static int getreg32(struct task_struct *child, unsigned regno, u32 *val) +int getreg32(struct task_struct *child, unsigned regno, u32 *val) { __u64 *stack = (__u64 *)task_pt_regs(child); @@ -248,6 +248,7 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) case PTRACE_SETOPTIONS: case PTRACE_SET_THREAD_AREA: case PTRACE_GET_THREAD_AREA: + case PTRACE_SWITCH_MM: return sys_ptrace(request, pid, addr, data); default: diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 3a058bb..b130f88 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -412,6 +412,7 @@ END(\label) PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend, %rdx PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx PTREGSCALL stub_iopl, sys_iopl, %rsi + PTREGSCALL stub_switch_mm, sys_switch_mm, %r8 ENTRY(ptregscall_common) popq %r11 diff --git a/arch/x86/kernel/ptrace_32.c b/arch/x86/kernel/ptrace_32.c index ff5431c..a35dd5f 100644 --- a/arch/x86/kernel/ptrace_32.c +++ b/arch/x86/kernel/ptrace_32.c @@ -83,8 +83,8 @@ static inline int put_stack_long(struct task_struct *task, int offset, return 0; } -static int putreg(struct task_struct *child, - unsigned long regno, unsigned long value) +int putreg(struct task_struct *child, + unsigned long regno, unsigned long value) { switch (regno >> 2) { case GS: @@ -116,7 +116,7 @@ static int putreg(struct task_struct *child, return 0; } -static unsigned long getreg(struct task_struct *child, +unsigned long getreg(struct task_struct *child, unsigned long regno) { unsigned long retval = ~0UL; @@ -715,3 +715,36 @@ out: audit_syscall_exit(AUDITSC_RESULT(regs->eax), regs->eax); return 1; } + +int copyin_user_regs(struct user_regs *to, unsigned long __user *from) +{ + return copy_from_user(&to->regs, from, sizeof(to->regs)); +} + +int ptrace_to_pt_regs(struct pt_regs *regs, struct user_regs *ptrace) +{ + int i, err; + + for (i = 0; i < FRAME_SIZE; i++){ + err = putreg(current, i * 4, ptrace->regs[i]); + if (err) + return err; + } + + return 0; +} + +int pt_regs_to_ptrace(unsigned long __user *ptrace, struct pt_regs *regs) +{ + int i; + + if (!access_ok(VERIFY_WRITE, ptrace, FRAME_SIZE * sizeof(long))) + return -EFAULT; + + for (i = 0; i < FRAME_SIZE; i++){ + unsigned long n = getreg(current, i * 4), err; + err = put_user(n, &ptrace[i]); + } + + return 0; +} diff --git a/arch/x86/kernel/ptrace_64.c b/arch/x86/kernel/ptrace_64.c index 607085f..ab8954d 100644 --- a/arch/x86/kernel/ptrace_64.c +++ b/arch/x86/kernel/ptrace_64.c @@ -226,7 +226,7 @@ void ptrace_disable(struct task_struct *child) clear_singlestep(child); } -static int putreg(struct task_struct *child, +int putreg(struct task_struct *child, unsigned long regno, unsigned long value) { unsigned long tmp; @@ -283,7 +283,7 @@ static int putreg(struct task_struct *child, return 0; } -static unsigned long getreg(struct task_struct *child, unsigned long regno) +unsigned long getreg(struct task_struct *child, unsigned long regno) { unsigned long val; switch (regno) { @@ -619,3 +619,101 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs) && (current->ptrace & PT_PTRACED)) syscall_trace(regs); } + +int copyin_user_regs(struct user_regs *to, unsigned long __user *from) +{ +#ifdef CONFIG_IA32_EMULATION + if (test_thread_flag(TIF_IA32)) + return copy_from_user(&to->u.regs32, from, + sizeof(to->u.regs32)); +#endif + return copy_from_user(&to->u.regs64, from, sizeof(to->u.regs64)); +} + +extern int putreg32(struct task_struct *child, unsigned regno, u32 val); + +int ptrace_to_pt_regs(struct pt_regs *regs, struct user_regs *ptrace) +{ + int i, err; + +#ifdef CONFIG_IA32_EMULATION + if (test_thread_flag(TIF_IA32)) { + for (i = 0; i < MAX_REG32_NR; i++){ + err = putreg32(current, i * 4, ptrace->u.regs32[i]); + if (err) + return err; + } + + return 0; + } +#endif + for (i = 0; i < MAX_REG_NR; i++){ + err = putreg(current, i * 8, ptrace->u.regs64[i]); + if (err) + return err; + } + + return 0; +} + +extern int getreg32(struct task_struct *child, unsigned regno, u32 *val); + +int pt_regs_to_ptrace(unsigned long __user *ptrace, struct pt_regs *regs) +{ + int i, err; + +#ifdef CONFIG_IA32_EMULATION + if (test_thread_flag(TIF_IA32)) { + u32 __user *ptrace32 = (u32 __user *) ptrace; + + if (!access_ok(VERIFY_WRITE, ptrace32, MAX_REG32_NR * 4)) + return -EFAULT; + + for (i = 0; i < MAX_REG32_NR; i++){ + u32 n; + + err = getreg32(current, i * 4, &n); + if (err) + return err; + + err = __put_user(n, &ptrace32[i]); + if (err) + return err; + } + + return 0; + } +#endif + if (!access_ok(VERIFY_WRITE, ptrace, MAX_REG_NR * 8)) + return -EFAULT; + + for (i = 0; i < MAX_REG_NR; i++){ + unsigned long n = getreg(current, i * 8); + err = __put_user(n, &ptrace[i]); + if (err) + return err; + } + + return 0; +} + +#define RIP_INDEX (128 / sizeof(long)) +#define RSP_INDEX (152 / sizeof(long)) + +unsigned long ptrace_ip(struct user_regs *regs) +{ +#ifdef CONFIG_IA32_EMULATION + if (test_thread_flag(TIF_IA32)) + return ptrace_ip32(regs->u.regs32); +#endif + return regs->u.regs64[RIP_INDEX]; +} + +unsigned long ptrace_sp(struct user_regs *regs) +{ +#ifdef CONFIG_IA32_EMULATION + if (test_thread_flag(TIF_IA32)) + return ptrace_sp32(regs->u.regs32); +#endif + return regs->u.regs64[RSP_INDEX]; +} diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c index a86d26f..7b9d43b 100644 --- a/arch/x86/kernel/sys_i386_32.c +++ b/arch/x86/kernel/sys_i386_32.c @@ -261,3 +261,12 @@ int kernel_execve(const char *filename, char *const argv[], char *const envp[]) : "0" (__NR_execve),"ri" (filename),"c" (argv), "d" (envp) : "memory"); return __res; } + +extern long do_switch_mm(int fd, int flags, long __user *new, long __user *save, + struct pt_regs *regs); + +asmlinkage long sys_switch_mm(struct pt_regs regs) +{ + return do_switch_mm(regs.ebx, regs.ecx, (long __user *) regs.edx, + (long __user *) regs.esi, ®s); +} diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c index 907942e..ddc1c98 100644 --- a/arch/x86/kernel/sys_x86_64.c +++ b/arch/x86/kernel/sys_x86_64.c @@ -153,3 +153,12 @@ asmlinkage long sys_uname(struct new_utsname __user * name) err |= copy_to_user(&name->machine, "i686", 5); return err ? -EFAULT : 0; } + +extern long do_switch_mm(int fd, int flags, long __user *new, + long __user *save, struct pt_regs *regs); + +asmlinkage long sys_switch_mm(int fd, int flags, long __user *new, + long __user *save, struct pt_regs *regs) +{ + return do_switch_mm(fd, flags, new, save, regs); +} diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S index 8344c70..3346997 100644 --- a/arch/x86/kernel/syscall_table_32.S +++ b/arch/x86/kernel/syscall_table_32.S @@ -324,3 +324,5 @@ ENTRY(sys_call_table) .long sys_timerfd .long sys_eventfd .long sys_fallocate + .long sys_new_mm + .long sys_switch_mm diff --git a/fs/proc/base.c b/fs/proc/base.c index 7411bfb..6dd8e34 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2187,6 +2187,34 @@ static int proc_pid_io_accounting(struct task_struct *task, char *buffer) } #endif +static int proc_pid_mm_open(struct inode *inode, struct file *file) +{ + struct task_struct *task = pid_task(proc_pid(inode), PIDTYPE_PID); + + if (task == NULL) + return -ENOENT; + + if(task->mm != NULL) + atomic_inc(&task->mm->mm_users); + file->private_data = task->mm; + return 0; +} + +static int proc_pid_mm_release(struct inode *inode, struct file *file) +{ + struct mm_struct *mm = file->private_data; + + if(mm != NULL) + mmput(mm); + + return 0; +} + +const struct file_operations proc_pid_mm_operations = { + .open = proc_pid_mm_open, + .release = proc_pid_mm_release, +}; + /* * Thread groups */ @@ -2250,6 +2278,7 @@ static const struct pid_entry tgid_base_stuff[] = { #ifdef CONFIG_TASK_IO_ACCOUNTING INF("io", S_IRUGO, pid_io_accounting), #endif + REG("mm", S_IRUSR | S_IWUSR, pid_mm), }; static int proc_tgid_base_readdir(struct file * filp, diff --git a/include/asm-um/ptrace-generic.h b/include/asm-um/ptrace-generic.h index 6aefcd3..7894c3d 100644 --- a/include/asm-um/ptrace-generic.h +++ b/include/asm-um/ptrace-generic.h @@ -34,6 +34,15 @@ struct pt_regs { #define instruction_pointer(regs) PT_REGS_IP(regs) +struct user_regs { + unsigned long regs[MAX_REG_NR]; +}; + +extern int copyin_user_regs(struct user_regs *to, unsigned long __user *from); +extern int ptrace_to_pt_regs(struct pt_regs *ptregs, struct user_regs *regs); +extern int pt_regs_to_ptrace(unsigned long __user *regs, + struct pt_regs *ptregs); + struct task_struct; extern long subarch_ptrace(struct task_struct *child, long request, long addr, diff --git a/include/asm-um/ptrace-i386.h b/include/asm-um/ptrace-i386.h index b2d24c5..9bec151 100644 --- a/include/asm-um/ptrace-i386.h +++ b/include/asm-um/ptrace-i386.h @@ -40,6 +40,12 @@ #define user_mode(r) UPT_IS_USER(&(r)->regs) +#define pt_regs_ip(r) (r).regs.gp[EIP] +#define pt_regs_sp(r) (r).regs.gp[UESP] + +#define ptrace_ip(r) (r)->regs[EIP] +#define ptrace_sp(r) (r)->regs[UESP] + /* * Forward declaration to avoid including sysdep/tls.h, which causes a * circular include, and compilation failures. diff --git a/include/asm-um/ptrace-x86_64.h b/include/asm-um/ptrace-x86_64.h index 4c47535..9c5365e 100644 --- a/include/asm-um/ptrace-x86_64.h +++ b/include/asm-um/ptrace-x86_64.h @@ -62,6 +62,12 @@ #define PT_FIX_EXEC_STACK(sp) do ; while(0) +#define pt_regs_ip(r) (r).regs.gp[RIP / sizeof(long)] +#define pt_regs_sp(r) (r).regs.gp[RSP / sizeof(long)] + +#define ptrace_ip(r) (r)->regs[RIP / sizeof(long)] +#define ptrace_sp(r) (r)->regs[RSP / sizeof(long)] + #define profile_pc(regs) PT_REGS_IP(regs) static inline int ptrace_get_thread_area(struct task_struct *child, int idx, diff --git a/include/asm-x86/ptrace.h b/include/asm-x86/ptrace.h index 51ddb25..229b5b2 100644 --- a/include/asm-x86/ptrace.h +++ b/include/asm-x86/ptrace.h @@ -2,6 +2,7 @@ #define _ASM_X86_PTRACE_H #include <linux/compiler.h> /* For __user */ +#include <asm/user.h> #include <asm/ptrace-abi.h> #ifndef __ASSEMBLY__ @@ -64,6 +65,22 @@ static inline int v8086_mode(struct pt_regs *regs) #define regs_return_value(regs) ((regs)->eax) extern unsigned long profile_pc(struct pt_regs *regs); + +struct user_regs { + unsigned long regs[FRAME_SIZE]; +}; + +#define pt_regs_ip(r) (r).eip +#define pt_regs_sp(r) (r).esp + +#define ptrace_ip(r) (r)->regs[EIP] +#define ptrace_sp(r) (r)->regs[UESP] + +extern int copyin_user_regs(struct user_regs *to, unsigned long __user *from); +extern int ptrace_to_pt_regs(struct pt_regs *regs, struct user_regs *ptrace); +extern int pt_regs_to_ptrace(unsigned long __user *ptrace, + struct pt_regs *regs); + #endif /* __KERNEL__ */ #else /* __i386__ */ @@ -135,6 +152,40 @@ enum { EF_VIP = 0x00100000, /* virtual interrupt pending */ EF_ID = 0x00200000, /* id */ }; + +#ifdef CONFIG_IA32_EMULATION +#define MAX_REG32_NR 17 + +#define EIP 12 +#define UESP 15 + +#define ptrace_ip32(regs) (unsigned long) (regs)[EIP] +#define ptrace_sp32(regs) (unsigned long) (regs)[UESP] + +#endif + +#define MAX_REG_NR (sizeof(struct user_regs_struct) / sizeof(long)) + +struct user_regs { + union { + unsigned long regs64[MAX_REG_NR]; +#ifdef CONFIG_IA32_EMULATION + u32 regs32[MAX_REG32_NR]; +#endif + } u; +}; + +#define pt_regs_ip(regs) (regs).rip +#define pt_regs_sp(regs) (regs).rsp + +extern unsigned long ptrace_ip(struct user_regs *regs); +extern unsigned long ptrace_sp(struct user_regs *regs); + +extern int copyin_user_regs(struct user_regs *to, unsigned long __user *from); +extern int ptrace_to_pt_regs(struct pt_regs *regs, struct user_regs *ptrace); +extern int pt_regs_to_ptrace(unsigned long __user *ptrace, + struct pt_regs *regs); + #endif /* __KERNEL__ */ #endif /* !__i386__ */ #endif /* !__ASSEMBLY__ */ diff --git a/include/asm-x86/unistd_32.h b/include/asm-x86/unistd_32.h index 9b15545..3477555 100644 --- a/include/asm-x86/unistd_32.h +++ b/include/asm-x86/unistd_32.h @@ -330,10 +330,12 @@ #define __NR_timerfd 322 #define __NR_eventfd 323 #define __NR_fallocate 324 +#define __NR_new_mm 325 +#define __NR_switch_mm 326 #ifdef __KERNEL__ -#define NR_syscalls 325 +#define NR_syscalls 327 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/include/asm-x86/unistd_64.h b/include/asm-x86/unistd_64.h index 5ff4d3e..baf4c0c 100644 --- a/include/asm-x86/unistd_64.h +++ b/include/asm-x86/unistd_64.h @@ -635,6 +635,10 @@ __SYSCALL(__NR_timerfd, sys_timerfd) __SYSCALL(__NR_eventfd, sys_eventfd) #define __NR_fallocate 285 __SYSCALL(__NR_fallocate, sys_fallocate) +#define __NR_new_mm 286 +__SYSCALL(__NR_new_mm, sys_new_mm) +#define __NR_switch_mm 287 +__SYSCALL(__NR_switch_mm, stub_switch_mm) #ifndef __NO_STUBS #define __ARCH_WANT_OLD_READDIR diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index 3ea5750..6758e86 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -21,6 +21,8 @@ #define PTRACE_SYSCALL 24 +#define PTRACE_SWITCH_MM 33 + /* 0x4200-0x4300 are reserved for architecture-independent additions. */ #define PTRACE_SETOPTIONS 0x4200 #define PTRACE_GETEVENTMSG 0x4201 diff --git a/include/linux/sched.h b/include/linux/sched.h index cc14656..9d11cca 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1652,6 +1652,7 @@ static inline int sas_ss_flags(unsigned long sp) * Routines for handling mm_structs */ extern struct mm_struct * mm_alloc(void); +extern struct mm_struct *dup_mm(struct task_struct *tsk); /* mmdrop drops the mm and the page tables */ extern void FASTCALL(__mmdrop(struct mm_struct *)); diff --git a/kernel/fork.c b/kernel/fork.c index 8dd8ff2..bd9afde 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -491,7 +491,7 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm) * Allocate a new mm structure and copy contents from the * mm structure of the passed in task structure. */ -static struct mm_struct *dup_mm(struct task_struct *tsk) +struct mm_struct *dup_mm(struct task_struct *tsk) { struct mm_struct *mm, *oldmm = current->mm; int err; diff --git a/kernel/ptrace.c b/kernel/ptrace.c index c25db86..71f6549 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -366,6 +366,23 @@ static int ptrace_setsiginfo(struct task_struct *child, siginfo_t __user * data) return error; } +extern struct mm_struct *fd_to_mm(int fd); +extern void do_switch(struct task_struct *task, struct mm_struct *mm); + +static int ptrace_switch_mm(struct task_struct *child, int mm_fd) +{ + struct mm_struct *new = fd_to_mm(mm_fd); + + if (IS_ERR(new)) + return PTR_ERR(new); + + do_switch(child, new); + + mmput(new); + + return 0; +} + int ptrace_request(struct task_struct *child, long request, long addr, long data) { @@ -390,6 +407,9 @@ int ptrace_request(struct task_struct *child, long request, case PTRACE_DETACH: /* detach a process that was attached. */ ret = ptrace_detach(child, data); break; + case PTRACE_SWITCH_MM: + ret = ptrace_switch_mm(child, data); + break; default: break; } diff --git a/mm/Makefile b/mm/Makefile index 5c0b0ea..9351c4e 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -4,8 +4,8 @@ mmu-y := nommu.o mmu-$(CONFIG_MMU) := fremap.o highmem.o madvise.o memory.o mincore.o \ - mlock.o mmap.o mprotect.o mremap.o msync.o rmap.o \ - vmalloc.o + mlock.o mmap.o mmfs.o mprotect.o mremap.o msync.o \ + rmap.o vmalloc.o obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \ page_alloc.o page-writeback.o pdflush.o \ ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ _______________________________________________ User-mode-linux-user mailing list User-mode-linux-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/user-mode-linux-user