From c0a18111e571138747a98af18b3a2124df56a0d1 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 6 May 2008 17:09:27 -0700 Subject: Revert "uml: fix gcc problem" This reverts commit 22eecde2f9034764a3fd095eecfa3adfb8ec9a98. Uli reports that it breaks UML on x86-64 with the Fedora 8 gcc (gcc 4.1.2), causing a crash on startup. See http://marc.info/?l=linux-kernel&m=121011722806093&w=2 for a trace. Reported-by: Ulrich Drepper Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/Makefile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'arch/um') diff --git a/arch/um/Makefile b/arch/um/Makefile index 01b97c19a8ba..dbeab15e7bb7 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -77,10 +77,7 @@ include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS) KERNEL_DEFINES = $(strip -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \ -Dmktime=kernel_mktime $(ARCH_KERNEL_DEFINES)) KBUILD_CFLAGS += $(KERNEL_DEFINES) -# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use -# a lot more stack due to the lack of sharing of stacklots: -KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then \ - echo $(call cc-option,-fno-unit-at-a-time); fi ;) +KBUILD_CFLAGS += $(call cc-option,-fno-unit-at-a-time,) PHONY += linux -- cgit v1.2.2 From 3168cb98be7199325de633052680098660ccaf84 Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Tue, 6 May 2008 20:42:33 -0700 Subject: uml: fix inconsistence due to tty_operation change 'put_char' of 'struct tty_operations' has changed from 'void' into 'int'. This can also shut up compiler warnings. Cc: Jeff Dike Signed-off-by: WANG Cong Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/line.c | 4 ++-- arch/um/include/line.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/um') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 10b86e1cc659..5047490fc299 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -191,9 +191,9 @@ void line_flush_chars(struct tty_struct *tty) line_flush_buffer(tty); } -void line_put_char(struct tty_struct *tty, unsigned char ch) +int line_put_char(struct tty_struct *tty, unsigned char ch) { - line_write(tty, &ch, sizeof(ch)); + return line_write(tty, &ch, sizeof(ch)); } int line_write(struct tty_struct *tty, const unsigned char *buf, int len) diff --git a/arch/um/include/line.h b/arch/um/include/line.h index 1223f2c844b4..979b73e6352d 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -71,7 +71,7 @@ extern int line_setup(struct line *lines, unsigned int sizeof_lines, char *init, char **error_out); extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len); -extern void line_put_char(struct tty_struct *tty, unsigned char ch); +extern int line_put_char(struct tty_struct *tty, unsigned char ch); extern void line_set_termios(struct tty_struct *tty, struct ktermios * old); extern int line_chars_in_buffer(struct tty_struct *tty); extern void line_flush_buffer(struct tty_struct *tty); -- cgit v1.2.2 From 53c258787427ea43ebfa76fefa6534cae507e521 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:47 -0700 Subject: uml: redo host capability detection and disabling Redo how host capabilities are recorded at startup and disabled on the command line. There are now explicit variables saying what's been disabled by the command line rather than the implicitness of the have_* variable being zero. The capability variables now start at zero and are set to one as their capabilities are found to be present on the host. Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/start_up.c | 81 +++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 40 deletions(-) (limited to 'arch/um') diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 997d01944f91..b4b36e0f2e89 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -23,6 +23,7 @@ #include "mem_user.h" #include "ptrace_user.h" #include "registers.h" +#include "skas.h" #include "skas_ptrace.h" static void ptrace_child(void) @@ -140,14 +141,27 @@ static int stop_ptraced_child(int pid, int exitcode, int mustexit) } /* Changed only during early boot */ -int ptrace_faultinfo = 1; -int ptrace_ldt = 1; -int proc_mm = 1; -int skas_needs_stub = 0; +int ptrace_faultinfo; +static int disable_ptrace_faultinfo; + +int ptrace_ldt; +static int disable_ptrace_ldt; + +int proc_mm; +static int disable_proc_mm; + +int have_switch_mm; +static int disable_switch_mm; + +int skas_needs_stub; static int __init skas0_cmd_param(char *str, int* add) { - ptrace_faultinfo = proc_mm = 0; + disable_ptrace_faultinfo = 1; + disable_ptrace_ldt = 1; + disable_proc_mm = 1; + disable_switch_mm = 1; + return 0; } @@ -157,15 +171,12 @@ static int __init mode_skas0_cmd_param(char *str, int* add) __attribute__((alias("skas0_cmd_param"))); __uml_setup("skas0", skas0_cmd_param, - "skas0\n" - " Disables SKAS3 usage, so that SKAS0 is used, unless \n" - " you specify mode=tt.\n\n"); +"skas0\n" +" Disables SKAS3 and SKAS4 usage, so that SKAS0 is used\n\n"); __uml_setup("mode=skas0", mode_skas0_cmd_param, - "mode=skas0\n" - " Disables SKAS3 usage, so that SKAS0 is used, unless you \n" - " specify mode=tt. Note that this was recently added - on \n" - " older kernels you must use simply \"skas0\".\n\n"); +"mode=skas0\n" +" Disables SKAS3 and SKAS4 usage, so that SKAS0 is used.\n\n"); /* Changed only during early boot */ static int force_sysemu_disabled = 0; @@ -360,7 +371,7 @@ void __init os_early_checks(void) static int __init noprocmm_cmd_param(char *str, int* add) { - proc_mm = 0; + disable_proc_mm = 1; return 0; } @@ -372,7 +383,7 @@ __uml_setup("noprocmm", noprocmm_cmd_param, static int __init noptracefaultinfo_cmd_param(char *str, int* add) { - ptrace_faultinfo = 0; + disable_ptrace_faultinfo = 1; return 0; } @@ -384,7 +395,7 @@ __uml_setup("noptracefaultinfo", noptracefaultinfo_cmd_param, static int __init noptraceldt_cmd_param(char *str, int* add) { - ptrace_ldt = 0; + disable_ptrace_ldt = 1; return 0; } @@ -404,17 +415,15 @@ static inline void check_skas3_ptrace_faultinfo(void) n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); if (n < 0) { - ptrace_faultinfo = 0; if (errno == EIO) non_fatal("not found\n"); else perror("not found"); - } + } else if (disable_ptrace_faultinfo) + non_fatal("found but disabled on command line\n"); else { - if (!ptrace_faultinfo) - non_fatal("found but disabled on command line\n"); - else - non_fatal("found\n"); + ptrace_faultinfo = 1; + non_fatal("found\n"); } stop_ptraced_child(pid, 1, 1); @@ -437,38 +446,30 @@ static inline void check_skas3_ptrace_ldt(void) if (n < 0) { if (errno == EIO) non_fatal("not found\n"); - else { + else perror("not found"); - } - ptrace_ldt = 0; - } + } else if (disable_ptrace_ldt) + non_fatal("found, but use is disabled\n"); else { - if (ptrace_ldt) - non_fatal("found\n"); - else - non_fatal("found, but use is disabled\n"); + ptrace_ldt = 1; + non_fatal("found\n"); } stop_ptraced_child(pid, 1, 1); -#else - /* PTRACE_LDT might be disabled via cmdline option. - * We want to override this, else we might use the stub - * without real need - */ - ptrace_ldt = 1; #endif } static inline void check_skas3_proc_mm(void) { non_fatal(" - /proc/mm..."); - if (access("/proc/mm", W_OK) < 0) { - proc_mm = 0; + if (access("/proc/mm", W_OK) < 0) perror("not found"); - } - else if (!proc_mm) + else if (disable_proc_mm) non_fatal("found but disabled on command line\n"); - else non_fatal("found\n"); + else { + proc_mm = 1; + non_fatal("found\n"); + } } void can_do_skas(void) -- cgit v1.2.2 From 96cee3044dca2e6510ca7cc276d1eac34a1cfd51 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:48 -0700 Subject: uml: style fixes A few random style fixes. Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/skas_ptrace.h | 13 +------------ arch/um/include/sysdep-i386/sigcontext.h | 2 +- arch/um/kernel/um_arch.c | 2 +- arch/um/os-Linux/skas/process.c | 2 +- 4 files changed, 4 insertions(+), 15 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/skas_ptrace.h b/arch/um/include/skas_ptrace.h index cd2327d09c8d..3d31bbacd016 100644 --- a/arch/um/include/skas_ptrace.h +++ b/arch/um/include/skas_ptrace.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -12,14 +12,3 @@ #include "sysdep/skas_ptrace.h" #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 - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/include/sysdep-i386/sigcontext.h b/arch/um/include/sysdep-i386/sigcontext.h index 67e77122aa45..f583c87111a0 100644 --- a/arch/um/include/sysdep-i386/sigcontext.h +++ b/arch/um/include/sysdep-i386/sigcontext.h @@ -10,7 +10,7 @@ #define IP_RESTART_SYSCALL(ip) ((ip) -= 2) -#define GET_FAULTINFO_FROM_SC(fi,sc) \ +#define GET_FAULTINFO_FROM_SC(fi, sc) \ { \ (fi).cr2 = SC_CR2(sc); \ (fi).error_code = SC_ERR(sc); \ diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 56deed623446..82058ac7d481 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -150,7 +150,7 @@ __uml_setup("root=", uml_root_setup, static int __init no_skas_debug_setup(char *line, int *add) { printf("'debug' is not necessary to gdb UML in skas mode - run \n"); - printf("'gdb linux'"); + printf("'gdb linux'\n"); return 0; } diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 1e8cba6550a9..6be028ca1817 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -442,7 +442,7 @@ void userspace(struct uml_pt_regs *regs) unblock_signals(); break; default: - printk(UM_KERN_ERR "userspace - child stopped " + printk(UM_KERN_ERR "userspace - child stopped " "with signal %d\n", sig); fatal_sigsegv(); } -- cgit v1.2.2 From 47906dd9e63ba1a8cb188e9e786c5928674fbbd3 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:50 -0700 Subject: uml: tidy ptrace interface Tidy the ptrace interface code. Removed a bunch of unused macros. Started converting register sets from arrays of longs to structures. Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/sysdep-i386/ptrace_user.h | 30 +---------------------------- arch/um/include/sysdep-x86_64/ptrace_user.h | 17 ++++------------ arch/um/os-Linux/sys-i386/registers.c | 5 +++-- arch/um/sys-i386/ptrace.c | 30 ++++++++++++++--------------- arch/um/sys-i386/user-offsets.c | 2 +- arch/um/sys-x86_64/user-offsets.c | 1 - 6 files changed, 23 insertions(+), 62 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/sysdep-i386/ptrace_user.h b/arch/um/include/sysdep-i386/ptrace_user.h index 75650723c38f..ef56247e4143 100644 --- a/arch/um/include/sysdep-i386/ptrace_user.h +++ b/arch/um/include/sysdep-i386/ptrace_user.h @@ -41,38 +41,10 @@ #define PT_SP_OFFSET PT_OFFSET(UESP) #define PT_SP(regs) ((regs)[UESP]) -#define FP_SIZE ((HOST_XFP_SIZE > HOST_FP_SIZE) ? HOST_XFP_SIZE : HOST_FP_SIZE) +#define FP_SIZE ((HOST_FPX_SIZE > HOST_FP_SIZE) ? HOST_FPX_SIZE : HOST_FP_SIZE) #ifndef FRAME_SIZE #define FRAME_SIZE (17) #endif -#define FRAME_SIZE_OFFSET (FRAME_SIZE * sizeof(unsigned long)) - -#define FP_FRAME_SIZE (27) -#define FPX_FRAME_SIZE (128) - -#ifdef PTRACE_GETREGS -#define UM_HAVE_GETREGS -#endif - -#ifdef PTRACE_SETREGS -#define UM_HAVE_SETREGS -#endif - -#ifdef PTRACE_GETFPREGS -#define UM_HAVE_GETFPREGS -#endif - -#ifdef PTRACE_SETFPREGS -#define UM_HAVE_SETFPREGS -#endif - -#ifdef PTRACE_GETFPXREGS -#define UM_HAVE_GETFPXREGS -#endif - -#ifdef PTRACE_SETFPXREGS -#define UM_HAVE_SETFPXREGS -#endif #endif diff --git a/arch/um/include/sysdep-x86_64/ptrace_user.h b/arch/um/include/sysdep-x86_64/ptrace_user.h index 45c0bd881cb3..4dbccdb58f48 100644 --- a/arch/um/include/sysdep-x86_64/ptrace_user.h +++ b/arch/um/include/sysdep-x86_64/ptrace_user.h @@ -48,7 +48,8 @@ #define PT_ORIG_RAX_OFFSET (ORIG_RAX) #define PT_ORIG_RAX(regs) ((regs)[PT_INDEX(ORIG_RAX)]) -/* x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though +/* + * x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though * it's defined in the kernel's include/linux/ptrace.h. Additionally, use the * 2.4 name and value for 2.4 host compatibility. */ @@ -56,7 +57,8 @@ #define PTRACE_OLDSETOPTIONS 21 #endif -/* These are before the system call, so the system call number is RAX +/* + * These are before the system call, so the system call number is RAX * rather than ORIG_RAX, and arg4 is R10 rather than RCX */ #define REGS_SYSCALL_NR PT_INDEX(RAX) @@ -73,14 +75,3 @@ #define FP_SIZE (HOST_FP_SIZE) #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 - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c index b613473b3ec1..c6183e7aec3d 100644 --- a/arch/um/os-Linux/sys-i386/registers.c +++ b/arch/um/os-Linux/sys-i386/registers.c @@ -5,6 +5,7 @@ */ #include +#include #include "kern_constants.h" #include "longjmp.h" #include "user.h" @@ -74,10 +75,10 @@ int put_fp_registers(int pid, unsigned long *regs) void arch_init_registers(int pid) { - unsigned long fpx_regs[HOST_XFP_SIZE]; + struct user_fxsr_struct fpx_regs; int err; - err = ptrace(PTRACE_GETFPXREGS, pid, 0, fpx_regs); + err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs); if (!err) return; diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c index 6b4499906a6c..c9b176534d65 100644 --- a/arch/um/sys-i386/ptrace.c +++ b/arch/um/sys-i386/ptrace.c @@ -148,14 +148,13 @@ int peek_user(struct task_struct *child, long addr, long data) int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) { int err, n, cpu = ((struct thread_info *) child->stack)->cpu; - long fpregs[HOST_FP_SIZE]; + struct user_i387_struct fpregs; - BUG_ON(sizeof(*buf) != sizeof(fpregs)); - err = save_fp_registers(userspace_pid[cpu], fpregs); + err = save_fp_registers(userspace_pid[cpu], (unsigned long *) &fpregs); if (err) return err; - n = copy_to_user(buf, fpregs, sizeof(fpregs)); + n = copy_to_user(buf, &fpregs, sizeof(fpregs)); if(n > 0) return -EFAULT; @@ -165,27 +164,26 @@ int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) { int n, cpu = ((struct thread_info *) child->stack)->cpu; - long fpregs[HOST_FP_SIZE]; + struct user_i387_struct fpregs; - BUG_ON(sizeof(*buf) != sizeof(fpregs)); - n = copy_from_user(fpregs, buf, sizeof(fpregs)); + n = copy_from_user(&fpregs, buf, sizeof(fpregs)); if (n > 0) return -EFAULT; - return restore_fp_registers(userspace_pid[cpu], fpregs); + return restore_fp_registers(userspace_pid[cpu], + (unsigned long *) &fpregs); } int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) { int err, n, cpu = ((struct thread_info *) child->stack)->cpu; - long fpregs[HOST_XFP_SIZE]; + struct user_fxsr_struct fpregs; - BUG_ON(sizeof(*buf) != sizeof(fpregs)); - err = save_fpx_registers(userspace_pid[cpu], fpregs); + err = save_fpx_registers(userspace_pid[cpu], (unsigned long *) &fpregs); if (err) return err; - n = copy_to_user(buf, fpregs, sizeof(fpregs)); + n = copy_to_user(buf, &fpregs, sizeof(fpregs)); if(n > 0) return -EFAULT; @@ -195,14 +193,14 @@ int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) { int n, cpu = ((struct thread_info *) child->stack)->cpu; - long fpregs[HOST_XFP_SIZE]; + struct user_fxsr_struct fpregs; - BUG_ON(sizeof(*buf) != sizeof(fpregs)); - n = copy_from_user(fpregs, buf, sizeof(fpregs)); + n = copy_from_user(&fpregs, buf, sizeof(fpregs)); if (n > 0) return -EFAULT; - return restore_fpx_registers(userspace_pid[cpu], fpregs); + return restore_fpx_registers(userspace_pid[cpu], + (unsigned long *) &fpregs); } long subarch_ptrace(struct task_struct *child, long request, long addr, diff --git a/arch/um/sys-i386/user-offsets.c b/arch/um/sys-i386/user-offsets.c index 39bd32bf84f0..5f883bfe773f 100644 --- a/arch/um/sys-i386/user-offsets.c +++ b/arch/um/sys-i386/user-offsets.c @@ -22,7 +22,7 @@ void foo(void) OFFSET(HOST_SC_CR2, sigcontext, cr2); DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_fpregs_struct)); - DEFINE_LONGS(HOST_XFP_SIZE, sizeof(struct user_fpxregs_struct)); + DEFINE_LONGS(HOST_FPX_SIZE, sizeof(struct user_fpxregs_struct)); DEFINE(HOST_IP, EIP); DEFINE(HOST_SP, UESP); diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c index 2f3443c6e859..973585414a66 100644 --- a/arch/um/sys-x86_64/user-offsets.c +++ b/arch/um/sys-x86_64/user-offsets.c @@ -24,7 +24,6 @@ void foo(void) OFFSET(HOST_SC_TRAPNO, sigcontext, trapno); DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long)); - DEFINE(HOST_XFP_SIZE, 0); DEFINE_LONGS(HOST_RBX, RBX); DEFINE_LONGS(HOST_RCX, RCX); DEFINE_LONGS(HOST_RDI, RDI); -- cgit v1.2.2 From 484f1e2c1ea58c6a4352313f7ee4edd4b52deecd Mon Sep 17 00:00:00 2001 From: Johann Felix Soden Date: Mon, 12 May 2008 14:01:51 -0700 Subject: uml: fix errno return Error returns are negative. Signed-off-by: Johann Felix Soden Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/hostaudio_kern.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/um') diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index ff1b22b69e9c..368219cc2366 100644 --- a/arch/um/drivers/hostaudio_kern.c +++ b/arch/um/drivers/hostaudio_kern.c @@ -154,7 +154,7 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file, case SNDCTL_DSP_SUBDIVIDE: case SNDCTL_DSP_SETFRAGMENT: if (get_user(data, (int __user *) arg)) - return EFAULT; + return -EFAULT; break; default: break; -- cgit v1.2.2 From 43f5b3085fdd27c4edf535d938b2cb0ccead4f75 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:52 -0700 Subject: uml: fix build when SLOB is enabled Reintroduce uml_kmalloc for the benefit of UML libc code. The previous tactic of declaring __kmalloc so it could be called directly from the libc side of the house turned out to be getting too intimate with slab, and it doesn't work with slob. So, the uml_kmalloc wrapper is back. It calls kmalloc or whatever that translates into, and libc code calls it. kfree is left alone since that still works, leaving a somewhat inconsistent API. Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/chan_user.c | 1 + arch/um/drivers/cow_sys.h | 2 +- arch/um/drivers/daemon_user.c | 4 ++-- arch/um/drivers/fd.c | 2 +- arch/um/drivers/mcast_user.c | 3 ++- arch/um/drivers/net_user.c | 2 +- arch/um/drivers/port_user.c | 2 +- arch/um/drivers/pty.c | 2 +- arch/um/drivers/slip_user.c | 2 +- arch/um/drivers/tty.c | 2 +- arch/um/drivers/xterm.c | 2 +- arch/um/include/um_malloc.h | 9 +++------ arch/um/kernel/mem.c | 5 +++++ arch/um/os-Linux/drivers/ethertap_user.c | 4 ++-- arch/um/os-Linux/helper.c | 4 ++-- arch/um/os-Linux/main.c | 2 +- arch/um/os-Linux/sigio.c | 4 ++-- 17 files changed, 28 insertions(+), 24 deletions(-) (limited to 'arch/um') diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index 025764089ac8..cfeb3f4a44af 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c @@ -11,6 +11,7 @@ #include #include #include "chan_user.h" +#include "kern_constants.h" #include "os.h" #include "um_malloc.h" #include "user.h" diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h index ca8c9e11a39b..f5701fd2ef90 100644 --- a/arch/um/drivers/cow_sys.h +++ b/arch/um/drivers/cow_sys.h @@ -8,7 +8,7 @@ static inline void *cow_malloc(int size) { - return kmalloc(size, UM_GFP_KERNEL); + return uml_kmalloc(size, UM_GFP_KERNEL); } static inline void cow_free(void *ptr) diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c index f23c109a055c..f8e85e0bdace 100644 --- a/arch/um/drivers/daemon_user.c +++ b/arch/um/drivers/daemon_user.c @@ -34,7 +34,7 @@ static struct sockaddr_un *new_addr(void *name, int len) { struct sockaddr_un *sun; - sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); + sun = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); if (sun == NULL) { printk(UM_KERN_ERR "new_addr: allocation of sockaddr_un " "failed\n"); @@ -83,7 +83,7 @@ static int connect_to_switch(struct daemon_data *pri) goto out_close; } - sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); + sun = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); if (sun == NULL) { printk(UM_KERN_ERR "new_addr: allocation of sockaddr_un " "failed\n"); diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c index 0a2bb5b64b82..f5a981a16240 100644 --- a/arch/um/drivers/fd.c +++ b/arch/um/drivers/fd.c @@ -40,7 +40,7 @@ static void *fd_init(char *str, int device, const struct chan_opts *opts) return NULL; } - data = kmalloc(sizeof(*data), UM_GFP_KERNEL); + data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL); if (data == NULL) return NULL; diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c index 5f647d7a7292..ee19e91568a2 100644 --- a/arch/um/drivers/mcast_user.c +++ b/arch/um/drivers/mcast_user.c @@ -15,6 +15,7 @@ #include #include #include +#include "kern_constants.h" #include "mcast.h" #include "net_user.h" #include "um_malloc.h" @@ -24,7 +25,7 @@ static struct sockaddr_in *new_addr(char *addr, unsigned short port) { struct sockaddr_in *sin; - sin = kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL); + sin = uml_kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL); if (sin == NULL) { printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in " "failed\n"); diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c index abf2653f5517..9415dd9e63ef 100644 --- a/arch/um/drivers/net_user.c +++ b/arch/um/drivers/net_user.c @@ -222,7 +222,7 @@ static void change(char *dev, char *what, unsigned char *addr, netmask[2], netmask[3]); output_len = UM_KERN_PAGE_SIZE; - output = kmalloc(output_len, UM_GFP_KERNEL); + output = uml_kmalloc(output_len, UM_GFP_KERNEL); if (output == NULL) printk(UM_KERN_ERR "change : failed to allocate output " "buffer\n"); diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c index d269ca387f10..b49bf56a56aa 100644 --- a/arch/um/drivers/port_user.c +++ b/arch/um/drivers/port_user.c @@ -47,7 +47,7 @@ static void *port_init(char *str, int device, const struct chan_opts *opts) if (kern_data == NULL) return NULL; - data = kmalloc(sizeof(*data), UM_GFP_KERNEL); + data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL); if (data == NULL) goto err; diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c index 49c79dda6046..1113911dcb2b 100644 --- a/arch/um/drivers/pty.c +++ b/arch/um/drivers/pty.c @@ -29,7 +29,7 @@ static void *pty_chan_init(char *str, int device, const struct chan_opts *opts) { struct pty_chan *data; - data = kmalloc(sizeof(*data), UM_GFP_KERNEL); + data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL); if (data == NULL) return NULL; diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c index 8b80505a3fb0..a1c2d2c98a94 100644 --- a/arch/um/drivers/slip_user.c +++ b/arch/um/drivers/slip_user.c @@ -96,7 +96,7 @@ static int slip_tramp(char **argv, int fd) pid = err; output_len = UM_KERN_PAGE_SIZE; - output = kmalloc(output_len, UM_GFP_KERNEL); + output = uml_kmalloc(output_len, UM_GFP_KERNEL); if (output == NULL) { printk(UM_KERN_ERR "slip_tramp : failed to allocate output " "buffer\n"); diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c index c930fedc5172..495858a090e4 100644 --- a/arch/um/drivers/tty.c +++ b/arch/um/drivers/tty.c @@ -29,7 +29,7 @@ static void *tty_chan_init(char *str, int device, const struct chan_opts *opts) } str++; - data = kmalloc(sizeof(*data), UM_GFP_KERNEL); + data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL); if (data == NULL) return NULL; *data = ((struct tty_chan) { .dev = str, diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index 8a1c18a9b240..da2caa5a21ef 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c @@ -30,7 +30,7 @@ static void *xterm_init(char *str, int device, const struct chan_opts *opts) { struct xterm_chan *data; - data = kmalloc(sizeof(*data), UM_GFP_KERNEL); + data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL); if (data == NULL) return NULL; *data = ((struct xterm_chan) { .pid = -1, diff --git a/arch/um/include/um_malloc.h b/arch/um/include/um_malloc.h index 0ad17cb83d96..c554d706d106 100644 --- a/arch/um/include/um_malloc.h +++ b/arch/um/include/um_malloc.h @@ -8,15 +8,12 @@ #include "kern_constants.h" -extern void *__kmalloc(int size, int flags); -static inline void *kmalloc(int size, int flags) -{ - return __kmalloc(size, flags); -} - +extern void *uml_kmalloc(int size, int flags); extern void kfree(const void *ptr); extern void *vmalloc(unsigned long size); extern void vfree(void *ptr); #endif /* __UM_MALLOC_H__ */ + + diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 2eea1ff235e6..b0ee64622ff7 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -375,3 +375,8 @@ pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address) return pmd; } #endif + +void *uml_kmalloc(int size, int flags) +{ + return kmalloc(size, flags); +} diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c index 6fb0b174f538..cc72cb2c1af6 100644 --- a/arch/um/os-Linux/drivers/ethertap_user.c +++ b/arch/um/os-Linux/drivers/ethertap_user.c @@ -52,7 +52,7 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask, return; } - output = kmalloc(UM_KERN_PAGE_SIZE, UM_GFP_KERNEL); + output = uml_kmalloc(UM_KERN_PAGE_SIZE, UM_GFP_KERNEL); if (output == NULL) printk(UM_KERN_ERR "etap_change : Failed to allocate output " "buffer\n"); @@ -165,7 +165,7 @@ static int etap_open(void *data) err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], control_fds[1], data_fds[0], data_fds[1]); output_len = UM_KERN_PAGE_SIZE; - output = kmalloc(output_len, UM_GFP_KERNEL); + output = uml_kmalloc(output_len, UM_GFP_KERNEL); read_output(control_fds[0], output, output_len); if (output == NULL) diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index f25c29a12d00..74ca7aabf4e1 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c @@ -71,8 +71,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv) data.pre_data = pre_data; data.argv = argv; data.fd = fds[1]; - data.buf = __cant_sleep() ? kmalloc(PATH_MAX, UM_GFP_ATOMIC) : - kmalloc(PATH_MAX, UM_GFP_KERNEL); + data.buf = __cant_sleep() ? uml_kmalloc(PATH_MAX, UM_GFP_ATOMIC) : + uml_kmalloc(PATH_MAX, UM_GFP_KERNEL); pid = clone(helper_child, (void *) sp, CLONE_VM, &data); if (pid < 0) { ret = -errno; diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index abb9b0ffd960..eee69b9f52c9 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c @@ -199,7 +199,7 @@ void *__wrap_malloc(int size) return __real_malloc(size); else if (size <= UM_KERN_PAGE_SIZE) /* finding contiguous pages can be hard*/ - ret = kmalloc(size, UM_GFP_KERNEL); + ret = uml_kmalloc(size, UM_GFP_KERNEL); else ret = vmalloc(size); /* diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c index abf47a7c4abd..0578481983c4 100644 --- a/arch/um/os-Linux/sigio.c +++ b/arch/um/os-Linux/sigio.c @@ -109,7 +109,7 @@ static int need_poll(struct pollfds *polls, int n) if (n <= polls->size) return 0; - new = kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC); + new = uml_kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC); if (new == NULL) { printk(UM_KERN_ERR "need_poll : failed to allocate new " "pollfds\n"); @@ -243,7 +243,7 @@ static struct pollfd *setup_initial_poll(int fd) { struct pollfd *p; - p = kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL); + p = uml_kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL); if (p == NULL) { printk(UM_KERN_ERR "setup_initial_poll : failed to allocate " "poll\n"); -- cgit v1.2.2 From cfd28f6695d0fc047478480791a21bdd4967f98e Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:53 -0700 Subject: uml: fix bad NTP interaction with clock UML's supposed nanosecond clock interacts badly with NTP when NTP decides that the clock has drifted ahead and needs to be slowed down. Slowing down the clock is done by decrementing the cycle-to-nanosecond multiplier, which is 1. Decrementing that gives you 0 and time is stopped. This is fixed by switching to a microsecond clock, with a multiplier of 1000. Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/time.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/um') diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index 0d0cea2ac98d..c3e2f369c33c 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -75,7 +75,7 @@ static irqreturn_t um_timer(int irq, void *dev) static cycle_t itimer_read(void) { - return os_nsecs(); + return os_nsecs() / 1000; } static struct clocksource itimer_clocksource = { @@ -83,7 +83,7 @@ static struct clocksource itimer_clocksource = { .rating = 300, .read = itimer_read, .mask = CLOCKSOURCE_MASK(64), - .mult = 1, + .mult = 1000, .shift = 0, .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -- cgit v1.2.2 From 5563d722bfc73f27423fcb76240bfc1fb4284635 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:54 -0700 Subject: uml: use __SPIN_LOCK_UNLOCKED From: Robert P. J. Day Use newer, non-deprecated __SPIN_LOCK_UNLOCKED macro. Signed-off-by: Robert P. J. Day Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/line.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/line.h b/arch/um/include/line.h index 979b73e6352d..311a0d3d93af 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -58,11 +58,11 @@ struct line { }; #define LINE_INIT(str, d) \ - { .count_lock = SPIN_LOCK_UNLOCKED, \ + { .count_lock = __SPIN_LOCK_UNLOCKED((str).count_lock), \ .init_str = str, \ .init_pri = INIT_STATIC, \ .valid = 1, \ - .lock = SPIN_LOCK_UNLOCKED, \ + .lock = __SPIN_LOCK_UNLOCKED((str).lock), \ .driver = d } extern void line_close(struct tty_struct *tty, struct file * filp); -- cgit v1.2.2 From 63b9871f6ee2607f3b44e0044e145574b3f08619 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Mon, 12 May 2008 14:01:55 -0700 Subject: uml: fix CONFIG_RAW dependencies Add the BLOCK dependency for RAW_DRIVER, to match what's in drivers/char/Kconfig. Also, while we're there, update the alleged obsolesence of RAW_DRIVER since it doesn't seem to be going away any time soon. Signed-off-by: Robert P. J. Day Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/Kconfig.char | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/um') diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char index 3a4b396d7979..1b238ebae6b3 100644 --- a/arch/um/Kconfig.char +++ b/arch/um/Kconfig.char @@ -145,14 +145,14 @@ config LEGACY_PTYS systems, it is safe to say N. config RAW_DRIVER - tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)" + tristate "RAW driver (/dev/raw/rawN)" + depends on BLOCK help The raw driver permits block devices to be bound to /dev/raw/rawN. Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. See the raw(8) manpage for more details. - The raw driver is deprecated and will be removed soon. - Applications should simply open the device (eg /dev/hda1) + Applications should preferably open the device (eg /dev/hda1) with the O_DIRECT flag. config MAX_RAW_DEVS -- cgit v1.2.2 From 6d0742426c9adc7465ef5c62a99a1d3e9696ea19 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 12 May 2008 14:01:56 -0700 Subject: uml: use DIV_ROUND_UP I just saw similar patches in the janitor kernel's list, and spotted place it fits. Signed-off-by: Jiri Olsa Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/ubd_kern.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/um') diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 5e45e39a8a8d..44ad1607be2d 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -1178,8 +1178,8 @@ static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask, * by one word. Thanks to Lynn Kerby for the fix and James McMechan * for the original diagnosis. */ - if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) / - sizeof(unsigned long) - 1)) + if (*cow_offset == (DIV_ROUND_UP(bitmap_len, + sizeof(unsigned long)) - 1)) (*cow_offset)--; bitmap_words[0] = bitmap[*cow_offset]; -- cgit v1.2.2 From a7dfa9403bf3b03899d5ef5d10b0c5c3f74b0682 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 12 May 2008 14:01:56 -0700 Subject: uml: use PAGE_SIZE in linker scripts This patch includes page.h header into linker scripts that allow us to use PAGE_SIZE macro instead of numeric constant. To be able to include page.h into linker scripts page.h is needed for some modification - i.e. we need to use __ASSEMBLY__ and _AC macro [jdike@linux.intel.com - fixed conflict with as-layout.h] Signed-off-by: Cyrill Gorcunov Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/as-layout.h | 14 +++++++------- arch/um/kernel/dyn.lds.S | 7 ++++--- arch/um/kernel/uml.lds.S | 7 ++++--- 3 files changed, 15 insertions(+), 13 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/as-layout.h b/arch/um/include/as-layout.h index cac542d8ff70..58e852dfb0ce 100644 --- a/arch/um/include/as-layout.h +++ b/arch/um/include/as-layout.h @@ -23,16 +23,16 @@ */ #ifdef __ASSEMBLY__ -#define _AC(X, Y) (Y) +#define _UML_AC(X, Y) (Y) #else -#define __AC(X, Y) (X (Y)) -#define _AC(X, Y) __AC(X, Y) +#define __UML_AC(X, Y) (X(Y)) +#define _UML_AC(X, Y) __UML_AC(X, Y) #endif -#define STUB_START _AC(, 0x100000) -#define STUB_CODE _AC((unsigned long), STUB_START) -#define STUB_DATA _AC((unsigned long), STUB_CODE + UM_KERN_PAGE_SIZE) -#define STUB_END _AC((unsigned long), STUB_DATA + UM_KERN_PAGE_SIZE) +#define STUB_START _UML_AC(, 0x100000) +#define STUB_CODE _UML_AC((unsigned long), STUB_START) +#define STUB_DATA _UML_AC((unsigned long), STUB_CODE + UM_KERN_PAGE_SIZE) +#define STUB_END _UML_AC((unsigned long), STUB_DATA + UM_KERN_PAGE_SIZE) #ifndef __ASSEMBLY__ diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S index 26090b7f323e..9975e1ab44fb 100644 --- a/arch/um/kernel/dyn.lds.S +++ b/arch/um/kernel/dyn.lds.S @@ -1,4 +1,5 @@ #include +#include OUTPUT_FORMAT(ELF_FORMAT) OUTPUT_ARCH(ELF_ARCH) @@ -21,7 +22,7 @@ SECTIONS _einittext = .; } - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); /* Read-only sections, merged into text segment: */ .hash : { *(.hash) } @@ -68,9 +69,9 @@ SECTIONS /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); } =0x90909090 - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); .syscall_stub : { __syscall_stub_start = .; *(.__syscall_stub*) diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index 5828c1d54505..11b835248b86 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S @@ -1,4 +1,5 @@ #include +#include OUTPUT_FORMAT(ELF_FORMAT) OUTPUT_ARCH(ELF_ARCH) @@ -26,7 +27,7 @@ SECTIONS INIT_TEXT _einittext = .; } - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); .text : { @@ -39,7 +40,7 @@ SECTIONS *(.gnu.linkonce.t*) } - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); .syscall_stub : { __syscall_stub_start = .; *(.__syscall_stub*) @@ -79,7 +80,7 @@ SECTIONS .sdata : { *(.sdata) } _edata = .; PROVIDE (edata = .); - . = ALIGN(0x1000); + . = ALIGN(PAGE_SIZE); .sbss : { __bss_start = .; -- cgit v1.2.2 From 60a2988aea701a6424809a5432bf068667aac177 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:57 -0700 Subject: uml: physical memory shouldn't include initial stack The top of physical memory should be below the initial process stack, not the top of the address space, at least for as long as the stack isn't known to the kernel VM system and appropriately reserved. Cc: "Christopher S. Aker" Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/um_arch.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch/um') diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 82058ac7d481..9db85b2ce698 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -258,6 +258,7 @@ int __init linux_main(int argc, char **argv) { unsigned long avail, diff; unsigned long virtmem_size, max_physmem; + unsigned long stack; unsigned int i; int add; char * mode; @@ -348,7 +349,9 @@ int __init linux_main(int argc, char **argv) } virtmem_size = physmem_size; - avail = TASK_SIZE - start_vm; + stack = (unsigned long) argv; + stack &= ~(1024 * 1024 - 1); + avail = stack - start_vm; if (physmem_size > avail) virtmem_size = avail; end_vm = start_vm + virtmem_size; -- cgit v1.2.2 From 5d33e4d7fd9a52d2673e5c730eab81856e100a74 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:58 -0700 Subject: uml: random driver fixes The random driver would essentially hang if the host's /dev/random returned -EAGAIN. There was a test of need_resched followed by a schedule inside the loop, but that didn't help and it's the wrong way to work anyway. The right way is to ask for an interrupt when there is input available from the host and handle it then rather than polling. Now, when the host's /dev/random returns -EAGAIN, the driver asks for a wakeup when there's randomness available again and sleeps. The interrupt routine just wakes up whatever processes are sleeping on host_read_wait. There is an atomic_t, host_sleep_count, which counts the number of processes waiting for randomness. When this reaches zero, the interrupt is disabled. An added complication is that async I/O notification was only recently added to /dev/random (by me), so essentially all hosts will lack it. So, we use the sigio workaround here, which is to have a separate thread poll on the descriptor and send an interrupt when there is input on it. This mechanism is activated when a process gets -EAGAIN (activating this multiple times is harmless, if a bit wasteful) and deactivated by the last process still waiting. The module name was changed from "random" to "hw_random" in order for udev to recognize it. The sigio workaround needed some changes. sigio_broken was added for cases when we know that async notification doesn't work. This is now called from maybe_sigio_broken, which deals with pts devices. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/random.c | 41 +++++++++++++++++++++++++++++++++++++---- arch/um/include/os.h | 1 + arch/um/include/process.h | 16 ++++------------ arch/um/os-Linux/sigio.c | 35 +++++++++++++++++++++-------------- 4 files changed, 63 insertions(+), 30 deletions(-) (limited to 'arch/um') diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c index 71f0959c1535..f92b7c81eb00 100644 --- a/arch/um/drivers/random.c +++ b/arch/um/drivers/random.c @@ -8,16 +8,18 @@ #include #include #include +#include #include #include #include +#include "irq_kern.h" #include "os.h" /* * core module and version information */ #define RNG_VERSION "1.0.0" -#define RNG_MODULE_NAME "random" +#define RNG_MODULE_NAME "hw_random" #define RNG_MISCDEV_MINOR 183 /* official */ @@ -26,6 +28,7 @@ * protects against a module being loaded twice at the same time. */ static int random_fd = -1; +static DECLARE_WAIT_QUEUE_HEAD(host_read_wait); static int rng_dev_open (struct inode *inode, struct file *filp) { @@ -38,6 +41,8 @@ static int rng_dev_open (struct inode *inode, struct file *filp) return 0; } +static atomic_t host_sleep_count = ATOMIC_INIT(0); + static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, loff_t * offp) { @@ -60,11 +65,26 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, } } else if(n == -EAGAIN){ + DECLARE_WAITQUEUE(wait, current); + if (filp->f_flags & O_NONBLOCK) return ret ? : -EAGAIN; - if(need_resched()) - schedule_timeout_interruptible(1); + atomic_inc(&host_sleep_count); + reactivate_fd(random_fd, RANDOM_IRQ); + add_sigio_fd(random_fd); + + add_wait_queue(&host_read_wait, &wait); + set_task_state(current, TASK_INTERRUPTIBLE); + + schedule(); + set_task_state(current, TASK_RUNNING); + remove_wait_queue(&host_read_wait, &wait); + + if (atomic_dec_and_test(&host_sleep_count)) { + ignore_sigio_fd(random_fd); + deactivate_fd(random_fd, RANDOM_IRQ); + } } else return n; if (signal_pending (current)) @@ -86,6 +106,13 @@ static struct miscdevice rng_miscdev = { &rng_chrdev_ops, }; +static irqreturn_t random_interrupt(int irq, void *data) +{ + wake_up(&host_read_wait); + + return IRQ_HANDLED; +} + /* * rng_init - initialize RNG module */ @@ -99,10 +126,14 @@ static int __init rng_init (void) random_fd = err; - err = os_set_fd_block(random_fd, 0); + err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt, + IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "random", + NULL); if(err) goto err_out_cleanup_hw; + sigio_broken(random_fd, 1); + err = misc_register (&rng_miscdev); if (err) { printk (KERN_ERR RNG_MODULE_NAME ": misc device register failed\n"); @@ -113,6 +144,7 @@ static int __init rng_init (void) return err; err_out_cleanup_hw: + os_close_file(random_fd); random_fd = -1; goto out; } @@ -122,6 +154,7 @@ static int __init rng_init (void) */ static void __exit rng_cleanup (void) { + os_close_file(random_fd); misc_deregister (&rng_miscdev); } diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 32c799e3a495..e2716ac8889a 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -290,6 +290,7 @@ extern void os_set_ioignore(void); extern int add_sigio_fd(int fd); extern int ignore_sigio_fd(int fd); extern void maybe_sigio_broken(int fd, int read); +extern void sigio_broken(int fd, int read); /* sys-x86_64/prctl.c */ extern int os_arch_prctl(int pid, int code, unsigned long *addr); diff --git a/arch/um/include/process.h b/arch/um/include/process.h index 5af9157ff54f..838b4802ce53 100644 --- a/arch/um/include/process.h +++ b/arch/um/include/process.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -8,18 +8,10 @@ #include +/* Copied from linux/compiler-gcc.h since we can't include it directly */ +#define barrier() __asm__ __volatile__("": : :"memory") + extern void sig_handler(int sig, struct sigcontext sc); extern void alarm_handler(int sig, struct sigcontext sc); #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 - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c index 0578481983c4..eb8f2e4be192 100644 --- a/arch/um/os-Linux/sigio.c +++ b/arch/um/os-Linux/sigio.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -15,6 +15,7 @@ #include "kern_util.h" #include "init.h" #include "os.h" +#include "process.h" #include "sigio.h" #include "um_malloc.h" #include "user.h" @@ -338,20 +339,10 @@ out_close1: close(l_write_sigio_fds[1]); } -/* Changed during early boot */ -static int pty_output_sigio = 0; -static int pty_close_sigio = 0; - -void maybe_sigio_broken(int fd, int read) +void sigio_broken(int fd, int read) { int err; - if (!isatty(fd)) - return; - - if ((read || pty_output_sigio) && (!read || pty_close_sigio)) - return; - write_sigio_workaround(); sigio_lock(); @@ -370,6 +361,21 @@ out: sigio_unlock(); } +/* Changed during early boot */ +static int pty_output_sigio; +static int pty_close_sigio; + +void maybe_sigio_broken(int fd, int read) +{ + if (!isatty(fd)) + return; + + if ((read || pty_output_sigio) && (!read || pty_close_sigio)) + return; + + sigio_broken(fd, read); +} + static void sigio_cleanup(void) { if (write_sigio_pid == -1) @@ -383,7 +389,7 @@ static void sigio_cleanup(void) __uml_exitcall(sigio_cleanup); /* Used as a flag during SIGIO testing early in boot */ -static volatile int got_sigio = 0; +static int got_sigio; static void __init handler(int sig) { @@ -498,7 +504,8 @@ static void tty_output(int master, int slave) if (errno != EAGAIN) printk(UM_KERN_ERR "tty_output : write failed, errno = %d\n", errno); - while (((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) + while (((n = read(slave, buf, sizeof(buf))) > 0) && + !({ barrier(); got_sigio; })) ; if (got_sigio) { -- cgit v1.2.2 From 3d88958e01e71bb14a367db75f12f7a59c068f02 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:59 -0700 Subject: uml: style fixes in the random driver Give random.c a style workover while I'm changing it. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/random.c | 79 +++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 38 deletions(-) (limited to 'arch/um') diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c index f92b7c81eb00..4949044773ba 100644 --- a/arch/um/drivers/random.c +++ b/arch/um/drivers/random.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2005 Jeff Dike */ +/* Copyright (C) 2005 - 2008 Jeff Dike */ + /* Much of this ripped from drivers/char/hw_random.c, see there for other * copyright. * @@ -35,7 +36,7 @@ static int rng_dev_open (struct inode *inode, struct file *filp) /* enforce read-only access to this chrdev */ if ((filp->f_mode & FMODE_READ) == 0) return -EINVAL; - if (filp->f_mode & FMODE_WRITE) + if ((filp->f_mode & FMODE_WRITE) != 0) return -EINVAL; return 0; @@ -44,31 +45,31 @@ static int rng_dev_open (struct inode *inode, struct file *filp) static atomic_t host_sleep_count = ATOMIC_INIT(0); static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, - loff_t * offp) + loff_t *offp) { - u32 data; - int n, ret = 0, have_data; - - while(size){ - n = os_read_file(random_fd, &data, sizeof(data)); - if(n > 0){ - have_data = n; - while (have_data && size) { - if (put_user((u8)data, buf++)) { - ret = ret ? : -EFAULT; - break; - } - size--; - ret++; - have_data--; - data>>=8; - } - } - else if(n == -EAGAIN){ + u32 data; + int n, ret = 0, have_data; + + while (size) { + n = os_read_file(random_fd, &data, sizeof(data)); + if (n > 0) { + have_data = n; + while (have_data && size) { + if (put_user((u8) data, buf++)) { + ret = ret ? : -EFAULT; + break; + } + size--; + ret++; + have_data--; + data >>= 8; + } + } + else if (n == -EAGAIN) { DECLARE_WAITQUEUE(wait, current); - if (filp->f_flags & O_NONBLOCK) - return ret ? : -EAGAIN; + if (filp->f_flags & O_NONBLOCK) + return ret ? : -EAGAIN; atomic_inc(&host_sleep_count); reactivate_fd(random_fd, RANDOM_IRQ); @@ -85,8 +86,10 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, ignore_sigio_fd(random_fd); deactivate_fd(random_fd, RANDOM_IRQ); } - } - else return n; + } + else + return n; + if (signal_pending (current)) return ret ? : -ERESTARTSYS; } @@ -120,33 +123,33 @@ static int __init rng_init (void) { int err; - err = os_open_file("/dev/random", of_read(OPENFLAGS()), 0); - if(err < 0) - goto out; + err = os_open_file("/dev/random", of_read(OPENFLAGS()), 0); + if (err < 0) + goto out; - random_fd = err; + random_fd = err; err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt, IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "random", NULL); - if(err) + if (err) goto err_out_cleanup_hw; sigio_broken(random_fd, 1); err = misc_register (&rng_miscdev); if (err) { - printk (KERN_ERR RNG_MODULE_NAME ": misc device register failed\n"); + printk (KERN_ERR RNG_MODULE_NAME ": misc device register " + "failed\n"); goto err_out_cleanup_hw; } +out: + return err; - out: - return err; - - err_out_cleanup_hw: +err_out_cleanup_hw: os_close_file(random_fd); - random_fd = -1; - goto out; + random_fd = -1; + goto out; } /* -- cgit v1.2.2 From fe2cc53ee013a4d4d0317d418e7019fe6533a5a8 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:02:00 -0700 Subject: uml: track and make up lost ticks Alarm delivery could be noticably late in the !CONFIG_NOHZ case because lost ticks weren't being taken into account. This is now treated more carefully, with the time between ticks being calculated and the appropriate number of ticks delivered to the timekeeping system. Cc: Nix Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/process.h | 4 ++-- arch/um/os-Linux/signal.c | 1 + arch/um/os-Linux/time.c | 54 +++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 53 insertions(+), 6 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/process.h b/arch/um/include/process.h index 838b4802ce53..bb873a51262e 100644 --- a/arch/um/include/process.h +++ b/arch/um/include/process.h @@ -11,7 +11,7 @@ /* Copied from linux/compiler-gcc.h since we can't include it directly */ #define barrier() __asm__ __volatile__("": : :"memory") -extern void sig_handler(int sig, struct sigcontext sc); -extern void alarm_handler(int sig, struct sigcontext sc); +extern void sig_handler(int sig, struct sigcontext *sc); +extern void alarm_handler(int sig, struct sigcontext *sc); #endif diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index 3f1694b134cb..5aade6027e40 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c @@ -12,6 +12,7 @@ #include "as-layout.h" #include "kern_util.h" #include "os.h" +#include "process.h" #include "sysdep/barrier.h" #include "sysdep/sigcontext.h" #include "user.h" diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index e49280599465..bee98f466d66 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c @@ -9,7 +9,9 @@ #include #include #include "kern_constants.h" +#include "kern_util.h" #include "os.h" +#include "process.h" #include "user.h" int set_interval(void) @@ -58,12 +60,17 @@ static inline long long timeval_to_ns(const struct timeval *tv) long long disable_timer(void) { struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } }); + int remain, max = UM_NSEC_PER_SEC / UM_HZ; if (setitimer(ITIMER_VIRTUAL, &time, &time) < 0) printk(UM_KERN_ERR "disable_timer - setitimer failed, " "errno = %d\n", errno); - return timeval_to_ns(&time.it_value); + remain = timeval_to_ns(&time.it_value); + if (remain > max) + remain = max; + + return remain; } long long os_nsecs(void) @@ -79,7 +86,44 @@ static int after_sleep_interval(struct timespec *ts) { return 0; } + +static void deliver_alarm(void) +{ + alarm_handler(SIGVTALRM, NULL); +} + +static unsigned long long sleep_time(unsigned long long nsecs) +{ + return nsecs; +} + #else +unsigned long long last_tick; +unsigned long long skew; + +static void deliver_alarm(void) +{ + unsigned long long this_tick = os_nsecs(); + int one_tick = UM_NSEC_PER_SEC / UM_HZ; + + if (last_tick == 0) + last_tick = this_tick - one_tick; + + skew += this_tick - last_tick; + + while (skew >= one_tick) { + alarm_handler(SIGVTALRM, NULL); + skew -= one_tick; + } + + last_tick = this_tick; +} + +static unsigned long long sleep_time(unsigned long long nsecs) +{ + return nsecs > skew ? nsecs - skew : 0; +} + static inline long long timespec_to_us(const struct timespec *ts) { return ((long long) ts->tv_sec * UM_USEC_PER_SEC) + @@ -102,6 +146,8 @@ static int after_sleep_interval(struct timespec *ts) */ if (start_usecs > usec) start_usecs = usec; + + start_usecs -= skew / UM_NSEC_PER_USEC; tv = ((struct timeval) { .tv_sec = start_usecs / UM_USEC_PER_SEC, .tv_usec = start_usecs % UM_USEC_PER_SEC }); interval = ((struct itimerval) { { 0, usec }, tv }); @@ -113,8 +159,6 @@ static int after_sleep_interval(struct timespec *ts) } #endif -extern void alarm_handler(int sig, struct sigcontext *sc); - void idle_sleep(unsigned long long nsecs) { struct timespec ts; @@ -126,10 +170,12 @@ void idle_sleep(unsigned long long nsecs) */ if (nsecs == 0) nsecs = UM_NSEC_PER_SEC / UM_HZ; + + nsecs = sleep_time(nsecs); ts = ((struct timespec) { .tv_sec = nsecs / UM_NSEC_PER_SEC, .tv_nsec = nsecs % UM_NSEC_PER_SEC }); if (nanosleep(&ts, &ts) == 0) - alarm_handler(SIGVTALRM, NULL); + deliver_alarm(); after_sleep_interval(&ts); } -- cgit v1.2.2