diff options
author | Jeff Garzik <jeff@garzik.org> | 2006-09-26 13:13:19 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-09-26 13:13:19 -0400 |
commit | c226951b93f7cd7c3a10b17384535b617bd43fd0 (patch) | |
tree | 07b8796a5c99fbbf587b8d0dbcbc173cfe5e381e /arch/um/os-Linux | |
parent | b0df3bd1e553e901ec7297267611a5db88240b38 (diff) | |
parent | e8216dee838c09776680a6f1a2e54d81f3cdfa14 (diff) |
Merge branch 'master' into upstream
Diffstat (limited to 'arch/um/os-Linux')
-rw-r--r-- | arch/um/os-Linux/helper.c | 22 | ||||
-rw-r--r-- | arch/um/os-Linux/irq.c | 2 | ||||
-rw-r--r-- | arch/um/os-Linux/main.c | 34 | ||||
-rw-r--r-- | arch/um/os-Linux/mem.c | 6 | ||||
-rw-r--r-- | arch/um/os-Linux/process.c | 13 | ||||
-rw-r--r-- | arch/um/os-Linux/sigio.c | 103 | ||||
-rw-r--r-- | arch/um/os-Linux/signal.c | 38 | ||||
-rw-r--r-- | arch/um/os-Linux/skas/process.c | 26 | ||||
-rw-r--r-- | arch/um/os-Linux/start_up.c | 1 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-i386/Makefile | 2 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-i386/registers.c | 17 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-i386/signal.c | 15 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-x86_64/Makefile | 2 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-x86_64/registers.c | 17 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-x86_64/signal.c | 16 | ||||
-rw-r--r-- | arch/um/os-Linux/time.c | 22 | ||||
-rw-r--r-- | arch/um/os-Linux/trap.c | 1 | ||||
-rw-r--r-- | arch/um/os-Linux/uaccess.c | 3 | ||||
-rw-r--r-- | arch/um/os-Linux/util.c | 5 |
19 files changed, 210 insertions, 135 deletions
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..42e3d1ed802c 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()); |
@@ -470,7 +484,7 @@ void thread_wait(void *sw, void *fb) | |||
470 | *switch_buf = &buf; | 484 | *switch_buf = &buf; |
471 | fork_buf = fb; | 485 | fork_buf = fb; |
472 | if(UML_SETJMP(&buf) == 0) | 486 | if(UML_SETJMP(&buf) == 0) |
473 | siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK); | 487 | UML_LONGJMP(fork_buf, INIT_JMP_REMOVE_SIGSTACK); |
474 | } | 488 | } |
475 | 489 | ||
476 | void switch_threads(void *me, void *next) | 490 | void switch_threads(void *me, void *next) |
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 | } |