diff options
author | Dave Kleikamp <shaggy@austin.ibm.com> | 2006-03-14 18:05:45 -0500 |
---|---|---|
committer | Dave Kleikamp <shaggy@austin.ibm.com> | 2006-03-14 18:05:45 -0500 |
commit | c5111f504d2a9b0d258d7c4752b4093523315989 (patch) | |
tree | 6a52864aff79691689aea21cb0cb928327d5de5b /arch/um | |
parent | 69eb66d7da7dba2696281981347698e1693c2340 (diff) | |
parent | a488edc914aa1d766a4e2c982b5ae03d5657ec1b (diff) |
Merge with /home/shaggy/git/linus-clean/
Diffstat (limited to 'arch/um')
38 files changed, 223 insertions, 688 deletions
diff --git a/arch/um/Makefile b/arch/um/Makefile index 6430a63838..c58b657f00 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile | |||
@@ -47,13 +47,16 @@ ARCH_INCLUDE += -I$(srctree)/$(ARCH_DIR)/include | |||
47 | endif | 47 | endif |
48 | SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH) | 48 | SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH) |
49 | 49 | ||
50 | # -Dvmap=kernel_vmap affects everything, and prevents anything from | 50 | # -Dvmap=kernel_vmap prevents anything from referencing the libpcap.o symbol so |
51 | # referencing the libpcap.o symbol so named. | 51 | # named - it's a common symbol in libpcap, so we get a binary which crashes. |
52 | # | 52 | # |
53 | # Same things for in6addr_loopback - found in libc. | 53 | # Same things for in6addr_loopback and mktime - found in libc. For these two we |
54 | # only get link-time error, luckily. | ||
55 | # | ||
56 | # These apply to USER_CFLAGS to. | ||
54 | 57 | ||
55 | CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ | 58 | CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ |
56 | $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \ | 59 | $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \ |
57 | -Din6addr_loopback=kernel_in6addr_loopback | 60 | -Din6addr_loopback=kernel_in6addr_loopback |
58 | 61 | ||
59 | AFLAGS += $(ARCH_INCLUDE) | 62 | AFLAGS += $(ARCH_INCLUDE) |
@@ -66,6 +69,7 @@ USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \ | |||
66 | # kernel_errno to separate them from the libc errno. This allows -fno-common | 69 | # kernel_errno to separate them from the libc errno. This allows -fno-common |
67 | # in CFLAGS. Otherwise, it would cause ld to complain about the two different | 70 | # in CFLAGS. Otherwise, it would cause ld to complain about the two different |
68 | # errnos. | 71 | # errnos. |
72 | # These apply to kernelspace only. | ||
69 | 73 | ||
70 | CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \ | 74 | CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \ |
71 | -Dmktime=kernel_mktime | 75 | -Dmktime=kernel_mktime |
@@ -168,10 +172,13 @@ else | |||
168 | $(Q)cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch | 172 | $(Q)cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch |
169 | endif | 173 | endif |
170 | 174 | ||
171 | $(ARCH_DIR)/include/sysdep: | 175 | $(objtree)/$(ARCH_DIR)/include: |
176 | @echo ' MKDIR $@' | ||
177 | $(Q)mkdir -p $@ | ||
178 | |||
179 | $(ARCH_DIR)/include/sysdep: $(objtree)/$(ARCH_DIR)/include | ||
172 | @echo ' SYMLINK $@' | 180 | @echo ' SYMLINK $@' |
173 | ifneq ($(KBUILD_SRC),) | 181 | ifneq ($(KBUILD_SRC),) |
174 | $(Q)mkdir -p $(ARCH_DIR)/include | ||
175 | $(Q)ln -fsn $(srctree)/$(ARCH_DIR)/include/sysdep-$(SUBARCH) $(ARCH_DIR)/include/sysdep | 182 | $(Q)ln -fsn $(srctree)/$(ARCH_DIR)/include/sysdep-$(SUBARCH) $(ARCH_DIR)/include/sysdep |
176 | else | 183 | else |
177 | $(Q)cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep | 184 | $(Q)cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep |
@@ -214,7 +221,7 @@ $(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/user-offsets.s | |||
214 | 221 | ||
215 | CLEAN_FILES += $(ARCH_DIR)/user-offsets.s | 222 | CLEAN_FILES += $(ARCH_DIR)/user-offsets.s |
216 | 223 | ||
217 | $(ARCH_DIR)/include/kern_constants.h: | 224 | $(ARCH_DIR)/include/kern_constants.h: $(objtree)/$(ARCH_DIR)/include |
218 | @echo ' SYMLINK $@' | 225 | @echo ' SYMLINK $@' |
219 | $(Q) ln -sf ../../../include/asm-um/asm-offsets.h $@ | 226 | $(Q) ln -sf ../../../include/asm-um/asm-offsets.h $@ |
220 | 227 | ||
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index ab0d0b1708..7218c75450 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c | |||
@@ -403,7 +403,7 @@ int chan_window_size(struct list_head *chans, unsigned short *rows_out, | |||
403 | return 0; | 403 | return 0; |
404 | } | 404 | } |
405 | 405 | ||
406 | void free_one_chan(struct chan *chan, int delay_free_irq) | 406 | static void free_one_chan(struct chan *chan, int delay_free_irq) |
407 | { | 407 | { |
408 | list_del(&chan->list); | 408 | list_del(&chan->list); |
409 | 409 | ||
@@ -416,7 +416,7 @@ void free_one_chan(struct chan *chan, int delay_free_irq) | |||
416 | kfree(chan); | 416 | kfree(chan); |
417 | } | 417 | } |
418 | 418 | ||
419 | void free_chan(struct list_head *chans, int delay_free_irq) | 419 | static void free_chan(struct list_head *chans, int delay_free_irq) |
420 | { | 420 | { |
421 | struct list_head *ele, *next; | 421 | struct list_head *ele, *next; |
422 | struct chan *chan; | 422 | struct chan *chan; |
@@ -497,7 +497,7 @@ struct chan_type { | |||
497 | struct chan_ops *ops; | 497 | struct chan_ops *ops; |
498 | }; | 498 | }; |
499 | 499 | ||
500 | struct chan_type chan_table[] = { | 500 | static struct chan_type chan_table[] = { |
501 | { "fd", &fd_ops }, | 501 | { "fd", &fd_ops }, |
502 | 502 | ||
503 | #ifdef CONFIG_NULL_CHAN | 503 | #ifdef CONFIG_NULL_CHAN |
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index 5d50d4a44a..2f880cb167 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <termios.h> | 9 | #include <termios.h> |
10 | #include <string.h> | 10 | #include <string.h> |
11 | #include <signal.h> | 11 | #include <signal.h> |
12 | #include <sched.h> | ||
12 | #include <sys/stat.h> | 13 | #include <sys/stat.h> |
13 | #include <sys/ioctl.h> | 14 | #include <sys/ioctl.h> |
14 | #include <sys/socket.h> | 15 | #include <sys/socket.h> |
@@ -73,7 +74,6 @@ static void winch_handler(int sig) | |||
73 | struct winch_data { | 74 | struct winch_data { |
74 | int pty_fd; | 75 | int pty_fd; |
75 | int pipe_fd; | 76 | int pipe_fd; |
76 | int close_me; | ||
77 | }; | 77 | }; |
78 | 78 | ||
79 | static int winch_thread(void *arg) | 79 | static int winch_thread(void *arg) |
@@ -84,7 +84,6 @@ static int winch_thread(void *arg) | |||
84 | int count, err; | 84 | int count, err; |
85 | char c = 1; | 85 | char c = 1; |
86 | 86 | ||
87 | os_close_file(data->close_me); | ||
88 | pty_fd = data->pty_fd; | 87 | pty_fd = data->pty_fd; |
89 | pipe_fd = data->pipe_fd; | 88 | pipe_fd = data->pipe_fd; |
90 | count = os_write_file(pipe_fd, &c, sizeof(c)); | 89 | count = os_write_file(pipe_fd, &c, sizeof(c)); |
@@ -153,15 +152,16 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out) | |||
153 | } | 152 | } |
154 | 153 | ||
155 | data = ((struct winch_data) { .pty_fd = fd, | 154 | data = ((struct winch_data) { .pty_fd = fd, |
156 | .pipe_fd = fds[1], | 155 | .pipe_fd = fds[1] } ); |
157 | .close_me = fds[0] } ); | 156 | /* CLONE_FILES so this thread doesn't hold open files which are open |
158 | err = run_helper_thread(winch_thread, &data, 0, &stack, 0); | 157 | * now, but later closed. This is a problem with /dev/net/tun. |
158 | */ | ||
159 | err = run_helper_thread(winch_thread, &data, CLONE_FILES, &stack, 0); | ||
159 | if(err < 0){ | 160 | if(err < 0){ |
160 | printk("fork of winch_thread failed - errno = %d\n", errno); | 161 | printk("fork of winch_thread failed - errno = %d\n", errno); |
161 | goto out_close; | 162 | goto out_close; |
162 | } | 163 | } |
163 | 164 | ||
164 | os_close_file(fds[1]); | ||
165 | *fd_out = fds[0]; | 165 | *fd_out = fds[0]; |
166 | n = os_read_file(fds[0], &c, sizeof(c)); | 166 | n = os_read_file(fds[0], &c, sizeof(c)); |
167 | if(n != sizeof(c)){ | 167 | if(n != sizeof(c)){ |
@@ -169,13 +169,12 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out) | |||
169 | printk("read failed, err = %d\n", -n); | 169 | printk("read failed, err = %d\n", -n); |
170 | printk("fd %d will not support SIGWINCH\n", fd); | 170 | printk("fd %d will not support SIGWINCH\n", fd); |
171 | err = -EINVAL; | 171 | err = -EINVAL; |
172 | goto out_close1; | 172 | goto out_close; |
173 | } | 173 | } |
174 | return err ; | 174 | return err ; |
175 | 175 | ||
176 | out_close: | 176 | out_close: |
177 | os_close_file(fds[1]); | 177 | os_close_file(fds[1]); |
178 | out_close1: | ||
179 | os_close_file(fds[0]); | 178 | os_close_file(fds[0]); |
180 | out: | 179 | out: |
181 | return err; | 180 | return err; |
diff --git a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h index dc36b22210..04e3958266 100644 --- a/arch/um/drivers/cow.h +++ b/arch/um/drivers/cow.h | |||
@@ -46,7 +46,7 @@ extern int file_reader(__u64 offset, char *buf, int len, void *arg); | |||
46 | extern int read_cow_header(int (*reader)(__u64, char *, int, void *), | 46 | extern int read_cow_header(int (*reader)(__u64, char *, int, void *), |
47 | void *arg, __u32 *version_out, | 47 | void *arg, __u32 *version_out, |
48 | char **backing_file_out, time_t *mtime_out, | 48 | char **backing_file_out, time_t *mtime_out, |
49 | unsigned long long *size_out, int *sectorsize_out, | 49 | __u64 *size_out, int *sectorsize_out, |
50 | __u32 *align_out, int *bitmap_offset_out); | 50 | __u32 *align_out, int *bitmap_offset_out); |
51 | 51 | ||
52 | extern int write_cow_header(char *cow_file, int fd, char *backing_file, | 52 | extern int write_cow_header(char *cow_file, int fd, char *backing_file, |
diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h index c83fc5d689..94de4ead4f 100644 --- a/arch/um/drivers/cow_sys.h +++ b/arch/um/drivers/cow_sys.h | |||
@@ -23,17 +23,17 @@ static inline char *cow_strdup(char *str) | |||
23 | return(uml_strdup(str)); | 23 | return(uml_strdup(str)); |
24 | } | 24 | } |
25 | 25 | ||
26 | static inline int cow_seek_file(int fd, unsigned long long offset) | 26 | static inline int cow_seek_file(int fd, __u64 offset) |
27 | { | 27 | { |
28 | return(os_seek_file(fd, offset)); | 28 | return(os_seek_file(fd, offset)); |
29 | } | 29 | } |
30 | 30 | ||
31 | static inline int cow_file_size(char *file, unsigned long long *size_out) | 31 | static inline int cow_file_size(char *file, __u64 *size_out) |
32 | { | 32 | { |
33 | return(os_file_size(file, size_out)); | 33 | return(os_file_size(file, size_out)); |
34 | } | 34 | } |
35 | 35 | ||
36 | static inline int cow_write_file(int fd, char *buf, int size) | 36 | static inline int cow_write_file(int fd, void *buf, int size) |
37 | { | 37 | { |
38 | return(os_write_file(fd, buf, size)); | 38 | return(os_write_file(fd, buf, size)); |
39 | } | 39 | } |
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c index fbe2217db5..61951b7212 100644 --- a/arch/um/drivers/cow_user.c +++ b/arch/um/drivers/cow_user.c | |||
@@ -176,7 +176,7 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, | |||
176 | err = -ENOMEM; | 176 | err = -ENOMEM; |
177 | header = cow_malloc(sizeof(*header)); | 177 | header = cow_malloc(sizeof(*header)); |
178 | if(header == NULL){ | 178 | if(header == NULL){ |
179 | cow_printf("Failed to allocate COW V3 header\n"); | 179 | cow_printf("write_cow_header - failed to allocate COW V3 header\n"); |
180 | goto out; | 180 | goto out; |
181 | } | 181 | } |
182 | header->magic = htonl(COW_MAGIC); | 182 | header->magic = htonl(COW_MAGIC); |
@@ -196,15 +196,17 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, | |||
196 | 196 | ||
197 | err = os_file_modtime(header->backing_file, &modtime); | 197 | err = os_file_modtime(header->backing_file, &modtime); |
198 | if(err < 0){ | 198 | if(err < 0){ |
199 | cow_printf("Backing file '%s' mtime request failed, " | 199 | cow_printf("write_cow_header - backing file '%s' mtime " |
200 | "err = %d\n", header->backing_file, -err); | 200 | "request failed, err = %d\n", header->backing_file, |
201 | -err); | ||
201 | goto out_free; | 202 | goto out_free; |
202 | } | 203 | } |
203 | 204 | ||
204 | err = cow_file_size(header->backing_file, size); | 205 | err = cow_file_size(header->backing_file, size); |
205 | if(err < 0){ | 206 | if(err < 0){ |
206 | cow_printf("Couldn't get size of backing file '%s', " | 207 | cow_printf("write_cow_header - couldn't get size of " |
207 | "err = %d\n", header->backing_file, -err); | 208 | "backing file '%s', err = %d\n", |
209 | header->backing_file, -err); | ||
208 | goto out_free; | 210 | goto out_free; |
209 | } | 211 | } |
210 | 212 | ||
@@ -214,10 +216,11 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, | |||
214 | header->alignment = htonl(alignment); | 216 | header->alignment = htonl(alignment); |
215 | header->cow_format = COW_BITMAP; | 217 | header->cow_format = COW_BITMAP; |
216 | 218 | ||
217 | err = os_write_file(fd, header, sizeof(*header)); | 219 | err = cow_write_file(fd, header, sizeof(*header)); |
218 | if(err != sizeof(*header)){ | 220 | if(err != sizeof(*header)){ |
219 | cow_printf("Write of header to new COW file '%s' failed, " | 221 | cow_printf("write_cow_header - write of header to " |
220 | "err = %d\n", cow_file, -err); | 222 | "new COW file '%s' failed, err = %d\n", cow_file, |
223 | -err); | ||
221 | goto out_free; | 224 | goto out_free; |
222 | } | 225 | } |
223 | err = 0; | 226 | err = 0; |
@@ -299,7 +302,7 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, | |||
299 | } | 302 | } |
300 | else if(version == 3){ | 303 | else if(version == 3){ |
301 | if(n < sizeof(header->v3)){ | 304 | if(n < sizeof(header->v3)){ |
302 | cow_printf("read_cow_header - failed to read V2 " | 305 | cow_printf("read_cow_header - failed to read V3 " |
303 | "header\n"); | 306 | "header\n"); |
304 | goto out; | 307 | goto out; |
305 | } | 308 | } |
@@ -359,7 +362,8 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, | |||
359 | if(err != sizeof(zero)){ | 362 | if(err != sizeof(zero)){ |
360 | cow_printf("Write of bitmap to new COW file '%s' failed, " | 363 | cow_printf("Write of bitmap to new COW file '%s' failed, " |
361 | "err = %d\n", cow_file, -err); | 364 | "err = %d\n", cow_file, -err); |
362 | err = -EINVAL; | 365 | if (err >= 0) |
366 | err = -EINVAL; | ||
363 | goto out; | 367 | goto out; |
364 | } | 368 | } |
365 | 369 | ||
diff --git a/arch/um/drivers/daemon_kern.c b/arch/um/drivers/daemon_kern.c index 507e3cbac9..a61b7b46bc 100644 --- a/arch/um/drivers/daemon_kern.c +++ b/arch/um/drivers/daemon_kern.c | |||
@@ -18,7 +18,7 @@ struct daemon_init { | |||
18 | char *ctl_sock; | 18 | char *ctl_sock; |
19 | }; | 19 | }; |
20 | 20 | ||
21 | void daemon_init(struct net_device *dev, void *data) | 21 | static void daemon_init(struct net_device *dev, void *data) |
22 | { | 22 | { |
23 | struct uml_net_private *pri; | 23 | struct uml_net_private *pri; |
24 | struct daemon_data *dpri; | 24 | struct daemon_data *dpri; |
@@ -64,7 +64,7 @@ static struct net_kern_info daemon_kern_info = { | |||
64 | .write = daemon_write, | 64 | .write = daemon_write, |
65 | }; | 65 | }; |
66 | 66 | ||
67 | int daemon_setup(char *str, char **mac_out, void *data) | 67 | static int daemon_setup(char *str, char **mac_out, void *data) |
68 | { | 68 | { |
69 | struct daemon_init *init = data; | 69 | struct daemon_init *init = data; |
70 | char *remain; | 70 | char *remain; |
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 46ceb25a99..6c2d4ccaf2 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c | |||
@@ -714,7 +714,7 @@ struct winch { | |||
714 | struct tty_struct *tty; | 714 | struct tty_struct *tty; |
715 | }; | 715 | }; |
716 | 716 | ||
717 | irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused) | 717 | static irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused) |
718 | { | 718 | { |
719 | struct winch *winch = data; | 719 | struct winch *winch = data; |
720 | struct tty_struct *tty; | 720 | struct tty_struct *tty; |
diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c index 217438cdef..c9b078fba0 100644 --- a/arch/um/drivers/mcast_kern.c +++ b/arch/um/drivers/mcast_kern.c | |||
@@ -26,7 +26,7 @@ struct mcast_init { | |||
26 | int ttl; | 26 | int ttl; |
27 | }; | 27 | }; |
28 | 28 | ||
29 | void mcast_init(struct net_device *dev, void *data) | 29 | static void mcast_init(struct net_device *dev, void *data) |
30 | { | 30 | { |
31 | struct uml_net_private *pri; | 31 | struct uml_net_private *pri; |
32 | struct mcast_data *dpri; | 32 | struct mcast_data *dpri; |
@@ -40,7 +40,7 @@ void mcast_init(struct net_device *dev, void *data) | |||
40 | dpri->dev = dev; | 40 | dpri->dev = dev; |
41 | 41 | ||
42 | printk("mcast backend "); | 42 | printk("mcast backend "); |
43 | printk("multicast adddress: %s:%u, TTL:%u ", | 43 | printk("multicast address: %s:%u, TTL:%u ", |
44 | dpri->addr, dpri->port, dpri->ttl); | 44 | dpri->addr, dpri->port, dpri->ttl); |
45 | 45 | ||
46 | printk("\n"); | 46 | printk("\n"); |
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index e3d5765671..54388d10bc 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c | |||
@@ -273,7 +273,7 @@ void mconsole_proc(struct mc_request *req) | |||
273 | config <dev> - Query the configuration of a device \n\ | 273 | config <dev> - Query the configuration of a device \n\ |
274 | remove <dev> - Remove a device from UML \n\ | 274 | remove <dev> - Remove a device from UML \n\ |
275 | sysrq <letter> - Performs the SysRq action controlled by the letter \n\ | 275 | sysrq <letter> - Performs the SysRq action controlled by the letter \n\ |
276 | cad - invoke the Ctl-Alt-Del handler \n\ | 276 | cad - invoke the Ctrl-Alt-Del handler \n\ |
277 | stop - pause the UML; it will do nothing until it receives a 'go' \n\ | 277 | stop - pause the UML; it will do nothing until it receives a 'go' \n\ |
278 | go - continue the UML after a 'stop' \n\ | 278 | go - continue the UML after a 'stop' \n\ |
279 | log <string> - make UML enter <string> into the kernel log\n\ | 279 | log <string> - make UML enter <string> into the kernel log\n\ |
@@ -327,7 +327,7 @@ void mconsole_stop(struct mc_request *req) | |||
327 | 327 | ||
328 | /* This list is populated by __initcall routines. */ | 328 | /* This list is populated by __initcall routines. */ |
329 | 329 | ||
330 | LIST_HEAD(mconsole_devices); | 330 | static LIST_HEAD(mconsole_devices); |
331 | 331 | ||
332 | void mconsole_register_dev(struct mc_device *new) | 332 | void mconsole_register_dev(struct mc_device *new) |
333 | { | 333 | { |
@@ -561,6 +561,8 @@ void mconsole_sysrq(struct mc_request *req) | |||
561 | } | 561 | } |
562 | #endif | 562 | #endif |
563 | 563 | ||
564 | #ifdef CONFIG_MODE_SKAS | ||
565 | |||
564 | static void stack_proc(void *arg) | 566 | static void stack_proc(void *arg) |
565 | { | 567 | { |
566 | struct task_struct *from = current, *to = arg; | 568 | struct task_struct *from = current, *to = arg; |
@@ -574,7 +576,7 @@ static void stack_proc(void *arg) | |||
574 | * Dumps a stacks registers to the linux console. | 576 | * Dumps a stacks registers to the linux console. |
575 | * Usage stack <pid>. | 577 | * Usage stack <pid>. |
576 | */ | 578 | */ |
577 | void do_stack(struct mc_request *req) | 579 | static void do_stack_trace(struct mc_request *req) |
578 | { | 580 | { |
579 | char *ptr = req->request.data; | 581 | char *ptr = req->request.data; |
580 | int pid_requested= -1; | 582 | int pid_requested= -1; |
@@ -605,6 +607,7 @@ void do_stack(struct mc_request *req) | |||
605 | } | 607 | } |
606 | with_console(req, stack_proc, to); | 608 | with_console(req, stack_proc, to); |
607 | } | 609 | } |
610 | #endif /* CONFIG_MODE_SKAS */ | ||
608 | 611 | ||
609 | void mconsole_stack(struct mc_request *req) | 612 | void mconsole_stack(struct mc_request *req) |
610 | { | 613 | { |
@@ -613,7 +616,7 @@ void mconsole_stack(struct mc_request *req) | |||
613 | */ | 616 | */ |
614 | CHOOSE_MODE(mconsole_reply(req, "Sorry, this doesn't work in TT mode", | 617 | CHOOSE_MODE(mconsole_reply(req, "Sorry, this doesn't work in TT mode", |
615 | 1, 0), | 618 | 1, 0), |
616 | do_stack(req)); | 619 | do_stack_trace(req)); |
617 | } | 620 | } |
618 | 621 | ||
619 | /* Changed by mconsole_setup, which is __setup, and called before SMP is | 622 | /* Changed by mconsole_setup, which is __setup, and called before SMP is |
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 8ebb2241ad..8c7279bb35 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c | |||
@@ -131,9 +131,8 @@ static int uml_net_open(struct net_device *dev) | |||
131 | SA_INTERRUPT | SA_SHIRQ, dev->name, dev); | 131 | SA_INTERRUPT | SA_SHIRQ, dev->name, dev); |
132 | if(err != 0){ | 132 | if(err != 0){ |
133 | printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err); | 133 | printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err); |
134 | if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); | ||
135 | lp->fd = -1; | ||
136 | err = -ENETUNREACH; | 134 | err = -ENETUNREACH; |
135 | goto out_close; | ||
137 | } | 136 | } |
138 | 137 | ||
139 | lp->tl.data = (unsigned long) &lp->user; | 138 | lp->tl.data = (unsigned long) &lp->user; |
@@ -145,9 +144,19 @@ static int uml_net_open(struct net_device *dev) | |||
145 | */ | 144 | */ |
146 | while((err = uml_net_rx(dev)) > 0) ; | 145 | while((err = uml_net_rx(dev)) > 0) ; |
147 | 146 | ||
148 | out: | ||
149 | spin_unlock(&lp->lock); | 147 | spin_unlock(&lp->lock); |
150 | return(err); | 148 | |
149 | spin_lock(&opened_lock); | ||
150 | list_add(&lp->list, &opened); | ||
151 | spin_unlock(&opened_lock); | ||
152 | |||
153 | return 0; | ||
154 | out_close: | ||
155 | if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); | ||
156 | lp->fd = -1; | ||
157 | out: | ||
158 | spin_unlock(&lp->lock); | ||
159 | return err; | ||
151 | } | 160 | } |
152 | 161 | ||
153 | static int uml_net_close(struct net_device *dev) | 162 | static int uml_net_close(struct net_device *dev) |
@@ -161,9 +170,13 @@ static int uml_net_close(struct net_device *dev) | |||
161 | if(lp->close != NULL) | 170 | if(lp->close != NULL) |
162 | (*lp->close)(lp->fd, &lp->user); | 171 | (*lp->close)(lp->fd, &lp->user); |
163 | lp->fd = -1; | 172 | lp->fd = -1; |
164 | list_del(&lp->list); | ||
165 | 173 | ||
166 | spin_unlock(&lp->lock); | 174 | spin_unlock(&lp->lock); |
175 | |||
176 | spin_lock(&opened_lock); | ||
177 | list_del(&lp->list); | ||
178 | spin_unlock(&opened_lock); | ||
179 | |||
167 | return 0; | 180 | return 0; |
168 | } | 181 | } |
169 | 182 | ||
@@ -410,11 +423,7 @@ static int eth_configure(int n, void *init, char *mac, | |||
410 | if (device->have_mac) | 423 | if (device->have_mac) |
411 | set_ether_mac(dev, device->mac); | 424 | set_ether_mac(dev, device->mac); |
412 | 425 | ||
413 | spin_lock(&opened_lock); | 426 | return 0; |
414 | list_add(&lp->list, &opened); | ||
415 | spin_unlock(&opened_lock); | ||
416 | |||
417 | return(0); | ||
418 | } | 427 | } |
419 | 428 | ||
420 | static struct uml_net *find_device(int n) | 429 | static struct uml_net *find_device(int n) |
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c index 098fa65981..0e2f06187e 100644 --- a/arch/um/drivers/net_user.c +++ b/arch/um/drivers/net_user.c | |||
@@ -47,10 +47,12 @@ void tap_check_ips(char *gate_addr, unsigned char *eth_addr) | |||
47 | } | 47 | } |
48 | } | 48 | } |
49 | 49 | ||
50 | /* Do reliable error handling as this fails frequently enough. */ | ||
50 | void read_output(int fd, char *output, int len) | 51 | void read_output(int fd, char *output, int len) |
51 | { | 52 | { |
52 | int remain, n, actual; | 53 | int remain, ret, expected; |
53 | char c; | 54 | char c; |
55 | char *str; | ||
54 | 56 | ||
55 | if(output == NULL){ | 57 | if(output == NULL){ |
56 | output = &c; | 58 | output = &c; |
@@ -58,23 +60,31 @@ void read_output(int fd, char *output, int len) | |||
58 | } | 60 | } |
59 | 61 | ||
60 | *output = '\0'; | 62 | *output = '\0'; |
61 | n = os_read_file(fd, &remain, sizeof(remain)); | 63 | ret = os_read_file(fd, &remain, sizeof(remain)); |
62 | if(n != sizeof(remain)){ | 64 | |
63 | printk("read_output - read of length failed, err = %d\n", -n); | 65 | if (ret != sizeof(remain)) { |
64 | return; | 66 | expected = sizeof(remain); |
67 | str = "length"; | ||
68 | goto err; | ||
65 | } | 69 | } |
66 | 70 | ||
67 | while(remain != 0){ | 71 | while(remain != 0){ |
68 | n = (remain < len) ? remain : len; | 72 | expected = (remain < len) ? remain : len; |
69 | actual = os_read_file(fd, output, n); | 73 | ret = os_read_file(fd, output, expected); |
70 | if(actual != n){ | 74 | if (ret != expected) { |
71 | printk("read_output - read of data failed, " | 75 | str = "data"; |
72 | "err = %d\n", -actual); | 76 | goto err; |
73 | return; | ||
74 | } | 77 | } |
75 | remain -= actual; | 78 | remain -= ret; |
76 | } | 79 | } |
80 | |||
77 | return; | 81 | return; |
82 | |||
83 | err: | ||
84 | if (ret < 0) | ||
85 | printk("read_output - read of %s failed, errno = %d\n", str, -ret); | ||
86 | else | ||
87 | printk("read_output - read of %s failed, read only %d of %d bytes\n", str, ret, expected); | ||
78 | } | 88 | } |
79 | 89 | ||
80 | int net_read(int fd, void *buf, int len) | 90 | int net_read(int fd, void *buf, int len) |
diff --git a/arch/um/drivers/slip_common.h b/arch/um/drivers/slip_common.h index 2ae76d8f1b..d574e0a9dc 100644 --- a/arch/um/drivers/slip_common.h +++ b/arch/um/drivers/slip_common.h | |||
@@ -88,12 +88,13 @@ struct slip_proto { | |||
88 | int esc; | 88 | int esc; |
89 | }; | 89 | }; |
90 | 90 | ||
91 | #define SLIP_PROTO_INIT { \ | 91 | static inline void slip_proto_init(struct slip_proto * slip) |
92 | .ibuf = { '\0' }, \ | 92 | { |
93 | .obuf = { '\0' }, \ | 93 | memset(slip->ibuf, 0, sizeof(slip->ibuf)); |
94 | .more = 0, \ | 94 | memset(slip->obuf, 0, sizeof(slip->obuf)); |
95 | .pos = 0, \ | 95 | slip->more = 0; |
96 | .esc = 0 \ | 96 | slip->pos = 0; |
97 | slip->esc = 0; | ||
97 | } | 98 | } |
98 | 99 | ||
99 | extern int slip_proto_read(int fd, void *buf, int len, | 100 | extern int slip_proto_read(int fd, void *buf, int len, |
diff --git a/arch/um/drivers/slip_kern.c b/arch/um/drivers/slip_kern.c index 9a6f5c85f9..a62f5ef445 100644 --- a/arch/um/drivers/slip_kern.c +++ b/arch/um/drivers/slip_kern.c | |||
@@ -21,13 +21,14 @@ void slip_init(struct net_device *dev, void *data) | |||
21 | 21 | ||
22 | private = dev->priv; | 22 | private = dev->priv; |
23 | spri = (struct slip_data *) private->user; | 23 | spri = (struct slip_data *) private->user; |
24 | *spri = ((struct slip_data) | 24 | |
25 | { .name = { '\0' }, | 25 | memset(spri->name, 0, sizeof(spri->name)); |
26 | .addr = NULL, | 26 | spri->addr = NULL; |
27 | .gate_addr = init->gate_addr, | 27 | spri->gate_addr = init->gate_addr; |
28 | .slave = -1, | 28 | spri->slave = -1; |
29 | .slip = SLIP_PROTO_INIT, | 29 | spri->dev = dev; |
30 | .dev = dev }); | 30 | |
31 | slip_proto_init(&spri->slip); | ||
31 | 32 | ||
32 | dev->init = NULL; | 33 | dev->init = NULL; |
33 | dev->header_cache_update = NULL; | 34 | dev->header_cache_update = NULL; |
diff --git a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c index 9864d27afd..33d7982be5 100644 --- a/arch/um/drivers/slirp_kern.c +++ b/arch/um/drivers/slirp_kern.c | |||
@@ -21,12 +21,13 @@ void slirp_init(struct net_device *dev, void *data) | |||
21 | 21 | ||
22 | private = dev->priv; | 22 | private = dev->priv; |
23 | spri = (struct slirp_data *) private->user; | 23 | spri = (struct slirp_data *) private->user; |
24 | *spri = ((struct slirp_data) | 24 | |
25 | { .argw = init->argw, | 25 | spri->argw = init->argw; |
26 | .pid = -1, | 26 | spri->pid = -1; |
27 | .slave = -1, | 27 | spri->slave = -1; |
28 | .slip = SLIP_PROTO_INIT, | 28 | spri->dev = dev; |
29 | .dev = dev }); | 29 | |
30 | slip_proto_init(&spri->slip); | ||
30 | 31 | ||
31 | dev->init = NULL; | 32 | dev->init = NULL; |
32 | dev->hard_header_len = 0; | 33 | dev->hard_header_len = 0; |
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index a32ef55cb2..a4d6415bc8 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c | |||
@@ -33,7 +33,7 @@ static struct tty_driver *ssl_driver; | |||
33 | 33 | ||
34 | #define NR_PORTS 64 | 34 | #define NR_PORTS 64 |
35 | 35 | ||
36 | void ssl_announce(char *dev_name, int dev) | 36 | static void ssl_announce(char *dev_name, int dev) |
37 | { | 37 | { |
38 | printk(KERN_INFO "Serial line %d assigned device '%s'\n", dev, | 38 | printk(KERN_INFO "Serial line %d assigned device '%s'\n", dev, |
39 | dev_name); | 39 | dev_name); |
@@ -98,7 +98,7 @@ static int ssl_remove(int n) | |||
98 | return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n); | 98 | return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n); |
99 | } | 99 | } |
100 | 100 | ||
101 | int ssl_open(struct tty_struct *tty, struct file *filp) | 101 | static int ssl_open(struct tty_struct *tty, struct file *filp) |
102 | { | 102 | { |
103 | return line_open(serial_lines, tty); | 103 | return line_open(serial_lines, tty); |
104 | } | 104 | } |
@@ -182,7 +182,7 @@ static struct console ssl_cons = { | |||
182 | .index = -1, | 182 | .index = -1, |
183 | }; | 183 | }; |
184 | 184 | ||
185 | int ssl_init(void) | 185 | static int ssl_init(void) |
186 | { | 186 | { |
187 | char *new_title; | 187 | char *new_title; |
188 | 188 | ||
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 101efd26d4..fa617e0719 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c | |||
@@ -1135,7 +1135,7 @@ static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow) | |||
1135 | static int backing_file_mismatch(char *file, __u64 size, time_t mtime) | 1135 | static int backing_file_mismatch(char *file, __u64 size, time_t mtime) |
1136 | { | 1136 | { |
1137 | unsigned long modtime; | 1137 | unsigned long modtime; |
1138 | long long actual; | 1138 | unsigned long long actual; |
1139 | int err; | 1139 | int err; |
1140 | 1140 | ||
1141 | err = os_file_modtime(file, &modtime); | 1141 | err = os_file_modtime(file, &modtime); |
diff --git a/arch/um/include/init.h b/arch/um/include/init.h index cbd79a8d21..d4de7c0120 100644 --- a/arch/um/include/init.h +++ b/arch/um/include/init.h | |||
@@ -122,7 +122,7 @@ extern struct uml_param __uml_setup_start, __uml_setup_end; | |||
122 | 122 | ||
123 | #define __exitcall(fn) static exitcall_t __exitcall_##fn __exit_call = fn | 123 | #define __exitcall(fn) static exitcall_t __exitcall_##fn __exit_call = fn |
124 | 124 | ||
125 | #define __init_call __attribute__ ((unused,__section__ (".initcall.init"))) | 125 | #define __init_call __attribute_used__ __attribute__ ((__section__ (".initcall.init"))) |
126 | 126 | ||
127 | #endif | 127 | #endif |
128 | 128 | ||
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h index c649108a9e..07176d92e1 100644 --- a/arch/um/include/kern_util.h +++ b/arch/um/include/kern_util.h | |||
@@ -31,8 +31,6 @@ extern int timer_irq_inited; | |||
31 | extern int jail; | 31 | extern int jail; |
32 | extern int nsyscalls; | 32 | extern int nsyscalls; |
33 | 33 | ||
34 | extern struct task_struct *idle_threads[NR_CPUS]; | ||
35 | |||
36 | #define UML_ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK)) | 34 | #define UML_ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK)) |
37 | #define UML_ROUND_UP(addr) \ | 35 | #define UML_ROUND_UP(addr) \ |
38 | UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1) | 36 | UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1) |
diff --git a/arch/um/include/os.h b/arch/um/include/os.h index eb1710b812..2a1c64d8d0 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h | |||
@@ -179,8 +179,11 @@ extern void os_stop_process(int pid); | |||
179 | extern void os_kill_process(int pid, int reap_child); | 179 | extern void os_kill_process(int pid, int reap_child); |
180 | extern void os_kill_ptraced_process(int pid, int reap_child); | 180 | extern void os_kill_ptraced_process(int pid, int reap_child); |
181 | extern void os_usr1_process(int pid); | 181 | extern void os_usr1_process(int pid); |
182 | extern long os_ptrace_ldt(long pid, long addr, long data); | ||
183 | |||
182 | extern int os_getpid(void); | 184 | extern int os_getpid(void); |
183 | extern int os_getpgrp(void); | 185 | extern int os_getpgrp(void); |
186 | |||
184 | extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)); | 187 | extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)); |
185 | extern void init_new_thread_signals(int altstack); | 188 | extern void init_new_thread_signals(int altstack); |
186 | extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr); | 189 | extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr); |
diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h index 4892e5fcef..83b688ca19 100644 --- a/arch/um/include/registers.h +++ b/arch/um/include/registers.h | |||
@@ -14,7 +14,7 @@ extern int restore_fp_registers(int pid, unsigned long *fp_regs); | |||
14 | extern void save_registers(int pid, union uml_pt_regs *regs); | 14 | extern void save_registers(int pid, union uml_pt_regs *regs); |
15 | extern void restore_registers(int pid, union uml_pt_regs *regs); | 15 | extern void restore_registers(int pid, union uml_pt_regs *regs); |
16 | extern void init_registers(int pid); | 16 | extern void init_registers(int pid); |
17 | extern void get_safe_registers(unsigned long * regs); | 17 | extern void get_safe_registers(unsigned long * regs, unsigned long * fp_regs); |
18 | extern void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer); | 18 | extern void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer); |
19 | 19 | ||
20 | #endif | 20 | #endif |
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c index 569fe8b9b0..c264e1c05a 100644 --- a/arch/um/kernel/exec_kern.c +++ b/arch/um/kernel/exec_kern.c | |||
@@ -33,7 +33,7 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) | |||
33 | extern void log_exec(char **argv, void *tty); | 33 | extern void log_exec(char **argv, void *tty); |
34 | 34 | ||
35 | static long execve1(char *file, char __user * __user *argv, | 35 | static long execve1(char *file, char __user * __user *argv, |
36 | char *__user __user *env) | 36 | char __user *__user *env) |
37 | { | 37 | { |
38 | long error; | 38 | long error; |
39 | 39 | ||
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index f3b583a878..544665e045 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c | |||
@@ -265,7 +265,7 @@ int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem) | |||
265 | highmem_len = highmem_pages * sizeof(struct page); | 265 | highmem_len = highmem_pages * sizeof(struct page); |
266 | 266 | ||
267 | total_pages = phys_pages + iomem_pages + highmem_pages; | 267 | total_pages = phys_pages + iomem_pages + highmem_pages; |
268 | total_len = phys_len + iomem_pages + highmem_len; | 268 | total_len = phys_len + iomem_len + highmem_len; |
269 | 269 | ||
270 | if(kmalloc_ok){ | 270 | if(kmalloc_ok){ |
271 | map = kmalloc(total_len, GFP_KERNEL); | 271 | map = kmalloc(total_len, GFP_KERNEL); |
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index 6f1a3a2881..3ef73bf2e7 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c | |||
@@ -5,6 +5,7 @@ | |||
5 | 5 | ||
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 "user_util.h" | 9 | #include "user_util.h" |
9 | #include "kern_util.h" | 10 | #include "kern_util.h" |
10 | #include "kern.h" | 11 | #include "kern.h" |
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c deleted file mode 100644 index eea1c9c4bb..0000000000 --- a/arch/um/kernel/skas/process.c +++ /dev/null | |||
@@ -1,569 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stdlib.h> | ||
7 | #include <string.h> | ||
8 | #include <unistd.h> | ||
9 | #include <errno.h> | ||
10 | #include <signal.h> | ||
11 | #include <setjmp.h> | ||
12 | #include <sched.h> | ||
13 | #include <sys/wait.h> | ||
14 | #include <sys/mman.h> | ||
15 | #include <sys/user.h> | ||
16 | #include <sys/time.h> | ||
17 | #include <asm/unistd.h> | ||
18 | #include <asm/types.h> | ||
19 | #include "user.h" | ||
20 | #include "ptrace_user.h" | ||
21 | #include "sysdep/ptrace.h" | ||
22 | #include "user_util.h" | ||
23 | #include "kern_util.h" | ||
24 | #include "skas.h" | ||
25 | #include "stub-data.h" | ||
26 | #include "mm_id.h" | ||
27 | #include "sysdep/sigcontext.h" | ||
28 | #include "sysdep/stub.h" | ||
29 | #include "os.h" | ||
30 | #include "proc_mm.h" | ||
31 | #include "skas_ptrace.h" | ||
32 | #include "chan_user.h" | ||
33 | #include "registers.h" | ||
34 | #include "mem.h" | ||
35 | #include "uml-config.h" | ||
36 | #include "process.h" | ||
37 | |||
38 | int is_skas_winch(int pid, int fd, void *data) | ||
39 | { | ||
40 | if(pid != os_getpgrp()) | ||
41 | return(0); | ||
42 | |||
43 | register_winch_irq(-1, fd, -1, data); | ||
44 | return(1); | ||
45 | } | ||
46 | |||
47 | void wait_stub_done(int pid, int sig, char * fname) | ||
48 | { | ||
49 | int n, status, err; | ||
50 | |||
51 | do { | ||
52 | if ( sig != -1 ) { | ||
53 | err = ptrace(PTRACE_CONT, pid, 0, sig); | ||
54 | if(err) | ||
55 | panic("%s : continue failed, errno = %d\n", | ||
56 | fname, errno); | ||
57 | } | ||
58 | sig = 0; | ||
59 | |||
60 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); | ||
61 | } while((n >= 0) && WIFSTOPPED(status) && | ||
62 | ((WSTOPSIG(status) == SIGVTALRM) || | ||
63 | /* running UML inside a detached screen can cause | ||
64 | * SIGWINCHes | ||
65 | */ | ||
66 | (WSTOPSIG(status) == SIGWINCH))); | ||
67 | |||
68 | if((n < 0) || !WIFSTOPPED(status) || | ||
69 | (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){ | ||
70 | unsigned long regs[HOST_FRAME_SIZE]; | ||
71 | if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) | ||
72 | printk("Failed to get registers from stub, " | ||
73 | "errno = %d\n", errno); | ||
74 | else { | ||
75 | int i; | ||
76 | |||
77 | printk("Stub registers -\n"); | ||
78 | for(i = 0; i < HOST_FRAME_SIZE; i++) | ||
79 | printk("\t%d - %lx\n", i, regs[i]); | ||
80 | } | ||
81 | panic("%s : failed to wait for SIGUSR1/SIGTRAP, " | ||
82 | "pid = %d, n = %d, errno = %d, status = 0x%x\n", | ||
83 | fname, pid, n, errno, status); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | void get_skas_faultinfo(int pid, struct faultinfo * fi) | ||
88 | { | ||
89 | int err; | ||
90 | |||
91 | if(ptrace_faultinfo){ | ||
92 | err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); | ||
93 | if(err) | ||
94 | panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " | ||
95 | "errno = %d\n", errno); | ||
96 | |||
97 | /* Special handling for i386, which has different structs */ | ||
98 | if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo)) | ||
99 | memset((char *)fi + sizeof(struct ptrace_faultinfo), 0, | ||
100 | sizeof(struct faultinfo) - | ||
101 | sizeof(struct ptrace_faultinfo)); | ||
102 | } | ||
103 | else { | ||
104 | wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo"); | ||
105 | |||
106 | /* faultinfo is prepared by the stub-segv-handler at start of | ||
107 | * the stub stack page. We just have to copy it. | ||
108 | */ | ||
109 | memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | static void handle_segv(int pid, union uml_pt_regs * regs) | ||
114 | { | ||
115 | get_skas_faultinfo(pid, ®s->skas.faultinfo); | ||
116 | segv(regs->skas.faultinfo, 0, 1, NULL); | ||
117 | } | ||
118 | |||
119 | /*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/ | ||
120 | static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu) | ||
121 | { | ||
122 | int err, status; | ||
123 | |||
124 | /* Mark this as a syscall */ | ||
125 | UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs); | ||
126 | |||
127 | if (!local_using_sysemu) | ||
128 | { | ||
129 | err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid); | ||
130 | if(err < 0) | ||
131 | panic("handle_trap - nullifying syscall failed errno = %d\n", | ||
132 | errno); | ||
133 | |||
134 | err = ptrace(PTRACE_SYSCALL, pid, 0, 0); | ||
135 | if(err < 0) | ||
136 | panic("handle_trap - continuing to end of syscall failed, " | ||
137 | "errno = %d\n", errno); | ||
138 | |||
139 | CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); | ||
140 | if((err < 0) || !WIFSTOPPED(status) || | ||
141 | (WSTOPSIG(status) != SIGTRAP + 0x80)) | ||
142 | panic("handle_trap - failed to wait at end of syscall, " | ||
143 | "errno = %d, status = %d\n", errno, status); | ||
144 | } | ||
145 | |||
146 | handle_syscall(regs); | ||
147 | } | ||
148 | |||
149 | extern int __syscall_stub_start; | ||
150 | int stub_code_fd = -1; | ||
151 | __u64 stub_code_offset; | ||
152 | |||
153 | static int userspace_tramp(void *stack) | ||
154 | { | ||
155 | void *addr; | ||
156 | |||
157 | ptrace(PTRACE_TRACEME, 0, 0, 0); | ||
158 | |||
159 | init_new_thread_signals(1); | ||
160 | enable_timer(); | ||
161 | |||
162 | if(!proc_mm){ | ||
163 | /* This has a pte, but it can't be mapped in with the usual | ||
164 | * tlb_flush mechanism because this is part of that mechanism | ||
165 | */ | ||
166 | addr = mmap64((void *) UML_CONFIG_STUB_CODE, page_size(), | ||
167 | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, | ||
168 | stub_code_fd, stub_code_offset); | ||
169 | if(addr == MAP_FAILED){ | ||
170 | printk("mapping stub code failed, errno = %d\n", | ||
171 | errno); | ||
172 | exit(1); | ||
173 | } | ||
174 | |||
175 | if(stack != NULL){ | ||
176 | int fd; | ||
177 | __u64 offset; | ||
178 | |||
179 | fd = phys_mapping(to_phys(stack), &offset); | ||
180 | addr = mmap((void *) UML_CONFIG_STUB_DATA, page_size(), | ||
181 | PROT_READ | PROT_WRITE, | ||
182 | MAP_FIXED | MAP_SHARED, fd, offset); | ||
183 | if(addr == MAP_FAILED){ | ||
184 | printk("mapping stub stack failed, " | ||
185 | "errno = %d\n", errno); | ||
186 | exit(1); | ||
187 | } | ||
188 | } | ||
189 | } | ||
190 | if(!ptrace_faultinfo){ | ||
191 | unsigned long v = UML_CONFIG_STUB_CODE + | ||
192 | (unsigned long) stub_segv_handler - | ||
193 | (unsigned long) &__syscall_stub_start; | ||
194 | |||
195 | set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size()); | ||
196 | set_handler(SIGSEGV, (void *) v, SA_ONSTACK, | ||
197 | SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, | ||
198 | SIGUSR1, -1); | ||
199 | } | ||
200 | |||
201 | os_stop_process(os_getpid()); | ||
202 | return(0); | ||
203 | } | ||
204 | |||
205 | /* Each element set once, and only accessed by a single processor anyway */ | ||
206 | #undef NR_CPUS | ||
207 | #define NR_CPUS 1 | ||
208 | int userspace_pid[NR_CPUS]; | ||
209 | |||
210 | int start_userspace(unsigned long stub_stack) | ||
211 | { | ||
212 | void *stack; | ||
213 | unsigned long sp; | ||
214 | int pid, status, n, flags; | ||
215 | |||
216 | if ( stub_code_fd == -1 ) | ||
217 | stub_code_fd = phys_mapping(to_phys(&__syscall_stub_start), | ||
218 | &stub_code_offset); | ||
219 | |||
220 | stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, | ||
221 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | ||
222 | if(stack == MAP_FAILED) | ||
223 | panic("start_userspace : mmap failed, errno = %d", errno); | ||
224 | sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); | ||
225 | |||
226 | flags = CLONE_FILES | SIGCHLD; | ||
227 | if(proc_mm) flags |= CLONE_VM; | ||
228 | pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); | ||
229 | if(pid < 0) | ||
230 | panic("start_userspace : clone failed, errno = %d", errno); | ||
231 | |||
232 | do { | ||
233 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); | ||
234 | if(n < 0) | ||
235 | panic("start_userspace : wait failed, errno = %d", | ||
236 | errno); | ||
237 | } while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); | ||
238 | |||
239 | if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) | ||
240 | panic("start_userspace : expected SIGSTOP, got status = %d", | ||
241 | status); | ||
242 | |||
243 | if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0) | ||
244 | panic("start_userspace : PTRACE_SETOPTIONS failed, errno=%d\n", | ||
245 | errno); | ||
246 | |||
247 | if(munmap(stack, PAGE_SIZE) < 0) | ||
248 | panic("start_userspace : munmap failed, errno = %d\n", errno); | ||
249 | |||
250 | return(pid); | ||
251 | } | ||
252 | |||
253 | void userspace(union uml_pt_regs *regs) | ||
254 | { | ||
255 | int err, status, op, pid = userspace_pid[0]; | ||
256 | int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/ | ||
257 | |||
258 | while(1){ | ||
259 | restore_registers(pid, regs); | ||
260 | |||
261 | /* Now we set local_using_sysemu to be used for one loop */ | ||
262 | local_using_sysemu = get_using_sysemu(); | ||
263 | |||
264 | op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL)); | ||
265 | |||
266 | err = ptrace(op, pid, 0, 0); | ||
267 | if(err) | ||
268 | panic("userspace - could not resume userspace process, " | ||
269 | "pid=%d, ptrace operation = %d, errno = %d\n", | ||
270 | op, errno); | ||
271 | |||
272 | CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); | ||
273 | if(err < 0) | ||
274 | panic("userspace - waitpid failed, errno = %d\n", | ||
275 | errno); | ||
276 | |||
277 | regs->skas.is_user = 1; | ||
278 | save_registers(pid, regs); | ||
279 | UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ | ||
280 | |||
281 | if(WIFSTOPPED(status)){ | ||
282 | switch(WSTOPSIG(status)){ | ||
283 | case SIGSEGV: | ||
284 | if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo) | ||
285 | user_signal(SIGSEGV, regs, pid); | ||
286 | else handle_segv(pid, regs); | ||
287 | break; | ||
288 | case SIGTRAP + 0x80: | ||
289 | handle_trap(pid, regs, local_using_sysemu); | ||
290 | break; | ||
291 | case SIGTRAP: | ||
292 | relay_signal(SIGTRAP, regs); | ||
293 | break; | ||
294 | case SIGIO: | ||
295 | case SIGVTALRM: | ||
296 | case SIGILL: | ||
297 | case SIGBUS: | ||
298 | case SIGFPE: | ||
299 | case SIGWINCH: | ||
300 | user_signal(WSTOPSIG(status), regs, pid); | ||
301 | break; | ||
302 | default: | ||
303 | printk("userspace - child stopped with signal " | ||
304 | "%d\n", WSTOPSIG(status)); | ||
305 | } | ||
306 | pid = userspace_pid[0]; | ||
307 | interrupt_end(); | ||
308 | |||
309 | /* Avoid -ERESTARTSYS handling in host */ | ||
310 | PT_SYSCALL_NR(regs->skas.regs) = -1; | ||
311 | } | ||
312 | } | ||
313 | } | ||
314 | #define INIT_JMP_NEW_THREAD 0 | ||
315 | #define INIT_JMP_REMOVE_SIGSTACK 1 | ||
316 | #define INIT_JMP_CALLBACK 2 | ||
317 | #define INIT_JMP_HALT 3 | ||
318 | #define INIT_JMP_REBOOT 4 | ||
319 | |||
320 | |||
321 | int copy_context_skas0(unsigned long new_stack, int pid) | ||
322 | { | ||
323 | int err; | ||
324 | unsigned long regs[MAX_REG_NR]; | ||
325 | unsigned long current_stack = current_stub_stack(); | ||
326 | struct stub_data *data = (struct stub_data *) current_stack; | ||
327 | struct stub_data *child_data = (struct stub_data *) new_stack; | ||
328 | __u64 new_offset; | ||
329 | int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset); | ||
330 | |||
331 | /* prepare offset and fd of child's stack as argument for parent's | ||
332 | * and child's mmap2 calls | ||
333 | */ | ||
334 | *data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset), | ||
335 | .fd = new_fd, | ||
336 | .timer = ((struct itimerval) | ||
337 | { { 0, 1000000 / hz() }, | ||
338 | { 0, 1000000 / hz() }})}); | ||
339 | get_safe_registers(regs); | ||
340 | |||
341 | /* Set parent's instruction pointer to start of clone-stub */ | ||
342 | regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + | ||
343 | (unsigned long) stub_clone_handler - | ||
344 | (unsigned long) &__syscall_stub_start; | ||
345 | regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE - | ||
346 | sizeof(void *); | ||
347 | err = ptrace_setregs(pid, regs); | ||
348 | if(err < 0) | ||
349 | panic("copy_context_skas0 : PTRACE_SETREGS failed, " | ||
350 | "pid = %d, errno = %d\n", pid, errno); | ||
351 | |||
352 | /* set a well known return code for detection of child write failure */ | ||
353 | child_data->err = 12345678; | ||
354 | |||
355 | /* Wait, until parent has finished its work: read child's pid from | ||
356 | * parent's stack, and check, if bad result. | ||
357 | */ | ||
358 | wait_stub_done(pid, 0, "copy_context_skas0"); | ||
359 | |||
360 | pid = data->err; | ||
361 | if(pid < 0) | ||
362 | panic("copy_context_skas0 - stub-parent reports error %d\n", | ||
363 | pid); | ||
364 | |||
365 | /* Wait, until child has finished too: read child's result from | ||
366 | * child's stack and check it. | ||
367 | */ | ||
368 | wait_stub_done(pid, -1, "copy_context_skas0"); | ||
369 | if (child_data->err != UML_CONFIG_STUB_DATA) | ||
370 | panic("copy_context_skas0 - stub-child reports error %d\n", | ||
371 | child_data->err); | ||
372 | |||
373 | if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, | ||
374 | (void *)PTRACE_O_TRACESYSGOOD) < 0) | ||
375 | panic("copy_context_skas0 : PTRACE_SETOPTIONS failed, " | ||
376 | "errno = %d\n", errno); | ||
377 | |||
378 | return pid; | ||
379 | } | ||
380 | |||
381 | /* | ||
382 | * This is used only, if stub pages are needed, while proc_mm is | ||
383 | * availabl. Opening /proc/mm creates a new mm_context, which lacks | ||
384 | * the stub-pages. Thus, we map them using /proc/mm-fd | ||
385 | */ | ||
386 | void map_stub_pages(int fd, unsigned long code, | ||
387 | unsigned long data, unsigned long stack) | ||
388 | { | ||
389 | struct proc_mm_op mmop; | ||
390 | int n; | ||
391 | |||
392 | mmop = ((struct proc_mm_op) { .op = MM_MMAP, | ||
393 | .u = | ||
394 | { .mmap = | ||
395 | { .addr = code, | ||
396 | .len = PAGE_SIZE, | ||
397 | .prot = PROT_EXEC, | ||
398 | .flags = MAP_FIXED | MAP_PRIVATE, | ||
399 | .fd = stub_code_fd, | ||
400 | .offset = stub_code_offset | ||
401 | } } }); | ||
402 | n = os_write_file(fd, &mmop, sizeof(mmop)); | ||
403 | if(n != sizeof(mmop)) | ||
404 | panic("map_stub_pages : /proc/mm map for code failed, " | ||
405 | "err = %d\n", -n); | ||
406 | |||
407 | if ( stack ) { | ||
408 | __u64 map_offset; | ||
409 | int map_fd = phys_mapping(to_phys((void *)stack), &map_offset); | ||
410 | mmop = ((struct proc_mm_op) | ||
411 | { .op = MM_MMAP, | ||
412 | .u = | ||
413 | { .mmap = | ||
414 | { .addr = data, | ||
415 | .len = PAGE_SIZE, | ||
416 | .prot = PROT_READ | PROT_WRITE, | ||
417 | .flags = MAP_FIXED | MAP_SHARED, | ||
418 | .fd = map_fd, | ||
419 | .offset = map_offset | ||
420 | } } }); | ||
421 | n = os_write_file(fd, &mmop, sizeof(mmop)); | ||
422 | if(n != sizeof(mmop)) | ||
423 | panic("map_stub_pages : /proc/mm map for data failed, " | ||
424 | "err = %d\n", -n); | ||
425 | } | ||
426 | } | ||
427 | |||
428 | void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, | ||
429 | void (*handler)(int)) | ||
430 | { | ||
431 | unsigned long flags; | ||
432 | sigjmp_buf switch_buf, fork_buf; | ||
433 | |||
434 | *switch_buf_ptr = &switch_buf; | ||
435 | *fork_buf_ptr = &fork_buf; | ||
436 | |||
437 | /* Somewhat subtle - siglongjmp restores the signal mask before doing | ||
438 | * the longjmp. This means that when jumping from one stack to another | ||
439 | * when the target stack has interrupts enabled, an interrupt may occur | ||
440 | * on the source stack. This is bad when starting up a process because | ||
441 | * it's not supposed to get timer ticks until it has been scheduled. | ||
442 | * So, we disable interrupts around the sigsetjmp to ensure that | ||
443 | * they can't happen until we get back here where they are safe. | ||
444 | */ | ||
445 | flags = get_signals(); | ||
446 | block_signals(); | ||
447 | if(sigsetjmp(fork_buf, 1) == 0) | ||
448 | new_thread_proc(stack, handler); | ||
449 | |||
450 | remove_sigstack(); | ||
451 | |||
452 | set_signals(flags); | ||
453 | } | ||
454 | |||
455 | void thread_wait(void *sw, void *fb) | ||
456 | { | ||
457 | sigjmp_buf buf, **switch_buf = sw, *fork_buf; | ||
458 | |||
459 | *switch_buf = &buf; | ||
460 | fork_buf = fb; | ||
461 | if(sigsetjmp(buf, 1) == 0) | ||
462 | siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK); | ||
463 | } | ||
464 | |||
465 | void switch_threads(void *me, void *next) | ||
466 | { | ||
467 | sigjmp_buf my_buf, **me_ptr = me, *next_buf = next; | ||
468 | |||
469 | *me_ptr = &my_buf; | ||
470 | if(sigsetjmp(my_buf, 1) == 0) | ||
471 | siglongjmp(*next_buf, 1); | ||
472 | } | ||
473 | |||
474 | static sigjmp_buf initial_jmpbuf; | ||
475 | |||
476 | /* XXX Make these percpu */ | ||
477 | static void (*cb_proc)(void *arg); | ||
478 | static void *cb_arg; | ||
479 | static sigjmp_buf *cb_back; | ||
480 | |||
481 | int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) | ||
482 | { | ||
483 | sigjmp_buf **switch_buf = switch_buf_ptr; | ||
484 | int n; | ||
485 | |||
486 | set_handler(SIGWINCH, (__sighandler_t) sig_handler, | ||
487 | SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, | ||
488 | SIGVTALRM, -1); | ||
489 | |||
490 | *fork_buf_ptr = &initial_jmpbuf; | ||
491 | n = sigsetjmp(initial_jmpbuf, 1); | ||
492 | switch(n){ | ||
493 | case INIT_JMP_NEW_THREAD: | ||
494 | new_thread_proc((void *) stack, new_thread_handler); | ||
495 | break; | ||
496 | case INIT_JMP_REMOVE_SIGSTACK: | ||
497 | remove_sigstack(); | ||
498 | break; | ||
499 | case INIT_JMP_CALLBACK: | ||
500 | (*cb_proc)(cb_arg); | ||
501 | siglongjmp(*cb_back, 1); | ||
502 | break; | ||
503 | case INIT_JMP_HALT: | ||
504 | kmalloc_ok = 0; | ||
505 | return(0); | ||
506 | case INIT_JMP_REBOOT: | ||
507 | kmalloc_ok = 0; | ||
508 | return(1); | ||
509 | default: | ||
510 | panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); | ||
511 | } | ||
512 | siglongjmp(**switch_buf, 1); | ||
513 | } | ||
514 | |||
515 | void initial_thread_cb_skas(void (*proc)(void *), void *arg) | ||
516 | { | ||
517 | sigjmp_buf here; | ||
518 | |||
519 | cb_proc = proc; | ||
520 | cb_arg = arg; | ||
521 | cb_back = &here; | ||
522 | |||
523 | block_signals(); | ||
524 | if(sigsetjmp(here, 1) == 0) | ||
525 | siglongjmp(initial_jmpbuf, INIT_JMP_CALLBACK); | ||
526 | unblock_signals(); | ||
527 | |||
528 | cb_proc = NULL; | ||
529 | cb_arg = NULL; | ||
530 | cb_back = NULL; | ||
531 | } | ||
532 | |||
533 | void halt_skas(void) | ||
534 | { | ||
535 | block_signals(); | ||
536 | siglongjmp(initial_jmpbuf, INIT_JMP_HALT); | ||
537 | } | ||
538 | |||
539 | void reboot_skas(void) | ||
540 | { | ||
541 | block_signals(); | ||
542 | siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT); | ||
543 | } | ||
544 | |||
545 | void switch_mm_skas(struct mm_id *mm_idp) | ||
546 | { | ||
547 | int err; | ||
548 | |||
549 | #warning need cpu pid in switch_mm_skas | ||
550 | if(proc_mm){ | ||
551 | err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, | ||
552 | mm_idp->u.mm_fd); | ||
553 | if(err) | ||
554 | panic("switch_mm_skas - PTRACE_SWITCH_MM failed, " | ||
555 | "errno = %d\n", errno); | ||
556 | } | ||
557 | else userspace_pid[0] = mm_idp->u.pid; | ||
558 | } | ||
559 | |||
560 | /* | ||
561 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
562 | * Emacs will notice this stuff at the end of the file and automatically | ||
563 | * adjust the settings for this buffer only. This must remain at the end | ||
564 | * of the file. | ||
565 | * --------------------------------------------------------------------------- | ||
566 | * Local variables: | ||
567 | * c-file-style: "linux" | ||
568 | * End: | ||
569 | */ | ||
diff --git a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c index 3d29c90514..3fda9a03c5 100644 --- a/arch/um/kernel/tt/syscall_kern.c +++ b/arch/um/kernel/tt/syscall_kern.c | |||
@@ -23,16 +23,20 @@ void syscall_handler_tt(int sig, struct pt_regs *regs) | |||
23 | int syscall; | 23 | int syscall; |
24 | #ifdef CONFIG_SYSCALL_DEBUG | 24 | #ifdef CONFIG_SYSCALL_DEBUG |
25 | int index; | 25 | int index; |
26 | index = record_syscall_start(syscall); | ||
27 | #endif | 26 | #endif |
28 | sc = UPT_SC(®s->regs); | 27 | sc = UPT_SC(®s->regs); |
29 | SC_START_SYSCALL(sc); | 28 | SC_START_SYSCALL(sc); |
30 | 29 | ||
30 | syscall = UPT_SYSCALL_NR(®s->regs); | ||
31 | |||
32 | #ifdef CONFIG_SYSCALL_DEBUG | ||
33 | index = record_syscall_start(syscall); | ||
34 | #endif | ||
35 | |||
31 | syscall_trace(®s->regs, 0); | 36 | syscall_trace(®s->regs, 0); |
32 | 37 | ||
33 | current->thread.nsyscalls++; | 38 | current->thread.nsyscalls++; |
34 | nsyscalls++; | 39 | nsyscalls++; |
35 | syscall = UPT_SYSCALL_NR(®s->regs); | ||
36 | 40 | ||
37 | if((syscall >= NR_syscalls) || (syscall < 0)) | 41 | if((syscall >= NR_syscalls) || (syscall < 0)) |
38 | result = -ENOSYS; | 42 | result = -ENOSYS; |
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index e2d3ca445e..27cdf91644 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c | |||
@@ -193,6 +193,24 @@ __uml_setup("root=", uml_root_setup, | |||
193 | " root=/dev/ubd5\n\n" | 193 | " root=/dev/ubd5\n\n" |
194 | ); | 194 | ); |
195 | 195 | ||
196 | #ifndef CONFIG_MODE_TT | ||
197 | |||
198 | static int __init no_skas_debug_setup(char *line, int *add) | ||
199 | { | ||
200 | printf("'debug' is not necessary to gdb UML in skas mode - run \n"); | ||
201 | printf("'gdb linux' and disable CONFIG_CMDLINE_ON_HOST if gdb \n"); | ||
202 | printf("doesn't work as expected\n"); | ||
203 | |||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | __uml_setup("debug", no_skas_debug_setup, | ||
208 | "debug\n" | ||
209 | " this flag is not needed to run gdb on UML in skas mode\n\n" | ||
210 | ); | ||
211 | |||
212 | #endif | ||
213 | |||
196 | #ifdef CONFIG_SMP | 214 | #ifdef CONFIG_SMP |
197 | static int __init uml_ncpus_setup(char *line, int *add) | 215 | static int __init uml_ncpus_setup(char *line, int *add) |
198 | { | 216 | { |
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c index 52945338b6..87c3aa0252 100644 --- a/arch/um/os-Linux/drivers/tuntap_user.c +++ b/arch/um/os-Linux/drivers/tuntap_user.c | |||
@@ -122,6 +122,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, | |||
122 | return(-EINVAL); | 122 | return(-EINVAL); |
123 | } | 123 | } |
124 | *fd_out = ((int *) CMSG_DATA(cmsg))[0]; | 124 | *fd_out = ((int *) CMSG_DATA(cmsg))[0]; |
125 | os_set_exec_close(*fd_out, 1); | ||
125 | return(0); | 126 | return(0); |
126 | } | 127 | } |
127 | 128 | ||
@@ -137,7 +138,8 @@ static int tuntap_open(void *data) | |||
137 | return(err); | 138 | return(err); |
138 | 139 | ||
139 | if(pri->fixed_config){ | 140 | if(pri->fixed_config){ |
140 | pri->fd = os_open_file("/dev/net/tun", of_rdwr(OPENFLAGS()), 0); | 141 | pri->fd = os_open_file("/dev/net/tun", |
142 | of_cloexec(of_rdwr(OPENFLAGS())), 0); | ||
141 | if(pri->fd < 0){ | 143 | if(pri->fd < 0){ |
142 | printk("Failed to open /dev/net/tun, err = %d\n", | 144 | printk("Failed to open /dev/net/tun, err = %d\n", |
143 | -pri->fd); | 145 | -pri->fd); |
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c index f55773c819..3bd10deea2 100644 --- a/arch/um/os-Linux/file.c +++ b/arch/um/os-Linux/file.c | |||
@@ -272,14 +272,23 @@ int os_connect_socket(char *name) | |||
272 | snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name); | 272 | snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name); |
273 | 273 | ||
274 | fd = socket(AF_UNIX, SOCK_STREAM, 0); | 274 | fd = socket(AF_UNIX, SOCK_STREAM, 0); |
275 | if(fd < 0) | 275 | if(fd < 0) { |
276 | return(fd); | 276 | err = -errno; |
277 | goto out; | ||
278 | } | ||
277 | 279 | ||
278 | err = connect(fd, (struct sockaddr *) &sock, sizeof(sock)); | 280 | err = connect(fd, (struct sockaddr *) &sock, sizeof(sock)); |
279 | if(err) | 281 | if(err) { |
280 | return(-errno); | 282 | err = -errno; |
283 | goto out_close; | ||
284 | } | ||
281 | 285 | ||
282 | return(fd); | 286 | return fd; |
287 | |||
288 | out_close: | ||
289 | close(fd); | ||
290 | out: | ||
291 | return err; | ||
283 | } | 292 | } |
284 | 293 | ||
285 | void os_close_file(int fd) | 294 | void os_close_file(int fd) |
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index 7f5e2dac2a..d261888f39 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include "irq_user.h" | 19 | #include "irq_user.h" |
20 | #include "kern_util.h" | 20 | #include "kern_util.h" |
21 | #include "longjmp.h" | 21 | #include "longjmp.h" |
22 | #include "skas_ptrace.h" | ||
22 | 23 | ||
23 | #define ARBITRARY_ADDR -1 | 24 | #define ARBITRARY_ADDR -1 |
24 | #define FAILURE_PID -1 | 25 | #define FAILURE_PID -1 |
@@ -100,6 +101,21 @@ void os_kill_process(int pid, int reap_child) | |||
100 | 101 | ||
101 | } | 102 | } |
102 | 103 | ||
104 | /* This is here uniquely to have access to the userspace errno, i.e. the one | ||
105 | * used by ptrace in case of error. | ||
106 | */ | ||
107 | |||
108 | long os_ptrace_ldt(long pid, long addr, long data) | ||
109 | { | ||
110 | int ret; | ||
111 | |||
112 | ret = ptrace(PTRACE_LDT, pid, addr, data); | ||
113 | |||
114 | if (ret < 0) | ||
115 | return -errno; | ||
116 | return ret; | ||
117 | } | ||
118 | |||
103 | /* Kill off a ptraced child by all means available. kill it normally first, | 119 | /* Kill off a ptraced child by all means available. kill it normally first, |
104 | * then PTRACE_KILL it, then PTRACE_CONT it in case it's in a run state from | 120 | * then PTRACE_KILL it, then PTRACE_CONT it in case it's in a run state from |
105 | * which it can't exit directly. | 121 | * which it can't exit directly. |
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c index 9890e9090f..fbb080c2fc 100644 --- a/arch/um/os-Linux/skas/mem.c +++ b/arch/um/os-Linux/skas/mem.c | |||
@@ -60,7 +60,7 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) | |||
60 | 60 | ||
61 | multi_count++; | 61 | multi_count++; |
62 | 62 | ||
63 | get_safe_registers(regs); | 63 | get_safe_registers(regs, NULL); |
64 | regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + | 64 | regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + |
65 | ((unsigned long) &batch_syscall_stub - | 65 | ((unsigned long) &batch_syscall_stub - |
66 | (unsigned long) &__syscall_stub_start); | 66 | (unsigned long) &__syscall_stub_start); |
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 120a21c588..bbf34cb91c 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c | |||
@@ -310,16 +310,12 @@ void userspace(union uml_pt_regs *regs) | |||
310 | } | 310 | } |
311 | } | 311 | } |
312 | } | 312 | } |
313 | #define INIT_JMP_NEW_THREAD 0 | ||
314 | #define INIT_JMP_REMOVE_SIGSTACK 1 | ||
315 | #define INIT_JMP_CALLBACK 2 | ||
316 | #define INIT_JMP_HALT 3 | ||
317 | #define INIT_JMP_REBOOT 4 | ||
318 | 313 | ||
319 | int copy_context_skas0(unsigned long new_stack, int pid) | 314 | int copy_context_skas0(unsigned long new_stack, int pid) |
320 | { | 315 | { |
321 | int err; | 316 | int err; |
322 | unsigned long regs[MAX_REG_NR]; | 317 | unsigned long regs[HOST_FRAME_SIZE]; |
318 | unsigned long fp_regs[HOST_FP_SIZE]; | ||
323 | unsigned long current_stack = current_stub_stack(); | 319 | unsigned long current_stack = current_stub_stack(); |
324 | struct stub_data *data = (struct stub_data *) current_stack; | 320 | struct stub_data *data = (struct stub_data *) current_stack; |
325 | struct stub_data *child_data = (struct stub_data *) new_stack; | 321 | struct stub_data *child_data = (struct stub_data *) new_stack; |
@@ -334,7 +330,7 @@ int copy_context_skas0(unsigned long new_stack, int pid) | |||
334 | .timer = ((struct itimerval) | 330 | .timer = ((struct itimerval) |
335 | { { 0, 1000000 / hz() }, | 331 | { { 0, 1000000 / hz() }, |
336 | { 0, 1000000 / hz() }})}); | 332 | { 0, 1000000 / hz() }})}); |
337 | get_safe_registers(regs); | 333 | get_safe_registers(regs, fp_regs); |
338 | 334 | ||
339 | /* Set parent's instruction pointer to start of clone-stub */ | 335 | /* Set parent's instruction pointer to start of clone-stub */ |
340 | regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + | 336 | regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + |
@@ -350,6 +346,11 @@ int copy_context_skas0(unsigned long new_stack, int pid) | |||
350 | panic("copy_context_skas0 : PTRACE_SETREGS failed, " | 346 | panic("copy_context_skas0 : PTRACE_SETREGS failed, " |
351 | "pid = %d, errno = %d\n", pid, errno); | 347 | "pid = %d, errno = %d\n", pid, errno); |
352 | 348 | ||
349 | err = ptrace_setfpregs(pid, fp_regs); | ||
350 | if(err < 0) | ||
351 | panic("copy_context_skas0 : PTRACE_SETFPREGS failed, " | ||
352 | "pid = %d, errno = %d\n", pid, errno); | ||
353 | |||
353 | /* set a well known return code for detection of child write failure */ | 354 | /* set a well known return code for detection of child write failure */ |
354 | child_data->err = 12345678; | 355 | child_data->err = 12345678; |
355 | 356 | ||
@@ -457,6 +458,12 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, | |||
457 | set_signals(flags); | 458 | set_signals(flags); |
458 | } | 459 | } |
459 | 460 | ||
461 | #define INIT_JMP_NEW_THREAD 0 | ||
462 | #define INIT_JMP_REMOVE_SIGSTACK 1 | ||
463 | #define INIT_JMP_CALLBACK 2 | ||
464 | #define INIT_JMP_HALT 3 | ||
465 | #define INIT_JMP_REBOOT 4 | ||
466 | |||
460 | void thread_wait(void *sw, void *fb) | 467 | void thread_wait(void *sw, void *fb) |
461 | { | 468 | { |
462 | sigjmp_buf buf, **switch_buf = sw, *fork_buf; | 469 | sigjmp_buf buf, **switch_buf = sw, *fork_buf; |
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 6c5b17ed59..829d6b0d8b 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c | |||
@@ -49,6 +49,7 @@ static int ptrace_child(void *arg) | |||
49 | int pid = os_getpid(), ppid = getppid(); | 49 | int pid = os_getpid(), ppid = getppid(); |
50 | int sc_result; | 50 | int sc_result; |
51 | 51 | ||
52 | change_sig(SIGWINCH, 0); | ||
52 | if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ | 53 | if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ |
53 | perror("ptrace"); | 54 | perror("ptrace"); |
54 | os_kill_process(pid, 0); | 55 | os_kill_process(pid, 0); |
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c index aee4812333..7a6f6b99ce 100644 --- a/arch/um/os-Linux/sys-i386/registers.c +++ b/arch/um/os-Linux/sys-i386/registers.c | |||
@@ -122,9 +122,12 @@ void init_registers(int pid) | |||
122 | err); | 122 | err); |
123 | } | 123 | } |
124 | 124 | ||
125 | void get_safe_registers(unsigned long *regs) | 125 | void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) |
126 | { | 126 | { |
127 | memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long)); | 127 | memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long)); |
128 | if(fp_regs != NULL) | ||
129 | memcpy(fp_regs, exec_fp_regs, | ||
130 | HOST_FP_SIZE * sizeof(unsigned long)); | ||
128 | } | 131 | } |
129 | 132 | ||
130 | void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer) | 133 | void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer) |
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c index 4b638dfb52..001941fa1a 100644 --- a/arch/um/os-Linux/sys-x86_64/registers.c +++ b/arch/um/os-Linux/sys-x86_64/registers.c | |||
@@ -70,9 +70,12 @@ void init_registers(int pid) | |||
70 | err); | 70 | err); |
71 | } | 71 | } |
72 | 72 | ||
73 | void get_safe_registers(unsigned long *regs) | 73 | void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) |
74 | { | 74 | { |
75 | memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long)); | 75 | memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long)); |
76 | if(fp_regs != NULL) | ||
77 | memcpy(fp_regs, exec_fp_regs, | ||
78 | HOST_FP_SIZE * sizeof(unsigned long)); | ||
76 | } | 79 | } |
77 | 80 | ||
78 | void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer) | 81 | void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer) |
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index 0cdfd4481d..fe0877b350 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include "choose-mode.h" | 16 | #include "choose-mode.h" |
17 | #include "kern.h" | 17 | #include "kern.h" |
18 | #include "mode_kern.h" | 18 | #include "mode_kern.h" |
19 | #include "proc_mm.h" | ||
20 | #include "os.h" | 19 | #include "os.h" |
21 | 20 | ||
22 | extern int modify_ldt(int func, void *ptr, unsigned long bytecount); | 21 | extern int modify_ldt(int func, void *ptr, unsigned long bytecount); |
@@ -90,6 +89,7 @@ out: | |||
90 | #include "skas.h" | 89 | #include "skas.h" |
91 | #include "skas_ptrace.h" | 90 | #include "skas_ptrace.h" |
92 | #include "asm/mmu_context.h" | 91 | #include "asm/mmu_context.h" |
92 | #include "proc_mm.h" | ||
93 | 93 | ||
94 | long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, | 94 | long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, |
95 | void **addr, int done) | 95 | void **addr, int done) |
@@ -107,7 +107,7 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, | |||
107 | * So we need to switch child's mm into our userspace, then | 107 | * So we need to switch child's mm into our userspace, then |
108 | * later switch back. | 108 | * later switch back. |
109 | * | 109 | * |
110 | * Note: I'm unshure: should interrupts be disabled here? | 110 | * Note: I'm unsure: should interrupts be disabled here? |
111 | */ | 111 | */ |
112 | if(!current->active_mm || current->active_mm == &init_mm || | 112 | if(!current->active_mm || current->active_mm == &init_mm || |
113 | mm_idp != ¤t->active_mm->context.skas.id) | 113 | mm_idp != ¤t->active_mm->context.skas.id) |
@@ -129,9 +129,7 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, | |||
129 | pid = userspace_pid[cpu]; | 129 | pid = userspace_pid[cpu]; |
130 | } | 130 | } |
131 | 131 | ||
132 | res = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op); | 132 | res = os_ptrace_ldt(pid, 0, (unsigned long) &ldt_op); |
133 | if(res) | ||
134 | res = errno; | ||
135 | 133 | ||
136 | if(proc_mm) | 134 | if(proc_mm) |
137 | put_cpu(); | 135 | put_cpu(); |
@@ -181,8 +179,7 @@ static long read_ldt_from_host(void __user * ptr, unsigned long bytecount) | |||
181 | */ | 179 | */ |
182 | 180 | ||
183 | cpu = get_cpu(); | 181 | cpu = get_cpu(); |
184 | res = ptrace(PTRACE_LDT, userspace_pid[cpu], 0, | 182 | res = os_ptrace_ldt(userspace_pid[cpu], 0, (unsigned long) &ptrace_ldt); |
185 | (unsigned long) &ptrace_ldt); | ||
186 | put_cpu(); | 183 | put_cpu(); |
187 | if(res < 0) | 184 | if(res < 0) |
188 | goto out; | 185 | goto out; |
diff --git a/arch/um/sys-x86_64/ptrace_user.c b/arch/um/sys-x86_64/ptrace_user.c index 12e404c6fa..b5f9c33e31 100644 --- a/arch/um/sys-x86_64/ptrace_user.c +++ b/arch/um/sys-x86_64/ptrace_user.c | |||
@@ -24,6 +24,13 @@ int ptrace_setregs(long pid, unsigned long *regs) | |||
24 | return(0); | 24 | return(0); |
25 | } | 25 | } |
26 | 26 | ||
27 | int ptrace_setfpregs(long pid, unsigned long *regs) | ||
28 | { | ||
29 | if (ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0) | ||
30 | return -errno; | ||
31 | return 0; | ||
32 | } | ||
33 | |||
27 | void ptrace_pokeuser(unsigned long addr, unsigned long data) | 34 | void ptrace_pokeuser(unsigned long addr, unsigned long data) |
28 | { | 35 | { |
29 | panic("ptrace_pokeuser"); | 36 | panic("ptrace_pokeuser"); |
diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c index 5a585bfbb8..7bd54a921c 100644 --- a/arch/um/sys-x86_64/user-offsets.c +++ b/arch/um/sys-x86_64/user-offsets.c | |||
@@ -57,7 +57,7 @@ void foo(void) | |||
57 | #endif | 57 | #endif |
58 | 58 | ||
59 | DEFINE_LONGS(HOST_FRAME_SIZE, FRAME_SIZE); | 59 | DEFINE_LONGS(HOST_FRAME_SIZE, FRAME_SIZE); |
60 | DEFINE(HOST_FP_SIZE, 0); | 60 | DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long)); |
61 | DEFINE(HOST_XFP_SIZE, 0); | 61 | DEFINE(HOST_XFP_SIZE, 0); |
62 | DEFINE_LONGS(HOST_RBX, RBX); | 62 | DEFINE_LONGS(HOST_RBX, RBX); |
63 | DEFINE_LONGS(HOST_RCX, RCX); | 63 | DEFINE_LONGS(HOST_RCX, RCX); |