From 06e1e4ffbd1932e288839b3140cda6b8141eb684 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Thu, 5 Jun 2008 22:46:10 -0700 Subject: uml: deal with host time going backwards Protection against the host's time going backwards (eg, ntp activity on the host) by keeping track of the time at the last tick and if it's greater than the current time, keep time stopped until the host catches up. Cc: Nix Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/time.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch/um') diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index bee98f466d66..dec5678fc17f 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c @@ -106,6 +106,10 @@ static void deliver_alarm(void) unsigned long long this_tick = os_nsecs(); int one_tick = UM_NSEC_PER_SEC / UM_HZ; + /* Protection against the host's time going backwards */ + if ((last_tick != 0) && (this_tick < last_tick)) + this_tick = last_tick; + if (last_tick == 0) last_tick = this_tick - one_tick; @@ -148,6 +152,9 @@ static int after_sleep_interval(struct timespec *ts) start_usecs = usec; start_usecs -= skew / UM_NSEC_PER_USEC; + if (start_usecs < 0) + start_usecs = 0; + 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 }); -- cgit v1.2.3 From 9f31287b443f30a591539e448fb628e3827a8f61 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Thu, 5 Jun 2008 22:46:11 -0700 Subject: uml: remove a duplicate include Removed duplicated include file "kern_util.h" in arch/um/drivers/ubd_kern.c. Signed-off-by: Huang Weiyi Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/ubd_kern.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/um') diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 44ad1607be2d..b58fb8941d8d 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -49,7 +49,6 @@ #include "irq_user.h" #include "irq_kern.h" #include "ubd_user.h" -#include "kern_util.h" #include "os.h" #include "mem.h" #include "mem_kern.h" -- cgit v1.2.3 From 40fb16a360d9c6459afee91dc793c1e3374feb94 Mon Sep 17 00:00:00 2001 From: Tom Spink Date: Thu, 5 Jun 2008 22:46:12 -0700 Subject: uml: deal with inaccessible address space start This patch makes os_get_task_size locate the bottom of the address space, as well as the top. This is for systems which put a lower limit on mmap addresses. It works by manually scanning pages from zero onwards until a valid page is found. Because the bottom of the address space may not be zero, it's not sufficient to assume the top of the address space is the size of the address space. The size is the difference between the top address and bottom address. [jdike@addtoit.com: changed the name to reflect that this function is supposed to return the top of the process address space, not its size and changed the return value to reflect that. Also some minor formatting changes] Signed-off-by: Tom Spink Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/os.h | 2 +- arch/um/kernel/um_arch.c | 2 +- arch/um/os-Linux/sys-i386/task_size.c | 31 +++++++++++++++++++++++-------- arch/um/os-Linux/sys-x86_64/task_size.c | 2 +- 4 files changed, 26 insertions(+), 11 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/os.h b/arch/um/include/os.h index e2716ac8889a..db5be46e3e18 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -299,6 +299,6 @@ extern int os_arch_prctl(int pid, int code, unsigned long *addr); extern int get_pty(void); /* sys-$ARCH/task_size.c */ -extern unsigned long os_get_task_size(void); +extern unsigned long os_get_top_address(void); #endif diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 9db85b2ce698..8d84250324b3 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -274,7 +274,7 @@ int __init linux_main(int argc, char **argv) if (have_root == 0) add_arg(DEFAULT_COMMAND_LINE); - host_task_size = os_get_task_size(); + host_task_size = os_get_top_address(); /* * TASK_SIZE needs to be PGDIR_SIZE aligned or else exit_mmap craps * out diff --git a/arch/um/os-Linux/sys-i386/task_size.c b/arch/um/os-Linux/sys-i386/task_size.c index ccb49b0aff59..be04c1e183bf 100644 --- a/arch/um/os-Linux/sys-i386/task_size.c +++ b/arch/um/os-Linux/sys-i386/task_size.c @@ -63,7 +63,7 @@ static int page_ok(unsigned long page) return ok; } -unsigned long os_get_task_size(void) +unsigned long os_get_top_address(void) { struct sigaction sa, old; unsigned long bottom = 0; @@ -76,9 +76,9 @@ unsigned long os_get_task_size(void) * hosts, but shouldn't hurt otherwise. */ unsigned long top = 0xffffd000 >> UM_KERN_PAGE_SHIFT; - unsigned long test; + unsigned long test, original; - printf("Locating the top of the address space ... "); + printf("Locating the bottom of the address space ... "); fflush(stdout); /* @@ -89,16 +89,31 @@ unsigned long os_get_task_size(void) sigemptyset(&sa.sa_mask); sa.sa_flags = SA_NODEFER; if (sigaction(SIGSEGV, &sa, &old)) { - perror("os_get_task_size"); + perror("os_get_top_address"); exit(1); } - if (!page_ok(bottom)) { - fprintf(stderr, "Address 0x%x no good?\n", - bottom << UM_KERN_PAGE_SHIFT); + /* Manually scan the address space, bottom-up, until we find + * the first valid page (or run out of them). + */ + for (bottom = 0; bottom < top; bottom++) { + if (page_ok(bottom)) + break; + } + + /* If we've got this far, we ran out of pages. */ + if (bottom == top) { + fprintf(stderr, "Unable to determine bottom of address " + "space.\n"); exit(1); } + printf("0x%x\n", bottom << UM_KERN_PAGE_SHIFT); + printf("Locating the top of the address space ... "); + fflush(stdout); + + original = bottom; + /* This could happen with a 4G/4G split */ if (page_ok(top)) goto out; @@ -114,7 +129,7 @@ unsigned long os_get_task_size(void) out: /* Restore the old SIGSEGV handling */ if (sigaction(SIGSEGV, &old, NULL)) { - perror("os_get_task_size"); + perror("os_get_top_address"); exit(1); } top <<= UM_KERN_PAGE_SHIFT; diff --git a/arch/um/os-Linux/sys-x86_64/task_size.c b/arch/um/os-Linux/sys-x86_64/task_size.c index fad6f57f8ee3..26a0dd1f349c 100644 --- a/arch/um/os-Linux/sys-x86_64/task_size.c +++ b/arch/um/os-Linux/sys-x86_64/task_size.c @@ -1,4 +1,4 @@ -unsigned long os_get_task_size(unsigned long shift) +unsigned long os_get_top_address(unsigned long shift) { /* The old value of CONFIG_TOP_ADDR */ return 0x7fc0000000; -- cgit v1.2.3 From 8bfd04b974689f700bbd053ad6e66b0a95fb80c9 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Thu, 5 Jun 2008 22:46:13 -0700 Subject: uml: memcpy export needs to follow host declaration x86_64 defines either memcpy or __memcpy depending on the gcc version, and it looks like UML needs to follow that in its exporting. Cc: Gabriel C Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/sys-x86_64/ksyms.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/um') diff --git a/arch/um/sys-x86_64/ksyms.c b/arch/um/sys-x86_64/ksyms.c index 6604673a849d..1db2fce00948 100644 --- a/arch/um/sys-x86_64/ksyms.c +++ b/arch/um/sys-x86_64/ksyms.c @@ -3,5 +3,9 @@ #include /*XXX: we need them because they would be exported by x86_64 */ +#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4 +EXPORT_SYMBOL(memcpy); +#else EXPORT_SYMBOL(__memcpy); +#endif EXPORT_SYMBOL(csum_partial); -- cgit v1.2.3 From 3d5ede6f776bdb1483bcd086f79c3bf41fed3865 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Thu, 5 Jun 2008 22:46:13 -0700 Subject: uml: stub needs to tolerate SIGWINCH We lost the marking of SIGWINCH as being OK to receive during stub execution, causing a panic should that happen. Cc: Benedict Verheyen Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/skas/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/um') diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 6be028ca1817..172ad8f72e12 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -55,7 +55,7 @@ static int ptrace_dump_regs(int pid) * Signals that are OK to receive in the stub - we'll just continue it. * SIGWINCH will happen when UML is inside a detached screen. */ -#define STUB_SIG_MASK (1 << SIGVTALRM) +#define STUB_SIG_MASK ((1 << SIGVTALRM) | (1 << SIGWINCH)) /* Signals that the stub will finish with - anything else is an error */ #define STUB_DONE_MASK (1 << SIGTRAP) -- cgit v1.2.3 From b6d8adf477439e7086224bc9674c6b6638780783 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 5 Jun 2008 22:46:14 -0700 Subject: uml: PATH_MAX needs limits.h Include limits.h to get a definition of PATH_MAX. Signed-off-by: Ingo Molnar Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/helper.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/um') diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index 74ca7aabf4e1..30860b89ec58 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include "kern_constants.h" -- cgit v1.2.3 From 14c8a77e1bbd693446dad297d2ae2dd22f187e4f Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Thu, 12 Jun 2008 15:21:40 -0700 Subject: uml: remove include of asm/user.h I allowed an include of asm/user.h to sneak back in. This patch replaces it with sys/user.h. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/sys-i386/registers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/um') diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c index b487cbead1bd..229f7a53d8da 100644 --- a/arch/um/os-Linux/sys-i386/registers.c +++ b/arch/um/os-Linux/sys-i386/registers.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include "kern_constants.h" #include "longjmp.h" #include "user.h" @@ -76,7 +76,7 @@ int put_fp_registers(int pid, unsigned long *regs) void arch_init_registers(int pid) { - struct user_fxsr_struct fpx_regs; + struct user_fpxregs_struct fpx_regs; int err; err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs); -- cgit v1.2.3 From f1ef9167ca4494a8c6d71d0031c73e9c8841eadd Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Thu, 12 Jun 2008 15:21:41 -0700 Subject: uml: work around broken host PTRACE_SYSEMU Fedora broke PTRACE_SYSEMU again, and UML crashes as a result when it doesn't need to. This patch makes the PTRACE_SYSEMU check fail gracefully and makes UML fall back to PTRACE_SYSCALL. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/start_up.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'arch/um') diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index b4b36e0f2e89..183db26d01bf 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -121,8 +121,10 @@ static int stop_ptraced_child(int pid, int exitcode, int mustexit) { int status, n, ret = 0; - if (ptrace(PTRACE_CONT, pid, 0, 0) < 0) - fatal_perror("stop_ptraced_child : ptrace failed"); + if (ptrace(PTRACE_CONT, pid, 0, 0) < 0) { + perror("stop_ptraced_child : ptrace failed"); + return -1; + } CATCH_EINTR(n = waitpid(pid, &status, 0)); if (!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { int exit_with = WEXITSTATUS(status); @@ -212,7 +214,7 @@ static void __init check_sysemu(void) if (n < 0) fatal_perror("check_sysemu : wait failed"); if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) - fatal("check_sysemu : expected SIGTRAP, got status = %d", + fatal("check_sysemu : expected SIGTRAP, got status = %d\n", status); if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) @@ -254,9 +256,11 @@ static void __init check_sysemu(void) if (WIFSTOPPED(status) && (WSTOPSIG(status) == (SIGTRAP|0x80))) { - if (!count) - fatal("check_ptrace : SYSEMU_SINGLESTEP " - "doesn't singlestep"); + if (!count) { + non_fatal("check_ptrace : SYSEMU_SINGLESTEP " + "doesn't singlestep"); + goto fail; + } n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid()); if (n < 0) @@ -266,9 +270,12 @@ static void __init check_sysemu(void) } else if (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) count++; - else - fatal("check_ptrace : expected SIGTRAP or " - "(SIGTRAP | 0x80), got status = %d", status); + else { + non_fatal("check_ptrace : expected SIGTRAP or " + "(SIGTRAP | 0x80), got status = %d\n", + status); + goto fail; + } } if (stop_ptraced_child(pid, 0, 0) < 0) goto fail_stopped; -- cgit v1.2.3 From 8691e5a8f691cc2a4fda0651e8d307aaba0e7d68 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 6 Jun 2008 11:18:06 +0200 Subject: smp_call_function: get rid of the unused nonatomic/retry argument It's never used and the comments refer to nonatomic and retry interchangably. So get rid of it. Acked-by: Jeremy Fitzhardinge Signed-off-by: Jens Axboe --- arch/um/kernel/smp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/um') diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c index e1062ec36d40..be2d50c3aa95 100644 --- a/arch/um/kernel/smp.c +++ b/arch/um/kernel/smp.c @@ -214,8 +214,7 @@ void smp_call_function_slave(int cpu) atomic_inc(&scf_finished); } -int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic, - int wait) +int smp_call_function(void (*_func)(void *info), void *_info, int wait) { int cpus = num_online_cpus() - 1; int i; -- cgit v1.2.3 From 78dccb46ddc2ff460c8b4d5ec0886964bd4b59e5 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 20 May 2008 19:16:54 +0200 Subject: uml-harddog: BKL pushdown Signed-off-by: Arnd Bergmann --- arch/um/drivers/harddog_kern.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/um') diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c index a9ad4bd6d953..d332503fa1be 100644 --- a/arch/um/drivers/harddog_kern.c +++ b/arch/um/drivers/harddog_kern.c @@ -66,6 +66,7 @@ static int harddog_open(struct inode *inode, struct file *file) int err = -EBUSY; char *sock = NULL; + lock_kernel(); spin_lock(&lock); if(timer_alive) goto err; @@ -82,9 +83,11 @@ static int harddog_open(struct inode *inode, struct file *file) timer_alive = 1; spin_unlock(&lock); + unlock_kernel(); return nonseekable_open(inode, file); err: spin_unlock(&lock); + unlock_kernel(); return err; } -- cgit v1.2.3 From bd6859fe836491d20ea6e57fee93e0e08ee69443 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 20 May 2008 19:16:56 +0200 Subject: uml-mmapper: BKL pushdown Signed-off-by: Arnd Bergmann --- arch/um/drivers/mmapper_kern.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/um') diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c index 67b2f55a602f..eb240323c40a 100644 --- a/arch/um/drivers/mmapper_kern.c +++ b/arch/um/drivers/mmapper_kern.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "mem_user.h" @@ -77,6 +78,7 @@ out: static int mmapper_open(struct inode *inode, struct file *file) { + cycle_kernel_lock(); return 0; } -- cgit v1.2.3 From 7eb500d1a0408c37d0c0360f066f8b7701835d68 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 20 May 2008 19:16:57 +0200 Subject: uml-random: BKL pushdown Signed-off-by: Arnd Bergmann --- arch/um/drivers/random.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/um') diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c index 4949044773ba..6eabb7022a2d 100644 --- a/arch/um/drivers/random.c +++ b/arch/um/drivers/random.c @@ -7,6 +7,7 @@ * of the GNU General Public License, incorporated herein by reference. */ #include +#include #include #include #include @@ -33,6 +34,8 @@ static DECLARE_WAIT_QUEUE_HEAD(host_read_wait); static int rng_dev_open (struct inode *inode, struct file *filp) { + cycle_kernel_lock(); + /* enforce read-only access to this chrdev */ if ((filp->f_mode & FMODE_READ) == 0) return -EINVAL; -- cgit v1.2.3 From 4f81c5350b44bcc501ab6f8a089b16d064b4d2f6 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 7 Jul 2008 13:36:56 -0400 Subject: [UML] fix gcc ICEs and unresolved externs There are various constraints on the use of unit-at-a-time: - i386 uses no-unit-at-a-time for pre-4.0 (not 4.3) - x86_64 uses unit-at-a-time always Uli reported a crash on x86_64 with gcc 4.1.2 with unit-at-a-time, resulting in commit c0a18111e571138747a98af18b3a2124df56a0d1 Ingo reported a gcc internal error with gcc 4.3 with no-unit-at-a-timem, resulting in 22eecde2f9034764a3fd095eecfa3adfb8ec9a98 Benny Halevy is seeing extern inlines not resolved with gcc 4.3 with no-unit-at-a-time This patch reintroduces unit-at-a-time for gcc >= 4.0, bringing back the possibility of Uli's crash. If that happens, we'll debug it. I started seeing both the internal compiler errors and unresolved inlines on Fedora 9. This patch fixes both problems, without so far reintroducing the crash reported by Uli. Signed-off-by: Jeff Dike Cc: Benny Halevy Cc: Adrian Bunk Cc: Ingo Molnar Cc: Ulrich Drepper Signed-off-by: Linus Torvalds --- arch/um/Makefile | 1 - arch/um/Makefile-i386 | 7 +++++++ arch/um/Makefile-x86_64 | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) (limited to 'arch/um') diff --git a/arch/um/Makefile b/arch/um/Makefile index dbeab15e7bb7..ca40397017b9 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -77,7 +77,6 @@ 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) -KBUILD_CFLAGS += $(call cc-option,-fno-unit-at-a-time,) PHONY += linux diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index 561e373bd850..302cbe504543 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 @@ -32,4 +32,11 @@ cflags-y += $(call cc-option,-mpreferred-stack-boundary=2) # an unresolved reference. cflags-y += -ffreestanding +# 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. Also, gcc +# 4.3.0 needs -funit-at-a-time for extern inline functions. +KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then \ + echo $(call cc-option,-fno-unit-at-a-time); \ + else echo $(call cc-option,-funit-at-a-time); fi ;) + KBUILD_CFLAGS += $(cflags-y) diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64 index 8ed362f93582..a9cd7e77a7ab 100644 --- a/arch/um/Makefile-x86_64 +++ b/arch/um/Makefile-x86_64 @@ -21,3 +21,6 @@ HEADER_ARCH := x86 LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib64 LINK-y += -m64 + +# Do unit-at-a-time unconditionally on x86_64, following the host +KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time) -- cgit v1.2.3