Skip to contentSkip to conversation

SKAS4 - Host get_mm and switch_mm

RFC PATCH In review Jeff Dike 1 participant 1 message Jan 9, 2008

Subsystems (7)
lore
Share & tools
lore

Jeff Dike

author
#0 lore raw

RFC PATCH 6/9 SKAS4 - Host get_mm and switch_mm

This is the new_mm, switch_mm, and /proc/<pid>/mm implementation for 32- and 64-bit x86 and UML.

include/asm-x86/unistd_32.h +3 -1
Index: linux-2.6-skas4/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
include/asm-x86/unistd_64.h +4 -0
Index: linux-2.6-skas4/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
include/linux/ptrace.h +2 -0
Index: linux-2.6-skas4/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
include/linux/sched.h +1 -0
Index: linux-2.6-skas4/include/linux/sched.h
===================================================================
@@ -1665,6 +1665,7 @@ static inline int sas_ss_flags(unsigned 
  * 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 *));
kernel/Makefile +1 -1
Index: linux-2.6-skas4/kernel/Makefile
===================================================================
@@ -3,7 +3,7 @@
 #
 
 obj-y     = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
-	    exit.o itimer.o time.o softirq.o resource.o \
+	    exit.o itimer.o time.o softirq.o resource.o mmfs.o \
 	    sysctl.o capability.o ptrace.o timer.o user.o user_namespace.o \
 	    signal.o sys.o kmod.o workqueue.o pid.o \
 	    rcupdate.o extable.o params.o posix-timers.o \
kernel/fork.c +1 -1
Index: linux-2.6-skas4/kernel/fork.c
===================================================================
@@ -491,7 +491,7 @@ void mm_release(struct task_struct *tsk,
  * 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;
kernel/mmfs.c new file +378 -0

378 lines not on this page · raw message

kernel/ptrace.c +26 -0
Index: linux-2.6-skas4/kernel/ptrace.c
===================================================================
@@ -366,6 +366,29 @@ static int ptrace_setsiginfo(struct task
 	return error;
 }
 
+extern struct mm_struct *fd_to_mm(int fd);
+
+static int ptrace_switch_mm(struct task_struct *child, int mm_fd)
+{
+	struct mm_struct *old = child->mm;
+	struct mm_struct *new = fd_to_mm(mm_fd);
+
+	if (IS_ERR(new))
+		return PTR_ERR(new);
+
+	task_lock(child);
+
+	atomic_inc(&new->mm_users);
+
+	child->mm = new;
+	child->active_mm = new;
+
+	task_unlock(child);
+	mmput(old);
+
+	return 0;
+}
+
 int ptrace_request(struct task_struct *child, long request,
 		   long addr, long data)
 {
@@ -390,6 +413,9 @@ int ptrace_request(struct task_struct *c
 	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;
 	}
arch/x86/kernel/entry_64.S +1 -0
Index: linux-2.6-skas4/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
arch/x86/kernel/ptrace_32.c +3 -3
Index: linux-2.6-skas4/arch/x86/kernel/ptrace_32.c
===================================================================
@@ -83,8 +83,8 @@ static inline int put_stack_long(struct 
 	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 *ch
 	return 0;
 }
 
-static unsigned long getreg(struct task_struct *child,
+unsigned long getreg(struct task_struct *child,
 	unsigned long regno)
 {
 	unsigned long retval = ~0UL;
arch/x86/kernel/ptrace_64.c +2 -2
Index: linux-2.6-skas4/arch/x86/kernel/ptrace_64.c
===================================================================
@@ -226,7 +226,7 @@ void ptrace_disable(struct task_struct *
 	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 *ch
 	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) {
arch/x86/kernel/sys_i386_32.c +9 -0
Index: linux-2.6-skas4/arch/x86/kernel/sys_i386_32.c
===================================================================
@@ -261,3 +261,12 @@ int kernel_execve(const char *filename, 
 	: "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, &regs);
+}
arch/x86/kernel/sys_x86_64.c +9 -0
Index: linux-2.6-skas4/arch/x86/kernel/sys_x86_64.c
===================================================================
@@ -153,3 +153,12 @@ asmlinkage long sys_uname(struct new_uts
 		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);
+}
arch/x86/kernel/syscall_table_32.S +2 -0
Index: linux-2.6-skas4/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
fs/proc/base.c +29 -0
Index: linux-2.6-skas4/fs/proc/base.c
===================================================================
@@ -2187,6 +2187,34 @@ static int proc_pid_io_accounting(struct
 }
 #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_
 #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,
arch/um/sys-x86_64/syscalls.c +8 -0
Index: linux-2.6-skas4/arch/um/sys-x86_64/syscalls.c
===================================================================
@@ -112,3 +112,11 @@ void arch_switch_to(struct task_struct *
 
 	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, &current->thread.regs);
+}
arch/um/sys-i386/syscalls.c +8 -0
Index: linux-2.6-skas4/arch/um/sys-i386/syscalls.c
===================================================================
@@ -200,3 +200,11 @@ long sys_sigaction(int sig, const struct
 
 	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, &current->thread.regs);
+}
arch/um/include/skas_ptrace.h +3 -1
Index: linux-2.6-skas4/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"
 
arch/um/kernel/ptrace.c +1 -1
Index: linux-2.6-skas4/arch/um/kernel/ptrace.c
===================================================================
@@ -192,7 +192,7 @@ long arch_ptrace(struct task_struct *chi
 	}
 #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);
 
arch/um/os-Linux/skas/process.c +1 -1
Index: linux-2.6-skas4/arch/um/os-Linux/skas/process.c
===================================================================
@@ -731,7 +731,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, "

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace
_______________________________________________
User-mode-linux-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel