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/include/os.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/um/include/os.h') 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); -- 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/um/include/os.h') 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 -- cgit v1.2.3