diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/um | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'arch/um')
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 | ||
7 | config GENERIC_HARDIRQS | ||
8 | bool | ||
9 | default y | ||
10 | |||
11 | config UML | 6 | config UML |
12 | bool | 7 | bool |
13 | default y | 8 | default y |
9 | select HAVE_GENERIC_HARDIRQS | ||
10 | select GENERIC_IRQ_SHOW | ||
14 | 11 | ||
15 | config MMU | 12 | config MMU |
16 | bool | 13 | bool |
@@ -19,8 +16,6 @@ config MMU | |||
19 | config NO_IOMEM | 16 | config NO_IOMEM |
20 | def_bool y | 17 | def_bool y |
21 | 18 | ||
22 | mainmenu "Linux/Usermode Kernel Configuration" | ||
23 | |||
24 | config ISA | 19 | config 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 | ||
31 | config DEBUG_STACK_USAGE | 31 | config 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. | ||
40 | endmenu | 40 | endmenu |
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 | ||
48 | config HPPFS | 48 | config 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 | ||
129 | config HIGHMEM | 129 | config 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 | |||
151 | config 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 | ||
5 | menu "Host processor type and features" | 5 | menu "Host processor type and features" |
6 | 6 | ||
7 | config CMPXCHG_LOCAL | ||
8 | bool | ||
9 | default n | ||
10 | |||
7 | source "arch/x86/Kconfig.cpu" | 11 | source "arch/x86/Kconfig.cpu" |
8 | 12 | ||
9 | endmenu | 13 | endmenu |
10 | 14 | ||
11 | config UML_X86 | 15 | config UML_X86 |
12 | def_bool y | 16 | def_bool y |
17 | select GENERIC_FIND_FIRST_BIT | ||
13 | 18 | ||
14 | config 64BIT | 19 | config 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 | ||
27 | config X86_64 | ||
28 | def_bool 64BIT | ||
29 | |||
22 | config RWSEM_XCHGADD_ALGORITHM | 30 | config RWSEM_XCHGADD_ALGORITHM |
23 | def_bool X86_XADD | 31 | def_bool X86_XADD && 64BIT |
24 | 32 | ||
25 | config RWSEM_GENERIC_SPINLOCK | 33 | config RWSEM_GENERIC_SPINLOCK |
26 | def_bool !X86_XADD | 34 | def_bool !RWSEM_XCHGADD_ALGORITHM |
27 | 35 | ||
28 | config 3_LEVEL_PGTABLES | 36 | config 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 |
134 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y | 134 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y |
135 | CONFIG_SYSCTL=y | 135 | CONFIG_SYSCTL=y |
136 | # CONFIG_EMBEDDED is not set | 136 | # CONFIG_EXPERT is not set |
137 | CONFIG_UID16=y | 137 | CONFIG_UID16=y |
138 | CONFIG_SYSCTL_SYSCALL=y | 138 | CONFIG_SYSCTL_SYSCALL=y |
139 | CONFIG_KALLSYMS=y | 139 | CONFIG_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 |
568 | CONFIG_PLIST=y | 568 | CONFIG_PLIST=y |
569 | CONFIG_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 @@ | |||
9 | slip-objs := slip_kern.o slip_user.o | 9 | slip-objs := slip_kern.o slip_user.o |
10 | slirp-objs := slirp_kern.o slirp_user.o | 10 | slirp-objs := slirp_kern.o slirp_user.o |
11 | daemon-objs := daemon_kern.o daemon_user.o | 11 | daemon-objs := daemon_kern.o daemon_user.o |
12 | mcast-objs := mcast_kern.o mcast_user.o | 12 | umcast-objs := umcast_kern.o umcast_user.o |
13 | net-objs := net_kern.o net_user.o | 13 | net-objs := net_kern.o net_user.o |
14 | mconsole-objs := mconsole_kern.o mconsole_user.o | 14 | mconsole-objs := mconsole_kern.o mconsole_user.o |
15 | hostaudio-objs := hostaudio_kern.o | 15 | hostaudio-objs := hostaudio_kern.o |
@@ -44,7 +44,7 @@ obj-$(CONFIG_UML_NET_SLIP) += slip.o slip_common.o | |||
44 | obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o | 44 | obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o |
45 | obj-$(CONFIG_UML_NET_DAEMON) += daemon.o | 45 | obj-$(CONFIG_UML_NET_DAEMON) += daemon.o |
46 | obj-$(CONFIG_UML_NET_VDE) += vde.o | 46 | obj-$(CONFIG_UML_NET_VDE) += vde.o |
47 | obj-$(CONFIG_UML_NET_MCAST) += mcast.o | 47 | obj-$(CONFIG_UML_NET_MCAST) += umcast.o |
48 | obj-$(CONFIG_UML_NET_PCAP) += pcap.o | 48 | obj-$(CONFIG_UML_NET_PCAP) += pcap.o |
49 | obj-$(CONFIG_UML_NET) += net.o | 49 | obj-$(CONFIG_UML_NET) += net.o |
50 | obj-$(CONFIG_MCONSOLE) += mconsole.o | 50 | obj-$(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 | ||
51 | MODULE_LICENSE("GPL"); | 51 | MODULE_LICENSE("GPL"); |
52 | 52 | ||
53 | static DEFINE_MUTEX(harddog_mutex); | ||
53 | static DEFINE_SPINLOCK(lock); | 54 | static DEFINE_SPINLOCK(lock); |
54 | static int timer_alive; | 55 | static int timer_alive; |
55 | static int harddog_in_fd = -1; | 56 | static 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); |
88 | err: | 89 | err: |
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 | ||
171 | static struct miscdevice harddog_miscdev = { | 173 | static 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 | ||
66 | static DEFINE_MUTEX(hostaudio_mutex); | ||
67 | |||
66 | /* /dev/dsp file operations */ | 68 | /* /dev/dsp file operations */ |
67 | 69 | ||
68 | static ssize_t hostaudio_read(struct file *file, char __user *buffer, | 70 | static 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 | ||
258 | int line_ioctl(struct tty_struct *tty, struct file * file, | 258 | int 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 | ||
728 | static void free_winch(struct winch *winch, int free_irq_ok) | 728 | static 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 | ||
821 | static void unregister_winch(struct tty_struct *tty) | 822 | static 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 | |||
11 | struct mcast_data { | ||
12 | char *addr; | ||
13 | unsigned short port; | ||
14 | void *mcast_addr; | ||
15 | int ttl; | ||
16 | void *dev; | ||
17 | }; | ||
18 | |||
19 | extern const struct net_user_info mcast_user_info; | ||
20 | |||
21 | extern 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 | |||
19 | struct mcast_init { | ||
20 | char *addr; | ||
21 | int port; | ||
22 | int ttl; | ||
23 | }; | ||
24 | |||
25 | static 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 | |||
42 | static 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 | |||
48 | static 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 | |||
54 | static 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 | |||
61 | static 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 | |||
104 | static 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 | |||
114 | static int register_mcast(void) | ||
115 | { | ||
116 | register_transport(&mcast_transport); | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | late_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 | |||
24 | static 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 | |||
40 | static 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 | |||
49 | static 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 | |||
57 | static 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 | |||
132 | static 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 | |||
149 | int 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 | |||
156 | const 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 |
125 | void mconsole_proc(struct mc_request *req) | 125 | void 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, | |||
843 | static const struct file_operations mconsole_proc_fops = { | 826 | static 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 | ||
848 | static int create_proc_mconsole(void) | 832 | static 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 | ||
49 | static long mmapper_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 43 | static 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 | ||
137 | MODULE_AUTHOR("Greg Lonnon <glonnon@ridgerun.com>"); | 132 | MODULE_AUTHOR("Greg Lonnon <glonnon@ridgerun.com>"); |
138 | MODULE_DESCRIPTION("DSPLinux simulator mmapper driver"); | 133 | MODULE_DESCRIPTION("DSPLinux simulator mmapper driver"); |
134 | MODULE_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 | ||
102 | static DEFINE_MUTEX(ubd_lock); | 102 | static DEFINE_MUTEX(ubd_lock); |
103 | static DEFINE_MUTEX(ubd_mutex); /* replaces BKL, might not be needed */ | ||
103 | 104 | ||
104 | static int ubd_open(struct block_device *bdev, fmode_t mode); | 105 | static int ubd_open(struct block_device *bdev, fmode_t mode); |
105 | static int ubd_release(struct gendisk *disk, fmode_t mode); | 106 | static 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 | }*/ |
1122 | out: | 1123 | out: |
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 | |||
11 | struct 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 | |||
22 | extern const struct net_user_info umcast_user_info; | ||
23 | |||
24 | extern 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 | |||
19 | struct umcast_init { | ||
20 | char *addr; | ||
21 | int lport; | ||
22 | int rport; | ||
23 | int ttl; | ||
24 | bool unicast; | ||
25 | }; | ||
26 | |||
27 | static 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 | |||
51 | static 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 | |||
57 | static 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 | |||
63 | static 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 | |||
70 | static 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 | |||
116 | static 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 | |||
161 | static 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 | |||
171 | static 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 | |||
181 | static int register_umcast(void) | ||
182 | { | ||
183 | register_transport(&mcast_transport); | ||
184 | register_transport(&ucast_transport); | ||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | late_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 | |||
24 | static 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 | |||
43 | static 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 | |||
56 | static 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 | |||
66 | static 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 | |||
150 | static 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 | |||
170 | int 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 | |||
177 | const 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 | |||
6 | static inline int | ||
7 | dma_supported(struct device *dev, u64 mask) | ||
8 | { | ||
9 | BUG(); | ||
10 | return(0); | ||
11 | } | ||
12 | |||
13 | static inline int | ||
14 | dma_set_mask(struct device *dev, u64 dma_mask) | ||
15 | { | ||
16 | BUG(); | ||
17 | return(0); | ||
18 | } | ||
19 | |||
20 | static inline void * | ||
21 | dma_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 | |||
28 | static inline void | ||
29 | dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, | ||
30 | dma_addr_t dma_handle) | ||
31 | { | ||
32 | BUG(); | ||
33 | } | ||
34 | |||
35 | static inline dma_addr_t | ||
36 | dma_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 | |||
43 | static inline void | ||
44 | dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | ||
45 | enum dma_data_direction direction) | ||
46 | { | ||
47 | BUG(); | ||
48 | } | ||
49 | |||
50 | static inline dma_addr_t | ||
51 | dma_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 | |||
59 | static inline void | ||
60 | dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, | ||
61 | enum dma_data_direction direction) | ||
62 | { | ||
63 | BUG(); | ||
64 | } | ||
65 | |||
66 | static inline int | ||
67 | dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | ||
68 | enum dma_data_direction direction) | ||
69 | { | ||
70 | BUG(); | ||
71 | return(0); | ||
72 | } | ||
73 | |||
74 | static inline void | ||
75 | dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, | ||
76 | enum dma_data_direction direction) | ||
77 | { | ||
78 | BUG(); | ||
79 | } | ||
80 | |||
81 | static inline void | ||
82 | dma_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 | |||
88 | static inline void | ||
89 | dma_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 | |||
98 | static inline void | ||
99 | dma_cache_sync(struct device *dev, void *vaddr, size_t size, | ||
100 | enum dma_data_direction direction) | ||
101 | { | ||
102 | BUG(); | ||
103 | } | ||
104 | |||
105 | static inline int | ||
106 | dma_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 | ||
345 | struct mm_struct; | 343 | struct mm_struct; |
346 | extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr); | 344 | extern 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 | |||
17 | struct mm_struct; | 19 | struct mm_struct; |
18 | 20 | ||
19 | struct thread_struct { | 21 | struct thread_struct { |
@@ -66,7 +68,7 @@ struct thread_struct { | |||
66 | .request = { 0 } \ | 68 | .request = { 0 } \ |
67 | } | 69 | } |
68 | 70 | ||
69 | extern struct task_struct *alloc_task_struct(void); | 71 | extern struct task_struct *alloc_task_struct_node(int node); |
70 | 72 | ||
71 | static inline void release_thread(struct task_struct *task) | 73 | static 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 | ||
39 | struct task_struct; | 39 | struct task_struct; |
40 | 40 | ||
41 | extern long subarch_ptrace(struct task_struct *child, long request, long addr, | 41 | extern long subarch_ptrace(struct task_struct *child, long request, |
42 | long data); | 42 | unsigned long addr, unsigned long data); |
43 | extern unsigned long getreg(struct task_struct *child, int regno); | 43 | extern unsigned long getreg(struct task_struct *child, int regno); |
44 | extern int putreg(struct task_struct *child, int regno, unsigned long value); | 44 | extern int putreg(struct task_struct *child, int regno, unsigned long value); |
45 | extern int get_fpregs(struct user_i387_struct __user *buf, | 45 | extern 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 */ | ||
15 | extern int hard_smp_processor_id(void); | 14 | extern 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); | |||
8 | extern void block_signals(void); | 8 | extern void block_signals(void); |
9 | extern void unblock_signals(void); | 9 | extern void unblock_signals(void); |
10 | 10 | ||
11 | #define local_save_flags(flags) do { typecheck(unsigned long, flags); \ | 11 | static 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); \ | 16 | static 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 | 21 | static 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); \ | 26 | static inline void arch_local_irq_disable(void) |
27 | }) | 27 | { |
28 | block_signals(); | ||
29 | } | ||
30 | |||
31 | static 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 | |||
39 | static inline bool arch_irqs_disabled(void) | ||
40 | { | ||
41 | return arch_local_save_flags() == 0; | ||
42 | } | ||
28 | 43 | ||
29 | extern void *_switch_to(void *prev, void *next, void *last); | 44 | extern 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. */ | ||
26 | DECLARE_PER_CPU(struct mmu_gather, mmu_gathers); | ||
27 | |||
28 | static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, | 25 | static 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 | 47 | static inline void |
51 | * Return a pointer to an initialized struct mmu_gather. | 48 | tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush) |
52 | */ | ||
53 | static inline struct mmu_gather * | ||
54 | tlb_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 | ||
66 | extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, | 56 | extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, |
67 | unsigned long end); | 57 | unsigned long end); |
68 | 58 | ||
69 | static inline void | 59 | static inline void |
70 | tlb_flush_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) | 60 | tlb_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) | |||
83 | static inline void | 73 | static inline void |
84 | tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) | 74 | tlb_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 | */ |
99 | static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) | 87 | static 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 | |||
94 | static 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); | |||
77 | extern void line_flush_buffer(struct tty_struct *tty); | 77 | extern void line_flush_buffer(struct tty_struct *tty); |
78 | extern void line_flush_chars(struct tty_struct *tty); | 78 | extern void line_flush_chars(struct tty_struct *tty); |
79 | extern int line_write_room(struct tty_struct *tty); | 79 | extern int line_write_room(struct tty_struct *tty); |
80 | extern int line_ioctl(struct tty_struct *tty, struct file * file, | 80 | extern int line_ioctl(struct tty_struct *tty, unsigned int cmd, |
81 | unsigned int cmd, unsigned long arg); | 81 | unsigned long arg); |
82 | extern void line_throttle(struct tty_struct *tty); | 82 | extern void line_throttle(struct tty_struct *tty); |
83 | extern void line_unthrottle(struct tty_struct *tty); | 83 | extern 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); | |||
238 | extern void setup_machinename(char *machine_out); | 244 | extern void setup_machinename(char *machine_out); |
239 | extern void setup_hostinfo(char *buf, int len); | 245 | extern void setup_hostinfo(char *buf, int len); |
240 | extern void os_dump_core(void) __attribute__ ((noreturn)); | 246 | extern void os_dump_core(void) __attribute__ ((noreturn)); |
247 | extern void um_early_printk(const char *s, unsigned int n); | ||
241 | 248 | ||
242 | /* time.c */ | 249 | /* time.c */ |
243 | extern void idle_sleep(unsigned long long nsecs); | 250 | extern 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 \ | |||
17 | obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o | 17 | obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o |
18 | obj-$(CONFIG_GPROF) += gprof_syms.o | 18 | obj-$(CONFIG_GPROF) += gprof_syms.o |
19 | obj-$(CONFIG_GCOV) += gmon_syms.o | 19 | obj-$(CONFIG_GCOV) += gmon_syms.o |
20 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | ||
20 | 21 | ||
21 | USER_OBJS := config.o | 22 | USER_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 | |||
14 | static void early_console_write(struct console *con, const char *s, unsigned int n) | ||
15 | { | ||
16 | um_early_printk(s, n); | ||
17 | } | ||
18 | |||
19 | static struct console early_console = { | ||
20 | .name = "earlycon", | ||
21 | .write = early_console_write, | ||
22 | .flags = CON_BOOT, | ||
23 | .index = -1, | ||
24 | }; | ||
25 | |||
26 | static int __init setup_early_printk(char *buf) | ||
27 | { | ||
28 | register_console(&early_console); | ||
29 | |||
30 | return 0; | ||
31 | } | ||
32 | |||
33 | early_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 | |||
24 | int 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'); | ||
56 | skip: | ||
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); | |||
360 | EXPORT_SYMBOL(reactivate_fd); | 316 | EXPORT_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 | */ |
366 | static void dummy(unsigned int irq) | 322 | static 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. */ |
371 | static struct irq_chip normal_irq_type = { | 327 | static 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 | ||
380 | static struct irq_chip SIGVTALRM_irq_type = { | 335 | static 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 | ||
390 | void __init init_IRQ(void) | 343 | void __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) | |||
42 | extern int peek_user(struct task_struct * child, long addr, long data); | 42 | extern int peek_user(struct task_struct * child, long addr, long data); |
43 | extern int poke_user(struct task_struct * child, long addr, long data); | 43 | extern int poke_user(struct task_struct * child, long addr, long data); |
44 | 44 | ||
45 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 45 | long 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. */ | ||
11 | DEFINE_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 | ||
116 | static 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 | |||
116 | static void bad_segv(struct faultinfo fi, unsigned long ip) | 137 | static 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 | ||
83 | static void setup_env_path(void) | 83 | static 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 | ||
258 | int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr) | 259 | int 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) | |||
60 | long long disable_timer(void) | 60 | long 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 | */ | ||
85 | static 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 | |||
78 | void os_dump_core(void) | 99 | void 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 | |||
143 | void 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 | ||
5 | obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ | 5 | obj-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 | ||
9 | obj-$(CONFIG_BINFMT_ELF) += elfcore.o | 9 | obj-$(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 | |||
78 | struct task_struct; | 80 | struct task_struct; |
79 | 81 | ||
80 | extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu); | 82 | extern 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 | |||
37 | ENTRY(atomic64_read_cx8) | ||
38 | CFI_STARTPROC | ||
39 | |||
40 | read64 %ecx | ||
41 | ret | ||
42 | CFI_ENDPROC | ||
43 | ENDPROC(atomic64_read_cx8) | ||
44 | |||
45 | ENTRY(atomic64_set_cx8) | ||
46 | CFI_STARTPROC | ||
47 | |||
48 | 1: | ||
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 | ||
56 | ENDPROC(atomic64_set_cx8) | ||
57 | |||
58 | ENTRY(atomic64_xchg_cx8) | ||
59 | CFI_STARTPROC | ||
60 | |||
61 | movl %ebx, %eax | ||
62 | movl %ecx, %edx | ||
63 | 1: | ||
64 | LOCK_PREFIX | ||
65 | cmpxchg8b (%esi) | ||
66 | jne 1b | ||
67 | |||
68 | ret | ||
69 | CFI_ENDPROC | ||
70 | ENDPROC(atomic64_xchg_cx8) | ||
71 | |||
72 | .macro addsub_return func ins insc | ||
73 | ENTRY(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 | ||
85 | 1: | ||
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 | |||
94 | 10: | ||
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 | ||
103 | ENDPROC(atomic64_\func\()_return_cx8) | ||
104 | .endm | ||
105 | |||
106 | addsub_return add add adc | ||
107 | addsub_return sub sub sbb | ||
108 | |||
109 | .macro incdec_return func ins insc | ||
110 | ENTRY(atomic64_\func\()_return_cx8) | ||
111 | CFI_STARTPROC | ||
112 | SAVE ebx | ||
113 | |||
114 | read64 %esi | ||
115 | 1: | ||
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 | |||
124 | 10: | ||
125 | movl %ebx, %eax | ||
126 | movl %ecx, %edx | ||
127 | RESTORE ebx | ||
128 | ret | ||
129 | CFI_ENDPROC | ||
130 | ENDPROC(atomic64_\func\()_return_cx8) | ||
131 | .endm | ||
132 | |||
133 | incdec_return inc add adc | ||
134 | incdec_return dec sub sbb | ||
135 | |||
136 | ENTRY(atomic64_dec_if_positive_cx8) | ||
137 | CFI_STARTPROC | ||
138 | SAVE ebx | ||
139 | |||
140 | read64 %esi | ||
141 | 1: | ||
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 | |||
151 | 2: | ||
152 | movl %ebx, %eax | ||
153 | movl %ecx, %edx | ||
154 | RESTORE ebx | ||
155 | ret | ||
156 | CFI_ENDPROC | ||
157 | ENDPROC(atomic64_dec_if_positive_cx8) | ||
158 | |||
159 | ENTRY(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 | ||
172 | 1: | ||
173 | cmpl %eax, 0(%esp) | ||
174 | je 4f | ||
175 | 2: | ||
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 | ||
185 | 3: | ||
186 | addl $8, %esp | ||
187 | CFI_ADJUST_CFA_OFFSET -8 | ||
188 | RESTORE ebx | ||
189 | RESTORE ebp | ||
190 | ret | ||
191 | 4: | ||
192 | cmpl %edx, 4(%esp) | ||
193 | jne 2b | ||
194 | xorl %eax, %eax | ||
195 | jmp 3b | ||
196 | CFI_ENDPROC | ||
197 | ENDPROC(atomic64_add_unless_cx8) | ||
198 | |||
199 | ENTRY(atomic64_inc_not_zero_cx8) | ||
200 | CFI_STARTPROC | ||
201 | SAVE ebx | ||
202 | |||
203 | read64 %esi | ||
204 | 1: | ||
205 | testl %eax, %eax | ||
206 | je 4f | ||
207 | 2: | ||
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 | ||
217 | 3: | ||
218 | RESTORE ebx | ||
219 | ret | ||
220 | 4: | ||
221 | testl %edx, %edx | ||
222 | jne 2b | ||
223 | jmp 3b | ||
224 | CFI_ENDPROC | ||
225 | ENDPROC(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 | ||
206 | long subarch_ptrace(struct task_struct *child, long request, long addr, | 206 | long 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 | |||
6 | OBJS = ptrace.o sigcontext.o checksum.o miscthings.o misc.o \ | 6 | OBJS = ptrace.o sigcontext.o checksum.o miscthings.o misc.o \ |
7 | ptrace_user.o sysrq.o | 7 | ptrace_user.o sysrq.o |
8 | 8 | ||
9 | EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel | 9 | asflags-y := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel |
10 | 10 | ||
11 | all: $(OBJ) | 11 | all: $(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 | ||
17 | ptrace_user.o: ptrace_user.c | 17 | ptrace_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 | ||
20 | sigcontext.o: sigcontext.c | 20 | sigcontext.o: sigcontext.c |
21 | $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< | 21 | $(CC) $(USER_CFLAGS) $(ccflags-y) -c -o $@ $< |
22 | 22 | ||
23 | checksum.S: | 23 | checksum.S: |
24 | rm -f $@ | 24 | rm -f $@ |
@@ -53,13 +53,13 @@ ppc_defs.h: mk_defs.c ppc_defs.head \ | |||
53 | checksum.o: checksum.S | 53 | checksum.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 | ||
59 | misc.o: misc.S ppc_defs.h | 59 | misc.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 | ||
65 | clean-files := $(OBJS) ppc_defs.h checksum.S mk_defs.c | 65 | clean-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 | |||
98 | struct task_struct; | 100 | struct task_struct; |
99 | 101 | ||
100 | extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu); | 102 | extern 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 | ||
178 | long subarch_ptrace(struct task_struct *child, long request, long addr, | 178 | long 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 | ||