diff options
Diffstat (limited to 'arch/um')
106 files changed, 1498 insertions, 1819 deletions
diff --git a/arch/um/defconfig b/arch/um/defconfig index 780cc0a4a128..f938fa822146 100644 --- a/arch/um/defconfig +++ b/arch/um/defconfig | |||
@@ -41,6 +41,7 @@ CONFIG_M686=y | |||
41 | # CONFIG_MGEODE_LX is not set | 41 | # CONFIG_MGEODE_LX is not set |
42 | # CONFIG_MCYRIXIII is not set | 42 | # CONFIG_MCYRIXIII is not set |
43 | # CONFIG_MVIAC3_2 is not set | 43 | # CONFIG_MVIAC3_2 is not set |
44 | # CONFIG_MVIAC7 is not set | ||
44 | # CONFIG_X86_GENERIC is not set | 45 | # CONFIG_X86_GENERIC is not set |
45 | CONFIG_X86_CMPXCHG=y | 46 | CONFIG_X86_CMPXCHG=y |
46 | CONFIG_X86_XADD=y | 47 | CONFIG_X86_XADD=y |
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 9fdfad649536..3aa351611763 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/tty_flip.h> | 12 | #include <linux/tty_flip.h> |
13 | #include <asm/irq.h> | 13 | #include <asm/irq.h> |
14 | #include "chan_kern.h" | 14 | #include "chan_kern.h" |
15 | #include "user_util.h" | ||
16 | #include "kern.h" | 15 | #include "kern.h" |
17 | #include "irq_user.h" | 16 | #include "irq_user.h" |
18 | #include "sigio.h" | 17 | #include "sigio.h" |
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index 0cad3546cb89..13f0bf852b2a 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <sys/ioctl.h> | 14 | #include <sys/ioctl.h> |
15 | #include <sys/socket.h> | 15 | #include <sys/socket.h> |
16 | #include "kern_util.h" | 16 | #include "kern_util.h" |
17 | #include "user_util.h" | ||
18 | #include "chan_user.h" | 17 | #include "chan_user.h" |
19 | #include "user.h" | 18 | #include "user.h" |
20 | #include "os.h" | 19 | #include "os.h" |
@@ -158,7 +157,7 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out) | |||
158 | */ | 157 | */ |
159 | err = run_helper_thread(winch_thread, &data, CLONE_FILES, &stack, 0); | 158 | err = run_helper_thread(winch_thread, &data, CLONE_FILES, &stack, 0); |
160 | if(err < 0){ | 159 | if(err < 0){ |
161 | printk("fork of winch_thread failed - errno = %d\n", errno); | 160 | printk("fork of winch_thread failed - errno = %d\n", -err); |
162 | goto out_close; | 161 | goto out_close; |
163 | } | 162 | } |
164 | 163 | ||
@@ -204,14 +203,3 @@ void register_winch(int fd, struct tty_struct *tty) | |||
204 | } | 203 | } |
205 | } | 204 | } |
206 | } | 205 | } |
207 | |||
208 | /* | ||
209 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
210 | * Emacs will notice this stuff at the end of the file and automatically | ||
211 | * adjust the settings for this buffer only. This must remain at the end | ||
212 | * of the file. | ||
213 | * --------------------------------------------------------------------------- | ||
214 | * Local variables: | ||
215 | * c-file-style: "linux" | ||
216 | * End: | ||
217 | */ | ||
diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h index c6a308464acb..15453845d2ba 100644 --- a/arch/um/drivers/cow_sys.h +++ b/arch/um/drivers/cow_sys.h | |||
@@ -2,14 +2,13 @@ | |||
2 | #define __COW_SYS_H__ | 2 | #define __COW_SYS_H__ |
3 | 3 | ||
4 | #include "kern_util.h" | 4 | #include "kern_util.h" |
5 | #include "user_util.h" | ||
6 | #include "os.h" | 5 | #include "os.h" |
7 | #include "user.h" | 6 | #include "user.h" |
8 | #include "um_malloc.h" | 7 | #include "um_malloc.h" |
9 | 8 | ||
10 | static inline void *cow_malloc(int size) | 9 | static inline void *cow_malloc(int size) |
11 | { | 10 | { |
12 | return(um_kmalloc(size)); | 11 | return um_kmalloc(size); |
13 | } | 12 | } |
14 | 13 | ||
15 | static inline void cow_free(void *ptr) | 14 | static inline void cow_free(void *ptr) |
@@ -21,29 +20,22 @@ static inline void cow_free(void *ptr) | |||
21 | 20 | ||
22 | static inline char *cow_strdup(char *str) | 21 | static inline char *cow_strdup(char *str) |
23 | { | 22 | { |
24 | return(uml_strdup(str)); | 23 | return uml_strdup(str); |
25 | } | 24 | } |
26 | 25 | ||
27 | static inline int cow_seek_file(int fd, __u64 offset) | 26 | static inline int cow_seek_file(int fd, __u64 offset) |
28 | { | 27 | { |
29 | return(os_seek_file(fd, offset)); | 28 | return os_seek_file(fd, offset); |
30 | } | 29 | } |
31 | 30 | ||
32 | static inline int cow_file_size(char *file, unsigned long long *size_out) | 31 | static inline int cow_file_size(char *file, unsigned long long *size_out) |
33 | { | 32 | { |
34 | return(os_file_size(file, size_out)); | 33 | return os_file_size(file, size_out); |
35 | } | 34 | } |
36 | 35 | ||
37 | static inline int cow_write_file(int fd, void *buf, int size) | 36 | static inline int cow_write_file(int fd, void *buf, int size) |
38 | { | 37 | { |
39 | return(os_write_file(fd, buf, size)); | 38 | return os_write_file(fd, buf, size); |
40 | } | 39 | } |
41 | 40 | ||
42 | #endif | 41 | #endif |
43 | |||
44 | /* | ||
45 | * --------------------------------------------------------------------------- | ||
46 | * Local variables: | ||
47 | * c-file-style: "linux" | ||
48 | * End: | ||
49 | */ | ||
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c index 021b82c7a759..b869e3899683 100644 --- a/arch/um/drivers/daemon_user.c +++ b/arch/um/drivers/daemon_user.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include "net_user.h" | 14 | #include "net_user.h" |
15 | #include "daemon.h" | 15 | #include "daemon.h" |
16 | #include "kern_util.h" | 16 | #include "kern_util.h" |
17 | #include "user_util.h" | ||
18 | #include "user.h" | 17 | #include "user.h" |
19 | #include "os.h" | 18 | #include "os.h" |
20 | #include "um_malloc.h" | 19 | #include "um_malloc.h" |
@@ -39,11 +38,11 @@ static struct sockaddr_un *new_addr(void *name, int len) | |||
39 | sun = um_kmalloc(sizeof(struct sockaddr_un)); | 38 | sun = um_kmalloc(sizeof(struct sockaddr_un)); |
40 | if(sun == NULL){ | 39 | if(sun == NULL){ |
41 | printk("new_addr: allocation of sockaddr_un failed\n"); | 40 | printk("new_addr: allocation of sockaddr_un failed\n"); |
42 | return(NULL); | 41 | return NULL; |
43 | } | 42 | } |
44 | sun->sun_family = AF_UNIX; | 43 | sun->sun_family = AF_UNIX; |
45 | memcpy(sun->sun_path, name, len); | 44 | memcpy(sun->sun_path, name, len); |
46 | return(sun); | 45 | return sun; |
47 | } | 46 | } |
48 | 47 | ||
49 | static int connect_to_switch(struct daemon_data *pri) | 48 | static int connect_to_switch(struct daemon_data *pri) |
@@ -112,7 +111,7 @@ static int connect_to_switch(struct daemon_data *pri) | |||
112 | } | 111 | } |
113 | 112 | ||
114 | pri->data_addr = sun; | 113 | pri->data_addr = sun; |
115 | return(fd); | 114 | return fd; |
116 | 115 | ||
117 | out_free: | 116 | out_free: |
118 | kfree(sun); | 117 | kfree(sun); |
@@ -120,10 +119,10 @@ static int connect_to_switch(struct daemon_data *pri) | |||
120 | os_close_file(fd); | 119 | os_close_file(fd); |
121 | out: | 120 | out: |
122 | os_close_file(pri->control); | 121 | os_close_file(pri->control); |
123 | return(err); | 122 | return err; |
124 | } | 123 | } |
125 | 124 | ||
126 | static void daemon_user_init(void *data, void *dev) | 125 | static int daemon_user_init(void *data, void *dev) |
127 | { | 126 | { |
128 | struct daemon_data *pri = data; | 127 | struct daemon_data *pri = data; |
129 | struct timeval tv; | 128 | struct timeval tv; |
@@ -146,13 +145,16 @@ static void daemon_user_init(void *data, void *dev) | |||
146 | if(pri->fd < 0){ | 145 | if(pri->fd < 0){ |
147 | kfree(pri->local_addr); | 146 | kfree(pri->local_addr); |
148 | pri->local_addr = NULL; | 147 | pri->local_addr = NULL; |
148 | return pri->fd; | ||
149 | } | 149 | } |
150 | |||
151 | return 0; | ||
150 | } | 152 | } |
151 | 153 | ||
152 | static int daemon_open(void *data) | 154 | static int daemon_open(void *data) |
153 | { | 155 | { |
154 | struct daemon_data *pri = data; | 156 | struct daemon_data *pri = data; |
155 | return(pri->fd); | 157 | return pri->fd; |
156 | } | 158 | } |
157 | 159 | ||
158 | static void daemon_remove(void *data) | 160 | static void daemon_remove(void *data) |
@@ -176,12 +178,12 @@ int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri) | |||
176 | { | 178 | { |
177 | struct sockaddr_un *data_addr = pri->data_addr; | 179 | struct sockaddr_un *data_addr = pri->data_addr; |
178 | 180 | ||
179 | return(net_sendto(fd, buf, len, data_addr, sizeof(*data_addr))); | 181 | return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); |
180 | } | 182 | } |
181 | 183 | ||
182 | static int daemon_set_mtu(int mtu, void *data) | 184 | static int daemon_set_mtu(int mtu, void *data) |
183 | { | 185 | { |
184 | return(mtu); | 186 | return mtu; |
185 | } | 187 | } |
186 | 188 | ||
187 | const struct net_user_info daemon_user_info = { | 189 | const struct net_user_info daemon_user_info = { |
@@ -194,14 +196,3 @@ const struct net_user_info daemon_user_info = { | |||
194 | .delete_address = NULL, | 196 | .delete_address = NULL, |
195 | .max_packet = MAX_PACKET - ETH_HEADER_OTHER | 197 | .max_packet = MAX_PACKET - ETH_HEADER_OTHER |
196 | }; | 198 | }; |
197 | |||
198 | /* | ||
199 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
200 | * Emacs will notice this stuff at the end of the file and automatically | ||
201 | * adjust the settings for this buffer only. This must remain at the end | ||
202 | * of the file. | ||
203 | * --------------------------------------------------------------------------- | ||
204 | * Local variables: | ||
205 | * c-file-style: "linux" | ||
206 | * End: | ||
207 | */ | ||
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c index 218aa0e9b792..7f083ec47a4f 100644 --- a/arch/um/drivers/fd.c +++ b/arch/um/drivers/fd.c | |||
@@ -9,7 +9,6 @@ | |||
9 | #include <termios.h> | 9 | #include <termios.h> |
10 | #include <errno.h> | 10 | #include <errno.h> |
11 | #include "user.h" | 11 | #include "user.h" |
12 | #include "user_util.h" | ||
13 | #include "chan_user.h" | 12 | #include "chan_user.h" |
14 | #include "os.h" | 13 | #include "os.h" |
15 | #include "um_malloc.h" | 14 | #include "um_malloc.h" |
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c index c495ecf263b1..5eeecf8917c3 100644 --- a/arch/um/drivers/harddog_user.c +++ b/arch/um/drivers/harddog_user.c | |||
@@ -6,7 +6,6 @@ | |||
6 | #include <stdio.h> | 6 | #include <stdio.h> |
7 | #include <unistd.h> | 7 | #include <unistd.h> |
8 | #include <errno.h> | 8 | #include <errno.h> |
9 | #include "user_util.h" | ||
10 | #include "user.h" | 9 | #include "user.h" |
11 | #include "mconsole.h" | 10 | #include "mconsole.h" |
12 | #include "os.h" | 11 | #include "os.h" |
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index f75d7b05c481..ced99106f798 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include "irq_user.h" | 13 | #include "irq_user.h" |
14 | #include "line.h" | 14 | #include "line.h" |
15 | #include "kern.h" | 15 | #include "kern.h" |
16 | #include "user_util.h" | ||
17 | #include "kern_util.h" | 16 | #include "kern_util.h" |
18 | #include "os.h" | 17 | #include "os.h" |
19 | #include "irq_kern.h" | 18 | #include "irq_kern.h" |
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c index b827e82884c9..d319db16d4ec 100644 --- a/arch/um/drivers/mcast_user.c +++ b/arch/um/drivers/mcast_user.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include "net_user.h" | 20 | #include "net_user.h" |
21 | #include "mcast.h" | 21 | #include "mcast.h" |
22 | #include "kern_util.h" | 22 | #include "kern_util.h" |
23 | #include "user_util.h" | ||
24 | #include "user.h" | 23 | #include "user.h" |
25 | #include "os.h" | 24 | #include "os.h" |
26 | #include "um_malloc.h" | 25 | #include "um_malloc.h" |
@@ -34,20 +33,21 @@ static struct sockaddr_in *new_addr(char *addr, unsigned short port) | |||
34 | sin = um_kmalloc(sizeof(struct sockaddr_in)); | 33 | sin = um_kmalloc(sizeof(struct sockaddr_in)); |
35 | if(sin == NULL){ | 34 | if(sin == NULL){ |
36 | printk("new_addr: allocation of sockaddr_in failed\n"); | 35 | printk("new_addr: allocation of sockaddr_in failed\n"); |
37 | return(NULL); | 36 | return NULL; |
38 | } | 37 | } |
39 | sin->sin_family = AF_INET; | 38 | sin->sin_family = AF_INET; |
40 | sin->sin_addr.s_addr = in_aton(addr); | 39 | sin->sin_addr.s_addr = in_aton(addr); |
41 | sin->sin_port = htons(port); | 40 | sin->sin_port = htons(port); |
42 | return(sin); | 41 | return sin; |
43 | } | 42 | } |
44 | 43 | ||
45 | static void mcast_user_init(void *data, void *dev) | 44 | static int mcast_user_init(void *data, void *dev) |
46 | { | 45 | { |
47 | struct mcast_data *pri = data; | 46 | struct mcast_data *pri = data; |
48 | 47 | ||
49 | pri->mcast_addr = new_addr(pri->addr, pri->port); | 48 | pri->mcast_addr = new_addr(pri->addr, pri->port); |
50 | pri->dev = dev; | 49 | pri->dev = dev; |
50 | return 0; | ||
51 | } | 51 | } |
52 | 52 | ||
53 | static void mcast_remove(void *data) | 53 | static void mcast_remove(void *data) |
@@ -107,8 +107,8 @@ static int mcast_open(void *data) | |||
107 | err = -errno; | 107 | err = -errno; |
108 | printk("mcast_open : data bind failed, errno = %d\n", errno); | 108 | printk("mcast_open : data bind failed, errno = %d\n", errno); |
109 | goto out_close; | 109 | goto out_close; |
110 | } | 110 | } |
111 | 111 | ||
112 | /* subscribe to the multicast group */ | 112 | /* subscribe to the multicast group */ |
113 | mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; | 113 | mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; |
114 | mreq.imr_interface.s_addr = 0; | 114 | mreq.imr_interface.s_addr = 0; |
@@ -153,12 +153,12 @@ int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri) | |||
153 | { | 153 | { |
154 | struct sockaddr_in *data_addr = pri->mcast_addr; | 154 | struct sockaddr_in *data_addr = pri->mcast_addr; |
155 | 155 | ||
156 | return(net_sendto(fd, buf, len, data_addr, sizeof(*data_addr))); | 156 | return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); |
157 | } | 157 | } |
158 | 158 | ||
159 | static int mcast_set_mtu(int mtu, void *data) | 159 | static int mcast_set_mtu(int mtu, void *data) |
160 | { | 160 | { |
161 | return(mtu); | 161 | return mtu; |
162 | } | 162 | } |
163 | 163 | ||
164 | const struct net_user_info mcast_user_info = { | 164 | const struct net_user_info mcast_user_info = { |
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 65ad2932672c..542c9ef858f8 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include "linux/console.h" | 25 | #include "linux/console.h" |
26 | #include "asm/irq.h" | 26 | #include "asm/irq.h" |
27 | #include "asm/uaccess.h" | 27 | #include "asm/uaccess.h" |
28 | #include "user_util.h" | ||
29 | #include "kern_util.h" | 28 | #include "kern_util.h" |
30 | #include "kern.h" | 29 | #include "kern.h" |
31 | #include "mconsole.h" | 30 | #include "mconsole.h" |
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index f02634fbf32a..62e5ad63181a 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include "sysdep/ptrace.h" | 17 | #include "sysdep/ptrace.h" |
18 | #include "mconsole.h" | 18 | #include "mconsole.h" |
19 | #include "os.h" | 19 | #include "os.h" |
20 | #include "user_util.h" | ||
21 | 20 | ||
22 | static struct mconsole_command commands[] = { | 21 | static struct mconsole_command commands[] = { |
23 | /* With uts namespaces, uts information becomes process-specific, so | 22 | /* With uts namespaces, uts information becomes process-specific, so |
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c index df3516e47d4d..e41a08f04694 100644 --- a/arch/um/drivers/mmapper_kern.c +++ b/arch/um/drivers/mmapper_kern.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/miscdevice.h> | 15 | #include <linux/miscdevice.h> |
16 | #include <asm/uaccess.h> | 16 | #include <asm/uaccess.h> |
17 | #include "mem_user.h" | 17 | #include "mem_user.h" |
18 | #include "user_util.h" | ||
19 | 18 | ||
20 | /* These are set in mmapper_init, which is called at boot time */ | 19 | /* These are set in mmapper_init, which is called at boot time */ |
21 | static unsigned long mmapper_size; | 20 | static unsigned long mmapper_size; |
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 859303730b2f..baac4ad5e68e 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include "linux/ethtool.h" | 21 | #include "linux/ethtool.h" |
22 | #include "linux/platform_device.h" | 22 | #include "linux/platform_device.h" |
23 | #include "asm/uaccess.h" | 23 | #include "asm/uaccess.h" |
24 | #include "user_util.h" | ||
25 | #include "kern_util.h" | 24 | #include "kern_util.h" |
26 | #include "net_kern.h" | 25 | #include "net_kern.h" |
27 | #include "net_user.h" | 26 | #include "net_user.h" |
@@ -284,7 +283,7 @@ void uml_net_user_timer_expire(unsigned long _conn) | |||
284 | #endif | 283 | #endif |
285 | } | 284 | } |
286 | 285 | ||
287 | static void setup_etheraddr(char *str, unsigned char *addr) | 286 | static void setup_etheraddr(char *str, unsigned char *addr, char *name) |
288 | { | 287 | { |
289 | char *end; | 288 | char *end; |
290 | int i; | 289 | int i; |
@@ -303,15 +302,32 @@ static void setup_etheraddr(char *str, unsigned char *addr) | |||
303 | } | 302 | } |
304 | str = end + 1; | 303 | str = end + 1; |
305 | } | 304 | } |
306 | if(addr[0] & 1){ | 305 | if (is_multicast_ether_addr(addr)) { |
307 | printk(KERN_ERR | 306 | printk(KERN_ERR |
308 | "Attempt to assign a broadcast ethernet address to a " | 307 | "Attempt to assign a multicast ethernet address to a " |
309 | "device disallowed\n"); | 308 | "device disallowed\n"); |
310 | goto random; | 309 | goto random; |
311 | } | 310 | } |
311 | if (!is_valid_ether_addr(addr)) { | ||
312 | printk(KERN_ERR | ||
313 | "Attempt to assign an invalid ethernet address to a " | ||
314 | "device disallowed\n"); | ||
315 | goto random; | ||
316 | } | ||
317 | if (!is_local_ether_addr(addr)) { | ||
318 | printk(KERN_WARNING | ||
319 | "Warning: attempt to assign a globally valid ethernet address to a " | ||
320 | "device\n"); | ||
321 | printk(KERN_WARNING "You should better enable the 2nd rightmost bit " | ||
322 | "in the first byte of the MAC, i.e. " | ||
323 | "%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
324 | addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4], addr[5]); | ||
325 | } | ||
312 | return; | 326 | return; |
313 | 327 | ||
314 | random: | 328 | random: |
329 | printk(KERN_INFO | ||
330 | "Choosing a random ethernet address for device %s\n", name); | ||
315 | random_ether_addr(addr); | 331 | random_ether_addr(addr); |
316 | } | 332 | } |
317 | 333 | ||
@@ -325,31 +341,53 @@ static struct platform_driver uml_net_driver = { | |||
325 | }; | 341 | }; |
326 | static int driver_registered; | 342 | static int driver_registered; |
327 | 343 | ||
328 | static int eth_configure(int n, void *init, char *mac, | 344 | static void net_device_release(struct device *dev) |
329 | struct transport *transport) | 345 | { |
346 | struct uml_net *device = dev->driver_data; | ||
347 | struct net_device *netdev = device->dev; | ||
348 | struct uml_net_private *lp = netdev->priv; | ||
349 | |||
350 | if(lp->remove != NULL) | ||
351 | (*lp->remove)(&lp->user); | ||
352 | list_del(&device->list); | ||
353 | kfree(device); | ||
354 | free_netdev(netdev); | ||
355 | } | ||
356 | |||
357 | static void eth_configure(int n, void *init, char *mac, | ||
358 | struct transport *transport) | ||
330 | { | 359 | { |
331 | struct uml_net *device; | 360 | struct uml_net *device; |
332 | struct net_device *dev; | 361 | struct net_device *dev; |
333 | struct uml_net_private *lp; | 362 | struct uml_net_private *lp; |
334 | int save, err, size; | 363 | int err, size; |
335 | 364 | ||
336 | size = transport->private_size + sizeof(struct uml_net_private) + | 365 | size = transport->private_size + sizeof(struct uml_net_private); |
337 | sizeof(((struct uml_net_private *) 0)->user); | ||
338 | 366 | ||
339 | device = kzalloc(sizeof(*device), GFP_KERNEL); | 367 | device = kzalloc(sizeof(*device), GFP_KERNEL); |
340 | if (device == NULL) { | 368 | if (device == NULL) { |
341 | printk(KERN_ERR "eth_configure failed to allocate uml_net\n"); | 369 | printk(KERN_ERR "eth_configure failed to allocate struct " |
342 | return(1); | 370 | "uml_net\n"); |
371 | return; | ||
372 | } | ||
373 | |||
374 | dev = alloc_etherdev(size); | ||
375 | if (dev == NULL) { | ||
376 | printk(KERN_ERR "eth_configure: failed to allocate struct " | ||
377 | "net_device for eth%d\n", n); | ||
378 | goto out_free_device; | ||
343 | } | 379 | } |
344 | 380 | ||
345 | INIT_LIST_HEAD(&device->list); | 381 | INIT_LIST_HEAD(&device->list); |
346 | device->index = n; | 382 | device->index = n; |
347 | 383 | ||
348 | spin_lock(&devices_lock); | 384 | /* If this name ends up conflicting with an existing registered |
349 | list_add(&device->list, &devices); | 385 | * netdevice, that is OK, register_netdev{,ice}() will notice this |
350 | spin_unlock(&devices_lock); | 386 | * and fail. |
387 | */ | ||
388 | snprintf(dev->name, sizeof(dev->name), "eth%d", n); | ||
351 | 389 | ||
352 | setup_etheraddr(mac, device->mac); | 390 | setup_etheraddr(mac, device->mac, dev->name); |
353 | 391 | ||
354 | printk(KERN_INFO "Netdevice %d ", n); | 392 | printk(KERN_INFO "Netdevice %d ", n); |
355 | printk("(%02x:%02x:%02x:%02x:%02x:%02x) ", | 393 | printk("(%02x:%02x:%02x:%02x:%02x:%02x) ", |
@@ -357,11 +395,6 @@ static int eth_configure(int n, void *init, char *mac, | |||
357 | device->mac[2], device->mac[3], | 395 | device->mac[2], device->mac[3], |
358 | device->mac[4], device->mac[5]); | 396 | device->mac[4], device->mac[5]); |
359 | printk(": "); | 397 | printk(": "); |
360 | dev = alloc_etherdev(size); | ||
361 | if (dev == NULL) { | ||
362 | printk(KERN_ERR "eth_configure: failed to allocate device\n"); | ||
363 | return 1; | ||
364 | } | ||
365 | 398 | ||
366 | lp = dev->priv; | 399 | lp = dev->priv; |
367 | /* This points to the transport private data. It's still clear, but we | 400 | /* This points to the transport private data. It's still clear, but we |
@@ -376,47 +409,20 @@ static int eth_configure(int n, void *init, char *mac, | |||
376 | } | 409 | } |
377 | device->pdev.id = n; | 410 | device->pdev.id = n; |
378 | device->pdev.name = DRIVER_NAME; | 411 | device->pdev.name = DRIVER_NAME; |
379 | platform_device_register(&device->pdev); | 412 | device->pdev.dev.release = net_device_release; |
413 | device->pdev.dev.driver_data = device; | ||
414 | if(platform_device_register(&device->pdev)) | ||
415 | goto out_free_netdev; | ||
380 | SET_NETDEV_DEV(dev,&device->pdev.dev); | 416 | SET_NETDEV_DEV(dev,&device->pdev.dev); |
381 | 417 | ||
382 | /* If this name ends up conflicting with an existing registered | ||
383 | * netdevice, that is OK, register_netdev{,ice}() will notice this | ||
384 | * and fail. | ||
385 | */ | ||
386 | snprintf(dev->name, sizeof(dev->name), "eth%d", n); | ||
387 | device->dev = dev; | 418 | device->dev = dev; |
388 | 419 | ||
420 | /* | ||
421 | * These just fill in a data structure, so there's no failure | ||
422 | * to be worried about. | ||
423 | */ | ||
389 | (*transport->kern->init)(dev, init); | 424 | (*transport->kern->init)(dev, init); |
390 | 425 | ||
391 | dev->mtu = transport->user->max_packet; | ||
392 | dev->open = uml_net_open; | ||
393 | dev->hard_start_xmit = uml_net_start_xmit; | ||
394 | dev->stop = uml_net_close; | ||
395 | dev->get_stats = uml_net_get_stats; | ||
396 | dev->set_multicast_list = uml_net_set_multicast_list; | ||
397 | dev->tx_timeout = uml_net_tx_timeout; | ||
398 | dev->set_mac_address = uml_net_set_mac; | ||
399 | dev->change_mtu = uml_net_change_mtu; | ||
400 | dev->ethtool_ops = ¨_net_ethtool_ops; | ||
401 | dev->watchdog_timeo = (HZ >> 1); | ||
402 | dev->irq = UM_ETH_IRQ; | ||
403 | |||
404 | rtnl_lock(); | ||
405 | err = register_netdevice(dev); | ||
406 | rtnl_unlock(); | ||
407 | if (err) { | ||
408 | device->dev = NULL; | ||
409 | /* XXX: should we call ->remove() here? */ | ||
410 | free_netdev(dev); | ||
411 | return 1; | ||
412 | } | ||
413 | |||
414 | /* lp.user is the first four bytes of the transport data, which | ||
415 | * has already been initialized. This structure assignment will | ||
416 | * overwrite that, so we make sure that .user gets overwritten with | ||
417 | * what it already has. | ||
418 | */ | ||
419 | save = lp->user[0]; | ||
420 | *lp = ((struct uml_net_private) | 426 | *lp = ((struct uml_net_private) |
421 | { .list = LIST_HEAD_INIT(lp->list), | 427 | { .list = LIST_HEAD_INIT(lp->list), |
422 | .dev = dev, | 428 | .dev = dev, |
@@ -430,20 +436,52 @@ static int eth_configure(int n, void *init, char *mac, | |||
430 | .write = transport->kern->write, | 436 | .write = transport->kern->write, |
431 | .add_address = transport->user->add_address, | 437 | .add_address = transport->user->add_address, |
432 | .delete_address = transport->user->delete_address, | 438 | .delete_address = transport->user->delete_address, |
433 | .set_mtu = transport->user->set_mtu, | 439 | .set_mtu = transport->user->set_mtu }); |
434 | .user = { save } }); | ||
435 | 440 | ||
436 | init_timer(&lp->tl); | 441 | init_timer(&lp->tl); |
437 | spin_lock_init(&lp->lock); | 442 | spin_lock_init(&lp->lock); |
438 | lp->tl.function = uml_net_user_timer_expire; | 443 | lp->tl.function = uml_net_user_timer_expire; |
439 | memcpy(lp->mac, device->mac, sizeof(lp->mac)); | 444 | memcpy(lp->mac, device->mac, sizeof(lp->mac)); |
440 | 445 | ||
441 | if (transport->user->init) | 446 | if ((transport->user->init != NULL) && |
442 | (*transport->user->init)(&lp->user, dev); | 447 | ((*transport->user->init)(&lp->user, dev) != 0)) |
448 | goto out_unregister; | ||
443 | 449 | ||
444 | set_ether_mac(dev, device->mac); | 450 | set_ether_mac(dev, device->mac); |
451 | dev->mtu = transport->user->max_packet; | ||
452 | dev->open = uml_net_open; | ||
453 | dev->hard_start_xmit = uml_net_start_xmit; | ||
454 | dev->stop = uml_net_close; | ||
455 | dev->get_stats = uml_net_get_stats; | ||
456 | dev->set_multicast_list = uml_net_set_multicast_list; | ||
457 | dev->tx_timeout = uml_net_tx_timeout; | ||
458 | dev->set_mac_address = uml_net_set_mac; | ||
459 | dev->change_mtu = uml_net_change_mtu; | ||
460 | dev->ethtool_ops = ¨_net_ethtool_ops; | ||
461 | dev->watchdog_timeo = (HZ >> 1); | ||
462 | dev->irq = UM_ETH_IRQ; | ||
445 | 463 | ||
446 | return 0; | 464 | rtnl_lock(); |
465 | err = register_netdevice(dev); | ||
466 | rtnl_unlock(); | ||
467 | if (err) | ||
468 | goto out_undo_user_init; | ||
469 | |||
470 | spin_lock(&devices_lock); | ||
471 | list_add(&device->list, &devices); | ||
472 | spin_unlock(&devices_lock); | ||
473 | |||
474 | return; | ||
475 | |||
476 | out_undo_user_init: | ||
477 | if (transport->user->remove != NULL) | ||
478 | (*transport->user->remove)(&lp->user); | ||
479 | out_unregister: | ||
480 | platform_device_unregister(&device->pdev); | ||
481 | out_free_netdev: | ||
482 | free_netdev(dev); | ||
483 | out_free_device: | ||
484 | kfree(device); | ||
447 | } | 485 | } |
448 | 486 | ||
449 | static struct uml_net *find_device(int n) | 487 | static struct uml_net *find_device(int n) |
@@ -666,13 +704,9 @@ static int net_remove(int n, char **error_out) | |||
666 | lp = dev->priv; | 704 | lp = dev->priv; |
667 | if(lp->fd > 0) | 705 | if(lp->fd > 0) |
668 | return -EBUSY; | 706 | return -EBUSY; |
669 | if(lp->remove != NULL) (*lp->remove)(&lp->user); | ||
670 | unregister_netdev(dev); | 707 | unregister_netdev(dev); |
671 | platform_device_unregister(&device->pdev); | 708 | platform_device_unregister(&device->pdev); |
672 | 709 | ||
673 | list_del(&device->list); | ||
674 | kfree(device); | ||
675 | free_netdev(dev); | ||
676 | return 0; | 710 | return 0; |
677 | } | 711 | } |
678 | 712 | ||
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c index 0ffd7ac295d4..3503cff867c3 100644 --- a/arch/um/drivers/net_user.c +++ b/arch/um/drivers/net_user.c | |||
@@ -14,11 +14,11 @@ | |||
14 | #include <sys/wait.h> | 14 | #include <sys/wait.h> |
15 | #include <sys/time.h> | 15 | #include <sys/time.h> |
16 | #include "user.h" | 16 | #include "user.h" |
17 | #include "user_util.h" | ||
18 | #include "kern_util.h" | 17 | #include "kern_util.h" |
19 | #include "net_user.h" | 18 | #include "net_user.h" |
20 | #include "os.h" | 19 | #include "os.h" |
21 | #include "um_malloc.h" | 20 | #include "um_malloc.h" |
21 | #include "kern_constants.h" | ||
22 | 22 | ||
23 | int tap_open_common(void *dev, char *gate_addr) | 23 | int tap_open_common(void *dev, char *gate_addr) |
24 | { | 24 | { |
@@ -216,7 +216,7 @@ static void change(char *dev, char *what, unsigned char *addr, | |||
216 | sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1], | 216 | sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1], |
217 | netmask[2], netmask[3]); | 217 | netmask[2], netmask[3]); |
218 | 218 | ||
219 | output_len = page_size(); | 219 | output_len = UM_KERN_PAGE_SIZE; |
220 | output = um_kmalloc(output_len); | 220 | output = um_kmalloc(output_len); |
221 | if(output == NULL) | 221 | if(output == NULL) |
222 | printk("change : failed to allocate output buffer\n"); | 222 | printk("change : failed to allocate output buffer\n"); |
diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c index 11921a7baa7b..dc0a903ef9a6 100644 --- a/arch/um/drivers/pcap_user.c +++ b/arch/um/drivers/pcap_user.c | |||
@@ -18,7 +18,7 @@ | |||
18 | 18 | ||
19 | #define PCAP_FD(p) (*(int *)(p)) | 19 | #define PCAP_FD(p) (*(int *)(p)) |
20 | 20 | ||
21 | static void pcap_user_init(void *data, void *dev) | 21 | static int pcap_user_init(void *data, void *dev) |
22 | { | 22 | { |
23 | struct pcap_data *pri = data; | 23 | struct pcap_data *pri = data; |
24 | pcap_t *p; | 24 | pcap_t *p; |
@@ -28,11 +28,12 @@ static void pcap_user_init(void *data, void *dev) | |||
28 | if(p == NULL){ | 28 | if(p == NULL){ |
29 | printk("pcap_user_init : pcap_open_live failed - '%s'\n", | 29 | printk("pcap_user_init : pcap_open_live failed - '%s'\n", |
30 | errors); | 30 | errors); |
31 | return; | 31 | return -EINVAL; |
32 | } | 32 | } |
33 | 33 | ||
34 | pri->dev = dev; | 34 | pri->dev = dev; |
35 | pri->pcap = p; | 35 | pri->pcap = p; |
36 | return 0; | ||
36 | } | 37 | } |
37 | 38 | ||
38 | static int pcap_open(void *data) | 39 | static int pcap_open(void *data) |
@@ -42,39 +43,39 @@ static int pcap_open(void *data) | |||
42 | int err; | 43 | int err; |
43 | 44 | ||
44 | if(pri->pcap == NULL) | 45 | if(pri->pcap == NULL) |
45 | return(-ENODEV); | 46 | return -ENODEV; |
46 | 47 | ||
47 | if(pri->filter != NULL){ | 48 | if(pri->filter != NULL){ |
48 | err = dev_netmask(pri->dev, &netmask); | 49 | err = dev_netmask(pri->dev, &netmask); |
49 | if(err < 0){ | 50 | if(err < 0){ |
50 | printk("pcap_open : dev_netmask failed\n"); | 51 | printk("pcap_open : dev_netmask failed\n"); |
51 | return(-EIO); | 52 | return -EIO; |
52 | } | 53 | } |
53 | 54 | ||
54 | pri->compiled = um_kmalloc(sizeof(struct bpf_program)); | 55 | pri->compiled = um_kmalloc(sizeof(struct bpf_program)); |
55 | if(pri->compiled == NULL){ | 56 | if(pri->compiled == NULL){ |
56 | printk("pcap_open : kmalloc failed\n"); | 57 | printk("pcap_open : kmalloc failed\n"); |
57 | return(-ENOMEM); | 58 | return -ENOMEM; |
58 | } | 59 | } |
59 | 60 | ||
60 | err = pcap_compile(pri->pcap, | 61 | err = pcap_compile(pri->pcap, |
61 | (struct bpf_program *) pri->compiled, | 62 | (struct bpf_program *) pri->compiled, |
62 | pri->filter, pri->optimize, netmask); | 63 | pri->filter, pri->optimize, netmask); |
63 | if(err < 0){ | 64 | if(err < 0){ |
64 | printk("pcap_open : pcap_compile failed - '%s'\n", | 65 | printk("pcap_open : pcap_compile failed - '%s'\n", |
65 | pcap_geterr(pri->pcap)); | 66 | pcap_geterr(pri->pcap)); |
66 | return(-EIO); | 67 | return -EIO; |
67 | } | 68 | } |
68 | 69 | ||
69 | err = pcap_setfilter(pri->pcap, pri->compiled); | 70 | err = pcap_setfilter(pri->pcap, pri->compiled); |
70 | if(err < 0){ | 71 | if(err < 0){ |
71 | printk("pcap_open : pcap_setfilter failed - '%s'\n", | 72 | printk("pcap_open : pcap_setfilter failed - '%s'\n", |
72 | pcap_geterr(pri->pcap)); | 73 | pcap_geterr(pri->pcap)); |
73 | return(-EIO); | 74 | return -EIO; |
74 | } | 75 | } |
75 | } | 76 | } |
76 | 77 | ||
77 | return(PCAP_FD(pri->pcap)); | 78 | return PCAP_FD(pri->pcap); |
78 | } | 79 | } |
79 | 80 | ||
80 | static void pcap_remove(void *data) | 81 | static void pcap_remove(void *data) |
@@ -114,11 +115,11 @@ int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri) | |||
114 | n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata); | 115 | n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata); |
115 | if(n < 0){ | 116 | if(n < 0){ |
116 | printk("pcap_dispatch failed - %s\n", pcap_geterr(pri->pcap)); | 117 | printk("pcap_dispatch failed - %s\n", pcap_geterr(pri->pcap)); |
117 | return(-EIO); | 118 | return -EIO; |
118 | } | 119 | } |
119 | else if(n == 0) | 120 | else if(n == 0) |
120 | return(0); | 121 | return 0; |
121 | return(hdata.len); | 122 | return hdata.len; |
122 | } | 123 | } |
123 | 124 | ||
124 | const struct net_user_info pcap_user_info = { | 125 | const struct net_user_info pcap_user_info = { |
@@ -131,14 +132,3 @@ const struct net_user_info pcap_user_info = { | |||
131 | .delete_address = NULL, | 132 | .delete_address = NULL, |
132 | .max_packet = MAX_PACKET - ETH_HEADER_OTHER | 133 | .max_packet = MAX_PACKET - ETH_HEADER_OTHER |
133 | }; | 134 | }; |
134 | |||
135 | /* | ||
136 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
137 | * Emacs will notice this stuff at the end of the file and automatically | ||
138 | * adjust the settings for this buffer only. This must remain at the end | ||
139 | * of the file. | ||
140 | * --------------------------------------------------------------------------- | ||
141 | * Local variables: | ||
142 | * c-file-style: "linux" | ||
143 | * End: | ||
144 | */ | ||
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c index 80508023054f..3f6357d24bee 100644 --- a/arch/um/drivers/port_user.c +++ b/arch/um/drivers/port_user.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <sys/socket.h> | 13 | #include <sys/socket.h> |
14 | #include <sys/un.h> | 14 | #include <sys/un.h> |
15 | #include <netinet/in.h> | 15 | #include <netinet/in.h> |
16 | #include "user_util.h" | ||
17 | #include "kern_util.h" | 16 | #include "kern_util.h" |
18 | #include "user.h" | 17 | #include "user.h" |
19 | #include "chan_user.h" | 18 | #include "chan_user.h" |
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c index 829a5eca8c07..df4976c9eef2 100644 --- a/arch/um/drivers/pty.c +++ b/arch/um/drivers/pty.c | |||
@@ -4,13 +4,13 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdio.h> | 6 | #include <stdio.h> |
7 | #include <stdlib.h> | ||
7 | #include <unistd.h> | 8 | #include <unistd.h> |
8 | #include <string.h> | 9 | #include <string.h> |
9 | #include <errno.h> | 10 | #include <errno.h> |
10 | #include <termios.h> | 11 | #include <termios.h> |
11 | #include "chan_user.h" | 12 | #include "chan_user.h" |
12 | #include "user.h" | 13 | #include "user.h" |
13 | #include "user_util.h" | ||
14 | #include "kern_util.h" | 14 | #include "kern_util.h" |
15 | #include "os.h" | 15 | #include "os.h" |
16 | #include "um_malloc.h" | 16 | #include "um_malloc.h" |
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c index 7eddacc53b6e..78f0e515da8f 100644 --- a/arch/um/drivers/slip_user.c +++ b/arch/um/drivers/slip_user.c | |||
@@ -8,7 +8,6 @@ | |||
8 | #include <sys/termios.h> | 8 | #include <sys/termios.h> |
9 | #include <sys/wait.h> | 9 | #include <sys/wait.h> |
10 | #include <sys/signal.h> | 10 | #include <sys/signal.h> |
11 | #include "user_util.h" | ||
12 | #include "kern_util.h" | 11 | #include "kern_util.h" |
13 | #include "user.h" | 12 | #include "user.h" |
14 | #include "net_user.h" | 13 | #include "net_user.h" |
@@ -16,12 +15,14 @@ | |||
16 | #include "slip_common.h" | 15 | #include "slip_common.h" |
17 | #include "os.h" | 16 | #include "os.h" |
18 | #include "um_malloc.h" | 17 | #include "um_malloc.h" |
18 | #include "kern_constants.h" | ||
19 | 19 | ||
20 | void slip_user_init(void *data, void *dev) | 20 | static int slip_user_init(void *data, void *dev) |
21 | { | 21 | { |
22 | struct slip_data *pri = data; | 22 | struct slip_data *pri = data; |
23 | 23 | ||
24 | pri->dev = dev; | 24 | pri->dev = dev; |
25 | return 0; | ||
25 | } | 26 | } |
26 | 27 | ||
27 | static int set_up_tty(int fd) | 28 | static int set_up_tty(int fd) |
@@ -89,7 +90,7 @@ static int slip_tramp(char **argv, int fd) | |||
89 | goto out_close; | 90 | goto out_close; |
90 | pid = err; | 91 | pid = err; |
91 | 92 | ||
92 | output_len = page_size(); | 93 | output_len = UM_KERN_PAGE_SIZE; |
93 | output = um_kmalloc(output_len); | 94 | output = um_kmalloc(output_len); |
94 | if(output == NULL){ | 95 | if(output == NULL){ |
95 | printk("slip_tramp : failed to allocate output buffer\n"); | 96 | printk("slip_tramp : failed to allocate output buffer\n"); |
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c index ce5e85d1de3d..39f889fe9949 100644 --- a/arch/um/drivers/slirp_user.c +++ b/arch/um/drivers/slirp_user.c | |||
@@ -7,7 +7,6 @@ | |||
7 | #include <errno.h> | 7 | #include <errno.h> |
8 | #include <sys/wait.h> | 8 | #include <sys/wait.h> |
9 | #include <sys/signal.h> | 9 | #include <sys/signal.h> |
10 | #include "user_util.h" | ||
11 | #include "kern_util.h" | 10 | #include "kern_util.h" |
12 | #include "user.h" | 11 | #include "user.h" |
13 | #include "net_user.h" | 12 | #include "net_user.h" |
@@ -15,11 +14,12 @@ | |||
15 | #include "slip_common.h" | 14 | #include "slip_common.h" |
16 | #include "os.h" | 15 | #include "os.h" |
17 | 16 | ||
18 | void slirp_user_init(void *data, void *dev) | 17 | static int slirp_user_init(void *data, void *dev) |
19 | { | 18 | { |
20 | struct slirp_data *pri = data; | 19 | struct slirp_data *pri = data; |
21 | 20 | ||
22 | pri->dev = dev; | 21 | pri->dev = dev; |
22 | return 0; | ||
23 | } | 23 | } |
24 | 24 | ||
25 | struct slirp_pre_exec_data { | 25 | struct slirp_pre_exec_data { |
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index 4b382a6e710f..fd09ad9e9c0a 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include "line.h" | 15 | #include "line.h" |
16 | #include "ssl.h" | 16 | #include "ssl.h" |
17 | #include "chan_kern.h" | 17 | #include "chan_kern.h" |
18 | #include "user_util.h" | ||
19 | #include "kern_util.h" | 18 | #include "kern_util.h" |
20 | #include "kern.h" | 19 | #include "kern.h" |
21 | #include "init.h" | 20 | #include "init.h" |
@@ -192,12 +191,12 @@ static int ssl_init(void) | |||
192 | ssl_driver = register_lines(&driver, &ssl_ops, serial_lines, | 191 | ssl_driver = register_lines(&driver, &ssl_ops, serial_lines, |
193 | ARRAY_SIZE(serial_lines)); | 192 | ARRAY_SIZE(serial_lines)); |
194 | 193 | ||
195 | lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts); | ||
196 | |||
197 | new_title = add_xterm_umid(opts.xterm_title); | 194 | new_title = add_xterm_umid(opts.xterm_title); |
198 | if (new_title != NULL) | 195 | if (new_title != NULL) |
199 | opts.xterm_title = new_title; | 196 | opts.xterm_title = new_title; |
200 | 197 | ||
198 | lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts); | ||
199 | |||
201 | ssl_init_done = 1; | 200 | ssl_init_done = 1; |
202 | register_console(&ssl_cons); | 201 | register_console(&ssl_cons); |
203 | return 0; | 202 | return 0; |
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 76d1f1c980ef..2bb4193ac1aa 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include "stdio_console.h" | 22 | #include "stdio_console.h" |
23 | #include "line.h" | 23 | #include "line.h" |
24 | #include "chan_kern.h" | 24 | #include "chan_kern.h" |
25 | #include "user_util.h" | ||
26 | #include "kern_util.h" | 25 | #include "kern_util.h" |
27 | #include "irq_user.h" | 26 | #include "irq_user.h" |
28 | #include "mconsole_kern.h" | 27 | #include "mconsole_kern.h" |
@@ -167,12 +166,12 @@ int stdio_init(void) | |||
167 | return -1; | 166 | return -1; |
168 | printk(KERN_INFO "Initialized stdio console driver\n"); | 167 | printk(KERN_INFO "Initialized stdio console driver\n"); |
169 | 168 | ||
170 | lines_init(vts, ARRAY_SIZE(vts), &opts); | ||
171 | |||
172 | new_title = add_xterm_umid(opts.xterm_title); | 169 | new_title = add_xterm_umid(opts.xterm_title); |
173 | if(new_title != NULL) | 170 | if(new_title != NULL) |
174 | opts.xterm_title = new_title; | 171 | opts.xterm_title = new_title; |
175 | 172 | ||
173 | lines_init(vts, ARRAY_SIZE(vts), &opts); | ||
174 | |||
176 | con_init_done = 1; | 175 | con_init_done = 1; |
177 | register_console(&stdiocons); | 176 | register_console(&stdiocons); |
178 | return 0; | 177 | return 0; |
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c index d95d64309eaf..c07d0d562780 100644 --- a/arch/um/drivers/tty.c +++ b/arch/um/drivers/tty.c | |||
@@ -8,7 +8,6 @@ | |||
8 | #include <errno.h> | 8 | #include <errno.h> |
9 | #include <unistd.h> | 9 | #include <unistd.h> |
10 | #include "chan_user.h" | 10 | #include "chan_user.h" |
11 | #include "user_util.h" | ||
12 | #include "user.h" | 11 | #include "user.h" |
13 | #include "os.h" | 12 | #include "os.h" |
14 | #include "um_malloc.h" | 13 | #include "um_malloc.h" |
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 8bd9204ac1ab..70509ddaac03 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c | |||
@@ -39,7 +39,6 @@ | |||
39 | #include "asm/irq.h" | 39 | #include "asm/irq.h" |
40 | #include "asm/types.h" | 40 | #include "asm/types.h" |
41 | #include "asm/tlbflush.h" | 41 | #include "asm/tlbflush.h" |
42 | #include "user_util.h" | ||
43 | #include "mem_user.h" | 42 | #include "mem_user.h" |
44 | #include "kern_util.h" | 43 | #include "kern_util.h" |
45 | #include "kern.h" | 44 | #include "kern.h" |
@@ -90,7 +89,7 @@ static inline int ubd_test_bit(__u64 bit, unsigned char *data) | |||
90 | bits = sizeof(data[0]) * 8; | 89 | bits = sizeof(data[0]) * 8; |
91 | n = bit / bits; | 90 | n = bit / bits; |
92 | off = bit % bits; | 91 | off = bit % bits; |
93 | return((data[n] & (1 << off)) != 0); | 92 | return (data[n] & (1 << off)) != 0; |
94 | } | 93 | } |
95 | 94 | ||
96 | static inline void ubd_set_bit(__u64 bit, unsigned char *data) | 95 | static inline void ubd_set_bit(__u64 bit, unsigned char *data) |
@@ -147,10 +146,13 @@ struct cow { | |||
147 | unsigned long *bitmap; | 146 | unsigned long *bitmap; |
148 | unsigned long bitmap_len; | 147 | unsigned long bitmap_len; |
149 | int bitmap_offset; | 148 | int bitmap_offset; |
150 | int data_offset; | 149 | int data_offset; |
151 | }; | 150 | }; |
152 | 151 | ||
152 | #define MAX_SG 64 | ||
153 | |||
153 | struct ubd { | 154 | struct ubd { |
155 | struct list_head restart; | ||
154 | /* name (and fd, below) of the file opened for writing, either the | 156 | /* name (and fd, below) of the file opened for writing, either the |
155 | * backing or the cow file. */ | 157 | * backing or the cow file. */ |
156 | char *file; | 158 | char *file; |
@@ -165,15 +167,17 @@ struct ubd { | |||
165 | struct platform_device pdev; | 167 | struct platform_device pdev; |
166 | struct request_queue *queue; | 168 | struct request_queue *queue; |
167 | spinlock_t lock; | 169 | spinlock_t lock; |
168 | int active; | 170 | struct scatterlist sg[MAX_SG]; |
171 | struct request *request; | ||
172 | int start_sg, end_sg; | ||
169 | }; | 173 | }; |
170 | 174 | ||
171 | #define DEFAULT_COW { \ | 175 | #define DEFAULT_COW { \ |
172 | .file = NULL, \ | 176 | .file = NULL, \ |
173 | .fd = -1, \ | 177 | .fd = -1, \ |
174 | .bitmap = NULL, \ | 178 | .bitmap = NULL, \ |
175 | .bitmap_offset = 0, \ | 179 | .bitmap_offset = 0, \ |
176 | .data_offset = 0, \ | 180 | .data_offset = 0, \ |
177 | } | 181 | } |
178 | 182 | ||
179 | #define DEFAULT_UBD { \ | 183 | #define DEFAULT_UBD { \ |
@@ -183,11 +187,13 @@ struct ubd { | |||
183 | .size = -1, \ | 187 | .size = -1, \ |
184 | .boot_openflags = OPEN_FLAGS, \ | 188 | .boot_openflags = OPEN_FLAGS, \ |
185 | .openflags = OPEN_FLAGS, \ | 189 | .openflags = OPEN_FLAGS, \ |
186 | .no_cow = 0, \ | 190 | .no_cow = 0, \ |
187 | .shared = 0, \ | 191 | .shared = 0, \ |
188 | .cow = DEFAULT_COW, \ | 192 | .cow = DEFAULT_COW, \ |
189 | .lock = SPIN_LOCK_UNLOCKED, \ | 193 | .lock = SPIN_LOCK_UNLOCKED, \ |
190 | .active = 0, \ | 194 | .request = NULL, \ |
195 | .start_sg = 0, \ | ||
196 | .end_sg = 0, \ | ||
191 | } | 197 | } |
192 | 198 | ||
193 | /* Protected by ubd_lock */ | 199 | /* Protected by ubd_lock */ |
@@ -243,7 +249,7 @@ static void make_ide_entries(char *dev_name) | |||
243 | static int fake_ide_setup(char *str) | 249 | static int fake_ide_setup(char *str) |
244 | { | 250 | { |
245 | fake_ide = 1; | 251 | fake_ide = 1; |
246 | return(1); | 252 | return 1; |
247 | } | 253 | } |
248 | 254 | ||
249 | __setup("fake_ide", fake_ide_setup); | 255 | __setup("fake_ide", fake_ide_setup); |
@@ -261,7 +267,7 @@ static int parse_unit(char **ptr) | |||
261 | if(isdigit(*str)) { | 267 | if(isdigit(*str)) { |
262 | n = simple_strtoul(str, &end, 0); | 268 | n = simple_strtoul(str, &end, 0); |
263 | if(end == str) | 269 | if(end == str) |
264 | return(-1); | 270 | return -1; |
265 | *ptr = end; | 271 | *ptr = end; |
266 | } | 272 | } |
267 | else if (('a' <= *str) && (*str <= 'z')) { | 273 | else if (('a' <= *str) && (*str <= 'z')) { |
@@ -269,7 +275,7 @@ static int parse_unit(char **ptr) | |||
269 | str++; | 275 | str++; |
270 | *ptr = str; | 276 | *ptr = str; |
271 | } | 277 | } |
272 | return(n); | 278 | return n; |
273 | } | 279 | } |
274 | 280 | ||
275 | /* If *index_out == -1 at exit, the passed option was a general one; | 281 | /* If *index_out == -1 at exit, the passed option was a general one; |
@@ -436,7 +442,7 @@ static int udb_setup(char *str) | |||
436 | { | 442 | { |
437 | printk("udb%s specified on command line is almost certainly a ubd -> " | 443 | printk("udb%s specified on command line is almost certainly a ubd -> " |
438 | "udb TYPO\n", str); | 444 | "udb TYPO\n", str); |
439 | return(1); | 445 | return 1; |
440 | } | 446 | } |
441 | 447 | ||
442 | __setup("udb", udb_setup); | 448 | __setup("udb", udb_setup); |
@@ -467,66 +473,75 @@ static void do_ubd_request(request_queue_t * q); | |||
467 | /* Only changed by ubd_init, which is an initcall. */ | 473 | /* Only changed by ubd_init, which is an initcall. */ |
468 | int thread_fd = -1; | 474 | int thread_fd = -1; |
469 | 475 | ||
470 | /* call ubd_finish if you need to serialize */ | 476 | static void ubd_end_request(struct request *req, int bytes, int uptodate) |
471 | static void __ubd_finish(struct request *req, int error) | ||
472 | { | 477 | { |
473 | int nsect; | 478 | if (!end_that_request_first(req, uptodate, bytes >> 9)) { |
474 | 479 | struct ubd *dev = req->rq_disk->private_data; | |
475 | if(error){ | 480 | unsigned long flags; |
476 | end_request(req, 0); | 481 | |
477 | return; | 482 | add_disk_randomness(req->rq_disk); |
483 | spin_lock_irqsave(&dev->lock, flags); | ||
484 | end_that_request_last(req, uptodate); | ||
485 | spin_unlock_irqrestore(&dev->lock, flags); | ||
478 | } | 486 | } |
479 | nsect = req->current_nr_sectors; | ||
480 | req->sector += nsect; | ||
481 | req->buffer += nsect << 9; | ||
482 | req->errors = 0; | ||
483 | req->nr_sectors -= nsect; | ||
484 | req->current_nr_sectors = 0; | ||
485 | end_request(req, 1); | ||
486 | } | 487 | } |
487 | 488 | ||
488 | /* Callable only from interrupt context - otherwise you need to do | 489 | /* Callable only from interrupt context - otherwise you need to do |
489 | * spin_lock_irq()/spin_lock_irqsave() */ | 490 | * spin_lock_irq()/spin_lock_irqsave() */ |
490 | static inline void ubd_finish(struct request *req, int error) | 491 | static inline void ubd_finish(struct request *req, int bytes) |
491 | { | 492 | { |
492 | struct ubd *dev = req->rq_disk->private_data; | 493 | if(bytes < 0){ |
493 | 494 | ubd_end_request(req, 0, 0); | |
494 | spin_lock(&dev->lock); | 495 | return; |
495 | __ubd_finish(req, error); | 496 | } |
496 | spin_unlock(&dev->lock); | 497 | ubd_end_request(req, bytes, 1); |
497 | } | 498 | } |
498 | 499 | ||
500 | static LIST_HEAD(restart); | ||
501 | |||
499 | /* XXX - move this inside ubd_intr. */ | 502 | /* XXX - move this inside ubd_intr. */ |
500 | /* Called without dev->lock held, and only in interrupt context. */ | 503 | /* Called without dev->lock held, and only in interrupt context. */ |
501 | static void ubd_handler(void) | 504 | static void ubd_handler(void) |
502 | { | 505 | { |
503 | struct io_thread_req req; | 506 | struct io_thread_req *req; |
504 | struct request *rq; | 507 | struct request *rq; |
505 | struct ubd *dev; | 508 | struct ubd *ubd; |
509 | struct list_head *list, *next_ele; | ||
510 | unsigned long flags; | ||
506 | int n; | 511 | int n; |
507 | 512 | ||
508 | n = os_read_file(thread_fd, &req, sizeof(req)); | 513 | while(1){ |
509 | if(n != sizeof(req)){ | 514 | n = os_read_file(thread_fd, &req, |
510 | printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, " | 515 | sizeof(struct io_thread_req *)); |
511 | "err = %d\n", os_getpid(), -n); | 516 | if(n != sizeof(req)){ |
512 | return; | 517 | if(n == -EAGAIN) |
513 | } | 518 | break; |
514 | 519 | printk(KERN_ERR "spurious interrupt in ubd_handler, " | |
515 | rq = req.req; | 520 | "err = %d\n", -n); |
516 | dev = rq->rq_disk->private_data; | 521 | return; |
517 | dev->active = 0; | 522 | } |
518 | 523 | ||
519 | ubd_finish(rq, req.error); | 524 | rq = req->req; |
525 | rq->nr_sectors -= req->length >> 9; | ||
526 | if(rq->nr_sectors == 0) | ||
527 | ubd_finish(rq, rq->hard_nr_sectors << 9); | ||
528 | kfree(req); | ||
529 | } | ||
520 | reactivate_fd(thread_fd, UBD_IRQ); | 530 | reactivate_fd(thread_fd, UBD_IRQ); |
521 | spin_lock(&dev->lock); | 531 | |
522 | do_ubd_request(dev->queue); | 532 | list_for_each_safe(list, next_ele, &restart){ |
523 | spin_unlock(&dev->lock); | 533 | ubd = container_of(list, struct ubd, restart); |
534 | list_del_init(&ubd->restart); | ||
535 | spin_lock_irqsave(&ubd->lock, flags); | ||
536 | do_ubd_request(ubd->queue); | ||
537 | spin_unlock_irqrestore(&ubd->lock, flags); | ||
538 | } | ||
524 | } | 539 | } |
525 | 540 | ||
526 | static irqreturn_t ubd_intr(int irq, void *dev) | 541 | static irqreturn_t ubd_intr(int irq, void *dev) |
527 | { | 542 | { |
528 | ubd_handler(); | 543 | ubd_handler(); |
529 | return(IRQ_HANDLED); | 544 | return IRQ_HANDLED; |
530 | } | 545 | } |
531 | 546 | ||
532 | /* Only changed by ubd_init, which is an initcall. */ | 547 | /* Only changed by ubd_init, which is an initcall. */ |
@@ -545,7 +560,7 @@ static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out) | |||
545 | char *file; | 560 | char *file; |
546 | 561 | ||
547 | file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file; | 562 | file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file; |
548 | return(os_file_size(file, size_out)); | 563 | return os_file_size(file, size_out); |
549 | } | 564 | } |
550 | 565 | ||
551 | static void ubd_close_dev(struct ubd *ubd_dev) | 566 | static void ubd_close_dev(struct ubd *ubd_dev) |
@@ -617,10 +632,18 @@ static int ubd_open_dev(struct ubd *ubd_dev) | |||
617 | if(err < 0) goto error; | 632 | if(err < 0) goto error; |
618 | ubd_dev->cow.fd = err; | 633 | ubd_dev->cow.fd = err; |
619 | } | 634 | } |
620 | return(0); | 635 | return 0; |
621 | error: | 636 | error: |
622 | os_close_file(ubd_dev->fd); | 637 | os_close_file(ubd_dev->fd); |
623 | return(err); | 638 | return err; |
639 | } | ||
640 | |||
641 | static void ubd_device_release(struct device *dev) | ||
642 | { | ||
643 | struct ubd *ubd_dev = dev->driver_data; | ||
644 | |||
645 | blk_cleanup_queue(ubd_dev->queue); | ||
646 | *ubd_dev = ((struct ubd) DEFAULT_UBD); | ||
624 | } | 647 | } |
625 | 648 | ||
626 | static int ubd_disk_register(int major, u64 size, int unit, | 649 | static int ubd_disk_register(int major, u64 size, int unit, |
@@ -630,7 +653,7 @@ static int ubd_disk_register(int major, u64 size, int unit, | |||
630 | 653 | ||
631 | disk = alloc_disk(1 << UBD_SHIFT); | 654 | disk = alloc_disk(1 << UBD_SHIFT); |
632 | if(disk == NULL) | 655 | if(disk == NULL) |
633 | return(-ENOMEM); | 656 | return -ENOMEM; |
634 | 657 | ||
635 | disk->major = major; | 658 | disk->major = major; |
636 | disk->first_minor = unit << UBD_SHIFT; | 659 | disk->first_minor = unit << UBD_SHIFT; |
@@ -645,6 +668,8 @@ static int ubd_disk_register(int major, u64 size, int unit, | |||
645 | if (major == MAJOR_NR) { | 668 | if (major == MAJOR_NR) { |
646 | ubd_devs[unit].pdev.id = unit; | 669 | ubd_devs[unit].pdev.id = unit; |
647 | ubd_devs[unit].pdev.name = DRIVER_NAME; | 670 | ubd_devs[unit].pdev.name = DRIVER_NAME; |
671 | ubd_devs[unit].pdev.dev.release = ubd_device_release; | ||
672 | ubd_devs[unit].pdev.dev.driver_data = &ubd_devs[unit]; | ||
648 | platform_device_register(&ubd_devs[unit].pdev); | 673 | platform_device_register(&ubd_devs[unit].pdev); |
649 | disk->driverfs_dev = &ubd_devs[unit].pdev.dev; | 674 | disk->driverfs_dev = &ubd_devs[unit].pdev.dev; |
650 | } | 675 | } |
@@ -675,6 +700,8 @@ static int ubd_add(int n, char **error_out) | |||
675 | 700 | ||
676 | ubd_dev->size = ROUND_BLOCK(ubd_dev->size); | 701 | ubd_dev->size = ROUND_BLOCK(ubd_dev->size); |
677 | 702 | ||
703 | INIT_LIST_HEAD(&ubd_dev->restart); | ||
704 | |||
678 | err = -ENOMEM; | 705 | err = -ENOMEM; |
679 | ubd_dev->queue = blk_init_queue(do_ubd_request, &ubd_dev->lock); | 706 | ubd_dev->queue = blk_init_queue(do_ubd_request, &ubd_dev->lock); |
680 | if (ubd_dev->queue == NULL) { | 707 | if (ubd_dev->queue == NULL) { |
@@ -683,6 +710,7 @@ static int ubd_add(int n, char **error_out) | |||
683 | } | 710 | } |
684 | ubd_dev->queue->queuedata = ubd_dev; | 711 | ubd_dev->queue->queuedata = ubd_dev; |
685 | 712 | ||
713 | blk_queue_max_hw_segments(ubd_dev->queue, MAX_SG); | ||
686 | err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]); | 714 | err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]); |
687 | if(err){ | 715 | if(err){ |
688 | *error_out = "Failed to register device"; | 716 | *error_out = "Failed to register device"; |
@@ -730,14 +758,14 @@ static int ubd_config(char *str, char **error_out) | |||
730 | goto err_free; | 758 | goto err_free; |
731 | } | 759 | } |
732 | 760 | ||
733 | mutex_lock(&ubd_lock); | 761 | mutex_lock(&ubd_lock); |
734 | ret = ubd_add(n, error_out); | 762 | ret = ubd_add(n, error_out); |
735 | if (ret) | 763 | if (ret) |
736 | ubd_devs[n].file = NULL; | 764 | ubd_devs[n].file = NULL; |
737 | mutex_unlock(&ubd_lock); | 765 | mutex_unlock(&ubd_lock); |
738 | 766 | ||
739 | out: | 767 | out: |
740 | return ret; | 768 | return ret; |
741 | 769 | ||
742 | err_free: | 770 | err_free: |
743 | kfree(str); | 771 | kfree(str); |
@@ -752,7 +780,7 @@ static int ubd_get_config(char *name, char *str, int size, char **error_out) | |||
752 | n = parse_unit(&name); | 780 | n = parse_unit(&name); |
753 | if((n >= MAX_DEV) || (n < 0)){ | 781 | if((n >= MAX_DEV) || (n < 0)){ |
754 | *error_out = "ubd_get_config : device number out of range"; | 782 | *error_out = "ubd_get_config : device number out of range"; |
755 | return(-1); | 783 | return -1; |
756 | } | 784 | } |
757 | 785 | ||
758 | ubd_dev = &ubd_devs[n]; | 786 | ubd_dev = &ubd_devs[n]; |
@@ -773,29 +801,27 @@ static int ubd_get_config(char *name, char *str, int size, char **error_out) | |||
773 | 801 | ||
774 | out: | 802 | out: |
775 | mutex_unlock(&ubd_lock); | 803 | mutex_unlock(&ubd_lock); |
776 | return(len); | 804 | return len; |
777 | } | 805 | } |
778 | 806 | ||
779 | static int ubd_id(char **str, int *start_out, int *end_out) | 807 | static int ubd_id(char **str, int *start_out, int *end_out) |
780 | { | 808 | { |
781 | int n; | 809 | int n; |
782 | 810 | ||
783 | n = parse_unit(str); | 811 | n = parse_unit(str); |
784 | *start_out = 0; | 812 | *start_out = 0; |
785 | *end_out = MAX_DEV - 1; | 813 | *end_out = MAX_DEV - 1; |
786 | return n; | 814 | return n; |
787 | } | 815 | } |
788 | 816 | ||
789 | static int ubd_remove(int n, char **error_out) | 817 | static int ubd_remove(int n, char **error_out) |
790 | { | 818 | { |
819 | struct gendisk *disk = ubd_gendisk[n]; | ||
791 | struct ubd *ubd_dev; | 820 | struct ubd *ubd_dev; |
792 | int err = -ENODEV; | 821 | int err = -ENODEV; |
793 | 822 | ||
794 | mutex_lock(&ubd_lock); | 823 | mutex_lock(&ubd_lock); |
795 | 824 | ||
796 | if(ubd_gendisk[n] == NULL) | ||
797 | goto out; | ||
798 | |||
799 | ubd_dev = &ubd_devs[n]; | 825 | ubd_dev = &ubd_devs[n]; |
800 | 826 | ||
801 | if(ubd_dev->file == NULL) | 827 | if(ubd_dev->file == NULL) |
@@ -806,9 +832,11 @@ static int ubd_remove(int n, char **error_out) | |||
806 | if(ubd_dev->count > 0) | 832 | if(ubd_dev->count > 0) |
807 | goto out; | 833 | goto out; |
808 | 834 | ||
809 | del_gendisk(ubd_gendisk[n]); | ||
810 | put_disk(ubd_gendisk[n]); | ||
811 | ubd_gendisk[n] = NULL; | 835 | ubd_gendisk[n] = NULL; |
836 | if(disk != NULL){ | ||
837 | del_gendisk(disk); | ||
838 | put_disk(disk); | ||
839 | } | ||
812 | 840 | ||
813 | if(fake_gendisk[n] != NULL){ | 841 | if(fake_gendisk[n] != NULL){ |
814 | del_gendisk(fake_gendisk[n]); | 842 | del_gendisk(fake_gendisk[n]); |
@@ -816,10 +844,8 @@ static int ubd_remove(int n, char **error_out) | |||
816 | fake_gendisk[n] = NULL; | 844 | fake_gendisk[n] = NULL; |
817 | } | 845 | } |
818 | 846 | ||
819 | blk_cleanup_queue(ubd_dev->queue); | ||
820 | platform_device_unregister(&ubd_dev->pdev); | ||
821 | *ubd_dev = ((struct ubd) DEFAULT_UBD); | ||
822 | err = 0; | 847 | err = 0; |
848 | platform_device_unregister(&ubd_dev->pdev); | ||
823 | out: | 849 | out: |
824 | mutex_unlock(&ubd_lock); | 850 | mutex_unlock(&ubd_lock); |
825 | return err; | 851 | return err; |
@@ -832,7 +858,7 @@ static struct mc_device ubd_mc = { | |||
832 | .list = LIST_HEAD_INIT(ubd_mc.list), | 858 | .list = LIST_HEAD_INIT(ubd_mc.list), |
833 | .name = "ubd", | 859 | .name = "ubd", |
834 | .config = ubd_config, | 860 | .config = ubd_config, |
835 | .get_config = ubd_get_config, | 861 | .get_config = ubd_get_config, |
836 | .id = ubd_id, | 862 | .id = ubd_id, |
837 | .remove = ubd_remove, | 863 | .remove = ubd_remove, |
838 | }; | 864 | }; |
@@ -854,7 +880,7 @@ static int __init ubd0_init(void) | |||
854 | ubd_dev->file = "root_fs"; | 880 | ubd_dev->file = "root_fs"; |
855 | mutex_unlock(&ubd_lock); | 881 | mutex_unlock(&ubd_lock); |
856 | 882 | ||
857 | return(0); | 883 | return 0; |
858 | } | 884 | } |
859 | 885 | ||
860 | __initcall(ubd0_init); | 886 | __initcall(ubd0_init); |
@@ -882,14 +908,14 @@ static int __init ubd_init(void) | |||
882 | return -1; | 908 | return -1; |
883 | } | 909 | } |
884 | platform_driver_register(&ubd_driver); | 910 | platform_driver_register(&ubd_driver); |
885 | mutex_lock(&ubd_lock); | 911 | mutex_lock(&ubd_lock); |
886 | for (i = 0; i < MAX_DEV; i++){ | 912 | for (i = 0; i < MAX_DEV; i++){ |
887 | err = ubd_add(i, &error); | 913 | err = ubd_add(i, &error); |
888 | if(err) | 914 | if(err) |
889 | printk(KERN_ERR "Failed to initialize ubd device %d :" | 915 | printk(KERN_ERR "Failed to initialize ubd device %d :" |
890 | "%s\n", i, error); | 916 | "%s\n", i, error); |
891 | } | 917 | } |
892 | mutex_unlock(&ubd_lock); | 918 | mutex_unlock(&ubd_lock); |
893 | return 0; | 919 | return 0; |
894 | } | 920 | } |
895 | 921 | ||
@@ -913,7 +939,7 @@ static int __init ubd_driver_init(void){ | |||
913 | "ubd : Failed to start I/O thread (errno = %d) - " | 939 | "ubd : Failed to start I/O thread (errno = %d) - " |
914 | "falling back to synchronous I/O\n", -io_pid); | 940 | "falling back to synchronous I/O\n", -io_pid); |
915 | io_pid = -1; | 941 | io_pid = -1; |
916 | return(0); | 942 | return 0; |
917 | } | 943 | } |
918 | err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, | 944 | err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, |
919 | IRQF_DISABLED, "ubd", ubd_devs); | 945 | IRQF_DISABLED, "ubd", ubd_devs); |
@@ -948,7 +974,7 @@ static int ubd_open(struct inode *inode, struct file *filp) | |||
948 | err = -EROFS; | 974 | err = -EROFS; |
949 | }*/ | 975 | }*/ |
950 | out: | 976 | out: |
951 | return(err); | 977 | return err; |
952 | } | 978 | } |
953 | 979 | ||
954 | static int ubd_release(struct inode * inode, struct file * file) | 980 | static int ubd_release(struct inode * inode, struct file * file) |
@@ -958,7 +984,7 @@ static int ubd_release(struct inode * inode, struct file * file) | |||
958 | 984 | ||
959 | if(--ubd_dev->count == 0) | 985 | if(--ubd_dev->count == 0) |
960 | ubd_close_dev(ubd_dev); | 986 | ubd_close_dev(ubd_dev); |
961 | return(0); | 987 | return 0; |
962 | } | 988 | } |
963 | 989 | ||
964 | static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask, | 990 | static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask, |
@@ -1014,7 +1040,7 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap, | |||
1014 | if(ubd_test_bit(sector + i, (unsigned char *) bitmap)) | 1040 | if(ubd_test_bit(sector + i, (unsigned char *) bitmap)) |
1015 | ubd_set_bit(i, (unsigned char *) | 1041 | ubd_set_bit(i, (unsigned char *) |
1016 | &req->sector_mask); | 1042 | &req->sector_mask); |
1017 | } | 1043 | } |
1018 | } | 1044 | } |
1019 | else cowify_bitmap(req->offset, req->length, &req->sector_mask, | 1045 | else cowify_bitmap(req->offset, req->length, &req->sector_mask, |
1020 | &req->cow_offset, bitmap, bitmap_offset, | 1046 | &req->cow_offset, bitmap, bitmap_offset, |
@@ -1022,26 +1048,16 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap, | |||
1022 | } | 1048 | } |
1023 | 1049 | ||
1024 | /* Called with dev->lock held */ | 1050 | /* Called with dev->lock held */ |
1025 | static int prepare_request(struct request *req, struct io_thread_req *io_req) | 1051 | static void prepare_request(struct request *req, struct io_thread_req *io_req, |
1052 | unsigned long long offset, int page_offset, | ||
1053 | int len, struct page *page) | ||
1026 | { | 1054 | { |
1027 | struct gendisk *disk = req->rq_disk; | 1055 | struct gendisk *disk = req->rq_disk; |
1028 | struct ubd *ubd_dev = disk->private_data; | 1056 | struct ubd *ubd_dev = disk->private_data; |
1029 | __u64 offset; | ||
1030 | int len; | ||
1031 | |||
1032 | /* This should be impossible now */ | ||
1033 | if((rq_data_dir(req) == WRITE) && !ubd_dev->openflags.w){ | ||
1034 | printk("Write attempted on readonly ubd device %s\n", | ||
1035 | disk->disk_name); | ||
1036 | end_request(req, 0); | ||
1037 | return(1); | ||
1038 | } | ||
1039 | |||
1040 | offset = ((__u64) req->sector) << 9; | ||
1041 | len = req->current_nr_sectors << 9; | ||
1042 | 1057 | ||
1043 | io_req->req = req; | 1058 | io_req->req = req; |
1044 | io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd : ubd_dev->fd; | 1059 | io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd : |
1060 | ubd_dev->fd; | ||
1045 | io_req->fds[1] = ubd_dev->fd; | 1061 | io_req->fds[1] = ubd_dev->fd; |
1046 | io_req->cow_offset = -1; | 1062 | io_req->cow_offset = -1; |
1047 | io_req->offset = offset; | 1063 | io_req->offset = offset; |
@@ -1052,45 +1068,66 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) | |||
1052 | io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE; | 1068 | io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE; |
1053 | io_req->offsets[0] = 0; | 1069 | io_req->offsets[0] = 0; |
1054 | io_req->offsets[1] = ubd_dev->cow.data_offset; | 1070 | io_req->offsets[1] = ubd_dev->cow.data_offset; |
1055 | io_req->buffer = req->buffer; | 1071 | io_req->buffer = page_address(page) + page_offset; |
1056 | io_req->sectorsize = 1 << 9; | 1072 | io_req->sectorsize = 1 << 9; |
1057 | 1073 | ||
1058 | if(ubd_dev->cow.file != NULL) | 1074 | if(ubd_dev->cow.file != NULL) |
1059 | cowify_req(io_req, ubd_dev->cow.bitmap, ubd_dev->cow.bitmap_offset, | 1075 | cowify_req(io_req, ubd_dev->cow.bitmap, |
1060 | ubd_dev->cow.bitmap_len); | 1076 | ubd_dev->cow.bitmap_offset, ubd_dev->cow.bitmap_len); |
1061 | 1077 | ||
1062 | return(0); | ||
1063 | } | 1078 | } |
1064 | 1079 | ||
1065 | /* Called with dev->lock held */ | 1080 | /* Called with dev->lock held */ |
1066 | static void do_ubd_request(request_queue_t *q) | 1081 | static void do_ubd_request(request_queue_t *q) |
1067 | { | 1082 | { |
1068 | struct io_thread_req io_req; | 1083 | struct io_thread_req *io_req; |
1069 | struct request *req; | 1084 | struct request *req; |
1070 | int err, n; | 1085 | int n; |
1071 | 1086 | ||
1072 | if(thread_fd == -1){ | 1087 | while(1){ |
1073 | while((req = elv_next_request(q)) != NULL){ | ||
1074 | err = prepare_request(req, &io_req); | ||
1075 | if(!err){ | ||
1076 | do_io(&io_req); | ||
1077 | __ubd_finish(req, io_req.error); | ||
1078 | } | ||
1079 | } | ||
1080 | } | ||
1081 | else { | ||
1082 | struct ubd *dev = q->queuedata; | 1088 | struct ubd *dev = q->queuedata; |
1083 | if(dev->active || (req = elv_next_request(q)) == NULL) | 1089 | if(dev->end_sg == 0){ |
1084 | return; | 1090 | struct request *req = elv_next_request(q); |
1085 | err = prepare_request(req, &io_req); | 1091 | if(req == NULL) |
1086 | if(!err){ | 1092 | return; |
1087 | dev->active = 1; | 1093 | |
1088 | n = os_write_file(thread_fd, (char *) &io_req, | 1094 | dev->request = req; |
1089 | sizeof(io_req)); | 1095 | blkdev_dequeue_request(req); |
1090 | if(n != sizeof(io_req)) | 1096 | dev->start_sg = 0; |
1091 | printk("write to io thread failed, " | 1097 | dev->end_sg = blk_rq_map_sg(q, req, dev->sg); |
1092 | "errno = %d\n", -n); | ||
1093 | } | 1098 | } |
1099 | |||
1100 | req = dev->request; | ||
1101 | while(dev->start_sg < dev->end_sg){ | ||
1102 | struct scatterlist *sg = &dev->sg[dev->start_sg]; | ||
1103 | |||
1104 | io_req = kmalloc(sizeof(struct io_thread_req), | ||
1105 | GFP_ATOMIC); | ||
1106 | if(io_req == NULL){ | ||
1107 | if(list_empty(&dev->restart)) | ||
1108 | list_add(&dev->restart, &restart); | ||
1109 | return; | ||
1110 | } | ||
1111 | prepare_request(req, io_req, | ||
1112 | (unsigned long long) req->sector << 9, | ||
1113 | sg->offset, sg->length, sg->page); | ||
1114 | |||
1115 | n = os_write_file(thread_fd, &io_req, | ||
1116 | sizeof(struct io_thread_req *)); | ||
1117 | if(n != sizeof(struct io_thread_req *)){ | ||
1118 | if(n != -EAGAIN) | ||
1119 | printk("write to io thread failed, " | ||
1120 | "errno = %d\n", -n); | ||
1121 | else if(list_empty(&dev->restart)) | ||
1122 | list_add(&dev->restart, &restart); | ||
1123 | return; | ||
1124 | } | ||
1125 | |||
1126 | req->sector += sg->length >> 9; | ||
1127 | dev->start_sg++; | ||
1128 | } | ||
1129 | dev->end_sg = 0; | ||
1130 | dev->request = NULL; | ||
1094 | } | 1131 | } |
1095 | } | 1132 | } |
1096 | 1133 | ||
@@ -1120,21 +1157,21 @@ static int ubd_ioctl(struct inode * inode, struct file * file, | |||
1120 | ubd_id.cyls = ubd_dev->size / (128 * 32 * 512); | 1157 | ubd_id.cyls = ubd_dev->size / (128 * 32 * 512); |
1121 | if(copy_to_user((char __user *) arg, (char *) &ubd_id, | 1158 | if(copy_to_user((char __user *) arg, (char *) &ubd_id, |
1122 | sizeof(ubd_id))) | 1159 | sizeof(ubd_id))) |
1123 | return(-EFAULT); | 1160 | return -EFAULT; |
1124 | return(0); | 1161 | return 0; |
1125 | 1162 | ||
1126 | case CDROMVOLREAD: | 1163 | case CDROMVOLREAD: |
1127 | if(copy_from_user(&volume, (char __user *) arg, sizeof(volume))) | 1164 | if(copy_from_user(&volume, (char __user *) arg, sizeof(volume))) |
1128 | return(-EFAULT); | 1165 | return -EFAULT; |
1129 | volume.channel0 = 255; | 1166 | volume.channel0 = 255; |
1130 | volume.channel1 = 255; | 1167 | volume.channel1 = 255; |
1131 | volume.channel2 = 255; | 1168 | volume.channel2 = 255; |
1132 | volume.channel3 = 255; | 1169 | volume.channel3 = 255; |
1133 | if(copy_to_user((char __user *) arg, &volume, sizeof(volume))) | 1170 | if(copy_to_user((char __user *) arg, &volume, sizeof(volume))) |
1134 | return(-EFAULT); | 1171 | return -EFAULT; |
1135 | return(0); | 1172 | return 0; |
1136 | } | 1173 | } |
1137 | return(-EINVAL); | 1174 | return -EINVAL; |
1138 | } | 1175 | } |
1139 | 1176 | ||
1140 | static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow) | 1177 | static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow) |
@@ -1176,29 +1213,29 @@ static int backing_file_mismatch(char *file, __u64 size, time_t mtime) | |||
1176 | if(err < 0){ | 1213 | if(err < 0){ |
1177 | printk("Failed to get modification time of backing file " | 1214 | printk("Failed to get modification time of backing file " |
1178 | "\"%s\", err = %d\n", file, -err); | 1215 | "\"%s\", err = %d\n", file, -err); |
1179 | return(err); | 1216 | return err; |
1180 | } | 1217 | } |
1181 | 1218 | ||
1182 | err = os_file_size(file, &actual); | 1219 | err = os_file_size(file, &actual); |
1183 | if(err < 0){ | 1220 | if(err < 0){ |
1184 | printk("Failed to get size of backing file \"%s\", " | 1221 | printk("Failed to get size of backing file \"%s\", " |
1185 | "err = %d\n", file, -err); | 1222 | "err = %d\n", file, -err); |
1186 | return(err); | 1223 | return err; |
1187 | } | 1224 | } |
1188 | 1225 | ||
1189 | if(actual != size){ | 1226 | if(actual != size){ |
1190 | /*__u64 can be a long on AMD64 and with %lu GCC complains; so | 1227 | /*__u64 can be a long on AMD64 and with %lu GCC complains; so |
1191 | * the typecast.*/ | 1228 | * the typecast.*/ |
1192 | printk("Size mismatch (%llu vs %llu) of COW header vs backing " | 1229 | printk("Size mismatch (%llu vs %llu) of COW header vs backing " |
1193 | "file\n", (unsigned long long) size, actual); | 1230 | "file\n", (unsigned long long) size, actual); |
1194 | return(-EINVAL); | 1231 | return -EINVAL; |
1195 | } | 1232 | } |
1196 | if(modtime != mtime){ | 1233 | if(modtime != mtime){ |
1197 | printk("mtime mismatch (%ld vs %ld) of COW header vs backing " | 1234 | printk("mtime mismatch (%ld vs %ld) of COW header vs backing " |
1198 | "file\n", mtime, modtime); | 1235 | "file\n", mtime, modtime); |
1199 | return(-EINVAL); | 1236 | return -EINVAL; |
1200 | } | 1237 | } |
1201 | return(0); | 1238 | return 0; |
1202 | } | 1239 | } |
1203 | 1240 | ||
1204 | int read_cow_bitmap(int fd, void *buf, int offset, int len) | 1241 | int read_cow_bitmap(int fd, void *buf, int offset, int len) |
@@ -1207,13 +1244,13 @@ int read_cow_bitmap(int fd, void *buf, int offset, int len) | |||
1207 | 1244 | ||
1208 | err = os_seek_file(fd, offset); | 1245 | err = os_seek_file(fd, offset); |
1209 | if(err < 0) | 1246 | if(err < 0) |
1210 | return(err); | 1247 | return err; |
1211 | 1248 | ||
1212 | err = os_read_file(fd, buf, len); | 1249 | err = os_read_file(fd, buf, len); |
1213 | if(err < 0) | 1250 | if(err < 0) |
1214 | return(err); | 1251 | return err; |
1215 | 1252 | ||
1216 | return(0); | 1253 | return 0; |
1217 | } | 1254 | } |
1218 | 1255 | ||
1219 | int open_ubd_file(char *file, struct openflags *openflags, int shared, | 1256 | int open_ubd_file(char *file, struct openflags *openflags, int shared, |
@@ -1231,14 +1268,14 @@ int open_ubd_file(char *file, struct openflags *openflags, int shared, | |||
1231 | if (fd < 0) { | 1268 | if (fd < 0) { |
1232 | if ((fd == -ENOENT) && (create_cow_out != NULL)) | 1269 | if ((fd == -ENOENT) && (create_cow_out != NULL)) |
1233 | *create_cow_out = 1; | 1270 | *create_cow_out = 1; |
1234 | if (!openflags->w || | 1271 | if (!openflags->w || |
1235 | ((fd != -EROFS) && (fd != -EACCES))) | 1272 | ((fd != -EROFS) && (fd != -EACCES))) |
1236 | return fd; | 1273 | return fd; |
1237 | openflags->w = 0; | 1274 | openflags->w = 0; |
1238 | fd = os_open_file(file, *openflags, mode); | 1275 | fd = os_open_file(file, *openflags, mode); |
1239 | if (fd < 0) | 1276 | if (fd < 0) |
1240 | return fd; | 1277 | return fd; |
1241 | } | 1278 | } |
1242 | 1279 | ||
1243 | if(shared) | 1280 | if(shared) |
1244 | printk("Not locking \"%s\" on the host\n", file); | 1281 | printk("Not locking \"%s\" on the host\n", file); |
@@ -1252,7 +1289,7 @@ int open_ubd_file(char *file, struct openflags *openflags, int shared, | |||
1252 | 1289 | ||
1253 | /* Successful return case! */ | 1290 | /* Successful return case! */ |
1254 | if(backing_file_out == NULL) | 1291 | if(backing_file_out == NULL) |
1255 | return(fd); | 1292 | return fd; |
1256 | 1293 | ||
1257 | err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime, | 1294 | err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime, |
1258 | &size, §orsize, &align, bitmap_offset_out); | 1295 | &size, §orsize, &align, bitmap_offset_out); |
@@ -1262,7 +1299,7 @@ int open_ubd_file(char *file, struct openflags *openflags, int shared, | |||
1262 | goto out_close; | 1299 | goto out_close; |
1263 | } | 1300 | } |
1264 | if(err) | 1301 | if(err) |
1265 | return(fd); | 1302 | return fd; |
1266 | 1303 | ||
1267 | asked_switch = path_requires_switch(*backing_file_out, backing_file, file); | 1304 | asked_switch = path_requires_switch(*backing_file_out, backing_file, file); |
1268 | 1305 | ||
@@ -1285,7 +1322,7 @@ int open_ubd_file(char *file, struct openflags *openflags, int shared, | |||
1285 | cow_sizes(version, size, sectorsize, align, *bitmap_offset_out, | 1322 | cow_sizes(version, size, sectorsize, align, *bitmap_offset_out, |
1286 | bitmap_len_out, data_offset_out); | 1323 | bitmap_len_out, data_offset_out); |
1287 | 1324 | ||
1288 | return fd; | 1325 | return fd; |
1289 | out_close: | 1326 | out_close: |
1290 | os_close_file(fd); | 1327 | os_close_file(fd); |
1291 | return err; | 1328 | return err; |
@@ -1310,10 +1347,10 @@ int create_cow_file(char *cow_file, char *backing_file, struct openflags flags, | |||
1310 | bitmap_offset_out, bitmap_len_out, | 1347 | bitmap_offset_out, bitmap_len_out, |
1311 | data_offset_out); | 1348 | data_offset_out); |
1312 | if(!err) | 1349 | if(!err) |
1313 | return(fd); | 1350 | return fd; |
1314 | os_close_file(fd); | 1351 | os_close_file(fd); |
1315 | out: | 1352 | out: |
1316 | return(err); | 1353 | return err; |
1317 | } | 1354 | } |
1318 | 1355 | ||
1319 | static int update_bitmap(struct io_thread_req *req) | 1356 | static int update_bitmap(struct io_thread_req *req) |
@@ -1321,23 +1358,23 @@ static int update_bitmap(struct io_thread_req *req) | |||
1321 | int n; | 1358 | int n; |
1322 | 1359 | ||
1323 | if(req->cow_offset == -1) | 1360 | if(req->cow_offset == -1) |
1324 | return(0); | 1361 | return 0; |
1325 | 1362 | ||
1326 | n = os_seek_file(req->fds[1], req->cow_offset); | 1363 | n = os_seek_file(req->fds[1], req->cow_offset); |
1327 | if(n < 0){ | 1364 | if(n < 0){ |
1328 | printk("do_io - bitmap lseek failed : err = %d\n", -n); | 1365 | printk("do_io - bitmap lseek failed : err = %d\n", -n); |
1329 | return(1); | 1366 | return 1; |
1330 | } | 1367 | } |
1331 | 1368 | ||
1332 | n = os_write_file(req->fds[1], &req->bitmap_words, | 1369 | n = os_write_file(req->fds[1], &req->bitmap_words, |
1333 | sizeof(req->bitmap_words)); | 1370 | sizeof(req->bitmap_words)); |
1334 | if(n != sizeof(req->bitmap_words)){ | 1371 | if(n != sizeof(req->bitmap_words)){ |
1335 | printk("do_io - bitmap update failed, err = %d fd = %d\n", -n, | 1372 | printk("do_io - bitmap update failed, err = %d fd = %d\n", -n, |
1336 | req->fds[1]); | 1373 | req->fds[1]); |
1337 | return(1); | 1374 | return 1; |
1338 | } | 1375 | } |
1339 | 1376 | ||
1340 | return(0); | 1377 | return 0; |
1341 | } | 1378 | } |
1342 | 1379 | ||
1343 | void do_io(struct io_thread_req *req) | 1380 | void do_io(struct io_thread_req *req) |
@@ -1409,13 +1446,14 @@ static int io_count = 0; | |||
1409 | 1446 | ||
1410 | int io_thread(void *arg) | 1447 | int io_thread(void *arg) |
1411 | { | 1448 | { |
1412 | struct io_thread_req req; | 1449 | struct io_thread_req *req; |
1413 | int n; | 1450 | int n; |
1414 | 1451 | ||
1415 | ignore_sigwinch_sig(); | 1452 | ignore_sigwinch_sig(); |
1416 | while(1){ | 1453 | while(1){ |
1417 | n = os_read_file(kernel_fd, &req, sizeof(req)); | 1454 | n = os_read_file(kernel_fd, &req, |
1418 | if(n != sizeof(req)){ | 1455 | sizeof(struct io_thread_req *)); |
1456 | if(n != sizeof(struct io_thread_req *)){ | ||
1419 | if(n < 0) | 1457 | if(n < 0) |
1420 | printk("io_thread - read failed, fd = %d, " | 1458 | printk("io_thread - read failed, fd = %d, " |
1421 | "err = %d\n", kernel_fd, -n); | 1459 | "err = %d\n", kernel_fd, -n); |
@@ -1426,9 +1464,10 @@ int io_thread(void *arg) | |||
1426 | continue; | 1464 | continue; |
1427 | } | 1465 | } |
1428 | io_count++; | 1466 | io_count++; |
1429 | do_io(&req); | 1467 | do_io(req); |
1430 | n = os_write_file(kernel_fd, &req, sizeof(req)); | 1468 | n = os_write_file(kernel_fd, &req, |
1431 | if(n != sizeof(req)) | 1469 | sizeof(struct io_thread_req *)); |
1470 | if(n != sizeof(struct io_thread_req *)) | ||
1432 | printk("io_thread - write failed, fd = %d, err = %d\n", | 1471 | printk("io_thread - write failed, fd = %d, err = %d\n", |
1433 | kernel_fd, -n); | 1472 | kernel_fd, -n); |
1434 | } | 1473 | } |
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c index b94d2bc4fe06..4707b3f14c2f 100644 --- a/arch/um/drivers/ubd_user.c +++ b/arch/um/drivers/ubd_user.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <sys/mman.h> | 16 | #include <sys/mman.h> |
17 | #include <sys/param.h> | 17 | #include <sys/param.h> |
18 | #include "asm/types.h" | 18 | #include "asm/types.h" |
19 | #include "user_util.h" | ||
20 | #include "kern_util.h" | 19 | #include "kern_util.h" |
21 | #include "user.h" | 20 | #include "user.h" |
22 | #include "ubd_user.h" | 21 | #include "ubd_user.h" |
@@ -47,8 +46,8 @@ int start_io_thread(unsigned long sp, int *fd_out) | |||
47 | pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD, | 46 | pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD, |
48 | NULL); | 47 | NULL); |
49 | if(pid < 0){ | 48 | if(pid < 0){ |
50 | printk("start_io_thread - clone failed : errno = %d\n", errno); | ||
51 | err = -errno; | 49 | err = -errno; |
50 | printk("start_io_thread - clone failed : errno = %d\n", errno); | ||
52 | goto out_close; | 51 | goto out_close; |
53 | } | 52 | } |
54 | 53 | ||
@@ -60,16 +59,5 @@ int start_io_thread(unsigned long sp, int *fd_out) | |||
60 | kernel_fd = -1; | 59 | kernel_fd = -1; |
61 | *fd_out = -1; | 60 | *fd_out = -1; |
62 | out: | 61 | out: |
63 | return(err); | 62 | return err; |
64 | } | 63 | } |
65 | |||
66 | /* | ||
67 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
68 | * Emacs will notice this stuff at the end of the file and automatically | ||
69 | * adjust the settings for this buffer only. This must remain at the end | ||
70 | * of the file. | ||
71 | * --------------------------------------------------------------------------- | ||
72 | * Local variables: | ||
73 | * c-file-style: "linux" | ||
74 | * End: | ||
75 | */ | ||
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index 850221d9b4c9..571c2b3325d5 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <sys/socket.h> | 14 | #include <sys/socket.h> |
15 | #include "kern_util.h" | 15 | #include "kern_util.h" |
16 | #include "chan_user.h" | 16 | #include "chan_user.h" |
17 | #include "user_util.h" | ||
18 | #include "user.h" | 17 | #include "user.h" |
19 | #include "os.h" | 18 | #include "os.h" |
20 | #include "xterm.h" | 19 | #include "xterm.h" |
diff --git a/arch/um/include/arch.h b/arch/um/include/arch.h new file mode 100644 index 000000000000..10ad52daa8c5 --- /dev/null +++ b/arch/um/include/arch.h | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __ARCH_H__ | ||
7 | #define __ARCH_H__ | ||
8 | |||
9 | #include "sysdep/ptrace.h" | ||
10 | |||
11 | extern void arch_check_bugs(void); | ||
12 | extern int arch_fixup(unsigned long address, union uml_pt_regs *regs); | ||
13 | extern int arch_handle_signal(int sig, union uml_pt_regs *regs); | ||
14 | |||
15 | #endif | ||
diff --git a/arch/um/include/as-layout.h b/arch/um/include/as-layout.h new file mode 100644 index 000000000000..fccf187bf4e1 --- /dev/null +++ b/arch/um/include/as-layout.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __START_H__ | ||
7 | #define __START_H__ | ||
8 | |||
9 | #include "sysdep/ptrace.h" | ||
10 | |||
11 | struct cpu_task { | ||
12 | int pid; | ||
13 | void *task; | ||
14 | }; | ||
15 | |||
16 | extern struct cpu_task cpu_tasks[]; | ||
17 | |||
18 | extern unsigned long low_physmem; | ||
19 | extern unsigned long high_physmem; | ||
20 | extern unsigned long uml_physmem; | ||
21 | extern unsigned long uml_reserved; | ||
22 | extern unsigned long end_vm; | ||
23 | extern unsigned long start_vm; | ||
24 | extern unsigned long long highmem; | ||
25 | |||
26 | extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end; | ||
27 | extern unsigned long _unprotected_end; | ||
28 | extern unsigned long brk_start; | ||
29 | |||
30 | extern int linux_main(int argc, char **argv); | ||
31 | extern void set_cmdline(char *cmd); | ||
32 | |||
33 | extern void (*sig_info[])(int, union uml_pt_regs *); | ||
34 | |||
35 | #endif | ||
diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h index 461175f8b1d9..5593a8027083 100644 --- a/arch/um/include/common-offsets.h +++ b/arch/um/include/common-offsets.h | |||
@@ -24,5 +24,7 @@ DEFINE(UM_ELF_CLASS, ELF_CLASS); | |||
24 | DEFINE(UM_ELFCLASS32, ELFCLASS32); | 24 | DEFINE(UM_ELFCLASS32, ELFCLASS32); |
25 | DEFINE(UM_ELFCLASS64, ELFCLASS64); | 25 | DEFINE(UM_ELFCLASS64, ELFCLASS64); |
26 | 26 | ||
27 | DEFINE(UM_NR_CPUS, NR_CPUS); | ||
28 | |||
27 | /* For crypto assembler code. */ | 29 | /* For crypto assembler code. */ |
28 | DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx)); | 30 | DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx)); |
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h index 173af029d12b..50a49691e0e6 100644 --- a/arch/um/include/kern_util.h +++ b/arch/um/include/kern_util.h | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | #include "sysdep/ptrace.h" | 9 | #include "sysdep/ptrace.h" |
10 | #include "sysdep/faultinfo.h" | 10 | #include "sysdep/faultinfo.h" |
11 | #include "uml-config.h" | ||
11 | 12 | ||
12 | typedef void (*kern_hndl)(int, union uml_pt_regs *); | 13 | typedef void (*kern_hndl)(int, union uml_pt_regs *); |
13 | 14 | ||
@@ -23,7 +24,6 @@ struct kern_handlers { | |||
23 | extern const struct kern_handlers handlinfo_kern; | 24 | extern const struct kern_handlers handlinfo_kern; |
24 | 25 | ||
25 | extern int ncpus; | 26 | extern int ncpus; |
26 | extern char *linux_prog; | ||
27 | extern char *gdb_init; | 27 | extern char *gdb_init; |
28 | extern int kmalloc_ok; | 28 | extern int kmalloc_ok; |
29 | extern int jail; | 29 | extern int jail; |
@@ -34,7 +34,9 @@ extern int nsyscalls; | |||
34 | UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1) | 34 | UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1) |
35 | 35 | ||
36 | extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg); | 36 | extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg); |
37 | #ifdef UML_CONFIG_MODE_TT | ||
37 | extern unsigned long stack_sp(unsigned long page); | 38 | extern unsigned long stack_sp(unsigned long page); |
39 | #endif | ||
38 | extern int kernel_thread_proc(void *data); | 40 | extern int kernel_thread_proc(void *data); |
39 | extern void syscall_segv(int sig); | 41 | extern void syscall_segv(int sig); |
40 | extern int current_pid(void); | 42 | extern int current_pid(void); |
@@ -42,7 +44,7 @@ extern unsigned long alloc_stack(int order, int atomic); | |||
42 | extern int do_signal(void); | 44 | extern int do_signal(void); |
43 | extern int is_stack_fault(unsigned long sp); | 45 | extern int is_stack_fault(unsigned long sp); |
44 | extern unsigned long segv(struct faultinfo fi, unsigned long ip, | 46 | extern unsigned long segv(struct faultinfo fi, unsigned long ip, |
45 | int is_user, void *sc); | 47 | int is_user, union uml_pt_regs *regs); |
46 | extern int handle_page_fault(unsigned long address, unsigned long ip, | 48 | extern int handle_page_fault(unsigned long address, unsigned long ip, |
47 | int is_write, int is_user, int *code_out); | 49 | int is_write, int is_user, int *code_out); |
48 | extern void syscall_ready(void); | 50 | extern void syscall_ready(void); |
@@ -50,7 +52,6 @@ extern void set_tracing(void *t, int tracing); | |||
50 | extern int is_tracing(void *task); | 52 | extern int is_tracing(void *task); |
51 | extern int segv_syscall(void); | 53 | extern int segv_syscall(void); |
52 | extern void kern_finish_exec(void *task, int new_pid, unsigned long stack); | 54 | extern void kern_finish_exec(void *task, int new_pid, unsigned long stack); |
53 | extern int page_size(void); | ||
54 | extern unsigned long page_mask(void); | 55 | extern unsigned long page_mask(void); |
55 | extern int need_finish_fork(void); | 56 | extern int need_finish_fork(void); |
56 | extern void free_stack(unsigned long stack, int order); | 57 | extern void free_stack(unsigned long stack, int order); |
@@ -58,7 +59,6 @@ extern void add_input_request(int op, void (*proc)(int), void *arg); | |||
58 | extern char *current_cmd(void); | 59 | extern char *current_cmd(void); |
59 | extern void timer_handler(int sig, union uml_pt_regs *regs); | 60 | extern void timer_handler(int sig, union uml_pt_regs *regs); |
60 | extern int set_signals(int enable); | 61 | extern int set_signals(int enable); |
61 | extern void force_sigbus(void); | ||
62 | extern int pid_to_processor_id(int pid); | 62 | extern int pid_to_processor_id(int pid); |
63 | extern void deliver_signals(void *t); | 63 | extern void deliver_signals(void *t); |
64 | extern int next_trap_index(int max); | 64 | extern int next_trap_index(int max); |
@@ -70,7 +70,6 @@ extern void *syscall_sp(void *t); | |||
70 | extern void syscall_trace(union uml_pt_regs *regs, int entryexit); | 70 | extern void syscall_trace(union uml_pt_regs *regs, int entryexit); |
71 | extern int hz(void); | 71 | extern int hz(void); |
72 | extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs); | 72 | extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs); |
73 | extern int external_pid(void *t); | ||
74 | extern void interrupt_end(void); | 73 | extern void interrupt_end(void); |
75 | extern void initial_thread_cb(void (*proc)(void *), void *arg); | 74 | extern void initial_thread_cb(void (*proc)(void *), void *arg); |
76 | extern int debugger_signal(int status, int pid); | 75 | extern int debugger_signal(int status, int pid); |
@@ -81,7 +80,6 @@ extern int init_parent_proxy(int pid); | |||
81 | extern int singlestepping(void *t); | 80 | extern int singlestepping(void *t); |
82 | extern void check_stack_overflow(void *ptr); | 81 | extern void check_stack_overflow(void *ptr); |
83 | extern void relay_signal(int sig, union uml_pt_regs *regs); | 82 | extern void relay_signal(int sig, union uml_pt_regs *regs); |
84 | extern void not_implemented(void); | ||
85 | extern int user_context(unsigned long sp); | 83 | extern int user_context(unsigned long sp); |
86 | extern void timer_irq(union uml_pt_regs *regs); | 84 | extern void timer_irq(union uml_pt_regs *regs); |
87 | extern void unprotect_stack(unsigned long stack); | 85 | extern void unprotect_stack(unsigned long stack); |
@@ -93,7 +91,6 @@ extern char *uml_strdup(char *string); | |||
93 | extern void unprotect_kernel_mem(void); | 91 | extern void unprotect_kernel_mem(void); |
94 | extern void protect_kernel_mem(void); | 92 | extern void protect_kernel_mem(void); |
95 | extern void uml_cleanup(void); | 93 | extern void uml_cleanup(void); |
96 | extern void set_current(void *t); | ||
97 | extern void lock_signalled_task(void *t); | 94 | extern void lock_signalled_task(void *t); |
98 | extern void IPI_handler(int cpu); | 95 | extern void IPI_handler(int cpu); |
99 | extern int jail_setup(char *line, int *add); | 96 | extern int jail_setup(char *line, int *add); |
@@ -118,4 +115,6 @@ extern void time_init_kern(void); | |||
118 | extern int __cant_sleep(void); | 115 | extern int __cant_sleep(void); |
119 | extern void sigio_handler(int sig, union uml_pt_regs *regs); | 116 | extern void sigio_handler(int sig, union uml_pt_regs *regs); |
120 | 117 | ||
118 | extern void copy_sc(union uml_pt_regs *regs, void *from); | ||
119 | |||
121 | #endif | 120 | #endif |
diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h index 125ab42df18a..9237056b9103 100644 --- a/arch/um/include/net_kern.h +++ b/arch/um/include/net_kern.h | |||
@@ -40,7 +40,7 @@ struct uml_net_private { | |||
40 | void (*add_address)(unsigned char *, unsigned char *, void *); | 40 | void (*add_address)(unsigned char *, unsigned char *, void *); |
41 | void (*delete_address)(unsigned char *, unsigned char *, void *); | 41 | void (*delete_address)(unsigned char *, unsigned char *, void *); |
42 | int (*set_mtu)(int mtu, void *); | 42 | int (*set_mtu)(int mtu, void *); |
43 | int user[1]; | 43 | char user[0]; |
44 | }; | 44 | }; |
45 | 45 | ||
46 | struct net_kern_info { | 46 | struct net_kern_info { |
diff --git a/arch/um/include/net_user.h b/arch/um/include/net_user.h index 19f207cd70fe..cfe7c50634b9 100644 --- a/arch/um/include/net_user.h +++ b/arch/um/include/net_user.h | |||
@@ -14,7 +14,7 @@ | |||
14 | #define UML_NET_VERSION (4) | 14 | #define UML_NET_VERSION (4) |
15 | 15 | ||
16 | struct net_user_info { | 16 | struct net_user_info { |
17 | void (*init)(void *, void *); | 17 | int (*init)(void *, void *); |
18 | int (*open)(void *); | 18 | int (*open)(void *); |
19 | void (*close)(int, void *); | 19 | void (*close)(int, void *); |
20 | void (*remove)(void *); | 20 | void (*remove)(void *); |
diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 5c74da410451..688d181b5f8a 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h | |||
@@ -16,6 +16,8 @@ | |||
16 | #include "sysdep/tls.h" | 16 | #include "sysdep/tls.h" |
17 | #include "sysdep/archsetjmp.h" | 17 | #include "sysdep/archsetjmp.h" |
18 | 18 | ||
19 | #define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR)) | ||
20 | |||
19 | #define OS_TYPE_FILE 1 | 21 | #define OS_TYPE_FILE 1 |
20 | #define OS_TYPE_DIR 2 | 22 | #define OS_TYPE_DIR 2 |
21 | #define OS_TYPE_SYMLINK 3 | 23 | #define OS_TYPE_SYMLINK 3 |
@@ -273,8 +275,9 @@ extern void stack_protections(unsigned long address); | |||
273 | extern void task_protections(unsigned long address); | 275 | extern void task_protections(unsigned long address); |
274 | extern int raw(int fd); | 276 | extern int raw(int fd); |
275 | extern void setup_machinename(char *machine_out); | 277 | extern void setup_machinename(char *machine_out); |
276 | extern void setup_hostinfo(void); | 278 | extern void setup_hostinfo(char *buf, int len); |
277 | extern int setjmp_wrapper(void (*proc)(void *, void *), ...); | 279 | extern int setjmp_wrapper(void (*proc)(void *, void *), ...); |
280 | extern void os_dump_core(void); | ||
278 | 281 | ||
279 | /* time.c */ | 282 | /* time.c */ |
280 | #define BILLION (1000 * 1000 * 1000) | 283 | #define BILLION (1000 * 1000 * 1000) |
@@ -297,13 +300,12 @@ extern long syscall_stub_data(struct mm_id * mm_idp, | |||
297 | unsigned long *data, int data_count, | 300 | unsigned long *data, int data_count, |
298 | void **addr, void **stub_addr); | 301 | void **addr, void **stub_addr); |
299 | extern int map(struct mm_id * mm_idp, unsigned long virt, | 302 | extern int map(struct mm_id * mm_idp, unsigned long virt, |
300 | unsigned long len, int r, int w, int x, int phys_fd, | 303 | unsigned long len, int prot, int phys_fd, |
301 | unsigned long long offset, int done, void **data); | 304 | unsigned long long offset, int done, void **data); |
302 | extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, | 305 | extern int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len, |
303 | int done, void **data); | 306 | int done, void **data); |
304 | extern int protect(struct mm_id * mm_idp, unsigned long addr, | 307 | extern int protect(struct mm_id * mm_idp, unsigned long addr, |
305 | unsigned long len, int r, int w, int x, int done, | 308 | unsigned long len, unsigned int prot, int done, void **data); |
306 | void **data); | ||
307 | 309 | ||
308 | /* skas/process.c */ | 310 | /* skas/process.c */ |
309 | extern int is_skas_winch(int pid, int fd, void *data); | 311 | extern int is_skas_winch(int pid, int fd, void *data); |
@@ -339,8 +341,11 @@ extern void maybe_sigio_broken(int fd, int read); | |||
339 | 341 | ||
340 | /* skas/trap */ | 342 | /* skas/trap */ |
341 | extern void sig_handler_common_skas(int sig, void *sc_ptr); | 343 | extern void sig_handler_common_skas(int sig, void *sc_ptr); |
342 | extern void user_signal(int sig, union uml_pt_regs *regs, int pid); | ||
343 | 344 | ||
345 | /* sys-x86_64/prctl.c */ | ||
344 | extern int os_arch_prctl(int pid, int code, unsigned long *addr); | 346 | extern int os_arch_prctl(int pid, int code, unsigned long *addr); |
345 | 347 | ||
348 | /* tty.c */ | ||
349 | int get_pty(void); | ||
350 | |||
346 | #endif | 351 | #endif |
diff --git a/arch/um/include/skas/mode_kern_skas.h b/arch/um/include/skas/mode_kern_skas.h index 9cd9c6ec9a63..8ee6285dfacc 100644 --- a/arch/um/include/skas/mode_kern_skas.h +++ b/arch/um/include/skas/mode_kern_skas.h | |||
@@ -33,6 +33,8 @@ extern unsigned long set_task_sizes_skas(unsigned long *task_size_out); | |||
33 | extern int start_uml_skas(void); | 33 | extern int start_uml_skas(void); |
34 | extern int external_pid_skas(struct task_struct *task); | 34 | extern int external_pid_skas(struct task_struct *task); |
35 | extern int thread_pid_skas(struct task_struct *task); | 35 | extern int thread_pid_skas(struct task_struct *task); |
36 | extern void flush_tlb_page_skas(struct vm_area_struct *vma, | ||
37 | unsigned long address); | ||
36 | 38 | ||
37 | #define kmem_end_skas (host_task_size - 1024 * 1024) | 39 | #define kmem_end_skas (host_task_size - 1024 * 1024) |
38 | 40 | ||
diff --git a/arch/um/include/tlb.h b/arch/um/include/tlb.h index 8efc1e0f1b84..bcd1a4afb842 100644 --- a/arch/um/include/tlb.h +++ b/arch/um/include/tlb.h | |||
@@ -14,9 +14,7 @@ struct host_vm_op { | |||
14 | struct { | 14 | struct { |
15 | unsigned long addr; | 15 | unsigned long addr; |
16 | unsigned long len; | 16 | unsigned long len; |
17 | unsigned int r:1; | 17 | unsigned int prot; |
18 | unsigned int w:1; | ||
19 | unsigned int x:1; | ||
20 | int fd; | 18 | int fd; |
21 | __u64 offset; | 19 | __u64 offset; |
22 | } mmap; | 20 | } mmap; |
@@ -27,9 +25,7 @@ struct host_vm_op { | |||
27 | struct { | 25 | struct { |
28 | unsigned long addr; | 26 | unsigned long addr; |
29 | unsigned long len; | 27 | unsigned long len; |
30 | unsigned int r:1; | 28 | unsigned int prot; |
31 | unsigned int w:1; | ||
32 | unsigned int x:1; | ||
33 | } mprotect; | 29 | } mprotect; |
34 | } u; | 30 | } u; |
35 | }; | 31 | }; |
diff --git a/arch/um/include/tt/uaccess-tt.h b/arch/um/include/tt/uaccess-tt.h index b19645f32f24..13a64f61fcf4 100644 --- a/arch/um/include/tt/uaccess-tt.h +++ b/arch/um/include/tt/uaccess-tt.h | |||
@@ -27,8 +27,6 @@ extern unsigned long uml_physmem; | |||
27 | #define access_ok_tt(type, addr, size) \ | 27 | #define access_ok_tt(type, addr, size) \ |
28 | (is_stack(addr, size)) | 28 | (is_stack(addr, size)) |
29 | 29 | ||
30 | extern unsigned long get_fault_addr(void); | ||
31 | |||
32 | extern int __do_copy_from_user(void *to, const void *from, int n, | 30 | extern int __do_copy_from_user(void *to, const void *from, int n, |
33 | void **fault_addr, void **fault_catcher); | 31 | void **fault_addr, void **fault_catcher); |
34 | extern int __do_strncpy_from_user(char *dst, const char *src, size_t n, | 32 | extern int __do_strncpy_from_user(char *dst, const char *src, size_t n, |
diff --git a/arch/um/include/um_malloc.h b/arch/um/include/um_malloc.h index 0363a9b53f8d..e6d7c5aa3f4e 100644 --- a/arch/um/include/um_malloc.h +++ b/arch/um/include/um_malloc.h | |||
@@ -11,7 +11,6 @@ extern void *um_kmalloc_atomic(int size); | |||
11 | extern void kfree(const void *ptr); | 11 | extern void kfree(const void *ptr); |
12 | 12 | ||
13 | extern void *um_vmalloc(int size); | 13 | extern void *um_vmalloc(int size); |
14 | extern void *um_vmalloc_atomic(int size); | ||
15 | extern void vfree(void *ptr); | 14 | extern void vfree(void *ptr); |
16 | 15 | ||
17 | #endif /* __UM_MALLOC_H__ */ | 16 | #endif /* __UM_MALLOC_H__ */ |
diff --git a/arch/um/include/user.h b/arch/um/include/user.h index acadce3f271f..d380e6d91a90 100644 --- a/arch/um/include/user.h +++ b/arch/um/include/user.h | |||
@@ -6,6 +6,19 @@ | |||
6 | #ifndef __USER_H__ | 6 | #ifndef __USER_H__ |
7 | #define __USER_H__ | 7 | #define __USER_H__ |
8 | 8 | ||
9 | /* | ||
10 | * The usual definition - copied here because the kernel provides its own, | ||
11 | * fancier, type-safe, definition. Using that one would require | ||
12 | * copying too much infrastructure for my taste, so userspace files | ||
13 | * get less checking than kernel files. | ||
14 | */ | ||
15 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) | ||
16 | |||
17 | /* | ||
18 | * This will provide the size_t definition in both kernel and userspace builds | ||
19 | */ | ||
20 | #include <linux/types.h> | ||
21 | |||
9 | extern void panic(const char *fmt, ...) | 22 | extern void panic(const char *fmt, ...) |
10 | __attribute__ ((format (printf, 1, 2))); | 23 | __attribute__ ((format (printf, 1, 2))); |
11 | extern int printk(const char *fmt, ...) | 24 | extern int printk(const char *fmt, ...) |
@@ -13,19 +26,7 @@ extern int printk(const char *fmt, ...) | |||
13 | extern void schedule(void); | 26 | extern void schedule(void); |
14 | extern int in_aton(char *str); | 27 | extern int in_aton(char *str); |
15 | extern int open_gdb_chan(void); | 28 | extern int open_gdb_chan(void); |
16 | /* These use size_t, however unsigned long is correct on both i386 and x86_64. */ | 29 | extern size_t strlcpy(char *, const char *, size_t); |
17 | extern unsigned long strlcpy(char *, const char *, unsigned long); | 30 | extern size_t strlcat(char *, const char *, size_t); |
18 | extern unsigned long strlcat(char *, const char *, unsigned long); | ||
19 | 31 | ||
20 | #endif | 32 | #endif |
21 | |||
22 | /* | ||
23 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
24 | * Emacs will notice this stuff at the end of the file and automatically | ||
25 | * adjust the settings for this buffer only. This must remain at the end | ||
26 | * of the file. | ||
27 | * --------------------------------------------------------------------------- | ||
28 | * Local variables: | ||
29 | * c-file-style: "linux" | ||
30 | * End: | ||
31 | */ | ||
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h deleted file mode 100644 index 023575f67343..000000000000 --- a/arch/um/include/user_util.h +++ /dev/null | |||
@@ -1,69 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __USER_UTIL_H__ | ||
7 | #define __USER_UTIL_H__ | ||
8 | |||
9 | #include "sysdep/ptrace.h" | ||
10 | |||
11 | /* Copied from kernel.h */ | ||
12 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) | ||
13 | |||
14 | #define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR)) | ||
15 | |||
16 | extern int mode_tt; | ||
17 | |||
18 | extern int grantpt(int __fd); | ||
19 | extern int unlockpt(int __fd); | ||
20 | extern char *ptsname(int __fd); | ||
21 | |||
22 | struct cpu_task { | ||
23 | int pid; | ||
24 | void *task; | ||
25 | }; | ||
26 | |||
27 | extern struct cpu_task cpu_tasks[]; | ||
28 | |||
29 | extern void (*sig_info[])(int, union uml_pt_regs *); | ||
30 | |||
31 | extern unsigned long low_physmem; | ||
32 | extern unsigned long high_physmem; | ||
33 | extern unsigned long uml_physmem; | ||
34 | extern unsigned long uml_reserved; | ||
35 | extern unsigned long end_vm; | ||
36 | extern unsigned long start_vm; | ||
37 | extern unsigned long long highmem; | ||
38 | |||
39 | extern char host_info[]; | ||
40 | |||
41 | extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end; | ||
42 | extern unsigned long _unprotected_end; | ||
43 | extern unsigned long brk_start; | ||
44 | |||
45 | extern int pty_output_sigio; | ||
46 | extern int pty_close_sigio; | ||
47 | |||
48 | extern void *add_signal_handler(int sig, void (*handler)(int)); | ||
49 | extern int linux_main(int argc, char **argv); | ||
50 | extern void set_cmdline(char *cmd); | ||
51 | extern void input_cb(void (*proc)(void *), void *arg, int arg_len); | ||
52 | extern int get_pty(void); | ||
53 | extern int switcheroo(int fd, int prot, void *from, void *to, int size); | ||
54 | extern void do_exec(int old_pid, int new_pid); | ||
55 | extern void tracer_panic(char *msg, ...) | ||
56 | __attribute__ ((format (printf, 1, 2))); | ||
57 | extern int detach(int pid, int sig); | ||
58 | extern int attach(int pid); | ||
59 | extern void kill_child_dead(int pid); | ||
60 | extern int cont(int pid); | ||
61 | extern void check_sigio(void); | ||
62 | extern void arch_check_bugs(void); | ||
63 | extern int cpu_feature(char *what, char *buf, int len); | ||
64 | extern int arch_handle_signal(int sig, union uml_pt_regs *regs); | ||
65 | extern int arch_fixup(unsigned long address, void *sc_ptr); | ||
66 | extern void arch_init_thread(void); | ||
67 | extern int raw(int fd); | ||
68 | |||
69 | #endif | ||
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index 121166400e25..356e50f5aaed 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c | |||
@@ -10,8 +10,8 @@ | |||
10 | #include "asm/pgtable.h" | 10 | #include "asm/pgtable.h" |
11 | #include "asm/tlbflush.h" | 11 | #include "asm/tlbflush.h" |
12 | #include "asm/uaccess.h" | 12 | #include "asm/uaccess.h" |
13 | #include "user_util.h" | ||
14 | #include "kern_util.h" | 13 | #include "kern_util.h" |
14 | #include "as-layout.h" | ||
15 | #include "mem_user.h" | 15 | #include "mem_user.h" |
16 | #include "kern.h" | 16 | #include "kern.h" |
17 | #include "irq_user.h" | 17 | #include "irq_user.h" |
diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c index 8cde431348cc..cda91aa8e703 100644 --- a/arch/um/kernel/init_task.c +++ b/arch/um/kernel/init_task.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include "linux/mqueue.h" | 10 | #include "linux/mqueue.h" |
11 | #include "asm/uaccess.h" | 11 | #include "asm/uaccess.h" |
12 | #include "asm/pgtable.h" | 12 | #include "asm/pgtable.h" |
13 | #include "user_util.h" | ||
14 | #include "mem_user.h" | 13 | #include "mem_user.h" |
15 | #include "os.h" | 14 | #include "os.h" |
16 | 15 | ||
diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c index 82ecf904b09c..16dc43e9d940 100644 --- a/arch/um/kernel/initrd.c +++ b/arch/um/kernel/initrd.c | |||
@@ -7,7 +7,6 @@ | |||
7 | #include "linux/bootmem.h" | 7 | #include "linux/bootmem.h" |
8 | #include "linux/initrd.h" | 8 | #include "linux/initrd.h" |
9 | #include "asm/types.h" | 9 | #include "asm/types.h" |
10 | #include "user_util.h" | ||
11 | #include "kern_util.h" | 10 | #include "kern_util.h" |
12 | #include "initrd.h" | 11 | #include "initrd.h" |
13 | #include "init.h" | 12 | #include "init.h" |
@@ -22,12 +21,20 @@ static int __init read_initrd(void) | |||
22 | long long size; | 21 | long long size; |
23 | int err; | 22 | int err; |
24 | 23 | ||
25 | if(initrd == NULL) return 0; | 24 | if(initrd == NULL) |
25 | return 0; | ||
26 | |||
26 | err = os_file_size(initrd, &size); | 27 | err = os_file_size(initrd, &size); |
27 | if(err) return 0; | 28 | if(err) |
29 | return 0; | ||
30 | |||
28 | area = alloc_bootmem(size); | 31 | area = alloc_bootmem(size); |
29 | if(area == NULL) return 0; | 32 | if(area == NULL) |
30 | if(load_initrd(initrd, area, size) == -1) return 0; | 33 | return 0; |
34 | |||
35 | if(load_initrd(initrd, area, size) == -1) | ||
36 | return 0; | ||
37 | |||
31 | initrd_start = (unsigned long) area; | 38 | initrd_start = (unsigned long) area; |
32 | initrd_end = initrd_start + size; | 39 | initrd_end = initrd_start + size; |
33 | return 0; | 40 | return 0; |
@@ -54,25 +61,15 @@ int load_initrd(char *filename, void *buf, int size) | |||
54 | fd = os_open_file(filename, of_read(OPENFLAGS()), 0); | 61 | fd = os_open_file(filename, of_read(OPENFLAGS()), 0); |
55 | if(fd < 0){ | 62 | if(fd < 0){ |
56 | printk("Opening '%s' failed - err = %d\n", filename, -fd); | 63 | printk("Opening '%s' failed - err = %d\n", filename, -fd); |
57 | return(-1); | 64 | return -1; |
58 | } | 65 | } |
59 | n = os_read_file(fd, buf, size); | 66 | n = os_read_file(fd, buf, size); |
60 | if(n != size){ | 67 | if(n != size){ |
61 | printk("Read of %d bytes from '%s' failed, err = %d\n", size, | 68 | printk("Read of %d bytes from '%s' failed, err = %d\n", size, |
62 | filename, -n); | 69 | filename, -n); |
63 | return(-1); | 70 | return -1; |
64 | } | 71 | } |
65 | 72 | ||
66 | os_close_file(fd); | 73 | os_close_file(fd); |
67 | return(0); | 74 | return 0; |
68 | } | 75 | } |
69 | /* | ||
70 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
71 | * Emacs will notice this stuff at the end of the file and automatically | ||
72 | * adjust the settings for this buffer only. This must remain at the end | ||
73 | * of the file. | ||
74 | * --------------------------------------------------------------------------- | ||
75 | * Local variables: | ||
76 | * c-file-style: "linux" | ||
77 | * End: | ||
78 | */ | ||
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index dbf2f5bc842f..8f2ed3690315 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include "asm/system.h" | 25 | #include "asm/system.h" |
26 | #include "asm/errno.h" | 26 | #include "asm/errno.h" |
27 | #include "asm/uaccess.h" | 27 | #include "asm/uaccess.h" |
28 | #include "user_util.h" | ||
29 | #include "kern_util.h" | 28 | #include "kern_util.h" |
30 | #include "irq_user.h" | 29 | #include "irq_user.h" |
31 | #include "irq_kern.h" | 30 | #include "irq_kern.h" |
@@ -79,6 +78,14 @@ skip: | |||
79 | return 0; | 78 | return 0; |
80 | } | 79 | } |
81 | 80 | ||
81 | /* | ||
82 | * This list is accessed under irq_lock, except in sigio_handler, | ||
83 | * where it is safe from being modified. IRQ handlers won't change it - | ||
84 | * if an IRQ source has vanished, it will be freed by free_irqs just | ||
85 | * before returning from sigio_handler. That will process a separate | ||
86 | * list of irqs to free, with its own locking, coming back here to | ||
87 | * remove list elements, taking the irq_lock to do so. | ||
88 | */ | ||
82 | static struct irq_fd *active_fds = NULL; | 89 | static struct irq_fd *active_fds = NULL; |
83 | static struct irq_fd **last_irq_ptr = &active_fds; | 90 | static struct irq_fd **last_irq_ptr = &active_fds; |
84 | 91 | ||
@@ -244,6 +251,7 @@ void free_irq_by_fd(int fd) | |||
244 | free_irq_by_cb(same_fd, &fd); | 251 | free_irq_by_cb(same_fd, &fd); |
245 | } | 252 | } |
246 | 253 | ||
254 | /* Must be called with irq_lock held */ | ||
247 | static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out) | 255 | static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out) |
248 | { | 256 | { |
249 | struct irq_fd *irq; | 257 | struct irq_fd *irq; |
@@ -309,6 +317,12 @@ void deactivate_fd(int fd, int irqnum) | |||
309 | ignore_sigio_fd(fd); | 317 | ignore_sigio_fd(fd); |
310 | } | 318 | } |
311 | 319 | ||
320 | /* | ||
321 | * Called just before shutdown in order to provide a clean exec | ||
322 | * environment in case the system is rebooting. No locking because | ||
323 | * that would cause a pointless shutdown hang if something hadn't | ||
324 | * released the lock. | ||
325 | */ | ||
312 | int deactivate_all_fds(void) | 326 | int deactivate_all_fds(void) |
313 | { | 327 | { |
314 | struct irq_fd *irq; | 328 | struct irq_fd *irq; |
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c index 0e00cf93f900..7b3e53fb8070 100644 --- a/arch/um/kernel/ksyms.c +++ b/arch/um/kernel/ksyms.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include "asm/page.h" | 16 | #include "asm/page.h" |
17 | #include "asm/tlbflush.h" | 17 | #include "asm/tlbflush.h" |
18 | #include "kern_util.h" | 18 | #include "kern_util.h" |
19 | #include "user_util.h" | 19 | #include "as-layout.h" |
20 | #include "mem_user.h" | 20 | #include "mem_user.h" |
21 | #include "os.h" | 21 | #include "os.h" |
22 | 22 | ||
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index df7d662b98ce..72ff85693a39 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c | |||
@@ -13,8 +13,8 @@ | |||
13 | #include "asm/page.h" | 13 | #include "asm/page.h" |
14 | #include "asm/fixmap.h" | 14 | #include "asm/fixmap.h" |
15 | #include "asm/pgalloc.h" | 15 | #include "asm/pgalloc.h" |
16 | #include "user_util.h" | ||
17 | #include "kern_util.h" | 16 | #include "kern_util.h" |
17 | #include "as-layout.h" | ||
18 | #include "kern.h" | 18 | #include "kern.h" |
19 | #include "mem_user.h" | 19 | #include "mem_user.h" |
20 | #include "uml_uaccess.h" | 20 | #include "uml_uaccess.h" |
@@ -216,7 +216,7 @@ static void __init fixaddr_user_init( void) | |||
216 | #endif | 216 | #endif |
217 | } | 217 | } |
218 | 218 | ||
219 | void paging_init(void) | 219 | void __init paging_init(void) |
220 | { | 220 | { |
221 | unsigned long zones_size[MAX_NR_ZONES], vaddr; | 221 | unsigned long zones_size[MAX_NR_ZONES], vaddr; |
222 | int i; | 222 | int i; |
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index 638f3b5f6094..3ba6e4c841da 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include "asm/types.h" | 13 | #include "asm/types.h" |
14 | #include "asm/pgtable.h" | 14 | #include "asm/pgtable.h" |
15 | #include "kern_util.h" | 15 | #include "kern_util.h" |
16 | #include "user_util.h" | 16 | #include "as-layout.h" |
17 | #include "mode_kern.h" | 17 | #include "mode_kern.h" |
18 | #include "mem.h" | 18 | #include "mem.h" |
19 | #include "mem_user.h" | 19 | #include "mem_user.h" |
@@ -21,229 +21,8 @@ | |||
21 | #include "kern.h" | 21 | #include "kern.h" |
22 | #include "init.h" | 22 | #include "init.h" |
23 | 23 | ||
24 | struct phys_desc { | ||
25 | struct rb_node rb; | ||
26 | int fd; | ||
27 | __u64 offset; | ||
28 | void *virt; | ||
29 | unsigned long phys; | ||
30 | struct list_head list; | ||
31 | }; | ||
32 | |||
33 | static struct rb_root phys_mappings = RB_ROOT; | ||
34 | |||
35 | static struct rb_node **find_rb(void *virt) | ||
36 | { | ||
37 | struct rb_node **n = &phys_mappings.rb_node; | ||
38 | struct phys_desc *d; | ||
39 | |||
40 | while(*n != NULL){ | ||
41 | d = rb_entry(*n, struct phys_desc, rb); | ||
42 | if(d->virt == virt) | ||
43 | return n; | ||
44 | |||
45 | if(d->virt > virt) | ||
46 | n = &(*n)->rb_left; | ||
47 | else | ||
48 | n = &(*n)->rb_right; | ||
49 | } | ||
50 | |||
51 | return n; | ||
52 | } | ||
53 | |||
54 | static struct phys_desc *find_phys_mapping(void *virt) | ||
55 | { | ||
56 | struct rb_node **n = find_rb(virt); | ||
57 | |||
58 | if(*n == NULL) | ||
59 | return NULL; | ||
60 | |||
61 | return rb_entry(*n, struct phys_desc, rb); | ||
62 | } | ||
63 | |||
64 | static void insert_phys_mapping(struct phys_desc *desc) | ||
65 | { | ||
66 | struct rb_node **n = find_rb(desc->virt); | ||
67 | |||
68 | if(*n != NULL) | ||
69 | panic("Physical remapping for %p already present", | ||
70 | desc->virt); | ||
71 | |||
72 | rb_link_node(&desc->rb, rb_parent(*n), n); | ||
73 | rb_insert_color(&desc->rb, &phys_mappings); | ||
74 | } | ||
75 | |||
76 | LIST_HEAD(descriptor_mappings); | ||
77 | |||
78 | struct desc_mapping { | ||
79 | int fd; | ||
80 | struct list_head list; | ||
81 | struct list_head pages; | ||
82 | }; | ||
83 | |||
84 | static struct desc_mapping *find_mapping(int fd) | ||
85 | { | ||
86 | struct desc_mapping *desc; | ||
87 | struct list_head *ele; | ||
88 | |||
89 | list_for_each(ele, &descriptor_mappings){ | ||
90 | desc = list_entry(ele, struct desc_mapping, list); | ||
91 | if(desc->fd == fd) | ||
92 | return desc; | ||
93 | } | ||
94 | |||
95 | return NULL; | ||
96 | } | ||
97 | |||
98 | static struct desc_mapping *descriptor_mapping(int fd) | ||
99 | { | ||
100 | struct desc_mapping *desc; | ||
101 | |||
102 | desc = find_mapping(fd); | ||
103 | if(desc != NULL) | ||
104 | return desc; | ||
105 | |||
106 | desc = kmalloc(sizeof(*desc), GFP_ATOMIC); | ||
107 | if(desc == NULL) | ||
108 | return NULL; | ||
109 | |||
110 | *desc = ((struct desc_mapping) | ||
111 | { .fd = fd, | ||
112 | .list = LIST_HEAD_INIT(desc->list), | ||
113 | .pages = LIST_HEAD_INIT(desc->pages) }); | ||
114 | list_add(&desc->list, &descriptor_mappings); | ||
115 | |||
116 | return desc; | ||
117 | } | ||
118 | |||
119 | int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w) | ||
120 | { | ||
121 | struct desc_mapping *fd_maps; | ||
122 | struct phys_desc *desc; | ||
123 | unsigned long phys; | ||
124 | int err; | ||
125 | |||
126 | fd_maps = descriptor_mapping(fd); | ||
127 | if(fd_maps == NULL) | ||
128 | return -ENOMEM; | ||
129 | |||
130 | phys = __pa(virt); | ||
131 | desc = find_phys_mapping(virt); | ||
132 | if(desc != NULL) | ||
133 | panic("Address 0x%p is already substituted\n", virt); | ||
134 | |||
135 | err = -ENOMEM; | ||
136 | desc = kmalloc(sizeof(*desc), GFP_ATOMIC); | ||
137 | if(desc == NULL) | ||
138 | goto out; | ||
139 | |||
140 | *desc = ((struct phys_desc) | ||
141 | { .fd = fd, | ||
142 | .offset = offset, | ||
143 | .virt = virt, | ||
144 | .phys = __pa(virt), | ||
145 | .list = LIST_HEAD_INIT(desc->list) }); | ||
146 | insert_phys_mapping(desc); | ||
147 | |||
148 | list_add(&desc->list, &fd_maps->pages); | ||
149 | |||
150 | virt = (void *) ((unsigned long) virt & PAGE_MASK); | ||
151 | err = os_map_memory(virt, fd, offset, PAGE_SIZE, 1, w, 0); | ||
152 | if(!err) | ||
153 | goto out; | ||
154 | |||
155 | rb_erase(&desc->rb, &phys_mappings); | ||
156 | kfree(desc); | ||
157 | out: | ||
158 | return err; | ||
159 | } | ||
160 | |||
161 | static int physmem_fd = -1; | 24 | static int physmem_fd = -1; |
162 | 25 | ||
163 | static void remove_mapping(struct phys_desc *desc) | ||
164 | { | ||
165 | void *virt = desc->virt; | ||
166 | int err; | ||
167 | |||
168 | rb_erase(&desc->rb, &phys_mappings); | ||
169 | list_del(&desc->list); | ||
170 | kfree(desc); | ||
171 | |||
172 | err = os_map_memory(virt, physmem_fd, __pa(virt), PAGE_SIZE, 1, 1, 0); | ||
173 | if(err) | ||
174 | panic("Failed to unmap block device page from physical memory, " | ||
175 | "errno = %d", -err); | ||
176 | } | ||
177 | |||
178 | int physmem_remove_mapping(void *virt) | ||
179 | { | ||
180 | struct phys_desc *desc; | ||
181 | |||
182 | virt = (void *) ((unsigned long) virt & PAGE_MASK); | ||
183 | desc = find_phys_mapping(virt); | ||
184 | if(desc == NULL) | ||
185 | return 0; | ||
186 | |||
187 | remove_mapping(desc); | ||
188 | return 1; | ||
189 | } | ||
190 | |||
191 | void physmem_forget_descriptor(int fd) | ||
192 | { | ||
193 | struct desc_mapping *desc; | ||
194 | struct phys_desc *page; | ||
195 | struct list_head *ele, *next; | ||
196 | __u64 offset; | ||
197 | void *addr; | ||
198 | int err; | ||
199 | |||
200 | desc = find_mapping(fd); | ||
201 | if(desc == NULL) | ||
202 | return; | ||
203 | |||
204 | list_for_each_safe(ele, next, &desc->pages){ | ||
205 | page = list_entry(ele, struct phys_desc, list); | ||
206 | offset = page->offset; | ||
207 | addr = page->virt; | ||
208 | remove_mapping(page); | ||
209 | err = os_seek_file(fd, offset); | ||
210 | if(err) | ||
211 | panic("physmem_forget_descriptor - failed to seek " | ||
212 | "to %lld in fd %d, error = %d\n", | ||
213 | offset, fd, -err); | ||
214 | err = os_read_file(fd, addr, PAGE_SIZE); | ||
215 | if(err < 0) | ||
216 | panic("physmem_forget_descriptor - failed to read " | ||
217 | "from fd %d to 0x%p, error = %d\n", | ||
218 | fd, addr, -err); | ||
219 | } | ||
220 | |||
221 | list_del(&desc->list); | ||
222 | kfree(desc); | ||
223 | } | ||
224 | |||
225 | EXPORT_SYMBOL(physmem_forget_descriptor); | ||
226 | EXPORT_SYMBOL(physmem_remove_mapping); | ||
227 | EXPORT_SYMBOL(physmem_subst_mapping); | ||
228 | |||
229 | void arch_free_page(struct page *page, int order) | ||
230 | { | ||
231 | void *virt; | ||
232 | int i; | ||
233 | |||
234 | for(i = 0; i < (1 << order); i++){ | ||
235 | virt = __va(page_to_phys(page + i)); | ||
236 | physmem_remove_mapping(virt); | ||
237 | } | ||
238 | } | ||
239 | |||
240 | int is_remapped(void *virt) | ||
241 | { | ||
242 | struct phys_desc *desc = find_phys_mapping(virt); | ||
243 | |||
244 | return desc != NULL; | ||
245 | } | ||
246 | |||
247 | /* Changed during early boot */ | 26 | /* Changed during early boot */ |
248 | unsigned long high_physmem; | 27 | unsigned long high_physmem; |
249 | 28 | ||
@@ -350,14 +129,9 @@ void setup_physmem(unsigned long start, unsigned long reserve_end, | |||
350 | 129 | ||
351 | int phys_mapping(unsigned long phys, __u64 *offset_out) | 130 | int phys_mapping(unsigned long phys, __u64 *offset_out) |
352 | { | 131 | { |
353 | struct phys_desc *desc = find_phys_mapping(__va(phys & PAGE_MASK)); | ||
354 | int fd = -1; | 132 | int fd = -1; |
355 | 133 | ||
356 | if(desc != NULL){ | 134 | if(phys < physmem_size){ |
357 | fd = desc->fd; | ||
358 | *offset_out = desc->offset; | ||
359 | } | ||
360 | else if(phys < physmem_size){ | ||
361 | fd = physmem_fd; | 135 | fd = physmem_fd; |
362 | *offset_out = phys; | 136 | *offset_out = phys; |
363 | } | 137 | } |
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 348b272bb766..8d2c5496532b 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c | |||
@@ -32,8 +32,8 @@ | |||
32 | #include "asm/tlbflush.h" | 32 | #include "asm/tlbflush.h" |
33 | #include "asm/uaccess.h" | 33 | #include "asm/uaccess.h" |
34 | #include "asm/user.h" | 34 | #include "asm/user.h" |
35 | #include "user_util.h" | ||
36 | #include "kern_util.h" | 35 | #include "kern_util.h" |
36 | #include "as-layout.h" | ||
37 | #include "kern.h" | 37 | #include "kern.h" |
38 | #include "signal_kern.h" | 38 | #include "signal_kern.h" |
39 | #include "init.h" | 39 | #include "init.h" |
@@ -54,11 +54,9 @@ | |||
54 | */ | 54 | */ |
55 | struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; | 55 | struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; |
56 | 56 | ||
57 | int external_pid(void *t) | 57 | static inline int external_pid(struct task_struct *task) |
58 | { | 58 | { |
59 | struct task_struct *task = t ? t : current; | 59 | return CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task); |
60 | |||
61 | return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task)); | ||
62 | } | 60 | } |
63 | 61 | ||
64 | int pid_to_processor_id(int pid) | 62 | int pid_to_processor_id(int pid) |
@@ -66,9 +64,10 @@ int pid_to_processor_id(int pid) | |||
66 | int i; | 64 | int i; |
67 | 65 | ||
68 | for(i = 0; i < ncpus; i++){ | 66 | for(i = 0; i < ncpus; i++){ |
69 | if(cpu_tasks[i].pid == pid) return(i); | 67 | if(cpu_tasks[i].pid == pid) |
68 | return i; | ||
70 | } | 69 | } |
71 | return(-1); | 70 | return -1; |
72 | } | 71 | } |
73 | 72 | ||
74 | void free_stack(unsigned long stack, int order) | 73 | void free_stack(unsigned long stack, int order) |
@@ -85,9 +84,9 @@ unsigned long alloc_stack(int order, int atomic) | |||
85 | flags = GFP_ATOMIC; | 84 | flags = GFP_ATOMIC; |
86 | page = __get_free_pages(flags, order); | 85 | page = __get_free_pages(flags, order); |
87 | if(page == 0) | 86 | if(page == 0) |
88 | return(0); | 87 | return 0; |
89 | stack_protections(page); | 88 | stack_protections(page); |
90 | return(page); | 89 | return page; |
91 | } | 90 | } |
92 | 91 | ||
93 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | 92 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) |
@@ -98,15 +97,11 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |||
98 | current->thread.request.u.thread.arg = arg; | 97 | current->thread.request.u.thread.arg = arg; |
99 | pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, | 98 | pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, |
100 | ¤t->thread.regs, 0, NULL, NULL); | 99 | ¤t->thread.regs, 0, NULL, NULL); |
101 | if(pid < 0) | 100 | return pid; |
102 | panic("do_fork failed in kernel_thread, errno = %d", pid); | ||
103 | return(pid); | ||
104 | } | 101 | } |
105 | 102 | ||
106 | void set_current(void *t) | 103 | static inline void set_current(struct task_struct *task) |
107 | { | 104 | { |
108 | struct task_struct *task = t; | ||
109 | |||
110 | cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) | 105 | cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) |
111 | { external_pid(task), task }); | 106 | { external_pid(task), task }); |
112 | } | 107 | } |
@@ -128,14 +123,16 @@ void *_switch_to(void *prev, void *next, void *last) | |||
128 | prev= current; | 123 | prev= current; |
129 | } while(current->thread.saved_task); | 124 | } while(current->thread.saved_task); |
130 | 125 | ||
131 | return(current->thread.prev_sched); | 126 | return current->thread.prev_sched; |
132 | 127 | ||
133 | } | 128 | } |
134 | 129 | ||
135 | void interrupt_end(void) | 130 | void interrupt_end(void) |
136 | { | 131 | { |
137 | if(need_resched()) schedule(); | 132 | if(need_resched()) |
138 | if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal(); | 133 | schedule(); |
134 | if(test_tsk_thread_flag(current, TIF_SIGPENDING)) | ||
135 | do_signal(); | ||
139 | } | 136 | } |
140 | 137 | ||
141 | void release_thread(struct task_struct *task) | 138 | void release_thread(struct task_struct *task) |
@@ -150,7 +147,7 @@ void exit_thread(void) | |||
150 | 147 | ||
151 | void *get_current(void) | 148 | void *get_current(void) |
152 | { | 149 | { |
153 | return(current); | 150 | return current; |
154 | } | 151 | } |
155 | 152 | ||
156 | int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, | 153 | int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, |
@@ -188,15 +185,12 @@ void initial_thread_cb(void (*proc)(void *), void *arg) | |||
188 | kmalloc_ok = save_kmalloc_ok; | 185 | kmalloc_ok = save_kmalloc_ok; |
189 | } | 186 | } |
190 | 187 | ||
188 | #ifdef CONFIG_MODE_TT | ||
191 | unsigned long stack_sp(unsigned long page) | 189 | unsigned long stack_sp(unsigned long page) |
192 | { | 190 | { |
193 | return(page + PAGE_SIZE - sizeof(void *)); | 191 | return page + PAGE_SIZE - sizeof(void *); |
194 | } | ||
195 | |||
196 | int current_pid(void) | ||
197 | { | ||
198 | return(current->pid); | ||
199 | } | 192 | } |
193 | #endif | ||
200 | 194 | ||
201 | void default_idle(void) | 195 | void default_idle(void) |
202 | { | 196 | { |
@@ -221,11 +215,6 @@ void cpu_idle(void) | |||
221 | CHOOSE_MODE(init_idle_tt(), init_idle_skas()); | 215 | CHOOSE_MODE(init_idle_tt(), init_idle_skas()); |
222 | } | 216 | } |
223 | 217 | ||
224 | int page_size(void) | ||
225 | { | ||
226 | return(PAGE_SIZE); | ||
227 | } | ||
228 | |||
229 | void *um_virt_to_phys(struct task_struct *task, unsigned long addr, | 218 | void *um_virt_to_phys(struct task_struct *task, unsigned long addr, |
230 | pte_t *pte_out) | 219 | pte_t *pte_out) |
231 | { | 220 | { |
@@ -236,68 +225,43 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr, | |||
236 | pte_t ptent; | 225 | pte_t ptent; |
237 | 226 | ||
238 | if(task->mm == NULL) | 227 | if(task->mm == NULL) |
239 | return(ERR_PTR(-EINVAL)); | 228 | return ERR_PTR(-EINVAL); |
240 | pgd = pgd_offset(task->mm, addr); | 229 | pgd = pgd_offset(task->mm, addr); |
241 | if(!pgd_present(*pgd)) | 230 | if(!pgd_present(*pgd)) |
242 | return(ERR_PTR(-EINVAL)); | 231 | return ERR_PTR(-EINVAL); |
243 | 232 | ||
244 | pud = pud_offset(pgd, addr); | 233 | pud = pud_offset(pgd, addr); |
245 | if(!pud_present(*pud)) | 234 | if(!pud_present(*pud)) |
246 | return(ERR_PTR(-EINVAL)); | 235 | return ERR_PTR(-EINVAL); |
247 | 236 | ||
248 | pmd = pmd_offset(pud, addr); | 237 | pmd = pmd_offset(pud, addr); |
249 | if(!pmd_present(*pmd)) | 238 | if(!pmd_present(*pmd)) |
250 | return(ERR_PTR(-EINVAL)); | 239 | return ERR_PTR(-EINVAL); |
251 | 240 | ||
252 | pte = pte_offset_kernel(pmd, addr); | 241 | pte = pte_offset_kernel(pmd, addr); |
253 | ptent = *pte; | 242 | ptent = *pte; |
254 | if(!pte_present(ptent)) | 243 | if(!pte_present(ptent)) |
255 | return(ERR_PTR(-EINVAL)); | 244 | return ERR_PTR(-EINVAL); |
256 | 245 | ||
257 | if(pte_out != NULL) | 246 | if(pte_out != NULL) |
258 | *pte_out = ptent; | 247 | *pte_out = ptent; |
259 | return((void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK)); | 248 | return (void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK); |
260 | } | 249 | } |
261 | 250 | ||
262 | char *current_cmd(void) | 251 | char *current_cmd(void) |
263 | { | 252 | { |
264 | #if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM) | 253 | #if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM) |
265 | return("(Unknown)"); | 254 | return "(Unknown)"; |
266 | #else | 255 | #else |
267 | void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL); | 256 | void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL); |
268 | return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr); | 257 | return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr); |
269 | #endif | 258 | #endif |
270 | } | 259 | } |
271 | 260 | ||
272 | void force_sigbus(void) | ||
273 | { | ||
274 | printk(KERN_ERR "Killing pid %d because of a lack of memory\n", | ||
275 | current->pid); | ||
276 | lock_kernel(); | ||
277 | sigaddset(¤t->pending.signal, SIGBUS); | ||
278 | recalc_sigpending(); | ||
279 | current->flags |= PF_SIGNALED; | ||
280 | do_exit(SIGBUS | 0x80); | ||
281 | } | ||
282 | |||
283 | void dump_thread(struct pt_regs *regs, struct user *u) | 261 | void dump_thread(struct pt_regs *regs, struct user *u) |
284 | { | 262 | { |
285 | } | 263 | } |
286 | 264 | ||
287 | void enable_hlt(void) | ||
288 | { | ||
289 | panic("enable_hlt"); | ||
290 | } | ||
291 | |||
292 | EXPORT_SYMBOL(enable_hlt); | ||
293 | |||
294 | void disable_hlt(void) | ||
295 | { | ||
296 | panic("disable_hlt"); | ||
297 | } | ||
298 | |||
299 | EXPORT_SYMBOL(disable_hlt); | ||
300 | |||
301 | void *um_kmalloc(int size) | 265 | void *um_kmalloc(int size) |
302 | { | 266 | { |
303 | return kmalloc(size, GFP_KERNEL); | 267 | return kmalloc(size, GFP_KERNEL); |
@@ -313,36 +277,17 @@ void *um_vmalloc(int size) | |||
313 | return vmalloc(size); | 277 | return vmalloc(size); |
314 | } | 278 | } |
315 | 279 | ||
316 | void *um_vmalloc_atomic(int size) | ||
317 | { | ||
318 | return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL); | ||
319 | } | ||
320 | |||
321 | int __cant_sleep(void) { | 280 | int __cant_sleep(void) { |
322 | return in_atomic() || irqs_disabled() || in_interrupt(); | 281 | return in_atomic() || irqs_disabled() || in_interrupt(); |
323 | /* Is in_interrupt() really needed? */ | 282 | /* Is in_interrupt() really needed? */ |
324 | } | 283 | } |
325 | 284 | ||
326 | unsigned long get_fault_addr(void) | ||
327 | { | ||
328 | return((unsigned long) current->thread.fault_addr); | ||
329 | } | ||
330 | |||
331 | EXPORT_SYMBOL(get_fault_addr); | ||
332 | |||
333 | void not_implemented(void) | ||
334 | { | ||
335 | printk(KERN_DEBUG "Something isn't implemented in here\n"); | ||
336 | } | ||
337 | |||
338 | EXPORT_SYMBOL(not_implemented); | ||
339 | |||
340 | int user_context(unsigned long sp) | 285 | int user_context(unsigned long sp) |
341 | { | 286 | { |
342 | unsigned long stack; | 287 | unsigned long stack; |
343 | 288 | ||
344 | stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER); | 289 | stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER); |
345 | return(stack != (unsigned long) current_thread); | 290 | return stack != (unsigned long) current_thread; |
346 | } | 291 | } |
347 | 292 | ||
348 | extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; | 293 | extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; |
@@ -363,22 +308,22 @@ char *uml_strdup(char *string) | |||
363 | 308 | ||
364 | int copy_to_user_proc(void __user *to, void *from, int size) | 309 | int copy_to_user_proc(void __user *to, void *from, int size) |
365 | { | 310 | { |
366 | return(copy_to_user(to, from, size)); | 311 | return copy_to_user(to, from, size); |
367 | } | 312 | } |
368 | 313 | ||
369 | int copy_from_user_proc(void *to, void __user *from, int size) | 314 | int copy_from_user_proc(void *to, void __user *from, int size) |
370 | { | 315 | { |
371 | return(copy_from_user(to, from, size)); | 316 | return copy_from_user(to, from, size); |
372 | } | 317 | } |
373 | 318 | ||
374 | int clear_user_proc(void __user *buf, int size) | 319 | int clear_user_proc(void __user *buf, int size) |
375 | { | 320 | { |
376 | return(clear_user(buf, size)); | 321 | return clear_user(buf, size); |
377 | } | 322 | } |
378 | 323 | ||
379 | int strlen_user_proc(char __user *str) | 324 | int strlen_user_proc(char __user *str) |
380 | { | 325 | { |
381 | return(strlen_user(str)); | 326 | return strlen_user(str); |
382 | } | 327 | } |
383 | 328 | ||
384 | int smp_sigio_handler(void) | 329 | int smp_sigio_handler(void) |
@@ -387,14 +332,14 @@ int smp_sigio_handler(void) | |||
387 | int cpu = current_thread->cpu; | 332 | int cpu = current_thread->cpu; |
388 | IPI_handler(cpu); | 333 | IPI_handler(cpu); |
389 | if(cpu != 0) | 334 | if(cpu != 0) |
390 | return(1); | 335 | return 1; |
391 | #endif | 336 | #endif |
392 | return(0); | 337 | return 0; |
393 | } | 338 | } |
394 | 339 | ||
395 | int cpu(void) | 340 | int cpu(void) |
396 | { | 341 | { |
397 | return(current_thread->cpu); | 342 | return current_thread->cpu; |
398 | } | 343 | } |
399 | 344 | ||
400 | static atomic_t using_sysemu = ATOMIC_INIT(0); | 345 | static atomic_t using_sysemu = ATOMIC_INIT(0); |
@@ -443,7 +388,7 @@ int __init make_proc_sysemu(void) | |||
443 | if (ent == NULL) | 388 | if (ent == NULL) |
444 | { | 389 | { |
445 | printk(KERN_WARNING "Failed to register /proc/sysemu\n"); | 390 | printk(KERN_WARNING "Failed to register /proc/sysemu\n"); |
446 | return(0); | 391 | return 0; |
447 | } | 392 | } |
448 | 393 | ||
449 | ent->read_proc = proc_read_sysemu; | 394 | ent->read_proc = proc_read_sysemu; |
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index f602623644aa..7e4305a1fd3c 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c | |||
@@ -6,7 +6,6 @@ | |||
6 | #include "linux/module.h" | 6 | #include "linux/module.h" |
7 | #include "linux/sched.h" | 7 | #include "linux/sched.h" |
8 | #include "asm/smp.h" | 8 | #include "asm/smp.h" |
9 | #include "user_util.h" | ||
10 | #include "kern_util.h" | 9 | #include "kern_util.h" |
11 | #include "kern.h" | 10 | #include "kern.h" |
12 | #include "os.h" | 11 | #include "os.h" |
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c index 3c798cdde550..c4020c3d7857 100644 --- a/arch/um/kernel/signal.c +++ b/arch/um/kernel/signal.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include "asm/signal.h" | 17 | #include "asm/signal.h" |
18 | #include "asm/uaccess.h" | 18 | #include "asm/uaccess.h" |
19 | #include "asm/unistd.h" | 19 | #include "asm/unistd.h" |
20 | #include "user_util.h" | ||
21 | #include "asm/ucontext.h" | 20 | #include "asm/ucontext.h" |
22 | #include "kern_util.h" | 21 | #include "kern_util.h" |
23 | #include "signal_kern.h" | 22 | #include "signal_kern.h" |
diff --git a/arch/um/kernel/skas/exec.c b/arch/um/kernel/skas/exec.c index 54b795951372..580eb6468949 100644 --- a/arch/um/kernel/skas/exec.c +++ b/arch/um/kernel/skas/exec.c | |||
@@ -17,7 +17,17 @@ | |||
17 | 17 | ||
18 | void flush_thread_skas(void) | 18 | void flush_thread_skas(void) |
19 | { | 19 | { |
20 | force_flush_all(); | 20 | void *data = NULL; |
21 | unsigned long end = proc_mm ? task_size : CONFIG_STUB_START; | ||
22 | int ret; | ||
23 | |||
24 | ret = unmap(¤t->mm->context.skas.id, 0, end, 1, &data); | ||
25 | if(ret){ | ||
26 | printk("flush_thread_skas - clearing address space failed, " | ||
27 | "err = %d\n", ret); | ||
28 | force_sig(SIGKILL, current); | ||
29 | } | ||
30 | |||
21 | switch_mm_skas(¤t->mm->context.skas.id); | 31 | switch_mm_skas(¤t->mm->context.skas.id); |
22 | } | 32 | } |
23 | 33 | ||
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index ae4fa71d3b8b..ef36facd8fe9 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c | |||
@@ -13,9 +13,9 @@ | |||
13 | #include "asm/uaccess.h" | 13 | #include "asm/uaccess.h" |
14 | #include "asm/atomic.h" | 14 | #include "asm/atomic.h" |
15 | #include "kern_util.h" | 15 | #include "kern_util.h" |
16 | #include "as-layout.h" | ||
16 | #include "skas.h" | 17 | #include "skas.h" |
17 | #include "os.h" | 18 | #include "os.h" |
18 | #include "user_util.h" | ||
19 | #include "tlb.h" | 19 | #include "tlb.h" |
20 | #include "kern.h" | 20 | #include "kern.h" |
21 | #include "mode.h" | 21 | #include "mode.h" |
diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c index 27eb29ce666b..c0f0693743ba 100644 --- a/arch/um/kernel/skas/tlb.c +++ b/arch/um/kernel/skas/tlb.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include "asm/page.h" | 10 | #include "asm/page.h" |
11 | #include "asm/pgtable.h" | 11 | #include "asm/pgtable.h" |
12 | #include "asm/mmu.h" | 12 | #include "asm/mmu.h" |
13 | #include "user_util.h" | ||
14 | #include "mem_user.h" | 13 | #include "mem_user.h" |
15 | #include "mem.h" | 14 | #include "mem.h" |
16 | #include "skas.h" | 15 | #include "skas.h" |
@@ -28,19 +27,17 @@ static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last, | |||
28 | switch(op->type){ | 27 | switch(op->type){ |
29 | case MMAP: | 28 | case MMAP: |
30 | ret = map(&mmu->skas.id, op->u.mmap.addr, | 29 | ret = map(&mmu->skas.id, op->u.mmap.addr, |
31 | op->u.mmap.len, op->u.mmap.r, op->u.mmap.w, | 30 | op->u.mmap.len, op->u.mmap.prot, |
32 | op->u.mmap.x, op->u.mmap.fd, | 31 | op->u.mmap.fd, op->u.mmap.offset, finished, |
33 | op->u.mmap.offset, finished, flush); | 32 | flush); |
34 | break; | 33 | break; |
35 | case MUNMAP: | 34 | case MUNMAP: |
36 | ret = unmap(&mmu->skas.id, | 35 | ret = unmap(&mmu->skas.id, op->u.munmap.addr, |
37 | (void *) op->u.munmap.addr, | ||
38 | op->u.munmap.len, finished, flush); | 36 | op->u.munmap.len, finished, flush); |
39 | break; | 37 | break; |
40 | case MPROTECT: | 38 | case MPROTECT: |
41 | ret = protect(&mmu->skas.id, op->u.mprotect.addr, | 39 | ret = protect(&mmu->skas.id, op->u.mprotect.addr, |
42 | op->u.mprotect.len, op->u.mprotect.r, | 40 | op->u.mprotect.len, op->u.mprotect.prot, |
43 | op->u.mprotect.w, op->u.mprotect.x, | ||
44 | finished, flush); | 41 | finished, flush); |
45 | break; | 42 | break; |
46 | default: | 43 | default: |
@@ -92,6 +89,76 @@ void flush_tlb_mm_skas(struct mm_struct *mm) | |||
92 | 89 | ||
93 | void force_flush_all_skas(void) | 90 | void force_flush_all_skas(void) |
94 | { | 91 | { |
95 | unsigned long end = proc_mm ? task_size : CONFIG_STUB_START; | 92 | struct mm_struct *mm = current->mm; |
96 | fix_range(current->mm, 0, end, 1); | 93 | struct vm_area_struct *vma = mm->mmap; |
94 | |||
95 | while(vma != NULL) { | ||
96 | fix_range(mm, vma->vm_start, vma->vm_end, 1); | ||
97 | vma = vma->vm_next; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | void flush_tlb_page_skas(struct vm_area_struct *vma, unsigned long address) | ||
102 | { | ||
103 | pgd_t *pgd; | ||
104 | pud_t *pud; | ||
105 | pmd_t *pmd; | ||
106 | pte_t *pte; | ||
107 | struct mm_struct *mm = vma->vm_mm; | ||
108 | void *flush = NULL; | ||
109 | int r, w, x, prot, err = 0; | ||
110 | struct mm_id *mm_id; | ||
111 | |||
112 | pgd = pgd_offset(mm, address); | ||
113 | if(!pgd_present(*pgd)) | ||
114 | goto kill; | ||
115 | |||
116 | pud = pud_offset(pgd, address); | ||
117 | if(!pud_present(*pud)) | ||
118 | goto kill; | ||
119 | |||
120 | pmd = pmd_offset(pud, address); | ||
121 | if(!pmd_present(*pmd)) | ||
122 | goto kill; | ||
123 | |||
124 | pte = pte_offset_kernel(pmd, address); | ||
125 | |||
126 | r = pte_read(*pte); | ||
127 | w = pte_write(*pte); | ||
128 | x = pte_exec(*pte); | ||
129 | if (!pte_young(*pte)) { | ||
130 | r = 0; | ||
131 | w = 0; | ||
132 | } else if (!pte_dirty(*pte)) { | ||
133 | w = 0; | ||
134 | } | ||
135 | |||
136 | mm_id = &mm->context.skas.id; | ||
137 | prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | | ||
138 | (x ? UM_PROT_EXEC : 0)); | ||
139 | if(pte_newpage(*pte)){ | ||
140 | if(pte_present(*pte)){ | ||
141 | unsigned long long offset; | ||
142 | int fd; | ||
143 | |||
144 | fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset); | ||
145 | err = map(mm_id, address, PAGE_SIZE, prot, fd, offset, | ||
146 | 1, &flush); | ||
147 | } | ||
148 | else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush); | ||
149 | } | ||
150 | else if(pte_newprot(*pte)) | ||
151 | err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush); | ||
152 | |||
153 | if(err) | ||
154 | goto kill; | ||
155 | |||
156 | *pte = pte_mkuptodate(*pte); | ||
157 | |||
158 | return; | ||
159 | |||
160 | kill: | ||
161 | printk("Failed to flush page for address 0x%lx\n", address); | ||
162 | force_sig(SIGKILL, current); | ||
97 | } | 163 | } |
164 | |||
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c index 759b07053160..e6a7778006ad 100644 --- a/arch/um/kernel/smp.c +++ b/arch/um/kernel/smp.c | |||
@@ -21,7 +21,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | |||
21 | #include "asm/smp.h" | 21 | #include "asm/smp.h" |
22 | #include "asm/processor.h" | 22 | #include "asm/processor.h" |
23 | #include "asm/spinlock.h" | 23 | #include "asm/spinlock.h" |
24 | #include "user_util.h" | ||
25 | #include "kern_util.h" | 24 | #include "kern_util.h" |
26 | #include "kern.h" | 25 | #include "kern.h" |
27 | #include "irq_user.h" | 26 | #include "irq_user.h" |
@@ -90,7 +89,7 @@ static int idle_proc(void *cpup) | |||
90 | 89 | ||
91 | cpu_set(cpu, cpu_online_map); | 90 | cpu_set(cpu, cpu_online_map); |
92 | default_idle(); | 91 | default_idle(); |
93 | return(0); | 92 | return 0; |
94 | } | 93 | } |
95 | 94 | ||
96 | static struct task_struct *idle_thread(int cpu) | 95 | static struct task_struct *idle_thread(int cpu) |
@@ -98,8 +97,8 @@ static struct task_struct *idle_thread(int cpu) | |||
98 | struct task_struct *new_task; | 97 | struct task_struct *new_task; |
99 | unsigned char c; | 98 | unsigned char c; |
100 | 99 | ||
101 | current->thread.request.u.thread.proc = idle_proc; | 100 | current->thread.request.u.thread.proc = idle_proc; |
102 | current->thread.request.u.thread.arg = (void *) cpu; | 101 | current->thread.request.u.thread.arg = (void *) cpu; |
103 | new_task = fork_idle(cpu); | 102 | new_task = fork_idle(cpu); |
104 | if(IS_ERR(new_task)) | 103 | if(IS_ERR(new_task)) |
105 | panic("copy_process failed in idle_thread, error = %ld", | 104 | panic("copy_process failed in idle_thread, error = %ld", |
@@ -110,9 +109,9 @@ static struct task_struct *idle_thread(int cpu) | |||
110 | .task = new_task } ); | 109 | .task = new_task } ); |
111 | idle_threads[cpu] = new_task; | 110 | idle_threads[cpu] = new_task; |
112 | CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c, | 111 | CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c, |
113 | sizeof(c)), | 112 | sizeof(c)), |
114 | ({ panic("skas mode doesn't support SMP"); })); | 113 | ({ panic("skas mode doesn't support SMP"); })); |
115 | return(new_task); | 114 | return new_task; |
116 | } | 115 | } |
117 | 116 | ||
118 | void smp_prepare_cpus(unsigned int maxcpus) | 117 | void smp_prepare_cpus(unsigned int maxcpus) |
@@ -163,13 +162,13 @@ int __cpu_up(unsigned int cpu) | |||
163 | cpu_set(cpu, smp_commenced_mask); | 162 | cpu_set(cpu, smp_commenced_mask); |
164 | while (!cpu_isset(cpu, cpu_online_map)) | 163 | while (!cpu_isset(cpu, cpu_online_map)) |
165 | mb(); | 164 | mb(); |
166 | return(0); | 165 | return 0; |
167 | } | 166 | } |
168 | 167 | ||
169 | int setup_profiling_timer(unsigned int multiplier) | 168 | int setup_profiling_timer(unsigned int multiplier) |
170 | { | 169 | { |
171 | printk(KERN_INFO "setup_profiling_timer\n"); | 170 | printk(KERN_INFO "setup_profiling_timer\n"); |
172 | return(0); | 171 | return 0; |
173 | } | 172 | } |
174 | 173 | ||
175 | void smp_call_function_slave(int cpu); | 174 | void smp_call_function_slave(int cpu); |
@@ -205,7 +204,7 @@ void IPI_handler(int cpu) | |||
205 | 204 | ||
206 | int hard_smp_processor_id(void) | 205 | int hard_smp_processor_id(void) |
207 | { | 206 | { |
208 | return(pid_to_processor_id(os_getpid())); | 207 | return pid_to_processor_id(os_getpid()); |
209 | } | 208 | } |
210 | 209 | ||
211 | static DEFINE_SPINLOCK(call_lock); | 210 | static DEFINE_SPINLOCK(call_lock); |
@@ -254,14 +253,3 @@ int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic, | |||
254 | } | 253 | } |
255 | 254 | ||
256 | #endif | 255 | #endif |
257 | |||
258 | /* | ||
259 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
260 | * Emacs will notice this stuff at the end of the file and automatically | ||
261 | * adjust the settings for this buffer only. This must remain at the end | ||
262 | * of the file. | ||
263 | * --------------------------------------------------------------------------- | ||
264 | * Local variables: | ||
265 | * c-file-style: "linux" | ||
266 | * End: | ||
267 | */ | ||
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index 2828c5283227..237c4eab7cfd 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include "asm/mman.h" | 18 | #include "asm/mman.h" |
19 | #include "asm/uaccess.h" | 19 | #include "asm/uaccess.h" |
20 | #include "kern_util.h" | 20 | #include "kern_util.h" |
21 | #include "user_util.h" | ||
22 | #include "sysdep/syscalls.h" | 21 | #include "sysdep/syscalls.h" |
23 | #include "mode_kern.h" | 22 | #include "mode_kern.h" |
24 | #include "choose-mode.h" | 23 | #include "choose-mode.h" |
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c index f9e02b31a97a..93263571d813 100644 --- a/arch/um/kernel/sysrq.c +++ b/arch/um/kernel/sysrq.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include "asm/page.h" | 10 | #include "asm/page.h" |
11 | #include "asm/processor.h" | 11 | #include "asm/processor.h" |
12 | #include "sysrq.h" | 12 | #include "sysrq.h" |
13 | #include "user_util.h" | ||
14 | 13 | ||
15 | /* Catch non-i386 SUBARCH's. */ | 14 | /* Catch non-i386 SUBARCH's. */ |
16 | #if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT) | 15 | #if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT) |
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index b1f8b0752419..cd7349de8ca6 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include "asm/param.h" | 18 | #include "asm/param.h" |
19 | #include "asm/current.h" | 19 | #include "asm/current.h" |
20 | #include "kern_util.h" | 20 | #include "kern_util.h" |
21 | #include "user_util.h" | ||
22 | #include "mode.h" | 21 | #include "mode.h" |
23 | #include "os.h" | 22 | #include "os.h" |
24 | 23 | ||
@@ -35,8 +34,8 @@ unsigned long long sched_clock(void) | |||
35 | return (unsigned long long)jiffies_64 * (1000000000 / HZ); | 34 | return (unsigned long long)jiffies_64 * (1000000000 / HZ); |
36 | } | 35 | } |
37 | 36 | ||
38 | static unsigned long long prev_nsecs[NR_CPUS]; | ||
39 | #ifdef CONFIG_UML_REAL_TIME_CLOCK | 37 | #ifdef CONFIG_UML_REAL_TIME_CLOCK |
38 | static unsigned long long prev_nsecs[NR_CPUS]; | ||
40 | static long long delta[NR_CPUS]; /* Deviation per interval */ | 39 | static long long delta[NR_CPUS]; /* Deviation per interval */ |
41 | #endif | 40 | #endif |
42 | 41 | ||
@@ -95,7 +94,12 @@ irqreturn_t um_timer(int irq, void *dev) | |||
95 | 94 | ||
96 | do_timer(1); | 95 | do_timer(1); |
97 | 96 | ||
97 | #ifdef CONFIG_UML_REAL_TIME_CLOCK | ||
98 | nsecs = get_time(); | 98 | nsecs = get_time(); |
99 | #else | ||
100 | nsecs = (unsigned long long) xtime.tv_sec * BILLION + xtime.tv_nsec + | ||
101 | BILLION / HZ; | ||
102 | #endif | ||
99 | xtime.tv_sec = nsecs / NSEC_PER_SEC; | 103 | xtime.tv_sec = nsecs / NSEC_PER_SEC; |
100 | xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC; | 104 | xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC; |
101 | 105 | ||
@@ -128,13 +132,18 @@ void time_init(void) | |||
128 | nsecs = os_nsecs(); | 132 | nsecs = os_nsecs(); |
129 | set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION, | 133 | set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION, |
130 | -nsecs % BILLION); | 134 | -nsecs % BILLION); |
135 | set_normalized_timespec(&xtime, nsecs / BILLION, nsecs % BILLION); | ||
131 | late_time_init = register_timer; | 136 | late_time_init = register_timer; |
132 | } | 137 | } |
133 | 138 | ||
134 | void do_gettimeofday(struct timeval *tv) | 139 | void do_gettimeofday(struct timeval *tv) |
135 | { | 140 | { |
141 | #ifdef CONFIG_UML_REAL_TIME_CLOCK | ||
136 | unsigned long long nsecs = get_time(); | 142 | unsigned long long nsecs = get_time(); |
137 | 143 | #else | |
144 | unsigned long long nsecs = (unsigned long long) xtime.tv_sec * BILLION + | ||
145 | xtime.tv_nsec; | ||
146 | #endif | ||
138 | tv->tv_sec = nsecs / NSEC_PER_SEC; | 147 | tv->tv_sec = nsecs / NSEC_PER_SEC; |
139 | /* Careful about calculations here - this was originally done as | 148 | /* Careful about calculations here - this was originally done as |
140 | * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC | 149 | * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC |
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c index 54a5ff25645a..8a8d52851443 100644 --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c | |||
@@ -6,17 +6,18 @@ | |||
6 | #include "linux/mm.h" | 6 | #include "linux/mm.h" |
7 | #include "asm/page.h" | 7 | #include "asm/page.h" |
8 | #include "asm/pgalloc.h" | 8 | #include "asm/pgalloc.h" |
9 | #include "asm/pgtable.h" | ||
9 | #include "asm/tlbflush.h" | 10 | #include "asm/tlbflush.h" |
10 | #include "choose-mode.h" | 11 | #include "choose-mode.h" |
11 | #include "mode_kern.h" | 12 | #include "mode_kern.h" |
12 | #include "user_util.h" | 13 | #include "as-layout.h" |
13 | #include "tlb.h" | 14 | #include "tlb.h" |
14 | #include "mem.h" | 15 | #include "mem.h" |
15 | #include "mem_user.h" | 16 | #include "mem_user.h" |
16 | #include "os.h" | 17 | #include "os.h" |
17 | 18 | ||
18 | static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, | 19 | static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, |
19 | int r, int w, int x, struct host_vm_op *ops, int *index, | 20 | unsigned int prot, struct host_vm_op *ops, int *index, |
20 | int last_filled, union mm_context *mmu, void **flush, | 21 | int last_filled, union mm_context *mmu, void **flush, |
21 | int (*do_ops)(union mm_context *, struct host_vm_op *, | 22 | int (*do_ops)(union mm_context *, struct host_vm_op *, |
22 | int, int, void **)) | 23 | int, int, void **)) |
@@ -30,8 +31,7 @@ static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, | |||
30 | last = &ops[*index]; | 31 | last = &ops[*index]; |
31 | if((last->type == MMAP) && | 32 | if((last->type == MMAP) && |
32 | (last->u.mmap.addr + last->u.mmap.len == virt) && | 33 | (last->u.mmap.addr + last->u.mmap.len == virt) && |
33 | (last->u.mmap.r == r) && (last->u.mmap.w == w) && | 34 | (last->u.mmap.prot == prot) && (last->u.mmap.fd == fd) && |
34 | (last->u.mmap.x == x) && (last->u.mmap.fd == fd) && | ||
35 | (last->u.mmap.offset + last->u.mmap.len == offset)){ | 35 | (last->u.mmap.offset + last->u.mmap.len == offset)){ |
36 | last->u.mmap.len += len; | 36 | last->u.mmap.len += len; |
37 | return 0; | 37 | return 0; |
@@ -47,9 +47,7 @@ static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, | |||
47 | .u = { .mmap = { | 47 | .u = { .mmap = { |
48 | .addr = virt, | 48 | .addr = virt, |
49 | .len = len, | 49 | .len = len, |
50 | .r = r, | 50 | .prot = prot, |
51 | .w = w, | ||
52 | .x = x, | ||
53 | .fd = fd, | 51 | .fd = fd, |
54 | .offset = offset } | 52 | .offset = offset } |
55 | } }); | 53 | } }); |
@@ -86,8 +84,8 @@ static int add_munmap(unsigned long addr, unsigned long len, | |||
86 | return ret; | 84 | return ret; |
87 | } | 85 | } |
88 | 86 | ||
89 | static int add_mprotect(unsigned long addr, unsigned long len, int r, int w, | 87 | static int add_mprotect(unsigned long addr, unsigned long len, |
90 | int x, struct host_vm_op *ops, int *index, | 88 | unsigned int prot, struct host_vm_op *ops, int *index, |
91 | int last_filled, union mm_context *mmu, void **flush, | 89 | int last_filled, union mm_context *mmu, void **flush, |
92 | int (*do_ops)(union mm_context *, struct host_vm_op *, | 90 | int (*do_ops)(union mm_context *, struct host_vm_op *, |
93 | int, int, void **)) | 91 | int, int, void **)) |
@@ -99,8 +97,7 @@ static int add_mprotect(unsigned long addr, unsigned long len, int r, int w, | |||
99 | last = &ops[*index]; | 97 | last = &ops[*index]; |
100 | if((last->type == MPROTECT) && | 98 | if((last->type == MPROTECT) && |
101 | (last->u.mprotect.addr + last->u.mprotect.len == addr) && | 99 | (last->u.mprotect.addr + last->u.mprotect.len == addr) && |
102 | (last->u.mprotect.r == r) && (last->u.mprotect.w == w) && | 100 | (last->u.mprotect.prot == prot)){ |
103 | (last->u.mprotect.x == x)){ | ||
104 | last->u.mprotect.len += len; | 101 | last->u.mprotect.len += len; |
105 | return 0; | 102 | return 0; |
106 | } | 103 | } |
@@ -115,114 +112,145 @@ static int add_mprotect(unsigned long addr, unsigned long len, int r, int w, | |||
115 | .u = { .mprotect = { | 112 | .u = { .mprotect = { |
116 | .addr = addr, | 113 | .addr = addr, |
117 | .len = len, | 114 | .len = len, |
118 | .r = r, | 115 | .prot = prot } } }); |
119 | .w = w, | ||
120 | .x = x } } }); | ||
121 | return ret; | 116 | return ret; |
122 | } | 117 | } |
123 | 118 | ||
124 | #define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1)) | 119 | #define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1)) |
125 | 120 | ||
121 | static inline int update_pte_range(pmd_t *pmd, unsigned long addr, | ||
122 | unsigned long end, struct host_vm_op *ops, | ||
123 | int last_op, int *op_index, int force, | ||
124 | union mm_context *mmu, void **flush, | ||
125 | int (*do_ops)(union mm_context *, | ||
126 | struct host_vm_op *, int, int, | ||
127 | void **)) | ||
128 | { | ||
129 | pte_t *pte; | ||
130 | int r, w, x, prot, ret = 0; | ||
131 | |||
132 | pte = pte_offset_kernel(pmd, addr); | ||
133 | do { | ||
134 | r = pte_read(*pte); | ||
135 | w = pte_write(*pte); | ||
136 | x = pte_exec(*pte); | ||
137 | if (!pte_young(*pte)) { | ||
138 | r = 0; | ||
139 | w = 0; | ||
140 | } else if (!pte_dirty(*pte)) { | ||
141 | w = 0; | ||
142 | } | ||
143 | prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | | ||
144 | (x ? UM_PROT_EXEC : 0)); | ||
145 | if(force || pte_newpage(*pte)){ | ||
146 | if(pte_present(*pte)) | ||
147 | ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK, | ||
148 | PAGE_SIZE, prot, ops, op_index, | ||
149 | last_op, mmu, flush, do_ops); | ||
150 | else ret = add_munmap(addr, PAGE_SIZE, ops, op_index, | ||
151 | last_op, mmu, flush, do_ops); | ||
152 | } | ||
153 | else if(pte_newprot(*pte)) | ||
154 | ret = add_mprotect(addr, PAGE_SIZE, prot, ops, op_index, | ||
155 | last_op, mmu, flush, do_ops); | ||
156 | *pte = pte_mkuptodate(*pte); | ||
157 | } while (pte++, addr += PAGE_SIZE, ((addr != end) && !ret)); | ||
158 | return ret; | ||
159 | } | ||
160 | |||
161 | static inline int update_pmd_range(pud_t *pud, unsigned long addr, | ||
162 | unsigned long end, struct host_vm_op *ops, | ||
163 | int last_op, int *op_index, int force, | ||
164 | union mm_context *mmu, void **flush, | ||
165 | int (*do_ops)(union mm_context *, | ||
166 | struct host_vm_op *, int, int, | ||
167 | void **)) | ||
168 | { | ||
169 | pmd_t *pmd; | ||
170 | unsigned long next; | ||
171 | int ret = 0; | ||
172 | |||
173 | pmd = pmd_offset(pud, addr); | ||
174 | do { | ||
175 | next = pmd_addr_end(addr, end); | ||
176 | if(!pmd_present(*pmd)){ | ||
177 | if(force || pmd_newpage(*pmd)){ | ||
178 | ret = add_munmap(addr, next - addr, ops, | ||
179 | op_index, last_op, mmu, | ||
180 | flush, do_ops); | ||
181 | pmd_mkuptodate(*pmd); | ||
182 | } | ||
183 | } | ||
184 | else ret = update_pte_range(pmd, addr, next, ops, last_op, | ||
185 | op_index, force, mmu, flush, | ||
186 | do_ops); | ||
187 | } while (pmd++, addr = next, ((addr != end) && !ret)); | ||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | static inline int update_pud_range(pgd_t *pgd, unsigned long addr, | ||
192 | unsigned long end, struct host_vm_op *ops, | ||
193 | int last_op, int *op_index, int force, | ||
194 | union mm_context *mmu, void **flush, | ||
195 | int (*do_ops)(union mm_context *, | ||
196 | struct host_vm_op *, int, int, | ||
197 | void **)) | ||
198 | { | ||
199 | pud_t *pud; | ||
200 | unsigned long next; | ||
201 | int ret = 0; | ||
202 | |||
203 | pud = pud_offset(pgd, addr); | ||
204 | do { | ||
205 | next = pud_addr_end(addr, end); | ||
206 | if(!pud_present(*pud)){ | ||
207 | if(force || pud_newpage(*pud)){ | ||
208 | ret = add_munmap(addr, next - addr, ops, | ||
209 | op_index, last_op, mmu, | ||
210 | flush, do_ops); | ||
211 | pud_mkuptodate(*pud); | ||
212 | } | ||
213 | } | ||
214 | else ret = update_pmd_range(pud, addr, next, ops, last_op, | ||
215 | op_index, force, mmu, flush, | ||
216 | do_ops); | ||
217 | } while (pud++, addr = next, ((addr != end) && !ret)); | ||
218 | return ret; | ||
219 | } | ||
220 | |||
126 | void fix_range_common(struct mm_struct *mm, unsigned long start_addr, | 221 | void fix_range_common(struct mm_struct *mm, unsigned long start_addr, |
127 | unsigned long end_addr, int force, | 222 | unsigned long end_addr, int force, |
128 | int (*do_ops)(union mm_context *, struct host_vm_op *, | 223 | int (*do_ops)(union mm_context *, struct host_vm_op *, |
129 | int, int, void **)) | 224 | int, int, void **)) |
130 | { | 225 | { |
131 | pgd_t *npgd; | 226 | pgd_t *pgd; |
132 | pud_t *npud; | ||
133 | pmd_t *npmd; | ||
134 | pte_t *npte; | ||
135 | union mm_context *mmu = &mm->context; | 227 | union mm_context *mmu = &mm->context; |
136 | unsigned long addr, end; | ||
137 | int r, w, x; | ||
138 | struct host_vm_op ops[1]; | 228 | struct host_vm_op ops[1]; |
229 | unsigned long addr = start_addr, next; | ||
230 | int ret = 0, last_op = ARRAY_SIZE(ops) - 1, op_index = -1; | ||
139 | void *flush = NULL; | 231 | void *flush = NULL; |
140 | int op_index = -1, last_op = ARRAY_SIZE(ops) - 1; | ||
141 | int ret = 0; | ||
142 | |||
143 | if(mm == NULL) | ||
144 | return; | ||
145 | 232 | ||
146 | ops[0].type = NONE; | 233 | ops[0].type = NONE; |
147 | for(addr = start_addr; addr < end_addr && !ret;){ | 234 | pgd = pgd_offset(mm, addr); |
148 | npgd = pgd_offset(mm, addr); | 235 | do { |
149 | if(!pgd_present(*npgd)){ | 236 | next = pgd_addr_end(addr, end_addr); |
150 | end = ADD_ROUND(addr, PGDIR_SIZE); | 237 | if(!pgd_present(*pgd)){ |
151 | if(end > end_addr) | 238 | if (force || pgd_newpage(*pgd)){ |
152 | end = end_addr; | 239 | ret = add_munmap(addr, next - addr, ops, |
153 | if(force || pgd_newpage(*npgd)){ | ||
154 | ret = add_munmap(addr, end - addr, ops, | ||
155 | &op_index, last_op, mmu, | ||
156 | &flush, do_ops); | ||
157 | pgd_mkuptodate(*npgd); | ||
158 | } | ||
159 | addr = end; | ||
160 | continue; | ||
161 | } | ||
162 | |||
163 | npud = pud_offset(npgd, addr); | ||
164 | if(!pud_present(*npud)){ | ||
165 | end = ADD_ROUND(addr, PUD_SIZE); | ||
166 | if(end > end_addr) | ||
167 | end = end_addr; | ||
168 | if(force || pud_newpage(*npud)){ | ||
169 | ret = add_munmap(addr, end - addr, ops, | ||
170 | &op_index, last_op, mmu, | ||
171 | &flush, do_ops); | ||
172 | pud_mkuptodate(*npud); | ||
173 | } | ||
174 | addr = end; | ||
175 | continue; | ||
176 | } | ||
177 | |||
178 | npmd = pmd_offset(npud, addr); | ||
179 | if(!pmd_present(*npmd)){ | ||
180 | end = ADD_ROUND(addr, PMD_SIZE); | ||
181 | if(end > end_addr) | ||
182 | end = end_addr; | ||
183 | if(force || pmd_newpage(*npmd)){ | ||
184 | ret = add_munmap(addr, end - addr, ops, | ||
185 | &op_index, last_op, mmu, | 240 | &op_index, last_op, mmu, |
186 | &flush, do_ops); | 241 | &flush, do_ops); |
187 | pmd_mkuptodate(*npmd); | 242 | pgd_mkuptodate(*pgd); |
188 | } | 243 | } |
189 | addr = end; | ||
190 | continue; | ||
191 | } | ||
192 | |||
193 | npte = pte_offset_kernel(npmd, addr); | ||
194 | r = pte_read(*npte); | ||
195 | w = pte_write(*npte); | ||
196 | x = pte_exec(*npte); | ||
197 | if (!pte_young(*npte)) { | ||
198 | r = 0; | ||
199 | w = 0; | ||
200 | } else if (!pte_dirty(*npte)) { | ||
201 | w = 0; | ||
202 | } | ||
203 | if(force || pte_newpage(*npte)){ | ||
204 | if(pte_present(*npte)) | ||
205 | ret = add_mmap(addr, | ||
206 | pte_val(*npte) & PAGE_MASK, | ||
207 | PAGE_SIZE, r, w, x, ops, | ||
208 | &op_index, last_op, mmu, | ||
209 | &flush, do_ops); | ||
210 | else ret = add_munmap(addr, PAGE_SIZE, ops, | ||
211 | &op_index, last_op, mmu, | ||
212 | &flush, do_ops); | ||
213 | } | 244 | } |
214 | else if(pte_newprot(*npte)) | 245 | else ret = update_pud_range(pgd, addr, next, ops, last_op, |
215 | ret = add_mprotect(addr, PAGE_SIZE, r, w, x, ops, | 246 | &op_index, force, mmu, &flush, |
216 | &op_index, last_op, mmu, | 247 | do_ops); |
217 | &flush, do_ops); | 248 | } while (pgd++, addr = next, ((addr != end_addr) && !ret)); |
218 | 249 | ||
219 | *npte = pte_mkuptodate(*npte); | ||
220 | addr += PAGE_SIZE; | ||
221 | } | ||
222 | if(!ret) | 250 | if(!ret) |
223 | ret = (*do_ops)(mmu, ops, op_index, 1, &flush); | 251 | ret = (*do_ops)(mmu, ops, op_index, 1, &flush); |
224 | 252 | ||
225 | /* This is not an else because ret is modified above */ | 253 | /* This is not an else because ret is modified above */ |
226 | if(ret) { | 254 | if(ret) { |
227 | printk("fix_range_common: failed, killing current process\n"); | 255 | printk("fix_range_common: failed, killing current process\n"); |
228 | force_sig(SIGKILL, current); | 256 | force_sig(SIGKILL, current); |
@@ -343,12 +371,6 @@ pte_t *addr_pte(struct task_struct *task, unsigned long addr) | |||
343 | return(pte_offset_map(pmd, addr)); | 371 | return(pte_offset_map(pmd, addr)); |
344 | } | 372 | } |
345 | 373 | ||
346 | void flush_tlb_page(struct vm_area_struct *vma, unsigned long address) | ||
347 | { | ||
348 | address &= PAGE_MASK; | ||
349 | flush_tlb_range(vma, address, address + PAGE_SIZE); | ||
350 | } | ||
351 | |||
352 | void flush_tlb_all(void) | 374 | void flush_tlb_all(void) |
353 | { | 375 | { |
354 | flush_tlb_mm(current->mm); | 376 | flush_tlb_mm(current->mm); |
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index 26f15c458574..abab90c3803f 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c | |||
@@ -18,8 +18,9 @@ | |||
18 | #include "asm/current.h" | 18 | #include "asm/current.h" |
19 | #include "asm/irq.h" | 19 | #include "asm/irq.h" |
20 | #include "sysdep/sigcontext.h" | 20 | #include "sysdep/sigcontext.h" |
21 | #include "user_util.h" | ||
22 | #include "kern_util.h" | 21 | #include "kern_util.h" |
22 | #include "as-layout.h" | ||
23 | #include "arch.h" | ||
23 | #include "kern.h" | 24 | #include "kern.h" |
24 | #include "chan_kern.h" | 25 | #include "chan_kern.h" |
25 | #include "mconsole_kern.h" | 26 | #include "mconsole_kern.h" |
@@ -71,8 +72,8 @@ good_area: | |||
71 | goto out; | 72 | goto out; |
72 | 73 | ||
73 | /* Don't require VM_READ|VM_EXEC for write faults! */ | 74 | /* Don't require VM_READ|VM_EXEC for write faults! */ |
74 | if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC))) | 75 | if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC))) |
75 | goto out; | 76 | goto out; |
76 | 77 | ||
77 | do { | 78 | do { |
78 | survive: | 79 | survive: |
@@ -156,20 +157,23 @@ static void segv_handler(int sig, union uml_pt_regs *regs) | |||
156 | * the info in the regs. A pointer to the info then would | 157 | * the info in the regs. A pointer to the info then would |
157 | * give us bad data! | 158 | * give us bad data! |
158 | */ | 159 | */ |
159 | unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) | 160 | unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, |
161 | union uml_pt_regs *regs) | ||
160 | { | 162 | { |
161 | struct siginfo si; | 163 | struct siginfo si; |
162 | void *catcher; | 164 | void *catcher; |
163 | int err; | 165 | int err; |
164 | int is_write = FAULT_WRITE(fi); | 166 | int is_write = FAULT_WRITE(fi); |
165 | unsigned long address = FAULT_ADDRESS(fi); | 167 | unsigned long address = FAULT_ADDRESS(fi); |
166 | 168 | ||
167 | if(!is_user && (address >= start_vm) && (address < end_vm)){ | 169 | if(!is_user && (address >= start_vm) && (address < end_vm)){ |
168 | flush_tlb_kernel_vm(); | 170 | flush_tlb_kernel_vm(); |
169 | return(0); | 171 | return 0; |
170 | } | 172 | } |
171 | else if(current->mm == NULL) | 173 | else if(current->mm == NULL) { |
172 | panic("Segfault with no mm"); | 174 | show_regs(container_of(regs, struct pt_regs, regs)); |
175 | panic("Segfault with no mm"); | ||
176 | } | ||
173 | 177 | ||
174 | if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi)) | 178 | if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi)) |
175 | err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); | 179 | err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); |
@@ -182,26 +186,28 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) | |||
182 | 186 | ||
183 | catcher = current->thread.fault_catcher; | 187 | catcher = current->thread.fault_catcher; |
184 | if(!err) | 188 | if(!err) |
185 | return(0); | 189 | return 0; |
186 | else if(catcher != NULL){ | 190 | else if(catcher != NULL){ |
187 | current->thread.fault_addr = (void *) address; | 191 | current->thread.fault_addr = (void *) address; |
188 | do_longjmp(catcher, 1); | 192 | do_longjmp(catcher, 1); |
189 | } | 193 | } |
190 | else if(current->thread.fault_addr != NULL) | 194 | else if(current->thread.fault_addr != NULL) |
191 | panic("fault_addr set but no fault catcher"); | 195 | panic("fault_addr set but no fault catcher"); |
192 | else if(!is_user && arch_fixup(ip, sc)) | 196 | else if(!is_user && arch_fixup(ip, regs)) |
193 | return(0); | 197 | return 0; |
194 | 198 | ||
195 | if(!is_user) | 199 | if(!is_user) { |
200 | show_regs(container_of(regs, struct pt_regs, regs)); | ||
196 | panic("Kernel mode fault at addr 0x%lx, ip 0x%lx", | 201 | panic("Kernel mode fault at addr 0x%lx, ip 0x%lx", |
197 | address, ip); | 202 | address, ip); |
203 | } | ||
198 | 204 | ||
199 | if (err == -EACCES) { | 205 | if (err == -EACCES) { |
200 | si.si_signo = SIGBUS; | 206 | si.si_signo = SIGBUS; |
201 | si.si_errno = 0; | 207 | si.si_errno = 0; |
202 | si.si_code = BUS_ADRERR; | 208 | si.si_code = BUS_ADRERR; |
203 | si.si_addr = (void __user *)address; | 209 | si.si_addr = (void __user *)address; |
204 | current->thread.arch.faultinfo = fi; | 210 | current->thread.arch.faultinfo = fi; |
205 | force_sig_info(SIGBUS, &si, current); | 211 | force_sig_info(SIGBUS, &si, current); |
206 | } else if (err == -ENOMEM) { | 212 | } else if (err == -ENOMEM) { |
207 | printk("VM: killing process %s\n", current->comm); | 213 | printk("VM: killing process %s\n", current->comm); |
@@ -210,10 +216,10 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) | |||
210 | BUG_ON(err != -EFAULT); | 216 | BUG_ON(err != -EFAULT); |
211 | si.si_signo = SIGSEGV; | 217 | si.si_signo = SIGSEGV; |
212 | si.si_addr = (void __user *) address; | 218 | si.si_addr = (void __user *) address; |
213 | current->thread.arch.faultinfo = fi; | 219 | current->thread.arch.faultinfo = fi; |
214 | force_sig_info(SIGSEGV, &si, current); | 220 | force_sig_info(SIGSEGV, &si, current); |
215 | } | 221 | } |
216 | return(0); | 222 | return 0; |
217 | } | 223 | } |
218 | 224 | ||
219 | void relay_signal(int sig, union uml_pt_regs *regs) | 225 | void relay_signal(int sig, union uml_pt_regs *regs) |
@@ -223,12 +229,12 @@ void relay_signal(int sig, union uml_pt_regs *regs) | |||
223 | 229 | ||
224 | if(!UPT_IS_USER(regs)){ | 230 | if(!UPT_IS_USER(regs)){ |
225 | if(sig == SIGBUS) | 231 | if(sig == SIGBUS) |
226 | printk("Bus error - the /dev/shm or /tmp mount likely " | 232 | printk("Bus error - the host /dev/shm or /tmp mount " |
227 | "just ran out of space\n"); | 233 | "likely just ran out of space\n"); |
228 | panic("Kernel mode signal %d", sig); | 234 | panic("Kernel mode signal %d", sig); |
229 | } | 235 | } |
230 | 236 | ||
231 | current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); | 237 | current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); |
232 | force_sig(sig, current); | 238 | force_sig(sig, current); |
233 | } | 239 | } |
234 | 240 | ||
diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c index ad66df17d9d7..98e21743e604 100644 --- a/arch/um/kernel/tt/exec_kern.c +++ b/arch/um/kernel/tt/exec_kern.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include "asm/uaccess.h" | 10 | #include "asm/uaccess.h" |
11 | #include "asm/pgalloc.h" | 11 | #include "asm/pgalloc.h" |
12 | #include "asm/tlbflush.h" | 12 | #include "asm/tlbflush.h" |
13 | #include "user_util.h" | ||
14 | #include "kern_util.h" | 13 | #include "kern_util.h" |
15 | #include "irq_user.h" | 14 | #include "irq_user.h" |
16 | #include "mem_user.h" | 15 | #include "mem_user.h" |
diff --git a/arch/um/kernel/tt/exec_user.c b/arch/um/kernel/tt/exec_user.c index a92c02ff2ce3..7b5f2181cf51 100644 --- a/arch/um/kernel/tt/exec_user.c +++ b/arch/um/kernel/tt/exec_user.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <errno.h> | 10 | #include <errno.h> |
11 | #include <sys/wait.h> | 11 | #include <sys/wait.h> |
12 | #include <signal.h> | 12 | #include <signal.h> |
13 | #include "user_util.h" | ||
14 | #include "kern_util.h" | 13 | #include "kern_util.h" |
15 | #include "user.h" | 14 | #include "user.h" |
16 | #include "ptrace_user.h" | 15 | #include "ptrace_user.h" |
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c index 8eba8f7dca68..030e4658f36b 100644 --- a/arch/um/kernel/tt/gdb.c +++ b/arch/um/kernel/tt/gdb.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include "user.h" | 17 | #include "user.h" |
18 | #include "debug.h" | 18 | #include "debug.h" |
19 | #include "kern_util.h" | 19 | #include "kern_util.h" |
20 | #include "user_util.h" | ||
21 | #include "tt.h" | 20 | #include "tt.h" |
22 | #include "sysdep/thread.h" | 21 | #include "sysdep/thread.h" |
23 | #include "os.h" | 22 | #include "os.h" |
@@ -115,6 +114,8 @@ struct gdb_data { | |||
115 | int err; | 114 | int err; |
116 | }; | 115 | }; |
117 | 116 | ||
117 | extern char *linux_prog; | ||
118 | |||
118 | static void config_gdb_cb(void *arg) | 119 | static void config_gdb_cb(void *arg) |
119 | { | 120 | { |
120 | struct gdb_data *data = arg; | 121 | struct gdb_data *data = arg; |
diff --git a/arch/um/kernel/tt/include/mode_kern-tt.h b/arch/um/kernel/tt/include/mode_kern-tt.h deleted file mode 100644 index 2a35b15c5fef..000000000000 --- a/arch/um/kernel/tt/include/mode_kern-tt.h +++ /dev/null | |||
@@ -1,52 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __TT_MODE_KERN_H__ | ||
7 | #define __TT_MODE_KERN_H__ | ||
8 | |||
9 | #include "linux/sched.h" | ||
10 | #include "asm/page.h" | ||
11 | #include "asm/ptrace.h" | ||
12 | #include "asm/uaccess.h" | ||
13 | |||
14 | extern void switch_to_tt(void *prev, void *next); | ||
15 | extern void flush_thread_tt(void); | ||
16 | extern void start_thread_tt(struct pt_regs *regs, unsigned long eip, | ||
17 | unsigned long esp); | ||
18 | extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, | ||
19 | unsigned long stack_top, struct task_struct *p, | ||
20 | struct pt_regs *regs); | ||
21 | extern void release_thread_tt(struct task_struct *task); | ||
22 | extern void initial_thread_cb_tt(void (*proc)(void *), void *arg); | ||
23 | extern void init_idle_tt(void); | ||
24 | extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end); | ||
25 | extern void flush_tlb_kernel_vm_tt(void); | ||
26 | extern void __flush_tlb_one_tt(unsigned long addr); | ||
27 | extern void flush_tlb_range_tt(struct vm_area_struct *vma, | ||
28 | unsigned long start, unsigned long end); | ||
29 | extern void flush_tlb_mm_tt(struct mm_struct *mm); | ||
30 | extern void force_flush_all_tt(void); | ||
31 | extern long execute_syscall_tt(void *r); | ||
32 | extern void before_mem_tt(unsigned long brk_start); | ||
33 | extern unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out, | ||
34 | unsigned long *task_size_out); | ||
35 | extern int start_uml_tt(void); | ||
36 | extern int external_pid_tt(struct task_struct *task); | ||
37 | extern int thread_pid_tt(struct task_struct *task); | ||
38 | |||
39 | #define kmem_end_tt (host_task_size - ABOVE_KMEM) | ||
40 | |||
41 | #endif | ||
42 | |||
43 | /* | ||
44 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
45 | * Emacs will notice this stuff at the end of the file and automatically | ||
46 | * adjust the settings for this buffer only. This must remain at the end | ||
47 | * of the file. | ||
48 | * --------------------------------------------------------------------------- | ||
49 | * Local variables: | ||
50 | * c-file-style: "linux" | ||
51 | * End: | ||
52 | */ | ||
diff --git a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c index 4d1929dfa285..d0c3c4975f28 100644 --- a/arch/um/kernel/tt/mem.c +++ b/arch/um/kernel/tt/mem.c | |||
@@ -8,7 +8,6 @@ | |||
8 | #include "asm/uaccess.h" | 8 | #include "asm/uaccess.h" |
9 | #include "mem_user.h" | 9 | #include "mem_user.h" |
10 | #include "kern_util.h" | 10 | #include "kern_util.h" |
11 | #include "user_util.h" | ||
12 | #include "kern.h" | 11 | #include "kern.h" |
13 | #include "tt.h" | 12 | #include "tt.h" |
14 | 13 | ||
diff --git a/arch/um/kernel/tt/mem_user.c b/arch/um/kernel/tt/mem_user.c index 03e589895388..9774f6360c32 100644 --- a/arch/um/kernel/tt/mem_user.c +++ b/arch/um/kernel/tt/mem_user.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <sys/mman.h> | 11 | #include <sys/mman.h> |
12 | #include "tt.h" | 12 | #include "tt.h" |
13 | #include "mem_user.h" | 13 | #include "mem_user.h" |
14 | #include "user_util.h" | ||
15 | #include "os.h" | 14 | #include "os.h" |
16 | 15 | ||
17 | void remap_data(void *segment_start, void *segment_end, int w) | 16 | void remap_data(void *segment_start, void *segment_end, int w) |
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c index 1e86f0bfef72..c631303cb800 100644 --- a/arch/um/kernel/tt/process_kern.c +++ b/arch/um/kernel/tt/process_kern.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include "asm/tlbflush.h" | 14 | #include "asm/tlbflush.h" |
15 | #include "irq_user.h" | 15 | #include "irq_user.h" |
16 | #include "kern_util.h" | 16 | #include "kern_util.h" |
17 | #include "user_util.h" | ||
18 | #include "os.h" | 17 | #include "os.h" |
19 | #include "kern.h" | 18 | #include "kern.h" |
20 | #include "sigcontext.h" | 19 | #include "sigcontext.h" |
@@ -65,7 +64,8 @@ void switch_to_tt(void *prev, void *next) | |||
65 | if(from->thread.mode.tt.switch_pipe[0] == -1) | 64 | if(from->thread.mode.tt.switch_pipe[0] == -1) |
66 | os_kill_process(os_getpid(), 0); | 65 | os_kill_process(os_getpid(), 0); |
67 | 66 | ||
68 | err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c)); | 67 | err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, |
68 | sizeof(c)); | ||
69 | if(err != sizeof(c)) | 69 | if(err != sizeof(c)) |
70 | panic("read of switch_pipe failed, errno = %d", -err); | 70 | panic("read of switch_pipe failed, errno = %d", -err); |
71 | 71 | ||
diff --git a/arch/um/kernel/tt/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c index 58800c50b10e..420c23f311f3 100644 --- a/arch/um/kernel/tt/ptproxy/proxy.c +++ b/arch/um/kernel/tt/ptproxy/proxy.c | |||
@@ -26,7 +26,6 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml | |||
26 | #include "sysdep.h" | 26 | #include "sysdep.h" |
27 | #include "wait.h" | 27 | #include "wait.h" |
28 | 28 | ||
29 | #include "user_util.h" | ||
30 | #include "user.h" | 29 | #include "user.h" |
31 | #include "os.h" | 30 | #include "os.h" |
32 | #include "tempfile.h" | 31 | #include "tempfile.h" |
@@ -339,11 +338,12 @@ int start_debugger(char *prog, int startup, int stop, int *fd_out) | |||
339 | "err = %d\n", -fd); | 338 | "err = %d\n", -fd); |
340 | exit(1); | 339 | exit(1); |
341 | } | 340 | } |
342 | os_write_file(fd, gdb_init_string, sizeof(gdb_init_string) - 1); | 341 | os_write_file(fd, gdb_init_string, |
342 | sizeof(gdb_init_string) - 1); | ||
343 | if(startup){ | 343 | if(startup){ |
344 | if(stop){ | 344 | if(stop){ |
345 | os_write_file(fd, "b start_kernel\n", | 345 | os_write_file(fd, "b start_kernel\n", |
346 | strlen("b start_kernel\n")); | 346 | strlen("b start_kernel\n")); |
347 | } | 347 | } |
348 | os_write_file(fd, "c\n", strlen("c\n")); | 348 | os_write_file(fd, "c\n", strlen("c\n")); |
349 | } | 349 | } |
diff --git a/arch/um/kernel/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c index 03774427d468..4b4f6179b212 100644 --- a/arch/um/kernel/tt/ptproxy/ptrace.c +++ b/arch/um/kernel/tt/ptproxy/ptrace.c | |||
@@ -16,7 +16,6 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml | |||
16 | 16 | ||
17 | #include "ptproxy.h" | 17 | #include "ptproxy.h" |
18 | #include "debug.h" | 18 | #include "debug.h" |
19 | #include "user_util.h" | ||
20 | #include "kern_util.h" | 19 | #include "kern_util.h" |
21 | #include "ptrace_user.h" | 20 | #include "ptrace_user.h" |
22 | #include "tt.h" | 21 | #include "tt.h" |
diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c index 99f178319d03..e0e1ab0588ad 100644 --- a/arch/um/kernel/tt/ptproxy/sysdep.c +++ b/arch/um/kernel/tt/ptproxy/sysdep.c | |||
@@ -13,7 +13,6 @@ terms and conditions. | |||
13 | #include <sys/types.h> | 13 | #include <sys/types.h> |
14 | #include <linux/unistd.h> | 14 | #include <linux/unistd.h> |
15 | #include "ptrace_user.h" | 15 | #include "ptrace_user.h" |
16 | #include "user_util.h" | ||
17 | #include "user.h" | 16 | #include "user.h" |
18 | #include "os.h" | 17 | #include "os.h" |
19 | 18 | ||
diff --git a/arch/um/kernel/tt/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c index 12f6319d8d76..bdd4af4b65fc 100644 --- a/arch/um/kernel/tt/ptproxy/wait.c +++ b/arch/um/kernel/tt/ptproxy/wait.c | |||
@@ -13,7 +13,6 @@ terms and conditions. | |||
13 | #include "ptproxy.h" | 13 | #include "ptproxy.h" |
14 | #include "sysdep.h" | 14 | #include "sysdep.h" |
15 | #include "wait.h" | 15 | #include "wait.h" |
16 | #include "user_util.h" | ||
17 | #include "ptrace_user.h" | 16 | #include "ptrace_user.h" |
18 | #include "sysdep/ptrace.h" | 17 | #include "sysdep/ptrace.h" |
19 | #include "sysdep/sigcontext.h" | 18 | #include "sysdep/sigcontext.h" |
diff --git a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c index 902987bf379b..f52b47aff1d2 100644 --- a/arch/um/kernel/tt/syscall_user.c +++ b/arch/um/kernel/tt/syscall_user.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include "sigcontext.h" | 11 | #include "sigcontext.h" |
12 | #include "ptrace_user.h" | 12 | #include "ptrace_user.h" |
13 | #include "task.h" | 13 | #include "task.h" |
14 | #include "user_util.h" | ||
15 | #include "kern_util.h" | 14 | #include "kern_util.h" |
16 | #include "syscall.h" | 15 | #include "syscall.h" |
17 | #include "tt.h" | 16 | #include "tt.h" |
diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c index ae6217c86135..7caa24fe05df 100644 --- a/arch/um/kernel/tt/tlb.c +++ b/arch/um/kernel/tt/tlb.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include "asm/pgtable.h" | 12 | #include "asm/pgtable.h" |
13 | #include "asm/uaccess.h" | 13 | #include "asm/uaccess.h" |
14 | #include "asm/tlbflush.h" | 14 | #include "asm/tlbflush.h" |
15 | #include "user_util.h" | ||
16 | #include "mem_user.h" | 15 | #include "mem_user.h" |
17 | #include "os.h" | 16 | #include "os.h" |
18 | #include "tlb.h" | 17 | #include "tlb.h" |
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c index b9195355075a..c23588393f6e 100644 --- a/arch/um/kernel/tt/tracer.c +++ b/arch/um/kernel/tt/tracer.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include "sigcontext.h" | 19 | #include "sigcontext.h" |
20 | #include "sysdep/sigcontext.h" | 20 | #include "sysdep/sigcontext.h" |
21 | #include "os.h" | 21 | #include "os.h" |
22 | #include "user_util.h" | ||
23 | #include "mem_user.h" | 22 | #include "mem_user.h" |
24 | #include "process.h" | 23 | #include "process.h" |
25 | #include "kern_util.h" | 24 | #include "kern_util.h" |
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c index b5d9d64d91e4..3032eb5e2467 100644 --- a/arch/um/kernel/tt/trap_user.c +++ b/arch/um/kernel/tt/trap_user.c | |||
@@ -8,7 +8,6 @@ | |||
8 | #include <signal.h> | 8 | #include <signal.h> |
9 | #include "sysdep/ptrace.h" | 9 | #include "sysdep/ptrace.h" |
10 | #include "sysdep/sigcontext.h" | 10 | #include "sysdep/sigcontext.h" |
11 | #include "user_util.h" | ||
12 | #include "kern_util.h" | 11 | #include "kern_util.h" |
13 | #include "task.h" | 12 | #include "task.h" |
14 | #include "tt.h" | 13 | #include "tt.h" |
diff --git a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c index ed1abcf4d057..0e5c82c5e5b7 100644 --- a/arch/um/kernel/tt/uaccess_user.c +++ b/arch/um/kernel/tt/uaccess_user.c | |||
@@ -5,7 +5,6 @@ | |||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <string.h> | 7 | #include <string.h> |
8 | #include "user_util.h" | ||
9 | #include "uml_uaccess.h" | 8 | #include "uml_uaccess.h" |
10 | #include "task.h" | 9 | #include "task.h" |
11 | #include "kern_util.h" | 10 | #include "kern_util.h" |
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 89c6dba731f8..1cf954a47fd7 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include "linux/seq_file.h" | 17 | #include "linux/seq_file.h" |
18 | #include "linux/delay.h" | 18 | #include "linux/delay.h" |
19 | #include "linux/module.h" | 19 | #include "linux/module.h" |
20 | #include "linux/utsname.h" | ||
20 | #include "asm/page.h" | 21 | #include "asm/page.h" |
21 | #include "asm/pgtable.h" | 22 | #include "asm/pgtable.h" |
22 | #include "asm/ptrace.h" | 23 | #include "asm/ptrace.h" |
@@ -25,8 +26,9 @@ | |||
25 | #include "asm/setup.h" | 26 | #include "asm/setup.h" |
26 | #include "ubd_user.h" | 27 | #include "ubd_user.h" |
27 | #include "asm/current.h" | 28 | #include "asm/current.h" |
28 | #include "user_util.h" | ||
29 | #include "kern_util.h" | 29 | #include "kern_util.h" |
30 | #include "as-layout.h" | ||
31 | #include "arch.h" | ||
30 | #include "kern.h" | 32 | #include "kern.h" |
31 | #include "mem_user.h" | 33 | #include "mem_user.h" |
32 | #include "mem.h" | 34 | #include "mem.h" |
@@ -42,7 +44,7 @@ | |||
42 | 44 | ||
43 | #define DEFAULT_COMMAND_LINE "root=98:0" | 45 | #define DEFAULT_COMMAND_LINE "root=98:0" |
44 | 46 | ||
45 | /* Changed in linux_main and setup_arch, which run before SMP is started */ | 47 | /* Changed in add_arg and setup_arch, which run before SMP is started */ |
46 | static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 }; | 48 | static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 }; |
47 | 49 | ||
48 | static void __init add_arg(char *arg) | 50 | static void __init add_arg(char *arg) |
@@ -56,17 +58,25 @@ static void __init add_arg(char *arg) | |||
56 | strcat(command_line, arg); | 58 | strcat(command_line, arg); |
57 | } | 59 | } |
58 | 60 | ||
59 | struct cpuinfo_um boot_cpu_data = { | 61 | /* |
62 | * These fields are initialized at boot time and not changed. | ||
63 | * XXX This structure is used only in the non-SMP case. Maybe this | ||
64 | * should be moved to smp.c. | ||
65 | */ | ||
66 | struct cpuinfo_um boot_cpu_data = { | ||
60 | .loops_per_jiffy = 0, | 67 | .loops_per_jiffy = 0, |
61 | .ipi_pipe = { -1, -1 } | 68 | .ipi_pipe = { -1, -1 } |
62 | }; | 69 | }; |
63 | 70 | ||
64 | unsigned long thread_saved_pc(struct task_struct *task) | 71 | unsigned long thread_saved_pc(struct task_struct *task) |
65 | { | 72 | { |
66 | return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas, | 73 | return os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas, |
67 | task))); | 74 | task)); |
68 | } | 75 | } |
69 | 76 | ||
77 | /* Changed in setup_arch, which is called in early boot */ | ||
78 | static char host_info[(__NEW_UTS_LEN + 1) * 5]; | ||
79 | |||
70 | static int show_cpuinfo(struct seq_file *m, void *v) | 80 | static int show_cpuinfo(struct seq_file *m, void *v) |
71 | { | 81 | { |
72 | int index = 0; | 82 | int index = 0; |
@@ -86,7 +96,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
86 | loops_per_jiffy/(500000/HZ), | 96 | loops_per_jiffy/(500000/HZ), |
87 | (loops_per_jiffy/(5000/HZ)) % 100); | 97 | (loops_per_jiffy/(5000/HZ)) % 100); |
88 | 98 | ||
89 | return(0); | 99 | return 0; |
90 | } | 100 | } |
91 | 101 | ||
92 | static void *c_start(struct seq_file *m, loff_t *pos) | 102 | static void *c_start(struct seq_file *m, loff_t *pos) |
@@ -114,14 +124,12 @@ const struct seq_operations cpuinfo_op = { | |||
114 | /* Set in linux_main */ | 124 | /* Set in linux_main */ |
115 | unsigned long host_task_size; | 125 | unsigned long host_task_size; |
116 | unsigned long task_size; | 126 | unsigned long task_size; |
117 | |||
118 | unsigned long uml_start; | ||
119 | |||
120 | /* Set in early boot */ | ||
121 | unsigned long uml_physmem; | 127 | unsigned long uml_physmem; |
122 | unsigned long uml_reserved; | 128 | unsigned long uml_reserved; /* Also modified in mem_init */ |
123 | unsigned long start_vm; | 129 | unsigned long start_vm; |
124 | unsigned long end_vm; | 130 | unsigned long end_vm; |
131 | |||
132 | /* Set in uml_ncpus_setup */ | ||
125 | int ncpus = 1; | 133 | int ncpus = 1; |
126 | 134 | ||
127 | #ifdef CONFIG_CMDLINE_ON_HOST | 135 | #ifdef CONFIG_CMDLINE_ON_HOST |
@@ -135,6 +143,8 @@ static char *argv1_end = NULL; | |||
135 | 143 | ||
136 | /* Set in early boot */ | 144 | /* Set in early boot */ |
137 | static int have_root __initdata = 0; | 145 | static int have_root __initdata = 0; |
146 | |||
147 | /* Set in uml_mem_setup and modified in linux_main */ | ||
138 | long long physmem_size = 32 * 1024 * 1024; | 148 | long long physmem_size = 32 * 1024 * 1024; |
139 | 149 | ||
140 | void set_cmdline(char *cmd) | 150 | void set_cmdline(char *cmd) |
@@ -212,12 +222,12 @@ __uml_setup("debug", no_skas_debug_setup, | |||
212 | #ifdef CONFIG_SMP | 222 | #ifdef CONFIG_SMP |
213 | static int __init uml_ncpus_setup(char *line, int *add) | 223 | static int __init uml_ncpus_setup(char *line, int *add) |
214 | { | 224 | { |
215 | if (!sscanf(line, "%d", &ncpus)) { | 225 | if (!sscanf(line, "%d", &ncpus)) { |
216 | printf("Couldn't parse [%s]\n", line); | 226 | printf("Couldn't parse [%s]\n", line); |
217 | return -1; | 227 | return -1; |
218 | } | 228 | } |
219 | 229 | ||
220 | return 0; | 230 | return 0; |
221 | } | 231 | } |
222 | 232 | ||
223 | __uml_setup("ncpus=", uml_ncpus_setup, | 233 | __uml_setup("ncpus=", uml_ncpus_setup, |
@@ -234,7 +244,7 @@ static int force_tt = 0; | |||
234 | static int __init mode_tt_setup(char *line, int *add) | 244 | static int __init mode_tt_setup(char *line, int *add) |
235 | { | 245 | { |
236 | force_tt = 1; | 246 | force_tt = 1; |
237 | return(0); | 247 | return 0; |
238 | } | 248 | } |
239 | 249 | ||
240 | #else | 250 | #else |
@@ -245,7 +255,7 @@ static int __init mode_tt_setup(char *line, int *add) | |||
245 | static int __init mode_tt_setup(char *line, int *add) | 255 | static int __init mode_tt_setup(char *line, int *add) |
246 | { | 256 | { |
247 | printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n"); | 257 | printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n"); |
248 | return(0); | 258 | return 0; |
249 | } | 259 | } |
250 | 260 | ||
251 | #else | 261 | #else |
@@ -256,7 +266,7 @@ static int __init mode_tt_setup(char *line, int *add) | |||
256 | static int __init mode_tt_setup(char *line, int *add) | 266 | static int __init mode_tt_setup(char *line, int *add) |
257 | { | 267 | { |
258 | printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n"); | 268 | printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n"); |
259 | return(0); | 269 | return 0; |
260 | } | 270 | } |
261 | 271 | ||
262 | #endif | 272 | #endif |
@@ -274,16 +284,15 @@ int mode_tt = DEFAULT_TT; | |||
274 | 284 | ||
275 | static int __init Usage(char *line, int *add) | 285 | static int __init Usage(char *line, int *add) |
276 | { | 286 | { |
277 | const char **p; | 287 | const char **p; |
278 | 288 | ||
279 | printf(usage_string, init_utsname()->release); | 289 | printf(usage_string, init_utsname()->release); |
280 | p = &__uml_help_start; | 290 | p = &__uml_help_start; |
281 | while (p < &__uml_help_end) { | 291 | while (p < &__uml_help_end) { |
282 | printf("%s", *p); | 292 | printf("%s", *p); |
283 | p++; | 293 | p++; |
284 | } | 294 | } |
285 | exit(0); | 295 | exit(0); |
286 | |||
287 | return 0; | 296 | return 0; |
288 | } | 297 | } |
289 | 298 | ||
@@ -374,13 +383,12 @@ int __init linux_main(int argc, char **argv) | |||
374 | 383 | ||
375 | printf("UML running in %s mode\n", mode); | 384 | printf("UML running in %s mode\n", mode); |
376 | 385 | ||
377 | uml_start = (unsigned long) &__binary_start; | ||
378 | host_task_size = CHOOSE_MODE_PROC(set_task_sizes_tt, | 386 | host_task_size = CHOOSE_MODE_PROC(set_task_sizes_tt, |
379 | set_task_sizes_skas, &task_size); | 387 | set_task_sizes_skas, &task_size); |
380 | 388 | ||
381 | /* | 389 | /* |
382 | * Setting up handlers to 'sig_info' struct | 390 | * Setting up handlers to 'sig_info' struct |
383 | */ | 391 | */ |
384 | os_fill_handlinfo(handlinfo_kern); | 392 | os_fill_handlinfo(handlinfo_kern); |
385 | 393 | ||
386 | brk_start = (unsigned long) sbrk(0); | 394 | brk_start = (unsigned long) sbrk(0); |
@@ -396,7 +404,7 @@ int __init linux_main(int argc, char **argv) | |||
396 | physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); | 404 | physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); |
397 | } | 405 | } |
398 | 406 | ||
399 | uml_physmem = uml_start & PAGE_MASK; | 407 | uml_physmem = (unsigned long) &__binary_start & PAGE_MASK; |
400 | 408 | ||
401 | /* Reserve up to 4M after the current brk */ | 409 | /* Reserve up to 4M after the current brk */ |
402 | uml_reserved = ROUND_4M(brk_start) + (1 << 22); | 410 | uml_reserved = ROUND_4M(brk_start) + (1 << 22); |
@@ -407,7 +415,7 @@ int __init linux_main(int argc, char **argv) | |||
407 | argv1_begin = argv[1]; | 415 | argv1_begin = argv[1]; |
408 | argv1_end = &argv[1][strlen(argv[1])]; | 416 | argv1_end = &argv[1][strlen(argv[1])]; |
409 | #endif | 417 | #endif |
410 | 418 | ||
411 | highmem = 0; | 419 | highmem = 0; |
412 | iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK; | 420 | iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK; |
413 | max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC; | 421 | max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC; |
@@ -449,12 +457,12 @@ int __init linux_main(int argc, char **argv) | |||
449 | printf("Kernel virtual memory size shrunk to %lu bytes\n", | 457 | printf("Kernel virtual memory size shrunk to %lu bytes\n", |
450 | virtmem_size); | 458 | virtmem_size); |
451 | 459 | ||
452 | uml_postsetup(); | 460 | uml_postsetup(); |
453 | 461 | ||
454 | task_protections((unsigned long) &init_thread_info); | 462 | task_protections((unsigned long) &init_thread_info); |
455 | os_flush_stdout(); | 463 | os_flush_stdout(); |
456 | 464 | ||
457 | return(CHOOSE_MODE(start_uml_tt(), start_uml_skas())); | 465 | return CHOOSE_MODE(start_uml_tt(), start_uml_skas()); |
458 | } | 466 | } |
459 | 467 | ||
460 | extern int uml_exitcode; | 468 | extern int uml_exitcode; |
@@ -466,8 +474,8 @@ static int panic_exit(struct notifier_block *self, unsigned long unused1, | |||
466 | show_regs(&(current->thread.regs)); | 474 | show_regs(&(current->thread.regs)); |
467 | bust_spinlocks(0); | 475 | bust_spinlocks(0); |
468 | uml_exitcode = 1; | 476 | uml_exitcode = 1; |
469 | machine_halt(); | 477 | os_dump_core(); |
470 | return(0); | 478 | return 0; |
471 | } | 479 | } |
472 | 480 | ||
473 | static struct notifier_block panic_exit_notifier = { | 481 | static struct notifier_block panic_exit_notifier = { |
@@ -482,14 +490,14 @@ void __init setup_arch(char **cmdline_p) | |||
482 | &panic_exit_notifier); | 490 | &panic_exit_notifier); |
483 | paging_init(); | 491 | paging_init(); |
484 | strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); | 492 | strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); |
485 | *cmdline_p = command_line; | 493 | *cmdline_p = command_line; |
486 | setup_hostinfo(); | 494 | setup_hostinfo(host_info, sizeof host_info); |
487 | } | 495 | } |
488 | 496 | ||
489 | void __init check_bugs(void) | 497 | void __init check_bugs(void) |
490 | { | 498 | { |
491 | arch_check_bugs(); | 499 | arch_check_bugs(); |
492 | os_check_bugs(); | 500 | os_check_bugs(); |
493 | } | 501 | } |
494 | 502 | ||
495 | void apply_alternatives(struct alt_instr *start, struct alt_instr *end) | 503 | void apply_alternatives(struct alt_instr *start, struct alt_instr *end) |
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index 6ff12743a0bd..9bf944f6a1db 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c | |||
@@ -132,10 +132,10 @@ static int aio_thread(void *arg) | |||
132 | { .data = (void *) (long) event.data, | 132 | { .data = (void *) (long) event.data, |
133 | .err = event.res }); | 133 | .err = event.res }); |
134 | reply_fd = ((struct aio_context *) reply.data)->reply_fd; | 134 | reply_fd = ((struct aio_context *) reply.data)->reply_fd; |
135 | err = os_write_file(reply_fd, &reply, sizeof(reply)); | 135 | err = write(reply_fd, &reply, sizeof(reply)); |
136 | if(err != sizeof(reply)) | 136 | if(err != sizeof(reply)) |
137 | printk("aio_thread - write failed, fd = %d, " | 137 | printk("aio_thread - write failed, fd = %d, " |
138 | "err = %d\n", reply_fd, -err); | 138 | "err = %d\n", reply_fd, errno); |
139 | } | 139 | } |
140 | } | 140 | } |
141 | return 0; | 141 | return 0; |
@@ -146,38 +146,31 @@ static int aio_thread(void *arg) | |||
146 | static int do_not_aio(struct aio_thread_req *req) | 146 | static int do_not_aio(struct aio_thread_req *req) |
147 | { | 147 | { |
148 | char c; | 148 | char c; |
149 | int err; | 149 | unsigned long long actual; |
150 | int n; | ||
151 | |||
152 | actual = lseek64(req->io_fd, req->offset, SEEK_SET); | ||
153 | if(actual != req->offset) | ||
154 | return -errno; | ||
150 | 155 | ||
151 | switch(req->type){ | 156 | switch(req->type){ |
152 | case AIO_READ: | 157 | case AIO_READ: |
153 | err = os_seek_file(req->io_fd, req->offset); | 158 | n = read(req->io_fd, req->buf, req->len); |
154 | if(err) | ||
155 | goto out; | ||
156 | |||
157 | err = os_read_file(req->io_fd, req->buf, req->len); | ||
158 | break; | 159 | break; |
159 | case AIO_WRITE: | 160 | case AIO_WRITE: |
160 | err = os_seek_file(req->io_fd, req->offset); | 161 | n = write(req->io_fd, req->buf, req->len); |
161 | if(err) | ||
162 | goto out; | ||
163 | |||
164 | err = os_write_file(req->io_fd, req->buf, req->len); | ||
165 | break; | 162 | break; |
166 | case AIO_MMAP: | 163 | case AIO_MMAP: |
167 | err = os_seek_file(req->io_fd, req->offset); | 164 | n = read(req->io_fd, &c, sizeof(c)); |
168 | if(err) | ||
169 | goto out; | ||
170 | |||
171 | err = os_read_file(req->io_fd, &c, sizeof(c)); | ||
172 | break; | 165 | break; |
173 | default: | 166 | default: |
174 | printk("do_not_aio - bad request type : %d\n", req->type); | 167 | printk("do_not_aio - bad request type : %d\n", req->type); |
175 | err = -EINVAL; | 168 | return -EINVAL; |
176 | break; | ||
177 | } | 169 | } |
178 | 170 | ||
179 | out: | 171 | if(n < 0) |
180 | return err; | 172 | return -errno; |
173 | return 0; | ||
181 | } | 174 | } |
182 | 175 | ||
183 | /* These are initialized in initcalls and not changed */ | 176 | /* These are initialized in initcalls and not changed */ |
@@ -193,12 +186,12 @@ static int not_aio_thread(void *arg) | |||
193 | 186 | ||
194 | signal(SIGWINCH, SIG_IGN); | 187 | signal(SIGWINCH, SIG_IGN); |
195 | while(1){ | 188 | while(1){ |
196 | err = os_read_file(aio_req_fd_r, &req, sizeof(req)); | 189 | err = read(aio_req_fd_r, &req, sizeof(req)); |
197 | if(err != sizeof(req)){ | 190 | if(err != sizeof(req)){ |
198 | if(err < 0) | 191 | if(err < 0) |
199 | printk("not_aio_thread - read failed, " | 192 | printk("not_aio_thread - read failed, " |
200 | "fd = %d, err = %d\n", aio_req_fd_r, | 193 | "fd = %d, err = %d\n", aio_req_fd_r, |
201 | -err); | 194 | errno); |
202 | else { | 195 | else { |
203 | printk("not_aio_thread - short read, fd = %d, " | 196 | printk("not_aio_thread - short read, fd = %d, " |
204 | "length = %d\n", aio_req_fd_r, err); | 197 | "length = %d\n", aio_req_fd_r, err); |
@@ -207,11 +200,11 @@ static int not_aio_thread(void *arg) | |||
207 | } | 200 | } |
208 | err = do_not_aio(&req); | 201 | err = do_not_aio(&req); |
209 | reply = ((struct aio_thread_reply) { .data = req.aio, | 202 | reply = ((struct aio_thread_reply) { .data = req.aio, |
210 | .err = err }); | 203 | .err = err }); |
211 | err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply)); | 204 | err = write(req.aio->reply_fd, &reply, sizeof(reply)); |
212 | if(err != sizeof(reply)) | 205 | if(err != sizeof(reply)) |
213 | printk("not_aio_thread - write failed, fd = %d, " | 206 | printk("not_aio_thread - write failed, fd = %d, " |
214 | "err = %d\n", req.aio->reply_fd, -err); | 207 | "err = %d\n", req.aio->reply_fd, errno); |
215 | } | 208 | } |
216 | 209 | ||
217 | return 0; | 210 | return 0; |
@@ -228,6 +221,11 @@ static int init_aio_24(void) | |||
228 | 221 | ||
229 | aio_req_fd_w = fds[0]; | 222 | aio_req_fd_w = fds[0]; |
230 | aio_req_fd_r = fds[1]; | 223 | aio_req_fd_r = fds[1]; |
224 | |||
225 | err = os_set_fd_block(aio_req_fd_w, 0); | ||
226 | if(err) | ||
227 | goto out_close_pipe; | ||
228 | |||
231 | err = run_helper_thread(not_aio_thread, NULL, | 229 | err = run_helper_thread(not_aio_thread, NULL, |
232 | CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); | 230 | CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); |
233 | if(err < 0) | 231 | if(err < 0) |
@@ -285,10 +283,12 @@ static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, | |||
285 | if(err){ | 283 | if(err){ |
286 | reply = ((struct aio_thread_reply) { .data = aio, | 284 | reply = ((struct aio_thread_reply) { .data = aio, |
287 | .err = err }); | 285 | .err = err }); |
288 | err = os_write_file(aio->reply_fd, &reply, sizeof(reply)); | 286 | err = write(aio->reply_fd, &reply, sizeof(reply)); |
289 | if(err != sizeof(reply)) | 287 | if(err != sizeof(reply)){ |
288 | err = -errno; | ||
290 | printk("submit_aio_26 - write failed, " | 289 | printk("submit_aio_26 - write failed, " |
291 | "fd = %d, err = %d\n", aio->reply_fd, -err); | 290 | "fd = %d, err = %d\n", aio->reply_fd, -err); |
291 | } | ||
292 | else err = 0; | 292 | else err = 0; |
293 | } | 293 | } |
294 | 294 | ||
@@ -383,9 +383,10 @@ static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len, | |||
383 | }; | 383 | }; |
384 | int err; | 384 | int err; |
385 | 385 | ||
386 | err = os_write_file(aio_req_fd_w, &req, sizeof(req)); | 386 | err = write(aio_req_fd_w, &req, sizeof(req)); |
387 | if(err == sizeof(req)) | 387 | if(err == sizeof(req)) |
388 | err = 0; | 388 | err = 0; |
389 | else err = -errno; | ||
389 | 390 | ||
390 | return err; | 391 | return err; |
391 | } | 392 | } |
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c index 863981ba1468..acba30161287 100644 --- a/arch/um/os-Linux/drivers/ethertap_user.c +++ b/arch/um/os-Linux/drivers/ethertap_user.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and | 2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and |
3 | * James Leu (jleu@mindspring.net). | 3 | * James Leu (jleu@mindspring.net). |
4 | * Copyright (C) 2001 by various other people who didn't put their name here. | 4 | * Copyright (C) 2001 by various other people who didn't put their name here. |
5 | * Licensed under the GPL. | 5 | * Licensed under the GPL. |
@@ -16,19 +16,20 @@ | |||
16 | #include <net/if.h> | 16 | #include <net/if.h> |
17 | #include "user.h" | 17 | #include "user.h" |
18 | #include "kern_util.h" | 18 | #include "kern_util.h" |
19 | #include "user_util.h" | ||
20 | #include "net_user.h" | 19 | #include "net_user.h" |
21 | #include "etap.h" | 20 | #include "etap.h" |
22 | #include "os.h" | 21 | #include "os.h" |
23 | #include "um_malloc.h" | 22 | #include "um_malloc.h" |
23 | #include "kern_constants.h" | ||
24 | 24 | ||
25 | #define MAX_PACKET ETH_MAX_PACKET | 25 | #define MAX_PACKET ETH_MAX_PACKET |
26 | 26 | ||
27 | void etap_user_init(void *data, void *dev) | 27 | static int etap_user_init(void *data, void *dev) |
28 | { | 28 | { |
29 | struct ethertap_data *pri = data; | 29 | struct ethertap_data *pri = data; |
30 | 30 | ||
31 | pri->dev = dev; | 31 | pri->dev = dev; |
32 | return 0; | ||
32 | } | 33 | } |
33 | 34 | ||
34 | struct addr_change { | 35 | struct addr_change { |
@@ -47,13 +48,16 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask, | |||
47 | change.what = op; | 48 | change.what = op; |
48 | memcpy(change.addr, addr, sizeof(change.addr)); | 49 | memcpy(change.addr, addr, sizeof(change.addr)); |
49 | memcpy(change.netmask, netmask, sizeof(change.netmask)); | 50 | memcpy(change.netmask, netmask, sizeof(change.netmask)); |
50 | n = os_write_file(fd, &change, sizeof(change)); | 51 | CATCH_EINTR(n = write(fd, &change, sizeof(change))); |
51 | if(n != sizeof(change)) | 52 | if(n != sizeof(change)){ |
52 | printk("etap_change - request failed, err = %d\n", -n); | 53 | printk("etap_change - request failed, err = %d\n", errno); |
53 | output = um_kmalloc(page_size()); | 54 | return; |
55 | } | ||
56 | |||
57 | output = um_kmalloc(UM_KERN_PAGE_SIZE); | ||
54 | if(output == NULL) | 58 | if(output == NULL) |
55 | printk("etap_change : Failed to allocate output buffer\n"); | 59 | printk("etap_change : Failed to allocate output buffer\n"); |
56 | read_output(fd, output, page_size()); | 60 | read_output(fd, output, UM_KERN_PAGE_SIZE); |
57 | if(output != NULL){ | 61 | if(output != NULL){ |
58 | printk("%s", output); | 62 | printk("%s", output); |
59 | kfree(output); | 63 | kfree(output); |
@@ -115,13 +119,15 @@ static int etap_tramp(char *dev, char *gate, int control_me, | |||
115 | pe_data.data_me = data_me; | 119 | pe_data.data_me = data_me; |
116 | pid = run_helper(etap_pre_exec, &pe_data, args, NULL); | 120 | pid = run_helper(etap_pre_exec, &pe_data, args, NULL); |
117 | 121 | ||
118 | if(pid < 0) err = pid; | 122 | if(pid < 0) |
123 | err = pid; | ||
119 | os_close_file(data_remote); | 124 | os_close_file(data_remote); |
120 | os_close_file(control_remote); | 125 | os_close_file(control_remote); |
121 | n = os_read_file(control_me, &c, sizeof(c)); | 126 | CATCH_EINTR(n = read(control_me, &c, sizeof(c))); |
122 | if(n != sizeof(c)){ | 127 | if(n != sizeof(c)){ |
123 | printk("etap_tramp : read of status failed, err = %d\n", -n); | 128 | err = -errno; |
124 | return(-EINVAL); | 129 | printk("etap_tramp : read of status failed, err = %d\n", -err); |
130 | return err; | ||
125 | } | 131 | } |
126 | if(c != 1){ | 132 | if(c != 1){ |
127 | printk("etap_tramp : uml_net failed\n"); | 133 | printk("etap_tramp : uml_net failed\n"); |
@@ -132,7 +138,7 @@ static int etap_tramp(char *dev, char *gate, int control_me, | |||
132 | else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)) | 138 | else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)) |
133 | printk("uml_net didn't exit with status 1\n"); | 139 | printk("uml_net didn't exit with status 1\n"); |
134 | } | 140 | } |
135 | return(err); | 141 | return err; |
136 | } | 142 | } |
137 | 143 | ||
138 | static int etap_open(void *data) | 144 | static int etap_open(void *data) |
@@ -142,23 +148,24 @@ static int etap_open(void *data) | |||
142 | int data_fds[2], control_fds[2], err, output_len; | 148 | int data_fds[2], control_fds[2], err, output_len; |
143 | 149 | ||
144 | err = tap_open_common(pri->dev, pri->gate_addr); | 150 | err = tap_open_common(pri->dev, pri->gate_addr); |
145 | if(err) return(err); | 151 | if(err) |
152 | return err; | ||
146 | 153 | ||
147 | err = os_pipe(data_fds, 0, 0); | 154 | err = os_pipe(data_fds, 0, 0); |
148 | if(err < 0){ | 155 | if(err < 0){ |
149 | printk("data os_pipe failed - err = %d\n", -err); | 156 | printk("data os_pipe failed - err = %d\n", -err); |
150 | return(err); | 157 | return err; |
151 | } | 158 | } |
152 | 159 | ||
153 | err = os_pipe(control_fds, 1, 0); | 160 | err = os_pipe(control_fds, 1, 0); |
154 | if(err < 0){ | 161 | if(err < 0){ |
155 | printk("control os_pipe failed - err = %d\n", -err); | 162 | printk("control os_pipe failed - err = %d\n", -err); |
156 | return(err); | 163 | return err; |
157 | } | 164 | } |
158 | 165 | ||
159 | err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], | 166 | err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], |
160 | control_fds[1], data_fds[0], data_fds[1]); | 167 | control_fds[1], data_fds[0], data_fds[1]); |
161 | output_len = page_size(); | 168 | output_len = UM_KERN_PAGE_SIZE; |
162 | output = um_kmalloc(output_len); | 169 | output = um_kmalloc(output_len); |
163 | read_output(control_fds[0], output, output_len); | 170 | read_output(control_fds[0], output, output_len); |
164 | 171 | ||
@@ -171,13 +178,13 @@ static int etap_open(void *data) | |||
171 | 178 | ||
172 | if(err < 0){ | 179 | if(err < 0){ |
173 | printk("etap_tramp failed - err = %d\n", -err); | 180 | printk("etap_tramp failed - err = %d\n", -err); |
174 | return(err); | 181 | return err; |
175 | } | 182 | } |
176 | 183 | ||
177 | pri->data_fd = data_fds[0]; | 184 | pri->data_fd = data_fds[0]; |
178 | pri->control_fd = control_fds[0]; | 185 | pri->control_fd = control_fds[0]; |
179 | iter_addresses(pri->dev, etap_open_addr, &pri->control_fd); | 186 | iter_addresses(pri->dev, etap_open_addr, &pri->control_fd); |
180 | return(data_fds[0]); | 187 | return data_fds[0]; |
181 | } | 188 | } |
182 | 189 | ||
183 | static void etap_close(int fd, void *data) | 190 | static void etap_close(int fd, void *data) |
@@ -195,7 +202,7 @@ static void etap_close(int fd, void *data) | |||
195 | 202 | ||
196 | static int etap_set_mtu(int mtu, void *data) | 203 | static int etap_set_mtu(int mtu, void *data) |
197 | { | 204 | { |
198 | return(mtu); | 205 | return mtu; |
199 | } | 206 | } |
200 | 207 | ||
201 | static void etap_add_addr(unsigned char *addr, unsigned char *netmask, | 208 | static void etap_add_addr(unsigned char *addr, unsigned char *netmask, |
@@ -204,7 +211,8 @@ static void etap_add_addr(unsigned char *addr, unsigned char *netmask, | |||
204 | struct ethertap_data *pri = data; | 211 | struct ethertap_data *pri = data; |
205 | 212 | ||
206 | tap_check_ips(pri->gate_addr, addr); | 213 | tap_check_ips(pri->gate_addr, addr); |
207 | if(pri->control_fd == -1) return; | 214 | if(pri->control_fd == -1) |
215 | return; | ||
208 | etap_open_addr(addr, netmask, &pri->control_fd); | 216 | etap_open_addr(addr, netmask, &pri->control_fd); |
209 | } | 217 | } |
210 | 218 | ||
@@ -213,7 +221,8 @@ static void etap_del_addr(unsigned char *addr, unsigned char *netmask, | |||
213 | { | 221 | { |
214 | struct ethertap_data *pri = data; | 222 | struct ethertap_data *pri = data; |
215 | 223 | ||
216 | if(pri->control_fd == -1) return; | 224 | if(pri->control_fd == -1) |
225 | return; | ||
217 | etap_close_addr(addr, netmask, &pri->control_fd); | 226 | etap_close_addr(addr, netmask, &pri->control_fd); |
218 | } | 227 | } |
219 | 228 | ||
@@ -227,14 +236,3 @@ const struct net_user_info ethertap_user_info = { | |||
227 | .delete_address = etap_del_addr, | 236 | .delete_address = etap_del_addr, |
228 | .max_packet = MAX_PACKET - ETH_HEADER_ETHERTAP | 237 | .max_packet = MAX_PACKET - ETH_HEADER_ETHERTAP |
229 | }; | 238 | }; |
230 | |||
231 | /* | ||
232 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
233 | * Emacs will notice this stuff at the end of the file and automatically | ||
234 | * adjust the settings for this buffer only. This must remain at the end | ||
235 | * of the file. | ||
236 | * --------------------------------------------------------------------------- | ||
237 | * Local variables: | ||
238 | * c-file-style: "linux" | ||
239 | * End: | ||
240 | */ | ||
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c index e846b23f7558..11a9779dc9f1 100644 --- a/arch/um/os-Linux/drivers/tuntap_user.c +++ b/arch/um/os-Linux/drivers/tuntap_user.c | |||
@@ -18,17 +18,17 @@ | |||
18 | #include "net_user.h" | 18 | #include "net_user.h" |
19 | #include "tuntap.h" | 19 | #include "tuntap.h" |
20 | #include "kern_util.h" | 20 | #include "kern_util.h" |
21 | #include "user_util.h" | ||
22 | #include "user.h" | 21 | #include "user.h" |
23 | #include "os.h" | 22 | #include "os.h" |
24 | 23 | ||
25 | #define MAX_PACKET ETH_MAX_PACKET | 24 | #define MAX_PACKET ETH_MAX_PACKET |
26 | 25 | ||
27 | void tuntap_user_init(void *data, void *dev) | 26 | static int tuntap_user_init(void *data, void *dev) |
28 | { | 27 | { |
29 | struct tuntap_data *pri = data; | 28 | struct tuntap_data *pri = data; |
30 | 29 | ||
31 | pri->dev = dev; | 30 | pri->dev = dev; |
31 | return 0; | ||
32 | } | 32 | } |
33 | 33 | ||
34 | static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask, | 34 | static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask, |
@@ -37,7 +37,8 @@ static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask, | |||
37 | struct tuntap_data *pri = data; | 37 | struct tuntap_data *pri = data; |
38 | 38 | ||
39 | tap_check_ips(pri->gate_addr, addr); | 39 | tap_check_ips(pri->gate_addr, addr); |
40 | if((pri->fd == -1) || pri->fixed_config) return; | 40 | if((pri->fd == -1) || pri->fixed_config) |
41 | return; | ||
41 | open_addr(addr, netmask, pri->dev_name); | 42 | open_addr(addr, netmask, pri->dev_name); |
42 | } | 43 | } |
43 | 44 | ||
@@ -46,7 +47,8 @@ static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask, | |||
46 | { | 47 | { |
47 | struct tuntap_data *pri = data; | 48 | struct tuntap_data *pri = data; |
48 | 49 | ||
49 | if((pri->fd == -1) || pri->fixed_config) return; | 50 | if((pri->fd == -1) || pri->fixed_config) |
51 | return; | ||
50 | close_addr(addr, netmask, pri->dev_name); | 52 | close_addr(addr, netmask, pri->dev_name); |
51 | } | 53 | } |
52 | 54 | ||
@@ -58,7 +60,7 @@ struct tuntap_pre_exec_data { | |||
58 | static void tuntap_pre_exec(void *arg) | 60 | static void tuntap_pre_exec(void *arg) |
59 | { | 61 | { |
60 | struct tuntap_pre_exec_data *data = arg; | 62 | struct tuntap_pre_exec_data *data = arg; |
61 | 63 | ||
62 | dup2(data->stdout, 1); | 64 | dup2(data->stdout, 1); |
63 | os_close_file(data->close_me); | 65 | os_close_file(data->close_me); |
64 | } | 66 | } |
@@ -83,7 +85,8 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, | |||
83 | 85 | ||
84 | pid = run_helper(tuntap_pre_exec, &data, argv, NULL); | 86 | pid = run_helper(tuntap_pre_exec, &data, argv, NULL); |
85 | 87 | ||
86 | if(pid < 0) return(-pid); | 88 | if(pid < 0) |
89 | return -pid; | ||
87 | 90 | ||
88 | os_close_file(remote); | 91 | os_close_file(remote); |
89 | 92 | ||
@@ -114,16 +117,16 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, | |||
114 | cmsg = CMSG_FIRSTHDR(&msg); | 117 | cmsg = CMSG_FIRSTHDR(&msg); |
115 | if(cmsg == NULL){ | 118 | if(cmsg == NULL){ |
116 | printk("tuntap_open_tramp : didn't receive a message\n"); | 119 | printk("tuntap_open_tramp : didn't receive a message\n"); |
117 | return(-EINVAL); | 120 | return -EINVAL; |
118 | } | 121 | } |
119 | if((cmsg->cmsg_level != SOL_SOCKET) || | 122 | if((cmsg->cmsg_level != SOL_SOCKET) || |
120 | (cmsg->cmsg_type != SCM_RIGHTS)){ | 123 | (cmsg->cmsg_type != SCM_RIGHTS)){ |
121 | printk("tuntap_open_tramp : didn't receive a descriptor\n"); | 124 | printk("tuntap_open_tramp : didn't receive a descriptor\n"); |
122 | return(-EINVAL); | 125 | return -EINVAL; |
123 | } | 126 | } |
124 | *fd_out = ((int *) CMSG_DATA(cmsg))[0]; | 127 | *fd_out = ((int *) CMSG_DATA(cmsg))[0]; |
125 | os_set_exec_close(*fd_out, 1); | 128 | os_set_exec_close(*fd_out, 1); |
126 | return(0); | 129 | return 0; |
127 | } | 130 | } |
128 | 131 | ||
129 | static int tuntap_open(void *data) | 132 | static int tuntap_open(void *data) |
@@ -135,7 +138,7 @@ static int tuntap_open(void *data) | |||
135 | 138 | ||
136 | err = tap_open_common(pri->dev, pri->gate_addr); | 139 | err = tap_open_common(pri->dev, pri->gate_addr); |
137 | if(err < 0) | 140 | if(err < 0) |
138 | return(err); | 141 | return err; |
139 | 142 | ||
140 | if(pri->fixed_config){ | 143 | if(pri->fixed_config){ |
141 | pri->fd = os_open_file("/dev/net/tun", | 144 | pri->fd = os_open_file("/dev/net/tun", |
@@ -143,7 +146,7 @@ static int tuntap_open(void *data) | |||
143 | if(pri->fd < 0){ | 146 | if(pri->fd < 0){ |
144 | printk("Failed to open /dev/net/tun, err = %d\n", | 147 | printk("Failed to open /dev/net/tun, err = %d\n", |
145 | -pri->fd); | 148 | -pri->fd); |
146 | return(pri->fd); | 149 | return pri->fd; |
147 | } | 150 | } |
148 | memset(&ifr, 0, sizeof(ifr)); | 151 | memset(&ifr, 0, sizeof(ifr)); |
149 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI; | 152 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI; |
@@ -160,7 +163,7 @@ static int tuntap_open(void *data) | |||
160 | if(err < 0){ | 163 | if(err < 0){ |
161 | printk("tuntap_open : os_pipe failed - err = %d\n", | 164 | printk("tuntap_open : os_pipe failed - err = %d\n", |
162 | -err); | 165 | -err); |
163 | return(err); | 166 | return err; |
164 | } | 167 | } |
165 | 168 | ||
166 | buffer = get_output_buffer(&len); | 169 | buffer = get_output_buffer(&len); |
@@ -175,7 +178,7 @@ static int tuntap_open(void *data) | |||
175 | printk("%s", output); | 178 | printk("%s", output); |
176 | free_output_buffer(buffer); | 179 | free_output_buffer(buffer); |
177 | printk("tuntap_open_tramp failed - err = %d\n", -err); | 180 | printk("tuntap_open_tramp failed - err = %d\n", -err); |
178 | return(err); | 181 | return err; |
179 | } | 182 | } |
180 | 183 | ||
181 | pri->dev_name = uml_strdup(buffer); | 184 | pri->dev_name = uml_strdup(buffer); |
@@ -187,7 +190,7 @@ static int tuntap_open(void *data) | |||
187 | iter_addresses(pri->dev, open_addr, pri->dev_name); | 190 | iter_addresses(pri->dev, open_addr, pri->dev_name); |
188 | } | 191 | } |
189 | 192 | ||
190 | return(pri->fd); | 193 | return pri->fd; |
191 | } | 194 | } |
192 | 195 | ||
193 | static void tuntap_close(int fd, void *data) | 196 | static void tuntap_close(int fd, void *data) |
@@ -202,7 +205,7 @@ static void tuntap_close(int fd, void *data) | |||
202 | 205 | ||
203 | static int tuntap_set_mtu(int mtu, void *data) | 206 | static int tuntap_set_mtu(int mtu, void *data) |
204 | { | 207 | { |
205 | return(mtu); | 208 | return mtu; |
206 | } | 209 | } |
207 | 210 | ||
208 | const struct net_user_info tuntap_user_info = { | 211 | const struct net_user_info tuntap_user_info = { |
@@ -215,14 +218,3 @@ const struct net_user_info tuntap_user_info = { | |||
215 | .delete_address = tuntap_del_addr, | 218 | .delete_address = tuntap_del_addr, |
216 | .max_packet = MAX_PACKET | 219 | .max_packet = MAX_PACKET |
217 | }; | 220 | }; |
218 | |||
219 | /* | ||
220 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
221 | * Emacs will notice this stuff at the end of the file and automatically | ||
222 | * adjust the settings for this buffer only. This must remain at the end | ||
223 | * of the file. | ||
224 | * --------------------------------------------------------------------------- | ||
225 | * Local variables: | ||
226 | * c-file-style: "linux" | ||
227 | * End: | ||
228 | */ | ||
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c index 371b4335f46d..6f92f732d253 100644 --- a/arch/um/os-Linux/file.c +++ b/arch/um/os-Linux/file.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include "os.h" | 18 | #include "os.h" |
19 | #include "user.h" | 19 | #include "user.h" |
20 | #include "kern_util.h" | 20 | #include "kern_util.h" |
21 | #include "user_util.h" | ||
22 | 21 | ||
23 | static void copy_stat(struct uml_stat *dst, struct stat64 *src) | 22 | static void copy_stat(struct uml_stat *dst, struct stat64 *src) |
24 | { | 23 | { |
@@ -291,54 +290,22 @@ int os_seek_file(int fd, __u64 offset) | |||
291 | return 0; | 290 | return 0; |
292 | } | 291 | } |
293 | 292 | ||
294 | static int fault_buffer(void *start, int len, | 293 | int os_read_file(int fd, void *buf, int len) |
295 | int (*copy_proc)(void *addr, void *buf, int len)) | ||
296 | { | ||
297 | int page = getpagesize(), i; | ||
298 | char c; | ||
299 | |||
300 | for(i = 0; i < len; i += page){ | ||
301 | if((*copy_proc)(start + i, &c, sizeof(c))) | ||
302 | return -EFAULT; | ||
303 | } | ||
304 | if((len % page) != 0){ | ||
305 | if((*copy_proc)(start + len - 1, &c, sizeof(c))) | ||
306 | return -EFAULT; | ||
307 | } | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | static int file_io(int fd, void *buf, int len, | ||
312 | int (*io_proc)(int fd, void *buf, int len), | ||
313 | int (*copy_user_proc)(void *addr, void *buf, int len)) | ||
314 | { | 294 | { |
315 | int n, err; | 295 | int n = read(fd, buf, len); |
316 | |||
317 | do { | ||
318 | n = (*io_proc)(fd, buf, len); | ||
319 | if((n < 0) && (errno == EFAULT)){ | ||
320 | err = fault_buffer(buf, len, copy_user_proc); | ||
321 | if(err) | ||
322 | return err; | ||
323 | n = (*io_proc)(fd, buf, len); | ||
324 | } | ||
325 | } while((n < 0) && (errno == EINTR)); | ||
326 | 296 | ||
327 | if(n < 0) | 297 | if(n < 0) |
328 | return -errno; | 298 | return -errno; |
329 | return n; | 299 | return n; |
330 | } | 300 | } |
331 | 301 | ||
332 | int os_read_file(int fd, void *buf, int len) | ||
333 | { | ||
334 | return file_io(fd, buf, len, (int (*)(int, void *, int)) read, | ||
335 | copy_from_user_proc); | ||
336 | } | ||
337 | |||
338 | int os_write_file(int fd, const void *buf, int len) | 302 | int os_write_file(int fd, const void *buf, int len) |
339 | { | 303 | { |
340 | return file_io(fd, (void *) buf, len, | 304 | int n = write(fd, (void *) buf, len); |
341 | (int (*)(int, void *, int)) write, copy_to_user_proc); | 305 | |
306 | if(n < 0) | ||
307 | return -errno; | ||
308 | return n; | ||
342 | } | 309 | } |
343 | 310 | ||
344 | int os_file_size(char *file, unsigned long long *size_out) | 311 | int os_file_size(char *file, unsigned long long *size_out) |
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index c7ad6306e22f..97bed16bf4c7 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c | |||
@@ -13,9 +13,9 @@ | |||
13 | #include <sys/wait.h> | 13 | #include <sys/wait.h> |
14 | #include "user.h" | 14 | #include "user.h" |
15 | #include "kern_util.h" | 15 | #include "kern_util.h" |
16 | #include "user_util.h" | ||
17 | #include "os.h" | 16 | #include "os.h" |
18 | #include "um_malloc.h" | 17 | #include "um_malloc.h" |
18 | #include "kern_constants.h" | ||
19 | 19 | ||
20 | struct helper_data { | 20 | struct helper_data { |
21 | void (*pre_exec)(void*); | 21 | void (*pre_exec)(void*); |
@@ -25,28 +25,18 @@ struct helper_data { | |||
25 | char *buf; | 25 | char *buf; |
26 | }; | 26 | }; |
27 | 27 | ||
28 | /* Debugging aid, changed only from gdb */ | ||
29 | int helper_pause = 0; | ||
30 | |||
31 | static void helper_hup(int sig) | ||
32 | { | ||
33 | } | ||
34 | |||
35 | static int helper_child(void *arg) | 28 | static int helper_child(void *arg) |
36 | { | 29 | { |
37 | struct helper_data *data = arg; | 30 | struct helper_data *data = arg; |
38 | char **argv = data->argv; | 31 | char **argv = data->argv; |
39 | int errval; | 32 | int errval; |
40 | 33 | ||
41 | if (helper_pause){ | ||
42 | signal(SIGHUP, helper_hup); | ||
43 | pause(); | ||
44 | } | ||
45 | if (data->pre_exec != NULL) | 34 | if (data->pre_exec != NULL) |
46 | (*data->pre_exec)(data->pre_data); | 35 | (*data->pre_exec)(data->pre_data); |
47 | errval = execvp_noalloc(data->buf, argv[0], argv); | 36 | errval = execvp_noalloc(data->buf, argv[0], argv); |
48 | printk("helper_child - execvp of '%s' failed - errno = %d\n", argv[0], -errval); | 37 | printk("helper_child - execvp of '%s' failed - errno = %d\n", argv[0], |
49 | os_write_file(data->fd, &errval, sizeof(errval)); | 38 | -errval); |
39 | write(data->fd, &errval, sizeof(errval)); | ||
50 | kill(os_getpid(), SIGKILL); | 40 | kill(os_getpid(), SIGKILL); |
51 | return 0; | 41 | return 0; |
52 | } | 42 | } |
@@ -81,7 +71,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, | |||
81 | goto out_close; | 71 | goto out_close; |
82 | } | 72 | } |
83 | 73 | ||
84 | sp = stack + page_size() - sizeof(void *); | 74 | sp = stack + UM_KERN_PAGE_SIZE - sizeof(void *); |
85 | data.pre_exec = pre_exec; | 75 | data.pre_exec = pre_exec; |
86 | data.pre_data = pre_data; | 76 | data.pre_data = pre_data; |
87 | data.argv = argv; | 77 | data.argv = argv; |
@@ -98,13 +88,16 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, | |||
98 | close(fds[1]); | 88 | close(fds[1]); |
99 | fds[1] = -1; | 89 | fds[1] = -1; |
100 | 90 | ||
101 | /* Read the errno value from the child, if the exec failed, or get 0 if | 91 | /* |
102 | * the exec succeeded because the pipe fd was set as close-on-exec. */ | 92 | * Read the errno value from the child, if the exec failed, or get 0 if |
103 | n = os_read_file(fds[0], &ret, sizeof(ret)); | 93 | * the exec succeeded because the pipe fd was set as close-on-exec. |
94 | */ | ||
95 | n = read(fds[0], &ret, sizeof(ret)); | ||
104 | if (n == 0) { | 96 | if (n == 0) { |
105 | ret = pid; | 97 | ret = pid; |
106 | } else { | 98 | } else { |
107 | if (n < 0) { | 99 | if (n < 0) { |
100 | n = -errno; | ||
108 | printk("run_helper : read on pipe failed, ret = %d\n", | 101 | printk("run_helper : read on pipe failed, ret = %d\n", |
109 | -n); | 102 | -n); |
110 | ret = n; | 103 | ret = n; |
@@ -135,7 +128,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, | |||
135 | if (stack == 0) | 128 | if (stack == 0) |
136 | return -ENOMEM; | 129 | return -ENOMEM; |
137 | 130 | ||
138 | sp = stack + (page_size() << stack_order) - sizeof(void *); | 131 | sp = stack + (UM_KERN_PAGE_SIZE << stack_order) - sizeof(void *); |
139 | pid = clone(proc, (void *) sp, flags | SIGCHLD, arg); | 132 | pid = clone(proc, (void *) sp, flags | SIGCHLD, arg); |
140 | if (pid < 0) { | 133 | if (pid < 0) { |
141 | err = -errno; | 134 | err = -errno; |
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c index d1b61d474e0a..a633fa8e0a94 100644 --- a/arch/um/os-Linux/irq.c +++ b/arch/um/os-Linux/irq.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <sys/poll.h> | 11 | #include <sys/poll.h> |
12 | #include <sys/types.h> | 12 | #include <sys/types.h> |
13 | #include <sys/time.h> | 13 | #include <sys/time.h> |
14 | #include "user_util.h" | ||
15 | #include "kern_util.h" | 14 | #include "kern_util.h" |
16 | #include "user.h" | 15 | #include "user.h" |
17 | #include "process.h" | 16 | #include "process.h" |
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index 685feaab65d2..ea9a23696f36 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c | |||
@@ -13,8 +13,8 @@ | |||
13 | #include <sys/mman.h> | 13 | #include <sys/mman.h> |
14 | #include <sys/user.h> | 14 | #include <sys/user.h> |
15 | #include <asm/page.h> | 15 | #include <asm/page.h> |
16 | #include "user_util.h" | ||
17 | #include "kern_util.h" | 16 | #include "kern_util.h" |
17 | #include "as-layout.h" | ||
18 | #include "mem_user.h" | 18 | #include "mem_user.h" |
19 | #include "irq_user.h" | 19 | #include "irq_user.h" |
20 | #include "user.h" | 20 | #include "user.h" |
@@ -25,12 +25,7 @@ | |||
25 | #include "os.h" | 25 | #include "os.h" |
26 | #include "um_malloc.h" | 26 | #include "um_malloc.h" |
27 | 27 | ||
28 | /* Set in set_stklim, which is called from main and __wrap_malloc. | 28 | /* Set in main, unchanged thereafter */ |
29 | * __wrap_malloc only calls it if main hasn't started. | ||
30 | */ | ||
31 | unsigned long stacksizelim; | ||
32 | |||
33 | /* Set in main */ | ||
34 | char *linux_prog; | 29 | char *linux_prog; |
35 | 30 | ||
36 | #define PGD_BOUND (4 * 1024 * 1024) | 31 | #define PGD_BOUND (4 * 1024 * 1024) |
@@ -52,7 +47,6 @@ static void set_stklim(void) | |||
52 | exit(1); | 47 | exit(1); |
53 | } | 48 | } |
54 | } | 49 | } |
55 | stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1); | ||
56 | } | 50 | } |
57 | 51 | ||
58 | static __init void do_uml_initcalls(void) | 52 | static __init void do_uml_initcalls(void) |
@@ -126,7 +120,7 @@ extern int uml_exitcode; | |||
126 | 120 | ||
127 | extern void scan_elf_aux( char **envp); | 121 | extern void scan_elf_aux( char **envp); |
128 | 122 | ||
129 | int main(int argc, char **argv, char **envp) | 123 | int __init main(int argc, char **argv, char **envp) |
130 | { | 124 | { |
131 | char **new_argv; | 125 | char **new_argv; |
132 | int ret, i, err; | 126 | int ret, i, err; |
@@ -224,7 +218,7 @@ int main(int argc, char **argv, char **envp) | |||
224 | ret = 1; | 218 | ret = 1; |
225 | } | 219 | } |
226 | printf("\n"); | 220 | printf("\n"); |
227 | return(uml_exitcode); | 221 | return uml_exitcode; |
228 | } | 222 | } |
229 | 223 | ||
230 | #define CAN_KMALLOC() \ | 224 | #define CAN_KMALLOC() \ |
@@ -237,7 +231,7 @@ void *__wrap_malloc(int size) | |||
237 | void *ret; | 231 | void *ret; |
238 | 232 | ||
239 | if(!CAN_KMALLOC()) | 233 | if(!CAN_KMALLOC()) |
240 | return(__real_malloc(size)); | 234 | return __real_malloc(size); |
241 | else if(size <= PAGE_SIZE) /* finding contiguos pages can be hard*/ | 235 | else if(size <= PAGE_SIZE) /* finding contiguos pages can be hard*/ |
242 | ret = um_kmalloc(size); | 236 | ret = um_kmalloc(size); |
243 | else ret = um_vmalloc(size); | 237 | else ret = um_vmalloc(size); |
@@ -248,16 +242,17 @@ void *__wrap_malloc(int size) | |||
248 | if(ret == NULL) | 242 | if(ret == NULL) |
249 | errno = ENOMEM; | 243 | errno = ENOMEM; |
250 | 244 | ||
251 | return(ret); | 245 | return ret; |
252 | } | 246 | } |
253 | 247 | ||
254 | void *__wrap_calloc(int n, int size) | 248 | void *__wrap_calloc(int n, int size) |
255 | { | 249 | { |
256 | void *ptr = __wrap_malloc(n * size); | 250 | void *ptr = __wrap_malloc(n * size); |
257 | 251 | ||
258 | if(ptr == NULL) return(NULL); | 252 | if(ptr == NULL) |
253 | return NULL; | ||
259 | memset(ptr, 0, n * size); | 254 | memset(ptr, 0, n * size); |
260 | return(ptr); | 255 | return ptr; |
261 | } | 256 | } |
262 | 257 | ||
263 | extern void __real_free(void *); | 258 | extern void __real_free(void *); |
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index f1ea169db85e..c6378c6d10d2 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <sys/statfs.h> | 11 | #include <sys/statfs.h> |
12 | #include "kern_util.h" | 12 | #include "kern_util.h" |
13 | #include "user.h" | 13 | #include "user.h" |
14 | #include "user_util.h" | ||
15 | #include "mem_user.h" | 14 | #include "mem_user.h" |
16 | #include "init.h" | 15 | #include "init.h" |
17 | #include "os.h" | 16 | #include "os.h" |
@@ -165,7 +164,8 @@ found: | |||
165 | * (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger). | 164 | * (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger). |
166 | * So it isn't 'static' yet. | 165 | * So it isn't 'static' yet. |
167 | */ | 166 | */ |
168 | int make_tempfile(const char *template, char **out_tempname, int do_unlink) | 167 | int __init make_tempfile(const char *template, char **out_tempname, |
168 | int do_unlink) | ||
169 | { | 169 | { |
170 | char *tempname; | 170 | char *tempname; |
171 | int fd; | 171 | int fd; |
@@ -206,7 +206,7 @@ out: | |||
206 | * This proc is used in start_up.c | 206 | * This proc is used in start_up.c |
207 | * So it isn't 'static'. | 207 | * So it isn't 'static'. |
208 | */ | 208 | */ |
209 | int create_tmp_file(unsigned long long len) | 209 | int __init create_tmp_file(unsigned long long len) |
210 | { | 210 | { |
211 | int fd, err; | 211 | int fd, err; |
212 | char zero; | 212 | char zero; |
@@ -232,17 +232,16 @@ int create_tmp_file(unsigned long long len) | |||
232 | 232 | ||
233 | zero = 0; | 233 | zero = 0; |
234 | 234 | ||
235 | err = os_write_file(fd, &zero, 1); | 235 | err = write(fd, &zero, 1); |
236 | if(err != 1){ | 236 | if(err != 1){ |
237 | errno = -err; | 237 | perror("write"); |
238 | perror("os_write_file"); | ||
239 | exit(1); | 238 | exit(1); |
240 | } | 239 | } |
241 | 240 | ||
242 | return fd; | 241 | return fd; |
243 | } | 242 | } |
244 | 243 | ||
245 | int create_mem_file(unsigned long long len) | 244 | int __init create_mem_file(unsigned long long len) |
246 | { | 245 | { |
247 | int err, fd; | 246 | int err, fd; |
248 | 247 | ||
@@ -257,7 +256,7 @@ int create_mem_file(unsigned long long len) | |||
257 | } | 256 | } |
258 | 257 | ||
259 | 258 | ||
260 | void check_tmpexec(void) | 259 | void __init check_tmpexec(void) |
261 | { | 260 | { |
262 | void *addr; | 261 | void *addr; |
263 | int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE); | 262 | int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE); |
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index 76bdd6712417..92a7b59120d6 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include "ptrace_user.h" | 14 | #include "ptrace_user.h" |
15 | #include "os.h" | 15 | #include "os.h" |
16 | #include "user.h" | 16 | #include "user.h" |
17 | #include "user_util.h" | ||
18 | #include "process.h" | 17 | #include "process.h" |
19 | #include "irq_user.h" | 18 | #include "irq_user.h" |
20 | #include "kern_util.h" | 19 | #include "kern_util.h" |
@@ -22,6 +21,7 @@ | |||
22 | #include "skas_ptrace.h" | 21 | #include "skas_ptrace.h" |
23 | #include "kern_constants.h" | 22 | #include "kern_constants.h" |
24 | #include "uml-config.h" | 23 | #include "uml-config.h" |
24 | #include "init.h" | ||
25 | 25 | ||
26 | #define ARBITRARY_ADDR -1 | 26 | #define ARBITRARY_ADDR -1 |
27 | #define FAILURE_PID -1 | 27 | #define FAILURE_PID -1 |
@@ -40,14 +40,14 @@ unsigned long os_process_pc(int pid) | |||
40 | if(fd < 0){ | 40 | if(fd < 0){ |
41 | printk("os_process_pc - couldn't open '%s', err = %d\n", | 41 | printk("os_process_pc - couldn't open '%s', err = %d\n", |
42 | proc_stat, -fd); | 42 | proc_stat, -fd); |
43 | return(ARBITRARY_ADDR); | 43 | return ARBITRARY_ADDR; |
44 | } | 44 | } |
45 | err = os_read_file(fd, buf, sizeof(buf)); | 45 | CATCH_EINTR(err = read(fd, buf, sizeof(buf))); |
46 | if(err < 0){ | 46 | if(err < 0){ |
47 | printk("os_process_pc - couldn't read '%s', err = %d\n", | 47 | printk("os_process_pc - couldn't read '%s', err = %d\n", |
48 | proc_stat, -err); | 48 | proc_stat, errno); |
49 | os_close_file(fd); | 49 | os_close_file(fd); |
50 | return(ARBITRARY_ADDR); | 50 | return ARBITRARY_ADDR; |
51 | } | 51 | } |
52 | os_close_file(fd); | 52 | os_close_file(fd); |
53 | pc = ARBITRARY_ADDR; | 53 | pc = ARBITRARY_ADDR; |
@@ -56,7 +56,7 @@ unsigned long os_process_pc(int pid) | |||
56 | "%*d %*d %*d %*d %*d %lu", &pc) != 1){ | 56 | "%*d %*d %*d %*d %*d %lu", &pc) != 1){ |
57 | printk("os_process_pc - couldn't find pc in '%s'\n", buf); | 57 | printk("os_process_pc - couldn't find pc in '%s'\n", buf); |
58 | } | 58 | } |
59 | return(pc); | 59 | return pc; |
60 | } | 60 | } |
61 | 61 | ||
62 | int os_process_parent(int pid) | 62 | int os_process_parent(int pid) |
@@ -65,21 +65,22 @@ int os_process_parent(int pid) | |||
65 | char data[256]; | 65 | char data[256]; |
66 | int parent, n, fd; | 66 | int parent, n, fd; |
67 | 67 | ||
68 | if(pid == -1) return(-1); | 68 | if(pid == -1) |
69 | return -1; | ||
69 | 70 | ||
70 | snprintf(stat, sizeof(stat), "/proc/%d/stat", pid); | 71 | snprintf(stat, sizeof(stat), "/proc/%d/stat", pid); |
71 | fd = os_open_file(stat, of_read(OPENFLAGS()), 0); | 72 | fd = os_open_file(stat, of_read(OPENFLAGS()), 0); |
72 | if(fd < 0){ | 73 | if(fd < 0){ |
73 | printk("Couldn't open '%s', err = %d\n", stat, -fd); | 74 | printk("Couldn't open '%s', err = %d\n", stat, -fd); |
74 | return(FAILURE_PID); | 75 | return FAILURE_PID; |
75 | } | 76 | } |
76 | 77 | ||
77 | n = os_read_file(fd, data, sizeof(data)); | 78 | CATCH_EINTR(n = read(fd, data, sizeof(data))); |
78 | os_close_file(fd); | 79 | os_close_file(fd); |
79 | 80 | ||
80 | if(n < 0){ | 81 | if(n < 0){ |
81 | printk("Couldn't read '%s', err = %d\n", stat, -n); | 82 | printk("Couldn't read '%s', err = %d\n", stat, errno); |
82 | return(FAILURE_PID); | 83 | return FAILURE_PID; |
83 | } | 84 | } |
84 | 85 | ||
85 | parent = FAILURE_PID; | 86 | parent = FAILURE_PID; |
@@ -87,7 +88,7 @@ int os_process_parent(int pid) | |||
87 | if(n != 1) | 88 | if(n != 1) |
88 | printk("Failed to scan '%s'\n", data); | 89 | printk("Failed to scan '%s'\n", data); |
89 | 90 | ||
90 | return(parent); | 91 | return parent; |
91 | } | 92 | } |
92 | 93 | ||
93 | void os_stop_process(int pid) | 94 | void os_stop_process(int pid) |
@@ -145,7 +146,7 @@ void os_usr1_process(int pid) | |||
145 | 146 | ||
146 | int os_getpid(void) | 147 | int os_getpid(void) |
147 | { | 148 | { |
148 | return(syscall(__NR_getpid)); | 149 | return syscall(__NR_getpid); |
149 | } | 150 | } |
150 | 151 | ||
151 | int os_getpgrp(void) | 152 | int os_getpgrp(void) |
@@ -165,8 +166,8 @@ int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, | |||
165 | loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, | 166 | loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, |
166 | fd, off); | 167 | fd, off); |
167 | if(loc == MAP_FAILED) | 168 | if(loc == MAP_FAILED) |
168 | return(-errno); | 169 | return -errno; |
169 | return(0); | 170 | return 0; |
170 | } | 171 | } |
171 | 172 | ||
172 | int os_protect_memory(void *addr, unsigned long len, int r, int w, int x) | 173 | int os_protect_memory(void *addr, unsigned long len, int r, int w, int x) |
@@ -175,8 +176,8 @@ int os_protect_memory(void *addr, unsigned long len, int r, int w, int x) | |||
175 | (x ? PROT_EXEC : 0)); | 176 | (x ? PROT_EXEC : 0)); |
176 | 177 | ||
177 | if(mprotect(addr, len, prot) < 0) | 178 | if(mprotect(addr, len, prot) < 0) |
178 | return(-errno); | 179 | return -errno; |
179 | return(0); | 180 | return 0; |
180 | } | 181 | } |
181 | 182 | ||
182 | int os_unmap_memory(void *addr, int len) | 183 | int os_unmap_memory(void *addr, int len) |
@@ -185,15 +186,15 @@ int os_unmap_memory(void *addr, int len) | |||
185 | 186 | ||
186 | err = munmap(addr, len); | 187 | err = munmap(addr, len); |
187 | if(err < 0) | 188 | if(err < 0) |
188 | return(-errno); | 189 | return -errno; |
189 | return(0); | 190 | return 0; |
190 | } | 191 | } |
191 | 192 | ||
192 | #ifndef MADV_REMOVE | 193 | #ifndef MADV_REMOVE |
193 | #define MADV_REMOVE KERNEL_MADV_REMOVE | 194 | #define MADV_REMOVE KERNEL_MADV_REMOVE |
194 | #endif | 195 | #endif |
195 | 196 | ||
196 | int os_drop_memory(void *addr, int length) | 197 | int __init os_drop_memory(void *addr, int length) |
197 | { | 198 | { |
198 | int err; | 199 | int err; |
199 | 200 | ||
@@ -203,7 +204,7 @@ int os_drop_memory(void *addr, int length) | |||
203 | return err; | 204 | return err; |
204 | } | 205 | } |
205 | 206 | ||
206 | int can_drop_memory(void) | 207 | int __init can_drop_memory(void) |
207 | { | 208 | { |
208 | void *addr; | 209 | void *addr; |
209 | int fd, ok = 0; | 210 | int fd, ok = 0; |
@@ -244,7 +245,7 @@ void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)) | |||
244 | 245 | ||
245 | if(sig_stack != NULL){ | 246 | if(sig_stack != NULL){ |
246 | pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER); | 247 | pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER); |
247 | set_sigstack(sig_stack, pages * page_size()); | 248 | set_sigstack(sig_stack, pages * UM_KERN_PAGE_SIZE); |
248 | flags = SA_ONSTACK; | 249 | flags = SA_ONSTACK; |
249 | } | 250 | } |
250 | if(usr1_handler){ | 251 | if(usr1_handler){ |
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c index 3fc43b33db66..8d4e0c6b8c92 100644 --- a/arch/um/os-Linux/sigio.c +++ b/arch/um/os-Linux/sigio.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <termios.h> | 8 | #include <termios.h> |
9 | #include <pty.h> | 9 | #include <pty.h> |
10 | #include <signal.h> | 10 | #include <signal.h> |
11 | #include <fcntl.h> | ||
11 | #include <errno.h> | 12 | #include <errno.h> |
12 | #include <string.h> | 13 | #include <string.h> |
13 | #include <sched.h> | 14 | #include <sched.h> |
@@ -16,10 +17,10 @@ | |||
16 | #include "init.h" | 17 | #include "init.h" |
17 | #include "user.h" | 18 | #include "user.h" |
18 | #include "kern_util.h" | 19 | #include "kern_util.h" |
19 | #include "user_util.h" | ||
20 | #include "sigio.h" | 20 | #include "sigio.h" |
21 | #include "os.h" | 21 | #include "os.h" |
22 | #include "um_malloc.h" | 22 | #include "um_malloc.h" |
23 | #include "init.h" | ||
23 | 24 | ||
24 | /* Protected by sigio_lock(), also used by sigio_cleanup, which is an | 25 | /* Protected by sigio_lock(), also used by sigio_cleanup, which is an |
25 | * exitcall. | 26 | * exitcall. |
@@ -68,11 +69,12 @@ static int write_sigio_thread(void *unused) | |||
68 | p = &fds->poll[i]; | 69 | p = &fds->poll[i]; |
69 | if(p->revents == 0) continue; | 70 | if(p->revents == 0) continue; |
70 | if(p->fd == sigio_private[1]){ | 71 | if(p->fd == sigio_private[1]){ |
71 | n = os_read_file(sigio_private[1], &c, sizeof(c)); | 72 | CATCH_EINTR(n = read(sigio_private[1], &c, |
73 | sizeof(c))); | ||
72 | if(n != sizeof(c)) | 74 | if(n != sizeof(c)) |
73 | printk("write_sigio_thread : " | 75 | printk("write_sigio_thread : " |
74 | "read on socket failed, " | 76 | "read on socket failed, " |
75 | "err = %d\n", -n); | 77 | "err = %d\n", errno); |
76 | tmp = current_poll; | 78 | tmp = current_poll; |
77 | current_poll = next_poll; | 79 | current_poll = next_poll; |
78 | next_poll = tmp; | 80 | next_poll = tmp; |
@@ -85,10 +87,10 @@ static int write_sigio_thread(void *unused) | |||
85 | (fds->used - i) * sizeof(*fds->poll)); | 87 | (fds->used - i) * sizeof(*fds->poll)); |
86 | } | 88 | } |
87 | 89 | ||
88 | n = os_write_file(respond_fd, &c, sizeof(c)); | 90 | CATCH_EINTR(n = write(respond_fd, &c, sizeof(c))); |
89 | if(n != sizeof(c)) | 91 | if(n != sizeof(c)) |
90 | printk("write_sigio_thread : write on socket " | 92 | printk("write_sigio_thread : write on socket " |
91 | "failed, err = %d\n", -n); | 93 | "failed, err = %d\n", errno); |
92 | } | 94 | } |
93 | } | 95 | } |
94 | 96 | ||
@@ -126,15 +128,15 @@ static void update_thread(void) | |||
126 | char c; | 128 | char c; |
127 | 129 | ||
128 | flags = set_signals(0); | 130 | flags = set_signals(0); |
129 | n = os_write_file(sigio_private[0], &c, sizeof(c)); | 131 | n = write(sigio_private[0], &c, sizeof(c)); |
130 | if(n != sizeof(c)){ | 132 | if(n != sizeof(c)){ |
131 | printk("update_thread : write failed, err = %d\n", -n); | 133 | printk("update_thread : write failed, err = %d\n", errno); |
132 | goto fail; | 134 | goto fail; |
133 | } | 135 | } |
134 | 136 | ||
135 | n = os_read_file(sigio_private[0], &c, sizeof(c)); | 137 | CATCH_EINTR(n = read(sigio_private[0], &c, sizeof(c))); |
136 | if(n != sizeof(c)){ | 138 | if(n != sizeof(c)){ |
137 | printk("update_thread : read failed, err = %d\n", -n); | 139 | printk("update_thread : read failed, err = %d\n", errno); |
138 | goto fail; | 140 | goto fail; |
139 | } | 141 | } |
140 | 142 | ||
@@ -320,6 +322,10 @@ out_close1: | |||
320 | close(l_write_sigio_fds[1]); | 322 | close(l_write_sigio_fds[1]); |
321 | } | 323 | } |
322 | 324 | ||
325 | /* Changed during early boot */ | ||
326 | static int pty_output_sigio = 0; | ||
327 | static int pty_close_sigio = 0; | ||
328 | |||
323 | void maybe_sigio_broken(int fd, int read) | 329 | void maybe_sigio_broken(int fd, int read) |
324 | { | 330 | { |
325 | int err; | 331 | int err; |
@@ -357,3 +363,143 @@ static void sigio_cleanup(void) | |||
357 | } | 363 | } |
358 | 364 | ||
359 | __uml_exitcall(sigio_cleanup); | 365 | __uml_exitcall(sigio_cleanup); |
366 | |||
367 | /* Used as a flag during SIGIO testing early in boot */ | ||
368 | static volatile int got_sigio = 0; | ||
369 | |||
370 | static void __init handler(int sig) | ||
371 | { | ||
372 | got_sigio = 1; | ||
373 | } | ||
374 | |||
375 | struct openpty_arg { | ||
376 | int master; | ||
377 | int slave; | ||
378 | int err; | ||
379 | }; | ||
380 | |||
381 | static void openpty_cb(void *arg) | ||
382 | { | ||
383 | struct openpty_arg *info = arg; | ||
384 | |||
385 | info->err = 0; | ||
386 | if(openpty(&info->master, &info->slave, NULL, NULL, NULL)) | ||
387 | info->err = -errno; | ||
388 | } | ||
389 | |||
390 | static int async_pty(int master, int slave) | ||
391 | { | ||
392 | int flags; | ||
393 | |||
394 | flags = fcntl(master, F_GETFL); | ||
395 | if(flags < 0) | ||
396 | return -errno; | ||
397 | |||
398 | if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || | ||
399 | (fcntl(master, F_SETOWN, os_getpid()) < 0)) | ||
400 | return -errno; | ||
401 | |||
402 | if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)) | ||
403 | return -errno; | ||
404 | |||
405 | return(0); | ||
406 | } | ||
407 | |||
408 | static void __init check_one_sigio(void (*proc)(int, int)) | ||
409 | { | ||
410 | struct sigaction old, new; | ||
411 | struct openpty_arg pty = { .master = -1, .slave = -1 }; | ||
412 | int master, slave, err; | ||
413 | |||
414 | initial_thread_cb(openpty_cb, &pty); | ||
415 | if(pty.err){ | ||
416 | printk("openpty failed, errno = %d\n", -pty.err); | ||
417 | return; | ||
418 | } | ||
419 | |||
420 | master = pty.master; | ||
421 | slave = pty.slave; | ||
422 | |||
423 | if((master == -1) || (slave == -1)){ | ||
424 | printk("openpty failed to allocate a pty\n"); | ||
425 | return; | ||
426 | } | ||
427 | |||
428 | /* Not now, but complain so we now where we failed. */ | ||
429 | err = raw(master); | ||
430 | if (err < 0) | ||
431 | panic("check_sigio : __raw failed, errno = %d\n", -err); | ||
432 | |||
433 | err = async_pty(master, slave); | ||
434 | if(err < 0) | ||
435 | panic("tty_fds : sigio_async failed, err = %d\n", -err); | ||
436 | |||
437 | if(sigaction(SIGIO, NULL, &old) < 0) | ||
438 | panic("check_sigio : sigaction 1 failed, errno = %d\n", errno); | ||
439 | new = old; | ||
440 | new.sa_handler = handler; | ||
441 | if(sigaction(SIGIO, &new, NULL) < 0) | ||
442 | panic("check_sigio : sigaction 2 failed, errno = %d\n", errno); | ||
443 | |||
444 | got_sigio = 0; | ||
445 | (*proc)(master, slave); | ||
446 | |||
447 | close(master); | ||
448 | close(slave); | ||
449 | |||
450 | if(sigaction(SIGIO, &old, NULL) < 0) | ||
451 | panic("check_sigio : sigaction 3 failed, errno = %d\n", errno); | ||
452 | } | ||
453 | |||
454 | static void tty_output(int master, int slave) | ||
455 | { | ||
456 | int n; | ||
457 | char buf[512]; | ||
458 | |||
459 | printk("Checking that host ptys support output SIGIO..."); | ||
460 | |||
461 | memset(buf, 0, sizeof(buf)); | ||
462 | |||
463 | while(write(master, buf, sizeof(buf)) > 0) ; | ||
464 | if(errno != EAGAIN) | ||
465 | panic("tty_output : write failed, errno = %d\n", errno); | ||
466 | while(((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) ; | ||
467 | |||
468 | if(got_sigio){ | ||
469 | printk("Yes\n"); | ||
470 | pty_output_sigio = 1; | ||
471 | } | ||
472 | else if(n == -EAGAIN) | ||
473 | printk("No, enabling workaround\n"); | ||
474 | else panic("tty_output : read failed, err = %d\n", n); | ||
475 | } | ||
476 | |||
477 | static void tty_close(int master, int slave) | ||
478 | { | ||
479 | printk("Checking that host ptys support SIGIO on close..."); | ||
480 | |||
481 | close(slave); | ||
482 | if(got_sigio){ | ||
483 | printk("Yes\n"); | ||
484 | pty_close_sigio = 1; | ||
485 | } | ||
486 | else printk("No, enabling workaround\n"); | ||
487 | } | ||
488 | |||
489 | void __init check_sigio(void) | ||
490 | { | ||
491 | if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) && | ||
492 | (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){ | ||
493 | printk("No pseudo-terminals available - skipping pty SIGIO " | ||
494 | "check\n"); | ||
495 | return; | ||
496 | } | ||
497 | check_one_sigio(tty_output); | ||
498 | check_one_sigio(tty_close); | ||
499 | } | ||
500 | |||
501 | /* Here because it only does the SIGIO testing for now */ | ||
502 | void __init os_check_bugs(void) | ||
503 | { | ||
504 | check_sigio(); | ||
505 | } | ||
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index 266768629fee..48d493415301 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <stdarg.h> | 11 | #include <stdarg.h> |
12 | #include <string.h> | 12 | #include <string.h> |
13 | #include <sys/mman.h> | 13 | #include <sys/mman.h> |
14 | #include "user_util.h" | ||
15 | #include "user.h" | 14 | #include "user.h" |
16 | #include "signal_kern.h" | 15 | #include "signal_kern.h" |
17 | #include "sysdep/sigcontext.h" | 16 | #include "sysdep/sigcontext.h" |
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c index 9383e8751ae7..8e490fff3d47 100644 --- a/arch/um/os-Linux/skas/mem.c +++ b/arch/um/os-Linux/skas/mem.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <signal.h> | 6 | #include <signal.h> |
7 | #include <errno.h> | 7 | #include <errno.h> |
8 | #include <string.h> | 8 | #include <string.h> |
9 | #include <unistd.h> | ||
9 | #include <sys/mman.h> | 10 | #include <sys/mman.h> |
10 | #include <sys/wait.h> | 11 | #include <sys/wait.h> |
11 | #include <asm/page.h> | 12 | #include <asm/page.h> |
@@ -17,17 +18,17 @@ | |||
17 | #include "os.h" | 18 | #include "os.h" |
18 | #include "proc_mm.h" | 19 | #include "proc_mm.h" |
19 | #include "ptrace_user.h" | 20 | #include "ptrace_user.h" |
20 | #include "user_util.h" | ||
21 | #include "kern_util.h" | 21 | #include "kern_util.h" |
22 | #include "task.h" | 22 | #include "task.h" |
23 | #include "registers.h" | 23 | #include "registers.h" |
24 | #include "uml-config.h" | 24 | #include "uml-config.h" |
25 | #include "sysdep/ptrace.h" | 25 | #include "sysdep/ptrace.h" |
26 | #include "sysdep/stub.h" | 26 | #include "sysdep/stub.h" |
27 | #include "init.h" | ||
27 | 28 | ||
28 | extern unsigned long batch_syscall_stub, __syscall_stub_start; | 29 | extern unsigned long batch_syscall_stub, __syscall_stub_start; |
29 | 30 | ||
30 | extern void wait_stub_done(int pid, int sig, char * fname); | 31 | extern void wait_stub_done(int pid); |
31 | 32 | ||
32 | static inline unsigned long *check_init_stack(struct mm_id * mm_idp, | 33 | static inline unsigned long *check_init_stack(struct mm_id * mm_idp, |
33 | unsigned long *stack) | 34 | unsigned long *stack) |
@@ -39,6 +40,19 @@ static inline unsigned long *check_init_stack(struct mm_id * mm_idp, | |||
39 | return stack; | 40 | return stack; |
40 | } | 41 | } |
41 | 42 | ||
43 | static unsigned long syscall_regs[MAX_REG_NR]; | ||
44 | |||
45 | static int __init init_syscall_regs(void) | ||
46 | { | ||
47 | get_safe_registers(syscall_regs, NULL); | ||
48 | syscall_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + | ||
49 | ((unsigned long) &batch_syscall_stub - | ||
50 | (unsigned long) &__syscall_stub_start); | ||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | __initcall(init_syscall_regs); | ||
55 | |||
42 | extern int proc_mm; | 56 | extern int proc_mm; |
43 | 57 | ||
44 | int single_count = 0; | 58 | int single_count = 0; |
@@ -47,12 +61,11 @@ int multi_op_count = 0; | |||
47 | 61 | ||
48 | static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) | 62 | static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) |
49 | { | 63 | { |
50 | unsigned long regs[MAX_REG_NR]; | ||
51 | int n, i; | 64 | int n, i; |
52 | long ret, offset; | 65 | long ret, offset; |
53 | unsigned long * data; | 66 | unsigned long * data; |
54 | unsigned long * syscall; | 67 | unsigned long * syscall; |
55 | int pid = mm_idp->u.pid; | 68 | int err, pid = mm_idp->u.pid; |
56 | 69 | ||
57 | if(proc_mm) | 70 | if(proc_mm) |
58 | #warning Need to look up userspace_pid by cpu | 71 | #warning Need to look up userspace_pid by cpu |
@@ -60,21 +73,21 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) | |||
60 | 73 | ||
61 | multi_count++; | 74 | multi_count++; |
62 | 75 | ||
63 | get_safe_registers(regs, NULL); | 76 | n = ptrace_setregs(pid, syscall_regs); |
64 | regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + | ||
65 | ((unsigned long) &batch_syscall_stub - | ||
66 | (unsigned long) &__syscall_stub_start); | ||
67 | |||
68 | n = ptrace_setregs(pid, regs); | ||
69 | if(n < 0){ | 77 | if(n < 0){ |
70 | printk("Registers - \n"); | 78 | printk("Registers - \n"); |
71 | for(i = 0; i < MAX_REG_NR; i++) | 79 | for(i = 0; i < MAX_REG_NR; i++) |
72 | printk("\t%d\t0x%lx\n", i, regs[i]); | 80 | printk("\t%d\t0x%lx\n", i, syscall_regs[i]); |
73 | panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", | 81 | panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", |
74 | -n); | 82 | -n); |
75 | } | 83 | } |
76 | 84 | ||
77 | wait_stub_done(pid, 0, "do_syscall_stub"); | 85 | err = ptrace(PTRACE_CONT, pid, 0, 0); |
86 | if(err) | ||
87 | panic("Failed to continue stub, pid = %d, errno = %d\n", pid, | ||
88 | errno); | ||
89 | |||
90 | wait_stub_done(pid); | ||
78 | 91 | ||
79 | /* When the stub stops, we find the following values on the | 92 | /* When the stub stops, we find the following values on the |
80 | * beginning of the stack: | 93 | * beginning of the stack: |
@@ -176,14 +189,10 @@ long syscall_stub_data(struct mm_id * mm_idp, | |||
176 | return 0; | 189 | return 0; |
177 | } | 190 | } |
178 | 191 | ||
179 | int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, | 192 | int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int prot, |
180 | int r, int w, int x, int phys_fd, unsigned long long offset, | 193 | int phys_fd, unsigned long long offset, int done, void **data) |
181 | int done, void **data) | ||
182 | { | 194 | { |
183 | int prot, ret; | 195 | int ret; |
184 | |||
185 | prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | | ||
186 | (x ? PROT_EXEC : 0); | ||
187 | 196 | ||
188 | if(proc_mm){ | 197 | if(proc_mm){ |
189 | struct proc_mm_op map; | 198 | struct proc_mm_op map; |
@@ -200,9 +209,11 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, | |||
200 | .fd = phys_fd, | 209 | .fd = phys_fd, |
201 | .offset= offset | 210 | .offset= offset |
202 | } } } ); | 211 | } } } ); |
203 | ret = os_write_file(fd, &map, sizeof(map)); | 212 | CATCH_EINTR(ret = write(fd, &map, sizeof(map))); |
204 | if(ret != sizeof(map)) | 213 | if(ret != sizeof(map)){ |
214 | ret = -errno; | ||
205 | printk("map : /proc/mm map failed, err = %d\n", -ret); | 215 | printk("map : /proc/mm map failed, err = %d\n", -ret); |
216 | } | ||
206 | else ret = 0; | 217 | else ret = 0; |
207 | } | 218 | } |
208 | else { | 219 | else { |
@@ -217,8 +228,8 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, | |||
217 | return ret; | 228 | return ret; |
218 | } | 229 | } |
219 | 230 | ||
220 | int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done, | 231 | int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len, |
221 | void **data) | 232 | int done, void **data) |
222 | { | 233 | { |
223 | int ret; | 234 | int ret; |
224 | 235 | ||
@@ -232,9 +243,11 @@ int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done, | |||
232 | { .addr = | 243 | { .addr = |
233 | (unsigned long) addr, | 244 | (unsigned long) addr, |
234 | .len = len } } } ); | 245 | .len = len } } } ); |
235 | ret = os_write_file(fd, &unmap, sizeof(unmap)); | 246 | CATCH_EINTR(ret = write(fd, &unmap, sizeof(unmap))); |
236 | if(ret != sizeof(unmap)) | 247 | if(ret != sizeof(unmap)){ |
248 | ret = -errno; | ||
237 | printk("unmap - proc_mm write returned %d\n", ret); | 249 | printk("unmap - proc_mm write returned %d\n", ret); |
250 | } | ||
238 | else ret = 0; | 251 | else ret = 0; |
239 | } | 252 | } |
240 | else { | 253 | else { |
@@ -249,13 +262,11 @@ int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done, | |||
249 | } | 262 | } |
250 | 263 | ||
251 | int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, | 264 | int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, |
252 | int r, int w, int x, int done, void **data) | 265 | unsigned int prot, int done, void **data) |
253 | { | 266 | { |
254 | struct proc_mm_op protect; | 267 | struct proc_mm_op protect; |
255 | int prot, ret; | 268 | int ret; |
256 | 269 | ||
257 | prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | | ||
258 | (x ? PROT_EXEC : 0); | ||
259 | if(proc_mm){ | 270 | if(proc_mm){ |
260 | int fd = mm_idp->u.mm_fd; | 271 | int fd = mm_idp->u.mm_fd; |
261 | 272 | ||
@@ -267,9 +278,11 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, | |||
267 | .len = len, | 278 | .len = len, |
268 | .prot = prot } } } ); | 279 | .prot = prot } } } ); |
269 | 280 | ||
270 | ret = os_write_file(fd, &protect, sizeof(protect)); | 281 | CATCH_EINTR(ret = write(fd, &protect, sizeof(protect))); |
271 | if(ret != sizeof(protect)) | 282 | if(ret != sizeof(protect)){ |
283 | ret = -errno; | ||
272 | printk("protect failed, err = %d", -ret); | 284 | printk("protect failed, err = %d", -ret); |
285 | } | ||
273 | else ret = 0; | 286 | else ret = 0; |
274 | } | 287 | } |
275 | else { | 288 | else { |
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 0564422c155f..5c088a55396c 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <asm/types.h> | 18 | #include <asm/types.h> |
19 | #include "user.h" | 19 | #include "user.h" |
20 | #include "sysdep/ptrace.h" | 20 | #include "sysdep/ptrace.h" |
21 | #include "user_util.h" | ||
22 | #include "kern_util.h" | 21 | #include "kern_util.h" |
23 | #include "skas.h" | 22 | #include "skas.h" |
24 | #include "stub-data.h" | 23 | #include "stub-data.h" |
@@ -34,6 +33,8 @@ | |||
34 | #include "uml-config.h" | 33 | #include "uml-config.h" |
35 | #include "process.h" | 34 | #include "process.h" |
36 | #include "longjmp.h" | 35 | #include "longjmp.h" |
36 | #include "kern_constants.h" | ||
37 | #include "as-layout.h" | ||
37 | 38 | ||
38 | int is_skas_winch(int pid, int fd, void *data) | 39 | int is_skas_winch(int pid, int fd, void *data) |
39 | { | 40 | { |
@@ -44,45 +45,58 @@ int is_skas_winch(int pid, int fd, void *data) | |||
44 | return(1); | 45 | return(1); |
45 | } | 46 | } |
46 | 47 | ||
47 | void wait_stub_done(int pid, int sig, char * fname) | 48 | static int ptrace_dump_regs(int pid) |
48 | { | 49 | { |
49 | int n, status, err; | 50 | unsigned long regs[MAX_REG_NR]; |
51 | int i; | ||
52 | |||
53 | if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) | ||
54 | return -errno; | ||
55 | else { | ||
56 | printk("Stub registers -\n"); | ||
57 | for(i = 0; i < ARRAY_SIZE(regs); i++) | ||
58 | printk("\t%d - %lx\n", i, regs[i]); | ||
59 | } | ||
60 | |||
61 | return 0; | ||
62 | } | ||
50 | 63 | ||
51 | do { | 64 | /* |
52 | if ( sig != -1 ) { | 65 | * Signals that are OK to receive in the stub - we'll just continue it. |
53 | err = ptrace(PTRACE_CONT, pid, 0, sig); | 66 | * SIGWINCH will happen when UML is inside a detached screen. |
54 | if(err) | 67 | */ |
55 | panic("%s : continue failed, errno = %d\n", | 68 | #define STUB_SIG_MASK ((1 << SIGVTALRM) | (1 << SIGWINCH)) |
56 | fname, errno); | 69 | |
57 | } | 70 | /* Signals that the stub will finish with - anything else is an error */ |
58 | sig = 0; | 71 | #define STUB_DONE_MASK ((1 << SIGUSR1) | (1 << SIGTRAP)) |
72 | |||
73 | void wait_stub_done(int pid) | ||
74 | { | ||
75 | int n, status, err; | ||
59 | 76 | ||
77 | while(1){ | ||
60 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); | 78 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); |
61 | } while((n >= 0) && WIFSTOPPED(status) && | 79 | if((n < 0) || !WIFSTOPPED(status)) |
62 | ((WSTOPSIG(status) == SIGVTALRM) || | 80 | goto bad_wait; |
63 | /* running UML inside a detached screen can cause | 81 | |
64 | * SIGWINCHes | 82 | if(((1 << WSTOPSIG(status)) & STUB_SIG_MASK) == 0) |
65 | */ | 83 | break; |
66 | (WSTOPSIG(status) == SIGWINCH))); | 84 | |
67 | 85 | err = ptrace(PTRACE_CONT, pid, 0, 0); | |
68 | if((n < 0) || !WIFSTOPPED(status) || | 86 | if(err) |
69 | (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){ | 87 | panic("wait_stub_done : continue failed, errno = %d\n", |
70 | unsigned long regs[MAX_REG_NR]; | 88 | errno); |
71 | |||
72 | if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) | ||
73 | printk("Failed to get registers from stub, " | ||
74 | "errno = %d\n", errno); | ||
75 | else { | ||
76 | int i; | ||
77 | |||
78 | printk("Stub registers -\n"); | ||
79 | for(i = 0; i < ARRAY_SIZE(regs); i++) | ||
80 | printk("\t%d - %lx\n", i, regs[i]); | ||
81 | } | ||
82 | panic("%s : failed to wait for SIGUSR1/SIGTRAP, " | ||
83 | "pid = %d, n = %d, errno = %d, status = 0x%x\n", | ||
84 | fname, pid, n, errno, status); | ||
85 | } | 89 | } |
90 | |||
91 | if(((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0) | ||
92 | return; | ||
93 | |||
94 | bad_wait: | ||
95 | err = ptrace_dump_regs(pid); | ||
96 | if(err) | ||
97 | printk("Failed to get registers from stub, errno = %d\n", -err); | ||
98 | panic("wait_stub_done : failed to wait for SIGUSR1/SIGTRAP, pid = %d, " | ||
99 | "n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status); | ||
86 | } | 100 | } |
87 | 101 | ||
88 | extern unsigned long current_stub_stack(void); | 102 | extern unsigned long current_stub_stack(void); |
@@ -104,7 +118,11 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi) | |||
104 | sizeof(struct ptrace_faultinfo)); | 118 | sizeof(struct ptrace_faultinfo)); |
105 | } | 119 | } |
106 | else { | 120 | else { |
107 | wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo"); | 121 | err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV); |
122 | if(err) | ||
123 | panic("Failed to continue stub, pid = %d, errno = %d\n", | ||
124 | pid, errno); | ||
125 | wait_stub_done(pid); | ||
108 | 126 | ||
109 | /* faultinfo is prepared by the stub-segv-handler at start of | 127 | /* faultinfo is prepared by the stub-segv-handler at start of |
110 | * the stub stack page. We just have to copy it. | 128 | * the stub stack page. We just have to copy it. |
@@ -142,9 +160,14 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu | |||
142 | 160 | ||
143 | CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); | 161 | CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); |
144 | if((err < 0) || !WIFSTOPPED(status) || | 162 | if((err < 0) || !WIFSTOPPED(status) || |
145 | (WSTOPSIG(status) != SIGTRAP + 0x80)) | 163 | (WSTOPSIG(status) != SIGTRAP + 0x80)){ |
164 | err = ptrace_dump_regs(pid); | ||
165 | if(err) | ||
166 | printk("Failed to get registers from process, " | ||
167 | "errno = %d\n", -err); | ||
146 | panic("handle_trap - failed to wait at end of syscall, " | 168 | panic("handle_trap - failed to wait at end of syscall, " |
147 | "errno = %d, status = %d\n", errno, status); | 169 | "errno = %d, status = %d\n", errno, status); |
170 | } | ||
148 | } | 171 | } |
149 | 172 | ||
150 | handle_syscall(regs); | 173 | handle_syscall(regs); |
@@ -172,7 +195,7 @@ static int userspace_tramp(void *stack) | |||
172 | int fd; | 195 | int fd; |
173 | __u64 offset; | 196 | __u64 offset; |
174 | fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); | 197 | fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); |
175 | addr = mmap64((void *) UML_CONFIG_STUB_CODE, page_size(), | 198 | addr = mmap64((void *) UML_CONFIG_STUB_CODE, UM_KERN_PAGE_SIZE, |
176 | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); | 199 | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); |
177 | if(addr == MAP_FAILED){ | 200 | if(addr == MAP_FAILED){ |
178 | printk("mapping mmap stub failed, errno = %d\n", | 201 | printk("mapping mmap stub failed, errno = %d\n", |
@@ -182,8 +205,8 @@ static int userspace_tramp(void *stack) | |||
182 | 205 | ||
183 | if(stack != NULL){ | 206 | if(stack != NULL){ |
184 | fd = phys_mapping(to_phys(stack), &offset); | 207 | fd = phys_mapping(to_phys(stack), &offset); |
185 | addr = mmap((void *) UML_CONFIG_STUB_DATA, page_size(), | 208 | addr = mmap((void *) UML_CONFIG_STUB_DATA, |
186 | PROT_READ | PROT_WRITE, | 209 | UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, |
187 | MAP_FIXED | MAP_SHARED, fd, offset); | 210 | MAP_FIXED | MAP_SHARED, fd, offset); |
188 | if(addr == MAP_FAILED){ | 211 | if(addr == MAP_FAILED){ |
189 | printk("mapping segfault stack failed, " | 212 | printk("mapping segfault stack failed, " |
@@ -199,7 +222,7 @@ static int userspace_tramp(void *stack) | |||
199 | (unsigned long) stub_segv_handler - | 222 | (unsigned long) stub_segv_handler - |
200 | (unsigned long) &__syscall_stub_start; | 223 | (unsigned long) &__syscall_stub_start; |
201 | 224 | ||
202 | set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size()); | 225 | set_sigstack((void *) UML_CONFIG_STUB_DATA, UM_KERN_PAGE_SIZE); |
203 | sigemptyset(&sa.sa_mask); | 226 | sigemptyset(&sa.sa_mask); |
204 | sigaddset(&sa.sa_mask, SIGIO); | 227 | sigaddset(&sa.sa_mask, SIGIO); |
205 | sigaddset(&sa.sa_mask, SIGWINCH); | 228 | sigaddset(&sa.sa_mask, SIGWINCH); |
@@ -291,10 +314,13 @@ void userspace(union uml_pt_regs *regs) | |||
291 | UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ | 314 | UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ |
292 | 315 | ||
293 | if(WIFSTOPPED(status)){ | 316 | if(WIFSTOPPED(status)){ |
294 | switch(WSTOPSIG(status)){ | 317 | int sig = WSTOPSIG(status); |
318 | switch(sig){ | ||
295 | case SIGSEGV: | 319 | case SIGSEGV: |
296 | if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo) | 320 | if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo){ |
297 | user_signal(SIGSEGV, regs, pid); | 321 | get_skas_faultinfo(pid, ®s->skas.faultinfo); |
322 | (*sig_info[SIGSEGV])(SIGSEGV, regs); | ||
323 | } | ||
298 | else handle_segv(pid, regs); | 324 | else handle_segv(pid, regs); |
299 | break; | 325 | break; |
300 | case SIGTRAP + 0x80: | 326 | case SIGTRAP + 0x80: |
@@ -309,11 +335,13 @@ void userspace(union uml_pt_regs *regs) | |||
309 | case SIGBUS: | 335 | case SIGBUS: |
310 | case SIGFPE: | 336 | case SIGFPE: |
311 | case SIGWINCH: | 337 | case SIGWINCH: |
312 | user_signal(WSTOPSIG(status), regs, pid); | 338 | block_signals(); |
339 | (*sig_info[sig])(sig, regs); | ||
340 | unblock_signals(); | ||
313 | break; | 341 | break; |
314 | default: | 342 | default: |
315 | printk("userspace - child stopped with signal " | 343 | printk("userspace - child stopped with signal " |
316 | "%d\n", WSTOPSIG(status)); | 344 | "%d\n", sig); |
317 | } | 345 | } |
318 | pid = userspace_pid[0]; | 346 | pid = userspace_pid[0]; |
319 | interrupt_end(); | 347 | interrupt_end(); |
@@ -325,11 +353,29 @@ void userspace(union uml_pt_regs *regs) | |||
325 | } | 353 | } |
326 | } | 354 | } |
327 | 355 | ||
356 | static unsigned long thread_regs[MAX_REG_NR]; | ||
357 | static unsigned long thread_fp_regs[HOST_FP_SIZE]; | ||
358 | |||
359 | static int __init init_thread_regs(void) | ||
360 | { | ||
361 | get_safe_registers(thread_regs, thread_fp_regs); | ||
362 | /* Set parent's instruction pointer to start of clone-stub */ | ||
363 | thread_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + | ||
364 | (unsigned long) stub_clone_handler - | ||
365 | (unsigned long) &__syscall_stub_start; | ||
366 | thread_regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE - | ||
367 | sizeof(void *); | ||
368 | #ifdef __SIGNAL_FRAMESIZE | ||
369 | thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE; | ||
370 | #endif | ||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | __initcall(init_thread_regs); | ||
375 | |||
328 | int copy_context_skas0(unsigned long new_stack, int pid) | 376 | int copy_context_skas0(unsigned long new_stack, int pid) |
329 | { | 377 | { |
330 | int err; | 378 | int err; |
331 | unsigned long regs[MAX_REG_NR]; | ||
332 | unsigned long fp_regs[HOST_FP_SIZE]; | ||
333 | unsigned long current_stack = current_stub_stack(); | 379 | unsigned long current_stack = current_stub_stack(); |
334 | struct stub_data *data = (struct stub_data *) current_stack; | 380 | struct stub_data *data = (struct stub_data *) current_stack; |
335 | struct stub_data *child_data = (struct stub_data *) new_stack; | 381 | struct stub_data *child_data = (struct stub_data *) new_stack; |
@@ -344,23 +390,12 @@ int copy_context_skas0(unsigned long new_stack, int pid) | |||
344 | .timer = ((struct itimerval) | 390 | .timer = ((struct itimerval) |
345 | { { 0, 1000000 / hz() }, | 391 | { { 0, 1000000 / hz() }, |
346 | { 0, 1000000 / hz() }})}); | 392 | { 0, 1000000 / hz() }})}); |
347 | get_safe_registers(regs, fp_regs); | 393 | err = ptrace_setregs(pid, thread_regs); |
348 | |||
349 | /* Set parent's instruction pointer to start of clone-stub */ | ||
350 | regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + | ||
351 | (unsigned long) stub_clone_handler - | ||
352 | (unsigned long) &__syscall_stub_start; | ||
353 | regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE - | ||
354 | sizeof(void *); | ||
355 | #ifdef __SIGNAL_FRAMESIZE | ||
356 | regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE; | ||
357 | #endif | ||
358 | err = ptrace_setregs(pid, regs); | ||
359 | if(err < 0) | 394 | if(err < 0) |
360 | panic("copy_context_skas0 : PTRACE_SETREGS failed, " | 395 | panic("copy_context_skas0 : PTRACE_SETREGS failed, " |
361 | "pid = %d, errno = %d\n", pid, -err); | 396 | "pid = %d, errno = %d\n", pid, -err); |
362 | 397 | ||
363 | err = ptrace_setfpregs(pid, fp_regs); | 398 | err = ptrace_setfpregs(pid, thread_fp_regs); |
364 | if(err < 0) | 399 | if(err < 0) |
365 | panic("copy_context_skas0 : PTRACE_SETFPREGS failed, " | 400 | panic("copy_context_skas0 : PTRACE_SETFPREGS failed, " |
366 | "pid = %d, errno = %d\n", pid, -err); | 401 | "pid = %d, errno = %d\n", pid, -err); |
@@ -371,7 +406,11 @@ int copy_context_skas0(unsigned long new_stack, int pid) | |||
371 | /* Wait, until parent has finished its work: read child's pid from | 406 | /* Wait, until parent has finished its work: read child's pid from |
372 | * parent's stack, and check, if bad result. | 407 | * parent's stack, and check, if bad result. |
373 | */ | 408 | */ |
374 | wait_stub_done(pid, 0, "copy_context_skas0"); | 409 | err = ptrace(PTRACE_CONT, pid, 0, 0); |
410 | if(err) | ||
411 | panic("Failed to continue new process, pid = %d, " | ||
412 | "errno = %d\n", pid, errno); | ||
413 | wait_stub_done(pid); | ||
375 | 414 | ||
376 | pid = data->err; | 415 | pid = data->err; |
377 | if(pid < 0) | 416 | if(pid < 0) |
@@ -381,7 +420,7 @@ int copy_context_skas0(unsigned long new_stack, int pid) | |||
381 | /* Wait, until child has finished too: read child's result from | 420 | /* Wait, until child has finished too: read child's result from |
382 | * child's stack and check it. | 421 | * child's stack and check it. |
383 | */ | 422 | */ |
384 | wait_stub_done(pid, -1, "copy_context_skas0"); | 423 | wait_stub_done(pid); |
385 | if (child_data->err != UML_CONFIG_STUB_DATA) | 424 | if (child_data->err != UML_CONFIG_STUB_DATA) |
386 | panic("copy_context_skas0 - stub-child reports error %ld\n", | 425 | panic("copy_context_skas0 - stub-child reports error %ld\n", |
387 | child_data->err); | 426 | child_data->err); |
@@ -396,7 +435,7 @@ int copy_context_skas0(unsigned long new_stack, int pid) | |||
396 | 435 | ||
397 | /* | 436 | /* |
398 | * This is used only, if stub pages are needed, while proc_mm is | 437 | * This is used only, if stub pages are needed, while proc_mm is |
399 | * availabl. Opening /proc/mm creates a new mm_context, which lacks | 438 | * available. Opening /proc/mm creates a new mm_context, which lacks |
400 | * the stub-pages. Thus, we map them using /proc/mm-fd | 439 | * the stub-pages. Thus, we map them using /proc/mm-fd |
401 | */ | 440 | */ |
402 | void map_stub_pages(int fd, unsigned long code, | 441 | void map_stub_pages(int fd, unsigned long code, |
@@ -418,12 +457,13 @@ void map_stub_pages(int fd, unsigned long code, | |||
418 | .fd = code_fd, | 457 | .fd = code_fd, |
419 | .offset = code_offset | 458 | .offset = code_offset |
420 | } } }); | 459 | } } }); |
421 | n = os_write_file(fd, &mmop, sizeof(mmop)); | 460 | CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); |
422 | if(n != sizeof(mmop)){ | 461 | if(n != sizeof(mmop)){ |
462 | n = errno; | ||
423 | printk("mmap args - addr = 0x%lx, fd = %d, offset = %llx\n", | 463 | printk("mmap args - addr = 0x%lx, fd = %d, offset = %llx\n", |
424 | code, code_fd, (unsigned long long) code_offset); | 464 | code, code_fd, (unsigned long long) code_offset); |
425 | panic("map_stub_pages : /proc/mm map for code failed, " | 465 | panic("map_stub_pages : /proc/mm map for code failed, " |
426 | "err = %d\n", -n); | 466 | "err = %d\n", n); |
427 | } | 467 | } |
428 | 468 | ||
429 | if ( stack ) { | 469 | if ( stack ) { |
@@ -440,10 +480,10 @@ void map_stub_pages(int fd, unsigned long code, | |||
440 | .fd = map_fd, | 480 | .fd = map_fd, |
441 | .offset = map_offset | 481 | .offset = map_offset |
442 | } } }); | 482 | } } }); |
443 | n = os_write_file(fd, &mmop, sizeof(mmop)); | 483 | CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); |
444 | if(n != sizeof(mmop)) | 484 | if(n != sizeof(mmop)) |
445 | panic("map_stub_pages : /proc/mm map for data failed, " | 485 | panic("map_stub_pages : /proc/mm map for data failed, " |
446 | "err = %d\n", -n); | 486 | "err = %d\n", errno); |
447 | } | 487 | } |
448 | } | 488 | } |
449 | 489 | ||
@@ -480,7 +520,15 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) | |||
480 | SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, | 520 | SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, |
481 | SIGVTALRM, -1); | 521 | SIGVTALRM, -1); |
482 | 522 | ||
483 | n = UML_SETJMP(&initial_jmpbuf); | 523 | /* |
524 | * Can't use UML_SETJMP or UML_LONGJMP here because they save | ||
525 | * and restore signals, with the possible side-effect of | ||
526 | * trying to handle any signals which came when they were | ||
527 | * blocked, which can't be done on this stack. | ||
528 | * Signals must be blocked when jumping back here and restored | ||
529 | * after returning to the jumper. | ||
530 | */ | ||
531 | n = setjmp(initial_jmpbuf); | ||
484 | switch(n){ | 532 | switch(n){ |
485 | case INIT_JMP_NEW_THREAD: | 533 | case INIT_JMP_NEW_THREAD: |
486 | (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler; | 534 | (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler; |
@@ -490,7 +538,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) | |||
490 | break; | 538 | break; |
491 | case INIT_JMP_CALLBACK: | 539 | case INIT_JMP_CALLBACK: |
492 | (*cb_proc)(cb_arg); | 540 | (*cb_proc)(cb_arg); |
493 | UML_LONGJMP(cb_back, 1); | 541 | longjmp(*cb_back, 1); |
494 | break; | 542 | break; |
495 | case INIT_JMP_HALT: | 543 | case INIT_JMP_HALT: |
496 | kmalloc_ok = 0; | 544 | kmalloc_ok = 0; |
@@ -501,7 +549,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) | |||
501 | default: | 549 | default: |
502 | panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); | 550 | panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); |
503 | } | 551 | } |
504 | UML_LONGJMP(switch_buf, 1); | 552 | longjmp(*switch_buf, 1); |
505 | } | 553 | } |
506 | 554 | ||
507 | void initial_thread_cb_skas(void (*proc)(void *), void *arg) | 555 | void initial_thread_cb_skas(void (*proc)(void *), void *arg) |
diff --git a/arch/um/os-Linux/skas/trap.c b/arch/um/os-Linux/skas/trap.c index 9ad5fbec4593..3b600c2e63b8 100644 --- a/arch/um/os-Linux/skas/trap.c +++ b/arch/um/os-Linux/skas/trap.c | |||
@@ -5,8 +5,8 @@ | |||
5 | 5 | ||
6 | #include <signal.h> | 6 | #include <signal.h> |
7 | #include <errno.h> | 7 | #include <errno.h> |
8 | #include "user_util.h" | ||
9 | #include "kern_util.h" | 8 | #include "kern_util.h" |
9 | #include "as-layout.h" | ||
10 | #include "task.h" | 10 | #include "task.h" |
11 | #include "sigcontext.h" | 11 | #include "sigcontext.h" |
12 | #include "skas.h" | 12 | #include "skas.h" |
@@ -15,29 +15,39 @@ | |||
15 | #include "sysdep/ptrace_user.h" | 15 | #include "sysdep/ptrace_user.h" |
16 | #include "os.h" | 16 | #include "os.h" |
17 | 17 | ||
18 | static union uml_pt_regs ksig_regs[UM_NR_CPUS]; | ||
19 | |||
18 | void sig_handler_common_skas(int sig, void *sc_ptr) | 20 | void sig_handler_common_skas(int sig, void *sc_ptr) |
19 | { | 21 | { |
20 | struct sigcontext *sc = sc_ptr; | 22 | struct sigcontext *sc = sc_ptr; |
21 | struct skas_regs *r; | 23 | union uml_pt_regs *r; |
22 | void (*handler)(int, union uml_pt_regs *); | 24 | void (*handler)(int, union uml_pt_regs *); |
23 | int save_errno = errno; | 25 | int save_user, save_errno = errno; |
24 | int save_user; | ||
25 | 26 | ||
26 | /* This is done because to allow SIGSEGV to be delivered inside a SEGV | 27 | /* This is done because to allow SIGSEGV to be delivered inside a SEGV |
27 | * handler. This can happen in copy_user, and if SEGV is disabled, | 28 | * handler. This can happen in copy_user, and if SEGV is disabled, |
28 | * the process will die. | 29 | * the process will die. |
29 | * XXX Figure out why this is better than SA_NODEFER | 30 | * XXX Figure out why this is better than SA_NODEFER |
30 | */ | 31 | */ |
31 | if(sig == SIGSEGV) | 32 | if(sig == SIGSEGV) { |
32 | change_sig(SIGSEGV, 1); | 33 | change_sig(SIGSEGV, 1); |
34 | /* For segfaults, we want the data from the | ||
35 | * sigcontext. In this case, we don't want to mangle | ||
36 | * the process registers, so use a static set of | ||
37 | * registers. For other signals, the process | ||
38 | * registers are OK. | ||
39 | */ | ||
40 | r = &ksig_regs[cpu()]; | ||
41 | copy_sc(r, sc_ptr); | ||
42 | } | ||
43 | else r = TASK_REGS(get_current()); | ||
33 | 44 | ||
34 | r = &TASK_REGS(get_current())->skas; | 45 | save_user = r->skas.is_user; |
35 | save_user = r->is_user; | 46 | r->skas.is_user = 0; |
36 | r->is_user = 0; | ||
37 | if ( sig == SIGFPE || sig == SIGSEGV || | 47 | if ( sig == SIGFPE || sig == SIGSEGV || |
38 | sig == SIGBUS || sig == SIGILL || | 48 | sig == SIGBUS || sig == SIGILL || |
39 | sig == SIGTRAP ) { | 49 | sig == SIGTRAP ) { |
40 | GET_FAULTINFO_FROM_SC(r->faultinfo, sc); | 50 | GET_FAULTINFO_FROM_SC(r->skas.faultinfo, sc); |
41 | } | 51 | } |
42 | 52 | ||
43 | change_sig(SIGUSR1, 1); | 53 | change_sig(SIGUSR1, 1); |
@@ -49,25 +59,8 @@ void sig_handler_common_skas(int sig, void *sc_ptr) | |||
49 | sig != SIGVTALRM && sig != SIGALRM) | 59 | sig != SIGVTALRM && sig != SIGALRM) |
50 | unblock_signals(); | 60 | unblock_signals(); |
51 | 61 | ||
52 | handler(sig, (union uml_pt_regs *) r); | 62 | handler(sig, r); |
53 | 63 | ||
54 | errno = save_errno; | 64 | errno = save_errno; |
55 | r->is_user = save_user; | 65 | r->skas.is_user = save_user; |
56 | } | ||
57 | |||
58 | extern int ptrace_faultinfo; | ||
59 | |||
60 | void user_signal(int sig, union uml_pt_regs *regs, int pid) | ||
61 | { | ||
62 | void (*handler)(int, union uml_pt_regs *); | ||
63 | int segv = ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) || | ||
64 | (sig == SIGILL) || (sig == SIGTRAP)); | ||
65 | |||
66 | if (segv) | ||
67 | get_skas_faultinfo(pid, ®s->skas.faultinfo); | ||
68 | |||
69 | handler = sig_info[sig]; | ||
70 | handler(sig, (union uml_pt_regs *) regs); | ||
71 | |||
72 | unblock_signals(); | ||
73 | } | 66 | } |
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 5178eba9afa5..79471f85eb89 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c | |||
@@ -17,10 +17,10 @@ | |||
17 | #include <sys/time.h> | 17 | #include <sys/time.h> |
18 | #include <sys/wait.h> | 18 | #include <sys/wait.h> |
19 | #include <sys/mman.h> | 19 | #include <sys/mman.h> |
20 | #include <sys/resource.h> | ||
20 | #include <asm/unistd.h> | 21 | #include <asm/unistd.h> |
21 | #include <asm/page.h> | 22 | #include <asm/page.h> |
22 | #include <sys/types.h> | 23 | #include <sys/types.h> |
23 | #include "user_util.h" | ||
24 | #include "kern_util.h" | 24 | #include "kern_util.h" |
25 | #include "user.h" | 25 | #include "user.h" |
26 | #include "signal_kern.h" | 26 | #include "signal_kern.h" |
@@ -329,8 +329,32 @@ static void __init check_ptrace(void) | |||
329 | 329 | ||
330 | extern void check_tmpexec(void); | 330 | extern void check_tmpexec(void); |
331 | 331 | ||
332 | void os_early_checks(void) | 332 | static void __init check_coredump_limit(void) |
333 | { | 333 | { |
334 | struct rlimit lim; | ||
335 | int err = getrlimit(RLIMIT_CORE, &lim); | ||
336 | |||
337 | if(err){ | ||
338 | perror("Getting core dump limit"); | ||
339 | return; | ||
340 | } | ||
341 | |||
342 | printf("Core dump limits :\n\tsoft - "); | ||
343 | if(lim.rlim_cur == RLIM_INFINITY) | ||
344 | printf("NONE\n"); | ||
345 | else printf("%lu\n", lim.rlim_cur); | ||
346 | |||
347 | printf("\thard - "); | ||
348 | if(lim.rlim_max == RLIM_INFINITY) | ||
349 | printf("NONE\n"); | ||
350 | else printf("%lu\n", lim.rlim_max); | ||
351 | } | ||
352 | |||
353 | void __init os_early_checks(void) | ||
354 | { | ||
355 | /* Print out the core dump limits early */ | ||
356 | check_coredump_limit(); | ||
357 | |||
334 | check_ptrace(); | 358 | check_ptrace(); |
335 | 359 | ||
336 | /* Need to check this early because mmapping happens before the | 360 | /* Need to check this early because mmapping happens before the |
@@ -528,148 +552,3 @@ int __init parse_iomem(char *str, int *add) | |||
528 | out: | 552 | out: |
529 | return 1; | 553 | return 1; |
530 | } | 554 | } |
531 | |||
532 | |||
533 | /* Changed during early boot */ | ||
534 | int pty_output_sigio = 0; | ||
535 | int pty_close_sigio = 0; | ||
536 | |||
537 | /* Used as a flag during SIGIO testing early in boot */ | ||
538 | static volatile int got_sigio = 0; | ||
539 | |||
540 | static void __init handler(int sig) | ||
541 | { | ||
542 | got_sigio = 1; | ||
543 | } | ||
544 | |||
545 | struct openpty_arg { | ||
546 | int master; | ||
547 | int slave; | ||
548 | int err; | ||
549 | }; | ||
550 | |||
551 | static void openpty_cb(void *arg) | ||
552 | { | ||
553 | struct openpty_arg *info = arg; | ||
554 | |||
555 | info->err = 0; | ||
556 | if(openpty(&info->master, &info->slave, NULL, NULL, NULL)) | ||
557 | info->err = -errno; | ||
558 | } | ||
559 | |||
560 | static int async_pty(int master, int slave) | ||
561 | { | ||
562 | int flags; | ||
563 | |||
564 | flags = fcntl(master, F_GETFL); | ||
565 | if(flags < 0) | ||
566 | return -errno; | ||
567 | |||
568 | if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || | ||
569 | (fcntl(master, F_SETOWN, os_getpid()) < 0)) | ||
570 | return -errno; | ||
571 | |||
572 | if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)) | ||
573 | return -errno; | ||
574 | |||
575 | return(0); | ||
576 | } | ||
577 | |||
578 | static void __init check_one_sigio(void (*proc)(int, int)) | ||
579 | { | ||
580 | struct sigaction old, new; | ||
581 | struct openpty_arg pty = { .master = -1, .slave = -1 }; | ||
582 | int master, slave, err; | ||
583 | |||
584 | initial_thread_cb(openpty_cb, &pty); | ||
585 | if(pty.err){ | ||
586 | printk("openpty failed, errno = %d\n", -pty.err); | ||
587 | return; | ||
588 | } | ||
589 | |||
590 | master = pty.master; | ||
591 | slave = pty.slave; | ||
592 | |||
593 | if((master == -1) || (slave == -1)){ | ||
594 | printk("openpty failed to allocate a pty\n"); | ||
595 | return; | ||
596 | } | ||
597 | |||
598 | /* Not now, but complain so we now where we failed. */ | ||
599 | err = raw(master); | ||
600 | if (err < 0) | ||
601 | panic("check_sigio : __raw failed, errno = %d\n", -err); | ||
602 | |||
603 | err = async_pty(master, slave); | ||
604 | if(err < 0) | ||
605 | panic("tty_fds : sigio_async failed, err = %d\n", -err); | ||
606 | |||
607 | if(sigaction(SIGIO, NULL, &old) < 0) | ||
608 | panic("check_sigio : sigaction 1 failed, errno = %d\n", errno); | ||
609 | new = old; | ||
610 | new.sa_handler = handler; | ||
611 | if(sigaction(SIGIO, &new, NULL) < 0) | ||
612 | panic("check_sigio : sigaction 2 failed, errno = %d\n", errno); | ||
613 | |||
614 | got_sigio = 0; | ||
615 | (*proc)(master, slave); | ||
616 | |||
617 | close(master); | ||
618 | close(slave); | ||
619 | |||
620 | if(sigaction(SIGIO, &old, NULL) < 0) | ||
621 | panic("check_sigio : sigaction 3 failed, errno = %d\n", errno); | ||
622 | } | ||
623 | |||
624 | static void tty_output(int master, int slave) | ||
625 | { | ||
626 | int n; | ||
627 | char buf[512]; | ||
628 | |||
629 | printk("Checking that host ptys support output SIGIO..."); | ||
630 | |||
631 | memset(buf, 0, sizeof(buf)); | ||
632 | |||
633 | while(os_write_file(master, buf, sizeof(buf)) > 0) ; | ||
634 | if(errno != EAGAIN) | ||
635 | panic("check_sigio : write failed, errno = %d\n", errno); | ||
636 | while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ; | ||
637 | |||
638 | if(got_sigio){ | ||
639 | printk("Yes\n"); | ||
640 | pty_output_sigio = 1; | ||
641 | } | ||
642 | else if(n == -EAGAIN) printk("No, enabling workaround\n"); | ||
643 | else panic("check_sigio : read failed, err = %d\n", n); | ||
644 | } | ||
645 | |||
646 | static void tty_close(int master, int slave) | ||
647 | { | ||
648 | printk("Checking that host ptys support SIGIO on close..."); | ||
649 | |||
650 | close(slave); | ||
651 | if(got_sigio){ | ||
652 | printk("Yes\n"); | ||
653 | pty_close_sigio = 1; | ||
654 | } | ||
655 | else printk("No, enabling workaround\n"); | ||
656 | } | ||
657 | |||
658 | void __init check_sigio(void) | ||
659 | { | ||
660 | if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) && | ||
661 | (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){ | ||
662 | printk("No pseudo-terminals available - skipping pty SIGIO " | ||
663 | "check\n"); | ||
664 | return; | ||
665 | } | ||
666 | check_one_sigio(tty_output); | ||
667 | check_one_sigio(tty_close); | ||
668 | } | ||
669 | |||
670 | void os_check_bugs(void) | ||
671 | { | ||
672 | check_ptrace(); | ||
673 | check_sigio(); | ||
674 | } | ||
675 | |||
diff --git a/arch/um/os-Linux/sys-i386/tls.c b/arch/um/os-Linux/sys-i386/tls.c index 256532034c62..32ed41ec1a3d 100644 --- a/arch/um/os-Linux/sys-i386/tls.c +++ b/arch/um/os-Linux/sys-i386/tls.c | |||
@@ -5,7 +5,7 @@ | |||
5 | #include <unistd.h> | 5 | #include <unistd.h> |
6 | 6 | ||
7 | #include "sysdep/tls.h" | 7 | #include "sysdep/tls.h" |
8 | #include "user_util.h" | 8 | #include "user.h" |
9 | 9 | ||
10 | /* Checks whether host supports TLS, and sets *tls_min according to the value | 10 | /* Checks whether host supports TLS, and sets *tls_min according to the value |
11 | * valid on the host. | 11 | * valid on the host. |
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index 2115b8beb541..5de169b168f6 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <sys/time.h> | 10 | #include <sys/time.h> |
11 | #include <signal.h> | 11 | #include <signal.h> |
12 | #include <errno.h> | 12 | #include <errno.h> |
13 | #include "user_util.h" | ||
14 | #include "kern_util.h" | 13 | #include "kern_util.h" |
15 | #include "user.h" | 14 | #include "user.h" |
16 | #include "process.h" | 15 | #include "process.h" |
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c index d221214d2ed5..295da657931a 100644 --- a/arch/um/os-Linux/trap.c +++ b/arch/um/os-Linux/trap.c | |||
@@ -6,7 +6,6 @@ | |||
6 | #include <stdlib.h> | 6 | #include <stdlib.h> |
7 | #include <signal.h> | 7 | #include <signal.h> |
8 | #include "kern_util.h" | 8 | #include "kern_util.h" |
9 | #include "user_util.h" | ||
10 | #include "os.h" | 9 | #include "os.h" |
11 | #include "mode.h" | 10 | #include "mode.h" |
12 | #include "longjmp.h" | 11 | #include "longjmp.h" |
diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c index 3dc3a02d6263..bcf9359c4e9f 100644 --- a/arch/um/os-Linux/tt.c +++ b/arch/um/os-Linux/tt.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <asm/ptrace.h> | 18 | #include <asm/ptrace.h> |
19 | #include <asm/unistd.h> | 19 | #include <asm/unistd.h> |
20 | #include <asm/page.h> | 20 | #include <asm/page.h> |
21 | #include "user_util.h" | ||
22 | #include "kern_util.h" | 21 | #include "kern_util.h" |
23 | #include "user.h" | 22 | #include "user.h" |
24 | #include "signal_kern.h" | 23 | #include "signal_kern.h" |
@@ -32,6 +31,7 @@ | |||
32 | #include "choose-mode.h" | 31 | #include "choose-mode.h" |
33 | #include "mode.h" | 32 | #include "mode.h" |
34 | #include "tempfile.h" | 33 | #include "tempfile.h" |
34 | #include "kern_constants.h" | ||
35 | 35 | ||
36 | int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, | 36 | int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, |
37 | int must_succeed) | 37 | int must_succeed) |
@@ -143,7 +143,7 @@ int outer_tramp(void *arg) | |||
143 | int sig = sigkill; | 143 | int sig = sigkill; |
144 | 144 | ||
145 | t = arg; | 145 | t = arg; |
146 | t->pid = clone(t->tramp, (void *) t->temp_stack + page_size()/2, | 146 | t->pid = clone(t->tramp, (void *) t->temp_stack + UM_KERN_PAGE_SIZE/2, |
147 | t->flags, t->tramp_data); | 147 | t->flags, t->tramp_data); |
148 | if(t->pid > 0) wait_for_stop(t->pid, SIGSTOP, PTRACE_CONT, NULL); | 148 | if(t->pid > 0) wait_for_stop(t->pid, SIGSTOP, PTRACE_CONT, NULL); |
149 | kill(os_getpid(), sig); | 149 | kill(os_getpid(), sig); |
diff --git a/arch/um/os-Linux/tty_log.c b/arch/um/os-Linux/tty_log.c index c6ba56c1560f..d11a55baa6bd 100644 --- a/arch/um/os-Linux/tty_log.c +++ b/arch/um/os-Linux/tty_log.c | |||
@@ -53,9 +53,9 @@ int open_tty_log(void *tty, void *current_tty) | |||
53 | .direction = 0, | 53 | .direction = 0, |
54 | .sec = tv.tv_sec, | 54 | .sec = tv.tv_sec, |
55 | .usec = tv.tv_usec } ); | 55 | .usec = tv.tv_usec } ); |
56 | os_write_file(tty_log_fd, &data, sizeof(data)); | 56 | write(tty_log_fd, &data, sizeof(data)); |
57 | os_write_file(tty_log_fd, ¤t_tty, data.len); | 57 | write(tty_log_fd, ¤t_tty, data.len); |
58 | return(tty_log_fd); | 58 | return tty_log_fd; |
59 | } | 59 | } |
60 | 60 | ||
61 | sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec, | 61 | sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec, |
@@ -67,7 +67,7 @@ int open_tty_log(void *tty, void *current_tty) | |||
67 | printk("open_tty_log : couldn't open '%s', errno = %d\n", | 67 | printk("open_tty_log : couldn't open '%s', errno = %d\n", |
68 | buf, -fd); | 68 | buf, -fd); |
69 | } | 69 | } |
70 | return(fd); | 70 | return fd; |
71 | } | 71 | } |
72 | 72 | ||
73 | void close_tty_log(int fd, void *tty) | 73 | void close_tty_log(int fd, void *tty) |
@@ -83,7 +83,7 @@ void close_tty_log(int fd, void *tty) | |||
83 | .direction = 0, | 83 | .direction = 0, |
84 | .sec = tv.tv_sec, | 84 | .sec = tv.tv_sec, |
85 | .usec = tv.tv_usec } ); | 85 | .usec = tv.tv_usec } ); |
86 | os_write_file(tty_log_fd, &data, sizeof(data)); | 86 | write(tty_log_fd, &data, sizeof(data)); |
87 | return; | 87 | return; |
88 | } | 88 | } |
89 | os_close_file(fd); | 89 | os_close_file(fd); |
@@ -98,21 +98,21 @@ static int log_chunk(int fd, const char *buf, int len) | |||
98 | try = (len > sizeof(chunk)) ? sizeof(chunk) : len; | 98 | try = (len > sizeof(chunk)) ? sizeof(chunk) : len; |
99 | missed = copy_from_user_proc(chunk, (char *) buf, try); | 99 | missed = copy_from_user_proc(chunk, (char *) buf, try); |
100 | try -= missed; | 100 | try -= missed; |
101 | n = os_write_file(fd, chunk, try); | 101 | n = write(fd, chunk, try); |
102 | if(n != try) { | 102 | if(n != try) { |
103 | if(n < 0) | 103 | if(n < 0) |
104 | return(n); | 104 | return -errno; |
105 | return(-EIO); | 105 | return -EIO; |
106 | } | 106 | } |
107 | if(missed != 0) | 107 | if(missed != 0) |
108 | return(-EFAULT); | 108 | return -EFAULT; |
109 | 109 | ||
110 | len -= try; | 110 | len -= try; |
111 | total += try; | 111 | total += try; |
112 | buf += try; | 112 | buf += try; |
113 | } | 113 | } |
114 | 114 | ||
115 | return(total); | 115 | return total; |
116 | } | 116 | } |
117 | 117 | ||
118 | int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read) | 118 | int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read) |
@@ -130,10 +130,10 @@ int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read) | |||
130 | .direction = direction, | 130 | .direction = direction, |
131 | .sec = tv.tv_sec, | 131 | .sec = tv.tv_sec, |
132 | .usec = tv.tv_usec } ); | 132 | .usec = tv.tv_usec } ); |
133 | os_write_file(tty_log_fd, &data, sizeof(data)); | 133 | write(tty_log_fd, &data, sizeof(data)); |
134 | } | 134 | } |
135 | 135 | ||
136 | return(log_chunk(fd, buf, len)); | 136 | return log_chunk(fd, buf, len); |
137 | } | 137 | } |
138 | 138 | ||
139 | void log_exec(char **argv, void *tty) | 139 | void log_exec(char **argv, void *tty) |
@@ -161,7 +161,7 @@ void log_exec(char **argv, void *tty) | |||
161 | .direction = 0, | 161 | .direction = 0, |
162 | .sec = tv.tv_sec, | 162 | .sec = tv.tv_sec, |
163 | .usec = tv.tv_usec } ); | 163 | .usec = tv.tv_usec } ); |
164 | os_write_file(tty_log_fd, &data, sizeof(data)); | 164 | write(tty_log_fd, &data, sizeof(data)); |
165 | 165 | ||
166 | for(ptr = argv; ; ptr++){ | 166 | for(ptr = argv; ; ptr++){ |
167 | if(copy_from_user_proc(&arg, ptr, sizeof(arg))) | 167 | if(copy_from_user_proc(&arg, ptr, sizeof(arg))) |
@@ -179,7 +179,7 @@ extern void register_tty_logger(int (*opener)(void *, void *), | |||
179 | static int register_logger(void) | 179 | static int register_logger(void) |
180 | { | 180 | { |
181 | register_tty_logger(open_tty_log, write_tty_log, close_tty_log); | 181 | register_tty_logger(open_tty_log, write_tty_log, close_tty_log); |
182 | return(0); | 182 | return 0; |
183 | } | 183 | } |
184 | 184 | ||
185 | __uml_initcall(register_logger); | 185 | __uml_initcall(register_logger); |
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c index 56b8a50e8bc2..c307a89ed259 100644 --- a/arch/um/os-Linux/util.c +++ b/arch/um/os-Linux/util.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <sched.h> | 21 | #include <sched.h> |
22 | #include <termios.h> | 22 | #include <termios.h> |
23 | #include <string.h> | 23 | #include <string.h> |
24 | #include "user_util.h" | ||
25 | #include "kern_util.h" | 24 | #include "kern_util.h" |
26 | #include "user.h" | 25 | #include "user.h" |
27 | #include "mem_user.h" | 26 | #include "mem_user.h" |
@@ -30,28 +29,29 @@ | |||
30 | #include "uml-config.h" | 29 | #include "uml-config.h" |
31 | #include "os.h" | 30 | #include "os.h" |
32 | #include "longjmp.h" | 31 | #include "longjmp.h" |
32 | #include "kern_constants.h" | ||
33 | 33 | ||
34 | void stack_protections(unsigned long address) | 34 | void stack_protections(unsigned long address) |
35 | { | 35 | { |
36 | int prot = PROT_READ | PROT_WRITE | PROT_EXEC; | 36 | int prot = PROT_READ | PROT_WRITE | PROT_EXEC; |
37 | 37 | ||
38 | if(mprotect((void *) address, page_size(), prot) < 0) | 38 | if(mprotect((void *) address, UM_KERN_PAGE_SIZE, prot) < 0) |
39 | panic("protecting stack failed, errno = %d", errno); | 39 | panic("protecting stack failed, errno = %d", errno); |
40 | } | 40 | } |
41 | 41 | ||
42 | void task_protections(unsigned long address) | 42 | void task_protections(unsigned long address) |
43 | { | 43 | { |
44 | unsigned long guard = address + page_size(); | 44 | unsigned long guard = address + UM_KERN_PAGE_SIZE; |
45 | unsigned long stack = guard + page_size(); | 45 | unsigned long stack = guard + UM_KERN_PAGE_SIZE; |
46 | int prot = 0, pages; | 46 | int prot = 0, pages; |
47 | 47 | ||
48 | #ifdef notdef | 48 | #ifdef notdef |
49 | if(mprotect((void *) stack, page_size(), prot) < 0) | 49 | if(mprotect((void *) stack, UM_KERN_PAGE_SIZE, prot) < 0) |
50 | panic("protecting guard page failed, errno = %d", errno); | 50 | panic("protecting guard page failed, errno = %d", errno); |
51 | #endif | 51 | #endif |
52 | pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2; | 52 | pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2; |
53 | prot = PROT_READ | PROT_WRITE | PROT_EXEC; | 53 | prot = PROT_READ | PROT_WRITE | PROT_EXEC; |
54 | if(mprotect((void *) stack, pages * page_size(), prot) < 0) | 54 | if(mprotect((void *) stack, pages * UM_KERN_PAGE_SIZE, prot) < 0) |
55 | panic("protecting stack failed, errno = %d", errno); | 55 | panic("protecting stack failed, errno = %d", errno); |
56 | } | 56 | } |
57 | 57 | ||
@@ -96,15 +96,13 @@ void setup_machinename(char *machine_out) | |||
96 | strcpy(machine_out, host.machine); | 96 | strcpy(machine_out, host.machine); |
97 | } | 97 | } |
98 | 98 | ||
99 | char host_info[(_UTSNAME_LENGTH + 1) * 4 + _UTSNAME_NODENAME_LENGTH + 1]; | 99 | void setup_hostinfo(char *buf, int len) |
100 | |||
101 | void setup_hostinfo(void) | ||
102 | { | 100 | { |
103 | struct utsname host; | 101 | struct utsname host; |
104 | 102 | ||
105 | uname(&host); | 103 | uname(&host); |
106 | sprintf(host_info, "%s %s %s %s %s", host.sysname, host.nodename, | 104 | snprintf(buf, len, "%s %s %s %s %s", host.sysname, host.nodename, |
107 | host.release, host.version, host.machine); | 105 | host.release, host.version, host.machine); |
108 | } | 106 | } |
109 | 107 | ||
110 | int setjmp_wrapper(void (*proc)(void *, void *), ...) | 108 | int setjmp_wrapper(void (*proc)(void *, void *), ...) |
@@ -121,3 +119,9 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...) | |||
121 | va_end(args); | 119 | va_end(args); |
122 | return n; | 120 | return n; |
123 | } | 121 | } |
122 | |||
123 | void os_dump_core(void) | ||
124 | { | ||
125 | signal(SIGSEGV, SIG_DFL); | ||
126 | abort(); | ||
127 | } | ||
diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c index f1bcd399ac90..0393e44813e7 100644 --- a/arch/um/sys-i386/bugs.c +++ b/arch/um/sys-i386/bugs.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
@@ -13,7 +13,6 @@ | |||
13 | #include "sysdep/ptrace.h" | 13 | #include "sysdep/ptrace.h" |
14 | #include "task.h" | 14 | #include "task.h" |
15 | #include "os.h" | 15 | #include "os.h" |
16 | #include "user_util.h" | ||
17 | 16 | ||
18 | #define MAXTOKEN 64 | 17 | #define MAXTOKEN 64 |
19 | 18 | ||
@@ -32,21 +31,21 @@ static char token(int fd, char *buf, int len, char stop) | |||
32 | n = os_read_file(fd, ptr, sizeof(*ptr)); | 31 | n = os_read_file(fd, ptr, sizeof(*ptr)); |
33 | c = *ptr++; | 32 | c = *ptr++; |
34 | if(n != sizeof(*ptr)){ | 33 | if(n != sizeof(*ptr)){ |
35 | if(n == 0) return(0); | 34 | if(n == 0) |
35 | return 0; | ||
36 | printk("Reading /proc/cpuinfo failed, err = %d\n", -n); | 36 | printk("Reading /proc/cpuinfo failed, err = %d\n", -n); |
37 | if(n < 0) | 37 | if(n < 0) |
38 | return(n); | 38 | return n; |
39 | else | 39 | else return -EIO; |
40 | return(-EIO); | ||
41 | } | 40 | } |
42 | } while((c != '\n') && (c != stop) && (ptr < end)); | 41 | } while((c != '\n') && (c != stop) && (ptr < end)); |
43 | 42 | ||
44 | if(ptr == end){ | 43 | if(ptr == end){ |
45 | printk("Failed to find '%c' in /proc/cpuinfo\n", stop); | 44 | printk("Failed to find '%c' in /proc/cpuinfo\n", stop); |
46 | return(-1); | 45 | return -1; |
47 | } | 46 | } |
48 | *(ptr - 1) = '\0'; | 47 | *(ptr - 1) = '\0'; |
49 | return(c); | 48 | return c; |
50 | } | 49 | } |
51 | 50 | ||
52 | static int find_cpuinfo_line(int fd, char *key, char *scratch, int len) | 51 | static int find_cpuinfo_line(int fd, char *key, char *scratch, int len) |
@@ -58,48 +57,25 @@ static int find_cpuinfo_line(int fd, char *key, char *scratch, int len) | |||
58 | while(1){ | 57 | while(1){ |
59 | c = token(fd, scratch, len - 1, ':'); | 58 | c = token(fd, scratch, len - 1, ':'); |
60 | if(c <= 0) | 59 | if(c <= 0) |
61 | return(0); | 60 | return 0; |
62 | else if(c != ':'){ | 61 | else if(c != ':'){ |
63 | printk("Failed to find ':' in /proc/cpuinfo\n"); | 62 | printk("Failed to find ':' in /proc/cpuinfo\n"); |
64 | return(0); | 63 | return 0; |
65 | } | 64 | } |
66 | 65 | ||
67 | if(!strncmp(scratch, key, strlen(key))) | 66 | if(!strncmp(scratch, key, strlen(key))) |
68 | return(1); | 67 | return 1; |
69 | 68 | ||
70 | do { | 69 | do { |
71 | n = os_read_file(fd, &c, sizeof(c)); | 70 | n = os_read_file(fd, &c, sizeof(c)); |
72 | if(n != sizeof(c)){ | 71 | if(n != sizeof(c)){ |
73 | printk("Failed to find newline in " | 72 | printk("Failed to find newline in " |
74 | "/proc/cpuinfo, err = %d\n", -n); | 73 | "/proc/cpuinfo, err = %d\n", -n); |
75 | return(0); | 74 | return 0; |
76 | } | 75 | } |
77 | } while(c != '\n'); | 76 | } while(c != '\n'); |
78 | } | 77 | } |
79 | return(0); | 78 | return 0; |
80 | } | ||
81 | |||
82 | int cpu_feature(char *what, char *buf, int len) | ||
83 | { | ||
84 | int fd, ret = 0; | ||
85 | |||
86 | fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); | ||
87 | if(fd < 0){ | ||
88 | printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd); | ||
89 | return(0); | ||
90 | } | ||
91 | |||
92 | if(!find_cpuinfo_line(fd, what, buf, len)){ | ||
93 | printk("Couldn't find '%s' line in /proc/cpuinfo\n", what); | ||
94 | goto out_close; | ||
95 | } | ||
96 | |||
97 | token(fd, buf, len, '\n'); | ||
98 | ret = 1; | ||
99 | |||
100 | out_close: | ||
101 | os_close_file(fd); | ||
102 | return(ret); | ||
103 | } | 79 | } |
104 | 80 | ||
105 | static int check_cpu_flag(char *feature, int *have_it) | 81 | static int check_cpu_flag(char *feature, int *have_it) |
@@ -119,7 +95,8 @@ static int check_cpu_flag(char *feature, int *have_it) | |||
119 | goto out; | 95 | goto out; |
120 | 96 | ||
121 | c = token(fd, buf, len - 1, ' '); | 97 | c = token(fd, buf, len - 1, ' '); |
122 | if(c < 0) goto out; | 98 | if(c < 0) |
99 | goto out; | ||
123 | else if(c != ' '){ | 100 | else if(c != ' '){ |
124 | printk("Failed to find ' ' in /proc/cpuinfo\n"); | 101 | printk("Failed to find ' ' in /proc/cpuinfo\n"); |
125 | goto out; | 102 | goto out; |
@@ -127,7 +104,8 @@ static int check_cpu_flag(char *feature, int *have_it) | |||
127 | 104 | ||
128 | while(1){ | 105 | while(1){ |
129 | c = token(fd, buf, len - 1, ' '); | 106 | c = token(fd, buf, len - 1, ' '); |
130 | if(c < 0) goto out; | 107 | if(c < 0) |
108 | goto out; | ||
131 | else if(c == '\n') break; | 109 | else if(c == '\n') break; |
132 | 110 | ||
133 | if(!strcmp(buf, feature)){ | 111 | if(!strcmp(buf, feature)){ |
@@ -136,8 +114,10 @@ static int check_cpu_flag(char *feature, int *have_it) | |||
136 | } | 114 | } |
137 | } | 115 | } |
138 | out: | 116 | out: |
139 | if(*have_it == 0) printk("No\n"); | 117 | if(*have_it == 0) |
140 | else if(*have_it == 1) printk("Yes\n"); | 118 | printk("No\n"); |
119 | else if(*have_it == 1) | ||
120 | printk("Yes\n"); | ||
141 | os_close_file(fd); | 121 | os_close_file(fd); |
142 | return 1; | 122 | return 1; |
143 | } | 123 | } |
@@ -189,12 +169,13 @@ int arch_handle_signal(int sig, union uml_pt_regs *regs) | |||
189 | /* This is testing for a cmov (0x0f 0x4x) instruction causing a | 169 | /* This is testing for a cmov (0x0f 0x4x) instruction causing a |
190 | * SIGILL in init. | 170 | * SIGILL in init. |
191 | */ | 171 | */ |
192 | if((sig != SIGILL) || (TASK_PID(get_current()) != 1)) return(0); | 172 | if((sig != SIGILL) || (TASK_PID(get_current()) != 1)) |
173 | return 0; | ||
193 | 174 | ||
194 | if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) | 175 | if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) |
195 | panic("SIGILL in init, could not read instructions!\n"); | 176 | panic("SIGILL in init, could not read instructions!\n"); |
196 | if((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40)) | 177 | if((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40)) |
197 | return(0); | 178 | return 0; |
198 | 179 | ||
199 | if(host_has_cmov == 0) | 180 | if(host_has_cmov == 0) |
200 | panic("SIGILL caused by cmov, which this processor doesn't " | 181 | panic("SIGILL caused by cmov, which this processor doesn't " |
@@ -208,16 +189,5 @@ int arch_handle_signal(int sig, union uml_pt_regs *regs) | |||
208 | "implements it, boot a filesystem compiled for older " | 189 | "implements it, boot a filesystem compiled for older " |
209 | "processors"); | 190 | "processors"); |
210 | else panic("Bad value for host_has_cmov (%d)", host_has_cmov); | 191 | else panic("Bad value for host_has_cmov (%d)", host_has_cmov); |
211 | return(0); | 192 | return 0; |
212 | } | 193 | } |
213 | |||
214 | /* | ||
215 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
216 | * Emacs will notice this stuff at the end of the file and automatically | ||
217 | * adjust the settings for this buffer only. This must remain at the end | ||
218 | * of the file. | ||
219 | * --------------------------------------------------------------------------- | ||
220 | * Local variables: | ||
221 | * c-file-style: "linux" | ||
222 | * End: | ||
223 | */ | ||
diff --git a/arch/um/sys-i386/fault.c b/arch/um/sys-i386/fault.c index d0bbcdfdb53f..745b4fd49e9f 100644 --- a/arch/um/sys-i386/fault.c +++ b/arch/um/sys-i386/fault.c | |||
@@ -3,9 +3,7 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <signal.h> | ||
7 | #include "sysdep/ptrace.h" | 6 | #include "sysdep/ptrace.h" |
8 | #include "sysdep/sigcontext.h" | ||
9 | 7 | ||
10 | /* These two are from asm-um/uaccess.h and linux/module.h, check them. */ | 8 | /* These two are from asm-um/uaccess.h and linux/module.h, check them. */ |
11 | struct exception_table_entry | 9 | struct exception_table_entry |
@@ -17,26 +15,14 @@ struct exception_table_entry | |||
17 | const struct exception_table_entry *search_exception_tables(unsigned long add); | 15 | const struct exception_table_entry *search_exception_tables(unsigned long add); |
18 | 16 | ||
19 | /* Compare this to arch/i386/mm/extable.c:fixup_exception() */ | 17 | /* Compare this to arch/i386/mm/extable.c:fixup_exception() */ |
20 | int arch_fixup(unsigned long address, void *sc_ptr) | 18 | int arch_fixup(unsigned long address, union uml_pt_regs *regs) |
21 | { | 19 | { |
22 | struct sigcontext *sc = sc_ptr; | ||
23 | const struct exception_table_entry *fixup; | 20 | const struct exception_table_entry *fixup; |
24 | 21 | ||
25 | fixup = search_exception_tables(address); | 22 | fixup = search_exception_tables(address); |
26 | if(fixup != 0){ | 23 | if(fixup != 0){ |
27 | sc->eip = fixup->fixup; | 24 | UPT_IP(regs) = fixup->fixup; |
28 | return(1); | 25 | return(1); |
29 | } | 26 | } |
30 | return(0); | 27 | return(0); |
31 | } | 28 | } |
32 | |||
33 | /* | ||
34 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
35 | * Emacs will notice this stuff at the end of the file and automatically | ||
36 | * adjust the settings for this buffer only. This must remain at the end | ||
37 | * of the file. | ||
38 | * --------------------------------------------------------------------------- | ||
39 | * Local variables: | ||
40 | * c-file-style: "linux" | ||
41 | * End: | ||
42 | */ | ||
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c index 01212c88fcc4..40ff0c831bd0 100644 --- a/arch/um/sys-i386/ptrace_user.c +++ b/arch/um/sys-i386/ptrace_user.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
@@ -15,7 +15,6 @@ | |||
15 | #include "user.h" | 15 | #include "user.h" |
16 | #include "os.h" | 16 | #include "os.h" |
17 | #include "uml-config.h" | 17 | #include "uml-config.h" |
18 | #include "user_util.h" | ||
19 | 18 | ||
20 | int ptrace_getregs(long pid, unsigned long *regs_out) | 19 | int ptrace_getregs(long pid, unsigned long *regs_out) |
21 | { | 20 | { |
@@ -45,7 +44,8 @@ int ptrace_setfpregs(long pid, unsigned long *regs) | |||
45 | return 0; | 44 | return 0; |
46 | } | 45 | } |
47 | 46 | ||
48 | /* All the below stuff is of interest for TT mode only */ | 47 | #ifdef UML_CONFIG_MODE_TT |
48 | |||
49 | static void write_debugregs(int pid, unsigned long *regs) | 49 | static void write_debugregs(int pid, unsigned long *regs) |
50 | { | 50 | { |
51 | struct user *dummy; | 51 | struct user *dummy; |
@@ -128,13 +128,4 @@ void update_debugregs(int seq) | |||
128 | } | 128 | } |
129 | #endif | 129 | #endif |
130 | 130 | ||
131 | /* | 131 | #endif |
132 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
133 | * Emacs will notice this stuff at the end of the file and automatically | ||
134 | * adjust the settings for this buffer only. This must remain at the end | ||
135 | * of the file. | ||
136 | * --------------------------------------------------------------------------- | ||
137 | * Local variables: | ||
138 | * c-file-style: "linux" | ||
139 | * End: | ||
140 | */ | ||
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c index 3f6acd667717..1cbf95f6858a 100644 --- a/arch/um/sys-i386/signal.c +++ b/arch/um/sys-i386/signal.c | |||
@@ -18,6 +18,28 @@ | |||
18 | 18 | ||
19 | #include "skas.h" | 19 | #include "skas.h" |
20 | 20 | ||
21 | void copy_sc(union uml_pt_regs *regs, void *from) | ||
22 | { | ||
23 | struct sigcontext *sc = from; | ||
24 | |||
25 | REGS_GS(regs->skas.regs) = sc->gs; | ||
26 | REGS_FS(regs->skas.regs) = sc->fs; | ||
27 | REGS_ES(regs->skas.regs) = sc->es; | ||
28 | REGS_DS(regs->skas.regs) = sc->ds; | ||
29 | REGS_EDI(regs->skas.regs) = sc->edi; | ||
30 | REGS_ESI(regs->skas.regs) = sc->esi; | ||
31 | REGS_EBP(regs->skas.regs) = sc->ebp; | ||
32 | REGS_SP(regs->skas.regs) = sc->esp; | ||
33 | REGS_EBX(regs->skas.regs) = sc->ebx; | ||
34 | REGS_EDX(regs->skas.regs) = sc->edx; | ||
35 | REGS_ECX(regs->skas.regs) = sc->ecx; | ||
36 | REGS_EAX(regs->skas.regs) = sc->eax; | ||
37 | REGS_IP(regs->skas.regs) = sc->eip; | ||
38 | REGS_CS(regs->skas.regs) = sc->cs; | ||
39 | REGS_EFLAGS(regs->skas.regs) = sc->eflags; | ||
40 | REGS_SS(regs->skas.regs) = sc->ss; | ||
41 | } | ||
42 | |||
21 | static int copy_sc_from_user_skas(struct pt_regs *regs, | 43 | static int copy_sc_from_user_skas(struct pt_regs *regs, |
22 | struct sigcontext __user *from) | 44 | struct sigcontext __user *from) |
23 | { | 45 | { |
@@ -28,33 +50,18 @@ static int copy_sc_from_user_skas(struct pt_regs *regs, | |||
28 | err = copy_from_user(&sc, from, sizeof(sc)); | 50 | err = copy_from_user(&sc, from, sizeof(sc)); |
29 | err |= copy_from_user(fpregs, sc.fpstate, sizeof(fpregs)); | 51 | err |= copy_from_user(fpregs, sc.fpstate, sizeof(fpregs)); |
30 | if(err) | 52 | if(err) |
31 | return(err); | 53 | return err; |
32 | 54 | ||
33 | REGS_GS(regs->regs.skas.regs) = sc.gs; | 55 | copy_sc(®s->regs, &sc); |
34 | REGS_FS(regs->regs.skas.regs) = sc.fs; | ||
35 | REGS_ES(regs->regs.skas.regs) = sc.es; | ||
36 | REGS_DS(regs->regs.skas.regs) = sc.ds; | ||
37 | REGS_EDI(regs->regs.skas.regs) = sc.edi; | ||
38 | REGS_ESI(regs->regs.skas.regs) = sc.esi; | ||
39 | REGS_EBP(regs->regs.skas.regs) = sc.ebp; | ||
40 | REGS_SP(regs->regs.skas.regs) = sc.esp; | ||
41 | REGS_EBX(regs->regs.skas.regs) = sc.ebx; | ||
42 | REGS_EDX(regs->regs.skas.regs) = sc.edx; | ||
43 | REGS_ECX(regs->regs.skas.regs) = sc.ecx; | ||
44 | REGS_EAX(regs->regs.skas.regs) = sc.eax; | ||
45 | REGS_IP(regs->regs.skas.regs) = sc.eip; | ||
46 | REGS_CS(regs->regs.skas.regs) = sc.cs; | ||
47 | REGS_EFLAGS(regs->regs.skas.regs) = sc.eflags; | ||
48 | REGS_SS(regs->regs.skas.regs) = sc.ss; | ||
49 | 56 | ||
50 | err = restore_fp_registers(userspace_pid[0], fpregs); | 57 | err = restore_fp_registers(userspace_pid[0], fpregs); |
51 | if(err < 0){ | 58 | if(err < 0) { |
52 | printk("copy_sc_from_user_skas - PTRACE_SETFPREGS failed, " | 59 | printk("copy_sc_from_user_skas - PTRACE_SETFPREGS failed, " |
53 | "errno = %d\n", err); | 60 | "errno = %d\n", -err); |
54 | return(1); | 61 | return err; |
55 | } | 62 | } |
56 | 63 | ||
57 | return(0); | 64 | return 0; |
58 | } | 65 | } |
59 | 66 | ||
60 | int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *to_fp, | 67 | int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *to_fp, |
@@ -90,16 +97,16 @@ int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *t | |||
90 | if(err < 0){ | 97 | if(err < 0){ |
91 | printk("copy_sc_to_user_skas - PTRACE_GETFPREGS failed, " | 98 | printk("copy_sc_to_user_skas - PTRACE_GETFPREGS failed, " |
92 | "errno = %d\n", err); | 99 | "errno = %d\n", err); |
93 | return(1); | 100 | return 1; |
94 | } | 101 | } |
95 | to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1)); | 102 | to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1)); |
96 | sc.fpstate = to_fp; | 103 | sc.fpstate = to_fp; |
97 | 104 | ||
98 | if(err) | 105 | if(err) |
99 | return(err); | 106 | return err; |
100 | 107 | ||
101 | return(copy_to_user(to, &sc, sizeof(sc)) || | 108 | return copy_to_user(to, &sc, sizeof(sc)) || |
102 | copy_to_user(to_fp, fpregs, sizeof(fpregs))); | 109 | copy_to_user(to_fp, fpregs, sizeof(fpregs)); |
103 | } | 110 | } |
104 | #endif | 111 | #endif |
105 | 112 | ||
@@ -129,7 +136,7 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from, | |||
129 | to->fpstate = to_fp; | 136 | to->fpstate = to_fp; |
130 | if(to_fp != NULL) | 137 | if(to_fp != NULL) |
131 | err |= copy_from_user(to_fp, from_fp, fpsize); | 138 | err |= copy_from_user(to_fp, from_fp, fpsize); |
132 | return(err); | 139 | return err; |
133 | } | 140 | } |
134 | 141 | ||
135 | int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp, | 142 | int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp, |
@@ -164,15 +171,15 @@ static int copy_sc_from_user(struct pt_regs *to, void __user *from) | |||
164 | ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, | 171 | ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, |
165 | sizeof(struct _fpstate)), | 172 | sizeof(struct _fpstate)), |
166 | copy_sc_from_user_skas(to, from)); | 173 | copy_sc_from_user_skas(to, from)); |
167 | return(ret); | 174 | return ret; |
168 | } | 175 | } |
169 | 176 | ||
170 | static int copy_sc_to_user(struct sigcontext __user *to, struct _fpstate __user *fp, | 177 | static int copy_sc_to_user(struct sigcontext __user *to, struct _fpstate __user *fp, |
171 | struct pt_regs *from, unsigned long sp) | 178 | struct pt_regs *from, unsigned long sp) |
172 | { | 179 | { |
173 | return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), | 180 | return CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), |
174 | sizeof(*fp), sp), | 181 | sizeof(*fp), sp), |
175 | copy_sc_to_user_skas(to, fp, from, sp))); | 182 | copy_sc_to_user_skas(to, fp, from, sp)); |
176 | } | 183 | } |
177 | 184 | ||
178 | static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __user *fp, | 185 | static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __user *fp, |
@@ -185,7 +192,7 @@ static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __u | |||
185 | err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size); | 192 | err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size); |
186 | err |= copy_sc_to_user(&uc->uc_mcontext, fp, ¤t->thread.regs, sp); | 193 | err |= copy_sc_to_user(&uc->uc_mcontext, fp, ¤t->thread.regs, sp); |
187 | err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set)); | 194 | err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set)); |
188 | return(err); | 195 | return err; |
189 | } | 196 | } |
190 | 197 | ||
191 | struct sigframe | 198 | struct sigframe |
@@ -359,7 +366,7 @@ long sys_sigreturn(struct pt_regs regs) | |||
359 | 366 | ||
360 | /* Avoid ERESTART handling */ | 367 | /* Avoid ERESTART handling */ |
361 | PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; | 368 | PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; |
362 | return(PT_REGS_SYSCALL_RET(¤t->thread.regs)); | 369 | return PT_REGS_SYSCALL_RET(¤t->thread.regs); |
363 | 370 | ||
364 | segfault: | 371 | segfault: |
365 | force_sig(SIGSEGV, current); | 372 | force_sig(SIGSEGV, current); |
@@ -389,20 +396,9 @@ long sys_rt_sigreturn(struct pt_regs regs) | |||
389 | 396 | ||
390 | /* Avoid ERESTART handling */ | 397 | /* Avoid ERESTART handling */ |
391 | PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; | 398 | PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; |
392 | return(PT_REGS_SYSCALL_RET(¤t->thread.regs)); | 399 | return PT_REGS_SYSCALL_RET(¤t->thread.regs); |
393 | 400 | ||
394 | segfault: | 401 | segfault: |
395 | force_sig(SIGSEGV, current); | 402 | force_sig(SIGSEGV, current); |
396 | return 0; | 403 | return 0; |
397 | } | 404 | } |
398 | |||
399 | /* | ||
400 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
401 | * Emacs will notice this stuff at the end of the file and automatically | ||
402 | * adjust the settings for this buffer only. This must remain at the end | ||
403 | * of the file. | ||
404 | * --------------------------------------------------------------------------- | ||
405 | * Local variables: | ||
406 | * c-file-style: "linux" | ||
407 | * End: | ||
408 | */ | ||
diff --git a/arch/um/sys-i386/tls.c b/arch/um/sys-i386/tls.c index 643dab585727..fea8e5e15cc4 100644 --- a/arch/um/sys-i386/tls.c +++ b/arch/um/sys-i386/tls.c | |||
@@ -23,9 +23,13 @@ | |||
23 | #include "skas.h" | 23 | #include "skas.h" |
24 | #endif | 24 | #endif |
25 | 25 | ||
26 | /* If needed we can detect when it's uninitialized. */ | 26 | /* |
27 | * If needed we can detect when it's uninitialized. | ||
28 | * | ||
29 | * These are initialized in an initcall and unchanged thereafter. | ||
30 | */ | ||
27 | static int host_supports_tls = -1; | 31 | static int host_supports_tls = -1; |
28 | int host_gdt_entry_tls_min = -1; | 32 | int host_gdt_entry_tls_min; |
29 | 33 | ||
30 | #ifdef CONFIG_MODE_SKAS | 34 | #ifdef CONFIG_MODE_SKAS |
31 | int do_set_thread_area_skas(struct user_desc *info) | 35 | int do_set_thread_area_skas(struct user_desc *info) |
@@ -361,7 +365,8 @@ out: | |||
361 | 365 | ||
362 | /* XXX: This part is probably common to i386 and x86-64. Don't create a common | 366 | /* XXX: This part is probably common to i386 and x86-64. Don't create a common |
363 | * file for now, do that when implementing x86-64 support.*/ | 367 | * file for now, do that when implementing x86-64 support.*/ |
364 | static int __init __setup_host_supports_tls(void) { | 368 | static int __init __setup_host_supports_tls(void) |
369 | { | ||
365 | check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min); | 370 | check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min); |
366 | if (host_supports_tls) { | 371 | if (host_supports_tls) { |
367 | printk(KERN_INFO "Host TLS support detected\n"); | 372 | printk(KERN_INFO "Host TLS support detected\n"); |
diff --git a/arch/um/sys-i386/user-offsets.c b/arch/um/sys-i386/user-offsets.c index 447306b20aea..29118cf5ff25 100644 --- a/arch/um/sys-i386/user-offsets.c +++ b/arch/um/sys-i386/user-offsets.c | |||
@@ -1,9 +1,10 @@ | |||
1 | #include <stdio.h> | 1 | #include <stdio.h> |
2 | #include <stddef.h> | ||
2 | #include <signal.h> | 3 | #include <signal.h> |
4 | #include <sys/poll.h> | ||
5 | #include <sys/mman.h> | ||
3 | #include <asm/ptrace.h> | 6 | #include <asm/ptrace.h> |
4 | #include <asm/user.h> | 7 | #include <asm/user.h> |
5 | #include <stddef.h> | ||
6 | #include <sys/poll.h> | ||
7 | 8 | ||
8 | #define DEFINE(sym, val) \ | 9 | #define DEFINE(sym, val) \ |
9 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) | 10 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) |
@@ -47,7 +48,6 @@ void foo(void) | |||
47 | OFFSET(HOST_SC_FP_ST, _fpstate, _st); | 48 | OFFSET(HOST_SC_FP_ST, _fpstate, _st); |
48 | OFFSET(HOST_SC_FXSR_ENV, _fpstate, _fxsr_env); | 49 | OFFSET(HOST_SC_FXSR_ENV, _fpstate, _fxsr_env); |
49 | 50 | ||
50 | DEFINE(HOST_FRAME_SIZE, FRAME_SIZE); | ||
51 | DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_i387_struct)); | 51 | DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_i387_struct)); |
52 | DEFINE_LONGS(HOST_XFP_SIZE, sizeof(struct user_fxsr_struct)); | 52 | DEFINE_LONGS(HOST_XFP_SIZE, sizeof(struct user_fxsr_struct)); |
53 | 53 | ||
@@ -73,4 +73,8 @@ void foo(void) | |||
73 | DEFINE(UM_POLLIN, POLLIN); | 73 | DEFINE(UM_POLLIN, POLLIN); |
74 | DEFINE(UM_POLLPRI, POLLPRI); | 74 | DEFINE(UM_POLLPRI, POLLPRI); |
75 | DEFINE(UM_POLLOUT, POLLOUT); | 75 | DEFINE(UM_POLLOUT, POLLOUT); |
76 | |||
77 | DEFINE(UM_PROT_READ, PROT_READ); | ||
78 | DEFINE(UM_PROT_WRITE, PROT_WRITE); | ||
79 | DEFINE(UM_PROT_EXEC, PROT_EXEC); | ||
76 | } | 80 | } |
diff --git a/arch/um/sys-ppc/sigcontext.c b/arch/um/sys-ppc/sigcontext.c index 5d430fc994af..4bdc15c89edd 100644 --- a/arch/um/sys-ppc/sigcontext.c +++ b/arch/um/sys-ppc/sigcontext.c | |||
@@ -1,7 +1,6 @@ | |||
1 | #include "asm/ptrace.h" | 1 | #include "asm/ptrace.h" |
2 | #include "asm/sigcontext.h" | 2 | #include "asm/sigcontext.h" |
3 | #include "sysdep/ptrace.h" | 3 | #include "sysdep/ptrace.h" |
4 | #include "user_util.h" | ||
5 | 4 | ||
6 | /* | 5 | /* |
7 | * Overrides for Emacs so that we follow Linus's tabbing style. | 6 | * Overrides for Emacs so that we follow Linus's tabbing style. |
diff --git a/arch/um/sys-x86_64/bugs.c b/arch/um/sys-x86_64/bugs.c index fdce7ea98ca7..095478890371 100644 --- a/arch/um/sys-x86_64/bugs.c +++ b/arch/um/sys-x86_64/bugs.c | |||
@@ -4,12 +4,7 @@ | |||
4 | * Licensed under the GPL | 4 | * Licensed under the GPL |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include "linux/sched.h" | ||
8 | #include "linux/errno.h" | ||
9 | #include "asm/system.h" | ||
10 | #include "asm/pda.h" | ||
11 | #include "sysdep/ptrace.h" | 7 | #include "sysdep/ptrace.h" |
12 | #include "os.h" | ||
13 | 8 | ||
14 | void arch_init_thread(void) | 9 | void arch_init_thread(void) |
15 | { | 10 | { |
@@ -21,102 +16,5 @@ void arch_check_bugs(void) | |||
21 | 16 | ||
22 | int arch_handle_signal(int sig, union uml_pt_regs *regs) | 17 | int arch_handle_signal(int sig, union uml_pt_regs *regs) |
23 | { | 18 | { |
24 | return(0); | 19 | return 0; |
25 | } | 20 | } |
26 | |||
27 | #define MAXTOKEN 64 | ||
28 | |||
29 | /* Set during early boot */ | ||
30 | int host_has_cmov = 1; | ||
31 | int host_has_xmm = 0; | ||
32 | |||
33 | static char token(int fd, char *buf, int len, char stop) | ||
34 | { | ||
35 | int n; | ||
36 | char *ptr, *end, c; | ||
37 | |||
38 | ptr = buf; | ||
39 | end = &buf[len]; | ||
40 | do { | ||
41 | n = os_read_file(fd, ptr, sizeof(*ptr)); | ||
42 | c = *ptr++; | ||
43 | if(n != sizeof(*ptr)){ | ||
44 | if(n == 0) return(0); | ||
45 | printk("Reading /proc/cpuinfo failed, err = %d\n", -n); | ||
46 | if(n < 0) | ||
47 | return(n); | ||
48 | else | ||
49 | return(-EIO); | ||
50 | } | ||
51 | } while((c != '\n') && (c != stop) && (ptr < end)); | ||
52 | |||
53 | if(ptr == end){ | ||
54 | printk("Failed to find '%c' in /proc/cpuinfo\n", stop); | ||
55 | return(-1); | ||
56 | } | ||
57 | *(ptr - 1) = '\0'; | ||
58 | return(c); | ||
59 | } | ||
60 | |||
61 | static int find_cpuinfo_line(int fd, char *key, char *scratch, int len) | ||
62 | { | ||
63 | int n; | ||
64 | char c; | ||
65 | |||
66 | scratch[len - 1] = '\0'; | ||
67 | while(1){ | ||
68 | c = token(fd, scratch, len - 1, ':'); | ||
69 | if(c <= 0) | ||
70 | return(0); | ||
71 | else if(c != ':'){ | ||
72 | printk("Failed to find ':' in /proc/cpuinfo\n"); | ||
73 | return(0); | ||
74 | } | ||
75 | |||
76 | if(!strncmp(scratch, key, strlen(key))) | ||
77 | return(1); | ||
78 | |||
79 | do { | ||
80 | n = os_read_file(fd, &c, sizeof(c)); | ||
81 | if(n != sizeof(c)){ | ||
82 | printk("Failed to find newline in " | ||
83 | "/proc/cpuinfo, err = %d\n", -n); | ||
84 | return(0); | ||
85 | } | ||
86 | } while(c != '\n'); | ||
87 | } | ||
88 | return(0); | ||
89 | } | ||
90 | |||
91 | int cpu_feature(char *what, char *buf, int len) | ||
92 | { | ||
93 | int fd, ret = 0; | ||
94 | |||
95 | fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); | ||
96 | if(fd < 0){ | ||
97 | printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd); | ||
98 | return(0); | ||
99 | } | ||
100 | |||
101 | if(!find_cpuinfo_line(fd, what, buf, len)){ | ||
102 | printk("Couldn't find '%s' line in /proc/cpuinfo\n", what); | ||
103 | goto out_close; | ||
104 | } | ||
105 | |||
106 | token(fd, buf, len, '\n'); | ||
107 | ret = 1; | ||
108 | |||
109 | out_close: | ||
110 | os_close_file(fd); | ||
111 | return(ret); | ||
112 | } | ||
113 | |||
114 | /* Overrides for Emacs so that we follow Linus's tabbing style. | ||
115 | * Emacs will notice this stuff at the end of the file and automatically | ||
116 | * adjust the settings for this buffer only. This must remain at the end | ||
117 | * of the file. | ||
118 | * --------------------------------------------------------------------------- | ||
119 | * Local variables: | ||
120 | * c-file-style: "linux" | ||
121 | * End: | ||
122 | */ | ||
diff --git a/arch/um/sys-x86_64/fault.c b/arch/um/sys-x86_64/fault.c index cee1513c5c31..4636b1465b6c 100644 --- a/arch/um/sys-x86_64/fault.c +++ b/arch/um/sys-x86_64/fault.c | |||
@@ -4,20 +4,24 @@ | |||
4 | * Licensed under the GPL | 4 | * Licensed under the GPL |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include "user.h" | 7 | #include "sysdep/ptrace.h" |
8 | 8 | ||
9 | int arch_fixup(unsigned long address, void *sc_ptr) | 9 | /* These two are from asm-um/uaccess.h and linux/module.h, check them. */ |
10 | struct exception_table_entry | ||
10 | { | 11 | { |
11 | /* XXX search_exception_tables() */ | 12 | unsigned long insn; |
13 | unsigned long fixup; | ||
14 | }; | ||
15 | |||
16 | const struct exception_table_entry *search_exception_tables(unsigned long add); | ||
17 | int arch_fixup(unsigned long address, union uml_pt_regs *regs) | ||
18 | { | ||
19 | const struct exception_table_entry *fixup; | ||
20 | |||
21 | fixup = search_exception_tables(address); | ||
22 | if(fixup != 0){ | ||
23 | UPT_IP(regs) = fixup->fixup; | ||
24 | return(1); | ||
25 | } | ||
12 | return(0); | 26 | return(0); |
13 | } | 27 | } |
14 | |||
15 | /* Overrides for Emacs so that we follow Linus's tabbing style. | ||
16 | * Emacs will notice this stuff at the end of the file and automatically | ||
17 | * adjust the settings for this buffer only. This must remain at the end | ||
18 | * of the file. | ||
19 | * --------------------------------------------------------------------------- | ||
20 | * Local variables: | ||
21 | * c-file-style: "linux" | ||
22 | * End: | ||
23 | */ | ||
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c index af2f017617b4..fe8ec04d35bb 100644 --- a/arch/um/sys-x86_64/signal.c +++ b/arch/um/sys-x86_64/signal.c | |||
@@ -20,6 +20,36 @@ | |||
20 | 20 | ||
21 | #include "skas.h" | 21 | #include "skas.h" |
22 | 22 | ||
23 | void copy_sc(union uml_pt_regs *regs, void *from) | ||
24 | { | ||
25 | struct sigcontext *sc = from; | ||
26 | |||
27 | #define GETREG(regs, regno, sc, regname) \ | ||
28 | (regs)->skas.regs[(regno) / sizeof(unsigned long)] = (sc)->regname | ||
29 | |||
30 | GETREG(regs, R8, sc, r8); | ||
31 | GETREG(regs, R9, sc, r9); | ||
32 | GETREG(regs, R10, sc, r10); | ||
33 | GETREG(regs, R11, sc, r11); | ||
34 | GETREG(regs, R12, sc, r12); | ||
35 | GETREG(regs, R13, sc, r13); | ||
36 | GETREG(regs, R14, sc, r14); | ||
37 | GETREG(regs, R15, sc, r15); | ||
38 | GETREG(regs, RDI, sc, rdi); | ||
39 | GETREG(regs, RSI, sc, rsi); | ||
40 | GETREG(regs, RBP, sc, rbp); | ||
41 | GETREG(regs, RBX, sc, rbx); | ||
42 | GETREG(regs, RDX, sc, rdx); | ||
43 | GETREG(regs, RAX, sc, rax); | ||
44 | GETREG(regs, RCX, sc, rcx); | ||
45 | GETREG(regs, RSP, sc, rsp); | ||
46 | GETREG(regs, RIP, sc, rip); | ||
47 | GETREG(regs, EFLAGS, sc, eflags); | ||
48 | GETREG(regs, CS, sc, cs); | ||
49 | |||
50 | #undef GETREG | ||
51 | } | ||
52 | |||
23 | static int copy_sc_from_user_skas(struct pt_regs *regs, | 53 | static int copy_sc_from_user_skas(struct pt_regs *regs, |
24 | struct sigcontext __user *from) | 54 | struct sigcontext __user *from) |
25 | { | 55 | { |
@@ -51,7 +81,7 @@ static int copy_sc_from_user_skas(struct pt_regs *regs, | |||
51 | 81 | ||
52 | #undef GETREG | 82 | #undef GETREG |
53 | 83 | ||
54 | return(err); | 84 | return err; |
55 | } | 85 | } |
56 | 86 | ||
57 | int copy_sc_to_user_skas(struct sigcontext __user *to, | 87 | int copy_sc_to_user_skas(struct sigcontext __user *to, |
diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c index 899cebb57c3f..0d5fd764c21f 100644 --- a/arch/um/sys-x86_64/user-offsets.c +++ b/arch/um/sys-x86_64/user-offsets.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <stddef.h> | 2 | #include <stddef.h> |
3 | #include <signal.h> | 3 | #include <signal.h> |
4 | #include <sys/poll.h> | 4 | #include <sys/poll.h> |
5 | #include <sys/mman.h> | ||
5 | #define __FRAME_OFFSETS | 6 | #define __FRAME_OFFSETS |
6 | #include <asm/ptrace.h> | 7 | #include <asm/ptrace.h> |
7 | #include <asm/types.h> | 8 | #include <asm/types.h> |
@@ -57,7 +58,6 @@ void foo(void) | |||
57 | OFFSET(HOST_SC_SS, sigcontext, ss); | 58 | OFFSET(HOST_SC_SS, sigcontext, ss); |
58 | #endif | 59 | #endif |
59 | 60 | ||
60 | DEFINE_LONGS(HOST_FRAME_SIZE, FRAME_SIZE); | ||
61 | DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long)); | 61 | DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long)); |
62 | DEFINE(HOST_XFP_SIZE, 0); | 62 | DEFINE(HOST_XFP_SIZE, 0); |
63 | DEFINE_LONGS(HOST_RBX, RBX); | 63 | DEFINE_LONGS(HOST_RBX, RBX); |
@@ -94,4 +94,8 @@ void foo(void) | |||
94 | DEFINE(UM_POLLIN, POLLIN); | 94 | DEFINE(UM_POLLIN, POLLIN); |
95 | DEFINE(UM_POLLPRI, POLLPRI); | 95 | DEFINE(UM_POLLPRI, POLLPRI); |
96 | DEFINE(UM_POLLOUT, POLLOUT); | 96 | DEFINE(UM_POLLOUT, POLLOUT); |
97 | |||
98 | DEFINE(UM_PROT_READ, PROT_READ); | ||
99 | DEFINE(UM_PROT_WRITE, PROT_WRITE); | ||
100 | DEFINE(UM_PROT_EXEC, PROT_EXEC); | ||
97 | } | 101 | } |