aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/um
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/Kconfig.common9
-rw-r--r--arch/um/Kconfig.debug16
-rw-r--r--arch/um/Kconfig.net2
-rw-r--r--arch/um/Kconfig.um7
-rw-r--r--arch/um/Kconfig.x8612
-rw-r--r--arch/um/defconfig3
-rw-r--r--arch/um/drivers/Makefile4
-rw-r--r--arch/um/drivers/harddog_kern.c14
-rw-r--r--arch/um/drivers/hostaudio_kern.c12
-rw-r--r--arch/um/drivers/line.c13
-rw-r--r--arch/um/drivers/mcast.h24
-rw-r--r--arch/um/drivers/mcast_kern.c120
-rw-r--r--arch/um/drivers/mcast_user.c165
-rw-r--r--arch/um/drivers/mconsole_kern.c22
-rw-r--r--arch/um/drivers/mmapper_kern.c12
-rw-r--r--arch/um/drivers/random.c1
-rw-r--r--arch/um/drivers/ubd_kern.c13
-rw-r--r--arch/um/drivers/umcast.h27
-rw-r--r--arch/um/drivers/umcast_kern.c188
-rw-r--r--arch/um/drivers/umcast_user.c186
-rw-r--r--arch/um/drivers/xterm.c2
-rw-r--r--arch/um/include/asm/bug.h6
-rw-r--r--arch/um/include/asm/common.lds.S2
-rw-r--r--arch/um/include/asm/dma-mapping.h112
-rw-r--r--arch/um/include/asm/percpu.h6
-rw-r--r--arch/um/include/asm/pgtable.h2
-rw-r--r--arch/um/include/asm/processor-generic.h4
-rw-r--r--arch/um/include/asm/ptrace-generic.h4
-rw-r--r--arch/um/include/asm/smp.h1
-rw-r--r--arch/um/include/asm/system.h49
-rw-r--r--arch/um/include/asm/thread_info.h5
-rw-r--r--arch/um/include/asm/tlb.h29
-rw-r--r--arch/um/include/shared/line.h4
-rw-r--r--arch/um/include/shared/os.h7
-rw-r--r--arch/um/kernel/Makefile1
-rw-r--r--arch/um/kernel/dyn.lds.S14
-rw-r--r--arch/um/kernel/early_printk.c33
-rw-r--r--arch/um/kernel/exec.c3
-rw-r--r--arch/um/kernel/irq.c87
-rw-r--r--arch/um/kernel/ptrace.c23
-rw-r--r--arch/um/kernel/skas/mmu.c2
-rw-r--r--arch/um/kernel/smp.c5
-rw-r--r--arch/um/kernel/trap.c24
-rw-r--r--arch/um/kernel/uml.lds.S19
-rw-r--r--arch/um/os-Linux/main.c3
-rw-r--r--arch/um/os-Linux/process.c1
-rw-r--r--arch/um/os-Linux/time.c2
-rw-r--r--arch/um/os-Linux/util.c28
-rw-r--r--arch/um/sys-i386/Makefile2
-rw-r--r--arch/um/sys-i386/asm/elf.h2
-rw-r--r--arch/um/sys-i386/atomic64_cx8_32.S225
-rw-r--r--arch/um/sys-i386/ptrace.c4
-rw-r--r--arch/um/sys-ppc/Makefile10
-rw-r--r--arch/um/sys-x86_64/asm/elf.h2
-rw-r--r--arch/um/sys-x86_64/ptrace.c11
55 files changed, 931 insertions, 653 deletions
diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common
index 7c8e277f6d34..a9234838e8a2 100644
--- a/arch/um/Kconfig.common
+++ b/arch/um/Kconfig.common
@@ -3,14 +3,11 @@ config DEFCONFIG_LIST
3 option defconfig_list 3 option defconfig_list
4 default "arch/$ARCH/defconfig" 4 default "arch/$ARCH/defconfig"
5 5
6# UML uses the generic IRQ subsystem
7config GENERIC_HARDIRQS
8 bool
9 default y
10
11config UML 6config UML
12 bool 7 bool
13 default y 8 default y
9 select HAVE_GENERIC_HARDIRQS
10 select GENERIC_IRQ_SHOW
14 11
15config MMU 12config MMU
16 bool 13 bool
@@ -19,8 +16,6 @@ config MMU
19config NO_IOMEM 16config NO_IOMEM
20 def_bool y 17 def_bool y
21 18
22mainmenu "Linux/Usermode Kernel Configuration"
23
24config ISA 19config ISA
25 bool 20 bool
26 21
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
index 8fce5e536b0f..68205fd3b08c 100644
--- a/arch/um/Kconfig.debug
+++ b/arch/um/Kconfig.debug
@@ -28,13 +28,13 @@ config GCOV
28 If you're involved in UML kernel development and want to use gcov, 28 If you're involved in UML kernel development and want to use gcov,
29 say Y. If you're unsure, say N. 29 say Y. If you're unsure, say N.
30 30
31config DEBUG_STACK_USAGE 31config EARLY_PRINTK
32 bool "Stack utilization instrumentation" 32 bool "Early printk"
33 default N 33 default y
34 help 34 ---help---
35 Track the maximum kernel stack usage - this will look at each 35 Write kernel log output directly to stdout.
36 kernel stack at process exit and log it if it's the deepest 36
37 stack seen so far. 37 This is useful for kernel debugging when your machine crashes very
38 early before the console code is initialized.
38 39
39 This option will slow down process creation and destruction somewhat.
40endmenu 40endmenu
diff --git a/arch/um/Kconfig.net b/arch/um/Kconfig.net
index 9e9a4aaa703d..3160b1a5adb7 100644
--- a/arch/um/Kconfig.net
+++ b/arch/um/Kconfig.net
@@ -186,7 +186,7 @@ config UML_NET_SLIRP
186 other transports, SLiRP works without the need of root level 186 other transports, SLiRP works without the need of root level
187 privleges, setuid binaries, or SLIP devices on the host. This 187 privleges, setuid binaries, or SLIP devices on the host. This
188 also means not every type of connection is possible, but most 188 also means not every type of connection is possible, but most
189 situations can be accomodated with carefully crafted slirp 189 situations can be accommodated with carefully crafted slirp
190 commands that can be passed along as part of the network device's 190 commands that can be passed along as part of the network device's
191 setup string. The effect of this transport on the UML is similar 191 setup string. The effect of this transport on the UML is similar
192 that of a host behind a firewall that masquerades all network 192 that of a host behind a firewall that masquerades all network
diff --git a/arch/um/Kconfig.um b/arch/um/Kconfig.um
index ec2b8da1aba4..b5e675e370c6 100644
--- a/arch/um/Kconfig.um
+++ b/arch/um/Kconfig.um
@@ -47,7 +47,7 @@ config HOSTFS
47 47
48config HPPFS 48config HPPFS
49 tristate "HoneyPot ProcFS (EXPERIMENTAL)" 49 tristate "HoneyPot ProcFS (EXPERIMENTAL)"
50 depends on EXPERIMENTAL 50 depends on EXPERIMENTAL && PROC_FS
51 help 51 help
52 hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc 52 hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
53 entries to be overridden, removed, or fabricated from the host. 53 entries to be overridden, removed, or fabricated from the host.
@@ -128,7 +128,7 @@ config NR_CPUS
128 128
129config HIGHMEM 129config HIGHMEM
130 bool "Highmem support (EXPERIMENTAL)" 130 bool "Highmem support (EXPERIMENTAL)"
131 depends on !64BIT && EXPERIMENTAL 131 depends on !64BIT && BROKEN
132 default n 132 default n
133 help 133 help
134 This was used to allow UML to run with big amounts of memory. 134 This was used to allow UML to run with big amounts of memory.
@@ -147,3 +147,6 @@ config KERNEL_STACK_ORDER
147 This option determines the size of UML kernel stacks. They will 147 This option determines the size of UML kernel stacks. They will
148 be 1 << order pages. The default is OK unless you're running Valgrind 148 be 1 << order pages. The default is OK unless you're running Valgrind
149 on UML, in which case, set this to 3. 149 on UML, in which case, set this to 3.
150
151config NO_DMA
152 def_bool y
diff --git a/arch/um/Kconfig.x86 b/arch/um/Kconfig.x86
index 5ee328099c63..8aae429a56e2 100644
--- a/arch/um/Kconfig.x86
+++ b/arch/um/Kconfig.x86
@@ -4,12 +4,17 @@ menu "UML-specific options"
4 4
5menu "Host processor type and features" 5menu "Host processor type and features"
6 6
7config CMPXCHG_LOCAL
8 bool
9 default n
10
7source "arch/x86/Kconfig.cpu" 11source "arch/x86/Kconfig.cpu"
8 12
9endmenu 13endmenu
10 14
11config UML_X86 15config UML_X86
12 def_bool y 16 def_bool y
17 select GENERIC_FIND_FIRST_BIT
13 18
14config 64BIT 19config 64BIT
15 bool 20 bool
@@ -19,11 +24,14 @@ config X86_32
19 def_bool !64BIT 24 def_bool !64BIT
20 select HAVE_AOUT 25 select HAVE_AOUT
21 26
27config X86_64
28 def_bool 64BIT
29
22config RWSEM_XCHGADD_ALGORITHM 30config RWSEM_XCHGADD_ALGORITHM
23 def_bool X86_XADD 31 def_bool X86_XADD && 64BIT
24 32
25config RWSEM_GENERIC_SPINLOCK 33config RWSEM_GENERIC_SPINLOCK
26 def_bool !X86_XADD 34 def_bool !RWSEM_XCHGADD_ALGORITHM
27 35
28config 3_LEVEL_PGTABLES 36config 3_LEVEL_PGTABLES
29 bool "Three-level pagetables (EXPERIMENTAL)" if !64BIT 37 bool "Three-level pagetables (EXPERIMENTAL)" if !64BIT
diff --git a/arch/um/defconfig b/arch/um/defconfig
index 6bd456f96f90..9f7634f08cf3 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -133,7 +133,7 @@ CONFIG_SYSFS_DEPRECATED=y
133# CONFIG_BLK_DEV_INITRD is not set 133# CONFIG_BLK_DEV_INITRD is not set
134CONFIG_CC_OPTIMIZE_FOR_SIZE=y 134CONFIG_CC_OPTIMIZE_FOR_SIZE=y
135CONFIG_SYSCTL=y 135CONFIG_SYSCTL=y
136# CONFIG_EMBEDDED is not set 136# CONFIG_EXPERT is not set
137CONFIG_UID16=y 137CONFIG_UID16=y
138CONFIG_SYSCTL_SYSCALL=y 138CONFIG_SYSCTL_SYSCALL=y
139CONFIG_KALLSYMS=y 139CONFIG_KALLSYMS=y
@@ -566,7 +566,6 @@ CONFIG_CRC32=m
566# CONFIG_CRC7 is not set 566# CONFIG_CRC7 is not set
567# CONFIG_LIBCRC32C is not set 567# CONFIG_LIBCRC32C is not set
568CONFIG_PLIST=y 568CONFIG_PLIST=y
569CONFIG_HAS_DMA=y
570 569
571# 570#
572# SCSI device support 571# SCSI device support
diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile
index 1d9b6ae967b0..e7582e1d248c 100644
--- a/arch/um/drivers/Makefile
+++ b/arch/um/drivers/Makefile
@@ -9,7 +9,7 @@
9slip-objs := slip_kern.o slip_user.o 9slip-objs := slip_kern.o slip_user.o
10slirp-objs := slirp_kern.o slirp_user.o 10slirp-objs := slirp_kern.o slirp_user.o
11daemon-objs := daemon_kern.o daemon_user.o 11daemon-objs := daemon_kern.o daemon_user.o
12mcast-objs := mcast_kern.o mcast_user.o 12umcast-objs := umcast_kern.o umcast_user.o
13net-objs := net_kern.o net_user.o 13net-objs := net_kern.o net_user.o
14mconsole-objs := mconsole_kern.o mconsole_user.o 14mconsole-objs := mconsole_kern.o mconsole_user.o
15hostaudio-objs := hostaudio_kern.o 15hostaudio-objs := hostaudio_kern.o
@@ -44,7 +44,7 @@ obj-$(CONFIG_UML_NET_SLIP) += slip.o slip_common.o
44obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o 44obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o
45obj-$(CONFIG_UML_NET_DAEMON) += daemon.o 45obj-$(CONFIG_UML_NET_DAEMON) += daemon.o
46obj-$(CONFIG_UML_NET_VDE) += vde.o 46obj-$(CONFIG_UML_NET_VDE) += vde.o
47obj-$(CONFIG_UML_NET_MCAST) += mcast.o 47obj-$(CONFIG_UML_NET_MCAST) += umcast.o
48obj-$(CONFIG_UML_NET_PCAP) += pcap.o 48obj-$(CONFIG_UML_NET_PCAP) += pcap.o
49obj-$(CONFIG_UML_NET) += net.o 49obj-$(CONFIG_UML_NET) += net.o
50obj-$(CONFIG_MCONSOLE) += mconsole.o 50obj-$(CONFIG_MCONSOLE) += mconsole.o
diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c
index cfcac1ff4cf2..2d0266d0254d 100644
--- a/arch/um/drivers/harddog_kern.c
+++ b/arch/um/drivers/harddog_kern.c
@@ -42,7 +42,7 @@
42#include <linux/miscdevice.h> 42#include <linux/miscdevice.h>
43#include <linux/watchdog.h> 43#include <linux/watchdog.h>
44#include <linux/reboot.h> 44#include <linux/reboot.h>
45#include <linux/smp_lock.h> 45#include <linux/mutex.h>
46#include <linux/init.h> 46#include <linux/init.h>
47#include <linux/spinlock.h> 47#include <linux/spinlock.h>
48#include <asm/uaccess.h> 48#include <asm/uaccess.h>
@@ -50,6 +50,7 @@
50 50
51MODULE_LICENSE("GPL"); 51MODULE_LICENSE("GPL");
52 52
53static DEFINE_MUTEX(harddog_mutex);
53static DEFINE_SPINLOCK(lock); 54static DEFINE_SPINLOCK(lock);
54static int timer_alive; 55static int timer_alive;
55static int harddog_in_fd = -1; 56static int harddog_in_fd = -1;
@@ -66,7 +67,7 @@ static int harddog_open(struct inode *inode, struct file *file)
66 int err = -EBUSY; 67 int err = -EBUSY;
67 char *sock = NULL; 68 char *sock = NULL;
68 69
69 lock_kernel(); 70 mutex_lock(&harddog_mutex);
70 spin_lock(&lock); 71 spin_lock(&lock);
71 if(timer_alive) 72 if(timer_alive)
72 goto err; 73 goto err;
@@ -83,11 +84,11 @@ static int harddog_open(struct inode *inode, struct file *file)
83 84
84 timer_alive = 1; 85 timer_alive = 1;
85 spin_unlock(&lock); 86 spin_unlock(&lock);
86 unlock_kernel(); 87 mutex_unlock(&harddog_mutex);
87 return nonseekable_open(inode, file); 88 return nonseekable_open(inode, file);
88err: 89err:
89 spin_unlock(&lock); 90 spin_unlock(&lock);
90 unlock_kernel(); 91 mutex_unlock(&harddog_mutex);
91 return err; 92 return err;
92} 93}
93 94
@@ -153,9 +154,9 @@ static long harddog_ioctl(struct file *file,
153{ 154{
154 long ret; 155 long ret;
155 156
156 lock_kernel(); 157 mutex_lock(&harddog_mutex);
157 ret = harddog_ioctl_unlocked(file, cmd, arg); 158 ret = harddog_ioctl_unlocked(file, cmd, arg);
158 unlock_kernel(); 159 mutex_unlock(&harddog_mutex);
159 160
160 return ret; 161 return ret;
161} 162}
@@ -166,6 +167,7 @@ static const struct file_operations harddog_fops = {
166 .unlocked_ioctl = harddog_ioctl, 167 .unlocked_ioctl = harddog_ioctl,
167 .open = harddog_open, 168 .open = harddog_open,
168 .release = harddog_release, 169 .release = harddog_release,
170 .llseek = no_llseek,
169}; 171};
170 172
171static struct miscdevice harddog_miscdev = { 173static struct miscdevice harddog_miscdev = {
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
index 63c740a85b4c..f9f6a4e20590 100644
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -8,7 +8,7 @@
8#include "linux/slab.h" 8#include "linux/slab.h"
9#include "linux/sound.h" 9#include "linux/sound.h"
10#include "linux/soundcard.h" 10#include "linux/soundcard.h"
11#include "linux/smp_lock.h" 11#include "linux/mutex.h"
12#include "asm/uaccess.h" 12#include "asm/uaccess.h"
13#include "init.h" 13#include "init.h"
14#include "os.h" 14#include "os.h"
@@ -63,6 +63,8 @@ static int set_mixer(char *name, int *add)
63__uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP); 63__uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP);
64#endif 64#endif
65 65
66static DEFINE_MUTEX(hostaudio_mutex);
67
66/* /dev/dsp file operations */ 68/* /dev/dsp file operations */
67 69
68static ssize_t hostaudio_read(struct file *file, char __user *buffer, 70static ssize_t hostaudio_read(struct file *file, char __user *buffer,
@@ -198,9 +200,9 @@ static int hostaudio_open(struct inode *inode, struct file *file)
198 w = 1; 200 w = 1;
199 201
200 kparam_block_sysfs_write(dsp); 202 kparam_block_sysfs_write(dsp);
201 lock_kernel(); 203 mutex_lock(&hostaudio_mutex);
202 ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); 204 ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
203 unlock_kernel(); 205 mutex_unlock(&hostaudio_mutex);
204 kparam_unblock_sysfs_write(dsp); 206 kparam_unblock_sysfs_write(dsp);
205 207
206 if (ret < 0) { 208 if (ret < 0) {
@@ -259,9 +261,9 @@ static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
259 w = 1; 261 w = 1;
260 262
261 kparam_block_sysfs_write(mixer); 263 kparam_block_sysfs_write(mixer);
262 lock_kernel(); 264 mutex_lock(&hostaudio_mutex);
263 ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); 265 ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
264 unlock_kernel(); 266 mutex_unlock(&hostaudio_mutex);
265 kparam_unblock_sysfs_write(mixer); 267 kparam_unblock_sysfs_write(mixer);
266 268
267 if (ret < 0) { 269 if (ret < 0) {
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 7f7338c90784..35dd0b86401a 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -255,8 +255,8 @@ static const struct {
255 { KDSIGACCEPT, KERN_INFO, "KDSIGACCEPT" }, 255 { KDSIGACCEPT, KERN_INFO, "KDSIGACCEPT" },
256}; 256};
257 257
258int line_ioctl(struct tty_struct *tty, struct file * file, 258int line_ioctl(struct tty_struct *tty, unsigned int cmd,
259 unsigned int cmd, unsigned long arg) 259 unsigned long arg)
260{ 260{
261 int ret; 261 int ret;
262 int i; 262 int i;
@@ -727,6 +727,9 @@ struct winch {
727 727
728static void free_winch(struct winch *winch, int free_irq_ok) 728static void free_winch(struct winch *winch, int free_irq_ok)
729{ 729{
730 if (free_irq_ok)
731 free_irq(WINCH_IRQ, winch);
732
730 list_del(&winch->list); 733 list_del(&winch->list);
731 734
732 if (winch->pid != -1) 735 if (winch->pid != -1)
@@ -735,8 +738,6 @@ static void free_winch(struct winch *winch, int free_irq_ok)
735 os_close_file(winch->fd); 738 os_close_file(winch->fd);
736 if (winch->stack != 0) 739 if (winch->stack != 0)
737 free_stack(winch->stack, 0); 740 free_stack(winch->stack, 0);
738 if (free_irq_ok)
739 free_irq(WINCH_IRQ, winch);
740 kfree(winch); 741 kfree(winch);
741} 742}
742 743
@@ -820,12 +821,12 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty,
820 821
821static void unregister_winch(struct tty_struct *tty) 822static void unregister_winch(struct tty_struct *tty)
822{ 823{
823 struct list_head *ele; 824 struct list_head *ele, *next;
824 struct winch *winch; 825 struct winch *winch;
825 826
826 spin_lock(&winch_handler_lock); 827 spin_lock(&winch_handler_lock);
827 828
828 list_for_each(ele, &winch_handlers) { 829 list_for_each_safe(ele, next, &winch_handlers) {
829 winch = list_entry(ele, struct winch, list); 830 winch = list_entry(ele, struct winch, list);
830 if (winch->tty == tty) { 831 if (winch->tty == tty) {
831 free_winch(winch, 1); 832 free_winch(winch, 1);
diff --git a/arch/um/drivers/mcast.h b/arch/um/drivers/mcast.h
deleted file mode 100644
index 6fa282e896be..000000000000
--- a/arch/um/drivers/mcast.h
+++ /dev/null
@@ -1,24 +0,0 @@
1/*
2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __DRIVERS_MCAST_H
7#define __DRIVERS_MCAST_H
8
9#include "net_user.h"
10
11struct mcast_data {
12 char *addr;
13 unsigned short port;
14 void *mcast_addr;
15 int ttl;
16 void *dev;
17};
18
19extern const struct net_user_info mcast_user_info;
20
21extern int mcast_user_write(int fd, void *buf, int len,
22 struct mcast_data *pri);
23
24#endif
diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c
deleted file mode 100644
index ffc6416d5ed7..000000000000
--- a/arch/um/drivers/mcast_kern.c
+++ /dev/null
@@ -1,120 +0,0 @@
1/*
2 * user-mode-linux networking multicast transport
3 * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org>
4 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
5 *
6 * based on the existing uml-networking code, which is
7 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
8 * James Leu (jleu@mindspring.net).
9 * Copyright (C) 2001 by various other people who didn't put their name here.
10 *
11 * Licensed under the GPL.
12 */
13
14#include "linux/init.h"
15#include <linux/netdevice.h>
16#include "mcast.h"
17#include "net_kern.h"
18
19struct mcast_init {
20 char *addr;
21 int port;
22 int ttl;
23};
24
25static void mcast_init(struct net_device *dev, void *data)
26{
27 struct uml_net_private *pri;
28 struct mcast_data *dpri;
29 struct mcast_init *init = data;
30
31 pri = netdev_priv(dev);
32 dpri = (struct mcast_data *) pri->user;
33 dpri->addr = init->addr;
34 dpri->port = init->port;
35 dpri->ttl = init->ttl;
36 dpri->dev = dev;
37
38 printk("mcast backend multicast address: %s:%u, TTL:%u\n",
39 dpri->addr, dpri->port, dpri->ttl);
40}
41
42static int mcast_read(int fd, struct sk_buff *skb, struct uml_net_private *lp)
43{
44 return net_recvfrom(fd, skb_mac_header(skb),
45 skb->dev->mtu + ETH_HEADER_OTHER);
46}
47
48static int mcast_write(int fd, struct sk_buff *skb, struct uml_net_private *lp)
49{
50 return mcast_user_write(fd, skb->data, skb->len,
51 (struct mcast_data *) &lp->user);
52}
53
54static const struct net_kern_info mcast_kern_info = {
55 .init = mcast_init,
56 .protocol = eth_protocol,
57 .read = mcast_read,
58 .write = mcast_write,
59};
60
61static int mcast_setup(char *str, char **mac_out, void *data)
62{
63 struct mcast_init *init = data;
64 char *port_str = NULL, *ttl_str = NULL, *remain;
65 char *last;
66
67 *init = ((struct mcast_init)
68 { .addr = "239.192.168.1",
69 .port = 1102,
70 .ttl = 1 });
71
72 remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str,
73 NULL);
74 if (remain != NULL) {
75 printk(KERN_ERR "mcast_setup - Extra garbage on "
76 "specification : '%s'\n", remain);
77 return 0;
78 }
79
80 if (port_str != NULL) {
81 init->port = simple_strtoul(port_str, &last, 10);
82 if ((*last != '\0') || (last == port_str)) {
83 printk(KERN_ERR "mcast_setup - Bad port : '%s'\n",
84 port_str);
85 return 0;
86 }
87 }
88
89 if (ttl_str != NULL) {
90 init->ttl = simple_strtoul(ttl_str, &last, 10);
91 if ((*last != '\0') || (last == ttl_str)) {
92 printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n",
93 ttl_str);
94 return 0;
95 }
96 }
97
98 printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr,
99 init->port, init->ttl);
100
101 return 1;
102}
103
104static struct transport mcast_transport = {
105 .list = LIST_HEAD_INIT(mcast_transport.list),
106 .name = "mcast",
107 .setup = mcast_setup,
108 .user = &mcast_user_info,
109 .kern = &mcast_kern_info,
110 .private_size = sizeof(struct mcast_data),
111 .setup_size = sizeof(struct mcast_init),
112};
113
114static int register_mcast(void)
115{
116 register_transport(&mcast_transport);
117 return 0;
118}
119
120late_initcall(register_mcast);
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
deleted file mode 100644
index ee19e91568a2..000000000000
--- a/arch/um/drivers/mcast_user.c
+++ /dev/null
@@ -1,165 +0,0 @@
1/*
2 * user-mode-linux networking multicast transport
3 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
4 * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org>
5 *
6 * based on the existing uml-networking code, which is
7 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
8 * James Leu (jleu@mindspring.net).
9 * Copyright (C) 2001 by various other people who didn't put their name here.
10 *
11 * Licensed under the GPL.
12 *
13 */
14
15#include <unistd.h>
16#include <errno.h>
17#include <netinet/in.h>
18#include "kern_constants.h"
19#include "mcast.h"
20#include "net_user.h"
21#include "um_malloc.h"
22#include "user.h"
23
24static struct sockaddr_in *new_addr(char *addr, unsigned short port)
25{
26 struct sockaddr_in *sin;
27
28 sin = uml_kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL);
29 if (sin == NULL) {
30 printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in "
31 "failed\n");
32 return NULL;
33 }
34 sin->sin_family = AF_INET;
35 sin->sin_addr.s_addr = in_aton(addr);
36 sin->sin_port = htons(port);
37 return sin;
38}
39
40static int mcast_user_init(void *data, void *dev)
41{
42 struct mcast_data *pri = data;
43
44 pri->mcast_addr = new_addr(pri->addr, pri->port);
45 pri->dev = dev;
46 return 0;
47}
48
49static void mcast_remove(void *data)
50{
51 struct mcast_data *pri = data;
52
53 kfree(pri->mcast_addr);
54 pri->mcast_addr = NULL;
55}
56
57static int mcast_open(void *data)
58{
59 struct mcast_data *pri = data;
60 struct sockaddr_in *sin = pri->mcast_addr;
61 struct ip_mreq mreq;
62 int fd, yes = 1, err = -EINVAL;
63
64
65 if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0))
66 goto out;
67
68 fd = socket(AF_INET, SOCK_DGRAM, 0);
69
70 if (fd < 0) {
71 err = -errno;
72 printk(UM_KERN_ERR "mcast_open : data socket failed, "
73 "errno = %d\n", errno);
74 goto out;
75 }
76
77 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
78 err = -errno;
79 printk(UM_KERN_ERR "mcast_open: SO_REUSEADDR failed, "
80 "errno = %d\n", errno);
81 goto out_close;
82 }
83
84 /* set ttl according to config */
85 if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl,
86 sizeof(pri->ttl)) < 0) {
87 err = -errno;
88 printk(UM_KERN_ERR "mcast_open: IP_MULTICAST_TTL failed, "
89 "error = %d\n", errno);
90 goto out_close;
91 }
92
93 /* set LOOP, so data does get fed back to local sockets */
94 if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
95 err = -errno;
96 printk(UM_KERN_ERR "mcast_open: IP_MULTICAST_LOOP failed, "
97 "error = %d\n", errno);
98 goto out_close;
99 }
100
101 /* bind socket to mcast address */
102 if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
103 err = -errno;
104 printk(UM_KERN_ERR "mcast_open : data bind failed, "
105 "errno = %d\n", errno);
106 goto out_close;
107 }
108
109 /* subscribe to the multicast group */
110 mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr;
111 mreq.imr_interface.s_addr = 0;
112 if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP,
113 &mreq, sizeof(mreq)) < 0) {
114 err = -errno;
115 printk(UM_KERN_ERR "mcast_open: IP_ADD_MEMBERSHIP failed, "
116 "error = %d\n", errno);
117 printk(UM_KERN_ERR "There appears not to be a multicast-"
118 "capable network interface on the host.\n");
119 printk(UM_KERN_ERR "eth0 should be configured in order to use "
120 "the multicast transport.\n");
121 goto out_close;
122 }
123
124 return fd;
125
126 out_close:
127 close(fd);
128 out:
129 return err;
130}
131
132static void mcast_close(int fd, void *data)
133{
134 struct ip_mreq mreq;
135 struct mcast_data *pri = data;
136 struct sockaddr_in *sin = pri->mcast_addr;
137
138 mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr;
139 mreq.imr_interface.s_addr = 0;
140 if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP,
141 &mreq, sizeof(mreq)) < 0) {
142 printk(UM_KERN_ERR "mcast_open: IP_DROP_MEMBERSHIP failed, "
143 "error = %d\n", errno);
144 }
145
146 close(fd);
147}
148
149int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri)
150{
151 struct sockaddr_in *data_addr = pri->mcast_addr;
152
153 return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr));
154}
155
156const struct net_user_info mcast_user_info = {
157 .init = mcast_user_init,
158 .open = mcast_open,
159 .close = mcast_close,
160 .remove = mcast_remove,
161 .add_address = NULL,
162 .delete_address = NULL,
163 .mtu = ETH_MAX_PACKET,
164 .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER,
165};
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index ebc680717e59..c70e047eed72 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -124,35 +124,18 @@ void mconsole_log(struct mc_request *req)
124#if 0 124#if 0
125void mconsole_proc(struct mc_request *req) 125void mconsole_proc(struct mc_request *req)
126{ 126{
127 struct nameidata nd;
128 struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt; 127 struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt;
129 struct file *file; 128 struct file *file;
130 int n, err; 129 int n;
131 char *ptr = req->request.data, *buf; 130 char *ptr = req->request.data, *buf;
132 mm_segment_t old_fs = get_fs(); 131 mm_segment_t old_fs = get_fs();
133 132
134 ptr += strlen("proc"); 133 ptr += strlen("proc");
135 ptr = skip_spaces(ptr); 134 ptr = skip_spaces(ptr);
136 135
137 err = vfs_path_lookup(mnt->mnt_root, mnt, ptr, LOOKUP_FOLLOW, &nd); 136 file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY);
138 if (err) {
139 mconsole_reply(req, "Failed to look up file", 1, 0);
140 goto out;
141 }
142
143 err = may_open(&nd.path, MAY_READ, O_RDONLY);
144 if (result) {
145 mconsole_reply(req, "Failed to open file", 1, 0);
146 path_put(&nd.path);
147 goto out;
148 }
149
150 file = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY,
151 current_cred());
152 err = PTR_ERR(file);
153 if (IS_ERR(file)) { 137 if (IS_ERR(file)) {
154 mconsole_reply(req, "Failed to open file", 1, 0); 138 mconsole_reply(req, "Failed to open file", 1, 0);
155 path_put(&nd.path);
156 goto out; 139 goto out;
157 } 140 }
158 141
@@ -843,6 +826,7 @@ static ssize_t mconsole_proc_write(struct file *file,
843static const struct file_operations mconsole_proc_fops = { 826static const struct file_operations mconsole_proc_fops = {
844 .owner = THIS_MODULE, 827 .owner = THIS_MODULE,
845 .write = mconsole_proc_write, 828 .write = mconsole_proc_write,
829 .llseek = noop_llseek,
846}; 830};
847 831
848static int create_proc_mconsole(void) 832static int create_proc_mconsole(void)
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c
index 7158393b6793..c0ef803c7c70 100644
--- a/arch/um/drivers/mmapper_kern.c
+++ b/arch/um/drivers/mmapper_kern.c
@@ -37,13 +37,7 @@ static ssize_t mmapper_write(struct file *file, const char __user *buf,
37 if (*ppos > mmapper_size) 37 if (*ppos > mmapper_size)
38 return -EINVAL; 38 return -EINVAL;
39 39
40 if (count > mmapper_size - *ppos) 40 return simple_write_to_buffer(v_buf, mmapper_size, ppos, buf, count);
41 count = mmapper_size - *ppos;
42
43 if (copy_from_user(&v_buf[*ppos], buf, count))
44 return -EFAULT;
45
46 return count;
47} 41}
48 42
49static long mmapper_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 43static long mmapper_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -93,6 +87,7 @@ static const struct file_operations mmapper_fops = {
93 .mmap = mmapper_mmap, 87 .mmap = mmapper_mmap,
94 .open = mmapper_open, 88 .open = mmapper_open,
95 .release = mmapper_release, 89 .release = mmapper_release,
90 .llseek = default_llseek,
96}; 91};
97 92
98/* 93/*
@@ -121,7 +116,7 @@ static int __init mmapper_init(void)
121 if (err) { 116 if (err) {
122 printk(KERN_ERR "mmapper - misc_register failed, err = %d\n", 117 printk(KERN_ERR "mmapper - misc_register failed, err = %d\n",
123 err); 118 err);
124 return err;; 119 return err;
125 } 120 }
126 return 0; 121 return 0;
127} 122}
@@ -136,3 +131,4 @@ module_exit(mmapper_exit);
136 131
137MODULE_AUTHOR("Greg Lonnon <glonnon@ridgerun.com>"); 132MODULE_AUTHOR("Greg Lonnon <glonnon@ridgerun.com>");
138MODULE_DESCRIPTION("DSPLinux simulator mmapper driver"); 133MODULE_DESCRIPTION("DSPLinux simulator mmapper driver");
134MODULE_LICENSE("GPL");
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index 4949044773ba..981085a93f30 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -100,6 +100,7 @@ static const struct file_operations rng_chrdev_ops = {
100 .owner = THIS_MODULE, 100 .owner = THIS_MODULE,
101 .open = rng_dev_open, 101 .open = rng_dev_open,
102 .read = rng_dev_read, 102 .read = rng_dev_read,
103 .llseek = noop_llseek,
103}; 104};
104 105
105/* rng_init shouldn't be called more than once at boot time */ 106/* rng_init shouldn't be called more than once at boot time */
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 9734994cba1e..620f5b70957d 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -33,7 +33,7 @@
33#include "linux/mm.h" 33#include "linux/mm.h"
34#include "linux/slab.h" 34#include "linux/slab.h"
35#include "linux/vmalloc.h" 35#include "linux/vmalloc.h"
36#include "linux/smp_lock.h" 36#include "linux/mutex.h"
37#include "linux/blkpg.h" 37#include "linux/blkpg.h"
38#include "linux/genhd.h" 38#include "linux/genhd.h"
39#include "linux/spinlock.h" 39#include "linux/spinlock.h"
@@ -100,6 +100,7 @@ static inline void ubd_set_bit(__u64 bit, unsigned char *data)
100#define DRIVER_NAME "uml-blkdev" 100#define DRIVER_NAME "uml-blkdev"
101 101
102static DEFINE_MUTEX(ubd_lock); 102static DEFINE_MUTEX(ubd_lock);
103static DEFINE_MUTEX(ubd_mutex); /* replaces BKL, might not be needed */
103 104
104static int ubd_open(struct block_device *bdev, fmode_t mode); 105static int ubd_open(struct block_device *bdev, fmode_t mode);
105static int ubd_release(struct gendisk *disk, fmode_t mode); 106static int ubd_release(struct gendisk *disk, fmode_t mode);
@@ -184,7 +185,7 @@ struct ubd {
184 .no_cow = 0, \ 185 .no_cow = 0, \
185 .shared = 0, \ 186 .shared = 0, \
186 .cow = DEFAULT_COW, \ 187 .cow = DEFAULT_COW, \
187 .lock = SPIN_LOCK_UNLOCKED, \ 188 .lock = __SPIN_LOCK_UNLOCKED(ubd_devs.lock), \
188 .request = NULL, \ 189 .request = NULL, \
189 .start_sg = 0, \ 190 .start_sg = 0, \
190 .end_sg = 0, \ 191 .end_sg = 0, \
@@ -1101,7 +1102,7 @@ static int ubd_open(struct block_device *bdev, fmode_t mode)
1101 struct ubd *ubd_dev = disk->private_data; 1102 struct ubd *ubd_dev = disk->private_data;
1102 int err = 0; 1103 int err = 0;
1103 1104
1104 lock_kernel(); 1105 mutex_lock(&ubd_mutex);
1105 if(ubd_dev->count == 0){ 1106 if(ubd_dev->count == 0){
1106 err = ubd_open_dev(ubd_dev); 1107 err = ubd_open_dev(ubd_dev);
1107 if(err){ 1108 if(err){
@@ -1120,7 +1121,7 @@ static int ubd_open(struct block_device *bdev, fmode_t mode)
1120 err = -EROFS; 1121 err = -EROFS;
1121 }*/ 1122 }*/
1122out: 1123out:
1123 unlock_kernel(); 1124 mutex_unlock(&ubd_mutex);
1124 return err; 1125 return err;
1125} 1126}
1126 1127
@@ -1128,10 +1129,10 @@ static int ubd_release(struct gendisk *disk, fmode_t mode)
1128{ 1129{
1129 struct ubd *ubd_dev = disk->private_data; 1130 struct ubd *ubd_dev = disk->private_data;
1130 1131
1131 lock_kernel(); 1132 mutex_lock(&ubd_mutex);
1132 if(--ubd_dev->count == 0) 1133 if(--ubd_dev->count == 0)
1133 ubd_close_dev(ubd_dev); 1134 ubd_close_dev(ubd_dev);
1134 unlock_kernel(); 1135 mutex_unlock(&ubd_mutex);
1135 return 0; 1136 return 0;
1136} 1137}
1137 1138
diff --git a/arch/um/drivers/umcast.h b/arch/um/drivers/umcast.h
new file mode 100644
index 000000000000..6f8c0fe890fb
--- /dev/null
+++ b/arch/um/drivers/umcast.h
@@ -0,0 +1,27 @@
1/*
2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __DRIVERS_UMCAST_H
7#define __DRIVERS_UMCAST_H
8
9#include "net_user.h"
10
11struct umcast_data {
12 char *addr;
13 unsigned short lport;
14 unsigned short rport;
15 void *listen_addr;
16 void *remote_addr;
17 int ttl;
18 int unicast;
19 void *dev;
20};
21
22extern const struct net_user_info umcast_user_info;
23
24extern int umcast_user_write(int fd, void *buf, int len,
25 struct umcast_data *pri);
26
27#endif
diff --git a/arch/um/drivers/umcast_kern.c b/arch/um/drivers/umcast_kern.c
new file mode 100644
index 000000000000..42dab11d2ecf
--- /dev/null
+++ b/arch/um/drivers/umcast_kern.c
@@ -0,0 +1,188 @@
1/*
2 * user-mode-linux networking multicast transport
3 * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org>
4 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
5 *
6 * based on the existing uml-networking code, which is
7 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
8 * James Leu (jleu@mindspring.net).
9 * Copyright (C) 2001 by various other people who didn't put their name here.
10 *
11 * Licensed under the GPL.
12 */
13
14#include "linux/init.h"
15#include <linux/netdevice.h>
16#include "umcast.h"
17#include "net_kern.h"
18
19struct umcast_init {
20 char *addr;
21 int lport;
22 int rport;
23 int ttl;
24 bool unicast;
25};
26
27static void umcast_init(struct net_device *dev, void *data)
28{
29 struct uml_net_private *pri;
30 struct umcast_data *dpri;
31 struct umcast_init *init = data;
32
33 pri = netdev_priv(dev);
34 dpri = (struct umcast_data *) pri->user;
35 dpri->addr = init->addr;
36 dpri->lport = init->lport;
37 dpri->rport = init->rport;
38 dpri->unicast = init->unicast;
39 dpri->ttl = init->ttl;
40 dpri->dev = dev;
41
42 if (dpri->unicast) {
43 printk(KERN_INFO "ucast backend address: %s:%u listen port: "
44 "%u\n", dpri->addr, dpri->rport, dpri->lport);
45 } else {
46 printk(KERN_INFO "mcast backend multicast address: %s:%u, "
47 "TTL:%u\n", dpri->addr, dpri->lport, dpri->ttl);
48 }
49}
50
51static int umcast_read(int fd, struct sk_buff *skb, struct uml_net_private *lp)
52{
53 return net_recvfrom(fd, skb_mac_header(skb),
54 skb->dev->mtu + ETH_HEADER_OTHER);
55}
56
57static int umcast_write(int fd, struct sk_buff *skb, struct uml_net_private *lp)
58{
59 return umcast_user_write(fd, skb->data, skb->len,
60 (struct umcast_data *) &lp->user);
61}
62
63static const struct net_kern_info umcast_kern_info = {
64 .init = umcast_init,
65 .protocol = eth_protocol,
66 .read = umcast_read,
67 .write = umcast_write,
68};
69
70static int mcast_setup(char *str, char **mac_out, void *data)
71{
72 struct umcast_init *init = data;
73 char *port_str = NULL, *ttl_str = NULL, *remain;
74 char *last;
75
76 *init = ((struct umcast_init)
77 { .addr = "239.192.168.1",
78 .lport = 1102,
79 .ttl = 1 });
80
81 remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str,
82 NULL);
83 if (remain != NULL) {
84 printk(KERN_ERR "mcast_setup - Extra garbage on "
85 "specification : '%s'\n", remain);
86 return 0;
87 }
88
89 if (port_str != NULL) {
90 init->lport = simple_strtoul(port_str, &last, 10);
91 if ((*last != '\0') || (last == port_str)) {
92 printk(KERN_ERR "mcast_setup - Bad port : '%s'\n",
93 port_str);
94 return 0;
95 }
96 }
97
98 if (ttl_str != NULL) {
99 init->ttl = simple_strtoul(ttl_str, &last, 10);
100 if ((*last != '\0') || (last == ttl_str)) {
101 printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n",
102 ttl_str);
103 return 0;
104 }
105 }
106
107 init->unicast = false;
108 init->rport = init->lport;
109
110 printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr,
111 init->lport, init->ttl);
112
113 return 1;
114}
115
116static int ucast_setup(char *str, char **mac_out, void *data)
117{
118 struct umcast_init *init = data;
119 char *lport_str = NULL, *rport_str = NULL, *remain;
120 char *last;
121
122 *init = ((struct umcast_init)
123 { .addr = "",
124 .lport = 1102,
125 .rport = 1102 });
126
127 remain = split_if_spec(str, mac_out, &init->addr,
128 &lport_str, &rport_str, NULL);
129 if (remain != NULL) {
130 printk(KERN_ERR "ucast_setup - Extra garbage on "
131 "specification : '%s'\n", remain);
132 return 0;
133 }
134
135 if (lport_str != NULL) {
136 init->lport = simple_strtoul(lport_str, &last, 10);
137 if ((*last != '\0') || (last == lport_str)) {
138 printk(KERN_ERR "ucast_setup - Bad listen port : "
139 "'%s'\n", lport_str);
140 return 0;
141 }
142 }
143
144 if (rport_str != NULL) {
145 init->rport = simple_strtoul(rport_str, &last, 10);
146 if ((*last != '\0') || (last == rport_str)) {
147 printk(KERN_ERR "ucast_setup - Bad remote port : "
148 "'%s'\n", rport_str);
149 return 0;
150 }
151 }
152
153 init->unicast = true;
154
155 printk(KERN_INFO "Configured ucast device: :%u -> %s:%u\n",
156 init->lport, init->addr, init->rport);
157
158 return 1;
159}
160
161static struct transport mcast_transport = {
162 .list = LIST_HEAD_INIT(mcast_transport.list),
163 .name = "mcast",
164 .setup = mcast_setup,
165 .user = &umcast_user_info,
166 .kern = &umcast_kern_info,
167 .private_size = sizeof(struct umcast_data),
168 .setup_size = sizeof(struct umcast_init),
169};
170
171static struct transport ucast_transport = {
172 .list = LIST_HEAD_INIT(ucast_transport.list),
173 .name = "ucast",
174 .setup = ucast_setup,
175 .user = &umcast_user_info,
176 .kern = &umcast_kern_info,
177 .private_size = sizeof(struct umcast_data),
178 .setup_size = sizeof(struct umcast_init),
179};
180
181static int register_umcast(void)
182{
183 register_transport(&mcast_transport);
184 register_transport(&ucast_transport);
185 return 0;
186}
187
188late_initcall(register_umcast);
diff --git a/arch/um/drivers/umcast_user.c b/arch/um/drivers/umcast_user.c
new file mode 100644
index 000000000000..59c56fd6f52a
--- /dev/null
+++ b/arch/um/drivers/umcast_user.c
@@ -0,0 +1,186 @@
1/*
2 * user-mode-linux networking multicast transport
3 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
4 * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org>
5 *
6 * based on the existing uml-networking code, which is
7 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
8 * James Leu (jleu@mindspring.net).
9 * Copyright (C) 2001 by various other people who didn't put their name here.
10 *
11 * Licensed under the GPL.
12 *
13 */
14
15#include <unistd.h>
16#include <errno.h>
17#include <netinet/in.h>
18#include "kern_constants.h"
19#include "umcast.h"
20#include "net_user.h"
21#include "um_malloc.h"
22#include "user.h"
23
24static struct sockaddr_in *new_addr(char *addr, unsigned short port)
25{
26 struct sockaddr_in *sin;
27
28 sin = uml_kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL);
29 if (sin == NULL) {
30 printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in "
31 "failed\n");
32 return NULL;
33 }
34 sin->sin_family = AF_INET;
35 if (addr)
36 sin->sin_addr.s_addr = in_aton(addr);
37 else
38 sin->sin_addr.s_addr = INADDR_ANY;
39 sin->sin_port = htons(port);
40 return sin;
41}
42
43static int umcast_user_init(void *data, void *dev)
44{
45 struct umcast_data *pri = data;
46
47 pri->remote_addr = new_addr(pri->addr, pri->rport);
48 if (pri->unicast)
49 pri->listen_addr = new_addr(NULL, pri->lport);
50 else
51 pri->listen_addr = pri->remote_addr;
52 pri->dev = dev;
53 return 0;
54}
55
56static void umcast_remove(void *data)
57{
58 struct umcast_data *pri = data;
59
60 kfree(pri->listen_addr);
61 if (pri->unicast)
62 kfree(pri->remote_addr);
63 pri->listen_addr = pri->remote_addr = NULL;
64}
65
66static int umcast_open(void *data)
67{
68 struct umcast_data *pri = data;
69 struct sockaddr_in *lsin = pri->listen_addr;
70 struct sockaddr_in *rsin = pri->remote_addr;
71 struct ip_mreq mreq;
72 int fd, yes = 1, err = -EINVAL;
73
74
75 if ((!pri->unicast && lsin->sin_addr.s_addr == 0) ||
76 (rsin->sin_addr.s_addr == 0) ||
77 (lsin->sin_port == 0) || (rsin->sin_port == 0))
78 goto out;
79
80 fd = socket(AF_INET, SOCK_DGRAM, 0);
81
82 if (fd < 0) {
83 err = -errno;
84 printk(UM_KERN_ERR "umcast_open : data socket failed, "
85 "errno = %d\n", errno);
86 goto out;
87 }
88
89 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
90 err = -errno;
91 printk(UM_KERN_ERR "umcast_open: SO_REUSEADDR failed, "
92 "errno = %d\n", errno);
93 goto out_close;
94 }
95
96 if (!pri->unicast) {
97 /* set ttl according to config */
98 if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl,
99 sizeof(pri->ttl)) < 0) {
100 err = -errno;
101 printk(UM_KERN_ERR "umcast_open: IP_MULTICAST_TTL "
102 "failed, error = %d\n", errno);
103 goto out_close;
104 }
105
106 /* set LOOP, so data does get fed back to local sockets */
107 if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP,
108 &yes, sizeof(yes)) < 0) {
109 err = -errno;
110 printk(UM_KERN_ERR "umcast_open: IP_MULTICAST_LOOP "
111 "failed, error = %d\n", errno);
112 goto out_close;
113 }
114 }
115
116 /* bind socket to the address */
117 if (bind(fd, (struct sockaddr *) lsin, sizeof(*lsin)) < 0) {
118 err = -errno;
119 printk(UM_KERN_ERR "umcast_open : data bind failed, "
120 "errno = %d\n", errno);
121 goto out_close;
122 }
123
124 if (!pri->unicast) {
125 /* subscribe to the multicast group */
126 mreq.imr_multiaddr.s_addr = lsin->sin_addr.s_addr;
127 mreq.imr_interface.s_addr = 0;
128 if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP,
129 &mreq, sizeof(mreq)) < 0) {
130 err = -errno;
131 printk(UM_KERN_ERR "umcast_open: IP_ADD_MEMBERSHIP "
132 "failed, error = %d\n", errno);
133 printk(UM_KERN_ERR "There appears not to be a "
134 "multicast-capable network interface on the "
135 "host.\n");
136 printk(UM_KERN_ERR "eth0 should be configured in order "
137 "to use the multicast transport.\n");
138 goto out_close;
139 }
140 }
141
142 return fd;
143
144 out_close:
145 close(fd);
146 out:
147 return err;
148}
149
150static void umcast_close(int fd, void *data)
151{
152 struct umcast_data *pri = data;
153
154 if (!pri->unicast) {
155 struct ip_mreq mreq;
156 struct sockaddr_in *lsin = pri->listen_addr;
157
158 mreq.imr_multiaddr.s_addr = lsin->sin_addr.s_addr;
159 mreq.imr_interface.s_addr = 0;
160 if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP,
161 &mreq, sizeof(mreq)) < 0) {
162 printk(UM_KERN_ERR "umcast_close: IP_DROP_MEMBERSHIP "
163 "failed, error = %d\n", errno);
164 }
165 }
166
167 close(fd);
168}
169
170int umcast_user_write(int fd, void *buf, int len, struct umcast_data *pri)
171{
172 struct sockaddr_in *data_addr = pri->remote_addr;
173
174 return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr));
175}
176
177const struct net_user_info umcast_user_info = {
178 .init = umcast_user_init,
179 .open = umcast_open,
180 .close = umcast_close,
181 .remove = umcast_remove,
182 .add_address = NULL,
183 .delete_address = NULL,
184 .mtu = ETH_MAX_PACKET,
185 .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER,
186};
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index da2caa5a21ef..8ac7146c237f 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -90,7 +90,7 @@ static int xterm_open(int input, int output, int primary, void *d,
90 int pid, fd, new, err; 90 int pid, fd, new, err;
91 char title[256], file[] = "/tmp/xterm-pipeXXXXXX"; 91 char title[256], file[] = "/tmp/xterm-pipeXXXXXX";
92 char *argv[] = { terminal_emulator, title_switch, title, exec_switch, 92 char *argv[] = { terminal_emulator, title_switch, title, exec_switch,
93 "/usr/lib/uml/port-helper", "-uml-socket", 93 OS_LIB_PATH "/uml/port-helper", "-uml-socket",
94 file, NULL }; 94 file, NULL };
95 95
96 if (access(argv[4], X_OK) < 0) 96 if (access(argv[4], X_OK) < 0)
diff --git a/arch/um/include/asm/bug.h b/arch/um/include/asm/bug.h
new file mode 100644
index 000000000000..9e33b864c359
--- /dev/null
+++ b/arch/um/include/asm/bug.h
@@ -0,0 +1,6 @@
1#ifndef __UM_BUG_H
2#define __UM_BUG_H
3
4#include <asm-generic/bug.h>
5
6#endif
diff --git a/arch/um/include/asm/common.lds.S b/arch/um/include/asm/common.lds.S
index ac55b9efa1ce..4938de5512d2 100644
--- a/arch/um/include/asm/common.lds.S
+++ b/arch/um/include/asm/common.lds.S
@@ -42,7 +42,7 @@
42 INIT_SETUP(0) 42 INIT_SETUP(0)
43 } 43 }
44 44
45 PERCPU(32) 45 PERCPU_SECTION(32)
46 46
47 .initcall.init : { 47 .initcall.init : {
48 INIT_CALLS 48 INIT_CALLS
diff --git a/arch/um/include/asm/dma-mapping.h b/arch/um/include/asm/dma-mapping.h
deleted file mode 100644
index 1f469e80fdd3..000000000000
--- a/arch/um/include/asm/dma-mapping.h
+++ /dev/null
@@ -1,112 +0,0 @@
1#ifndef _ASM_DMA_MAPPING_H
2#define _ASM_DMA_MAPPING_H
3
4#include <asm/scatterlist.h>
5
6static inline int
7dma_supported(struct device *dev, u64 mask)
8{
9 BUG();
10 return(0);
11}
12
13static inline int
14dma_set_mask(struct device *dev, u64 dma_mask)
15{
16 BUG();
17 return(0);
18}
19
20static inline void *
21dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
22 gfp_t flag)
23{
24 BUG();
25 return((void *) 0);
26}
27
28static inline void
29dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
30 dma_addr_t dma_handle)
31{
32 BUG();
33}
34
35static inline dma_addr_t
36dma_map_single(struct device *dev, void *cpu_addr, size_t size,
37 enum dma_data_direction direction)
38{
39 BUG();
40 return(0);
41}
42
43static inline void
44dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
45 enum dma_data_direction direction)
46{
47 BUG();
48}
49
50static inline dma_addr_t
51dma_map_page(struct device *dev, struct page *page,
52 unsigned long offset, size_t size,
53 enum dma_data_direction direction)
54{
55 BUG();
56 return(0);
57}
58
59static inline void
60dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
61 enum dma_data_direction direction)
62{
63 BUG();
64}
65
66static inline int
67dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
68 enum dma_data_direction direction)
69{
70 BUG();
71 return(0);
72}
73
74static inline void
75dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
76 enum dma_data_direction direction)
77{
78 BUG();
79}
80
81static inline void
82dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
83 enum dma_data_direction direction)
84{
85 BUG();
86}
87
88static inline void
89dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
90 enum dma_data_direction direction)
91{
92 BUG();
93}
94
95#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
96#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
97
98static inline void
99dma_cache_sync(struct device *dev, void *vaddr, size_t size,
100 enum dma_data_direction direction)
101{
102 BUG();
103}
104
105static inline int
106dma_mapping_error(struct device *dev, dma_addr_t dma_handle)
107{
108 BUG();
109 return 0;
110}
111
112#endif
diff --git a/arch/um/include/asm/percpu.h b/arch/um/include/asm/percpu.h
new file mode 100644
index 000000000000..efe7508d8abd
--- /dev/null
+++ b/arch/um/include/asm/percpu.h
@@ -0,0 +1,6 @@
1#ifndef __UM_PERCPU_H
2#define __UM_PERCPU_H
3
4#include <asm-generic/percpu.h>
5
6#endif /* __UM_PERCPU_H */
diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h
index a9f7251b4a8d..41474fb5eee7 100644
--- a/arch/um/include/asm/pgtable.h
+++ b/arch/um/include/asm/pgtable.h
@@ -338,9 +338,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
338 ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address)) 338 ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address))
339#define pte_offset_map(dir, address) \ 339#define pte_offset_map(dir, address) \
340 ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address)) 340 ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
341#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
342#define pte_unmap(pte) do { } while (0) 341#define pte_unmap(pte) do { } while (0)
343#define pte_unmap_nested(pte) do { } while (0)
344 342
345struct mm_struct; 343struct mm_struct;
346extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr); 344extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr);
diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h
index bed668824b5f..98d01bc4fa92 100644
--- a/arch/um/include/asm/processor-generic.h
+++ b/arch/um/include/asm/processor-generic.h
@@ -14,6 +14,8 @@ struct task_struct;
14#include "registers.h" 14#include "registers.h"
15#include "sysdep/archsetjmp.h" 15#include "sysdep/archsetjmp.h"
16 16
17#include <linux/prefetch.h>
18
17struct mm_struct; 19struct mm_struct;
18 20
19struct thread_struct { 21struct thread_struct {
@@ -66,7 +68,7 @@ struct thread_struct {
66 .request = { 0 } \ 68 .request = { 0 } \
67} 69}
68 70
69extern struct task_struct *alloc_task_struct(void); 71extern struct task_struct *alloc_task_struct_node(int node);
70 72
71static inline void release_thread(struct task_struct *task) 73static inline void release_thread(struct task_struct *task)
72{ 74{
diff --git a/arch/um/include/asm/ptrace-generic.h b/arch/um/include/asm/ptrace-generic.h
index 2cd899f75a3c..b7c5bab9bd77 100644
--- a/arch/um/include/asm/ptrace-generic.h
+++ b/arch/um/include/asm/ptrace-generic.h
@@ -38,8 +38,8 @@ struct pt_regs {
38 38
39struct task_struct; 39struct task_struct;
40 40
41extern long subarch_ptrace(struct task_struct *child, long request, long addr, 41extern long subarch_ptrace(struct task_struct *child, long request,
42 long data); 42 unsigned long addr, unsigned long data);
43extern unsigned long getreg(struct task_struct *child, int regno); 43extern unsigned long getreg(struct task_struct *child, int regno);
44extern int putreg(struct task_struct *child, int regno, unsigned long value); 44extern int putreg(struct task_struct *child, int regno, unsigned long value);
45extern int get_fpregs(struct user_i387_struct __user *buf, 45extern int get_fpregs(struct user_i387_struct __user *buf,
diff --git a/arch/um/include/asm/smp.h b/arch/um/include/asm/smp.h
index f27a96313174..4a4b09d4f366 100644
--- a/arch/um/include/asm/smp.h
+++ b/arch/um/include/asm/smp.h
@@ -11,7 +11,6 @@
11 11
12#define cpu_logical_map(n) (n) 12#define cpu_logical_map(n) (n)
13#define cpu_number_map(n) (n) 13#define cpu_number_map(n) (n)
14#define PROC_CHANGE_PENALTY 15 /* Pick a number, any number */
15extern int hard_smp_processor_id(void); 14extern int hard_smp_processor_id(void);
16#define NO_PROC_ID -1 15#define NO_PROC_ID -1
17 16
diff --git a/arch/um/include/asm/system.h b/arch/um/include/asm/system.h
index 93af1cf0907d..68a90ecd1450 100644
--- a/arch/um/include/asm/system.h
+++ b/arch/um/include/asm/system.h
@@ -8,23 +8,38 @@ extern int set_signals(int enable);
8extern void block_signals(void); 8extern void block_signals(void);
9extern void unblock_signals(void); 9extern void unblock_signals(void);
10 10
11#define local_save_flags(flags) do { typecheck(unsigned long, flags); \ 11static inline unsigned long arch_local_save_flags(void)
12 (flags) = get_signals(); } while(0) 12{
13#define local_irq_restore(flags) do { typecheck(unsigned long, flags); \ 13 return get_signals();
14 set_signals(flags); } while(0) 14}
15 15
16#define local_irq_save(flags) do { local_save_flags(flags); \ 16static inline void arch_local_irq_restore(unsigned long flags)
17 local_irq_disable(); } while(0) 17{
18 18 set_signals(flags);
19#define local_irq_enable() unblock_signals() 19}
20#define local_irq_disable() block_signals() 20
21 21static inline void arch_local_irq_enable(void)
22#define irqs_disabled() \ 22{
23({ \ 23 unblock_signals();
24 unsigned long flags; \ 24}
25 local_save_flags(flags); \ 25
26 (flags == 0); \ 26static inline void arch_local_irq_disable(void)
27}) 27{
28 block_signals();
29}
30
31static inline unsigned long arch_local_irq_save(void)
32{
33 unsigned long flags;
34 flags = arch_local_save_flags();
35 arch_local_irq_disable();
36 return flags;
37}
38
39static inline bool arch_irqs_disabled(void)
40{
41 return arch_local_save_flags() == 0;
42}
28 43
29extern void *_switch_to(void *prev, void *next, void *last); 44extern void *_switch_to(void *prev, void *next, void *last);
30#define switch_to(prev, next, last) prev = _switch_to(prev, next, last) 45#define switch_to(prev, next, last) prev = _switch_to(prev, next, last)
diff --git a/arch/um/include/asm/thread_info.h b/arch/um/include/asm/thread_info.h
index e2cf786bda0a..5bd1bad33fab 100644
--- a/arch/um/include/asm/thread_info.h
+++ b/arch/um/include/asm/thread_info.h
@@ -49,7 +49,10 @@ static inline struct thread_info *current_thread_info(void)
49{ 49{
50 struct thread_info *ti; 50 struct thread_info *ti;
51 unsigned long mask = THREAD_SIZE - 1; 51 unsigned long mask = THREAD_SIZE - 1;
52 ti = (struct thread_info *) (((unsigned long) &ti) & ~mask); 52 void *p;
53
54 asm volatile ("" : "=r" (p) : "0" (&ti));
55 ti = (struct thread_info *) (((unsigned long)p) & ~mask);
53 return ti; 56 return ti;
54} 57}
55 58
diff --git a/arch/um/include/asm/tlb.h b/arch/um/include/asm/tlb.h
index 660caedac9eb..4febacd1a8a1 100644
--- a/arch/um/include/asm/tlb.h
+++ b/arch/um/include/asm/tlb.h
@@ -22,9 +22,6 @@ struct mmu_gather {
22 unsigned int fullmm; /* non-zero means full mm flush */ 22 unsigned int fullmm; /* non-zero means full mm flush */
23}; 23};
24 24
25/* Users of the generic TLB shootdown code must declare this storage space. */
26DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
27
28static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, 25static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep,
29 unsigned long address) 26 unsigned long address)
30{ 27{
@@ -47,27 +44,20 @@ static inline void init_tlb_gather(struct mmu_gather *tlb)
47 } 44 }
48} 45}
49 46
50/* tlb_gather_mmu 47static inline void
51 * Return a pointer to an initialized struct mmu_gather. 48tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush)
52 */
53static inline struct mmu_gather *
54tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
55{ 49{
56 struct mmu_gather *tlb = &get_cpu_var(mmu_gathers);
57
58 tlb->mm = mm; 50 tlb->mm = mm;
59 tlb->fullmm = full_mm_flush; 51 tlb->fullmm = full_mm_flush;
60 52
61 init_tlb_gather(tlb); 53 init_tlb_gather(tlb);
62
63 return tlb;
64} 54}
65 55
66extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, 56extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
67 unsigned long end); 57 unsigned long end);
68 58
69static inline void 59static inline void
70tlb_flush_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) 60tlb_flush_mmu(struct mmu_gather *tlb)
71{ 61{
72 if (!tlb->need_flush) 62 if (!tlb->need_flush)
73 return; 63 return;
@@ -83,12 +73,10 @@ tlb_flush_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
83static inline void 73static inline void
84tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) 74tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
85{ 75{
86 tlb_flush_mmu(tlb, start, end); 76 tlb_flush_mmu(tlb);
87 77
88 /* keep the page table cache within bounds */ 78 /* keep the page table cache within bounds */
89 check_pgt_cache(); 79 check_pgt_cache();
90
91 put_cpu_var(mmu_gathers);
92} 80}
93 81
94/* tlb_remove_page 82/* tlb_remove_page
@@ -96,11 +84,16 @@ tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
96 * while handling the additional races in SMP caused by other CPUs 84 * while handling the additional races in SMP caused by other CPUs
97 * caching valid mappings in their TLBs. 85 * caching valid mappings in their TLBs.
98 */ 86 */
99static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) 87static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page)
100{ 88{
101 tlb->need_flush = 1; 89 tlb->need_flush = 1;
102 free_page_and_swap_cache(page); 90 free_page_and_swap_cache(page);
103 return; 91 return 1; /* avoid calling tlb_flush_mmu */
92}
93
94static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
95{
96 __tlb_remove_page(tlb, page);
104} 97}
105 98
106/** 99/**
diff --git a/arch/um/include/shared/line.h b/arch/um/include/shared/line.h
index 311a0d3d93af..72f4f25af247 100644
--- a/arch/um/include/shared/line.h
+++ b/arch/um/include/shared/line.h
@@ -77,8 +77,8 @@ extern int line_chars_in_buffer(struct tty_struct *tty);
77extern void line_flush_buffer(struct tty_struct *tty); 77extern void line_flush_buffer(struct tty_struct *tty);
78extern void line_flush_chars(struct tty_struct *tty); 78extern void line_flush_chars(struct tty_struct *tty);
79extern int line_write_room(struct tty_struct *tty); 79extern int line_write_room(struct tty_struct *tty);
80extern int line_ioctl(struct tty_struct *tty, struct file * file, 80extern int line_ioctl(struct tty_struct *tty, unsigned int cmd,
81 unsigned int cmd, unsigned long arg); 81 unsigned long arg);
82extern void line_throttle(struct tty_struct *tty); 82extern void line_throttle(struct tty_struct *tty);
83extern void line_unthrottle(struct tty_struct *tty); 83extern void line_unthrottle(struct tty_struct *tty);
84 84
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h
index c4617baaa4f2..83c7c2ecd614 100644
--- a/arch/um/include/shared/os.h
+++ b/arch/um/include/shared/os.h
@@ -29,6 +29,12 @@
29#define OS_ACC_R_OK 4 /* Test for read permission. */ 29#define OS_ACC_R_OK 4 /* Test for read permission. */
30#define OS_ACC_RW_OK (OS_ACC_W_OK | OS_ACC_R_OK) /* Test for RW permission */ 30#define OS_ACC_RW_OK (OS_ACC_W_OK | OS_ACC_R_OK) /* Test for RW permission */
31 31
32#ifdef CONFIG_64BIT
33#define OS_LIB_PATH "/usr/lib64/"
34#else
35#define OS_LIB_PATH "/usr/lib/"
36#endif
37
32/* 38/*
33 * types taken from stat_file() in hostfs_user.c 39 * types taken from stat_file() in hostfs_user.c
34 * (if they are wrong here, they are wrong there...). 40 * (if they are wrong here, they are wrong there...).
@@ -238,6 +244,7 @@ extern int raw(int fd);
238extern void setup_machinename(char *machine_out); 244extern void setup_machinename(char *machine_out);
239extern void setup_hostinfo(char *buf, int len); 245extern void setup_hostinfo(char *buf, int len);
240extern void os_dump_core(void) __attribute__ ((noreturn)); 246extern void os_dump_core(void) __attribute__ ((noreturn));
247extern void um_early_printk(const char *s, unsigned int n);
241 248
242/* time.c */ 249/* time.c */
243extern void idle_sleep(unsigned long long nsecs); 250extern void idle_sleep(unsigned long long nsecs);
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 1119233597a1..c4491c15afb2 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -17,6 +17,7 @@ obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \
17obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o 17obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
18obj-$(CONFIG_GPROF) += gprof_syms.o 18obj-$(CONFIG_GPROF) += gprof_syms.o
19obj-$(CONFIG_GCOV) += gmon_syms.o 19obj-$(CONFIG_GCOV) += gmon_syms.o
20obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
20 21
21USER_OBJS := config.o 22USER_OBJS := config.o
22 23
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index 69268014dd8e..a3cab6d3ae02 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -50,8 +50,18 @@ SECTIONS
50 .rela.got : { *(.rela.got) } 50 .rela.got : { *(.rela.got) }
51 .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } 51 .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
52 .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } 52 .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
53 .rel.plt : { *(.rel.plt) } 53 .rel.plt : {
54 .rela.plt : { *(.rela.plt) } 54 *(.rel.plt)
55 PROVIDE_HIDDEN(__rel_iplt_start = .);
56 *(.rel.iplt)
57 PROVIDE_HIDDEN(__rel_iplt_end = .);
58 }
59 .rela.plt : {
60 *(.rela.plt)
61 PROVIDE_HIDDEN(__rela_iplt_start = .);
62 *(.rela.iplt)
63 PROVIDE_HIDDEN(__rela_iplt_end = .);
64 }
55 .init : { 65 .init : {
56 KEEP (*(.init)) 66 KEEP (*(.init))
57 } =0x90909090 67 } =0x90909090
diff --git a/arch/um/kernel/early_printk.c b/arch/um/kernel/early_printk.c
new file mode 100644
index 000000000000..ec649bf72f68
--- /dev/null
+++ b/arch/um/kernel/early_printk.c
@@ -0,0 +1,33 @@
1/*
2 * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/kernel.h>
10#include <linux/console.h>
11#include <linux/init.h>
12#include "os.h"
13
14static void early_console_write(struct console *con, const char *s, unsigned int n)
15{
16 um_early_printk(s, n);
17}
18
19static struct console early_console = {
20 .name = "earlycon",
21 .write = early_console_write,
22 .flags = CON_BOOT,
23 .index = -1,
24};
25
26static int __init setup_early_printk(char *buf)
27{
28 register_console(&early_console);
29
30 return 0;
31}
32
33early_param("earlyprintk", setup_early_printk);
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 49b5e1eb3262..09bd7b585726 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -5,7 +5,6 @@
5 5
6#include "linux/stddef.h" 6#include "linux/stddef.h"
7#include "linux/fs.h" 7#include "linux/fs.h"
8#include "linux/smp_lock.h"
9#include "linux/ptrace.h" 8#include "linux/ptrace.h"
10#include "linux/sched.h" 9#include "linux/sched.h"
11#include "linux/slab.h" 10#include "linux/slab.h"
@@ -78,13 +77,11 @@ long sys_execve(const char __user *file, const char __user *const __user *argv,
78 long error; 77 long error;
79 char *filename; 78 char *filename;
80 79
81 lock_kernel();
82 filename = getname(file); 80 filename = getname(file);
83 error = PTR_ERR(filename); 81 error = PTR_ERR(filename);
84 if (IS_ERR(filename)) goto out; 82 if (IS_ERR(filename)) goto out;
85 error = execve1(filename, argv, env); 83 error = execve1(filename, argv, env);
86 putname(filename); 84 putname(filename);
87 out: 85 out:
88 unlock_kernel();
89 return error; 86 return error;
90} 87}
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index a3f0b04d7101..9e485c770308 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -18,50 +18,6 @@
18#include "os.h" 18#include "os.h"
19 19
20/* 20/*
21 * Generic, controller-independent functions:
22 */
23
24int show_interrupts(struct seq_file *p, void *v)
25{
26 int i = *(loff_t *) v, j;
27 struct irqaction * action;
28 unsigned long flags;
29
30 if (i == 0) {
31 seq_printf(p, " ");
32 for_each_online_cpu(j)
33 seq_printf(p, "CPU%d ",j);
34 seq_putc(p, '\n');
35 }
36
37 if (i < NR_IRQS) {
38 raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
39 action = irq_desc[i].action;
40 if (!action)
41 goto skip;
42 seq_printf(p, "%3d: ",i);
43#ifndef CONFIG_SMP
44 seq_printf(p, "%10u ", kstat_irqs(i));
45#else
46 for_each_online_cpu(j)
47 seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
48#endif
49 seq_printf(p, " %14s", irq_desc[i].chip->typename);
50 seq_printf(p, " %s", action->name);
51
52 for (action=action->next; action; action = action->next)
53 seq_printf(p, ", %s", action->name);
54
55 seq_putc(p, '\n');
56skip:
57 raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
58 } else if (i == NR_IRQS)
59 seq_putc(p, '\n');
60
61 return 0;
62}
63
64/*
65 * This list is accessed under irq_lock, except in sigio_handler, 21 * This list is accessed under irq_lock, except in sigio_handler,
66 * where it is safe from being modified. IRQ handlers won't change it - 22 * where it is safe from being modified. IRQ handlers won't change it -
67 * if an IRQ source has vanished, it will be freed by free_irqs just 23 * if an IRQ source has vanished, it will be freed by free_irqs just
@@ -334,7 +290,7 @@ unsigned int do_IRQ(int irq, struct uml_pt_regs *regs)
334{ 290{
335 struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs); 291 struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs);
336 irq_enter(); 292 irq_enter();
337 __do_IRQ(irq); 293 generic_handle_irq(irq);
338 irq_exit(); 294 irq_exit();
339 set_irq_regs(old_regs); 295 set_irq_regs(old_regs);
340 return 1; 296 return 1;
@@ -360,49 +316,38 @@ EXPORT_SYMBOL(um_request_irq);
360EXPORT_SYMBOL(reactivate_fd); 316EXPORT_SYMBOL(reactivate_fd);
361 317
362/* 318/*
363 * irq_chip must define (startup || enable) && 319 * irq_chip must define at least enable/disable and ack when
364 * (shutdown || disable) && end 320 * the edge handler is used.
365 */ 321 */
366static void dummy(unsigned int irq) 322static void dummy(struct irq_data *d)
367{ 323{
368} 324}
369 325
370/* This is used for everything else than the timer. */ 326/* This is used for everything else than the timer. */
371static struct irq_chip normal_irq_type = { 327static struct irq_chip normal_irq_type = {
372 .typename = "SIGIO", 328 .name = "SIGIO",
373 .release = free_irq_by_irq_and_dev, 329 .release = free_irq_by_irq_and_dev,
374 .disable = dummy, 330 .irq_disable = dummy,
375 .enable = dummy, 331 .irq_enable = dummy,
376 .ack = dummy, 332 .irq_ack = dummy,
377 .end = dummy
378}; 333};
379 334
380static struct irq_chip SIGVTALRM_irq_type = { 335static struct irq_chip SIGVTALRM_irq_type = {
381 .typename = "SIGVTALRM", 336 .name = "SIGVTALRM",
382 .release = free_irq_by_irq_and_dev, 337 .release = free_irq_by_irq_and_dev,
383 .shutdown = dummy, /* never called */ 338 .irq_disable = dummy,
384 .disable = dummy, 339 .irq_enable = dummy,
385 .enable = dummy, 340 .irq_ack = dummy,
386 .ack = dummy,
387 .end = dummy
388}; 341};
389 342
390void __init init_IRQ(void) 343void __init init_IRQ(void)
391{ 344{
392 int i; 345 int i;
393 346
394 irq_desc[TIMER_IRQ].status = IRQ_DISABLED; 347 irq_set_chip_and_handler(TIMER_IRQ, &SIGVTALRM_irq_type, handle_edge_irq);
395 irq_desc[TIMER_IRQ].action = NULL; 348
396 irq_desc[TIMER_IRQ].depth = 1; 349 for (i = 1; i < NR_IRQS; i++)
397 irq_desc[TIMER_IRQ].chip = &SIGVTALRM_irq_type; 350 irq_set_chip_and_handler(i, &normal_irq_type, handle_edge_irq);
398 enable_irq(TIMER_IRQ);
399 for (i = 1; i < NR_IRQS; i++) {
400 irq_desc[i].status = IRQ_DISABLED;
401 irq_desc[i].action = NULL;
402 irq_desc[i].depth = 1;
403 irq_desc[i].chip = &normal_irq_type;
404 enable_irq(i);
405 }
406} 351}
407 352
408/* 353/*
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index e0510496596c..701b672c1122 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -42,10 +42,12 @@ void ptrace_disable(struct task_struct *child)
42extern int peek_user(struct task_struct * child, long addr, long data); 42extern int peek_user(struct task_struct * child, long addr, long data);
43extern int poke_user(struct task_struct * child, long addr, long data); 43extern int poke_user(struct task_struct * child, long addr, long data);
44 44
45long arch_ptrace(struct task_struct *child, long request, long addr, long data) 45long arch_ptrace(struct task_struct *child, long request,
46 unsigned long addr, unsigned long data)
46{ 47{
47 int i, ret; 48 int i, ret;
48 unsigned long __user *p = (void __user *)(unsigned long)data; 49 unsigned long __user *p = (void __user *)data;
50 void __user *vp = p;
49 51
50 switch (request) { 52 switch (request) {
51 /* read word at location addr. */ 53 /* read word at location addr. */
@@ -107,24 +109,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
107#endif 109#endif
108#ifdef PTRACE_GETFPREGS 110#ifdef PTRACE_GETFPREGS
109 case PTRACE_GETFPREGS: /* Get the child FPU state. */ 111 case PTRACE_GETFPREGS: /* Get the child FPU state. */
110 ret = get_fpregs((struct user_i387_struct __user *) data, 112 ret = get_fpregs(vp, child);
111 child);
112 break; 113 break;
113#endif 114#endif
114#ifdef PTRACE_SETFPREGS 115#ifdef PTRACE_SETFPREGS
115 case PTRACE_SETFPREGS: /* Set the child FPU state. */ 116 case PTRACE_SETFPREGS: /* Set the child FPU state. */
116 ret = set_fpregs((struct user_i387_struct __user *) data, 117 ret = set_fpregs(vp, child);
117 child);
118 break; 118 break;
119#endif 119#endif
120 case PTRACE_GET_THREAD_AREA: 120 case PTRACE_GET_THREAD_AREA:
121 ret = ptrace_get_thread_area(child, addr, 121 ret = ptrace_get_thread_area(child, addr, vp);
122 (struct user_desc __user *) data);
123 break; 122 break;
124 123
125 case PTRACE_SET_THREAD_AREA: 124 case PTRACE_SET_THREAD_AREA:
126 ret = ptrace_set_thread_area(child, addr, 125 ret = ptrace_set_thread_area(child, addr, vp);
127 (struct user_desc __user *) data);
128 break; 126 break;
129 127
130 case PTRACE_FAULTINFO: { 128 case PTRACE_FAULTINFO: {
@@ -134,7 +132,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
134 * On i386, ptrace_faultinfo is smaller! 132 * On i386, ptrace_faultinfo is smaller!
135 */ 133 */
136 ret = copy_to_user(p, &child->thread.arch.faultinfo, 134 ret = copy_to_user(p, &child->thread.arch.faultinfo,
137 sizeof(struct ptrace_faultinfo)); 135 sizeof(struct ptrace_faultinfo)) ?
136 -EIO : 0;
138 break; 137 break;
139 } 138 }
140 139
@@ -158,7 +157,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
158#ifdef PTRACE_ARCH_PRCTL 157#ifdef PTRACE_ARCH_PRCTL
159 case PTRACE_ARCH_PRCTL: 158 case PTRACE_ARCH_PRCTL:
160 /* XXX Calls ptrace on the host - needs some SMP thinking */ 159 /* XXX Calls ptrace on the host - needs some SMP thinking */
161 ret = arch_prctl(child, data, (void *) addr); 160 ret = arch_prctl(child, data, (void __user *) addr);
162 break; 161 break;
163#endif 162#endif
164 default: 163 default:
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 3d099f974785..1aee587e9c5d 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -31,7 +31,7 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
31 if (!pmd) 31 if (!pmd)
32 goto out_pmd; 32 goto out_pmd;
33 33
34 pte = pte_alloc_map(mm, pmd, proc); 34 pte = pte_alloc_map(mm, NULL, pmd, proc);
35 if (!pte) 35 if (!pte)
36 goto out_pte; 36 goto out_pte;
37 37
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
index 106bf27e2a9a..155206a66908 100644
--- a/arch/um/kernel/smp.c
+++ b/arch/um/kernel/smp.c
@@ -7,9 +7,6 @@
7#include "asm/pgalloc.h" 7#include "asm/pgalloc.h"
8#include "asm/tlb.h" 8#include "asm/tlb.h"
9 9
10/* For some reason, mmu_gathers are referenced when CONFIG_SMP is off. */
11DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
12
13#ifdef CONFIG_SMP 10#ifdef CONFIG_SMP
14 11
15#include "linux/sched.h" 12#include "linux/sched.h"
@@ -173,7 +170,7 @@ void IPI_handler(int cpu)
173 break; 170 break;
174 171
175 case 'R': 172 case 'R':
176 set_tsk_need_resched(current); 173 scheduler_ipi();
177 break; 174 break;
178 175
179 case 'S': 176 case 'S':
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 637c6505dc00..8c7b8823d1f0 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -113,6 +113,27 @@ out_of_memory:
113 return 0; 113 return 0;
114} 114}
115 115
116static void show_segv_info(struct uml_pt_regs *regs)
117{
118 struct task_struct *tsk = current;
119 struct faultinfo *fi = UPT_FAULTINFO(regs);
120
121 if (!unhandled_signal(tsk, SIGSEGV))
122 return;
123
124 if (!printk_ratelimit())
125 return;
126
127 printk("%s%s[%d]: segfault at %lx ip %p sp %p error %x",
128 task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
129 tsk->comm, task_pid_nr(tsk), FAULT_ADDRESS(*fi),
130 (void *)UPT_IP(regs), (void *)UPT_SP(regs),
131 fi->error_code);
132
133 print_vma_addr(KERN_CONT " in ", UPT_IP(regs));
134 printk(KERN_CONT "\n");
135}
136
116static void bad_segv(struct faultinfo fi, unsigned long ip) 137static void bad_segv(struct faultinfo fi, unsigned long ip)
117{ 138{
118 struct siginfo si; 139 struct siginfo si;
@@ -141,6 +162,7 @@ void segv_handler(int sig, struct uml_pt_regs *regs)
141 struct faultinfo * fi = UPT_FAULTINFO(regs); 162 struct faultinfo * fi = UPT_FAULTINFO(regs);
142 163
143 if (UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)) { 164 if (UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)) {
165 show_segv_info(regs);
144 bad_segv(*fi, UPT_IP(regs)); 166 bad_segv(*fi, UPT_IP(regs));
145 return; 167 return;
146 } 168 }
@@ -202,6 +224,8 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
202 address, ip); 224 address, ip);
203 } 225 }
204 226
227 show_segv_info(regs);
228
205 if (err == -EACCES) { 229 if (err == -EACCES) {
206 si.si_signo = SIGBUS; 230 si.si_signo = SIGBUS;
207 si.si_errno = 0; 231 si.si_errno = 0;
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index ec6378550671..fbd99402d4d2 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -22,7 +22,7 @@ SECTIONS
22 _text = .; 22 _text = .;
23 _stext = .; 23 _stext = .;
24 __init_begin = .; 24 __init_begin = .;
25 INIT_TEXT_SECTION(PAGE_SIZE) 25 INIT_TEXT_SECTION(0)
26 . = ALIGN(PAGE_SIZE); 26 . = ALIGN(PAGE_SIZE);
27 27
28 .text : 28 .text :
@@ -43,6 +43,23 @@ SECTIONS
43 __syscall_stub_end = .; 43 __syscall_stub_end = .;
44 } 44 }
45 45
46 /*
47 * These are needed even in a static link, even if they wind up being empty.
48 * Newer glibc needs these __rel{,a}_iplt_{start,end} symbols.
49 */
50 .rel.plt : {
51 *(.rel.plt)
52 PROVIDE_HIDDEN(__rel_iplt_start = .);
53 *(.rel.iplt)
54 PROVIDE_HIDDEN(__rel_iplt_end = .);
55 }
56 .rela.plt : {
57 *(.rela.plt)
58 PROVIDE_HIDDEN(__rela_iplt_start = .);
59 *(.rela.iplt)
60 PROVIDE_HIDDEN(__rela_iplt_end = .);
61 }
62
46 #include "asm/common.lds.S" 63 #include "asm/common.lds.S"
47 64
48 init.data : { INIT_DATA } 65 init.data : { INIT_DATA }
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index eee69b9f52c9..fb2a97a75fb1 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -78,7 +78,7 @@ static void install_fatal_handler(int sig)
78 } 78 }
79} 79}
80 80
81#define UML_LIB_PATH ":/usr/lib/uml" 81#define UML_LIB_PATH ":" OS_LIB_PATH "/uml"
82 82
83static void setup_env_path(void) 83static void setup_env_path(void)
84{ 84{
@@ -142,7 +142,6 @@ int __init main(int argc, char **argv, char **envp)
142 */ 142 */
143 install_fatal_handler(SIGINT); 143 install_fatal_handler(SIGINT);
144 install_fatal_handler(SIGTERM); 144 install_fatal_handler(SIGTERM);
145 install_fatal_handler(SIGHUP);
146 145
147 scan_elf_aux(envp); 146 scan_elf_aux(envp);
148 147
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index e0477c3ee894..0c45dc8efb05 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -253,6 +253,7 @@ void init_new_thread_signals(void)
253 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, 253 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM,
254 SIGVTALRM, -1); 254 SIGVTALRM, -1);
255 signal(SIGWINCH, SIG_IGN); 255 signal(SIGWINCH, SIG_IGN);
256 signal(SIGTERM, SIG_DFL);
256} 257}
257 258
258int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr) 259int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr)
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index dec5678fc17f..6e3359d6a839 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -60,7 +60,7 @@ static inline long long timeval_to_ns(const struct timeval *tv)
60long long disable_timer(void) 60long long disable_timer(void)
61{ 61{
62 struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } }); 62 struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } });
63 int remain, max = UM_NSEC_PER_SEC / UM_HZ; 63 long long remain, max = UM_NSEC_PER_SEC / UM_HZ;
64 64
65 if (setitimer(ITIMER_VIRTUAL, &time, &time) < 0) 65 if (setitimer(ITIMER_VIRTUAL, &time, &time) < 0)
66 printk(UM_KERN_ERR "disable_timer - setitimer failed, " 66 printk(UM_KERN_ERR "disable_timer - setitimer failed, "
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index 6ea77979531c..5803b1887672 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -5,6 +5,7 @@
5 5
6#include <stdio.h> 6#include <stdio.h>
7#include <stdlib.h> 7#include <stdlib.h>
8#include <unistd.h>
8#include <errno.h> 9#include <errno.h>
9#include <signal.h> 10#include <signal.h>
10#include <string.h> 11#include <string.h>
@@ -75,6 +76,26 @@ void setup_hostinfo(char *buf, int len)
75 host.release, host.version, host.machine); 76 host.release, host.version, host.machine);
76} 77}
77 78
79/*
80 * We cannot use glibc's abort(). It makes use of tgkill() which
81 * has no effect within UML's kernel threads.
82 * After that glibc would execute an invalid instruction to kill
83 * the calling process and UML crashes with SIGSEGV.
84 */
85static inline void __attribute__ ((noreturn)) uml_abort(void)
86{
87 sigset_t sig;
88
89 fflush(NULL);
90
91 if (!sigemptyset(&sig) && !sigaddset(&sig, SIGABRT))
92 sigprocmask(SIG_UNBLOCK, &sig, 0);
93
94 for (;;)
95 if (kill(getpid(), SIGABRT) < 0)
96 exit(127);
97}
98
78void os_dump_core(void) 99void os_dump_core(void)
79{ 100{
80 int pid; 101 int pid;
@@ -116,5 +137,10 @@ void os_dump_core(void)
116 while ((pid = waitpid(-1, NULL, WNOHANG | __WALL)) > 0) 137 while ((pid = waitpid(-1, NULL, WNOHANG | __WALL)) > 0)
117 os_kill_ptraced_process(pid, 0); 138 os_kill_ptraced_process(pid, 0);
118 139
119 abort(); 140 uml_abort();
141}
142
143void um_early_printk(const char *s, unsigned int n)
144{
145 printf("%.*s", n, s);
120} 146}
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 804b28dd0328..b1da91c1b200 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -4,7 +4,7 @@
4 4
5obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ 5obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
6 ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \ 6 ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \
7 sys_call_table.o tls.o 7 sys_call_table.o tls.o atomic64_cx8_32.o
8 8
9obj-$(CONFIG_BINFMT_ELF) += elfcore.o 9obj-$(CONFIG_BINFMT_ELF) += elfcore.o
10 10
diff --git a/arch/um/sys-i386/asm/elf.h b/arch/um/sys-i386/asm/elf.h
index a979a22a8d9f..d964a4111ac6 100644
--- a/arch/um/sys-i386/asm/elf.h
+++ b/arch/um/sys-i386/asm/elf.h
@@ -75,6 +75,8 @@ typedef struct user_i387_struct elf_fpregset_t;
75 pr_reg[16] = PT_REGS_SS(regs); \ 75 pr_reg[16] = PT_REGS_SS(regs); \
76} while (0); 76} while (0);
77 77
78#define task_pt_regs(t) (&(t)->thread.regs)
79
78struct task_struct; 80struct task_struct;
79 81
80extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu); 82extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu);
diff --git a/arch/um/sys-i386/atomic64_cx8_32.S b/arch/um/sys-i386/atomic64_cx8_32.S
new file mode 100644
index 000000000000..1e901d3d4a95
--- /dev/null
+++ b/arch/um/sys-i386/atomic64_cx8_32.S
@@ -0,0 +1,225 @@
1/*
2 * atomic64_t for 586+
3 *
4 * Copied from arch/x86/lib/atomic64_cx8_32.S
5 *
6 * Copyright © 2010 Luca Barbieri
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 */
14
15#include <linux/linkage.h>
16#include <asm/alternative-asm.h>
17#include <asm/dwarf2.h>
18
19.macro SAVE reg
20 pushl_cfi %\reg
21 CFI_REL_OFFSET \reg, 0
22.endm
23
24.macro RESTORE reg
25 popl_cfi %\reg
26 CFI_RESTORE \reg
27.endm
28
29.macro read64 reg
30 movl %ebx, %eax
31 movl %ecx, %edx
32/* we need LOCK_PREFIX since otherwise cmpxchg8b always does the write */
33 LOCK_PREFIX
34 cmpxchg8b (\reg)
35.endm
36
37ENTRY(atomic64_read_cx8)
38 CFI_STARTPROC
39
40 read64 %ecx
41 ret
42 CFI_ENDPROC
43ENDPROC(atomic64_read_cx8)
44
45ENTRY(atomic64_set_cx8)
46 CFI_STARTPROC
47
481:
49/* we don't need LOCK_PREFIX since aligned 64-bit writes
50 * are atomic on 586 and newer */
51 cmpxchg8b (%esi)
52 jne 1b
53
54 ret
55 CFI_ENDPROC
56ENDPROC(atomic64_set_cx8)
57
58ENTRY(atomic64_xchg_cx8)
59 CFI_STARTPROC
60
61 movl %ebx, %eax
62 movl %ecx, %edx
631:
64 LOCK_PREFIX
65 cmpxchg8b (%esi)
66 jne 1b
67
68 ret
69 CFI_ENDPROC
70ENDPROC(atomic64_xchg_cx8)
71
72.macro addsub_return func ins insc
73ENTRY(atomic64_\func\()_return_cx8)
74 CFI_STARTPROC
75 SAVE ebp
76 SAVE ebx
77 SAVE esi
78 SAVE edi
79
80 movl %eax, %esi
81 movl %edx, %edi
82 movl %ecx, %ebp
83
84 read64 %ebp
851:
86 movl %eax, %ebx
87 movl %edx, %ecx
88 \ins\()l %esi, %ebx
89 \insc\()l %edi, %ecx
90 LOCK_PREFIX
91 cmpxchg8b (%ebp)
92 jne 1b
93
9410:
95 movl %ebx, %eax
96 movl %ecx, %edx
97 RESTORE edi
98 RESTORE esi
99 RESTORE ebx
100 RESTORE ebp
101 ret
102 CFI_ENDPROC
103ENDPROC(atomic64_\func\()_return_cx8)
104.endm
105
106addsub_return add add adc
107addsub_return sub sub sbb
108
109.macro incdec_return func ins insc
110ENTRY(atomic64_\func\()_return_cx8)
111 CFI_STARTPROC
112 SAVE ebx
113
114 read64 %esi
1151:
116 movl %eax, %ebx
117 movl %edx, %ecx
118 \ins\()l $1, %ebx
119 \insc\()l $0, %ecx
120 LOCK_PREFIX
121 cmpxchg8b (%esi)
122 jne 1b
123
12410:
125 movl %ebx, %eax
126 movl %ecx, %edx
127 RESTORE ebx
128 ret
129 CFI_ENDPROC
130ENDPROC(atomic64_\func\()_return_cx8)
131.endm
132
133incdec_return inc add adc
134incdec_return dec sub sbb
135
136ENTRY(atomic64_dec_if_positive_cx8)
137 CFI_STARTPROC
138 SAVE ebx
139
140 read64 %esi
1411:
142 movl %eax, %ebx
143 movl %edx, %ecx
144 subl $1, %ebx
145 sbb $0, %ecx
146 js 2f
147 LOCK_PREFIX
148 cmpxchg8b (%esi)
149 jne 1b
150
1512:
152 movl %ebx, %eax
153 movl %ecx, %edx
154 RESTORE ebx
155 ret
156 CFI_ENDPROC
157ENDPROC(atomic64_dec_if_positive_cx8)
158
159ENTRY(atomic64_add_unless_cx8)
160 CFI_STARTPROC
161 SAVE ebp
162 SAVE ebx
163/* these just push these two parameters on the stack */
164 SAVE edi
165 SAVE esi
166
167 movl %ecx, %ebp
168 movl %eax, %esi
169 movl %edx, %edi
170
171 read64 %ebp
1721:
173 cmpl %eax, 0(%esp)
174 je 4f
1752:
176 movl %eax, %ebx
177 movl %edx, %ecx
178 addl %esi, %ebx
179 adcl %edi, %ecx
180 LOCK_PREFIX
181 cmpxchg8b (%ebp)
182 jne 1b
183
184 movl $1, %eax
1853:
186 addl $8, %esp
187 CFI_ADJUST_CFA_OFFSET -8
188 RESTORE ebx
189 RESTORE ebp
190 ret
1914:
192 cmpl %edx, 4(%esp)
193 jne 2b
194 xorl %eax, %eax
195 jmp 3b
196 CFI_ENDPROC
197ENDPROC(atomic64_add_unless_cx8)
198
199ENTRY(atomic64_inc_not_zero_cx8)
200 CFI_STARTPROC
201 SAVE ebx
202
203 read64 %esi
2041:
205 testl %eax, %eax
206 je 4f
2072:
208 movl %eax, %ebx
209 movl %edx, %ecx
210 addl $1, %ebx
211 adcl $0, %ecx
212 LOCK_PREFIX
213 cmpxchg8b (%esi)
214 jne 1b
215
216 movl $1, %eax
2173:
218 RESTORE ebx
219 ret
2204:
221 testl %edx, %edx
222 jne 2b
223 jmp 3b
224 CFI_ENDPROC
225ENDPROC(atomic64_inc_not_zero_cx8)
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c
index c9b176534d65..d23b2d3ea384 100644
--- a/arch/um/sys-i386/ptrace.c
+++ b/arch/um/sys-i386/ptrace.c
@@ -203,8 +203,8 @@ int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
203 (unsigned long *) &fpregs); 203 (unsigned long *) &fpregs);
204} 204}
205 205
206long subarch_ptrace(struct task_struct *child, long request, long addr, 206long subarch_ptrace(struct task_struct *child, long request,
207 long data) 207 unsigned long addr, unsigned long data)
208{ 208{
209 return -EIO; 209 return -EIO;
210} 210}
diff --git a/arch/um/sys-ppc/Makefile b/arch/um/sys-ppc/Makefile
index b8bc844fd2c4..20d363bd7004 100644
--- a/arch/um/sys-ppc/Makefile
+++ b/arch/um/sys-ppc/Makefile
@@ -6,7 +6,7 @@ OBJ = built-in.o
6OBJS = ptrace.o sigcontext.o checksum.o miscthings.o misc.o \ 6OBJS = ptrace.o sigcontext.o checksum.o miscthings.o misc.o \
7 ptrace_user.o sysrq.o 7 ptrace_user.o sysrq.o
8 8
9EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel 9asflags-y := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel
10 10
11all: $(OBJ) 11all: $(OBJ)
12 12
@@ -15,10 +15,10 @@ $(OBJ): $(OBJS)
15 $(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@ 15 $(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@
16 16
17ptrace_user.o: ptrace_user.c 17ptrace_user.o: ptrace_user.c
18 $(CC) -D__KERNEL__ $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< 18 $(CC) -D__KERNEL__ $(USER_CFLAGS) $(ccflags-y) -c -o $@ $<
19 19
20sigcontext.o: sigcontext.c 20sigcontext.o: sigcontext.c
21 $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< 21 $(CC) $(USER_CFLAGS) $(ccflags-y) -c -o $@ $<
22 22
23checksum.S: 23checksum.S:
24 rm -f $@ 24 rm -f $@
@@ -53,13 +53,13 @@ ppc_defs.h: mk_defs.c ppc_defs.head \
53checksum.o: checksum.S 53checksum.o: checksum.S
54 rm -f asm 54 rm -f asm
55 ln -s $(srctree)/include/asm-ppc asm 55 ln -s $(srctree)/include/asm-ppc asm
56 $(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o 56 $(CC) $(asflags-y) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
57 rm -f asm 57 rm -f asm
58 58
59misc.o: misc.S ppc_defs.h 59misc.o: misc.S ppc_defs.h
60 rm -f asm 60 rm -f asm
61 ln -s $(srctree)/include/asm-ppc asm 61 ln -s $(srctree)/include/asm-ppc asm
62 $(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o 62 $(CC) $(asflags-y) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
63 rm -f asm 63 rm -f asm
64 64
65clean-files := $(OBJS) ppc_defs.h checksum.S mk_defs.c 65clean-files := $(OBJS) ppc_defs.h checksum.S mk_defs.c
diff --git a/arch/um/sys-x86_64/asm/elf.h b/arch/um/sys-x86_64/asm/elf.h
index d760967f33a7..d6d5af376251 100644
--- a/arch/um/sys-x86_64/asm/elf.h
+++ b/arch/um/sys-x86_64/asm/elf.h
@@ -95,6 +95,8 @@ typedef struct user_i387_struct elf_fpregset_t;
95 (pr_reg)[25] = 0; \ 95 (pr_reg)[25] = 0; \
96 (pr_reg)[26] = 0; 96 (pr_reg)[26] = 0;
97 97
98#define task_pt_regs(t) (&(t)->thread.regs)
99
98struct task_struct; 100struct task_struct;
99 101
100extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu); 102extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu);
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
index f3458d7d1c5a..f43613643cdb 100644
--- a/arch/um/sys-x86_64/ptrace.c
+++ b/arch/um/sys-x86_64/ptrace.c
@@ -175,19 +175,18 @@ int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
175 return restore_fp_registers(userspace_pid[cpu], fpregs); 175 return restore_fp_registers(userspace_pid[cpu], fpregs);
176} 176}
177 177
178long subarch_ptrace(struct task_struct *child, long request, long addr, 178long subarch_ptrace(struct task_struct *child, long request,
179 long data) 179 unsigned long addr, unsigned long data)
180{ 180{
181 int ret = -EIO; 181 int ret = -EIO;
182 void __user *datap = (void __user *) data;
182 183
183 switch (request) { 184 switch (request) {
184 case PTRACE_GETFPXREGS: /* Get the child FPU state. */ 185 case PTRACE_GETFPXREGS: /* Get the child FPU state. */
185 ret = get_fpregs((struct user_i387_struct __user *) data, 186 ret = get_fpregs(datap, child);
186 child);
187 break; 187 break;
188 case PTRACE_SETFPXREGS: /* Set the child FPU state. */ 188 case PTRACE_SETFPXREGS: /* Set the child FPU state. */
189 ret = set_fpregs((struct user_i387_struct __user *) data, 189 ret = set_fpregs(datap, child);
190 child);
191 break; 190 break;
192 } 191 }
193 192