[RFC] PATCH 4/4 - Time virtualization : UML support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add UML support for time namespaces.  We call unshare(CLONE_TIME) to create
the new namespace, set gettimeofday to run untraced, and make settimeofday
call the host's settimeofday to update the namespace offset rather than
maintaining the offset locally.

Index: linux-2.6.17-mm-vtime/arch/um/os-Linux/skas/process.c
===================================================================
--- linux-2.6.17-mm-vtime.orig/arch/um/os-Linux/skas/process.c	2006-04-13 13:48:01.000000000 -0400
+++ linux-2.6.17-mm-vtime/arch/um/os-Linux/skas/process.c	2006-04-13 13:50:34.000000000 -0400
@@ -17,6 +17,7 @@
 #include <sys/time.h>
 #include <asm/unistd.h>
 #include <asm/types.h>
+#include <asm/bitops.h>
 #include "user.h"
 #include "sysdep/ptrace.h"
 #include "user_util.h"
@@ -209,11 +210,16 @@ static int userspace_tramp(void *stack)
 #define NR_CPUS 1
 int userspace_pid[NR_CPUS];
 
+#ifndef PTRACE_SYSCALL_MASK
+#define PTRACE_SYSCALL_MASK	  27
+#endif
+
 int start_userspace(unsigned long stub_stack)
 {
 	void *stack;
 	unsigned long sp;
 	int pid, status, n, flags;
+	char mask[(KERNEL_NR_SYSCALLS + 7) / 8];
 
 	stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
 		     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
@@ -242,6 +248,12 @@ int start_userspace(unsigned long stub_s
 		panic("start_userspace : PTRACE_OLDSETOPTIONS failed, errno=%d\n",
 		      errno);
 
+	memset(mask, 0xff, sizeof(mask));
+	clear_bit(__NR_gettimeofday, mask);
+	if(ptrace(PTRACE_SYSCALL_MASK, pid, mask, sizeof(mask)) < 0)
+		panic("start_userspace : PTRACE_SYSCALL_MASK failed, "
+		      "errno = %d\n", errno);
+
 	if(munmap(stack, PAGE_SIZE) < 0)
 		panic("start_userspace : munmap failed, errno = %d\n", errno);
 
@@ -321,6 +333,7 @@ int copy_context_skas0(unsigned long new
 	struct stub_data *child_data = (struct stub_data *) new_stack;
 	__u64 new_offset;
 	int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset);
+	char mask[(KERNEL_NR_SYSCALLS + 7) / 8];
 
 	/* prepare offset and fd of child's stack as argument for parent's
 	 * and child's mmap2 calls
@@ -377,6 +390,12 @@ int copy_context_skas0(unsigned long new
 		panic("copy_context_skas0 : PTRACE_OLDSETOPTIONS failed, "
 		      "errno = %d\n", errno);
 
+	memset(mask, 0xff, sizeof(mask));
+	clear_bit(__NR_gettimeofday, mask);
+	if(ptrace(PTRACE_SYSCALL_MASK, pid, mask, sizeof(mask)) < 0)
+		panic("start_userspace : PTRACE_SYSCALL_MASK failed, "
+		      "errno = %d\n", errno);
+
 	return pid;
 }
 
@@ -492,11 +511,18 @@ static void (*cb_proc)(void *arg);
 static void *cb_arg;
 static sigjmp_buf *cb_back;
 
+#ifndef CLONE_TIME
+#define CLONE_TIME		0x04000000
+#endif
+
 int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
 {
 	sigjmp_buf **switch_buf = switch_buf_ptr;
-	int n, enable;
+	int n, enable, err;
 
+	err = unshare(CLONE_TIME);
+	if(err)
+		panic("Couldn't create time namespace, err = %d", err);
 	set_handler(SIGWINCH, (__sighandler_t) sig_handler,
 		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
 		    SIGVTALRM, -1);
Index: linux-2.6.17-mm-vtime/arch/um/include/sysdep-i386/kernel-offsets.h
===================================================================
--- linux-2.6.17-mm-vtime.orig/arch/um/include/sysdep-i386/kernel-offsets.h	2006-04-13 13:48:01.000000000 -0400
+++ linux-2.6.17-mm-vtime/arch/um/include/sysdep-i386/kernel-offsets.h	2006-04-13 13:50:34.000000000 -0400
@@ -1,6 +1,7 @@
 #include <linux/stddef.h>
 #include <linux/sched.h>
 #include <linux/elf.h>
+#include <asm/unistd.h>
 
 #define DEFINE(sym, val) \
 	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -16,6 +17,7 @@
 void foo(void)
 {
 	OFFSET(HOST_TASK_DEBUGREGS, task_struct, thread.arch.debugregs);
+	DEFINE(KERNEL_NR_SYSCALLS, NR_syscalls);
 #ifdef CONFIG_MODE_TT
 	OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
 #endif
Index: linux-2.6.17-mm-vtime/arch/um/include/os.h
===================================================================
--- linux-2.6.17-mm-vtime.orig/arch/um/include/os.h	2006-04-13 13:48:01.000000000 -0400
+++ linux-2.6.17-mm-vtime/arch/um/include/os.h	2006-04-13 13:50:34.000000000 -0400
@@ -281,6 +281,7 @@ extern void disable_timer(void);
 extern void user_time_init(void);
 extern void uml_idle_timer(void);
 extern unsigned long long os_nsecs(void);
+extern int os_set_time(unsigned long long nsecs);
 
 /* skas/mem.c */
 extern long run_syscall_stub(struct mm_id * mm_idp,
Index: linux-2.6.17-mm-vtime/arch/um/kernel/time.c
===================================================================
--- linux-2.6.17-mm-vtime.orig/arch/um/kernel/time.c	2006-04-13 13:48:01.000000000 -0400
+++ linux-2.6.17-mm-vtime/arch/um/kernel/time.c	2006-04-13 13:50:50.000000000 -0400
@@ -129,7 +129,7 @@ void do_gettimeofday(struct timeval *tv)
 	clock_was_set();
 }
 
-int do_settimeofday(struct timespec *tv)
+int do_settimeofday()
 {
 	struct timeval now;
 	unsigned long flags;
@@ -138,15 +138,7 @@ int do_settimeofday(struct timespec *tv)
 	if ((unsigned long) tv->tv_nsec >= UM_NSEC_PER_SEC)
 		return -EINVAL;
 
-	tv_in.tv_sec = tv->tv_sec;
-	tv_in.tv_usec = tv->tv_nsec / 1000;
-
-	flags = time_lock();
-	gettimeofday(&now, NULL);
-	timersub(&tv_in, &now, &local_offset);
-	time_unlock(flags);
-
-	return(0);
+	return os_set_time(tv);
 }
 
 void idle_sleep(int secs)
Index: linux-2.6.17-mm-vtime/arch/um/kernel/time_kern.c
===================================================================
--- linux-2.6.17-mm-vtime.orig/arch/um/kernel/time_kern.c	2006-04-13 13:48:01.000000000 -0400
+++ linux-2.6.17-mm-vtime/arch/um/kernel/time_kern.c	2006-04-13 13:50:34.000000000 -0400
@@ -151,19 +151,6 @@ void do_gettimeofday(struct timeval *tv)
 	tv->tv_usec = (unsigned long) nsecs / NSEC_PER_USEC;
 }
 
-static inline void set_time(unsigned long long nsecs)
-{
-	unsigned long long now;
-	unsigned long flags;
-
-	spin_lock_irqsave(&timer_spinlock, flags);
-	now = os_nsecs();
-	local_offset = nsecs - now;
-	spin_unlock_irqrestore(&timer_spinlock, flags);
-
-	clock_was_set();
-}
-
 long um_stime(int __user *tptr)
 {
 	int value;
@@ -171,16 +158,12 @@ long um_stime(int __user *tptr)
 	if (get_user(value, tptr))
                 return -EFAULT;
 
-	set_time((unsigned long long) value * NSEC_PER_SEC);
-
-	return 0;
+	return os_set_time((unsigned long long) value * NSEC_PER_SEC);
 }
 
 int do_settimeofday(struct timespec *tv)
 {
-	set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec);
-
-	return 0;
+	return os_set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec);
 }
 
 void timer_handler(int sig, union uml_pt_regs *regs)
Index: linux-2.6.17-mm-vtime/arch/um/os-Linux/time.c
===================================================================
--- linux-2.6.17-mm-vtime.orig/arch/um/os-Linux/time.c	2006-04-13 13:48:01.000000000 -0400
+++ linux-2.6.17-mm-vtime/arch/um/os-Linux/time.c	2006-04-13 13:50:34.000000000 -0400
@@ -126,3 +126,21 @@ void user_time_init(void)
 		    SIGVTALRM, SIGUSR2, -1);
 	set_interval(ITIMER_VIRTUAL);
 }
+
+#define NSEC_PER_USEC 1000
+#define NSEC_PER_SEC (1000000 * NSEC_PER_USEC)
+
+int os_set_time(unsigned long long nsecs)
+{
+	struct timeval tv;
+	int err;
+
+	tv.tv_sec = nsecs / NSEC_PER_SEC;
+	nsecs -= tv.tv_sec * NSEC_PER_SEC;
+	tv.tv_usec = (unsigned long) nsecs / NSEC_PER_USEC;
+
+	err = settimeofday(&tv, NULL);
+	if(err)
+		return -errno;
+	return 0;
+}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux