diff options
Diffstat (limited to 'arch/um/os-Linux')
26 files changed, 237 insertions, 194 deletions
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index f4bfc4c7ccac..b4183929b32c 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile | |||
| @@ -4,15 +4,19 @@ | |||
| 4 | # | 4 | # |
| 5 | 5 | ||
| 6 | obj-y = aio.o elf_aux.o file.o helper.o irq.o main.o mem.o process.o sigio.o \ | 6 | obj-y = aio.o elf_aux.o file.o helper.o irq.o main.o mem.o process.o sigio.o \ |
| 7 | signal.o start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o tls.o \ | 7 | signal.o start_up.o time.o trap.o tty.o uaccess.o umid.o tls.o \ |
| 8 | user_syms.o util.o drivers/ sys-$(SUBARCH)/ | 8 | user_syms.o util.o drivers/ sys-$(SUBARCH)/ |
| 9 | 9 | ||
| 10 | obj-$(CONFIG_MODE_SKAS) += skas/ | 10 | obj-$(CONFIG_MODE_SKAS) += skas/ |
| 11 | |||
| 12 | obj-$(CONFIG_MODE_TT) += tt.o | ||
| 13 | user-objs-$(CONFIG_MODE_TT) += tt.o | ||
| 14 | |||
| 11 | obj-$(CONFIG_TTY_LOG) += tty_log.o | 15 | obj-$(CONFIG_TTY_LOG) += tty_log.o |
| 12 | user-objs-$(CONFIG_TTY_LOG) += tty_log.o | 16 | user-objs-$(CONFIG_TTY_LOG) += tty_log.o |
| 13 | 17 | ||
| 14 | USER_OBJS := $(user-objs-y) aio.o elf_aux.o file.o helper.o irq.o main.o mem.o \ | 18 | USER_OBJS := $(user-objs-y) aio.o elf_aux.o file.o helper.o irq.o main.o mem.o \ |
| 15 | process.o sigio.o signal.o start_up.o time.o trap.o tt.o tty.o tls.o \ | 19 | process.o sigio.o signal.o start_up.o time.o trap.o tty.o tls.o \ |
| 16 | uaccess.o umid.o util.o | 20 | uaccess.o umid.o util.o |
| 17 | 21 | ||
| 18 | CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) | 22 | CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) |
diff --git a/arch/um/os-Linux/drivers/etap.h b/arch/um/os-Linux/drivers/etap.h index b84f6c4740f7..57ecdaf2f67e 100644 --- a/arch/um/os-Linux/drivers/etap.h +++ b/arch/um/os-Linux/drivers/etap.h | |||
| @@ -13,7 +13,7 @@ struct ethertap_data { | |||
| 13 | void *dev; | 13 | void *dev; |
| 14 | }; | 14 | }; |
| 15 | 15 | ||
| 16 | extern struct net_user_info ethertap_user_info; | 16 | extern const struct net_user_info ethertap_user_info; |
| 17 | 17 | ||
| 18 | /* | 18 | /* |
| 19 | * Overrides for Emacs so that we follow Linus's tabbing style. | 19 | * Overrides for Emacs so that we follow Linus's tabbing style. |
diff --git a/arch/um/os-Linux/drivers/ethertap_kern.c b/arch/um/os-Linux/drivers/ethertap_kern.c index 768606bec233..16385e2ada85 100644 --- a/arch/um/os-Linux/drivers/ethertap_kern.c +++ b/arch/um/os-Linux/drivers/ethertap_kern.c | |||
| @@ -65,7 +65,7 @@ static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) | |||
| 65 | return(net_send(fd, (*skb)->data, (*skb)->len)); | 65 | return(net_send(fd, (*skb)->data, (*skb)->len)); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | struct net_kern_info ethertap_kern_info = { | 68 | const struct net_kern_info ethertap_kern_info = { |
| 69 | .init = etap_init, | 69 | .init = etap_init, |
| 70 | .protocol = eth_protocol, | 70 | .protocol = eth_protocol, |
| 71 | .read = etap_read, | 71 | .read = etap_read, |
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c index 8f49507e64ef..f559bdf746e6 100644 --- a/arch/um/os-Linux/drivers/ethertap_user.c +++ b/arch/um/os-Linux/drivers/ethertap_user.c | |||
| @@ -216,7 +216,7 @@ static void etap_del_addr(unsigned char *addr, unsigned char *netmask, | |||
| 216 | etap_close_addr(addr, netmask, &pri->control_fd); | 216 | etap_close_addr(addr, netmask, &pri->control_fd); |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | struct net_user_info ethertap_user_info = { | 219 | const struct net_user_info ethertap_user_info = { |
| 220 | .init = etap_user_init, | 220 | .init = etap_user_init, |
| 221 | .open = etap_open, | 221 | .open = etap_open, |
| 222 | .close = etap_close, | 222 | .close = etap_close, |
diff --git a/arch/um/os-Linux/drivers/tuntap.h b/arch/um/os-Linux/drivers/tuntap.h index 25d4a2868814..d3e8d3af6245 100644 --- a/arch/um/os-Linux/drivers/tuntap.h +++ b/arch/um/os-Linux/drivers/tuntap.h | |||
| @@ -16,7 +16,7 @@ struct tuntap_data { | |||
| 16 | void *dev; | 16 | void *dev; |
| 17 | }; | 17 | }; |
| 18 | 18 | ||
| 19 | extern struct net_user_info tuntap_user_info; | 19 | extern const struct net_user_info tuntap_user_info; |
| 20 | 20 | ||
| 21 | #endif | 21 | #endif |
| 22 | 22 | ||
diff --git a/arch/um/os-Linux/drivers/tuntap_kern.c b/arch/um/os-Linux/drivers/tuntap_kern.c index 190009a6f89c..0edbac63c527 100644 --- a/arch/um/os-Linux/drivers/tuntap_kern.c +++ b/arch/um/os-Linux/drivers/tuntap_kern.c | |||
| @@ -53,7 +53,7 @@ static int tuntap_write(int fd, struct sk_buff **skb, | |||
| 53 | return(net_write(fd, (*skb)->data, (*skb)->len)); | 53 | return(net_write(fd, (*skb)->data, (*skb)->len)); |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | struct net_kern_info tuntap_kern_info = { | 56 | const struct net_kern_info tuntap_kern_info = { |
| 57 | .init = tuntap_init, | 57 | .init = tuntap_init, |
| 58 | .protocol = eth_protocol, | 58 | .protocol = eth_protocol, |
| 59 | .read = tuntap_read, | 59 | .read = tuntap_read, |
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c index 87c3aa0252db..e846b23f7558 100644 --- a/arch/um/os-Linux/drivers/tuntap_user.c +++ b/arch/um/os-Linux/drivers/tuntap_user.c | |||
| @@ -205,7 +205,7 @@ static int tuntap_set_mtu(int mtu, void *data) | |||
| 205 | return(mtu); | 205 | return(mtu); |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | struct net_user_info tuntap_user_info = { | 208 | const struct net_user_info tuntap_user_info = { |
| 209 | .init = tuntap_user_init, | 209 | .init = tuntap_user_init, |
| 210 | .open = tuntap_open, | 210 | .open = tuntap_open, |
| 211 | .close = tuntap_close, | 211 | .close = tuntap_close, |
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index 6987d1d247a2..cd15b9df5b5c 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c | |||
| @@ -42,7 +42,7 @@ static int helper_child(void *arg) | |||
| 42 | if(data->pre_exec != NULL) | 42 | if(data->pre_exec != NULL) |
| 43 | (*data->pre_exec)(data->pre_data); | 43 | (*data->pre_exec)(data->pre_data); |
| 44 | execvp(argv[0], argv); | 44 | execvp(argv[0], argv); |
| 45 | errval = errno; | 45 | errval = -errno; |
| 46 | printk("helper_child - execve of '%s' failed - errno = %d\n", argv[0], errno); | 46 | printk("helper_child - execve of '%s' failed - errno = %d\n", argv[0], errno); |
| 47 | os_write_file(data->fd, &errval, sizeof(errval)); | 47 | os_write_file(data->fd, &errval, sizeof(errval)); |
| 48 | kill(os_getpid(), SIGKILL); | 48 | kill(os_getpid(), SIGKILL); |
| @@ -62,7 +62,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, | |||
| 62 | stack = *stack_out; | 62 | stack = *stack_out; |
| 63 | else stack = alloc_stack(0, __cant_sleep()); | 63 | else stack = alloc_stack(0, __cant_sleep()); |
| 64 | if(stack == 0) | 64 | if(stack == 0) |
| 65 | return(-ENOMEM); | 65 | return -ENOMEM; |
| 66 | 66 | ||
| 67 | ret = os_pipe(fds, 1, 0); | 67 | ret = os_pipe(fds, 1, 0); |
| 68 | if(ret < 0){ | 68 | if(ret < 0){ |
| @@ -95,16 +95,16 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, | |||
| 95 | /* Read the errno value from the child, if the exec failed, or get 0 if | 95 | /* Read the errno value from the child, if the exec failed, or get 0 if |
| 96 | * the exec succeeded because the pipe fd was set as close-on-exec. */ | 96 | * the exec succeeded because the pipe fd was set as close-on-exec. */ |
| 97 | n = os_read_file(fds[0], &ret, sizeof(ret)); | 97 | n = os_read_file(fds[0], &ret, sizeof(ret)); |
| 98 | if (n < 0) { | 98 | if(n == 0) |
| 99 | printk("run_helper : read on pipe failed, ret = %d\n", -n); | ||
| 100 | ret = n; | ||
| 101 | kill(pid, SIGKILL); | ||
| 102 | CATCH_EINTR(waitpid(pid, NULL, 0)); | ||
| 103 | } else if(n != 0){ | ||
| 104 | CATCH_EINTR(n = waitpid(pid, NULL, 0)); | ||
| 105 | ret = -errno; | ||
| 106 | } else { | ||
| 107 | ret = pid; | 99 | ret = pid; |
| 100 | else { | ||
| 101 | if(n < 0){ | ||
| 102 | printk("run_helper : read on pipe failed, ret = %d\n", | ||
| 103 | -n); | ||
| 104 | ret = n; | ||
| 105 | kill(pid, SIGKILL); | ||
| 106 | } | ||
| 107 | CATCH_EINTR(waitpid(pid, NULL, 0)); | ||
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | out_close: | 110 | out_close: |
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c index 7555bf9c33d9..a97206df5b52 100644 --- a/arch/um/os-Linux/irq.c +++ b/arch/um/os-Linux/irq.c | |||
| @@ -132,7 +132,7 @@ void os_set_pollfd(int i, int fd) | |||
| 132 | 132 | ||
| 133 | void os_set_ioignore(void) | 133 | void os_set_ioignore(void) |
| 134 | { | 134 | { |
| 135 | set_handler(SIGIO, SIG_IGN, 0, -1); | 135 | signal(SIGIO, SIG_IGN); |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | void init_irq_signals(int on_sigstack) | 138 | void init_irq_signals(int on_sigstack) |
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index 90912aaca7aa..d1c5670787dc 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c | |||
| @@ -67,13 +67,32 @@ static __init void do_uml_initcalls(void) | |||
| 67 | 67 | ||
| 68 | static void last_ditch_exit(int sig) | 68 | static void last_ditch_exit(int sig) |
| 69 | { | 69 | { |
| 70 | signal(SIGINT, SIG_DFL); | ||
| 71 | signal(SIGTERM, SIG_DFL); | ||
| 72 | signal(SIGHUP, SIG_DFL); | ||
| 73 | uml_cleanup(); | 70 | uml_cleanup(); |
| 74 | exit(1); | 71 | exit(1); |
| 75 | } | 72 | } |
| 76 | 73 | ||
| 74 | static void install_fatal_handler(int sig) | ||
| 75 | { | ||
| 76 | struct sigaction action; | ||
| 77 | |||
| 78 | /* All signals are enabled in this handler ... */ | ||
| 79 | sigemptyset(&action.sa_mask); | ||
| 80 | |||
| 81 | /* ... including the signal being handled, plus we want the | ||
| 82 | * handler reset to the default behavior, so that if an exit | ||
| 83 | * handler is hanging for some reason, the UML will just die | ||
| 84 | * after this signal is sent a second time. | ||
| 85 | */ | ||
| 86 | action.sa_flags = SA_RESETHAND | SA_NODEFER; | ||
| 87 | action.sa_restorer = NULL; | ||
| 88 | action.sa_handler = last_ditch_exit; | ||
| 89 | if(sigaction(sig, &action, NULL) < 0){ | ||
| 90 | printf("failed to install handler for signal %d - errno = %d\n", | ||
| 91 | errno); | ||
| 92 | exit(1); | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 77 | #define UML_LIB_PATH ":/usr/lib/uml" | 96 | #define UML_LIB_PATH ":/usr/lib/uml" |
| 78 | 97 | ||
| 79 | static void setup_env_path(void) | 98 | static void setup_env_path(void) |
| @@ -158,9 +177,12 @@ int main(int argc, char **argv, char **envp) | |||
| 158 | } | 177 | } |
| 159 | new_argv[argc] = NULL; | 178 | new_argv[argc] = NULL; |
| 160 | 179 | ||
| 161 | set_handler(SIGINT, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); | 180 | /* Allow these signals to bring down a UML if all other |
| 162 | set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); | 181 | * methods of control fail. |
| 163 | set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); | 182 | */ |
| 183 | install_fatal_handler(SIGINT); | ||
| 184 | install_fatal_handler(SIGTERM); | ||
| 185 | install_fatal_handler(SIGHUP); | ||
| 164 | 186 | ||
| 165 | scan_elf_aux( envp); | 187 | scan_elf_aux( envp); |
| 166 | 188 | ||
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index 560c8063c77c..b170b4704dc4 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c | |||
| @@ -114,14 +114,14 @@ static void which_tmpdir(void) | |||
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | while(1){ | 116 | while(1){ |
| 117 | found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' '); | 117 | found = next(fd, buf, ARRAY_SIZE(buf), ' '); |
| 118 | if(found != 1) | 118 | if(found != 1) |
| 119 | break; | 119 | break; |
| 120 | 120 | ||
| 121 | if(!strncmp(buf, "/dev/shm", strlen("/dev/shm"))) | 121 | if(!strncmp(buf, "/dev/shm", strlen("/dev/shm"))) |
| 122 | goto found; | 122 | goto found; |
| 123 | 123 | ||
| 124 | found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), '\n'); | 124 | found = next(fd, buf, ARRAY_SIZE(buf), '\n'); |
| 125 | if(found != 1) | 125 | if(found != 1) |
| 126 | break; | 126 | break; |
| 127 | } | 127 | } |
| @@ -135,7 +135,7 @@ err: | |||
| 135 | return; | 135 | return; |
| 136 | 136 | ||
| 137 | found: | 137 | found: |
| 138 | found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' '); | 138 | found = next(fd, buf, ARRAY_SIZE(buf), ' '); |
| 139 | if(found != 1) | 139 | if(found != 1) |
| 140 | goto err; | 140 | goto err; |
| 141 | 141 | ||
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index b98d3ca2cd1b..ff203625a4bd 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | #include <stdio.h> | 7 | #include <stdio.h> |
| 8 | #include <errno.h> | 8 | #include <errno.h> |
| 9 | #include <signal.h> | 9 | #include <signal.h> |
| 10 | #include <setjmp.h> | ||
| 11 | #include <linux/unistd.h> | 10 | #include <linux/unistd.h> |
| 12 | #include <sys/mman.h> | 11 | #include <sys/mman.h> |
| 13 | #include <sys/wait.h> | 12 | #include <sys/wait.h> |
| @@ -247,7 +246,17 @@ void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)) | |||
| 247 | set_sigstack(sig_stack, pages * page_size()); | 246 | set_sigstack(sig_stack, pages * page_size()); |
| 248 | flags = SA_ONSTACK; | 247 | flags = SA_ONSTACK; |
| 249 | } | 248 | } |
| 250 | if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1); | 249 | if(usr1_handler){ |
| 250 | struct sigaction sa; | ||
| 251 | |||
| 252 | sa.sa_handler = usr1_handler; | ||
| 253 | sigemptyset(&sa.sa_mask); | ||
| 254 | sa.sa_flags = flags; | ||
| 255 | sa.sa_restorer = NULL; | ||
| 256 | if(sigaction(SIGUSR1, &sa, NULL) < 0) | ||
| 257 | panic("init_new_thread_stack - sigaction failed - " | ||
| 258 | "errno = %d\n", errno); | ||
| 259 | } | ||
| 251 | } | 260 | } |
| 252 | 261 | ||
| 253 | void init_new_thread_signals(void) | 262 | void init_new_thread_signals(void) |
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c index 0ecac563c7b3..f6457765b17d 100644 --- a/arch/um/os-Linux/sigio.c +++ b/arch/um/os-Linux/sigio.c | |||
| @@ -43,17 +43,9 @@ struct pollfds { | |||
| 43 | /* Protected by sigio_lock(). Used by the sigio thread, but the UML thread | 43 | /* Protected by sigio_lock(). Used by the sigio thread, but the UML thread |
| 44 | * synchronizes with it. | 44 | * synchronizes with it. |
| 45 | */ | 45 | */ |
| 46 | static struct pollfds current_poll = { | 46 | static struct pollfds current_poll; |
| 47 | .poll = NULL, | 47 | static struct pollfds next_poll; |
| 48 | .size = 0, | 48 | static struct pollfds all_sigio_fds; |
| 49 | .used = 0 | ||
| 50 | }; | ||
| 51 | |||
| 52 | static struct pollfds next_poll = { | ||
| 53 | .poll = NULL, | ||
| 54 | .size = 0, | ||
| 55 | .used = 0 | ||
| 56 | }; | ||
| 57 | 49 | ||
| 58 | static int write_sigio_thread(void *unused) | 50 | static int write_sigio_thread(void *unused) |
| 59 | { | 51 | { |
| @@ -78,7 +70,8 @@ static int write_sigio_thread(void *unused) | |||
| 78 | n = os_read_file(sigio_private[1], &c, sizeof(c)); | 70 | n = os_read_file(sigio_private[1], &c, sizeof(c)); |
| 79 | if(n != sizeof(c)) | 71 | if(n != sizeof(c)) |
| 80 | printk("write_sigio_thread : " | 72 | printk("write_sigio_thread : " |
| 81 | "read failed, err = %d\n", -n); | 73 | "read on socket failed, " |
| 74 | "err = %d\n", -n); | ||
| 82 | tmp = current_poll; | 75 | tmp = current_poll; |
| 83 | current_poll = next_poll; | 76 | current_poll = next_poll; |
| 84 | next_poll = tmp; | 77 | next_poll = tmp; |
| @@ -93,35 +86,36 @@ static int write_sigio_thread(void *unused) | |||
| 93 | 86 | ||
| 94 | n = os_write_file(respond_fd, &c, sizeof(c)); | 87 | n = os_write_file(respond_fd, &c, sizeof(c)); |
| 95 | if(n != sizeof(c)) | 88 | if(n != sizeof(c)) |
| 96 | printk("write_sigio_thread : write failed, " | 89 | printk("write_sigio_thread : write on socket " |
| 97 | "err = %d\n", -n); | 90 | "failed, err = %d\n", -n); |
| 98 | } | 91 | } |
| 99 | } | 92 | } |
| 100 | 93 | ||
| 101 | return 0; | 94 | return 0; |
| 102 | } | 95 | } |
| 103 | 96 | ||
| 104 | static int need_poll(int n) | 97 | static int need_poll(struct pollfds *polls, int n) |
| 105 | { | 98 | { |
| 106 | if(n <= next_poll.size){ | 99 | if(n <= polls->size){ |
| 107 | next_poll.used = n; | 100 | polls->used = n; |
| 108 | return(0); | 101 | return 0; |
| 109 | } | 102 | } |
| 110 | kfree(next_poll.poll); | 103 | kfree(polls->poll); |
| 111 | next_poll.poll = um_kmalloc_atomic(n * sizeof(struct pollfd)); | 104 | polls->poll = um_kmalloc_atomic(n * sizeof(struct pollfd)); |
| 112 | if(next_poll.poll == NULL){ | 105 | if(polls->poll == NULL){ |
| 113 | printk("need_poll : failed to allocate new pollfds\n"); | 106 | printk("need_poll : failed to allocate new pollfds\n"); |
| 114 | next_poll.size = 0; | 107 | polls->size = 0; |
| 115 | next_poll.used = 0; | 108 | polls->used = 0; |
| 116 | return(-1); | 109 | return -ENOMEM; |
| 117 | } | 110 | } |
| 118 | next_poll.size = n; | 111 | polls->size = n; |
| 119 | next_poll.used = n; | 112 | polls->used = n; |
| 120 | return(0); | 113 | return 0; |
| 121 | } | 114 | } |
| 122 | 115 | ||
| 123 | /* Must be called with sigio_lock held, because it's needed by the marked | 116 | /* Must be called with sigio_lock held, because it's needed by the marked |
| 124 | * critical section. */ | 117 | * critical section. |
| 118 | */ | ||
| 125 | static void update_thread(void) | 119 | static void update_thread(void) |
| 126 | { | 120 | { |
| 127 | unsigned long flags; | 121 | unsigned long flags; |
| @@ -156,34 +150,39 @@ static void update_thread(void) | |||
| 156 | set_signals(flags); | 150 | set_signals(flags); |
| 157 | } | 151 | } |
| 158 | 152 | ||
| 159 | static int add_sigio_fd(int fd, int read) | 153 | int add_sigio_fd(int fd) |
| 160 | { | 154 | { |
| 161 | int err = 0, i, n, events; | 155 | struct pollfd *p; |
| 156 | int err = 0, i, n; | ||
| 162 | 157 | ||
| 163 | sigio_lock(); | 158 | sigio_lock(); |
| 159 | for(i = 0; i < all_sigio_fds.used; i++){ | ||
| 160 | if(all_sigio_fds.poll[i].fd == fd) | ||
| 161 | break; | ||
| 162 | } | ||
| 163 | if(i == all_sigio_fds.used) | ||
| 164 | goto out; | ||
| 165 | |||
| 166 | p = &all_sigio_fds.poll[i]; | ||
| 167 | |||
| 164 | for(i = 0; i < current_poll.used; i++){ | 168 | for(i = 0; i < current_poll.used; i++){ |
| 165 | if(current_poll.poll[i].fd == fd) | 169 | if(current_poll.poll[i].fd == fd) |
| 166 | goto out; | 170 | goto out; |
| 167 | } | 171 | } |
| 168 | 172 | ||
| 169 | n = current_poll.used + 1; | 173 | n = current_poll.used + 1; |
| 170 | err = need_poll(n); | 174 | err = need_poll(&next_poll, n); |
| 171 | if(err) | 175 | if(err) |
| 172 | goto out; | 176 | goto out; |
| 173 | 177 | ||
| 174 | for(i = 0; i < current_poll.used; i++) | 178 | for(i = 0; i < current_poll.used; i++) |
| 175 | next_poll.poll[i] = current_poll.poll[i]; | 179 | next_poll.poll[i] = current_poll.poll[i]; |
| 176 | 180 | ||
| 177 | if(read) events = POLLIN; | 181 | next_poll.poll[n - 1] = *p; |
| 178 | else events = POLLOUT; | ||
| 179 | |||
| 180 | next_poll.poll[n - 1] = ((struct pollfd) { .fd = fd, | ||
| 181 | .events = events, | ||
| 182 | .revents = 0 }); | ||
| 183 | update_thread(); | 182 | update_thread(); |
| 184 | out: | 183 | out: |
| 185 | sigio_unlock(); | 184 | sigio_unlock(); |
| 186 | return(err); | 185 | return err; |
| 187 | } | 186 | } |
| 188 | 187 | ||
| 189 | int ignore_sigio_fd(int fd) | 188 | int ignore_sigio_fd(int fd) |
| @@ -205,18 +204,14 @@ int ignore_sigio_fd(int fd) | |||
| 205 | if(i == current_poll.used) | 204 | if(i == current_poll.used) |
| 206 | goto out; | 205 | goto out; |
| 207 | 206 | ||
| 208 | err = need_poll(current_poll.used - 1); | 207 | err = need_poll(&next_poll, current_poll.used - 1); |
| 209 | if(err) | 208 | if(err) |
| 210 | goto out; | 209 | goto out; |
| 211 | 210 | ||
| 212 | for(i = 0; i < current_poll.used; i++){ | 211 | for(i = 0; i < current_poll.used; i++){ |
| 213 | p = ¤t_poll.poll[i]; | 212 | p = ¤t_poll.poll[i]; |
| 214 | if(p->fd != fd) next_poll.poll[n++] = current_poll.poll[i]; | 213 | if(p->fd != fd) |
| 215 | } | 214 | next_poll.poll[n++] = *p; |
| 216 | if(n == i){ | ||
| 217 | printk("ignore_sigio_fd : fd %d not found\n", fd); | ||
| 218 | err = -1; | ||
| 219 | goto out; | ||
| 220 | } | 215 | } |
| 221 | 216 | ||
| 222 | update_thread(); | 217 | update_thread(); |
| @@ -234,7 +229,7 @@ static struct pollfd *setup_initial_poll(int fd) | |||
| 234 | printk("setup_initial_poll : failed to allocate poll\n"); | 229 | printk("setup_initial_poll : failed to allocate poll\n"); |
| 235 | return NULL; | 230 | return NULL; |
| 236 | } | 231 | } |
| 237 | *p = ((struct pollfd) { .fd = fd, | 232 | *p = ((struct pollfd) { .fd = fd, |
| 238 | .events = POLLIN, | 233 | .events = POLLIN, |
| 239 | .revents = 0 }); | 234 | .revents = 0 }); |
| 240 | return p; | 235 | return p; |
| @@ -323,6 +318,8 @@ out_close1: | |||
| 323 | 318 | ||
| 324 | void maybe_sigio_broken(int fd, int read) | 319 | void maybe_sigio_broken(int fd, int read) |
| 325 | { | 320 | { |
| 321 | int err; | ||
| 322 | |||
| 326 | if(!isatty(fd)) | 323 | if(!isatty(fd)) |
| 327 | return; | 324 | return; |
| 328 | 325 | ||
| @@ -330,7 +327,19 @@ void maybe_sigio_broken(int fd, int read) | |||
| 330 | return; | 327 | return; |
| 331 | 328 | ||
| 332 | write_sigio_workaround(); | 329 | write_sigio_workaround(); |
| 333 | add_sigio_fd(fd, read); | 330 | |
| 331 | sigio_lock(); | ||
| 332 | err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1); | ||
| 333 | if(err){ | ||
| 334 | printk("maybe_sigio_broken - failed to add pollfd\n"); | ||
| 335 | goto out; | ||
| 336 | } | ||
| 337 | all_sigio_fds.poll[all_sigio_fds.used++] = | ||
| 338 | ((struct pollfd) { .fd = fd, | ||
| 339 | .events = read ? POLLIN : POLLOUT, | ||
| 340 | .revents = 0 }); | ||
| 341 | out: | ||
| 342 | sigio_unlock(); | ||
| 334 | } | 343 | } |
| 335 | 344 | ||
| 336 | static void sigio_cleanup(void) | 345 | static void sigio_cleanup(void) |
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index 60e4faedf254..6b81739279d1 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | #include "user.h" | 15 | #include "user.h" |
| 16 | #include "signal_kern.h" | 16 | #include "signal_kern.h" |
| 17 | #include "sysdep/sigcontext.h" | 17 | #include "sysdep/sigcontext.h" |
| 18 | #include "sysdep/signal.h" | ||
| 19 | #include "sigcontext.h" | 18 | #include "sigcontext.h" |
| 20 | #include "mode.h" | 19 | #include "mode.h" |
| 21 | #include "os.h" | 20 | #include "os.h" |
| @@ -38,18 +37,10 @@ | |||
| 38 | static int signals_enabled = 1; | 37 | static int signals_enabled = 1; |
| 39 | static int pending = 0; | 38 | static int pending = 0; |
| 40 | 39 | ||
| 41 | void sig_handler(ARCH_SIGHDLR_PARAM) | 40 | void sig_handler(int sig, struct sigcontext *sc) |
| 42 | { | 41 | { |
| 43 | struct sigcontext *sc; | ||
| 44 | int enabled; | 42 | int enabled; |
| 45 | 43 | ||
| 46 | /* Must be the first thing that this handler does - x86_64 stores | ||
| 47 | * the sigcontext in %rdx, and we need to save it before it has a | ||
| 48 | * chance to get trashed. | ||
| 49 | */ | ||
| 50 | |||
| 51 | ARCH_GET_SIGCONTEXT(sc, sig); | ||
| 52 | |||
| 53 | enabled = signals_enabled; | 44 | enabled = signals_enabled; |
| 54 | if(!enabled && (sig == SIGIO)){ | 45 | if(!enabled && (sig == SIGIO)){ |
| 55 | pending |= SIGIO_MASK; | 46 | pending |= SIGIO_MASK; |
| @@ -64,15 +55,8 @@ void sig_handler(ARCH_SIGHDLR_PARAM) | |||
| 64 | set_signals(enabled); | 55 | set_signals(enabled); |
| 65 | } | 56 | } |
| 66 | 57 | ||
| 67 | extern int timer_irq_inited; | ||
| 68 | |||
| 69 | static void real_alarm_handler(int sig, struct sigcontext *sc) | 58 | static void real_alarm_handler(int sig, struct sigcontext *sc) |
| 70 | { | 59 | { |
| 71 | if(!timer_irq_inited){ | ||
| 72 | signals_enabled = 1; | ||
| 73 | return; | ||
| 74 | } | ||
| 75 | |||
| 76 | if(sig == SIGALRM) | 60 | if(sig == SIGALRM) |
| 77 | switch_timers(0); | 61 | switch_timers(0); |
| 78 | 62 | ||
| @@ -84,13 +68,10 @@ static void real_alarm_handler(int sig, struct sigcontext *sc) | |||
| 84 | 68 | ||
| 85 | } | 69 | } |
| 86 | 70 | ||
| 87 | void alarm_handler(ARCH_SIGHDLR_PARAM) | 71 | void alarm_handler(int sig, struct sigcontext *sc) |
| 88 | { | 72 | { |
| 89 | struct sigcontext *sc; | ||
| 90 | int enabled; | 73 | int enabled; |
| 91 | 74 | ||
| 92 | ARCH_GET_SIGCONTEXT(sc, sig); | ||
| 93 | |||
| 94 | enabled = signals_enabled; | 75 | enabled = signals_enabled; |
| 95 | if(!signals_enabled){ | 76 | if(!signals_enabled){ |
| 96 | if(sig == SIGVTALRM) | 77 | if(sig == SIGVTALRM) |
| @@ -126,6 +107,10 @@ void remove_sigstack(void) | |||
| 126 | panic("disabling signal stack failed, errno = %d\n", errno); | 107 | panic("disabling signal stack failed, errno = %d\n", errno); |
| 127 | } | 108 | } |
| 128 | 109 | ||
| 110 | void (*handlers[_NSIG])(int sig, struct sigcontext *sc); | ||
| 111 | |||
| 112 | extern void hard_handler(int sig); | ||
| 113 | |||
| 129 | void set_handler(int sig, void (*handler)(int), int flags, ...) | 114 | void set_handler(int sig, void (*handler)(int), int flags, ...) |
| 130 | { | 115 | { |
| 131 | struct sigaction action; | 116 | struct sigaction action; |
| @@ -133,13 +118,16 @@ void set_handler(int sig, void (*handler)(int), int flags, ...) | |||
| 133 | sigset_t sig_mask; | 118 | sigset_t sig_mask; |
| 134 | int mask; | 119 | int mask; |
| 135 | 120 | ||
| 136 | va_start(ap, flags); | 121 | handlers[sig] = (void (*)(int, struct sigcontext *)) handler; |
| 137 | action.sa_handler = handler; | 122 | action.sa_handler = hard_handler; |
| 123 | |||
| 138 | sigemptyset(&action.sa_mask); | 124 | sigemptyset(&action.sa_mask); |
| 139 | while((mask = va_arg(ap, int)) != -1){ | 125 | |
| 126 | va_start(ap, flags); | ||
| 127 | while((mask = va_arg(ap, int)) != -1) | ||
| 140 | sigaddset(&action.sa_mask, mask); | 128 | sigaddset(&action.sa_mask, mask); |
| 141 | } | ||
| 142 | va_end(ap); | 129 | va_end(ap); |
| 130 | |||
| 143 | action.sa_flags = flags; | 131 | action.sa_flags = flags; |
| 144 | action.sa_restorer = NULL; | 132 | action.sa_restorer = NULL; |
| 145 | if(sigaction(sig, &action, NULL) < 0) | 133 | if(sigaction(sig, &action, NULL) < 0) |
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 7baf90fda58b..cb9ab54146cc 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | #include <unistd.h> | 8 | #include <unistd.h> |
| 9 | #include <errno.h> | 9 | #include <errno.h> |
| 10 | #include <signal.h> | 10 | #include <signal.h> |
| 11 | #include <setjmp.h> | ||
| 12 | #include <sched.h> | 11 | #include <sched.h> |
| 13 | #include "ptrace_user.h" | 12 | #include "ptrace_user.h" |
| 14 | #include <sys/wait.h> | 13 | #include <sys/wait.h> |
| @@ -156,11 +155,15 @@ extern int __syscall_stub_start; | |||
| 156 | static int userspace_tramp(void *stack) | 155 | static int userspace_tramp(void *stack) |
| 157 | { | 156 | { |
| 158 | void *addr; | 157 | void *addr; |
| 158 | int err; | ||
| 159 | 159 | ||
| 160 | ptrace(PTRACE_TRACEME, 0, 0, 0); | 160 | ptrace(PTRACE_TRACEME, 0, 0, 0); |
| 161 | 161 | ||
| 162 | init_new_thread_signals(); | 162 | init_new_thread_signals(); |
| 163 | enable_timer(); | 163 | err = set_interval(1); |
| 164 | if(err) | ||
| 165 | panic("userspace_tramp - setting timer failed, errno = %d\n", | ||
| 166 | err); | ||
| 164 | 167 | ||
| 165 | if(!proc_mm){ | 168 | if(!proc_mm){ |
| 166 | /* This has a pte, but it can't be mapped in with the usual | 169 | /* This has a pte, but it can't be mapped in with the usual |
| @@ -190,14 +193,25 @@ static int userspace_tramp(void *stack) | |||
| 190 | } | 193 | } |
| 191 | } | 194 | } |
| 192 | if(!ptrace_faultinfo && (stack != NULL)){ | 195 | if(!ptrace_faultinfo && (stack != NULL)){ |
| 196 | struct sigaction sa; | ||
| 197 | |||
| 193 | unsigned long v = UML_CONFIG_STUB_CODE + | 198 | unsigned long v = UML_CONFIG_STUB_CODE + |
| 194 | (unsigned long) stub_segv_handler - | 199 | (unsigned long) stub_segv_handler - |
| 195 | (unsigned long) &__syscall_stub_start; | 200 | (unsigned long) &__syscall_stub_start; |
| 196 | 201 | ||
| 197 | set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size()); | 202 | set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size()); |
| 198 | set_handler(SIGSEGV, (void *) v, SA_ONSTACK, | 203 | sigemptyset(&sa.sa_mask); |
| 199 | SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, | 204 | sigaddset(&sa.sa_mask, SIGIO); |
| 200 | SIGUSR1, -1); | 205 | sigaddset(&sa.sa_mask, SIGWINCH); |
| 206 | sigaddset(&sa.sa_mask, SIGALRM); | ||
| 207 | sigaddset(&sa.sa_mask, SIGVTALRM); | ||
| 208 | sigaddset(&sa.sa_mask, SIGUSR1); | ||
| 209 | sa.sa_flags = SA_ONSTACK; | ||
| 210 | sa.sa_handler = (void *) v; | ||
| 211 | sa.sa_restorer = NULL; | ||
| 212 | if(sigaction(SIGSEGV, &sa, NULL) < 0) | ||
| 213 | panic("userspace_tramp - setting SIGSEGV handler " | ||
| 214 | "failed - errno = %d\n", errno); | ||
| 201 | } | 215 | } |
| 202 | 216 | ||
| 203 | os_stop_process(os_getpid()); | 217 | os_stop_process(os_getpid()); |
| @@ -430,56 +444,22 @@ void map_stub_pages(int fd, unsigned long code, | |||
| 430 | } | 444 | } |
| 431 | } | 445 | } |
| 432 | 446 | ||
| 433 | void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, | 447 | void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) |
| 434 | void (*handler)(int)) | ||
| 435 | { | 448 | { |
| 436 | unsigned long flags; | 449 | (*buf)[0].JB_IP = (unsigned long) handler; |
| 437 | jmp_buf switch_buf, fork_buf; | 450 | (*buf)[0].JB_SP = (unsigned long) stack + |
| 438 | 451 | (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - sizeof(void *); | |
| 439 | *switch_buf_ptr = &switch_buf; | ||
| 440 | *fork_buf_ptr = &fork_buf; | ||
| 441 | |||
| 442 | /* Somewhat subtle - siglongjmp restores the signal mask before doing | ||
| 443 | * the longjmp. This means that when jumping from one stack to another | ||
| 444 | * when the target stack has interrupts enabled, an interrupt may occur | ||
| 445 | * on the source stack. This is bad when starting up a process because | ||
| 446 | * it's not supposed to get timer ticks until it has been scheduled. | ||
| 447 | * So, we disable interrupts around the sigsetjmp to ensure that | ||
| 448 | * they can't happen until we get back here where they are safe. | ||
| 449 | */ | ||
| 450 | flags = get_signals(); | ||
| 451 | block_signals(); | ||
| 452 | if(UML_SETJMP(&fork_buf) == 0) | ||
| 453 | new_thread_proc(stack, handler); | ||
| 454 | |||
| 455 | remove_sigstack(); | ||
| 456 | |||
| 457 | set_signals(flags); | ||
| 458 | } | 452 | } |
| 459 | 453 | ||
| 460 | #define INIT_JMP_NEW_THREAD 0 | 454 | #define INIT_JMP_NEW_THREAD 0 |
| 461 | #define INIT_JMP_REMOVE_SIGSTACK 1 | 455 | #define INIT_JMP_CALLBACK 1 |
| 462 | #define INIT_JMP_CALLBACK 2 | 456 | #define INIT_JMP_HALT 2 |
| 463 | #define INIT_JMP_HALT 3 | 457 | #define INIT_JMP_REBOOT 3 |
| 464 | #define INIT_JMP_REBOOT 4 | ||
| 465 | 458 | ||
| 466 | void thread_wait(void *sw, void *fb) | 459 | void switch_threads(jmp_buf *me, jmp_buf *you) |
| 467 | { | 460 | { |
| 468 | jmp_buf buf, **switch_buf = sw, *fork_buf; | 461 | if(UML_SETJMP(me) == 0) |
| 469 | 462 | UML_LONGJMP(you, 1); | |
| 470 | *switch_buf = &buf; | ||
| 471 | fork_buf = fb; | ||
| 472 | if(UML_SETJMP(&buf) == 0) | ||
| 473 | siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK); | ||
| 474 | } | ||
| 475 | |||
| 476 | void switch_threads(void *me, void *next) | ||
| 477 | { | ||
| 478 | jmp_buf my_buf, **me_ptr = me, *next_buf = next; | ||
| 479 | |||
| 480 | *me_ptr = &my_buf; | ||
| 481 | if(UML_SETJMP(&my_buf) == 0) | ||
| 482 | UML_LONGJMP(next_buf, 1); | ||
| 483 | } | 463 | } |
| 484 | 464 | ||
| 485 | static jmp_buf initial_jmpbuf; | 465 | static jmp_buf initial_jmpbuf; |
| @@ -489,23 +469,21 @@ static void (*cb_proc)(void *arg); | |||
| 489 | static void *cb_arg; | 469 | static void *cb_arg; |
| 490 | static jmp_buf *cb_back; | 470 | static jmp_buf *cb_back; |
| 491 | 471 | ||
| 492 | int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) | 472 | int start_idle_thread(void *stack, jmp_buf *switch_buf) |
| 493 | { | 473 | { |
| 494 | jmp_buf **switch_buf = switch_buf_ptr; | ||
| 495 | int n; | 474 | int n; |
| 496 | 475 | ||
| 497 | set_handler(SIGWINCH, (__sighandler_t) sig_handler, | 476 | set_handler(SIGWINCH, (__sighandler_t) sig_handler, |
| 498 | SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, | 477 | SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, |
| 499 | SIGVTALRM, -1); | 478 | SIGVTALRM, -1); |
| 500 | 479 | ||
| 501 | *fork_buf_ptr = &initial_jmpbuf; | ||
| 502 | n = UML_SETJMP(&initial_jmpbuf); | 480 | n = UML_SETJMP(&initial_jmpbuf); |
| 503 | switch(n){ | 481 | switch(n){ |
| 504 | case INIT_JMP_NEW_THREAD: | 482 | case INIT_JMP_NEW_THREAD: |
| 505 | new_thread_proc((void *) stack, new_thread_handler); | 483 | (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler; |
| 506 | break; | 484 | (*switch_buf)[0].JB_SP = (unsigned long) stack + |
| 507 | case INIT_JMP_REMOVE_SIGSTACK: | 485 | (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - |
| 508 | remove_sigstack(); | 486 | sizeof(void *); |
| 509 | break; | 487 | break; |
| 510 | case INIT_JMP_CALLBACK: | 488 | case INIT_JMP_CALLBACK: |
| 511 | (*cb_proc)(cb_arg); | 489 | (*cb_proc)(cb_arg); |
| @@ -520,7 +498,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) | |||
| 520 | default: | 498 | default: |
| 521 | panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); | 499 | panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); |
| 522 | } | 500 | } |
| 523 | UML_LONGJMP(*switch_buf, 1); | 501 | UML_LONGJMP(switch_buf, 1); |
| 524 | } | 502 | } |
| 525 | 503 | ||
| 526 | void initial_thread_cb_skas(void (*proc)(void *), void *arg) | 504 | void initial_thread_cb_skas(void (*proc)(void *), void *arg) |
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 503148504009..7fe92680c7dd 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c | |||
| @@ -14,7 +14,6 @@ | |||
| 14 | #include <sched.h> | 14 | #include <sched.h> |
| 15 | #include <fcntl.h> | 15 | #include <fcntl.h> |
| 16 | #include <errno.h> | 16 | #include <errno.h> |
| 17 | #include <setjmp.h> | ||
| 18 | #include <sys/time.h> | 17 | #include <sys/time.h> |
| 19 | #include <sys/wait.h> | 18 | #include <sys/wait.h> |
| 20 | #include <sys/mman.h> | 19 | #include <sys/mman.h> |
diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile index b3213613c41c..37806621b25d 100644 --- a/arch/um/os-Linux/sys-i386/Makefile +++ b/arch/um/os-Linux/sys-i386/Makefile | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | # Licensed under the GPL | 3 | # Licensed under the GPL |
| 4 | # | 4 | # |
| 5 | 5 | ||
| 6 | obj-$(CONFIG_MODE_SKAS) = registers.o tls.o | 6 | obj-$(CONFIG_MODE_SKAS) = registers.o signal.o tls.o |
| 7 | 7 | ||
| 8 | USER_OBJS := $(obj-y) | 8 | USER_OBJS := $(obj-y) |
| 9 | 9 | ||
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c index 516f66dd87e3..7cd0369e02b3 100644 --- a/arch/um/os-Linux/sys-i386/registers.c +++ b/arch/um/os-Linux/sys-i386/registers.c | |||
| @@ -5,12 +5,12 @@ | |||
| 5 | 5 | ||
| 6 | #include <errno.h> | 6 | #include <errno.h> |
| 7 | #include <string.h> | 7 | #include <string.h> |
| 8 | #include <setjmp.h> | ||
| 9 | #include "sysdep/ptrace_user.h" | 8 | #include "sysdep/ptrace_user.h" |
| 10 | #include "sysdep/ptrace.h" | 9 | #include "sysdep/ptrace.h" |
| 11 | #include "uml-config.h" | 10 | #include "uml-config.h" |
| 12 | #include "skas_ptregs.h" | 11 | #include "skas_ptregs.h" |
| 13 | #include "registers.h" | 12 | #include "registers.h" |
| 13 | #include "longjmp.h" | ||
| 14 | #include "user.h" | 14 | #include "user.h" |
| 15 | 15 | ||
| 16 | /* These are set once at boot time and not changed thereafter */ | 16 | /* These are set once at boot time and not changed thereafter */ |
| @@ -130,11 +130,14 @@ void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) | |||
| 130 | HOST_FP_SIZE * sizeof(unsigned long)); | 130 | HOST_FP_SIZE * sizeof(unsigned long)); |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer) | 133 | unsigned long get_thread_reg(int reg, jmp_buf *buf) |
| 134 | { | 134 | { |
| 135 | struct __jmp_buf_tag *jmpbuf = buffer; | 135 | switch(reg){ |
| 136 | 136 | case EIP: return buf[0]->__eip; | |
| 137 | UPT_SET(uml_regs, EIP, jmpbuf->__jmpbuf[JB_PC]); | 137 | case UESP: return buf[0]->__esp; |
| 138 | UPT_SET(uml_regs, UESP, jmpbuf->__jmpbuf[JB_SP]); | 138 | case EBP: return buf[0]->__ebp; |
| 139 | UPT_SET(uml_regs, EBP, jmpbuf->__jmpbuf[JB_BP]); | 139 | default: |
| 140 | printk("get_thread_regs - unknown register %d\n", reg); | ||
| 141 | return 0; | ||
| 142 | } | ||
| 140 | } | 143 | } |
diff --git a/arch/um/os-Linux/sys-i386/signal.c b/arch/um/os-Linux/sys-i386/signal.c new file mode 100644 index 000000000000..0d3eae518352 --- /dev/null +++ b/arch/um/os-Linux/sys-i386/signal.c | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) | ||
| 3 | * Licensed under the GPL | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <signal.h> | ||
| 7 | |||
| 8 | extern void (*handlers[])(int sig, struct sigcontext *sc); | ||
| 9 | |||
| 10 | void hard_handler(int sig) | ||
| 11 | { | ||
| 12 | struct sigcontext *sc = (struct sigcontext *) (&sig + 1); | ||
| 13 | |||
| 14 | (*handlers[sig])(sig, sc); | ||
| 15 | } | ||
diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile index 340ef26f5944..f67842a7735b 100644 --- a/arch/um/os-Linux/sys-x86_64/Makefile +++ b/arch/um/os-Linux/sys-x86_64/Makefile | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | # Licensed under the GPL | 3 | # Licensed under the GPL |
| 4 | # | 4 | # |
| 5 | 5 | ||
| 6 | obj-$(CONFIG_MODE_SKAS) = registers.o | 6 | obj-$(CONFIG_MODE_SKAS) = registers.o signal.o |
| 7 | 7 | ||
| 8 | USER_OBJS := $(obj-y) | 8 | USER_OBJS := $(obj-y) |
| 9 | 9 | ||
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c index becd898d9398..cb8e8a263280 100644 --- a/arch/um/os-Linux/sys-x86_64/registers.c +++ b/arch/um/os-Linux/sys-x86_64/registers.c | |||
| @@ -5,11 +5,11 @@ | |||
| 5 | 5 | ||
| 6 | #include <errno.h> | 6 | #include <errno.h> |
| 7 | #include <string.h> | 7 | #include <string.h> |
| 8 | #include <setjmp.h> | ||
| 9 | #include "ptrace_user.h" | 8 | #include "ptrace_user.h" |
| 10 | #include "uml-config.h" | 9 | #include "uml-config.h" |
| 11 | #include "skas_ptregs.h" | 10 | #include "skas_ptregs.h" |
| 12 | #include "registers.h" | 11 | #include "registers.h" |
| 12 | #include "longjmp.h" | ||
| 13 | #include "user.h" | 13 | #include "user.h" |
| 14 | 14 | ||
| 15 | /* These are set once at boot time and not changed thereafter */ | 15 | /* These are set once at boot time and not changed thereafter */ |
| @@ -78,11 +78,14 @@ void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) | |||
| 78 | HOST_FP_SIZE * sizeof(unsigned long)); | 78 | HOST_FP_SIZE * sizeof(unsigned long)); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer) | 81 | unsigned long get_thread_reg(int reg, jmp_buf *buf) |
| 82 | { | 82 | { |
| 83 | struct __jmp_buf_tag *jmpbuf = buffer; | 83 | switch(reg){ |
| 84 | 84 | case RIP: return buf[0]->__rip; | |
| 85 | UPT_SET(uml_regs, RIP, jmpbuf->__jmpbuf[JB_PC]); | 85 | case RSP: return buf[0]->__rsp; |
| 86 | UPT_SET(uml_regs, RSP, jmpbuf->__jmpbuf[JB_RSP]); | 86 | case RBP: return buf[0]->__rbp; |
| 87 | UPT_SET(uml_regs, RBP, jmpbuf->__jmpbuf[JB_RBP]); | 87 | default: |
| 88 | printk("get_thread_regs - unknown register %d\n", reg); | ||
| 89 | return 0; | ||
| 90 | } | ||
| 88 | } | 91 | } |
diff --git a/arch/um/os-Linux/sys-x86_64/signal.c b/arch/um/os-Linux/sys-x86_64/signal.c new file mode 100644 index 000000000000..3f369e5f976b --- /dev/null +++ b/arch/um/os-Linux/sys-x86_64/signal.c | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) | ||
| 3 | * Licensed under the GPL | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <signal.h> | ||
| 7 | |||
| 8 | extern void (*handlers[])(int sig, struct sigcontext *sc); | ||
| 9 | |||
| 10 | void hard_handler(int sig) | ||
| 11 | { | ||
| 12 | struct ucontext *uc; | ||
| 13 | asm("movq %%rdx, %0" : "=r" (uc)); | ||
| 14 | |||
| 15 | (*handlers[sig])(sig, (struct sigcontext *) &uc->uc_mcontext); | ||
| 16 | } | ||
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index 4ae73c0e5485..38be096e750f 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c | |||
| @@ -17,20 +17,25 @@ | |||
| 17 | #include "kern_constants.h" | 17 | #include "kern_constants.h" |
| 18 | #include "os.h" | 18 | #include "os.h" |
| 19 | 19 | ||
| 20 | static void set_interval(int timer_type) | 20 | int set_interval(int is_virtual) |
| 21 | { | 21 | { |
| 22 | int usec = 1000000/hz(); | 22 | int usec = 1000000/hz(); |
| 23 | int timer_type = is_virtual ? ITIMER_VIRTUAL : ITIMER_REAL; | ||
| 23 | struct itimerval interval = ((struct itimerval) { { 0, usec }, | 24 | struct itimerval interval = ((struct itimerval) { { 0, usec }, |
| 24 | { 0, usec } }); | 25 | { 0, usec } }); |
| 25 | 26 | ||
| 26 | if(setitimer(timer_type, &interval, NULL) == -1) | 27 | if(setitimer(timer_type, &interval, NULL) == -1) |
| 27 | panic("setitimer failed - errno = %d\n", errno); | 28 | return -errno; |
| 29 | |||
| 30 | return 0; | ||
| 28 | } | 31 | } |
| 29 | 32 | ||
| 33 | #ifdef CONFIG_MODE_TT | ||
| 30 | void enable_timer(void) | 34 | void enable_timer(void) |
| 31 | { | 35 | { |
| 32 | set_interval(ITIMER_VIRTUAL); | 36 | set_interval(1); |
| 33 | } | 37 | } |
| 38 | #endif | ||
| 34 | 39 | ||
| 35 | void disable_timer(void) | 40 | void disable_timer(void) |
| 36 | { | 41 | { |
| @@ -40,8 +45,8 @@ void disable_timer(void) | |||
| 40 | printk("disnable_timer - setitimer failed, errno = %d\n", | 45 | printk("disnable_timer - setitimer failed, errno = %d\n", |
| 41 | errno); | 46 | errno); |
| 42 | /* If there are signals already queued, after unblocking ignore them */ | 47 | /* If there are signals already queued, after unblocking ignore them */ |
| 43 | set_handler(SIGALRM, SIG_IGN, 0, -1); | 48 | signal(SIGALRM, SIG_IGN); |
| 44 | set_handler(SIGVTALRM, SIG_IGN, 0, -1); | 49 | signal(SIGVTALRM, SIG_IGN); |
| 45 | } | 50 | } |
| 46 | 51 | ||
| 47 | void switch_timers(int to_real) | 52 | void switch_timers(int to_real) |
| @@ -74,7 +79,7 @@ void uml_idle_timer(void) | |||
| 74 | 79 | ||
| 75 | set_handler(SIGALRM, (__sighandler_t) alarm_handler, | 80 | set_handler(SIGALRM, (__sighandler_t) alarm_handler, |
| 76 | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); | 81 | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); |
| 77 | set_interval(ITIMER_REAL); | 82 | set_interval(0); |
| 78 | } | 83 | } |
| 79 | #endif | 84 | #endif |
| 80 | 85 | ||
| @@ -94,8 +99,3 @@ void idle_sleep(int secs) | |||
| 94 | ts.tv_nsec = 0; | 99 | ts.tv_nsec = 0; |
| 95 | nanosleep(&ts, NULL); | 100 | nanosleep(&ts, NULL); |
| 96 | } | 101 | } |
| 97 | |||
| 98 | void user_time_init(void) | ||
| 99 | { | ||
| 100 | set_interval(ITIMER_VIRTUAL); | ||
| 101 | } | ||
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c index 90b29ae9af46..1df231a26244 100644 --- a/arch/um/os-Linux/trap.c +++ b/arch/um/os-Linux/trap.c | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | 5 | ||
| 6 | #include <stdlib.h> | 6 | #include <stdlib.h> |
| 7 | #include <signal.h> | 7 | #include <signal.h> |
| 8 | #include <setjmp.h> | ||
| 9 | #include "kern_util.h" | 8 | #include "kern_util.h" |
| 10 | #include "user_util.h" | 9 | #include "user_util.h" |
| 11 | #include "os.h" | 10 | #include "os.h" |
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c index 865f6a6a2590..bbb73a650370 100644 --- a/arch/um/os-Linux/uaccess.c +++ b/arch/um/os-Linux/uaccess.c | |||
| @@ -4,8 +4,7 @@ | |||
| 4 | * Licensed under the GPL | 4 | * Licensed under the GPL |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include <setjmp.h> | 7 | #include <stddef.h> |
| 8 | #include <string.h> | ||
| 9 | #include "longjmp.h" | 8 | #include "longjmp.h" |
| 10 | 9 | ||
| 11 | unsigned long __do_user_copy(void *to, const void *from, int n, | 10 | unsigned long __do_user_copy(void *to, const void *from, int n, |
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c index c47a2a7ce70e..3f5b1514e8a7 100644 --- a/arch/um/os-Linux/util.c +++ b/arch/um/os-Linux/util.c | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | #include <stdlib.h> | 7 | #include <stdlib.h> |
| 8 | #include <unistd.h> | 8 | #include <unistd.h> |
| 9 | #include <limits.h> | 9 | #include <limits.h> |
| 10 | #include <setjmp.h> | ||
| 11 | #include <sys/mman.h> | 10 | #include <sys/mman.h> |
| 12 | #include <sys/stat.h> | 11 | #include <sys/stat.h> |
| 13 | #include <sys/utsname.h> | 12 | #include <sys/utsname.h> |
| @@ -107,11 +106,11 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...) | |||
| 107 | jmp_buf buf; | 106 | jmp_buf buf; |
| 108 | int n; | 107 | int n; |
| 109 | 108 | ||
| 110 | n = sigsetjmp(buf, 1); | 109 | n = UML_SETJMP(&buf); |
| 111 | if(n == 0){ | 110 | if(n == 0){ |
| 112 | va_start(args, proc); | 111 | va_start(args, proc); |
| 113 | (*proc)(&buf, &args); | 112 | (*proc)(&buf, &args); |
| 114 | } | 113 | } |
| 115 | va_end(args); | 114 | va_end(args); |
| 116 | return(n); | 115 | return n; |
| 117 | } | 116 | } |
