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 6430a6383853..c58b657f0097 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 ab0d0b170816..7218c754505b 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 5d50d4a44abf..2f880cb167a5 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 dc36b222100b..04e3958266e0 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 c83fc5d68936..94de4ead4f7a 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 fbe2217db5dd..61951b721268 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 507e3cbac9d3..a61b7b46bc02 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 46ceb25a9959..6c2d4ccaf20f 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 217438cdef33..c9b078fba03e 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 e3d576567172..54388d10bcf9 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 8ebb2241ad42..8c7279bb353b 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 098fa65981ab..0e2f06187ea7 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 2ae76d8f1be1..d574e0a9dc13 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 9a6f5c85f902..a62f5ef445cf 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 9864d27afdbe..33d7982be5d3 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 a32ef55cb244..a4d6415bc8c4 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 101efd26d467..fa617e0719ab 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 cbd79a8d213d..d4de7c0120ce 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 c649108a9e9f..07176d92e1c9 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 eb1710b81255..2a1c64d8d0bf 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 4892e5fcef07..83b688ca198f 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 569fe8b9b053..c264e1c05ab3 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 f3b583a878a6..544665e04513 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 6f1a3a288117..3ef73bf2e781 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 eea1c9c4bb0f..000000000000 --- 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 3d29c90514cc..3fda9a03c59a 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 e2d3ca445ef5..27cdf9164422 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 52945338b64d..87c3aa0252db 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 f55773c819e6..3bd10deea280 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 7f5e2dac2a35..d261888f39c4 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 9890e9090f58..fbb080c2fc26 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 120a21c5883f..bbf34cb91ce1 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 6c5b17ed59e1..829d6b0d8b02 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 aee4812333c6..7a6f6b99ceff 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 4b638dfb52b0..001941fa1a1e 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 0cdfd4481d5e..fe0877b3509c 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 12e404c6fa46..b5f9c33e311e 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 5a585bfbb8c2..7bd54a921cf7 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); |
